diff options
-rw-r--r-- | src/common/HPM.c | 4 | ||||
-rw-r--r-- | src/common/sql.c | 3 | ||||
-rw-r--r-- | src/map/itemdb.c | 123 | ||||
-rw-r--r-- | src/map/itemdb.h | 3 | ||||
-rw-r--r-- | src/map/map.c | 9 | ||||
-rw-r--r-- | src/map/map.h | 1 | ||||
-rw-r--r-- | src/plugins/db2sql.c | 246 |
7 files changed, 216 insertions, 173 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c index 81acb3415..1f4d4d532 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -640,7 +640,9 @@ void hplugins_share_defaults(void) { HPM->share(SQL,"SQL"); /* timer */ HPM->share(timer,"timer"); - + /* libconfig (temp) */ + HPM->share(config_setting_lookup_string,"config_setting_lookup_string"); + HPM->share(config_setting_lookup_int,"config_setting_lookup_int"); } void hpm_init(void) { diff --git a/src/common/sql.c b/src/common/sql.c index dc6c4c569..0e06d6d18 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -1005,6 +1005,9 @@ void Sql_HerculesUpdateCheck(Sql* self) { unsigned int performed = 0; StringBuf buf; + if( self == NULL ) + return;/* return silently, build has no mysql connection */ + if( !( ifp = fopen("sql-files/upgrades/index.txt", "r") ) ) { ShowError("SQL upgrade index was not found!\n"); return; diff --git a/src/map/itemdb.c b/src/map/itemdb.c index dff0207c7..f48ed8259 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1826,43 +1826,36 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) * Reading item from item db * item_db2 overwriting item_db *------------------------------------------*/ -int itemdb_readdb(void) { - const char* filename[] = { - DBPATH"item_db.conf", - "item_db2.conf", - }; +int itemdb_readdb(const char *filename) { bool duplicate[MAX_ITEMDB]; - int fi; config_t item_db_conf; config_setting_t *itdb, *it; + char filepath[256]; + int i = 0, count = 0; + + sprintf(filepath, "%s/%s", map->db_path, filename); + memset(&duplicate,0,sizeof(duplicate)); + if( conf_read_file(&item_db_conf, filepath) || !(itdb = config_setting_get_member(item_db_conf.root, "item_db")) ) { + ShowError("can't read %s\n", filepath); + return 0; + } - for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { - char filepath[256]; - int i = 0, count = 0; - sprintf(filepath, "%s/%s", map->db_path, filename[fi]); - memset(&duplicate,0,sizeof(duplicate)); - if( conf_read_file(&item_db_conf, filepath) || !(itdb = config_setting_get_member(item_db_conf.root, "item_db")) ) { - ShowError("can't read %s\n", filepath); - continue; - } - - while( (it = config_setting_get_elem(itdb,i++)) ) { - int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename[fi]); + while( (it = config_setting_get_elem(itdb,i++)) ) { + int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename); - if( !nameid ) - continue; + if( !nameid ) + continue; - count++; + count++; - if( duplicate[nameid] ) { - ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n", - filename[fi], nameid, itemdb_name(nameid), itemdb_jname(nameid)); - } else - duplicate[nameid] = true; - } - config_destroy(&item_db_conf); - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]); + if( duplicate[nameid] ) { + ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n", + filename, nameid, itemdb_name(nameid), itemdb_jname(nameid)); + } else + duplicate[nameid] = true; } + config_destroy(&item_db_conf); + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); return 0; } @@ -1956,8 +1949,15 @@ void itemdb_read(bool minimal) { if (map->db_use_sql_item_db) itemdb->read_sqldb(); - else - itemdb->readdb(); + else { + const char* filename[] = { + DBPATH"item_db.conf", + "item_db2.conf", + }; + + for(i = 0; i < ARRAYLENGTH(filename); i++) + itemdb->readdb(filename[i]); + } for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) { if( itemdb->array[i] ) { @@ -2034,18 +2034,13 @@ int itemdb_final_sub(DBKey key, DBData *data, va_list ap) return 0; } - -void itemdb_reload(void) { - struct s_mapiterator* iter; - struct map_session_data* sd; - - int i,d,k; - +void itemdb_clear(bool total) { + int i; // clear the previous itemdb data for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) if( itemdb->array[i] ) itemdb->destroy_item_data(itemdb->array[i], 1); - + for( i = 0; i < itemdb->group_count; i++ ) { if( itemdb->groups[i].nameid ) aFree(itemdb->groups[i].nameid); @@ -2084,12 +2079,24 @@ void itemdb_reload(void) { itemdb->packages = NULL; itemdb->package_count = 0; + if( total ) + return; + itemdb->other->clear(itemdb->other, itemdb->final_sub); memset(itemdb->array, 0, sizeof(itemdb->array)); db_clear(itemdb->names); - + +} +void itemdb_reload(void) { + struct s_mapiterator* iter; + struct map_session_data* sd; + + int i,d,k; + + itemdb->clear(false); + // read new data itemdb->read(false); @@ -2160,41 +2167,8 @@ void itemdb_force_name_constants(void) { dbi_destroy(iter); } void do_final_itemdb(void) { - int i; - - for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) - if( itemdb->array[i] ) - itemdb->destroy_item_data(itemdb->array[i], 1); - - for( i = 0; i < itemdb->group_count; i++ ) { - if( itemdb->groups[i].nameid ) - aFree(itemdb->groups[i].nameid); - } - - if( itemdb->groups ) - aFree(itemdb->groups); - - for( i = 0; i < itemdb->chain_count; i++ ) { - if( itemdb->chains[i].items ) - aFree(itemdb->chains[i].items); - } - - if( itemdb->chains ) - aFree(itemdb->chains); - - for( i = 0; i < itemdb->package_count; i++ ) { - int c; - for( c = 0; c < itemdb->packages[i].random_qty; c++ ) - aFree(itemdb->packages[i].random_groups[c].random_list); - if( itemdb->packages[i].random_groups ) - aFree(itemdb->packages[i].random_groups); - if( itemdb->packages[i].must_items ) - aFree(itemdb->packages[i].must_items); - } + itemdb->clear(true); - if( itemdb->packages ) - aFree(itemdb->packages); - itemdb->other->destroy(itemdb->other, itemdb->final_sub); itemdb->destroy_item_data(&itemdb->dummy, 0); db_destroy(itemdb->names); @@ -2295,4 +2269,5 @@ void itemdb_defaults(void) { itemdb->read = itemdb_read; itemdb->destroy_item_data = destroy_item_data; itemdb->final_sub = itemdb_final_sub; + itemdb->clear = itemdb_clear; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 870ecce58..533a808bc 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -349,13 +349,14 @@ struct itemdb_interface { int (*validate_entry) (struct item_data *entry, int n, const char *source); int (*readdb_sql_sub) (Sql *handle, int n, const char *source); int (*readdb_libconfig_sub) (config_setting_t *it, int n, const char *source); - int (*readdb) (void); + int (*readdb) (const char *filename); int (*read_sqldb) (void); uint64 (*unique_id) (int8 flag, int64 value); int (*uid_load) (); void (*read) (bool minimal); void (*destroy_item_data) (struct item_data *self, int free_self); int (*final_sub) (DBKey key, DBData *data, va_list ap); + void (*clear) (bool total); }; struct itemdb_interface *itemdb; diff --git a/src/map/map.c b/src/map/map.c index b846d6125..b0ae2f340 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -5438,6 +5438,7 @@ int do_init(int argc, char *argv[]) HPM->event(HPET_PRE_INIT); + minimal = map->minimal;/* temp (perhaps make minimal a mask with options of what to load? e.g. plugin 1 does minimal |= mob_db; */ for( i = 1; i < argc ; i++ ) { const char* arg = argv[i]; @@ -5619,12 +5620,17 @@ int do_init(int argc, char *argv[]) duel->init(minimal); vending->init(minimal); - if (minimal) { + if (scriptcheck) { if (npc->parsesrcfile(scriptcheck, false) == 0) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } + if( minimal ) { + HPM->event(HPET_READY); + exit(EXIT_SUCCESS); + } + npc->event_do_oninit(); // Init npcs (OnInit) if (battle_config.pk_mode) @@ -5659,6 +5665,7 @@ void map_defaults(void) { map = &map_s; /* */ + map->minimal = false; map->count = 0; sprintf(map->db_path ,"db"); diff --git a/src/map/map.h b/src/map/map.h index 4b2671702..4cb00f144 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -800,6 +800,7 @@ struct map_cache_map_info { struct map_interface { /* vars */ + bool minimal; int count; int autosave_interval; diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c index d769a601e..c8321f886 100644 --- a/src/plugins/db2sql.c +++ b/src/plugins/db2sql.c @@ -5,7 +5,9 @@ #include "../common/strlib.h" #include "../common/timer.h" #include "../common/HPMi.h" +#include "../common/malloc.h" #include "../common/mmo.h" +#include "../common/conf.h" #include "../config/core.h" #include "../map/clif.h" #include "../map/pc.h" @@ -15,124 +17,176 @@ #include <stdlib.h> HPExport struct hplugin_info pinfo = { - "DB2SQL", // Plugin name - SERVER_TYPE_MAP,// Which server types this plugin works with? - "0.4", // Plugin version - HPM_VERSION, // HPM Version (don't change, macro is automatically updated) + "DB2SQL", // Plugin name + SERVER_TYPE_MAP, // Which server types this plugin works with? + "0.5", // Plugin version + HPM_VERSION, // HPM Version (don't change, macro is automatically updated) }; -SqlStmt* stmt; +struct { + FILE *fp; + struct { + char *p; + unsigned int len; + } buf[4]; + char *db_name; +} tosql; +bool torun = false; -int (*parse_dbrow)(char** str, const char* source, int line, int scriptopt); +int (*itemdb_readdb_libconfig_sub) (config_setting_t *it, int n, const char *source); +int (*h_config_setting_lookup_string) (const config_setting_t *setting, const char *name, const char **value); +int (*h_config_setting_lookup_int) (const config_setting_t *setting, const char *name, int *value); -char* trimbraces(char* str) { - size_t start; - size_t end; - - if( str == NULL ) - return str; - - for( start = 0; str[start] && str[start] == '{'; ++start ) - ; - for( end = strlen(str); start < end && str[end-1] && (str[end-1] == '}' || str[end-1] == '\n'); --end ) - ; - if( start == end ) - *str = '\0'; - else { - str[end] = '\0'; - memmove(str,str+start,end-start+1); - trim(str); +void hstr(const char *str) { + if( strlen(str) > tosql.buf[3].len ) { + tosql.buf[3].len = tosql.buf[3].len + strlen(str) + 1000; + RECREATE(tosql.buf[3].p,char,tosql.buf[3].len); } - return str; + safestrncpy(tosql.buf[3].p,str,strlen(str)); + normalize_name(tosql.buf[3].p,"\t\n"); } -int db2sql(char** str, const char* source, int line, int scriptopt) { +int db2sql(config_setting_t *entry, int n, const char *source) { struct item_data *it = NULL; - unsigned char offset = 0; -#ifdef RENEWAL - if( map->db_use_sql_item_db ) offset = 1; -#endif // RENEWAL - if( (it = itemdb->exists(parse_dbrow(str,source,line,scriptopt))) ) { - /* renewal has the 'matk' and 'equip_level' is now 'equip_level_min', and there is a new 'equip_level_max' field */ -#ifdef RENEWAL - if( SQL_SUCCESS != SQL->StmtPrepare(stmt, "REPLACE INTO `%s` (`id`,`name_english`,`name_japanese`,`type`,`price_buy`,`price_sell`,`weight`,`atk`,`matk`,`defence`,`range`,`slots`,`equip_jobs`,`equip_upper`,`equip_genders`,`equip_locations`,`weapon_level`,`equip_level_min`,`equip_level_max`,`refineable`,`view`,`script`,`equip_script`,`unequip_script`) VALUES ('%u',?,?,'%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u',?,?,?)",map->item_db_re_db, - it->nameid,it->flag.delay_consume?IT_DELAYCONSUME:it->type,it->value_buy,it->value_sell,it->weight,it->atk,it->matk,it->def,it->range,it->slot,(unsigned int)strtoul(str[11+offset],NULL,0),atoi(str[12+offset]),atoi(str[13+offset]),atoi(str[14+offset]),it->wlv,it->elv,it->elvmax,atoi(str[17+offset]),it->look) ) -#else // not RENEWAL - if( SQL_SUCCESS != SQL->StmtPrepare(stmt, "REPLACE INTO `%s` (`id`,`name_english`,`name_japanese`,`type`,`price_buy`,`price_sell`,`weight`,`atk`,`defence`,`range`,`slots`,`equip_jobs`,`equip_upper`,`equip_genders`,`equip_locations`,`weapon_level`,`equip_level`,`refineable`,`view`,`script`,`equip_script`,`unequip_script`) VALUES ('%u',?,?,'%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u',?,?,?)",map->item_db_db, - it->nameid,it->flag.delay_consume?IT_DELAYCONSUME:it->type,it->value_buy,it->value_sell,it->weight,it->atk,it->def,it->range,it->slot,(unsigned int)strtoul(str[11],NULL,0),atoi(str[12]),atoi(str[13]),atoi(str[14]),it->wlv,it->elv,atoi(str[17]),it->look) ) -#endif // RENEWAL - SqlStmt_ShowDebug(stmt); - else { - if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, it->name, strlen(it->name)) ) - SqlStmt_ShowDebug(stmt); - else { - if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, it->jname, strlen(it->jname)) ) - SqlStmt_ShowDebug(stmt); - else { -#ifdef RENEWAL - if( map->db_use_sql_item_db ) offset += 1; -#endif // RENEWAL - if( it->script ) trimbraces(str[19+offset]); - if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 2, SQLDT_STRING, it->script?str[19+offset]:"", it->script?strlen(str[19+offset]):0) ) - SqlStmt_ShowDebug(stmt); - else { - if( it->equip_script ) trimbraces(str[20+offset]); - if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 3, SQLDT_STRING, it->equip_script?str[20+offset]:"", it->equip_script?strlen(str[20+offset]):0) ) - SqlStmt_ShowDebug(stmt); - else { - if( it->unequip_script ) trimbraces(str[21+offset]); - if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 4, SQLDT_STRING, it->unequip_script?str[21+offset]:"", it->unequip_script?strlen(str[21+offset]):0) ) - SqlStmt_ShowDebug(stmt); - else { - if( SQL_SUCCESS != SQL->StmtExecute(stmt) ) - SqlStmt_ShowDebug(stmt); - } - } - } - } - } - } - return it->nameid; - } - return 0; -} + + if( (it = itemdb->exists(itemdb_readdb_libconfig_sub(entry,n,source))) ) { + char e_name[ITEM_NAME_LENGTH*2+1], e_jname[ITEM_NAME_LENGTH*2+1]; + const char *script = NULL; + char *str; + int i32; + unsigned int ui32, job = 0, upper = 0; + + SQL->EscapeString(NULL, e_name, it->name); + SQL->EscapeString(NULL, e_jname, it->jname); + if( it->script ) { h_config_setting_lookup_string(entry, "Script", &script); hstr(script); str = tosql.buf[3].p; if ( strlen(str) > tosql.buf[0].len ) { tosql.buf[0].len = tosql.buf[0].len + strlen(str) + 1000; RECREATE(tosql.buf[0].p,char,tosql.buf[0].len); } SQL->EscapeString(NULL, tosql.buf[0].p, str); } + if( it->equip_script ) { h_config_setting_lookup_string(entry, "OnEquipScript", &script); hstr(script); str = tosql.buf[3].p; if ( strlen(str) > tosql.buf[1].len ) { tosql.buf[1].len = tosql.buf[1].len + strlen(str) + 1000; RECREATE(tosql.buf[1].p,char,tosql.buf[1].len); } SQL->EscapeString(NULL, tosql.buf[1].p, str); } + if( it->unequip_script ) { h_config_setting_lookup_string(entry, "OnUnequipScript", &script); hstr(script); str = tosql.buf[3].p; if ( strlen(str) > tosql.buf[2].len ) { tosql.buf[2].len = tosql.buf[2].len + strlen(str) + 1000; RECREATE(tosql.buf[2].p,char,tosql.buf[2].len); } SQL->EscapeString(NULL, tosql.buf[2].p, str); } + + if( h_config_setting_lookup_int(entry, "Job", &i32) ) // This is an unsigned value, do not check for >= 0 + ui32 = (unsigned int)i32; + else + ui32 = UINT_MAX; + + job = ui32; + + if( h_config_setting_lookup_int(entry, "Upper", &i32) && i32 >= 0 ) + ui32 = (unsigned int)i32; + else + ui32 = ITEMUPPER_ALL; -CPCMD(db2sql) { + upper = ui32; + + fprintf(tosql.fp,"REPLACE INTO `%s` VALUES ('%u','%s','%s','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%s','%s','%s');\n", + tosql.db_name,it->nameid,e_name,e_jname,it->flag.delay_consume?IT_DELAYCONSUME:it->type,it->value_buy,it->value_sell,it->weight,it->atk,it->matk,it->def,it->range,it->slot,job,upper,it->sex,it->equip,it->wlv,it->elv,it->elvmax,it->flag.no_refine?0:1,it->look,it->script?tosql.buf[0].p:"",it->equip_script?tosql.buf[1].p:"",it->unequip_script?tosql.buf[2].p:""); + } + return it?it->nameid:0; +} +void totable(void) { + fprintf(tosql.fp,"#\n" + "# Table structure for table `%s`\n" + "#\n" + "\n" + "DROP TABLE IF EXISTS `%s`;\n" + "CREATE TABLE `%s` (\n" + " `id` smallint(5) unsigned NOT NULL DEFAULT '0',\n" + " `name_english` varchar(50) NOT NULL DEFAULT '',\n" + " `name_japanese` varchar(50) NOT NULL DEFAULT '',\n" + " `type` tinyint(2) unsigned NOT NULL DEFAULT '0',\n" + " `price_buy` mediumint(10) DEFAULT NULL,\n" + " `price_sell` mediumint(10) DEFAULT NULL,\n" + " `weight` smallint(5) unsigned DEFAULT NULL,\n" + " `atk` smallint(5) unsigned DEFAULT NULL,\n" + " `matk` smallint(5) unsigned DEFAULT NULL,\n" + " `defence` smallint(5) unsigned DEFAULT NULL,\n" + " `range` tinyint(2) unsigned DEFAULT NULL,\n" + " `slots` tinyint(2) unsigned DEFAULT NULL,\n" + " `equip_jobs` int(12) unsigned DEFAULT NULL,\n" + " `equip_upper` tinyint(8) unsigned DEFAULT NULL,\n" + " `equip_genders` tinyint(2) unsigned DEFAULT NULL,\n" + " `equip_locations` smallint(4) unsigned DEFAULT NULL,\n" + " `weapon_level` tinyint(2) unsigned DEFAULT NULL,\n" + " `equip_level_min` smallint(5) unsigned DEFAULT NULL,\n" + " `equip_level_max` smallint(5) unsigned DEFAULT NULL,\n" + " `refineable` tinyint(1) unsigned DEFAULT NULL,\n" + " `view` smallint(3) unsigned DEFAULT NULL,\n" + " `script` text,\n" + " `equip_script` text,\n" + " `unequip_script` text,\n" + " PRIMARY KEY (`id`)\n" + ") ENGINE=MyISAM;\n" + "\n",tosql.db_name,tosql.db_name,tosql.db_name); +} +void do_db2sql(void) { if( map->db_use_sql_item_db ) { ShowInfo("db2sql: this should not be used with 'db_use_sql_item_db' enabled, skipping...\n"); return; } - stmt = SQL->StmtMalloc(mysql_handle); - if( stmt == NULL ) { - SqlStmt_ShowDebug(stmt); - return; - } - /* link */ - parse_dbrow = itemdb->parse_dbrow; - itemdb->parse_dbrow = db2sql; - /* empty table */ -#ifdef RENEWAL - if ( SQL_ERROR == SQL->Query(mysql_handle, "DELETE FROM `%s`", map->item_db_re_db ) ) -#else // not RENEWAL - if ( SQL_ERROR == SQL->Query(mysql_handle, "DELETE FROM `%s`", map->item_db_db) ) -#endif // RENEWAL - Sql_ShowDebug(mysql_handle); - else { - itemdb->reload(); - } + itemdb_readdb_libconfig_sub = itemdb->readdb_libconfig_sub; + itemdb->readdb_libconfig_sub = db2sql; + /* */ + + if ((tosql.fp = fopen("sql-files/item_db_re.sql", "wt+")) == NULL) { + ShowError("itemdb_tosql: File not found \"%s\".\n", "sql-files/item_db_re.sql"); + return; + } + + tosql.db_name = map->item_db_re_db; + totable(); + + memset(&tosql.buf, 0, sizeof(tosql.buf) ); + + itemdb->clear(false); + itemdb->readdb("re/item_db.conf"); + + fclose(tosql.fp); + + if ((tosql.fp = fopen("sql-files/item_db.sql", "wt+")) == NULL) { + ShowError("itemdb_tosql: File not found \"%s\".\n", "sql-files/item_db.sql"); + return; + } + + tosql.db_name = map->item_db_db; + totable(); + + itemdb->clear(false); + itemdb->readdb("pre-re/item_db.conf"); + + fclose(tosql.fp); + /* unlink */ - itemdb->parse_dbrow = parse_dbrow; + itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub; - SQL->StmtFree(stmt); + if( tosql.buf[0].p ) aFree(tosql.buf[0].p); + if( tosql.buf[1].p ) aFree(tosql.buf[1].p); + if( tosql.buf[2].p ) aFree(tosql.buf[2].p); + if( tosql.buf[3].p ) aFree(tosql.buf[3].p); } - -HPExport void plugin_init (void) { +CPCMD(db2sql) { + do_db2sql(); +} +void db2sql_arg(char *param) { + torun = true; +} +HPExport void server_preinit (void) { + h_config_setting_lookup_string = GET_SYMBOL("config_setting_lookup_string"); + h_config_setting_lookup_int = GET_SYMBOL("config_setting_lookup_int"); + SQL = GET_SYMBOL("SQL"); itemdb = GET_SYMBOL("itemdb"); map = GET_SYMBOL("map"); strlib = GET_SYMBOL("strlib"); + iMalloc = GET_SYMBOL("iMalloc"); + addArg("--db2sql",false,db2sql_arg,NULL); + + map->minimal = true; +} +HPExport void plugin_init (void) { HPMi->addCPCommand("server:tools:db2sql",CPCMD_A(db2sql)); } +HPExport void server_online (void) { + if( torun ) + do_db2sql(); +} |