From d18235cae43500d68210b09514b76506fc831014 Mon Sep 17 00:00:00 2001
From: Haru <haru@dotalux.com>
Date: Tue, 28 Oct 2014 15:52:53 +0100
Subject: Added preliminary support for login and char server in the
 HPMDataCheck

- Special thanks to Ind

Signed-off-by: Haru <haru@dotalux.com>
---
 src/char/HPMchar.c        | 53 +++++++++++++++++++++++++++++++
 src/char/HPMchar.h        | 21 +++++++++++++
 src/char/Makefile.in      | 12 +++----
 src/char/char.c           | 33 +++++++++++++++++--
 src/common/HPM.c          | 80 ++++++++++++++++++++++++++++++++++++++++++-----
 src/common/HPM.h          |  4 ++-
 src/common/HPMDataCheck.h | 73 +++++++++++++++++++++---------------------
 src/common/HPMi.h         |  1 +
 src/login/HPMlogin.c      | 53 +++++++++++++++++++++++++++++++
 src/login/HPMlogin.h      | 20 ++++++++++++
 src/login/Makefile.in     |  4 +--
 src/login/account_sql.c   | 10 +++---
 src/login/login.c         | 50 ++++++++++++++++++++++-------
 src/map/HPMmap.c          | 44 +++-----------------------
 src/map/HPMmap.h          |  2 --
 src/map/map.c             |  3 --
 src/plugins/sample.c      |  2 +-
 17 files changed, 348 insertions(+), 117 deletions(-)
 create mode 100644 src/char/HPMchar.c
 create mode 100644 src/char/HPMchar.h
 create mode 100644 src/login/HPMlogin.c
 create mode 100644 src/login/HPMlogin.h

(limited to 'src')

diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c
new file mode 100644
index 000000000..4b153b244
--- /dev/null
+++ b/src/char/HPMchar.c
@@ -0,0 +1,53 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#define HERCULES_CORE
+
+#include "HPMchar.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/db.h"
+#include "../common/des.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/mapindex.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+
+#include "../common/HPMDataCheck.h"
+
+bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
+	/* record address */
+	switch( type ) {
+		default:
+			return false;
+	}
+	return true;
+}
+
+void HPM_char_plugin_load_sub(struct hplugin *plugin) {
+}
+
+void HPM_char_do_init(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+	HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
+#else
+	HPM->DataCheck = NULL;
+#endif
+}
+
+void HPM_char_do_final(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+	HPM->datacheck_final();
+#endif
+}
diff --git a/src/char/HPMchar.h b/src/char/HPMchar.h
new file mode 100644
index 000000000..9d367725c
--- /dev/null
+++ b/src/char/HPMchar.h
@@ -0,0 +1,21 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef CHAR_HPMCHAR_H
+#define CHAR_HPMCHAR_H
+
+#include "../common/cbasetypes.h"
+#include "../common/HPM.h"
+
+struct hplugin;
+
+bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+
+void HPM_char_plugin_load_sub(struct hplugin *plugin);
+
+void HPM_char_do_final(void);
+
+void HPM_char_do_init(void);
+
+#endif /* CHAR_HPMCHAR_H */
+
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index ecb2f8741..d591a5370 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -22,13 +22,13 @@ MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
 MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
 MT19937AR_INCLUDE = -I$(MT19937AR_D)
 
-CHAR_C = char.c inter.c int_auction.c int_elemental.c int_guild.c int_homun.c \
-         int_mail.c int_mercenary.c int_party.c int_pet.c int_quest.c \
-         int_storage.c pincode.c
+CHAR_C = char.c HPMchar.c inter.c int_auction.c int_elemental.c int_guild.c \
+         int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \
+         int_quest.c int_storage.c pincode.c
 CHAR_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(CHAR_C)))
-CHAR_H = char.h inter.h int_auction.h int_elemental.h int_guild.h int_homun.h \
-         int_mail.h int_mercenary.h int_party.h int_pet.h int_quest.h \
-         int_storage.h pincode.h
+CHAR_H = char.h HPMchar.h inter.h int_auction.h int_elemental.h int_guild.h \
+         int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \
+         int_quest.h int_storage.h pincode.h
 
 HAVE_MYSQL=@HAVE_MYSQL@
 ifeq ($(HAVE_MYSQL),yes)
diff --git a/src/char/char.c b/src/char/char.c
index 824c782bc..3dcc48f2e 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -15,6 +15,7 @@
 #include <sys/types.h>
 #include <time.h>
 
+#include "HPMchar.h"
 #include "int_elemental.h"
 #include "int_guild.h"
 #include "int_homun.h"
@@ -5375,6 +5376,8 @@ int do_final(void) {
 		char_fd = -1;
 	}
 
+	HPM_char_do_final();
+
 	SQL->Free(sql_handle);
 	mapindex->final();
 
@@ -5382,6 +5385,8 @@ int do_final(void) {
 		if( server[i].map )
 			aFree(server[i].map);
 	
+	HPM->event(HPET_POST_FINAL);
+
 	ShowStatus("Finished.\n");
 	return EXIT_SUCCESS;
 }
@@ -5416,6 +5421,9 @@ void do_shutdown(void)
 	}
 }
 
+void char_hp_symbols(void) {
+	HPM->share(sql_handle,"sql_handle");
+}
 
 int do_init(int argc, char **argv) {
 	int i;
@@ -5426,6 +5434,29 @@ int do_init(int argc, char **argv) {
 
 	mapindex_defaults();
 	pincode_defaults();
+
+	HPM_char_do_init();
+	HPM->symbol_defaults_sub = char_hp_symbols;
+#if 0
+	/* TODO: Move to common code */
+	for( i = 1; i < argc; i++ ) {
+		const char* arg = argv[i];
+		if( strcmp(arg, "--load-plugin") == 0 ) {
+			if( map->arg_next_value(arg, i, argc, true) ) {
+				RECREATE(load_extras, char *, ++load_extras_count);
+				load_extras[load_extras_count-1] = argv[++i];
+			}
+		}
+	}
+	HPM->config_read((const char * const *)load_extras, load_extras_count);
+	if (load_extras) {
+		aFree(load_extras);
+		load_extras = NULL;
+		load_extras_count = 0;
+	}
+#endif
+	HPM->config_read(NULL, 0);
+	HPM->event(HPET_PRE_INIT);
 	
 	//Read map indexes
 	mapindex->init();
@@ -5446,8 +5477,6 @@ int do_init(int argc, char **argv) {
 	auth_db = idb_alloc(DB_OPT_RELEASE_DATA);
 	online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
 
-	HPM->share(sql_handle,"sql_handle");
-	HPM->config_read(NULL, 0);
 	HPM->event(HPET_INIT);
 	
 	mmo_char_sql_init();
diff --git a/src/common/HPM.c b/src/common/HPM.c
index f39954175..641d84c68 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -31,6 +31,13 @@
 struct malloc_interface iMalloc_HPM;
 struct malloc_interface *HPMiMalloc;
 
+/**
+ * (char*) data name -> (unsigned int) HPMDataCheck[] index
+ **/
+DBMap *datacheck_db;
+int datacheck_version;
+const struct s_HPMDataCheck *datacheck_data;
+
 void hplugin_trigger_event(enum hp_event_types type) {
 	unsigned int i;
 	for( i = 0; i < HPM->plugin_count; i++ ) {
@@ -122,6 +129,7 @@ struct hplugin *hplugin_load(const char* filename) {
 	bool anyEvent = false;
 	void **import_symbol_ref;
 	Sql **sql_handle;
+	int *HPMDataCheckVer;
 	unsigned int *HPMDataCheckLen;
 	struct s_HPMDataCheck *HPMDataCheck;
 		
@@ -217,13 +225,20 @@ struct hplugin *hplugin_load(const char* filename) {
 		return NULL;
 	}
 	
+	if( !( HPMDataCheckVer = plugin_import(plugin->dll, "HPMDataCheckVer", int *) ) ) {
+		ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheckVer' for '"CL_WHITE"%s"CL_RESET"', most likely an outdated plugin, skipping...\n", filename);
+		HPM->unload(plugin);
+		return NULL;
+	}
+
 	if( !( HPMDataCheck = plugin_import(plugin->dll, "HPMDataCheck", struct s_HPMDataCheck *) ) ) {
 		ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheck' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h, skipping...\n", filename);
 		HPM->unload(plugin);
 		return NULL;
 	}
 	
-	if( HPM->DataCheck && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,plugin->info->name) ) {
+	// TODO: Remove the HPM->DataCheck != NULL check once login and char support is complete
+	if (HPM->DataCheck != NULL && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,*HPMDataCheckVer,plugin->info->name)) {
 		ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' failed DataCheck, out of sync from the core (recompile plugin), skipping...\n", filename);
 		HPM->unload(plugin);
 		return NULL;
@@ -282,12 +297,6 @@ void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_c
 	FILE *fp;
 	int i;
 	
-// uncomment once login/char support is wrapped up
-//	if( !HPM->DataCheck ) {
-//		ShowError("HPM:config_read: HPM->DataCheck not set! Failure\n");
-//		return;
-//	}
-	
 	/* yes its ugly, its temporary and will be gone as soon as the new inter-server.conf is set */
 	if( (fp = fopen("conf/import/plugins.conf","r")) ) {
 		config_filename = "conf/import/plugins.conf";
@@ -688,6 +697,56 @@ bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType po
 	return false;
 }
 
+/**
+ * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching!
+ **/
+bool HPM_DataCheck(struct s_HPMDataCheck *src, unsigned int size, int version, char *name) {
+	unsigned int i, j;
+
+	if (version != datacheck_version) {
+		ShowError("HPMDataCheck:%s: DataCheck API version mismatch %d != %d\n", name, datacheck_version, version);
+		return false;
+	}
+	
+	for (i = 0; i < size; i++) {
+		if (!(src[i].type|SERVER_TYPE))
+			continue;
+
+		if (!strdb_exists(datacheck_db, src[i].name)) {
+			ShowError("HPMDataCheck:%s: '%s' was not found\n",name,src[i].name);
+			return false;
+		} else {
+			j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */
+			if (src[i].size != datacheck_data[j].size) {
+				ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,datacheck_data[j].size);
+				return false;
+			}
+		}
+	}
+	
+	return true;
+}
+
+void HPM_datacheck_init(const struct s_HPMDataCheck *src, unsigned int length, int version) {
+	unsigned int i;
+
+	datacheck_version = version;
+	datacheck_data = src;
+	
+	/**
+	 * Populates datacheck_db for easy lookup later on
+	 **/
+	datacheck_db = strdb_alloc(DB_OPT_BASE,0);
+	
+	for(i = 0; i < length; i++) {
+		strdb_uiput(datacheck_db, src[i].name, i);
+	}
+}
+
+void HPM_datacheck_final(void) {
+	db_destroy(datacheck_db);
+}
+
 void hplugins_share_defaults(void) {
 	/* console */
 #ifdef CONSOLE_INPUT
@@ -729,6 +788,9 @@ void hplugins_share_defaults(void) {
 
 void hpm_init(void) {
 	unsigned int i;
+	datacheck_db = NULL;
+	datacheck_data = NULL;
+	datacheck_version = 0;
 	
 	HPM->symbols = NULL;
 	HPM->plugins = NULL;
@@ -866,5 +928,7 @@ void hpm_defaults(void) {
 	HPM->grabHPData = hplugins_grabHPData;
 	HPM->grabHPDataSub = NULL;
 	HPM->parseConf = hplugins_parse_conf;
-	HPM->DataCheck = NULL;
+	HPM->DataCheck = HPM_DataCheck;
+	HPM->datacheck_init = HPM_datacheck_init;
+	HPM->datacheck_final = HPM_datacheck_final;
 }
diff --git a/src/common/HPM.h b/src/common/HPM.h
index fe8d45066..a4ea504e6 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -151,7 +151,9 @@ struct HPM_interface {
 	/* for custom config parsing */
 	bool (*parseConf) (const char *w1, const char *w2, enum HPluginConfType point);
 	/* validates plugin data */
-	bool (*DataCheck) (struct s_HPMDataCheck *src, unsigned int size, char *name);
+	bool (*DataCheck) (struct s_HPMDataCheck *src, unsigned int size, int version, char *name);
+	void (*datacheck_init) (const struct s_HPMDataCheck *src, unsigned int length, int version);
+	void (*datacheck_final) (void);
 } HPM_s;
 
 struct HPM_interface *HPM;
diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h
index 79ec36472..9f4316617 100644
--- a/src/common/HPMDataCheck.h
+++ b/src/common/HPMDataCheck.h
@@ -9,134 +9,135 @@
 
 HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
 	#ifdef COMMON_CONF_H
-		{ "libconfig_interface", sizeof(struct libconfig_interface) },
+		{ "libconfig_interface", sizeof(struct libconfig_interface), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_CONF_H
 	#endif // COMMON_CONF_H
 	#ifdef COMMON_DB_H
-		{ "DBData", sizeof(struct DBData) },
-		{ "DBIterator", sizeof(struct DBIterator) },
-		{ "DBMap", sizeof(struct DBMap) },
+		{ "DBData", sizeof(struct DBData), SERVER_TYPE_ALL },
+		{ "DBIterator", sizeof(struct DBIterator), SERVER_TYPE_ALL },
+		{ "DBMap", sizeof(struct DBMap), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_DB_H
 	#endif // COMMON_DB_H
 	#ifdef COMMON_DES_H
-		{ "BIT64", sizeof(struct BIT64) },
+		{ "BIT64", sizeof(struct BIT64), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_DES_H
 	#endif // COMMON_DES_H
 	#ifdef COMMON_ERS_H
-		{ "eri", sizeof(struct eri) },
+		{ "eri", sizeof(struct eri), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_ERS_H
 	#endif // COMMON_ERS_H
 	#ifdef COMMON_MAPINDEX_H
-		{ "mapindex_interface", sizeof(struct mapindex_interface) },
+		{ "mapindex_interface", sizeof(struct mapindex_interface), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_MAPINDEX_H
 	#endif // COMMON_MAPINDEX_H
 	#ifdef COMMON_MMO_H
-		{ "quest", sizeof(struct quest) },
+		{ "quest", sizeof(struct quest), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_MMO_H
 	#endif // COMMON_MMO_H
 	#ifdef COMMON_SOCKET_H
-		{ "socket_interface", sizeof(struct socket_interface) },
+		{ "socket_interface", sizeof(struct socket_interface), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_SOCKET_H
 	#endif // COMMON_SOCKET_H
 	#ifdef COMMON_STRLIB_H
-		{ "StringBuf", sizeof(struct StringBuf) },
-		{ "s_svstate", sizeof(struct s_svstate) },
+		{ "StringBuf", sizeof(struct StringBuf), SERVER_TYPE_ALL },
+		{ "s_svstate", sizeof(struct s_svstate), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_STRLIB_H
 	#endif // COMMON_STRLIB_H
 	#ifdef COMMON_SYSINFO_H
-		{ "sysinfo_interface", sizeof(struct sysinfo_interface) },
+		{ "sysinfo_interface", sizeof(struct sysinfo_interface), SERVER_TYPE_ALL },
 	#else
 		#define COMMON_SYSINFO_H
 	#endif // COMMON_SYSINFO_H
 	#ifdef MAP_ATCOMMAND_H
-		{ "AliasInfo", sizeof(struct AliasInfo) },
-		{ "atcommand_interface", sizeof(struct atcommand_interface) },
+		{ "AliasInfo", sizeof(struct AliasInfo), SERVER_TYPE_MAP },
+		{ "atcommand_interface", sizeof(struct atcommand_interface), SERVER_TYPE_MAP },
 	#else
 		#define MAP_ATCOMMAND_H
 	#endif // MAP_ATCOMMAND_H
 	#ifdef MAP_BATTLE_H
-		{ "Damage", sizeof(struct Damage) },
-		{ "battle_interface", sizeof(struct battle_interface) },
+		{ "Damage", sizeof(struct Damage), SERVER_TYPE_MAP },
+		{ "battle_interface", sizeof(struct battle_interface), SERVER_TYPE_MAP },
 	#else
 		#define MAP_BATTLE_H
 	#endif // MAP_BATTLE_H
 	#ifdef MAP_BUYINGSTORE_H
-		{ "buyingstore_interface", sizeof(struct buyingstore_interface) },
-		{ "s_buyingstore_item", sizeof(struct s_buyingstore_item) },
+		{ "buyingstore_interface", sizeof(struct buyingstore_interface), SERVER_TYPE_MAP },
+		{ "s_buyingstore_item", sizeof(struct s_buyingstore_item), SERVER_TYPE_MAP },
 	#else
 		#define MAP_BUYINGSTORE_H
 	#endif // MAP_BUYINGSTORE_H
 	#ifdef MAP_CHRIF_H
-		{ "auth_node", sizeof(struct auth_node) },
+		{ "auth_node", sizeof(struct auth_node), SERVER_TYPE_MAP },
 	#else
 		#define MAP_CHRIF_H
 	#endif // MAP_CHRIF_H
 	#ifdef MAP_CLIF_H
-		{ "clif_interface", sizeof(struct clif_interface) },
+		{ "clif_interface", sizeof(struct clif_interface), SERVER_TYPE_MAP },
 	#else
 		#define MAP_CLIF_H
 	#endif // MAP_CLIF_H
 	#ifdef MAP_ELEMENTAL_H
-		{ "elemental_skill", sizeof(struct elemental_skill) },
+		{ "elemental_skill", sizeof(struct elemental_skill), SERVER_TYPE_MAP },
 	#else
 		#define MAP_ELEMENTAL_H
 	#endif // MAP_ELEMENTAL_H
 	#ifdef MAP_GUILD_H
-		{ "eventlist", sizeof(struct eventlist) },
-		{ "guardian_data", sizeof(struct guardian_data) },
+		{ "eventlist", sizeof(struct eventlist), SERVER_TYPE_MAP },
+		{ "guardian_data", sizeof(struct guardian_data), SERVER_TYPE_MAP },
 	#else
 		#define MAP_GUILD_H
 	#endif // MAP_GUILD_H
 	#ifdef MAP_MAPREG_H
-		{ "mapreg_save", sizeof(struct mapreg_save) },
+		{ "mapreg_save", sizeof(struct mapreg_save), SERVER_TYPE_MAP },
 	#else
 		#define MAP_MAPREG_H
 	#endif // MAP_MAPREG_H
 	#ifdef MAP_MAP_H
-		{ "map_data_other_server", sizeof(struct map_data_other_server) },
+		{ "map_data_other_server", sizeof(struct map_data_other_server), SERVER_TYPE_MAP },
 	#else
 		#define MAP_MAP_H
 	#endif // MAP_MAP_H
 	#ifdef MAP_PACKETS_STRUCT_H
-		{ "EQUIPSLOTINFO", sizeof(struct EQUIPSLOTINFO) },
+		{ "EQUIPSLOTINFO", sizeof(struct EQUIPSLOTINFO), SERVER_TYPE_MAP },
 	#else
 		#define MAP_PACKETS_STRUCT_H
 	#endif // MAP_PACKETS_STRUCT_H
 	#ifdef MAP_PC_H
-		{ "autotrade_vending", sizeof(struct autotrade_vending) },
-		{ "item_cd", sizeof(struct item_cd) },
+		{ "autotrade_vending", sizeof(struct autotrade_vending), SERVER_TYPE_MAP },
+		{ "item_cd", sizeof(struct item_cd), SERVER_TYPE_MAP },
 	#else
 		#define MAP_PC_H
 	#endif // MAP_PC_H
 	#ifdef MAP_SCRIPT_H
-		{ "Script_Config", sizeof(struct Script_Config) },
-		{ "reg_db", sizeof(struct reg_db) },
-		{ "script_interface", sizeof(struct script_interface) },
+		{ "Script_Config", sizeof(struct Script_Config), SERVER_TYPE_MAP },
+		{ "reg_db", sizeof(struct reg_db), SERVER_TYPE_MAP },
+		{ "script_interface", sizeof(struct script_interface), SERVER_TYPE_MAP },
 	#else
 		#define MAP_SCRIPT_H
 	#endif // MAP_SCRIPT_H
 	#ifdef MAP_SEARCHSTORE_H
-		{ "searchstore_interface", sizeof(struct searchstore_interface) },
+		{ "searchstore_interface", sizeof(struct searchstore_interface), SERVER_TYPE_MAP },
 	#else
 		#define MAP_SEARCHSTORE_H
 	#endif // MAP_SEARCHSTORE_H
 	#ifdef MAP_SKILL_H
-		{ "skill_cd", sizeof(struct skill_cd) },
-		{ "skill_condition", sizeof(struct skill_condition) },
-		{ "skill_interface", sizeof(struct skill_interface) },
-		{ "skill_unit_save", sizeof(struct skill_unit_save) },
+		{ "skill_cd", sizeof(struct skill_cd), SERVER_TYPE_MAP },
+		{ "skill_condition", sizeof(struct skill_condition), SERVER_TYPE_MAP },
+		{ "skill_interface", sizeof(struct skill_interface), SERVER_TYPE_MAP },
+		{ "skill_unit_save", sizeof(struct skill_unit_save), SERVER_TYPE_MAP },
 	#else
 		#define MAP_SKILL_H
 	#endif // MAP_SKILL_H
 };
 HPExport unsigned int HPMDataCheckLen = ARRAYLENGTH(HPMDataCheck);
+HPExport int HPMDataCheckVer = 1;
 
 #endif /* HPM_DATA_CHECK_H */
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
index 478cfbdd9..485586f6f 100644
--- a/src/common/HPMi.h
+++ b/src/common/HPMi.h
@@ -36,6 +36,7 @@ struct hplugin_info {
 struct s_HPMDataCheck {
 	char *name;
 	unsigned int size;
+	int type;
 };
 
 HPExport void *(*import_symbol) (char *name, unsigned int pID);
diff --git a/src/login/HPMlogin.c b/src/login/HPMlogin.c
new file mode 100644
index 000000000..6b223d249
--- /dev/null
+++ b/src/login/HPMlogin.c
@@ -0,0 +1,53 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#define HERCULES_CORE
+
+#include "HPMlogin.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/db.h"
+#include "../common/des.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/mapindex.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+
+#include "../common/HPMDataCheck.h"
+
+bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
+	/* record address */
+	switch( type ) {
+		default:
+			return false;
+	}
+	return true;
+}
+
+void HPM_login_plugin_load_sub(struct hplugin *plugin) {
+}
+
+void HPM_login_do_init(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+	HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
+#else
+	HPM->DataCheck = NULL;
+#endif
+}
+
+void HPM_login_do_final(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+	HPM->datacheck_final();
+#endif
+}
diff --git a/src/login/HPMlogin.h b/src/login/HPMlogin.h
new file mode 100644
index 000000000..6bdc0fb7b
--- /dev/null
+++ b/src/login/HPMlogin.h
@@ -0,0 +1,20 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef LOGIN_HPMLOGIN_H
+#define LOGIN_HPMLOGIN_H
+
+#include "../common/cbasetypes.h"
+#include "../common/HPM.h"
+
+struct hplugin;
+
+bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+
+void HPM_login_plugin_load_sub(struct hplugin *plugin);
+
+void HPM_login_do_final(void);
+
+void HPM_login_do_init(void);
+
+#endif /* LOGIN_HPMLOGIN_H */
diff --git a/src/login/Makefile.in b/src/login/Makefile.in
index a4aec59cf..9b1db69c2 100644
--- a/src/login/Makefile.in
+++ b/src/login/Makefile.in
@@ -22,9 +22,9 @@ MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
 MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
 MT19937AR_INCLUDE = -I$(MT19937AR_D)
 
-LOGIN_C = account_sql.c ipban_sql.c login.c loginlog_sql.c
+LOGIN_C = account_sql.c HPMlogin.c ipban_sql.c login.c loginlog_sql.c
 LOGIN_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(LOGIN_C)))
-LOGIN_H = login.h account.h ipban.h loginlog.h
+LOGIN_H = login.h account.h HPMlogin.h ipban.h loginlog.h
 
 HAVE_MYSQL=@HAVE_MYSQL@
 ifeq ($(HAVE_MYSQL),yes)
diff --git a/src/login/account_sql.c b/src/login/account_sql.c
index 51e499369..996bfcf44 100644
--- a/src/login/account_sql.c
+++ b/src/login/account_sql.c
@@ -169,6 +169,10 @@ static bool account_db_sql_init(AccountDB* self)
 	if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) )
 		Sql_ShowDebug(sql_handle);
 
+	Sql_HerculesUpdateCheck(db->accounts);
+#ifdef CONSOLE_INPUT
+	console->input->setSQL(db->accounts);
+#endif
 	return true;
 }
 
@@ -655,11 +659,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
 
 Sql* account_db_sql_up(AccountDB* self) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
-	Sql_HerculesUpdateCheck(db->accounts);
-#ifdef CONSOLE_INPUT
-	console->input->setSQL(db->accounts);
-#endif
-	return db->accounts;
+	return db ? db->accounts : NULL;
 }
 void mmo_save_accreg2(AccountDB* self, int fd, int account_id, int char_id) {
 	Sql* sql_handle = ((AccountDB_SQL*)self)->accounts;
diff --git a/src/login/login.c b/src/login/login.c
index 129049627..9aa2e778b 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -10,6 +10,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "HPMlogin.h"
 #include "account.h"
 #include "ipban.h"
 #include "loginlog.h"
@@ -1737,6 +1738,10 @@ int do_final(void) {
 		login_fd = -1;
 	}
 
+	HPM_login_do_final();
+
+	HPM->event(HPET_POST_FINAL);
+
 	ShowStatus("Finished.\n");
 	return EXIT_SUCCESS;
 }
@@ -1770,6 +1775,9 @@ void do_shutdown(void)
 	}
 }
 
+void login_hp_symbols(void) {
+	HPM->share(account_db_sql_up(accounts),"sql_handle");
+}
 
 //------------------------------
 // Login server initialization
@@ -1780,9 +1788,38 @@ int do_init(int argc, char** argv)
 
 	// initialize engine (to accept config settings)
 	account_engine[0].db = account_engine[0].constructor();
+	accounts = account_engine[0].db;
+	if( accounts == NULL ) {
+		ShowFatalError("do_init: account engine 'sql' not found.\n");
+		exit(EXIT_FAILURE);
+	}
 
 	// read login-server configuration
 	login_set_defaults();
+
+	HPM_login_do_init();
+	HPM->symbol_defaults_sub = login_hp_symbols;
+	HPM->config_read(NULL, 0);
+#if 0
+	/* TODO: Move to common code */
+	for( i = 1; i < argc; i++ ) {
+		const char* arg = argv[i];
+		if( strcmp(arg, "--load-plugin") == 0 ) {
+			if( map->arg_next_value(arg, i, argc, true) ) {
+				RECREATE(load_extras, char *, ++load_extras_count);
+				load_extras[load_extras_count-1] = argv[++i];
+			}
+		}
+	}
+	HPM->config_read((const char * const *)load_extras, load_extras_count);
+	if (load_extras) {
+		aFree(load_extras);
+		load_extras = NULL;
+		load_extras_count = 0;
+	}
+#endif
+	HPM->event(HPET_PRE_INIT);
+
 	login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
 	login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME);
 		
@@ -1817,20 +1854,11 @@ int do_init(int argc, char** argv)
 	}
 
 	// Account database init
-	accounts = account_engine[0].db;
-	if( accounts == NULL ) {
-		ShowFatalError("do_init: account engine 'sql' not found.\n");
+	if(!accounts->init(accounts)) {
+		ShowFatalError("do_init: Failed to initialize account engine 'sql'.\n");
 		exit(EXIT_FAILURE);
-	} else {
-
-		if(!accounts->init(accounts)) {
-			ShowFatalError("do_init: Failed to initialize account engine 'sql'.\n");
-			exit(EXIT_FAILURE);
-		}
 	}
 
-	HPM->share(account_db_sql_up(accounts),"sql_handle");
-	HPM->config_read(NULL, 0);
 	HPM->event(HPET_INIT);
 	
 	// server port open & binding
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c
index cb8c979c6..a0701ae45 100644
--- a/src/map/HPMmap.c
+++ b/src/map/HPMmap.c
@@ -74,11 +74,6 @@ struct HPM_atcommand_list {
 struct HPM_atcommand_list *atcommand_list = NULL;
 unsigned int atcommand_list_items = 0;
 
-/**
- * (char*) data name -> (unsigned int) HPMDataCheck[] index
- **/
-DBMap *datacheck_db;
-
 bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
 	/* record address */
 	switch( type ) {
@@ -146,29 +141,6 @@ void HPM_map_atcommands(void) {
 	}
 }
 
-/**
- * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching!
- **/
-bool HPM_map_DataCheck (struct s_HPMDataCheck *src, unsigned int size, char *name) {
-	unsigned int i, j;
-	
-	for(i = 0; i < size; i++) {
-		
-		if( !strdb_exists(datacheck_db, src[i].name) ) {
-			ShowError("HPMDataCheck:%s: '%s' was not found\n",name,src[i].name);
-			return false;
-		} else {
-			j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */
-			if( src[i].size != HPMDataCheck[j].size ) {
-				ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,HPMDataCheck[j].size);
-				return false;
-			}
-		}
-	}
-	
-	return true;
-}
-
 /**
  * Adds a new group permission to the HPM-provided list
  **/
@@ -183,17 +155,9 @@ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned in
 }
 
 void HPM_map_do_init(void) {
-	unsigned int i;
-	
-	/**
-	 * Populates datacheck_db for easy lookup later on
-	 **/
-	datacheck_db = strdb_alloc(DB_OPT_BASE,0);
-	
-	for(i = 0; i < HPMDataCheckLen; i++) {
-		strdb_uiput(datacheck_db, HPMDataCheck[i].name, i);
-	}
-	
+	HPM->load_sub = HPM_map_plugin_load_sub;
+	HPM->grabHPDataSub = HPM_map_grabHPData;
+	HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
 }
 
 void HPM_map_do_final(void) {
@@ -211,5 +175,5 @@ void HPM_map_do_final(void) {
 	if( pcg->HPMpermissions )
 		aFree(pcg->HPMpermissions);
 	
-	db_destroy(datacheck_db);
+	HPM->datacheck_final();
 }
diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h
index 99c4224ff..fa2f625c0 100644
--- a/src/map/HPMmap.h
+++ b/src/map/HPMmap.h
@@ -22,8 +22,6 @@ void HPM_map_do_final(void);
 
 void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask);
 
-bool HPM_map_DataCheck(struct s_HPMDataCheck *src, unsigned int size, char *name);
-
 void HPM_map_do_init(void);
 
 #endif /* MAP_HPMMAP_H */
diff --git a/src/map/map.c b/src/map/map.c
index 045233e91..bb3b17822 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -5614,10 +5614,7 @@ int do_init(int argc, char *argv[])
 	map_load_defaults();
 
 	HPM_map_do_init();
-	HPM->DataCheck = HPM_map_DataCheck;
-	HPM->load_sub = HPM_map_plugin_load_sub;
 	HPM->symbol_defaults_sub = map_hp_symbols;
-	HPM->grabHPDataSub = HPM_map_grabHPData;
 	for( i = 1; i < argc; i++ ) {
 		const char* arg = argv[i];
 		if( strcmp(arg, "--load-plugin") == 0 ) {
diff --git a/src/plugins/sample.c b/src/plugins/sample.c
index 84df88e06..88ef84d48 100644
--- a/src/plugins/sample.c
+++ b/src/plugins/sample.c
@@ -19,7 +19,7 @@
 
 HPExport struct hplugin_info pinfo = {
 	"Sample",		// Plugin name
-	SERVER_TYPE_MAP,// Which server types this plugin works with?
+	SERVER_TYPE_LOGIN|SERVER_TYPE_MAP,// Which server types this plugin works with?
 	"0.1",			// Plugin version
 	HPM_VERSION,	// HPM Version (don't change, macro is automatically updated)
 };
-- 
cgit v1.2.3-70-g09d2