diff options
Diffstat (limited to 'src')
106 files changed, 4540 insertions, 2584 deletions
diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c index a67f017c1..99e7c598f 100644 --- a/src/char/HPMchar.c +++ b/src/char/HPMchar.c @@ -31,7 +31,7 @@ #include "common/db.h" #include "common/des.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mapindex.h" #include "common/mmo.h" #include "common/nullpo.h" @@ -47,13 +47,19 @@ // HPMDataCheck comes after all the other includes #include "common/HPMDataCheck.h" -bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) { - /* record address */ - switch( type ) { +/** + * HPM plugin data store validator sub-handler (char-server) + * + * @see HPM_interface::data_store_validate + */ +bool HPM_char_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize) +{ + switch (type) { + // No supported types at the moment. default: - return false; + break; } - return true; + return false; } void HPM_char_plugin_load_sub(struct hplugin *plugin) { @@ -61,6 +67,8 @@ void HPM_char_plugin_load_sub(struct hplugin *plugin) { } void HPM_char_do_init(void) { + HPM->load_sub = HPM_char_plugin_load_sub; + HPM->data_store_validate_sub = HPM_char_data_store_validate; HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer); HPM_shared_symbols(SERVER_TYPE_CHAR); } diff --git a/src/char/HPMchar.h b/src/char/HPMchar.h index e3e000ef3..431017b7a 100644 --- a/src/char/HPMchar.h +++ b/src/char/HPMchar.h @@ -13,7 +13,7 @@ struct hplugin; -bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr); +bool HPM_char_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize); void HPM_char_plugin_load_sub(struct hplugin *plugin); diff --git a/src/char/char.c b/src/char/char.c index 3cc8853a4..41b13b3db 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -29,7 +29,7 @@ #include "common/console.h" #include "common/core.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mapindex.h" #include "common/mmo.h" #include "common/nullpo.h" @@ -94,10 +94,6 @@ int save_log = 1; char db_path[1024] = "db"; -int db_use_sql_item_db; -int db_use_sql_mob_db; -int db_use_sql_mob_skill_db; - char wisp_server_name[NAME_LENGTH] = "Server"; char login_ip_str[128]; uint32 login_ip = 0; @@ -2626,10 +2622,12 @@ int char_parse_fromlogin(int fd) { while(RFIFOREST(fd) >= 2) { uint16 command = RFIFOW(fd,0); - if( HPM->packetsc[hpParse_FromLogin] ) { - int success = HPM->parse_packets(fd,hpParse_FromLogin); - if( success == 1 ) continue; - else if( success == 2 ) return 0; + if (VECTOR_LENGTH(HPM->packets[hpParse_FromLogin]) > 0) { + int result = HPM->parse_packets(fd,hpParse_FromLogin); + if (result == 1) + continue; + if (result == 2) + return 0; } switch (command) { @@ -2965,9 +2963,11 @@ void mapif_server_reset(int id) WBUFL(buf,4) = htonl(chr->server[id].ip); WBUFW(buf,8) = htons(chr->server[id].port); j = 0; - for(i = 0; i < chr->server[id].maps; i++) - if (chr->server[id].map[i]) - WBUFW(buf,10+(j++)*4) = chr->server[id].map[i]; + for (i = 0; i < VECTOR_LENGTH(chr->server[id].maps); i++) { + uint16 m = VECTOR_INDEX(chr->server[id].maps, i); + if (m != 0) + WBUFW(buf,10+(j++)*4) = m; + } if (j > 0) { WBUFW(buf,2) = j * 4 + 10; mapif->sendallwos(fd, buf, WBUFW(buf,2)); @@ -3050,14 +3050,16 @@ void char_send_maps(int fd, int id, int j) // Transmitting the maps of the other map-servers to the new map-server for(k = 0; k < ARRAYLENGTH(chr->server); k++) { if (chr->server[k].fd > 0 && k != id) { - WFIFOHEAD(fd,10 +4*chr->server[k].maps); + WFIFOHEAD(fd,10 + 4 * VECTOR_LENGTH(chr->server[k].maps)); WFIFOW(fd,0) = 0x2b04; WFIFOL(fd,4) = htonl(chr->server[k].ip); WFIFOW(fd,8) = htons(chr->server[k].port); j = 0; - for(i = 0; i < chr->server[k].maps; i++) - if (chr->server[k].map[i]) - WFIFOW(fd,10+(j++)*4) = chr->server[k].map[i]; + for(i = 0; i < VECTOR_LENGTH(chr->server[k].maps); i++) { + uint16 m = VECTOR_INDEX(chr->server[k].maps, i); + if (m != 0) + WFIFOW(fd,10+(j++)*4) = m; + } if (j > 0) { WFIFOW(fd,2) = j * 4 + 10; WFIFOSET(fd,WFIFOW(fd,2)); @@ -3068,27 +3070,22 @@ void char_send_maps(int fd, int id, int j) void char_parse_frommap_map_names(int fd, int id) { - int i,j = 0; - - if( chr->server[id].map != NULL ) { aFree(chr->server[id].map); chr->server[id].map = NULL; } - - chr->server[id].maps = ( RFIFOW(fd, 2) - 4 ) / 4; - CREATE(chr->server[id].map, unsigned short, chr->server[id].maps); - + int i; - for(i = 4; i < RFIFOW(fd,2); i += 4) { - chr->server[id].map[j] = RFIFOW(fd,i); - j++; + VECTOR_CLEAR(chr->server[id].maps); + VECTOR_ENSURE(chr->server[id].maps, (RFIFOW(fd, 2) - 4) / 4, 1); + for (i = 4; i < RFIFOW(fd,2); i += 4) { + VECTOR_PUSH(chr->server[id].maps, RFIFOW(fd,i)); } ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", - id, j, CONVIP(chr->server[id].ip), chr->server[id].port); + id, (int)VECTOR_LENGTH(chr->server[id].maps), CONVIP(chr->server[id].ip), chr->server[id].port); ShowStatus("Map-server %d loading complete.\n", id); // send name for wisp to player chr->map_received_ok(fd); chr->send_fame_list(fd); //Send fame list. - chr->send_maps(fd, id, j); + chr->send_maps(fd, id, (int)VECTOR_LENGTH(chr->server[id].maps)); RFIFOSKIP(fd,RFIFOW(fd,2)); } @@ -3896,7 +3893,6 @@ void char_parse_frommap_scdata_delete(int fd) int char_parse_frommap(int fd) { - int i; int id; ARR_FIND( 0, ARRAYLENGTH(chr->server), id, chr->server[id].fd == fd ); @@ -3913,11 +3909,12 @@ int char_parse_frommap(int fd) } while(RFIFOREST(fd) >= 2) { - if( HPM->packetsc[hpParse_FromMap] ) { - if( (i = HPM->parse_packets(fd,hpParse_FromMap)) ) { - if( i == 1 ) continue; - if( i == 2 ) return 0; - } + if (VECTOR_LENGTH(HPM->packets[hpParse_FromMap]) > 0) { + int result = HPM->parse_packets(fd,hpParse_FromMap); + if (result == 1) + continue; + if (result == 2) + return 0; } switch(RFIFOW(fd,0)) { @@ -4154,11 +4151,11 @@ int char_search_mapserver(unsigned short map, uint32 ip, uint16 port) { if (chr->server[i].fd > 0 && (ip == (uint32)-1 || chr->server[i].ip == ip) - && (port == (uint16)-1 || chr->server[i].port == port)) - { - for (j = 0; chr->server[i].map[j]; j++) - if (chr->server[i].map[j] == map) - return i; + && (port == (uint16)-1 || chr->server[i].port == port) + ) { + ARR_FIND(0, VECTOR_LENGTH(chr->server[i].maps), j, VECTOR_INDEX(chr->server[i].maps, j) == map); + if (j != VECTOR_LENGTH(chr->server[i].maps)) + return i; } } @@ -4577,7 +4574,7 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl) } #endif - ARR_FIND( 0, ARRAYLENGTH(chr->server), server_id, chr->server[server_id].fd > 0 && chr->server[server_id].map ); + ARR_FIND(0, ARRAYLENGTH(chr->server), server_id, chr->server[server_id].fd > 0 && VECTOR_LENGTH(chr->server[server_id].maps) > 0); /* not available, tell it to wait (client wont close; char select will respawn). * magic response found by Ind thanks to Yommy <3 */ if( server_id == ARRAYLENGTH(chr->server) ) { @@ -4638,7 +4635,7 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl) if (i < 0 || !cd->last_point.map) { unsigned short j; //First check that there's actually a map server online. - ARR_FIND( 0, ARRAYLENGTH(chr->server), j, chr->server[j].fd >= 0 && chr->server[j].map ); + ARR_FIND(0, ARRAYLENGTH(chr->server), j, chr->server[j].fd >= 0 && VECTOR_LENGTH(chr->server[j].maps) > 0); if (j == ARRAYLENGTH(chr->server)) { ShowInfo("Connection Closed. No map servers available.\n"); chr->authfail_fd(fd, 1); // 1 = Server closed @@ -5095,10 +5092,12 @@ int char_parse_char(int fd) //For use in packets that depend on an sd being present [Skotlex] #define FIFOSD_CHECK(rest) do { if(RFIFOREST(fd) < (rest)) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,(rest)); return 0; } } while (0) - if( HPM->packetsc[hpParse_Char] ) { - int success = HPM->parse_packets(fd,hpParse_Char); - if( success == 1 ) continue; - else if( success == 2 ) return 0; + if (VECTOR_LENGTH(HPM->packets[hpParse_Char]) > 0) { + int result = HPM->parse_packets(fd,hpParse_Char); + if (result == 1) + continue; + if (result == 2) + return 0; } cmd = RFIFOW(fd,0); @@ -5785,9 +5784,8 @@ int do_final(void) { SQL->Free(inter->sql_handle); mapindex->final(); - for(i = 0; i < MAX_MAP_SERVERS; i++ ) - if( chr->server[i].map ) - aFree(chr->server[i].map); + for (i = 0; i < MAX_MAP_SERVERS; i++) + VECTOR_CLEAR(chr->server[i].maps); aFree(chr->CHAR_CONF_NAME); aFree(chr->NET_CONF_NAME); @@ -5886,8 +5884,8 @@ int do_init(int argc, char **argv) { chr->SQL_CONF_NAME = aStrdup("conf/inter-server.conf"); chr->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); - for(i = 0; i < MAX_MAP_SERVERS; i++ ) - chr->server[i].map = NULL; + for (i = 0; i < MAX_MAP_SERVERS; i++) + VECTOR_INIT(chr->server[i].maps); HPM_char_do_init(); cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); diff --git a/src/char/char.h b/src/char/char.h index e79cc1898..7576b00ce 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -49,8 +49,7 @@ struct mmo_map_server { uint32 ip; uint16 port; int users; - unsigned short *map; - unsigned short maps; + VECTOR_DECL(uint16) maps; }; #define MAX_MAP_SERVERS 2 @@ -299,10 +298,6 @@ extern char acc_reg_str_db[32]; extern char char_reg_str_db[32]; extern char char_reg_num_db[32]; -extern int db_use_sql_item_db; -extern int db_use_sql_mob_db; -extern int db_use_sql_mob_skill_db; - extern int guild_exp_rate; extern int log_inter; diff --git a/src/char/geoip.c b/src/char/geoip.c index 65bb2bdd4..924c1cd83 100644 --- a/src/char/geoip.c +++ b/src/char/geoip.c @@ -7,7 +7,7 @@ #include "geoip.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/showmsg.h" #include <errno.h> diff --git a/src/char/int_auction.c b/src/char/int_auction.c index 67c83ca22..48bf715f2 100644 --- a/src/char/int_auction.c +++ b/src/char/int_auction.c @@ -12,7 +12,7 @@ #include "char/mapif.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_elemental.c b/src/char/int_elemental.c index e7708179a..3969e5e43 100644 --- a/src/char/int_elemental.c +++ b/src/char/int_elemental.c @@ -9,7 +9,7 @@ #include "char/char.h" #include "char/inter.h" #include "char/mapif.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_guild.c b/src/char/int_guild.c index 54355161d..239e8a296 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -12,7 +12,7 @@ #include "char/mapif.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_homun.c b/src/char/int_homun.c index be72ecd58..78b4dbb61 100644 --- a/src/char/int_homun.c +++ b/src/char/int_homun.c @@ -9,7 +9,7 @@ #include "char/char.h" #include "char/inter.h" #include "char/mapif.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_mail.c b/src/char/int_mail.c index 854fe31b1..933856b14 100644 --- a/src/char/int_mail.c +++ b/src/char/int_mail.c @@ -9,7 +9,7 @@ #include "char/char.h" #include "char/inter.h" #include "char/mapif.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_mercenary.c b/src/char/int_mercenary.c index dd40a0224..fb98161fe 100644 --- a/src/char/int_mercenary.c +++ b/src/char/int_mercenary.c @@ -10,7 +10,7 @@ #include "char/inter.h" #include "char/mapif.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_party.c b/src/char/int_party.c index aedcb8535..d4af67eb3 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -11,7 +11,7 @@ #include "char/mapif.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mapindex.h" #include "common/mmo.h" #include "common/nullpo.h" diff --git a/src/char/int_pet.c b/src/char/int_pet.c index 97b2fb6a4..37e238725 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -9,7 +9,7 @@ #include "char/char.h" #include "char/inter.h" #include "char/mapif.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_quest.c b/src/char/int_quest.c index fcd56230b..e2ee3401a 100644 --- a/src/char/int_quest.c +++ b/src/char/int_quest.c @@ -10,7 +10,7 @@ #include "char/inter.h" #include "char/mapif.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 3a8a6a169..c0cae5300 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -10,7 +10,7 @@ #include "char/char.h" #include "char/inter.h" #include "char/mapif.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/inter.c b/src/char/inter.c index 65048a9f9..1ed29719e 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -21,7 +21,7 @@ #include "char/mapif.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/char/loginif.c b/src/char/loginif.c index 422c7c589..e99e05237 100644 --- a/src/char/loginif.c +++ b/src/char/loginif.c @@ -63,8 +63,8 @@ void loginif_on_ready(void) chr->send_accounts_tologin(INVALID_TIMER, timer->gettick(), 0, 0); // if no map-server already connected, display a message... - ARR_FIND( 0, ARRAYLENGTH(chr->server), i, chr->server[i].fd > 0 && chr->server[i].map ); - if( i == ARRAYLENGTH(chr->server) ) + ARR_FIND(0, ARRAYLENGTH(chr->server), i, chr->server[i].fd > 0 && VECTOR_LENGTH(chr->server[i].maps)); + if (i == ARRAYLENGTH(chr->server)) ShowStatus("Awaiting maps from map-server.\n"); } diff --git a/src/common/HPM.c b/src/common/HPM.c index 23265fa24..7d9a0b104 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -11,7 +11,7 @@ #include "common/console.h" #include "common/core.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mapindex.h" #include "common/mmo.h" #include "common/showmsg.h" @@ -43,28 +43,52 @@ 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++ ) { - if( HPM->plugins[i]->hpi->event[type] != NULL ) - (HPM->plugins[i]->hpi->event[type])(); +/** + * Executes an event on all loaded plugins. + * + * @param type The event type to trigger. + */ +void hplugin_trigger_event(enum hp_event_types type) +{ + int i; + for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i); + if (plugin->hpi->event[type] != NULL) + plugin->hpi->event[type](); } } -void hplugin_export_symbol(void *var, char *name) { - RECREATE(HPM->symbols, struct hpm_symbol *, ++HPM->symbol_count); - CREATE(HPM->symbols[HPM->symbol_count - 1] ,struct hpm_symbol, 1); - HPM->symbols[HPM->symbol_count - 1]->name = name; - HPM->symbols[HPM->symbol_count - 1]->ptr = var; +/** + * Exports a symbol to the shared symbols list. + * + * @param value The symbol value. + * @param name The symbol name. + */ +void hplugin_export_symbol(void *value, const char *name) +{ + struct hpm_symbol *symbol = NULL; + CREATE(symbol ,struct hpm_symbol, 1); + symbol->name = name; + symbol->ptr = value; + VECTOR_ENSURE(HPM->symbols, 1, 1); + VECTOR_PUSH(HPM->symbols, symbol); } -void *hplugin_import_symbol(char *name, unsigned int pID) { - unsigned int i; +/** + * Imports a shared symbol. + * + * @param name The symbol name. + * @param pID The requesting plugin ID. + * @return The symbol value. + * @retval NULL if the symbol wasn't found. + */ +void *hplugin_import_symbol(char *name, unsigned int pID) +{ + int i; + ARR_FIND(0, VECTOR_LENGTH(HPM->symbols), i, strcmp(VECTOR_INDEX(HPM->symbols, i)->name, name) == 0); - for( i = 0; i < HPM->symbol_count; i++ ) { - if( strcmp(HPM->symbols[i]->name,name) == 0 ) - return HPM->symbols[i]->ptr; - } + if (i != VECTOR_LENGTH(HPM->symbols)) + return VECTOR_INDEX(HPM->symbols, i)->ptr; ShowError("HPM:get_symbol:%s: '"CL_WHITE"%s"CL_RESET"' not found!\n",HPM->pid2name(pID),name); return NULL; @@ -81,40 +105,60 @@ bool hplugin_iscompatible(char* version) { return ( req_major == HPM->version[0] && req_minor <= HPM->version[1] ) ? true : false; } -bool hplugin_exists(const char *filename) { - unsigned int i; - for(i = 0; i < HPM->plugin_count; i++) { - if( strcmpi(HPM->plugins[i]->filename,filename) == 0 ) +/** + * Checks whether a plugin is currently loaded + * + * @param filename The plugin filename. + * @retval true if the plugin exists and is currently loaded. + * @retval false otherwise. + */ +bool hplugin_exists(const char *filename) +{ + int i; + for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + if (strcmpi(VECTOR_INDEX(HPM->plugins, i)->filename,filename) == 0) return true; } return false; } -struct hplugin *hplugin_create(void) { - RECREATE(HPM->plugins, struct hplugin *, ++HPM->plugin_count); - CREATE(HPM->plugins[HPM->plugin_count - 1], struct hplugin, 1); - HPM->plugins[HPM->plugin_count - 1]->idx = HPM->plugin_count - 1; - HPM->plugins[HPM->plugin_count - 1]->filename = NULL; - return HPM->plugins[HPM->plugin_count - 1]; + +/** + * Initializes the data structure for a new plugin and registers it. + * + * @return A (retained) pointer to the initialized data. + */ +struct hplugin *hplugin_create(void) +{ + struct hplugin *plugin = NULL; + CREATE(plugin, struct hplugin, 1); + plugin->idx = (int)VECTOR_LENGTH(HPM->plugins); + plugin->filename = NULL; + VECTOR_ENSURE(HPM->plugins, 1, 1); + VECTOR_PUSH(HPM->plugins, plugin); + return plugin; } -bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receive) (int fd), unsigned int point,unsigned int pluginID) { +bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receive) (int fd), unsigned int point, unsigned int pluginID) +{ struct HPluginPacket *packet; - unsigned int i; + int i; - if( point >= hpPHP_MAX ) { + if (point >= hpPHP_MAX) { ShowError("HPM->addPacket:%s: unknown point '%u' specified for packet 0x%04x (len %d)\n",HPM->pid2name(pluginID),point,cmd,length); return false; } - for(i = 0; i < HPM->packetsc[point]; i++) { - if( HPM->packets[point][i].cmd == cmd ) { - ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!",HPM->pid2name(pluginID),cmd,HPM->pid2name(HPM->packets[point][i].pluginID)); + for (i = 0; i < VECTOR_LENGTH(HPM->packets[point]); i++) { + if (VECTOR_INDEX(HPM->packets[point], i).cmd == cmd ) { + ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!", + HPM->pid2name(pluginID), cmd, HPM->pid2name(VECTOR_INDEX(HPM->packets[point], i).pluginID)); return false; } } - RECREATE(HPM->packets[point], struct HPluginPacket, ++HPM->packetsc[point]); - packet = &HPM->packets[point][HPM->packetsc[point] - 1]; + VECTOR_ENSURE(HPM->packets[point], 1, 1); + VECTOR_PUSHZEROED(HPM->packets[point]); + packet = &VECTOR_LAST(HPM->packets[point]); packet->pluginID = pluginID; packet->cmd = cmd; @@ -124,136 +168,158 @@ bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receiv return true; } -void hplugins_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) +/** + * Validates and if necessary initializes a plugin data store. + * + * @param type[in] The data store type. + * @param storeptr[in,out] A pointer to the store. + * @param initialize Whether the store should be initialized in case it isn't. + * @retval false if the store is an invalid or mismatching type. + * @retval true if the store is a valid type. + * + * @remark + * If \c storeptr is a pointer to a NULL pointer (\c storeptr itself can't + * be NULL), two things may happen, depending on the \c initialize value: + * if false, then \c storeptr isn't changed; if true, then \c storeptr is + * initialized through \c HPM->data_store_create() and ownership is passed + * to the caller. + */ +bool hplugin_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize) { - /* record address */ + struct hplugin_data_store *store; + nullpo_retr(false, storeptr); + store = *storeptr; + if (!initialize && store == NULL) + return true; + switch (type) { /* core-handled */ case HPDT_SESSION: - ret->HPDataSRCPtr = (void**)(&((struct socket_data *)ptr)->hdata); - ret->hdatac = &((struct socket_data *)ptr)->hdatac; break; - /* goes to sub */ default: - if (HPM->grabHPDataSub) { - if (HPM->grabHPDataSub(ret,type,ptr)) - return; - ShowError("HPM:HPM:grabHPData failed, unknown type %d!\n",type); - } else { - ShowError("HPM:grabHPData failed, type %d needs sub-handler!\n",type); + if (HPM->data_store_validate_sub == NULL) { + ShowError("HPM:validateHPData failed, type %d needs sub-handler!\n",type); + return false; + } + if (!HPM->data_store_validate_sub(type, storeptr, initialize)) { + ShowError("HPM:HPM:validateHPData failed, unknown type %d!\n",type); + return false; } - ret->HPDataSRCPtr = NULL; - ret->hdatac = NULL; - return; + break; + } + if (initialize && (!store || store->type == HPDT_UNKNOWN)) { + HPM->data_store_create(storeptr, type); + store = *storeptr; } + if (store->type != type) { + ShowError("HPM:HPM:validateHPData failed, store type mismatch %d != %d.\n",store->type, type); + return false; + } + return true; } -void hplugins_addToHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, void *data, unsigned int index, bool autofree) +/** + * Adds an entry to a plugin data store. + * + * @param type[in] The store type. + * @param pluginID[in] The plugin identifier. + * @param storeptr[in,out] A pointer to the store. The store will be initialized if necessary. + * @param data[in] The data entry to add. + * @param classid[in] The entry class identifier. + * @param autofree[in] Whether the entry should be automatically freed when removed. + */ +void hplugins_addToHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store **storeptr, void *data, uint32 classid, bool autofree) { - struct HPluginData *HPData, **HPDataSRC; - struct HPDataOperationStorage action; - unsigned int i, max; - - HPM->grabHPData(&action,type,ptr); + struct hplugin_data_store *store; + struct hplugin_data_entry *entry; + int i; + nullpo_retv(storeptr); - if (action.hdatac == NULL) { /* woo it failed! */ - ShowError("HPM:addToHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index); + if (!HPM->data_store_validate(type, storeptr, true)) { + /* woo it failed! */ + ShowError("HPM:addToHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); return; } - - /* flag */ - HPDataSRC = *(action.HPDataSRCPtr); - max = *(action.hdatac); + store = *storeptr; /* duplicate check */ - for (i = 0; i < max; i++) { - if (HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index) { - ShowError("HPM:addToHPData:%s: error! attempting to insert duplicate struct of id %u and index %u\n",HPM->pid2name(pluginID),pluginID,index); - return; - } + ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid); + if (i != VECTOR_LENGTH(store->entries)) { + ShowError("HPM:addToHPData:%s: error! attempting to insert duplicate struct of id %u and classid %u\n", HPM->pid2name(pluginID), pluginID, classid); + return; } - /* HPluginData is always same size, probably better to use the ERS (with reasonable chunk size e.g. 10/25/50) */ - CREATE(HPData, struct HPluginData, 1); + /* hplugin_data_entry is always same size, probably better to use the ERS (with reasonable chunk size e.g. 10/25/50) */ + CREATE(entry, struct hplugin_data_entry, 1); /* input */ - HPData->pluginID = pluginID; - HPData->type = index; - HPData->flag.free = autofree ? 1 : 0; - HPData->data = data; - - /* resize */ - *(action.hdatac) += 1; - RECREATE(*(action.HPDataSRCPtr),struct HPluginData *,*(action.hdatac)); + entry->pluginID = pluginID; + entry->classid = classid; + entry->flag.free = autofree ? 1 : 0; + entry->data = data; - /* RECREATE modified the address */ - HPDataSRC = *(action.HPDataSRCPtr); - HPDataSRC[*(action.hdatac) - 1] = HPData; + VECTOR_ENSURE(store->entries, 1, 1); + VECTOR_PUSH(store->entries, entry); } -void *hplugins_getFromHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index) +/** + * Retrieves an entry from a plugin data store. + * + * @param type[in] The store type. + * @param pluginID[in] The plugin identifier. + * @param store[in] The store. + * @param classid[in] The entry class identifier. + * + * @return The retrieved entry, or NULL. + */ +void *hplugins_getFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid) { - struct HPDataOperationStorage action; - struct HPluginData **HPDataSRC; - unsigned int i, max; - - HPM->grabHPData(&action,type,ptr); + int i; - if (action.hdatac == NULL) { /* woo it failed! */ - ShowError("HPM:getFromHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index); + if (!HPM->data_store_validate(type, &store, false)) { + /* woo it failed! */ + ShowError("HPM:getFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); return NULL; } + if (!store) + return NULL; - /* flag */ - HPDataSRC = *(action.HPDataSRCPtr); - max = *(action.hdatac); - - for (i = 0; i < max; i++) { - if (HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index) - return HPDataSRC[i]->data; - } + ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid); + if (i != VECTOR_LENGTH(store->entries)) + return VECTOR_INDEX(store->entries, i)->data; return NULL; } -void hplugins_removeFromHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index) +/** + * Removes an entry from a plugin data store. + * + * @param type[in] The store type. + * @param pluginID[in] The plugin identifier. + * @param store[in] The store. + * @param classid[in] The entry class identifier. + */ +void hplugins_removeFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid) { - struct HPDataOperationStorage action; - struct HPluginData **HPDataSRC; - unsigned int i, max; - - HPM->grabHPData(&action,type,ptr); + struct hplugin_data_entry *entry; + int i; - if (action.hdatac == NULL) { /* woo it failed! */ - ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index); + if (!HPM->data_store_validate(type, &store, false)) { + /* woo it failed! */ + ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); return; } + if (!store) + return; - /* flag */ - HPDataSRC = *(action.HPDataSRCPtr); - max = *(action.hdatac); - - for (i = 0; i < max; i++) { - if (HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index) - break; - } - - if (i != max) { - unsigned int cursor; - - aFree(HPDataSRC[i]->data);/* when its removed we delete it regardless of autofree */ - aFree(HPDataSRC[i]); - HPDataSRC[i] = NULL; + ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid); + if (i == VECTOR_LENGTH(store->entries)) + return; - for (i = 0, cursor = 0; i < max; i++) { - if (HPDataSRC[i] == NULL) - continue; - if (i != cursor) - HPDataSRC[cursor] = HPDataSRC[i]; - cursor++; - } - *(action.hdatac) = cursor; - } + entry = VECTOR_INDEX(store->entries, i); + VECTOR_ERASE(store->entries, i); // Erase and compact + aFree(entry->data); // when it's removed we delete it regardless of autofree + aFree(entry); } /* TODO: add ability for tracking using pID for the upcoming runtime load/unload support. */ @@ -303,9 +369,9 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecF return false; } - ARR_FIND(0, cmdline->args_data_count, i, strcmp(cmdline->args_data[i].name, name) == 0); + ARR_FIND(0, VECTOR_LENGTH(cmdline->args_data), i, strcmp(VECTOR_INDEX(cmdline->args_data, i).name, name) == 0); - if (i < cmdline->args_data_count) { + if (i != VECTOR_LENGTH(cmdline->args_data)) { ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID)); return false; } @@ -313,25 +379,36 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecF return cmdline->arg_add(pluginID, name, '\0', func, help, has_param ? CMDLINE_OPT_PARAM : CMDLINE_OPT_NORMAL); } +/** + * Adds a configuration listener for a plugin. + * + * @param pluginID The plugin identifier. + * @param type The configuration type to listen for. + * @param name The configuration entry name. + * @param func The callback function. + * @retval true if the listener was added successfully. + * @retval false in case of error. + */ bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val)) { struct HPConfListenStorage *conf; - unsigned int i; + int i; if (type >= HPCT_MAX) { ShowError("HPM->addConf:%s: unknown point '%u' specified for config '%s'\n",HPM->pid2name(pluginID),type,name); return false; } - for (i = 0; i < HPM->confsc[type]; i++) { - if (!strcmpi(name,HPM->confs[type][i].key)) { - ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!",HPM->pid2name(pluginID),name,HPM->pid2name(HPM->confs[type][i].pluginID)); - return false; - } + ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[type]), i, strcmpi(name, VECTOR_INDEX(HPM->config_listeners[type], i).key) == 0); + if (i != VECTOR_LENGTH(HPM->config_listeners[type])) { + ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!", + HPM->pid2name(pluginID), name, HPM->pid2name(VECTOR_INDEX(HPM->config_listeners[type], i).pluginID)); + return false; } - RECREATE(HPM->confs[type], struct HPConfListenStorage, ++HPM->confsc[type]); - conf = &HPM->confs[type][HPM->confsc[type] - 1]; + VECTOR_ENSURE(HPM->config_listeners[type], 1, 1); + VECTOR_PUSHZEROED(HPM->config_listeners[type]); + conf = &VECTOR_LAST(HPM->config_listeners[type]); conf->pluginID = pluginID; safestrncpy(conf->key, name, HPM_ADDCONF_LENGTH); @@ -477,30 +554,23 @@ struct hplugin *hplugin_load(const char* filename) { return plugin; } +/** + * Unloads and unregisters a plugin. + * + * @param plugin The plugin data. + */ void hplugin_unload(struct hplugin* plugin) { + int i; if (plugin->filename) aFree(plugin->filename); if (plugin->dll) plugin_close(plugin->dll); /* TODO: for manual packet unload */ /* - Go through known packets and unlink any belonging to the plugin being removed */ - if (!HPM->off) { - int i, cursor; - for (cursor = 0; cursor < HPM->plugin_count; cursor++) { - if (HPM->plugins[cursor]->idx != plugin->idx) - continue; - HPM->plugins[cursor] = NULL; - break; - } - for(i = cursor + 1; i < HPM->plugin_count; i++) { - HPM->plugins[cursor] = HPM->plugins[i]; - cursor++; - } - if (!(HPM->plugin_count = cursor)) { - aFree(HPM->plugins); - HPM->plugins = NULL; - } + ARR_FIND(0, VECTOR_LENGTH(HPM->plugins), i, VECTOR_INDEX(HPM->plugins, i)->idx == plugin->idx); + if (i != VECTOR_LENGTH(HPM->plugins)) { + VECTOR_ERASE(HPM->plugins, i); } aFree(plugin); } @@ -510,8 +580,8 @@ void hplugin_unload(struct hplugin* plugin) */ CMDLINEARG(loadplugin) { - RECREATE(HPM->cmdline_plugins, char *, ++HPM->cmdline_plugins_count); - HPM->cmdline_plugins[HPM->cmdline_plugins_count-1] = aStrdup(params); + VECTOR_ENSURE(HPM->cmdline_load_plugins, 1, 1); + VECTOR_PUSH(HPM->cmdline_load_plugins, aStrdup(params)); return true; } @@ -535,9 +605,9 @@ void hplugins_config_read(void) { return; plist = libconfig->lookup(&plugins_conf, "plugins_list"); - for (i = 0; i < HPM->cmdline_plugins_count; i++) { + for (i = 0; i < VECTOR_LENGTH(HPM->cmdline_load_plugins); i++) { config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING); - config_setting_set_string(entry, HPM->cmdline_plugins[i]); + config_setting_set_string(entry, VECTOR_INDEX(HPM->cmdline_load_plugins, i)); } if (plist != NULL) { @@ -584,83 +654,117 @@ void hplugins_config_read(void) { } libconfig->destroy(&plugins_conf); - if( HPM->plugin_count ) - ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", HPM->plugin_count); + if (VECTOR_LENGTH(HPM->plugins)) + ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", VECTOR_LENGTH(HPM->plugins)); } -CPCMD(plugins) { - if( HPM->plugin_count == 0 ) { + +/** + * Console command: plugins + * + * Shows a list of loaded plugins. + * + * @see CPCMD() + */ +CPCMD(plugins) +{ + int i; + + if (VECTOR_LENGTH(HPM->plugins) == 0) { ShowInfo("HPC: there are no plugins loaded\n"); - } else { - unsigned int i; + return; + } - ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n",HPM->plugin_count); + ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n", VECTOR_LENGTH(HPM->plugins)); - for(i = 0; i < HPM->plugin_count; i++) { - ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n",HPM->plugins[i]->info->name,HPM->plugins[i]->filename); - } + for(i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i); + ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n", plugin->info->name, plugin->filename); } } -/* - 0 = unknown - 1 = OK - 2 = incomplete +/** + * Parses a packet through the registered plugin. + * + * @param fd The connection fd. + * @param point The packet hooking point. + * @retval 0 unknown packet + * @retval 1 OK + * @retval 2 incomplete packet */ -unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point) { - unsigned int i; +unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point) +{ + struct HPluginPacket *packet = NULL; + int i; + int16 length; - for(i = 0; i < HPM->packetsc[point]; i++) { - if( HPM->packets[point][i].cmd == RFIFOW(fd,0) ) - break; - } + ARR_FIND(0, VECTOR_LENGTH(HPM->packets[point]), i, VECTOR_INDEX(HPM->packets[point], i).cmd == RFIFOW(fd,0)); - if( i != HPM->packetsc[point] ) { - struct HPluginPacket *packet = &HPM->packets[point][i]; - short length; + if (i == VECTOR_LENGTH(HPM->packets[point])) + return 0; - if( (length = packet->len) == -1 ) { - if( (length = RFIFOW(fd, 2)) > (int)RFIFOREST(fd) ) - return 2; - } + packet = &VECTOR_INDEX(HPM->packets[point], i); + length = packet->len; + if (length == -1) + length = RFIFOW(fd, 2); - packet->receive(fd); - RFIFOSKIP(fd, length); - return 1; - } + if (length > (int)RFIFOREST(fd)) + return 2; - return 0; + packet->receive(fd); + RFIFOSKIP(fd, length); + return 1; } -char *hplugins_id2name (unsigned int pid) { - unsigned int i; +/** + * Retrieves a plugin name by ID. + * + * @param pid The plugin identifier. + * @return The plugin name. + * @retval "core" if the plugin ID belongs to the Hercules core. + * @retval "UnknownPlugin" if the plugin wasn't found. + */ +char *hplugins_id2name(unsigned int pid) +{ + int i; if (pid == HPM_PID_CORE) return "core"; - for( i = 0; i < HPM->plugin_count; i++ ) { - if( HPM->plugins[i]->idx == pid ) - return HPM->plugins[i]->info->name; + for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i); + if (plugin->idx == pid) + return plugin->info->name; } return "UnknownPlugin"; } -char* HPM_file2ptr(const char *file) { - unsigned int i; - for(i = 0; i < HPM->fnamec; i++) { - if( HPM->fnames[i].addr == file ) - return HPM->fnames[i].name; - } +/** + * Returns a retained permanent pointer to a source filename, for memory-manager reporting use. + * + * The returned pointer is safe to be used as filename in the memory manager + * functions, and it will be available during and after the memory manager + * shutdown (for memory leak reporting purposes). + * + * @param file The string/filename to retain + * @return A retained copy of the source string. + */ +const char *HPM_file2ptr(const char *file) +{ + int i; - i = HPM->fnamec; + ARR_FIND(0, HPM->filenames.count, i, HPM->filenames.data[i].addr == file); + if (i != HPM->filenames.count) { + return HPM->filenames.data[i].name; + } /* we handle this memory outside of the server's memory manager because we need it to exist after the memory manager goes down */ - HPM->fnames = realloc(HPM->fnames,(++HPM->fnamec)*sizeof(struct HPMFileNameCache)); + HPM->filenames.data = realloc(HPM->filenames.data, (++HPM->filenames.count)*sizeof(struct HPMFileNameCache)); - HPM->fnames[i].addr = file; - HPM->fnames[i].name = strdup(file); + HPM->filenames.data[i].addr = file; + HPM->filenames.data[i].name = strdup(file); - return HPM->fnames[i].name; + return HPM->filenames.data[i].name; } void* HPM_mmalloc(size_t size, const char *file, int line, const char *func) { return iMalloc->malloc(size,HPM_file2ptr(file),line,func); @@ -678,22 +782,74 @@ char* HPM_astrdup(const char *p, const char *file, int line, const char *func) { return iMalloc->astrdup(p,HPM_file2ptr(file),line,func); } -bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType point) { - unsigned int i; +/** + * Parses a configuration entry through the registered plugins. + * + * @param w1 The configuration entry name. + * @param w2 The configuration entry value. + * @param point The type of configuration file. + * @retval true if a registered plugin was found to handle the entry. + * @retval false if no registered plugins could be found. + */ +bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType point) +{ + int i; + ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[point]), i, strcmpi(w1, VECTOR_INDEX(HPM->config_listeners[point], i).key) == 0); + if (i == VECTOR_LENGTH(HPM->config_listeners[point])) + return false; - /* exists? */ - for(i = 0; i < HPM->confsc[point]; i++) { - if( !strcmpi(w1,HPM->confs[point][i].key) ) - break; + VECTOR_INDEX(HPM->config_listeners[point], i).func(w2); + return true; +} + +/** + * Helper to destroy an interface's hplugin_data store and release any owned memory. + * + * The pointer will be cleared. + * + * @param storeptr[in,out] A pointer to the plugin data store. + */ +void hplugin_data_store_destroy(struct hplugin_data_store **storeptr) +{ + struct hplugin_data_store *store; + nullpo_retv(storeptr); + store = *storeptr; + if (store == NULL) + return; + + while (VECTOR_LENGTH(store->entries) > 0) { + struct hplugin_data_entry *entry = VECTOR_POP(store->entries); + if (entry->flag.free) { + aFree(entry->data); + } + aFree(entry); } + VECTOR_CLEAR(store->entries); + aFree(store); + *storeptr = NULL; +} - /* trigger and we're set! */ - if( i != HPM->confsc[point] ) { - HPM->confs[point][i].func(w2); - return true; +/** + * Helper to create and initialize an interface's hplugin_data store. + * + * The store is owned by the caller, and it should be eventually destroyed by + * \c hdata_destroy. + * + * @param storeptr[in,out] A pointer to the data store to initialize. + * @param type[in] The store type. + */ +void hplugin_data_store_create(struct hplugin_data_store **storeptr, enum HPluginDataTypes type) +{ + struct hplugin_data_store *store; + nullpo_retv(storeptr); + + if (*storeptr == NULL) { + CREATE(*storeptr, struct hplugin_data_store, 1); } + store = *storeptr; - return false; + store->type = type; + VECTOR_INIT(store->entries); } /** @@ -747,14 +903,14 @@ void HPM_datacheck_final(void) { } void hpm_init(void) { - unsigned int i; + int i; datacheck_db = NULL; datacheck_data = NULL; datacheck_version = 0; - HPM->symbols = NULL; - HPM->plugins = NULL; - HPM->plugin_count = HPM->symbol_count = 0; + VECTOR_INIT(HPM->plugins); + VECTOR_INIT(HPM->symbols); + HPM->off = false; memcpy(&iMalloc_HPM, iMalloc, sizeof(struct malloc_interface)); @@ -772,9 +928,12 @@ void hpm_init(void) { return; } - for(i = 0; i < hpPHP_MAX; i++) { - HPM->packets[i] = NULL; - HPM->packetsc[i] = 0; + for (i = 0; i < hpPHP_MAX; i++) { + VECTOR_INIT(HPM->packets[i]); + } + + for (i = 0; i < HPCT_MAX; i++) { + VECTOR_INIT(HPM->config_listeners[i]); } #ifdef CONSOLE_INPUT @@ -782,84 +941,68 @@ void hpm_init(void) { #endif return; } + +/** + * Releases the retained filenames cache. + */ void hpm_memdown(void) { - /* this memory is handled outside of the server's memory manager and thus cleared after memory manager goes down */ - - if (HPM->fnames) { - unsigned int i; - for (i = 0; i < HPM->fnamec; i++) { - free(HPM->fnames[i].name); + /* this memory is handled outside of the server's memory manager and + * thus cleared after memory manager goes down */ + if (HPM->filenames.count) { + int i; + for (i = 0; i < HPM->filenames.count; i++) { + free(HPM->filenames.data[i].name); } - free(HPM->fnames); + free(HPM->filenames.data); + HPM->filenames.data = NULL; + HPM->filenames.count = 0; } } -void hpm_final(void) { - unsigned int i; + +void hpm_final(void) +{ + int i; HPM->off = true; - if( HPM->plugins ) - { - for( i = 0; i < HPM->plugin_count; i++ ) { - HPM->unload(HPM->plugins[i]); - } - aFree(HPM->plugins); + while (VECTOR_LENGTH(HPM->plugins)) { + HPM->unload(VECTOR_LAST(HPM->plugins)); } + VECTOR_CLEAR(HPM->plugins); - if( HPM->symbols ) - { - for( i = 0; i < HPM->symbol_count; i++ ) { - aFree(HPM->symbols[i]); - } - aFree(HPM->symbols); + while (VECTOR_LENGTH(HPM->symbols)) { + aFree(VECTOR_POP(HPM->symbols)); } + VECTOR_CLEAR(HPM->symbols); - for( i = 0; i < hpPHP_MAX; i++ ) { - if( HPM->packets[i] ) - aFree(HPM->packets[i]); + for (i = 0; i < hpPHP_MAX; i++) { + VECTOR_CLEAR(HPM->packets[i]); } - for( i = 0; i < HPCT_MAX; i++ ) { - if( HPM->confsc[i] ) - aFree(HPM->confs[i]); + for (i = 0; i < HPCT_MAX; i++) { + VECTOR_CLEAR(HPM->config_listeners[i]); } - if (HPM->cmdline_plugins) { - int j; - for (j = 0; j < HPM->cmdline_plugins_count; j++) - aFree(HPM->cmdline_plugins[j]); - aFree(HPM->cmdline_plugins); - HPM->cmdline_plugins = NULL; - HPM->cmdline_plugins_count = 0; + + while (VECTOR_LENGTH(HPM->cmdline_load_plugins)) { + aFree(VECTOR_POP(HPM->cmdline_load_plugins)); } + VECTOR_CLEAR(HPM->cmdline_load_plugins); /* HPM->fnames is cleared after the memory manager goes down */ iMalloc->post_shutdown = hpm_memdown; return; } -void hpm_defaults(void) { - unsigned int i; +void hpm_defaults(void) +{ HPM = &HPM_s; - HPM->fnames = NULL; - HPM->fnamec = 0; + memset(&HPM->filenames, 0, sizeof(HPM->filenames)); + VECTOR_INIT(HPM->cmdline_load_plugins); HPM->force_return = false; HPM->hooking = false; /* */ - HPM->fnames = NULL; - HPM->fnamec = 0; - for(i = 0; i < hpPHP_MAX; i++) { - HPM->packets[i] = NULL; - HPM->packetsc[i] = 0; - } - for(i = 0; i < HPCT_MAX; i++) { - HPM->confs[i] = NULL; - HPM->confsc[i] = 0; - } - HPM->cmdline_plugins = NULL; - HPM->cmdline_plugins_count = 0; - /* */ HPM->init = hpm_init; HPM->final = hpm_final; @@ -876,10 +1019,13 @@ void hpm_defaults(void) { HPM->parse_packets = hplugins_parse_packets; HPM->load_sub = NULL; HPM->addhook_sub = NULL; - HPM->grabHPData = hplugins_grabHPData; - HPM->grabHPDataSub = NULL; HPM->parseConf = hplugins_parse_conf; HPM->DataCheck = HPM_DataCheck; HPM->datacheck_init = HPM_datacheck_init; HPM->datacheck_final = HPM_datacheck_final; + + HPM->data_store_destroy = hplugin_data_store_destroy; + HPM->data_store_create = hplugin_data_store_create; + HPM->data_store_validate = hplugin_data_store_validate; + HPM->data_store_validate_sub = NULL; } diff --git a/src/common/HPM.h b/src/common/HPM.h index c13132cfc..5420e5300 100644 --- a/src/common/HPM.h +++ b/src/common/HPM.h @@ -9,6 +9,7 @@ #endif #include "common/hercules.h" +#include "common/db.h" #include "common/HPMi.h" #ifdef WIN32 @@ -56,18 +57,32 @@ struct hplugin { struct HPMi_interface *hpi; }; +/** + * Symbols shared between core and plugins. + */ struct hpm_symbol { - char *name; - void *ptr; + const char *name; ///< The symbol name + void *ptr; ///< The symbol value }; -struct HPluginData { - unsigned int pluginID; - unsigned int type; +/** + * A plugin custom data, to be injected in various interfaces and objects. + */ +struct hplugin_data_entry { + uint32 pluginID; ///< The owner plugin identifier. + uint32 classid; ///< The entry's object type, managed by the plugin (for plugins that need more than one entry). struct { - unsigned int free : 1; + unsigned int free : 1; ///< Whether the entry data should be automatically cleared by the HPM. } flag; - void *data; + void *data; ///< The entry data. +}; + +/** + * A store for plugin custom data entries. + */ +struct hplugin_data_store { + enum HPluginDataTypes type; ///< The store type. + VECTOR_DECL(struct hplugin_data_entry *) entries; ///< The store entries. }; struct HPluginPacket { @@ -82,10 +97,6 @@ struct HPMFileNameCache { char *name; }; -struct HPDataOperationStorage { - void **HPDataSRCPtr; - unsigned int *hdatac; -}; /* */ struct HPConfListenStorage { unsigned int pluginID; @@ -102,22 +113,20 @@ struct HPM_interface { /* hooking */ bool force_return; /* data */ - struct hplugin **plugins; - unsigned int plugin_count; - struct hpm_symbol **symbols; - unsigned int symbol_count; + VECTOR_DECL(struct hplugin *) plugins; + VECTOR_DECL(struct hpm_symbol *) symbols; /* packet hooking points */ - struct HPluginPacket *packets[hpPHP_MAX]; - unsigned int packetsc[hpPHP_MAX]; + VECTOR_DECL(struct HPluginPacket) packets[hpPHP_MAX]; /* plugin file ptr caching */ - struct HPMFileNameCache *fnames; - unsigned int fnamec; + struct { + // This doesn't use a VECTOR because it needs to exist after the memory manager goes down. + int count; + struct HPMFileNameCache *data; + } filenames; /* config listen */ - struct HPConfListenStorage *confs[HPCT_MAX]; - unsigned int confsc[HPCT_MAX]; + VECTOR_DECL(struct HPConfListenStorage) config_listeners[HPCT_MAX]; /** Plugins requested through the command line */ - char **cmdline_plugins; - int cmdline_plugins_count; + VECTOR_DECL(char *) cmdline_load_plugins; /* funcs */ void (*init) (void); void (*final) (void); @@ -128,21 +137,24 @@ struct HPM_interface { bool (*iscompatible) (char* version); void (*event) (enum hp_event_types type); void *(*import_symbol) (char *name, unsigned int pID); - void (*share) (void *, char *); + void (*share) (void *value, const char *name); void (*config_read) (void); char *(*pid2name) (unsigned int pid); unsigned char (*parse_packets) (int fd, enum HPluginPacketHookingPoints point); void (*load_sub) (struct hplugin *plugin); bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID); - void (*grabHPData) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr); - /* for server-specific HPData e.g. map_session_data */ - bool (*grabHPDataSub) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr); /* 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, int version, char *name); void (*datacheck_init) (const struct s_HPMDataCheck *src, unsigned int length, int version); void (*datacheck_final) (void); + + void (*data_store_create) (struct hplugin_data_store **storeptr, enum HPluginDataTypes type); + void (*data_store_destroy) (struct hplugin_data_store **storeptr); + bool (*data_store_validate) (enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize); + /* for server-specific HPData e.g. map_session_data */ + bool (*data_store_validate_sub) (enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize); }; CMDLINEARG(loadplugin); diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h index 4fd16114b..923b6ccbf 100644 --- a/src/common/HPMDataCheck.h +++ b/src/common/HPMDataCheck.h @@ -144,16 +144,16 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { #else #define COMMON_HPMI_H #endif // COMMON_HPMI_H - #ifdef COMMON_MALLOC_H - { "malloc_interface", sizeof(struct malloc_interface), SERVER_TYPE_ALL }, - #else - #define COMMON_MALLOC_H - #endif // COMMON_MALLOC_H #ifdef COMMON_MAPINDEX_H { "mapindex_interface", sizeof(struct mapindex_interface), SERVER_TYPE_CHAR|SERVER_TYPE_MAP }, #else #define COMMON_MAPINDEX_H #endif // COMMON_MAPINDEX_H + #ifdef COMMON_MEMMGR_H + { "malloc_interface", sizeof(struct malloc_interface), SERVER_TYPE_ALL }, + #else + #define COMMON_MEMMGR_H + #endif // COMMON_MEMMGR_H #ifdef COMMON_MMO_H { "auction_data", sizeof(struct auction_data), SERVER_TYPE_ALL }, { "fame_list", sizeof(struct fame_list), SERVER_TYPE_ALL }, @@ -201,6 +201,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { #ifdef COMMON_SOCKET_H { "hSockOpt", sizeof(struct hSockOpt), SERVER_TYPE_ALL }, { "s_subnet", sizeof(struct s_subnet), SERVER_TYPE_ALL }, + { "s_subnet_vector", sizeof(struct s_subnet_vector), SERVER_TYPE_ALL }, { "socket_data", sizeof(struct socket_data), SERVER_TYPE_ALL }, { "socket_interface", sizeof(struct socket_interface), SERVER_TYPE_ALL }, #else diff --git a/src/common/HPMSymbols.inc.h b/src/common/HPMSymbols.inc.h index 3a4c5852c..4c3722b69 100644 --- a/src/common/HPMSymbols.inc.h +++ b/src/common/HPMSymbols.inc.h @@ -125,9 +125,9 @@ struct loginif_interface *loginif; #ifdef MAP_MAIL_H /* mail */ struct mail_interface *mail; #endif // MAP_MAIL_H -#ifdef COMMON_MALLOC_H /* iMalloc */ +#ifdef COMMON_MEMMGR_H /* iMalloc */ struct malloc_interface *iMalloc; -#endif // COMMON_MALLOC_H +#endif // COMMON_MEMMGR_H #ifdef MAP_MAP_H /* map */ struct map_interface *map; #endif // MAP_MAP_H @@ -348,9 +348,9 @@ if ((server_type&(SERVER_TYPE_CHAR)) && !HPM_SYMBOL("loginif", loginif)) return #ifdef MAP_MAIL_H /* mail */ if ((server_type&(SERVER_TYPE_MAP)) && !HPM_SYMBOL("mail", mail)) return "mail"; #endif // MAP_MAIL_H -#ifdef COMMON_MALLOC_H /* iMalloc */ +#ifdef COMMON_MEMMGR_H /* iMalloc */ if ((server_type&(SERVER_TYPE_ALL)) && !HPM_SYMBOL("iMalloc", iMalloc)) return "iMalloc"; -#endif // COMMON_MALLOC_H +#endif // COMMON_MEMMGR_H #ifdef MAP_MAP_H /* map */ if ((server_type&(SERVER_TYPE_MAP)) && !HPM_SYMBOL("map", map)) return "map"; #endif // MAP_MAP_H diff --git a/src/common/HPMi.h b/src/common/HPMi.h index e03f52e3b..9a61dd256 100644 --- a/src/common/HPMi.h +++ b/src/common/HPMi.h @@ -14,6 +14,7 @@ struct script_state; struct AtCommandInfo; struct socket_data; struct map_session_data; +struct hplugin_data_store; #define HPM_VERSION "1.1" #define HPM_ADDCONF_LENGTH 40 @@ -59,30 +60,34 @@ enum HPluginHookType { HOOK_TYPE_POST, }; +/** + * Data types for plugin custom data. + */ enum HPluginDataTypes { - HPDT_SESSION, - HPDT_MSD, - HPDT_NPCD, - HPDT_MAP, - HPDT_INSTANCE, - HPDT_GUILD, - HPDT_PARTY, - HPDT_MOBDB, - HPDT_MOBDATA, - HPDT_ITEMDATA, - HPDT_BGDATA, - HPDT_AUTOTRADE_VEND, + HPDT_UNKNOWN, ///< Unknown type (such as an uninitialized store). + HPDT_SESSION, ///< For struct socket_data. + HPDT_MSD, ///< For struct map_session_data. + HPDT_NPCD, ///< For struct npc_data. + HPDT_MAP, ///< For struct map_data. + HPDT_INSTANCE, ///< For struct instance_data. + HPDT_GUILD, ///< For struct guild. + HPDT_PARTY, ///< For struct party_data. + HPDT_MOBDB, ///< For struct mob_db. + HPDT_MOBDATA, ///< For struct mob_data. + HPDT_ITEMDATA, ///< For struct item_data. + HPDT_BGDATA, ///< For struct battleground_data. + HPDT_AUTOTRADE_VEND, ///< For struct autotrade_vending. }; /* used in macros and conf storage */ enum HPluginConfType { - HPCT_BATTLE, /* battle-conf (map-server) */ - HPCT_LOGIN, /* login-server.conf (login-server) */ - HPCT_CHAR, /* char-server.conf (char-server) */ - HPCT_CHAR_INTER, /* inter-server.conf (char-server) */ - HPCT_MAP_INTER, /* inter-server.conf (map-server) */ - HPCT_LOG, /* logs.conf (map-server) */ - HPCT_SCRIPT, /* script.conf (map-server) */ + HPCT_BATTLE, ///< battle-conf (map-server) + HPCT_LOGIN, ///< login-server.conf (login-server) + HPCT_CHAR, ///< char-server.conf (char-server) + HPCT_CHAR_INTER, ///< inter-server.conf (char-server) + HPCT_MAP_INTER, ///< inter-server.conf (map-server) + HPCT_LOG, ///< logs.conf (map-server) + HPCT_SCRIPT, ///< script.conf (map-server) HPCT_MAX, }; @@ -96,53 +101,53 @@ enum HPluginConfType { #define addArg(name, param,func,help) (HPMi->addArg(HPMi->pid,(name),(param),(cmdline_arg_ ## func),(help))) /* HPData handy redirects */ /* session[] */ -#define addToSession(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_SESSION,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromSession(ptr,index) (HPMi->getFromHPData(HPDT_SESSION,HPMi->pid,(ptr),(index))) -#define removeFromSession(ptr,index) (HPMi->removeFromHPData(HPDT_SESSION,HPMi->pid,(ptr),(index))) +#define addToSession(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_SESSION,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromSession(ptr,classid) (HPMi->getFromHPData(HPDT_SESSION,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromSession(ptr,classid) (HPMi->removeFromHPData(HPDT_SESSION,HPMi->pid,(ptr)->hdata,(classid))) /* map_session_data */ -#define addToMSD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MSD,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromMSD(ptr,index) (HPMi->getFromHPData(HPDT_MSD,HPMi->pid,(ptr),(index))) -#define removeFromMSD(ptr,index) (HPMi->removeFromHPData(HPDT_MSD,HPMi->pid,(ptr),(index))) +#define addToMSD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MSD,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromMSD(ptr,classid) (HPMi->getFromHPData(HPDT_MSD,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromMSD(ptr,classid) (HPMi->removeFromHPData(HPDT_MSD,HPMi->pid,(ptr)->hdata,(classid))) /* npc_data */ -#define addToNPCD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_NPCD,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromNPCD(ptr,index) (HPMi->getFromHPData(HPDT_NPCD,HPMi->pid,(ptr),(index))) -#define removeFromNPCD(ptr,index) (HPMi->removeFromHPData(HPDT_NPCD,HPMi->pid,(ptr),(index))) +#define addToNPCD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_NPCD,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromNPCD(ptr,classid) (HPMi->getFromHPData(HPDT_NPCD,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromNPCD(ptr,classid) (HPMi->removeFromHPData(HPDT_NPCD,HPMi->pid,(ptr)->hdata,(classid))) /* map_data */ -#define addToMAPD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MAP,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromMAPD(ptr,index) (HPMi->getFromHPData(HPDT_MAP,HPMi->pid,(ptr),(index))) -#define removeFromMAPD(ptr,index) (HPMi->removeFromHPData(HPDT_MAP,HPMi->pid,(ptr),(index))) +#define addToMAPD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MAP,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromMAPD(ptr,classid) (HPMi->getFromHPData(HPDT_MAP,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromMAPD(ptr,classid) (HPMi->removeFromHPData(HPDT_MAP,HPMi->pid,(ptr)->hdata,(classid))) /* party_data */ -#define addToPAD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_PARTY,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromPAD(ptr,index) (HPMi->getFromHPData(HPDT_PARTY,HPMi->pid,(ptr),(index))) -#define removeFromPAD(ptr,index) (HPMi->removeFromHPData(HPDT_PARTY,HPMi->pid,(ptr),(index))) +#define addToPAD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_PARTY,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromPAD(ptr,classid) (HPMi->getFromHPData(HPDT_PARTY,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromPAD(ptr,classid) (HPMi->removeFromHPData(HPDT_PARTY,HPMi->pid,(ptr)->hdata,(classid))) /* guild */ -#define addToGLD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_GUILD,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromGLD(ptr,index) (HPMi->getFromHPData(HPDT_GUILD,HPMi->pid,(ptr),(index))) -#define removeFromGLD(ptr,index) (HPMi->removeFromHPData(HPDT_GUILD,HPMi->pid,(ptr),(index))) +#define addToGLD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_GUILD,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromGLD(ptr,classid) (HPMi->getFromHPData(HPDT_GUILD,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromGLD(ptr,classid) (HPMi->removeFromHPData(HPDT_GUILD,HPMi->pid,(ptr)->hdata,(classid))) /* instance_data */ -#define addToINSTD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_INSTANCE,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromINSTD(ptr,index) (HPMi->getFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr),(index))) -#define removeFromINSTD(ptr,index) (HPMi->removeFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr),(index))) +#define addToINSTD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_INSTANCE,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromINSTD(ptr,classid) (HPMi->getFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromINSTD(ptr,classid) (HPMi->removeFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr)->hdata,(classid))) /* mob_db */ -#define addToMOBDB(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MOBDB,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromMOBDB(ptr,index) (HPMi->getFromHPData(HPDT_MOBDB,HPMi->pid,(ptr),(index))) -#define removeFromMOBDB(ptr,index) (HPMi->removeFromHPData(HPDT_MOBDB,HPMi->pid,(ptr),(index))) +#define addToMOBDB(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MOBDB,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromMOBDB(ptr,classid) (HPMi->getFromHPData(HPDT_MOBDB,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromMOBDB(ptr,classid) (HPMi->removeFromHPData(HPDT_MOBDB,HPMi->pid,(ptr)->hdata,(classid))) /* mob_data */ -#define addToMOBDATA(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MOBDATA,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromMOBDATA(ptr,index) (HPMi->getFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr),(index))) -#define removeFromMOBDATA(ptr,index) (HPMi->removeFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr),(index))) +#define addToMOBDATA(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MOBDATA,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromMOBDATA(ptr,classid) (HPMi->getFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromMOBDATA(ptr,classid) (HPMi->removeFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr)->hdata,(classid))) /* item_data */ -#define addToITEMDATA(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_ITEMDATA,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromITEMDATA(ptr,index) (HPMi->getFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr),(index))) -#define removeFromITEMDATA(ptr,index) (HPMi->removeFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr),(index))) +#define addToITEMDATA(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_ITEMDATA,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromITEMDATA(ptr,classid) (HPMi->getFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromITEMDATA(ptr,classid) (HPMi->removeFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr)->hdata,(classid))) /* battleground_data */ -#define addToBGDATA(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_BGDATA,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromBGDATA(ptr,index) (HPMi->getFromHPData(HPDT_BGDATA,HPMi->pid,(ptr),(index))) -#define removeFromBGDATA(ptr,index) (HPMi->removeFromHPData(HPDT_BGDATA,HPMi->pid,(ptr),(index))) +#define addToBGDATA(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_BGDATA,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromBGDATA(ptr,classid) (HPMi->getFromHPData(HPDT_BGDATA,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromBGDATA(ptr,classid) (HPMi->removeFromHPData(HPDT_BGDATA,HPMi->pid,(ptr)->hdata,(classid))) /* autotrade_vending */ -#define addToATVEND(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr),(data),(index),(autofree))) -#define getFromATVEND(ptr,index) (HPMi->getFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr),(index))) -#define removeFromATVEND(ptr,index) (HPMi->removeFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr),(index))) +#define addToATVEND(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree))) +#define getFromATVEND(ptr,classid) (HPMi->getFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr)->hdata,(classid))) +#define removeFromATVEND(ptr,classid) (HPMi->removeFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr)->hdata,(classid))) /// HPMi->addCommand #define addAtcommand(cname,funcname) do { \ @@ -205,9 +210,9 @@ struct HPMi_interface { bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st), bool isDeprecated); void (*addCPCommand) (char *name, CParseFunc func); /* HPM Custom Data */ - void (*addToHPData) (enum HPluginDataTypes type, unsigned int pluginID, void *ptr, void *data, unsigned int index, bool autofree); - void *(*getFromHPData) (enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index); - void (*removeFromHPData) (enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index); + void (*addToHPData) (enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store **storeptr, void *data, uint32 classid, bool autofree); + void *(*getFromHPData) (enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid); + void (*removeFromHPData) (enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid); /* packet */ bool (*addPacket) (unsigned short cmd, unsigned short length, void (*receive)(int fd), unsigned int point, unsigned int pluginID); /* Hooking */ diff --git a/src/common/Makefile.in b/src/common/Makefile.in index 208d3b111..88e991651 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -27,12 +27,12 @@ COMMON_SHARED_C = conf.c db.c des.c ers.c grfio.c HPM.c mapindex.c md5calc.c \ COMMON_C = $(COMMON_SHARED_C) COMMON_SHARED_OBJ = $(patsubst %.c,%.o,$(COMMON_SHARED_C)) COMMON_OBJ = $(addprefix obj_all/, $(COMMON_SHARED_OBJ) \ - console.o core.o malloc.o socket.o) + console.o core.o memmgr.o socket.o) COMMON_MINI_OBJ = $(addprefix obj_all/, $(COMMON_SHARED_OBJ) \ - miniconsole.o minicore.o minimalloc.o minisocket.o) -COMMON_C += console.c core.c malloc.c socket.c + miniconsole.o minicore.o minimemmgr.o minisocket.o) +COMMON_C += console.c core.c memmgr.c socket.c COMMON_H = atomic.h cbasetypes.h conf.h console.h core.h db.h des.h ers.h \ - grfio.h hercules.h HPM.h HPMi.h malloc.h mapindex.h md5calc.h \ + grfio.h hercules.h HPM.h HPMi.h memmgr.h mapindex.h md5calc.h \ mmo.h mutex.h nullpo.h random.h showmsg.h socket.h spinlock.h \ sql.h strlib.h sysinfo.h thread.h timer.h utils.h winapi.h diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index 575428f96..64f21f7e0 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -391,7 +391,7 @@ typedef char bool; ////////////////////////////////////////////////////////////////////////// // length of a static array -#define ARRAYLENGTH(A) ( sizeof(A)/sizeof((A)[0]) ) +#define ARRAYLENGTH(A) ( (int)(sizeof(A)/sizeof((A)[0])) ) ////////////////////////////////////////////////////////////////////////// // Make sure va_copy exists diff --git a/src/common/conf.h b/src/common/conf.h index ac97a5427..0ef86adea 100644 --- a/src/common/conf.h +++ b/src/common/conf.h @@ -16,8 +16,8 @@ struct libconfig_interface { int (*read) (config_t *config, FILE *stream); void (*write) (const config_t *config, FILE *stream); /* */ - void (*set_auto_convert) (config_t *config, int flag); - int (*get_auto_convert) (const config_t *config); + void (*set_auto_convert) (config_t *config, int flag); // TODO: Replace with config_set_options + int (*get_auto_convert) (const config_t *config); // TODO: Replace with config_get_options /* */ int (*read_string) (config_t *config, const char *str); int (*read_file_src) (config_t *config, const char *filename); diff --git a/src/common/console.c b/src/common/console.c index eb55d7462..477141b48 100644 --- a/src/common/console.c +++ b/src/common/console.c @@ -9,13 +9,14 @@ #include "common/cbasetypes.h" #include "common/core.h" +#include "common/nullpo.h" #include "common/showmsg.h" #include "common/sysinfo.h" #ifndef MINICORE # include "common/atomic.h" # include "common/ers.h" -# include "common/malloc.h" +# include "common/memmgr.h" # include "common/mutex.h" # include "common/spinlock.h" # include "common/sql.h" @@ -124,14 +125,16 @@ CPCMD_C(mem_report,server) { /** * Displays command list **/ -CPCMD(help) { - unsigned int i = 0; - for ( i = 0; i < console->input->cmd_list_count; i++ ) { - if( console->input->cmd_list[i]->next_count ) { - ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",console->input->cmd_list[i]->cmd); - console->input->parse_list_subs(console->input->cmd_list[i],2); +CPCMD(help) +{ + int i; + for (i = 0; i < VECTOR_LENGTH(console->input->command_list); i++) { + struct CParseEntry *entry = VECTOR_INDEX(console->input->command_list, i); + if (entry->type == CPET_CATEGORY) { + ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n", entry->cmd); + console->input->parse_list_subs(entry, 2); } else { - ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n",console->input->cmd_list[i]->cmd); + ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n", entry->cmd); } } } @@ -171,7 +174,7 @@ void console_load_defaults(void) * 'sql' is the main category * CP_DEF_C(category) **/ -#define CP_DEF_C(x) { #x , NULL , NULL, NULL } +#define CP_DEF_C(x) { #x , CPET_CATEGORY, NULL , NULL, NULL } /** * Defines a sub-category. * @@ -181,20 +184,21 @@ void console_load_defaults(void) * 'update' is a sub-category * CP_DEF_C2(command, category) **/ -#define CP_DEF_C2(x,y) { #x , NULL , #y, NULL } +#define CP_DEF_C2(x,y) { #x , CPET_CATEGORY, NULL , #y, NULL } /** * Defines a command that is inside a category or sub-category * CP_DEF_S(command, category/sub-category) **/ -#define CP_DEF_S(x,y) { #x, CPCMD_C_A(x,y), #y, NULL } +#define CP_DEF_S(x,y) { #x, CPET_FUNCTION, CPCMD_C_A(x,y), #y, NULL } /** * Defines a command that is _not_ inside any category * CP_DEF_S(command) **/ -#define CP_DEF(x) { #x , CPCMD_A(x), NULL, NULL } +#define CP_DEF(x) { #x , CPET_FUNCTION, CPCMD_A(x), NULL, NULL } struct { char *name; + int type; CParseFunc func; char *connect; struct CParseEntry *self; @@ -215,43 +219,49 @@ void console_load_defaults(void) CP_DEF_C2(update,sql), CP_DEF_S(skip,update), }; - unsigned int i, len = ARRAYLENGTH(default_list); + int len = ARRAYLENGTH(default_list); struct CParseEntry *cmd; + int i; - RECREATE(console->input->cmds,struct CParseEntry *, len); + VECTOR_ENSURE(console->input->commands, len, 1); for(i = 0; i < len; i++) { CREATE(cmd, struct CParseEntry, 1); safestrncpy(cmd->cmd, default_list[i].name, CP_CMD_LENGTH); - if( default_list[i].func ) - cmd->u.func = default_list[i].func; - else - cmd->u.next = NULL; + cmd->type = default_list[i].type; - cmd->next_count = 0; + switch (cmd->type) { + case CPET_FUNCTION: + cmd->u.func = default_list[i].func; + break; + case CPET_CATEGORY: + VECTOR_INIT(cmd->u.children); + break; + case CPET_UNKNOWN: + break; + } - console->input->cmd_count++; - console->input->cmds[i] = cmd; + VECTOR_PUSH(console->input->commands, cmd); default_list[i].self = cmd; - if( !default_list[i].connect ) { - RECREATE(console->input->cmd_list,struct CParseEntry *, ++console->input->cmd_list_count); - console->input->cmd_list[console->input->cmd_list_count - 1] = cmd; + if (!default_list[i].connect) { + VECTOR_ENSURE(console->input->command_list, 1, 1); + VECTOR_PUSH(console->input->command_list, cmd); } } - for(i = 0; i < len; i++) { - unsigned int k; - if( !default_list[i].connect ) + for (i = 0; i < len; i++) { + int k; + if (!default_list[i].connect) continue; - for(k = 0; k < console->input->cmd_count; k++) { - if( strcmpi(default_list[i].connect,console->input->cmds[k]->cmd) == 0 ) { - cmd = default_list[i].self; - RECREATE(console->input->cmds[k]->u.next, struct CParseEntry *, ++console->input->cmds[k]->next_count); - console->input->cmds[k]->u.next[console->input->cmds[k]->next_count - 1] = cmd; - break; - } + ARR_FIND(0, VECTOR_LENGTH(console->input->commands), k, strcmpi(default_list[i].connect, VECTOR_INDEX(console->input->commands, k)->cmd) == 0); + if (k != VECTOR_LENGTH(console->input->commands)) { + struct CParseEntry *parent = VECTOR_INDEX(console->input->commands, k); + Assert_retb(parent->type == CPET_CATEGORY); + cmd = default_list[i].self; + VECTOR_ENSURE(parent->u.children, 1, 1); + VECTOR_PUSH(parent->u.children, cmd); } } #undef CP_DEF_C @@ -260,8 +270,15 @@ void console_load_defaults(void) #undef CP_DEF } -void console_parse_create(char *name, CParseFunc func) { - unsigned int i; +/** + * Creates a new console command entry. + * + * @param name The command name. + * @param func The command callback. + */ +void console_parse_create(char *name, CParseFunc func) +{ + int i; char *tok; char sublist[CP_CMD_LENGTH * 5]; struct CParseEntry *cmd; @@ -269,123 +286,135 @@ void console_parse_create(char *name, CParseFunc func) { safestrncpy(sublist, name, CP_CMD_LENGTH * 5); tok = strtok(sublist,":"); - for ( i = 0; i < console->input->cmd_list_count; i++ ) { - if( strcmpi(tok,console->input->cmd_list[i]->cmd) == 0 ) - break; - } + ARR_FIND(0, VECTOR_LENGTH(console->input->command_list), i, strcmpi(tok, VECTOR_INDEX(console->input->command_list, i)->cmd) == 0); - if( i == console->input->cmd_list_count ) { - RECREATE(console->input->cmds,struct CParseEntry *, ++console->input->cmd_count); + if (i == VECTOR_LENGTH(console->input->command_list)) { CREATE(cmd, struct CParseEntry, 1); safestrncpy(cmd->cmd, tok, CP_CMD_LENGTH); - cmd->next_count = 0; - console->input->cmds[console->input->cmd_count - 1] = cmd; - RECREATE(console->input->cmd_list,struct CParseEntry *, ++console->input->cmd_list_count); - console->input->cmd_list[console->input->cmd_list_count - 1] = cmd; - i = console->input->cmd_list_count - 1; + cmd->type = CPET_UNKNOWN; + VECTOR_ENSURE(console->input->commands, 1, 1); + VECTOR_PUSH(console->input->commands, cmd); + VECTOR_ENSURE(console->input->command_list, 1, 1); + VECTOR_PUSH(console->input->command_list, cmd); } - cmd = console->input->cmd_list[i]; - while( ( tok = strtok(NULL, ":") ) != NULL ) { - for(i = 0; i < cmd->next_count; i++) { - if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 ) - break; + cmd = VECTOR_INDEX(console->input->command_list, i); + while ((tok = strtok(NULL, ":")) != NULL) { + if (cmd->type == CPET_UNKNOWN) { + cmd->type = CPET_CATEGORY; + VECTOR_INIT(cmd->u.children); } - - if ( i == cmd->next_count ) { - RECREATE(console->input->cmds,struct CParseEntry *, ++console->input->cmd_count); - CREATE(console->input->cmds[console->input->cmd_count-1], struct CParseEntry, 1); - safestrncpy(console->input->cmds[console->input->cmd_count-1]->cmd, tok, CP_CMD_LENGTH); - console->input->cmds[console->input->cmd_count-1]->next_count = 0; - RECREATE(cmd->u.next, struct CParseEntry *, ++cmd->next_count); - cmd->u.next[cmd->next_count - 1] = console->input->cmds[console->input->cmd_count-1]; - cmd = console->input->cmds[console->input->cmd_count-1]; + Assert_retv(cmd->type == CPET_CATEGORY); + + ARR_FIND(0, VECTOR_LENGTH(cmd->u.children), i, strcmpi(VECTOR_INDEX(cmd->u.children, i)->cmd,tok) == 0); + if (i == VECTOR_LENGTH(cmd->u.children)) { + struct CParseEntry *entry; + CREATE(entry, struct CParseEntry, 1); + safestrncpy(entry->cmd, tok, CP_CMD_LENGTH); + entry->type = CPET_UNKNOWN; + VECTOR_ENSURE(console->input->commands, 1, 1); + VECTOR_PUSH(console->input->commands, entry); + VECTOR_ENSURE(cmd->u.children, 1, 1); + VECTOR_PUSH(cmd->u.children, entry); + cmd = entry; continue; } + cmd = VECTOR_INDEX(cmd->u.children, i); } + Assert_retv(cmd->type != CPET_CATEGORY); + cmd->type = CPET_FUNCTION; cmd->u.func = func; } -void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth) { - unsigned int i; + +/** + * Shows the help message for a console command category. + * + * @param cmd The command entry. + * @param depth The current tree depth (for display purposes). + */ +void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth) +{ + int i; char msg[CP_CMD_LENGTH * 2]; - for( i = 0; i < cmd->next_count; i++ ) { - if( cmd->u.next[i]->next_count ) { - memset(msg, '-', depth); - snprintf(msg + depth,( CP_CMD_LENGTH * 2 ) - depth, " '"CL_WHITE"%s"CL_RESET"'",cmd->u.next[i]->cmd); - ShowInfo("%s subs\n",msg); - console->input->parse_list_subs(cmd->u.next[i],depth + 1); - } else { - memset(msg, '-', depth); - snprintf(msg + depth,(CP_CMD_LENGTH * 2) - depth, " %s",cmd->u.next[i]->cmd); + Assert_retv(cmd->type == CPET_CATEGORY); + for (i = 0; i < VECTOR_LENGTH(cmd->u.children); i++) { + struct CParseEntry *child = VECTOR_INDEX(cmd->u.children, i); + memset(msg, '-', depth); + snprintf(msg + depth, (CP_CMD_LENGTH * 2) - depth, " '"CL_WHITE"%s"CL_RESET"'", child->cmd); + if (child->type == CPET_FUNCTION) { ShowInfo("%s\n",msg); + } else { + ShowInfo("%s subs\n",msg); + console->input->parse_list_subs(child,depth + 1); } } } -void console_parse_sub(char *line) { + +/** + * Parses a console command. + * + * @param line The input line. + */ +void console_parse_sub(char *line) +{ struct CParseEntry *cmd; char bline[200]; char *tok; char sublist[CP_CMD_LENGTH * 5]; - unsigned int i, len = 0; + int i; memcpy(bline, line, 200); tok = strtok(line, " "); - for ( i = 0; i < console->input->cmd_list_count; i++ ) { - if( strcmpi(tok,console->input->cmd_list[i]->cmd) == 0 ) - break; + ARR_FIND(0, VECTOR_LENGTH(console->input->command_list), i, strcmpi(tok, VECTOR_INDEX(console->input->command_list, i)->cmd) == 0); + if (i == VECTOR_LENGTH(console->input->command_list)) { + ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known command, type '"CL_WHITE"help"CL_RESET"' to list all commands\n",line); + return; } - if( i == console->input->cmd_list_count ) { - ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known command, type '"CL_WHITE"help"CL_RESET"' to list all commands\n",line); + cmd = VECTOR_INDEX(console->input->command_list, i); + + snprintf(sublist, sizeof(sublist), "%s", cmd->cmd); + + if (cmd->type == CPET_FUNCTION) { + tok = strtok(NULL, ""); + cmd->u.func(tok); return; } - cmd = console->input->cmd_list[i]; + while ((tok = strtok(NULL, " ")) != NULL) { + struct CParseEntry *entry = NULL; - len += snprintf(sublist,CP_CMD_LENGTH * 5,"%s", cmd->cmd) + 1; + Assert_retv(cmd->type == CPET_CATEGORY); - if( cmd->next_count == 0 && console->input->cmd_list[i]->u.func ) { - char *r = NULL; - if( (tok = strtok(NULL, " ")) ) { - r = bline; - r += len + 1; - } - cmd->u.func(r); - } else { - while( ( tok = strtok(NULL, " ") ) != NULL ) { - for( i = 0; i < cmd->next_count; i++ ) { - if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 ) - break; - } - if( i == cmd->next_count ) { - if( strcmpi("help",tok) == 0 ) { - if( cmd->next_count ) { - ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist); - console->input->parse_list_subs(cmd,2); - } else { - ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist); - } - return; + ARR_FIND(0, VECTOR_LENGTH(cmd->u.children), i, strcmpi(VECTOR_INDEX(cmd->u.children, i)->cmd, tok) == 0); + if (i == VECTOR_LENGTH(cmd->u.children)) { + if (strcmpi("help", tok) == 0) { + if (VECTOR_LENGTH(cmd->u.children)) { + ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist); + console->input->parse_list_subs(cmd,2); + } else { + ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist); } - ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known subcommand of '"CL_WHITE"%s"CL_RESET"'\n",tok,cmd->cmd); - ShowError("type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist); return; } - if( cmd->u.next[i]->next_count == 0 && cmd->u.next[i]->u.func ) { - char *r = NULL; - if( (tok = strtok(NULL, " ")) ) { - r = bline; - r += len + strlen(cmd->u.next[i]->cmd) + 1; - } - cmd->u.next[i]->u.func(r); - return; - } else - cmd = cmd->u.next[i]; - len += snprintf(sublist + len,(CP_CMD_LENGTH * 5) - len,":%s", cmd->cmd); + ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known subcommand of '"CL_WHITE"%s"CL_RESET"'\n",tok,cmd->cmd); + ShowError("type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist); + return; + } + entry = VECTOR_INDEX(cmd->u.children, i); + if (entry->type == CPET_FUNCTION) { + tok = strtok(NULL, ""); + entry->u.func(tok); + return; } - ShowError("Is only a category, type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist); + + cmd = entry; + + if (strlen(sublist) < sizeof(sublist)-1) + snprintf(sublist+strlen(sublist), sizeof(sublist), " %s", cmd->cmd); } + ShowError("Is only a category, type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist); } void console_parse(char* line) { int c, i = 0, len = MAX_CONSOLE_INPUT - 1;/* we leave room for the \0 :P */ @@ -472,27 +501,33 @@ void console_setSQL(Sql *SQL_handle) { } #endif /* CONSOLE_INPUT */ -void console_init (void) { +void console_init(void) +{ #ifdef CONSOLE_INPUT - console->input->cmd_count = console->input->cmd_list_count = 0; + VECTOR_INIT(console->input->command_list); + VECTOR_INIT(console->input->commands); console->input->load_defaults(); console->input->parse_init(); #endif } -void console_final(void) { + +void console_final(void) +{ #ifdef CONSOLE_INPUT - unsigned int i; console->input->parse_final(); - for( i = 0; i < console->input->cmd_count; i++ ) { - if( console->input->cmds[i]->next_count ) - aFree(console->input->cmds[i]->u.next); - aFree(console->input->cmds[i]); + while (VECTOR_LENGTH(console->input->commands)) { + struct CParseEntry *entry = VECTOR_POP(console->input->commands); + if (entry->type == CPET_CATEGORY) + VECTOR_CLEAR(entry->u.children); + aFree(entry); } - aFree(console->input->cmds); - aFree(console->input->cmd_list); + VECTOR_CLEAR(console->input->commands); + VECTOR_CLEAR(console->input->command_list); #endif } -void console_defaults(void) { + +void console_defaults(void) +{ console = &console_s; console->init = console_init; console->final = console_final; diff --git a/src/common/console.h b/src/common/console.h index ffb4a165b..ef6db0cb4 100644 --- a/src/common/console.h +++ b/src/common/console.h @@ -5,6 +5,7 @@ #define COMMON_CONSOLE_H #include "common/hercules.h" +#include "common/db.h" #include "common/mutex.h" #include "common/spinlock.h" #include "common/sql.h" @@ -33,13 +34,20 @@ typedef void (*CParseFunc)(char *line); #define CPCMD_C_A(x,y) console_parse_ ##y ##x #define CP_CMD_LENGTH 20 + +enum CONSOLE_PARSE_ENTRY_TYPE { + CPET_UNKNOWN, + CPET_FUNCTION, + CPET_CATEGORY, +}; + struct CParseEntry { char cmd[CP_CMD_LENGTH]; + int type; ///< Entry type (@see enum CONSOLE_PARSE_ENTRY_TYPE) union { CParseFunc func; - struct CParseEntry **next; + VECTOR_DECL(struct CParseEntry *) children; } u; - unsigned short next_count; }; #ifdef CONSOLE_INPUT @@ -51,10 +59,8 @@ struct console_input_interface { ramutex *ptmutex;/* parse thread mutex */ racond *ptcond;/* parse thread cond */ /* */ - struct CParseEntry **cmd_list; - struct CParseEntry **cmds; - unsigned int cmd_count; - unsigned int cmd_list_count; + VECTOR_DECL(struct CParseEntry *) command_list; + VECTOR_DECL(struct CParseEntry *) commands; /* */ Sql *SQL; /* */ diff --git a/src/common/core.c b/src/common/core.c index dcc96fa41..6f21f526b 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -10,7 +10,7 @@ #include "common/cbasetypes.h" #include "common/console.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/random.h" #include "common/showmsg.h" @@ -207,8 +207,9 @@ const char *cmdline_arg_source(struct CmdlineArgData *arg) { bool cmdline_arg_add(unsigned int pluginID, const char *name, char shortname, CmdlineExecFunc func, const char *help, unsigned int options) { struct CmdlineArgData *data = NULL; - RECREATE(cmdline->args_data, struct CmdlineArgData, ++cmdline->args_data_count); - data = &cmdline->args_data[cmdline->args_data_count-1]; + VECTOR_ENSURE(cmdline->args_data, 1, 1); + VECTOR_PUSHZEROED(cmdline->args_data); + data = &VECTOR_LAST(cmdline->args_data); data->pluginID = pluginID; data->name = aStrdup(name); data->shortname = shortname; @@ -228,8 +229,8 @@ static CMDLINEARG(help) ShowInfo("\n"); ShowInfo("Options:\n"); - for (i = 0; i < cmdline->args_data_count; i++) { - struct CmdlineArgData *data = &cmdline->args_data[i]; + for (i = 0; i < VECTOR_LENGTH(cmdline->args_data); i++) { + struct CmdlineArgData *data = &VECTOR_INDEX(cmdline->args_data, i); char altname[16], paramnames[256]; if (data->shortname) { snprintf(altname, sizeof(altname), " [-%c]", data->shortname); @@ -288,8 +289,9 @@ bool cmdline_arg_next_value(const char *name, int current_arg, int argc) */ int cmdline_exec(int argc, char **argv, unsigned int options) { - int count = 0, i, j; + int count = 0, i; for (i = 1; i < argc; i++) { + int j; struct CmdlineArgData *data = NULL; const char *arg = argv[i]; if (arg[0] != '-') { // All arguments must begin with '-' @@ -297,17 +299,17 @@ int cmdline_exec(int argc, char **argv, unsigned int options) exit(EXIT_FAILURE); } if (arg[1] != '-' && strlen(arg) == 2) { - ARR_FIND(0, cmdline->args_data_count, j, cmdline->args_data[j].shortname == arg[1]); + ARR_FIND(0, VECTOR_LENGTH(cmdline->args_data), j, VECTOR_INDEX(cmdline->args_data, j).shortname == arg[1]); } else { - ARR_FIND(0, cmdline->args_data_count, j, strcmpi(cmdline->args_data[j].name, arg) == 0); + ARR_FIND(0, VECTOR_LENGTH(cmdline->args_data), j, strcmpi(VECTOR_INDEX(cmdline->args_data, j).name, arg) == 0); } - if (j == cmdline->args_data_count) { + if (j == VECTOR_LENGTH(cmdline->args_data)) { if (options&(CMDLINE_OPT_SILENT|CMDLINE_OPT_PREINIT)) continue; ShowError("Unknown option '%s'.\n", arg); exit(EXIT_FAILURE); } - data = &cmdline->args_data[j]; + data = &VECTOR_INDEX(cmdline->args_data, j); if (data->options&CMDLINE_OPT_PARAM) { if (!cmdline->arg_next_value(arg, i, argc)) exit(EXIT_FAILURE); @@ -346,15 +348,15 @@ void cmdline_init(void) #endif // !MINICORE cmdline_args_init_local(); } + void cmdline_final(void) { - int i; - for (i = 0; i < cmdline->args_data_count; i++) { - aFree(cmdline->args_data[i].name); - aFree(cmdline->args_data[i].help); + while (VECTOR_LENGTH(cmdline->args_data) > 0) { + struct CmdlineArgData *data = &VECTOR_POP(cmdline->args_data); + aFree(data->name); + aFree(data->help); } - if (cmdline->args_data) - aFree(cmdline->args_data); + VECTOR_CLEAR(cmdline->args_data); } struct cmdline_interface cmdline_s; @@ -364,8 +366,7 @@ void cmdline_defaults(void) { cmdline = &cmdline_s; - cmdline->args_data = NULL; - cmdline->args_data_count = 0; + VECTOR_INIT(cmdline->args_data); cmdline->init = cmdline_init; cmdline->final = cmdline_final; diff --git a/src/common/core.h b/src/common/core.h index c92bf4fa6..f8e748db4 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -6,6 +6,7 @@ #define COMMON_CORE_H #include "common/hercules.h" +#include "common/db.h" /* so that developers with --enable-debug can raise signals from any section of the code they'd like */ #ifdef DEBUG @@ -46,8 +47,7 @@ struct CmdlineArgData { }; struct cmdline_interface { - struct CmdlineArgData *args_data; - int args_data_count; + VECTOR_DECL(struct CmdlineArgData) args_data; void (*init) (void); void (*final) (void); diff --git a/src/common/db.c b/src/common/db.c index 4df5c08db..0600be2e8 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -73,7 +73,7 @@ #include "db.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/showmsg.h" #include "common/strlib.h" diff --git a/src/common/db.h b/src/common/db.h index 73d44a755..1df306038 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -935,608 +935,785 @@ void db_defaults(void); HPShared struct db_interface *DB; -/// Finds an entry in an array. -/// ex: ARR_FIND(0, size, i, list[i] == target); -/// -/// @param __start Starting index (ex: 0) -/// @param __end End index (ex: size of the array) -/// @param __var Index variable -/// @param __cmp Expression that returns true when the target entry is found -#define ARR_FIND(__start, __end, __var, __cmp) \ - do{ \ - for( (__var) = (__start); (__var) < (__end); ++(__var) ) \ - if( __cmp ) \ +/** + * Array Helper macros + */ + +/** + * Finds an entry in an array. + * + * @code + * ARR_FIND(0, size, i, list[i] == target); + * @endcode + * + * To differentiate between the found and not found cases, the caller code can + * compare _end and _var after this macro returns. + * + * @param _start Starting index (ex: 0). + * @param _end End index (ex: size of the array). + * @param _var Index variable. + * @param _cmp Search expression (should return true when the target entry is found). + */ +#define ARR_FIND(_start, _end, _var, _cmp) \ + do { \ + for ((_var) = (_start); (_var) < (_end); ++(_var)) \ + if (_cmp) \ break; \ - }while(0) - -/// Moves an entry of the array. -/// Use ARR_MOVERIGHT/ARR_MOVELEFT if __from and __to are direct numbers. -/// ex: ARR_MOVE(i, 0, list, int);// move index i to index 0 -/// -/// -/// @param __from Initial index of the entry -/// @param __to Target index of the entry -/// @param __arr Array -/// @param __type Type of entry -#define ARR_MOVE(__from, __to, __arr, __type) \ - do{ \ - if( (__from) != (__to) ) \ - { \ - __type __backup__; \ - memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \ - if( (__from) < (__to) ) \ - memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \ - else if( (__from) > (__to) ) \ - memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \ - memmove((__arr)+(__to), &__backup__, sizeof(__type)); \ + } while(false) + +/** + * Moves an entry of the array. + * + * @code + * ARR_MOVE(i, 0, list, int); // move index i to index 0 + * @endcode + * + * @remark + * Use ARR_MOVERIGHT/ARR_MOVELEFT if _from and _to are direct numbers. + * + * @param _from Initial index of the entry. + * @param _to Target index of the entry. + * @param _arr Array. + * @param _type Type of entry. + */ +#define ARR_MOVE(_from, _to, _arr, _type) \ + do { \ + if ((_from) != (_to)) { \ + _type _backup_; \ + memmove(&_backup_, (_arr)+(_from), sizeof(_type)); \ + if ((_from) < (_to)) \ + memmove((_arr)+(_from), (_arr)+(_from)+1, ((_to)-(_from))*sizeof(_type)); \ + else if ((_from) > (_to)) \ + memmove((_arr)+(_to)+1, (_arr)+(_to), ((_from)-(_to))*sizeof(_type)); \ + memmove((_arr)+(_to), &_backup_, sizeof(_type)); \ } \ - }while(0) - -/// Moves an entry of the array to the right. -/// ex: ARR_MOVERIGHT(1, 4, list, int);// move index 1 to index 4 -/// -/// @param __from Initial index of the entry -/// @param __to Target index of the entry -/// @param __arr Array -/// @param __type Type of entry -#define ARR_MOVERIGHT(__from, __to, __arr, __type) \ - do{ \ - __type __backup__; \ - memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \ - memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \ - memmove((__arr)+(__to), &__backup__, sizeof(__type)); \ - }while(0) - -/// Moves an entry of the array to the left. -/// ex: ARR_MOVELEFT(3, 0, list, int);// move index 3 to index 0 -/// -/// @param __from Initial index of the entry -/// @param __end Target index of the entry -/// @param __arr Array -/// @param __type Type of entry -#define ARR_MOVELEFT(__from, __to, __arr, __type) \ - do{ \ - __type __backup__; \ - memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \ - memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \ - memmove((__arr)+(__to), &__backup__, sizeof(__type)); \ - }while(0) - -///////////////////////////////////////////////////////////////////// -// Vector library based on defines. (dynamic array) -// uses aMalloc, aRealloc, aFree - -/// Declares an anonymous vector struct. -/// -/// @param __type Type of data -#define VECTOR_DECL(__type) \ + } while(false) + +/** + * Moves an entry of the array to the right. + * + * @code + * ARR_MOVERIGHT(1, 4, list, int); // move index 1 to index 4 + * @endcode + * + * @param _from Initial index of the entry. + * @param _to Target index of the entry. + * @param _arr Array. + * @param _type Type of entry. + */ +#define ARR_MOVERIGHT(_from, _to, _arr, _type) \ + do { \ + _type _backup_; \ + memmove(&_backup_, (_arr)+(_from), sizeof(_type)); \ + memmove((_arr)+(_from), (_arr)+(_from)+1, ((_to)-(_from))*sizeof(_type)); \ + memmove((_arr)+(_to), &_backup_, sizeof(_type)); \ + } while(false) + +/** + * Moves an entry of the array to the left. + * + * @code + * ARR_MOVELEFT(3, 0, list, int); // move index 3 to index 0 + * @endcode + * + * @param _from Initial index of the entry. + * @param _end Target index of the entry. + * @param _arr Array. + * @param _type Type of entry. + */ +#define ARR_MOVELEFT(_from, _to, _arr, _type) \ + do { \ + _type _backup_; \ + memmove(&_backup_, (_arr)+(_from), sizeof(_type)); \ + memmove((_arr)+(_to)+1, (_arr)+(_to), ((_from)-(_to))*sizeof(_type)); \ + memmove((_arr)+(_to), &_backup_, sizeof(_type)); \ + } while(false) + +/** + * Vector library based on defines (dynamic array). + * + * @remark + * This library uses aMalloc, aRealloc, aFree. + */ + +/** + * Declares an anonymous vector struct. + * + * @param _type Type of data to be contained. + */ +#define VECTOR_DECL(_type) \ struct { \ - size_t _max_; \ - size_t _len_; \ - __type* _data_; \ + int _max_; \ + int _len_; \ + _type *_data_; \ } -/// Declares a named vector struct. -/// -/// @param __name Structure name -/// @param __type Type of data -#define VECTOR_STRUCT_DECL(__name,__type) \ - struct __name { \ - size_t _max_; \ - size_t _len_; \ - __type* _data_; \ +/** + * Declares a named vector struct. + * + * @param _name Structure name. + * @param _type Type of data to be contained. + */ +#define VECTOR_STRUCT_DECL(_name, _type) \ + struct _name { \ + int _max_; \ + int _len_; \ + _type *_data_; \ } -/// Declares and initializes an anonymous vector variable. -/// -/// @param __type Type of data -/// @param __var Variable name -#define VECTOR_VAR(__type,__var) \ - VECTOR_DECL(__type) __var = {0,0,NULL} - -/// Declares and initializes a named vector variable. -/// -/// @param __name Structure name -/// @param __var Variable name -#define VECTOR_STRUCT_VAR(__name,__var) \ - struct __name __var = {0,0,NULL} - -/// Initializes a vector. -/// -/// @param __vec Vector -#define VECTOR_INIT(__vec) \ - memset(&(__vec), 0, sizeof(__vec)) - -/// Returns the internal array of values. -/// -/// @param __vec Vector -/// @return Array of values -#define VECTOR_DATA(__vec) \ - ( (__vec)._data_ ) - -/// Returns the length of the vector. -/// -/// @param __vec Vector -/// @return Length -#define VECTOR_LENGTH(__vec) \ - ( (__vec)._len_ ) - -/// Returns the capacity of the vector. -/// -/// @param __vec Vector -/// @return Capacity -#define VECTOR_CAPACITY(__vec) \ - ( (__vec)._max_ ) - -/// Returns the value at the target index. -/// Assumes the index exists. -/// -/// @param __vec Vector -/// @param __idx Index -/// @return Value -#define VECTOR_INDEX(__vec,__idx) \ - ( VECTOR_DATA(__vec)[__idx] ) - -/// Returns the first value of the vector. -/// Assumes the array is not empty. -/// -/// @param __vec Vector -/// @return First value -#define VECTOR_FIRST(__vec) \ - ( VECTOR_INDEX(__vec,0) ) - -/// Returns the last value of the vector. -/// Assumes the array is not empty. -/// -/// @param __vec Vector -/// @return Last value -#define VECTOR_LAST(__vec) \ - ( VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)-1) ) - -/// Resizes the vector. -/// Excess values are discarded, new positions are zeroed. -/// -/// @param __vec Vector -/// @param __n Size -#define VECTOR_RESIZE(__vec,__n) \ - do{ \ - if( (__n) > VECTOR_CAPACITY(__vec) ) \ - { /* increase size */ \ - if( VECTOR_CAPACITY(__vec) == 0 ) VECTOR_DATA(__vec) = aMalloc((__n)*sizeof(VECTOR_FIRST(__vec))); /* allocate new */ \ - else VECTOR_DATA(__vec) = aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec))); /* reallocate */ \ - memset(VECTOR_DATA(__vec)+VECTOR_LENGTH(__vec), 0, (VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec))*sizeof(VECTOR_FIRST(__vec))); /* clear new data */ \ - VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \ - } \ - else if( (__n) == 0 && VECTOR_CAPACITY(__vec) ) \ - { /* clear vector */ \ - aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* free data */ \ - VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \ - VECTOR_LENGTH(__vec) = 0; /* clear length */ \ - } \ - else if( (__n) < VECTOR_CAPACITY(__vec) ) \ - { /* reduce size */ \ - VECTOR_DATA(__vec) = aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec))); /* reallocate */ \ - VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \ - if( VECTOR_LENGTH(__vec) > (__n) ) VECTOR_LENGTH(__vec) = (__n); /* update length */ \ +/** + * Declares and initializes an anonymous vector variable. + * + * @param _type Type of data to be contained. + * @param _var Variable name. + */ +#define VECTOR_VAR(_type, _var) \ + VECTOR_DECL(_type) _var = {0, 0, NULL} + +/** + * Declares and initializes a named vector variable. + * + * @param _name Structure name. + * @param _var Variable name. + */ +#define VECTOR_STRUCT_VAR(_name, _var) \ + struct _name _var = {0, 0, NULL} + +/** + * Initializes a vector. + * + * @param _vec Vector. + */ +#define VECTOR_INIT(_vec) \ + memset(&(_vec), 0, sizeof(_vec)) + +/** + * Returns the internal array of values. + * + * @param _vec Vector. + * @return Internal array of values. + */ +#define VECTOR_DATA(_vec) \ + ( (_vec)._data_ ) + +/** + * Returns the length of the vector (number of elements in use). + * + * @param _vec Vector + * @return Length + */ +#define VECTOR_LENGTH(_vec) \ + ( (_vec)._len_ ) + +/** + * Returns the capacity of the vector (number of elements allocated). + * + * @param _vec Vector. + * @return Capacity. + */ +#define VECTOR_CAPACITY(_vec) \ + ( (_vec)._max_ ) + +/** + * Returns the value at the target index. + * + * Assumes the index exists. + * + * @param _vec Vector. + * @param _idx Index. + * @return Value. + */ +#define VECTOR_INDEX(_vec, _idx) \ + ( VECTOR_DATA(_vec)[_idx] ) + +/** + * Returns the first value of the vector. + * + * Assumes the array is not empty. + * + * @param _vec Vector. + * @return First value. + */ +#define VECTOR_FIRST(_vec) \ + ( VECTOR_INDEX(_vec, 0) ) + +/** + * Returns the last value of the vector. + * + * Assumes the array is not empty. + * + * @param _vec Vector. + * @return Last value. + */ +#define VECTOR_LAST(_vec) \ + ( VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)-1) ) + +/** + * Resizes the vector. + * + * Excess values are discarded, new positions are zeroed. + * + * @param _vec Vector. + * @param _n New size. + */ +#define VECTOR_RESIZE(_vec, _n) \ + do { \ + if ((_n) > VECTOR_CAPACITY(_vec)) { \ + /* increase size */ \ + if (VECTOR_CAPACITY(_vec) == 0) \ + VECTOR_DATA(_vec) = aMalloc((_n)*sizeof(VECTOR_FIRST(_vec))); /* allocate new */ \ + else \ + VECTOR_DATA(_vec) = aRealloc(VECTOR_DATA(_vec), (_n)*sizeof(VECTOR_FIRST(_vec))); /* reallocate */ \ + memset(VECTOR_DATA(_vec)+VECTOR_LENGTH(_vec), 0, (VECTOR_CAPACITY(_vec)-VECTOR_LENGTH(_vec))*sizeof(VECTOR_FIRST(_vec))); /* clear new data */ \ + VECTOR_CAPACITY(_vec) = (_n); /* update capacity */ \ + } else if ((_n) == 0 && VECTOR_CAPACITY(_vec) > 0) { \ + /* clear vector */ \ + aFree(VECTOR_DATA(_vec)); VECTOR_DATA(_vec) = NULL; /* free data */ \ + VECTOR_CAPACITY(_vec) = 0; /* clear capacity */ \ + VECTOR_LENGTH(_vec) = 0; /* clear length */ \ + } else if ((_n) < VECTOR_CAPACITY(_vec)) { \ + /* reduce size */ \ + VECTOR_DATA(_vec) = aRealloc(VECTOR_DATA(_vec), (_n)*sizeof(VECTOR_FIRST(_vec))); /* reallocate */ \ + VECTOR_CAPACITY(_vec) = (_n); /* update capacity */ \ + if ((_n) - VECTOR_LENGTH(_vec) > 0) \ + VECTOR_LENGTH(_vec) = (_n); /* update length */ \ } \ - }while(0) - -/// Ensures that the array has the target number of empty positions. -/// Increases the capacity in multiples of __step. -/// -/// @param __vec Vector -/// @param __n Empty positions -/// @param __step Increase -#define VECTOR_ENSURE(__vec,__n,__step) \ - do{ \ - size_t _empty_ = VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec); \ - if( (__n) > _empty_ ) { \ - while( (__n) > _empty_ ) _empty_ += (__step); \ - VECTOR_RESIZE(__vec,_empty_+VECTOR_LENGTH(__vec)); \ + } while(false) + +/** + * Ensures that the array has the target number of empty positions. + * + * Increases the capacity in multiples of _step. + * + * @param _vec Vector. + * @param _n Desired empty positions. + * @param _step Increase. + */ +#define VECTOR_ENSURE(_vec, _n, _step) \ + do { \ + int _empty_ = VECTOR_CAPACITY(_vec)-VECTOR_LENGTH(_vec); \ + if ((_n) > _empty_) { \ + while ((_n) > _empty_) \ + _empty_ += (_step); \ + VECTOR_RESIZE(_vec, _empty_+VECTOR_LENGTH(_vec)); \ } \ - }while(0) - -/// Inserts a zeroed value in the target index. -/// Assumes the index is valid and there is enough capacity. -/// -/// @param __vec Vector -/// @param __idx Index -#define VECTOR_INSERTZEROED(__vec,__idx) \ - do{ \ - if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \ - memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \ - memset(&VECTOR_INDEX(__vec,__idx), 0, sizeof(VECTOR_INDEX(__vec,__idx))); /* set zeroed value */ \ - ++VECTOR_LENGTH(__vec); /* increase length */ \ - }while(0) - -/// Inserts a value in the target index. (using the '=' operator) -/// Assumes the index is valid and there is enough capacity. -/// -/// @param __vec Vector -/// @param __idx Index -/// @param __val Value -#define VECTOR_INSERT(__vec,__idx,__val) \ - do{ \ - if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \ - memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \ - VECTOR_INDEX(__vec,__idx) = (__val); /* set value */ \ - ++VECTOR_LENGTH(__vec); /* increase length */ \ - }while(0) - -/// Inserts a value in the target index. (using memcpy) -/// Assumes the index is valid and there is enough capacity. -/// -/// @param __vec Vector -/// @param __idx Index -/// @param __val Value -#define VECTOR_INSERTCOPY(__vec,__idx,__val) \ - VECTOR_INSERTARRAY(__vec,__idx,&(__val),1) - -/// Inserts the values of the array in the target index. (using memcpy) -/// Assumes the index is valid and there is enough capacity. -/// -/// @param __vec Vector -/// @param __idx Index -/// @param __pval Array of values -/// @param __n Number of values -#define VECTOR_INSERTARRAY(__vec,__idx,__pval,__n) \ - do{ \ - if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \ - memmove(&VECTOR_INDEX(__vec,(__idx)+(__n)),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \ - memcpy(&VECTOR_INDEX(__vec,__idx), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \ - VECTOR_LENGTH(__vec) += (__n); /* increase length */ \ - }while(0) - -/// Inserts a zeroed value in the end of the vector. -/// Assumes there is enough capacity. -/// -/// @param __vec Vector -#define VECTOR_PUSHZEROED(__vec) \ - do{ \ - memset(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), 0, sizeof(VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)))); /* set zeroed value */ \ - ++VECTOR_LENGTH(__vec); /* increase length */ \ - }while(0) - -/// Inserts a value in the end of the vector. (using the '=' operator) -/// Assumes there is enough capacity. -/// -/// @param __vec Vector -/// @param __val Value -#define VECTOR_PUSH(__vec,__val) \ - do{ \ - VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)) = (__val); /* set value */ \ - ++VECTOR_LENGTH(__vec); /* increase length */ \ - }while(0) - -/// Inserts a value in the end of the vector. (using memcpy) -/// Assumes there is enough capacity. -/// -/// @param __vec Vector -/// @param __val Value -#define VECTOR_PUSHCOPY(__vec,__val) \ - VECTOR_PUSHARRAY(__vec,&(__val),1) - -/// Inserts the values of the array in the end of the vector. (using memcpy) -/// Assumes there is enough capacity. -/// -/// @param __vec Vector -/// @param __pval Array of values -/// @param __n Number of values -#define VECTOR_PUSHARRAY(__vec,__pval,__n) \ - do{ \ - memcpy(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \ - VECTOR_LENGTH(__vec) += (__n); /* increase length */ \ - }while(0) - -/// Removes and returns the last value of the vector. -/// Assumes the array is not empty. -/// -/// @param __vec Vector -/// @return Removed value -#define VECTOR_POP(__vec) \ - ( VECTOR_INDEX(__vec,--VECTOR_LENGTH(__vec)) ) - -/// Removes the last N values of the vector and returns the value of the last pop. -/// Assumes there are enough values. -/// -/// @param __vec Vector -/// @param __n Number of pops -/// @return Last removed value -#define VECTOR_POPN(__vec,__n) \ - ( VECTOR_INDEX(__vec,(VECTOR_LENGTH(__vec)-=(__n))) ) - -/// Removes the target index from the vector. -/// Assumes the index is valid and there are enough values. -/// -/// @param __vec Vector -/// @param __idx Index -#define VECTOR_ERASE(__vec,__idx) \ - VECTOR_ERASEN(__vec,__idx,1) - -/// Removes N values from the target index of the vector. -/// Assumes the index is valid and there are enough values. -/// -/// @param __vec Vector -/// @param __idx Index -/// @param __n Number of values -#define VECTOR_ERASEN(__vec,__idx,__n) \ - do{ \ - if( (__idx) < VECTOR_LENGTH(__vec)-(__n) ) /* move data */ \ - memmove(&VECTOR_INDEX(__vec,__idx),&VECTOR_INDEX(__vec,(__idx)+(__n)),(VECTOR_LENGTH(__vec)-((__idx)+(__n)))*sizeof(VECTOR_FIRST(__vec))); \ - VECTOR_LENGTH(__vec) -= (__n); /* decrease length */ \ - }while(0) - -/// Clears the vector, freeing allocated data. -/// -/// @param __vec Vector -#define VECTOR_CLEAR(__vec) \ - do{ \ - if( VECTOR_CAPACITY(__vec) ) \ - { \ - aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* clear allocated array */ \ - VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \ - VECTOR_LENGTH(__vec) = 0; /* clear length */ \ + } while(false) + +/** + * Inserts a zeroed value in the target index. + * + * Assumes the index is valid and there is enough capacity. + * + * @param _vec Vector. + * @param _idx Index. + */ +#define VECTOR_INSERTZEROED(_vec, _idx) \ + do { \ + if ((_idx) < VECTOR_LENGTH(_vec)) /* move data */ \ + memmove(&VECTOR_INDEX(_vec, (_idx)+1), &VECTOR_INDEX(_vec, _idx), (VECTOR_LENGTH(_vec)-(_idx))*sizeof(VECTOR_FIRST(_vec))); \ + memset(&VECTOR_INDEX(_vec, _idx), 0, sizeof(VECTOR_INDEX(_vec, _idx))); /* set zeroed value */ \ + ++VECTOR_LENGTH(_vec); /* increase length */ \ + } while(false) + +/** + * Inserts a value in the target index (using the '=' operator). + * + * Assumes the index is valid and there is enough capacity. + * + * @param _vec Vector. + * @param _idx Index. + * @param _val Value. + */ +#define VECTOR_INSERT(_vec, _idx, _val) \ + do { \ + if ((_idx) < VECTOR_LENGTH(_vec)) /* move data */ \ + memmove(&VECTOR_INDEX(_vec, (_idx)+1), &VECTOR_INDEX(_vec, _idx), (VECTOR_LENGTH(_vec)-(_idx))*sizeof(VECTOR_FIRST(_vec))); \ + VECTOR_INDEX(_vec, _idx) = (_val); /* set value */ \ + ++VECTOR_LENGTH(_vec); /* increase length */ \ + } while(false) + +/** + * Inserts a value in the target index (using memcpy). + * + * Assumes the index is valid and there is enough capacity. + * + * @param _vec Vector. + * @param _idx Index. + * @param _val Value. + */ +#define VECTOR_INSERTCOPY(_vec, _idx, _val) \ + VECTOR_INSERTARRAY(_vec, _idx, &(_val), 1) + +/** + * Inserts the values of the array in the target index (using memcpy). + * + * Assumes the index is valid and there is enough capacity. + * + * @param _vec Vector. + * @param _idx Index. + * @param _pval Array of values. + * @param _n Number of values. + */ +#define VECTOR_INSERTARRAY(_vec, _idx, _pval, _n) \ + do { \ + if ((_idx) < VECTOR_LENGTH(_vec)) /* move data */ \ + memmove(&VECTOR_INDEX(_vec, (_idx)+(_n)), &VECTOR_INDEX(_vec, _idx), (VECTOR_LENGTH(_vec)-(_idx))*sizeof(VECTOR_FIRST(_vec))); \ + memcpy(&VECTOR_INDEX(_vec, _idx), (_pval), (_n)*sizeof(VECTOR_FIRST(_vec))); /* set values */ \ + VECTOR_LENGTH(_vec) += (_n); /* increase length */ \ + } while(false) + +/** + * Inserts a zeroed value in the end of the vector. + * + * Assumes there is enough capacity. + * + * @param _vec Vector. + */ +#define VECTOR_PUSHZEROED(_vec) \ + do { \ + memset(&VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)), 0, sizeof(VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)))); /* set zeroed value */ \ + ++VECTOR_LENGTH(_vec); /* increase length */ \ + } while(false) + +/** + * Appends a value at the end of the vector (using the '=' operator). + * + * Assumes there is enough capacity. + * + * @param _vec Vector. + * @param _val Value. + */ +#define VECTOR_PUSH(_vec, _val) \ + do { \ + VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)) = (_val); /* set value */ \ + ++VECTOR_LENGTH(_vec); /* increase length */ \ + }while(false) + +/** + * Appends a value at the end of the vector (using memcpy). + * + * Assumes there is enough capacity. + * + * @param _vec Vector. + * @param _val Value. + */ +#define VECTOR_PUSHCOPY(_vec, _val) \ + VECTOR_PUSHARRAY(_vec, &(_val), 1) + +/** + * Appends the values of the array at the end of the vector (using memcpy). + * + * Assumes there is enough capacity. + * + * @param _vec Vector. + * @param _pval Array of values. + * @param _n Number of values. + */ +#define VECTOR_PUSHARRAY(_vec, _pval, _n) \ + do { \ + memcpy(&VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)), (_pval), (_n)*sizeof(VECTOR_FIRST(_vec))); /* set values */ \ + VECTOR_LENGTH(_vec) += (_n); /* increase length */ \ + } while(false) + +/** + * Removes and returns the last value of the vector. + * + * Assumes the array is not empty. + * + * @param _vec Vector. + * @return Removed value. + */ +#define VECTOR_POP(_vec) \ + ( VECTOR_INDEX(_vec, --VECTOR_LENGTH(_vec)) ) + +/** + * Removes the last N values of the vector and returns the value of the last pop. + * + * Assumes there are enough values. + * + * @param _vec Vector. + * @param _n Number of pops. + * @return Last removed value. + */ +#define VECTOR_POPN(_vec, _n) \ + ( VECTOR_INDEX(_vec, (VECTOR_LENGTH(_vec) -= (_n))) ) + +/** + * Removes the target index from the vector. + * + * Assumes the index is valid and there are enough values. + * + * @param _vec Vector. + * @param _idx Index. + */ +#define VECTOR_ERASE(_vec, _idx) \ + VECTOR_ERASEN(_vec, _idx, 1) + +/** + * Removes N values from the target index of the vector. + * + * Assumes the index is valid and there are enough values. + * + * @param _vec Vector. + * @param _idx Index. + * @param _n Number of values to remove. + */ +#define VECTOR_ERASEN(_vec, _idx, _n) \ + do { \ + if ((_idx) < VECTOR_LENGTH(_vec)-(_n) ) /* move data */ \ + memmove(&VECTOR_INDEX(_vec, _idx), &VECTOR_INDEX(_vec, (_idx)+(_n)), (VECTOR_LENGTH(_vec)-((_idx)+(_n)))*sizeof(VECTOR_FIRST(_vec))); \ + VECTOR_LENGTH(_vec) -= (_n); /* decrease length */ \ + } while(false) + +/** + * Clears the vector, freeing allocated data. + * + * @param _vec Vector. + */ +#define VECTOR_CLEAR(_vec) \ + do { \ + if (VECTOR_CAPACITY(_vec) > 0) { \ + aFree(VECTOR_DATA(_vec)); VECTOR_DATA(_vec) = NULL; /* clear allocated array */ \ + VECTOR_CAPACITY(_vec) = 0; /* clear capacity */ \ + VECTOR_LENGTH(_vec) = 0; /* clear length */ \ } \ - }while(0) - -///////////////////////////////////////////////////////////////////// -// Binary heap library based on defines. (uses the vector defines above) -// uses aMalloc, aRealloc, aFree -// WARNING: BHEAP implementation details affect behaviour of A* pathfinding - -/// Declares an anonymous binary heap struct. -/// -/// @param __type Type of data -#define BHEAP_DECL(__type) VECTOR_DECL(__type) - -/// Declares a named binary heap struct. -/// -/// @param __name Structure name -/// @param __type Type of data -#define BHEAP_STRUCT_DECL(__name,__type) VECTOR_STRUCT_DECL(__name,__type) - -/// Declares and initializes an anonymous binary heap variable. -/// -/// @param __type Type of data -/// @param __var Variable name -#define BHEAP_VAR(__type,__var) VECTOR_VAR(__type,__var) - -/// Declares and initializes a named binary heap variable. -/// -/// @param __name Structure name -/// @param __var Variable name -#define BHEAP_STRUCT_VAR(__name,__var) VECTOR_STRUCT_VAR(__name,__var) - -/// Initializes a heap. -/// -/// @param __heap Binary heap -#define BHEAP_INIT(__heap) VECTOR_INIT(__heap) - -/// Returns the internal array of values. -/// -/// @param __heap Binary heap -/// @return Array of values -#define BHEAP_DATA(__heap) VECTOR_DATA(__heap) - -/// Returns the length of the heap. -/// -/// @param __heap Binary heap -/// @return Length -#define BHEAP_LENGTH(__heap) VECTOR_LENGTH(__heap) - -/// Returns the capacity of the heap. -/// -/// @param __heap Binary heap -/// @return Capacity -#define BHEAP_CAPACITY(__heap) VECTOR_CAPACITY(__heap) - -/// Ensures that the heap has the target number of empty positions. -/// Increases the capacity in multiples of __step. -/// -/// @param __heap Binary heap -/// @param __n Empty positions -/// @param __step Increase -#define BHEAP_ENSURE(__heap,__n,__step) VECTOR_ENSURE(__heap,__n,__step) - -/// Returns the top value of the heap. -/// Assumes the heap is not empty. -/// -/// @param __heap Binary heap -/// @return Value at the top -#define BHEAP_PEEK(__heap) VECTOR_INDEX(__heap,0) - -/// Inserts a value in the heap. (using the '=' operator) -/// Assumes there is enough capacity. -/// -/// The comparator takes two values as arguments, returns: -/// - negative if the first value is on the top -/// - positive if the second value is on the top -/// - 0 if they are equal -/// -/// @param __heap Binary heap -/// @param __val Value -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_PUSH(__heap,__val,__topcmp,__swp) \ - do{ \ - size_t _i_ = VECTOR_LENGTH(__heap); \ - VECTOR_PUSH(__heap,__val); /* insert at end */ \ - while( _i_ ) \ - { /* restore heap property in parents */ \ - size_t _parent_ = (_i_-1)/2; \ - if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \ + } while(false) + +/** + * Binary heap library based on defines. + * + * Uses the VECTOR defines above. + * Uses aMalloc, aRealloc, aFree. + * + * @warning + * BHEAP implementation details affect behaviour of A* pathfinding. + */ + +/** + * Declares an anonymous binary heap struct. + * + * @param _type Type of data. + */ +#define BHEAP_DECL(_type) \ + VECTOR_DECL(_type) + +/** + * Declares a named binary heap struct. + * + * @param _name Structure name. + * @param _type Type of data. + */ +#define BHEAP_STRUCT_DECL(_name, _type) \ + VECTOR_STRUCT_DECL(_name, _type) + +/** + * Declares and initializes an anonymous binary heap variable. + * + * @param _type Type of data. + * @param _var Variable name. + */ +#define BHEAP_VAR(_type, _var) \ + VECTOR_VAR(_type, _var) + +/** + * Declares and initializes a named binary heap variable. + * + * @param _name Structure name. + * @param _var Variable name. + */ +#define BHEAP_STRUCT_VAR(_name, _var) \ + VECTOR_STRUCT_VAR(_name, _var) + +/** + * Initializes a heap. + * + * @param _heap Binary heap. + */ +#define BHEAP_INIT(_heap) \ + VECTOR_INIT(_heap) + +/** + * Returns the internal array of values. + * + * @param _heap Binary heap. + * @return Internal array of values. + */ +#define BHEAP_DATA(_heap) \ + VECTOR_DATA(_heap) + +/** + * Returns the length of the heap. + * + * @param _heap Binary heap. + * @return Length. + */ +#define BHEAP_LENGTH(_heap) \ + VECTOR_LENGTH(_heap) + +/** + * Returns the capacity of the heap. + * + * @param _heap Binary heap. + * @return Capacity. + */ +#define BHEAP_CAPACITY(_heap) \ + VECTOR_CAPACITY(_heap) + +/** + * Ensures that the heap has the target number of empty positions. + * + * Increases the capacity in multiples of _step. + * + * @param _heap Binary heap. + * @param _n Required empty positions. + * @param _step Increase. + */ +#define BHEAP_ENSURE(_heap, _n, _step) \ + VECTOR_ENSURE(_heap, _n, _step) + +/** + * Returns the top value of the heap. + * + * Assumes the heap is not empty. + * + * @param _heap Binary heap. + * @return Value at the top. + */ +#define BHEAP_PEEK(_heap) \ + VECTOR_INDEX(_heap, 0) + +/** + * Inserts a value in the heap (using the '=' operator). + * + * Assumes there is enough capacity. + * + * The comparator takes two values as arguments, returns: + * - negative if the first value is on the top + * - positive if the second value is on the top + * - 0 if they are equal + * + * @param _heap Binary heap. + * @param _val Value. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_PUSH(_heap, _val, _topcmp, _swp) \ + do { \ + int _i_ = VECTOR_LENGTH(_heap); \ + VECTOR_PUSH(_heap, _val); /* insert at end */ \ + while (_i_ > 0) { \ + /* restore heap property in parents */ \ + int _parent_ = (_i_-1)/2; \ + if (_topcmp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)) < 0) \ break; /* done */ \ - __swp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \ + _swp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)); \ _i_ = _parent_; \ } \ - }while(0) - -/// See BHEAP_PUSH. Version used by A* implementation, matching client bheap. -/// -/// @param __heap Binary heap -/// @param __val Value -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_PUSH2(__heap,__val,__topcmp,__swp) \ - do{ \ - size_t _i_ = VECTOR_LENGTH(__heap); \ - VECTOR_PUSH(__heap,__val); /* insert at end */ \ - BHEAP_SIFTDOWN(__heap,0,_i_,__topcmp,__swp); \ - }while(0) - -/// Removes the top value of the heap. (using the '=' operator) -/// Assumes the heap is not empty. -/// -/// The comparator takes two values as arguments, returns: -/// - negative if the first value is on the top -/// - positive if the second value is on the top -/// - 0 if they are equal -/// -/// @param __heap Binary heap -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_POP(__heap,__topcmp,__swp) BHEAP_POPINDEX(__heap,0,__topcmp,__swp) - -/// See BHEAP_POP. Version used by A* implementation, matching client bheap. -/// -/// @param __heap Binary heap -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_POP2(__heap,__topcmp,__swp) \ - do{ \ - VECTOR_INDEX(__heap,0) = VECTOR_POP(__heap); /* put last at index */ \ - if( !VECTOR_LENGTH(__heap) ) /* removed last, nothing to do */ \ + } while(false) + +/** + * Variant of BHEAP_PUSH used by A* implementation, matching client bheap. + * + * @see BHEAP_PUSH. + * + * @param _heap Binary heap. + * @param _val Value. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_PUSH2(_heap, _val, _topcmp, _swp) \ + do { \ + int _i_ = VECTOR_LENGTH(_heap); \ + VECTOR_PUSH(_heap, _val); /* insert at end */ \ + BHEAP_SIFTDOWN(_heap, 0, _i_, _topcmp, _swp); \ + } while(false) + +/** + * Removes the top value of the heap (using the '=' operator). + * + * Assumes the heap is not empty. + * + * The comparator takes two values as arguments, returns: + * - negative if the first value is on the top + * - positive if the second value is on the top + * - 0 if they are equal + * + * @param _heap Binary heap. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_POP(_heap, _topcmp, _swp) \ + BHEAP_POPINDEX(_heap, 0, _topcmp, _swp) + +/** + * Variant of BHEAP_POP used by A* implementation, matching client bheap. + * + * @see BHEAP_POP. + * + * @param _heap Binary heap. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_POP2(_heap, _topcmp, _swp) \ + do { \ + VECTOR_INDEX(_heap, 0) = VECTOR_POP(_heap); /* put last at index */ \ + if (VECTOR_LENGTH(_heap) == 0) /* removed last, nothing to do */ \ break; \ - BHEAP_SIFTUP(__heap,0,__topcmp,__swp); \ - }while(0) - -/// Removes the target value of the heap. (using the '=' operator) -/// Assumes the index exists. -/// -/// The comparator takes two values as arguments, returns: -/// - negative if the first value is on the top -/// - positive if the second value is on the top -/// - 0 if they are equal -/// -/// @param __heap Binary heap -/// @param __idx Index -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_POPINDEX(__heap,__idx,__topcmp,__swp) \ - do{ \ - size_t _i_ = __idx; \ - VECTOR_INDEX(__heap,__idx) = VECTOR_POP(__heap); /* put last at index */ \ - if( _i_ >= VECTOR_LENGTH(__heap)) /* removed last, nothing to do */ \ + BHEAP_SIFTUP(_heap, 0, _topcmp, _swp); \ + } while(false) + +/** + * Removes the target value of the heap (using the '=' operator). + * + * Assumes the index exists. + * + * The comparator takes two values as arguments, returns: + * - negative if the first value is on the top + * - positive if the second value is on the top + * - 0 if they are equal + * + * @param _heap Binary heap. + * @param _idx Index. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_POPINDEX(_heap, _idx, _topcmp, _swp) \ + do { \ + int _i_ = _idx; \ + VECTOR_INDEX(_heap, _idx) = VECTOR_POP(_heap); /* put last at index */ \ + if (_i_ >= VECTOR_LENGTH(_heap)) /* removed last, nothing to do */ \ break; \ - while( _i_ ) \ - { /* restore heap property in parents */ \ - size_t _parent_ = (_i_-1)/2; \ - if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \ + while (_i_ > 0) { \ + /* restore heap property in parents */ \ + int _parent_ = (_i_-1)/2; \ + if (_topcmp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)) < 0) \ break; /* done */ \ - __swp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \ + _swp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)); \ _i_ = _parent_; \ } \ - while( _i_ < VECTOR_LENGTH(__heap) ) \ - { /* restore heap property in childs */ \ - size_t _lchild_ = _i_*2 + 1; \ - size_t _rchild_ = _i_*2 + 2; \ - if( (_lchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)) <= 0) && \ - (_rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)) <= 0) ) \ + while (_i_ < VECTOR_LENGTH(_heap)) { \ + /* restore heap property in children */ \ + int _lchild_ = _i_*2 + 1; \ + int _rchild_ = _i_*2 + 2; \ + if ((_lchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _lchild_)) <= 0) \ + && (_rchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _rchild_)) <= 0)) { \ break; /* done */ \ - else if( _rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_lchild_),VECTOR_INDEX(__heap,_rchild_)) <= 0 ) \ - { /* left child */ \ - __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)); \ + } else if (_rchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _lchild_), VECTOR_INDEX(_heap, _rchild_)) <= 0) { \ + /* left child */ \ + _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _lchild_)); \ _i_ = _lchild_; \ - } \ - else \ - { /* right child */ \ - __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)); \ + } else { \ + /* right child */ \ + _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _rchild_)); \ _i_ = _rchild_; \ } \ } \ - }while(0) - -/// Follow path up towards (but not all the way to) the root, swapping nodes until finding -/// a place where the new item that was placed at __idx fits. -/// Only goes as high as __startidx (usually 0). -/// -/// @param __heap Binary heap -/// @param __startidx Index of an ancestor of __idx -/// @param __idx Index of an inserted element -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_SIFTDOWN(__heap,__startidx,__idx,__topcmp,__swp) \ - do{ \ - size_t _i2_ = __idx; \ - while( _i2_ > __startidx ) \ - { /* restore heap property in parents */ \ - size_t _parent_ = (_i2_-1)/2; \ - if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i2_)) <= 0 ) \ + } while(false) + +/** + * Follow path up towards (but not all the way to) the root, swapping nodes + * until finding a place where the new item that was placed at _idx fits. + * + * Only goes as high as _startidx (usually 0). + * + * @param _heap Binary heap. + * @param _startidx Index of an ancestor of _idx. + * @param _idx Index of an inserted element. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_SIFTDOWN(_heap, _startidx, _idx, _topcmp, _swp) \ + do { \ + int _i2_ = _idx; \ + while (_i2_ > _startidx) { \ + /* restore heap property in parents */ \ + int _parent_ = (_i2_-1)/2; \ + if (_topcmp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i2_)) <= 0) \ break; /* done */ \ - __swp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i2_)); \ + _swp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i2_)); \ _i2_ = _parent_; \ } \ - }while(0) - -/// Repeatedly swap the smaller child with parent, after placing a new item at __idx. -/// -/// @param __heap Binary heap -/// @param __idx Index of an inserted element -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_SIFTUP(__heap,__idx,__topcmp,__swp) \ - do{ \ - size_t _i_ = __idx; \ - size_t _lchild_ = _i_*2 + 1; \ - while( _lchild_ < VECTOR_LENGTH(__heap) ) \ - { /* restore heap property in childs */ \ - size_t _rchild_ = _i_*2 + 2; \ - if( _rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_lchild_),VECTOR_INDEX(__heap,_rchild_)) < 0 ) \ - { /* left child */ \ - __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)); \ + } while(false) + +/** + * Repeatedly swap the smaller child with parent, after placing a new item at _idx. + * + * @param _heap Binary heap. + * @param _idx Index of an inserted element. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_SIFTUP(_heap, _idx, _topcmp, _swp) \ + do { \ + int _i_ = _idx; \ + int _lchild_ = _i_*2 + 1; \ + while (_lchild_ < VECTOR_LENGTH(_heap)) { \ + /* restore heap property in children */ \ + int _rchild_ = _i_*2 + 2; \ + if (_rchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _lchild_), VECTOR_INDEX(_heap, _rchild_)) < 0) { \ + /* left child */ \ + _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _lchild_)); \ _i_ = _lchild_; \ - } \ - else \ - { /* right child */ \ - __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)); \ + } else { \ + /* right child */ \ + _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _rchild_)); \ _i_ = _rchild_; \ } \ _lchild_ = _i_*2 + 1; \ } \ - BHEAP_SIFTDOWN(__heap,__idx,_i_,__topcmp,__swp); \ - }while(0) - -/// Call this after modifying the item at __idx__ to restore the heap -/// -/// @param __heap Binary heap -/// @param __idx Index -/// @param __topcmp Comparator -/// @param __swp Swapper -#define BHEAP_UPDATE(__heap,__idx,__topcmp,__swp) \ - do{ \ - BHEAP_SIFTDOWN(__heap,0,__idx,__topcmp,__swp); \ - BHEAP_SIFTUP(__heap,__idx,__topcmp,__swp); \ - }while(0) - -/// Clears the binary heap, freeing allocated data. -/// -/// @param __heap Binary heap -#define BHEAP_CLEAR(__heap) VECTOR_CLEAR(__heap) - -/// Generic comparator for a min-heap. (minimum value at top) -/// Returns -1 if v1 is smaller, 1 if v2 is smaller, 0 if equal. -/// -/// @param v1 First value -/// @param v2 Second value -/// @return negative if v1 is top, positive if v2 is top, 0 if equal -#define BHEAP_MINTOPCMP(v1,v2) ( v1 == v2 ? 0 : v1 < v2 ? -1 : 1 ) - -/// Generic comparator for a max-heap. (maximum value at top) -/// Returns -1 if v1 is bigger, 1 if v2 is bigger, 0 if equal. -/// -/// @param v1 First value -/// @param v2 Second value -/// @return negative if v1 is top, positive if v2 is top, 0 if equal -#define BHEAP_MAXTOPCMP(v1,v2) ( v1 == v2 ? 0 : v1 > v2 ? -1 : 1 ) + BHEAP_SIFTDOWN(_heap, _idx, _i_, _topcmp, _swp); \ + } while(false) + +/** + * Restores a heap (after modifying the item at _idx). + * + * @param _heap Binary heap. + * @param _idx Index. + * @param _topcmp Comparator. + * @param _swp Swapper. + */ +#define BHEAP_UPDATE(_heap, _idx, _topcmp, _swp) \ + do { \ + BHEAP_SIFTDOWN(_heap, 0, _idx, _topcmp, _swp); \ + BHEAP_SIFTUP(_heap, _idx, _topcmp, _swp); \ + } while(false) + +/** + * Clears the binary heap, freeing allocated data. + * + * @param _heap Binary heap. + */ +#define BHEAP_CLEAR(_heap) \ + VECTOR_CLEAR(_heap) + +/** + * Generic comparator for a min-heap (minimum value at top). + * + * Returns -1 if v1 is smaller, 1 if v2 is smaller, 0 if equal. + * + * @warning + * Arguments may be evaluted more than once. + * + * @param v1 First value. + * @param v2 Second value. + * @return negative if v1 is top, positive if v2 is top, 0 if equal. + */ +#define BHEAP_MINTOPCMP(v1, v2) \ + ( v1 == v2 ? 0 : v1 < v2 ? -1 : 1 ) + +/** + * Generic comparator for a max-heap (maximum value at top). + * + * Returns -1 if v1 is bigger, 1 if v2 is bigger, 0 if equal. + * + * @warning + * Arguments may be evaluted more than once. + * + * @param v1 First value. + * @param v2 Second value. + * @return negative if v1 is top, positive if v2 is top, 0 if equal. + */ +#define BHEAP_MAXTOPCMP(v1, v2) \ + ( v1 == v2 ? 0 : v1 > v2 ? -1 : 1 ) #endif /* COMMON_DB_H */ diff --git a/src/common/ers.c b/src/common/ers.c index 91fc6ccfb..bf17e087d 100644 --- a/src/common/ers.c +++ b/src/common/ers.c @@ -45,7 +45,7 @@ #include "ers.h" #include "common/cbasetypes.h" -#include "common/malloc.h" // CREATE, RECREATE, aMalloc, aFree +#include "common/memmgr.h" // CREATE, RECREATE, aMalloc, aFree #include "common/nullpo.h" #include "common/showmsg.h" // ShowMessage, ShowError, ShowFatalError, CL_BOLD, CL_NORMAL diff --git a/src/common/grfio.c b/src/common/grfio.c index b59c2b63d..46804ea08 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -8,7 +8,7 @@ #include "common/cbasetypes.h" #include "common/des.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/strlib.h" diff --git a/src/common/malloc.c b/src/common/memmgr.c index 63de90cb3..0d9305b06 100644 --- a/src/common/malloc.c +++ b/src/common/memmgr.c @@ -4,7 +4,7 @@ #define HERCULES_CORE -#include "malloc.h" +#include "memmgr.h" #include "common/cbasetypes.h" #include "common/core.h" @@ -79,6 +79,26 @@ struct malloc_interface *iMalloc; #endif +#ifndef USE_MEMMGR + +#ifdef __APPLE__ +#include <malloc/malloc.h> +#define BUFFER_SIZE(ptr) malloc_size(ptr) +#elif __FreeBSD__ +#include <malloc_np.h> +#define BUFFER_SIZE(ptr) malloc_usable_size(ptr) +#elif defined __linux__ || defined __linux || defined CYGWIN +#include <malloc.h> +#define BUFFER_SIZE(ptr) malloc_usable_size(ptr) +#elif defined WIN32 +#include <malloc.h> +#define BUFFER_SIZE(ptr) _msize(ptr) +#else +#error Unsupported OS +#endif + +#endif + void* aMalloc_(size_t size, const char *file, int line, const char *func) { void *ret = MALLOC(size, file, line, func); @@ -110,6 +130,34 @@ void* aRealloc_(void *p, size_t size, const char *file, int line, const char *fu } return ret; } + +void* aReallocz_(void *p, size_t size, const char *file, int line, const char *func) +{ + void *ret; + // ShowMessage("%s:%d: in func %s: aReallocz %p %ld\n",file,line,func,p,size); +#ifdef USE_MEMMGR + ret = REALLOC(p, size, file, line, func); +#else + size_t newSize; + if (p) { + size_t oldSize = malloc_usable_size(p); + ret = REALLOC(p, size, file, line, func); + newSize = BUFFER_SIZE(ret); + if (ret && newSize > oldSize) + memset(ret + oldSize, 0, newSize - oldSize); + } else { + ret = REALLOC(p, size, file, line, func); + if (ret) + memset(ret, 0, BUFFER_SIZE(ret)); + } +#endif + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aRealloc error out of memory!\n",file,line,func); + exit(EXIT_FAILURE); + } + return ret; +} + char* aStrdup_(const char *p, const char *file, int line, const char *func) { char *ret = STRDUP(p, file, line, func); @@ -888,7 +936,7 @@ void malloc_defaults(void) { iMalloc->malloc = aMalloc_; iMalloc->calloc = aCalloc_; iMalloc->realloc = aRealloc_; - iMalloc->reallocz = aRealloc_;/* not using memory manager huhum o.o perhaps we could still do something about */ + iMalloc->reallocz = aReallocz_;/* not using memory manager huhum o.o perhaps we could still do something about */ iMalloc->astrdup = aStrdup_; iMalloc->free = aFree_; #endif diff --git a/src/common/malloc.h b/src/common/memmgr.h index b194c7cf3..c5a3358db 100644 --- a/src/common/malloc.h +++ b/src/common/memmgr.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef COMMON_MALLOC_H -#define COMMON_MALLOC_H +#ifndef COMMON_MEMMGR_H +#define COMMON_MEMMGR_H #include "common/hercules.h" @@ -86,4 +86,4 @@ void memmgr_report(int extra); HPShared struct malloc_interface *iMalloc; -#endif /* COMMON_MALLOC_H */ +#endif /* COMMON_MEMMGR_H */ diff --git a/src/common/mmo.h b/src/common/mmo.h index 75b62fdc4..73d4510a1 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -198,7 +198,7 @@ #define JOBL_BABY 0x2000 //8192 #define JOBL_THIRD 0x4000 //16384 -struct HPluginData; +struct hplugin_data_store; enum item_types { IT_HEALING = 0, @@ -299,6 +299,7 @@ enum e_mmo_charstatus_opt { }; enum e_item_bound_type { + IBT_NONE = 0x0, IBT_MIN = 0x1, IBT_ACCOUNT = 0x1, IBT_GUILD = 0x2, @@ -660,10 +661,7 @@ struct guild { unsigned short instances; struct channel_data *channel; - - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; struct guild_castle { diff --git a/src/common/mutex.c b/src/common/mutex.c index 715609628..af1a6d155 100644 --- a/src/common/mutex.c +++ b/src/common/mutex.c @@ -6,7 +6,7 @@ #include "mutex.h" #include "common/cbasetypes.h" // for WIN32 -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/showmsg.h" #include "common/timer.h" diff --git a/src/common/socket.c b/src/common/socket.c index de8ca4682..b418a468f 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -10,7 +10,7 @@ #include "common/HPM.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" @@ -623,7 +623,6 @@ static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseF sockt->session[fd]->rdata_tick = sockt->last_tick; sockt->session[fd]->session_data = NULL; sockt->session[fd]->hdata = NULL; - sockt->session[fd]->hdatac = 0; return 0; } @@ -638,16 +637,7 @@ static void delete_session(int fd) aFree(sockt->session[fd]->wdata); if( sockt->session[fd]->session_data ) aFree(sockt->session[fd]->session_data); - if (sockt->session[fd]->hdata) { - unsigned int i; - for(i = 0; i < sockt->session[fd]->hdatac; i++) { - if( sockt->session[fd]->hdata[i]->flag.free ) { - aFree(sockt->session[fd]->hdata[i]->data); - } - aFree(sockt->session[fd]->hdata[i]); - } - aFree(sockt->session[fd]->hdata); - } + HPM->data_store_destroy(&sockt->session[fd]->hdata); aFree(sockt->session[fd]); sockt->session[fd] = NULL; } @@ -977,7 +967,7 @@ static int connect_check_(uint32 ip) // Search the allow list for( i=0; i < access_allownum; ++i ){ - if( (ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask) ){ + if (SUBNET_MATCH(ip, access_allow[i].ip, access_allow[i].mask)) { if( access_debug ){ ShowInfo("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", CONVIP(ip), @@ -990,7 +980,7 @@ static int connect_check_(uint32 ip) } // Search the deny list for( i=0; i < access_denynum; ++i ){ - if( (ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask) ){ + if (SUBNET_MATCH(ip, access_deny[i].ip, access_deny[i].mask)) { if( access_debug ){ ShowInfo("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", CONVIP(ip), @@ -1226,20 +1216,9 @@ void socket_final(void) aFree(sockt->session); - if (sockt->lan_subnet) - aFree(sockt->lan_subnet); - sockt->lan_subnet = NULL; - sockt->lan_subnet_count = 0; - - if (sockt->allowed_ip) - aFree(sockt->allowed_ip); - sockt->allowed_ip = NULL; - sockt->allowed_ip_count = 0; - - if (sockt->trusted_ip) - aFree(sockt->trusted_ip); - sockt->trusted_ip = NULL; - sockt->trusted_ip_count = 0; + VECTOR_CLEAR(sockt->lan_subnets); + VECTOR_CLEAR(sockt->allowed_ips); + VECTOR_CLEAR(sockt->trusted_ips); } /// Closes a socket. @@ -1544,7 +1523,7 @@ void send_shortlist_add_fd(int fd) return;// already in the list if (send_shortlist_count >= ARRAYLENGTH(send_shortlist_array)) { - ShowDebug("send_shortlist_add_fd: shortlist is full, ignoring... (fd=%d shortlist.count=%d shortlist.length=%"PRIuS")\n", + ShowDebug("send_shortlist_add_fd: shortlist is full, ignoring... (fd=%d shortlist.count=%d shortlist.length=%d)\n", fd, send_shortlist_count, ARRAYLENGTH(send_shortlist_array)); return; } @@ -1615,13 +1594,13 @@ void send_shortlist_do_sends() uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info) { int i; - ARR_FIND(0, sockt->lan_subnet_count, i, (sockt->lan_subnet[i].ip & sockt->lan_subnet[i].mask) == (ip & sockt->lan_subnet[i].mask)); - if (i < sockt->lan_subnet_count) { + ARR_FIND(0, VECTOR_LENGTH(sockt->lan_subnets), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->lan_subnets, i).ip, VECTOR_INDEX(sockt->lan_subnets, i).mask)); + if (i != VECTOR_LENGTH(sockt->lan_subnets)) { if (info) { - info->ip = sockt->lan_subnet[i].ip; - info->mask = sockt->lan_subnet[i].mask; + info->ip = VECTOR_INDEX(sockt->lan_subnets, i).ip; + info->mask = VECTOR_INDEX(sockt->lan_subnets, i).mask; } - return sockt->lan_subnet[i].ip; + return VECTOR_INDEX(sockt->lan_subnets, i).ip; } if (info) { info->ip = info->mask = 0; @@ -1639,8 +1618,8 @@ uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info) bool socket_allowed_ip_check(uint32 ip) { int i; - ARR_FIND(0, sockt->allowed_ip_count, i, (sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == (ip & sockt->allowed_ip[i].mask) ); - if (i < sockt->allowed_ip_count) + ARR_FIND(0, VECTOR_LENGTH(sockt->allowed_ips), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->allowed_ips, i).ip, VECTOR_INDEX(sockt->allowed_ips, i).mask)); + if (i != VECTOR_LENGTH(sockt->allowed_ips)) return true; return sockt->trusted_ip_check(ip); // If an address is trusted, it's automatically also allowed. } @@ -1655,8 +1634,8 @@ bool socket_allowed_ip_check(uint32 ip) bool socket_trusted_ip_check(uint32 ip) { int i; - ARR_FIND(0, sockt->trusted_ip_count, i, (sockt->trusted_ip[i].ip & sockt->trusted_ip[i].mask) == (ip & sockt->trusted_ip[i].mask)); - if (i < sockt->trusted_ip_count) + ARR_FIND(0, VECTOR_LENGTH(sockt->trusted_ips), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->trusted_ips, i).ip, VECTOR_INDEX(sockt->trusted_ips, i).mask)); + if (i != VECTOR_LENGTH(sockt->trusted_ips)) return true; return false; } @@ -1667,39 +1646,38 @@ bool socket_trusted_ip_check(uint32 ip) * Entries will be appended to the variable-size array pointed to by list/count. * * @param[in] t The list to parse. - * @param[in,out] list Pointer to the head of the output array to append to. Must not be NULL (but the array may be empty). - * @param[in,out] count Pointer to the counter of the output array to append to. Must not be NULL (but it may contain zero). + * @param[in,out] list Vector to append to. Must not be NULL (but the vector may be empty). * @param[in] filename Current filename, for output/logging reasons. * @param[in] groupname Current group name, for output/logging reasons. * @return The amount of entries read, zero in case of errors. */ -int socket_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) +int socket_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) { int i, len; char ipbuf[64], maskbuf[64]; nullpo_retr(0, list); - nullpo_retr(0, count); if (t == NULL) return 0; len = libconfig->setting_length(t); + VECTOR_ENSURE(*list, len, 1); for (i = 0; i < len; ++i) { const char *subnet = libconfig->setting_get_string_elem(t, i); - struct s_subnet *l = NULL; + struct s_subnet *entry = NULL; if (sscanf(subnet, "%63[^:]:%63[^:]", ipbuf, maskbuf) != 2) { ShowWarning("Invalid IP:Subnet entry in configuration file %s: '%s' (%s)\n", filename, subnet, groupname); + continue; } - RECREATE(*list, struct s_subnet, *count + 1); - l = *list; - l[*count].ip = sockt->str2ip(ipbuf); - l[*count].mask = sockt->str2ip(maskbuf); - ++*count; + VECTOR_PUSHZEROED(*list); + entry = &VECTOR_LAST(*list); + entry->ip = sockt->str2ip(ipbuf); + entry->mask = sockt->str2ip(maskbuf); } - return *count; + return (int)VECTOR_LENGTH(*list); } /** @@ -1718,45 +1696,29 @@ void socket_net_config_read(const char *filename) return; } - if (sockt->lan_subnet) { - aFree(sockt->lan_subnet); - sockt->lan_subnet = NULL; - } - sockt->lan_subnet_count = 0; - if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "lan_subnets"), &sockt->lan_subnet, &sockt->lan_subnet_count, filename, "lan_subnets") > 0) - ShowStatus("Read information about %d LAN subnets.\n", sockt->lan_subnet_count); + VECTOR_CLEAR(sockt->lan_subnets); + if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "lan_subnets"), &sockt->lan_subnets, filename, "lan_subnets") > 0) + ShowStatus("Read information about %d LAN subnets.\n", (int)VECTOR_LENGTH(sockt->lan_subnets)); - if (sockt->trusted_ip) { - aFree(sockt->trusted_ip); - sockt->trusted_ip = NULL; - } - sockt->trusted_ip_count = 0; - if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "trusted"), &sockt->trusted_ip, &sockt->trusted_ip_count, filename, "trusted") > 0) - ShowStatus("Read information about %d trusted IP ranges.\n", sockt->trusted_ip_count); - for (i = 0; i < sockt->allowed_ip_count; ++i) { - if ((sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == 0) { - ShowError("Using a wildcard IP range in the trusted server IPs is NOT RECOMMENDED.\n"); - ShowNotice("Please edit your '%s' trusted list to fit your network configuration.\n", filename); - break; - } + VECTOR_CLEAR(sockt->trusted_ips); + if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "trusted"), &sockt->trusted_ips, filename, "trusted") > 0) + ShowStatus("Read information about %d trusted IP ranges.\n", (int)VECTOR_LENGTH(sockt->trusted_ips)); + ARR_FIND(0, VECTOR_LENGTH(sockt->trusted_ips), i, SUBNET_MATCH(0, VECTOR_INDEX(sockt->trusted_ips, i).ip, VECTOR_INDEX(sockt->trusted_ips, i).mask)); + if (i != VECTOR_LENGTH(sockt->trusted_ips)) { + ShowError("Using a wildcard IP range in the trusted server IPs is NOT RECOMMENDED.\n"); + ShowNotice("Please edit your '%s' trusted list to fit your network configuration.\n", filename); } - if (sockt->allowed_ip) { - aFree(sockt->allowed_ip); - sockt->allowed_ip = NULL; - } - sockt->allowed_ip_count = 0; - if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "allowed"), &sockt->allowed_ip, &sockt->allowed_ip_count, filename, "allowed") > 0) - ShowStatus("Read information about %d allowed server IP ranges.\n", sockt->allowed_ip_count); - if (sockt->allowed_ip_count == 0) { + VECTOR_CLEAR(sockt->allowed_ips); + if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "allowed"), &sockt->allowed_ips, filename, "allowed") > 0) + ShowStatus("Read information about %d allowed server IP ranges.\n", (int)VECTOR_LENGTH(sockt->allowed_ips)); + if (VECTOR_LENGTH(sockt->allowed_ips) + VECTOR_LENGTH(sockt->trusted_ips) == 0) { ShowError("No allowed server IP ranges configured. This server won't be able to accept connections from any char servers.\n"); } - for (i = 0; i < sockt->allowed_ip_count; ++i) { - if ((sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == 0) { - ShowWarning("Using a wildcard IP range in the allowed server IPs is NOT RECOMMENDED.\n"); - ShowNotice("Please edit your '%s' allowed list to fit your network configuration.\n", filename); - break; - } + ARR_FIND(0, VECTOR_LENGTH(sockt->allowed_ips), i, SUBNET_MATCH(0, VECTOR_INDEX(sockt->allowed_ips, i).ip, VECTOR_INDEX(sockt->allowed_ips, i).mask)); + if (i != VECTOR_LENGTH(sockt->allowed_ips)) { + ShowWarning("Using a wildcard IP range in the allowed server IPs is NOT RECOMMENDED.\n"); + ShowNotice("Please edit your '%s' allowed list to fit your network configuration.\n", filename); } libconfig->destroy(&network_config); return; @@ -1773,12 +1735,9 @@ void socket_defaults(void) { memset(&sockt->addr_, 0, sizeof(sockt->addr_)); sockt->naddr_ = 0; /* */ - sockt->lan_subnet_count = 0; - sockt->lan_subnet = NULL; - sockt->allowed_ip_count = 0; - sockt->allowed_ip = NULL; - sockt->trusted_ip_count = 0; - sockt->trusted_ip = NULL; + VECTOR_INIT(sockt->lan_subnets); + VECTOR_INIT(sockt->allowed_ips); + VECTOR_INIT(sockt->trusted_ips); sockt->init = socket_init; sockt->final = socket_final; diff --git a/src/common/socket.h b/src/common/socket.h index a995bffc8..426f8e4bb 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -7,6 +7,7 @@ #include "common/hercules.h" #include "common/conf.h" +#include "common/db.h" #ifdef WIN32 # include "common/winapi.h" @@ -17,7 +18,7 @@ # include <sys/types.h> #endif -struct HPluginData; +struct hplugin_data_store; #define FIFOSIZE_SERVERLINK 256*1024 @@ -104,9 +105,7 @@ struct socket_data { ParseFunc func_parse; void* session_data; // stores application-specific data related to the session - - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store. }; struct hSockOpt { @@ -120,6 +119,9 @@ struct s_subnet { uint32 mask; }; +/// A vector of subnets/IP ranges. +VECTOR_STRUCT_DECL(s_subnet_vector, struct s_subnet); + /// Use a shortlist of sockets instead of iterating all sessions for sockets /// that have data to send or need eof handling. /// Adapted to use a static array instead of a linked list. @@ -131,6 +133,11 @@ struct s_subnet { #define CONVIP(ip) ((ip)>>24)&0xFF,((ip)>>16)&0xFF,((ip)>>8)&0xFF,((ip)>>0)&0xFF #define MAKEIP(a,b,c,d) ((uint32)( ( ( (a)&0xFF ) << 24 ) | ( ( (b)&0xFF ) << 16 ) | ( ( (c)&0xFF ) << 8 ) | ( ( (d)&0xFF ) << 0 ) )) +/// Applies a subnet mask to an IP +#define APPLY_MASK(ip, mask) ((ip)&(mask)) +/// Verifies the match between two IPs, with a subnet mask applied +#define SUBNET_MATCH(ip1, ip2, mask) (APPLY_MASK((ip1), (mask)) == APPLY_MASK((ip2), (mask))) + /** * Socket.c interface, mostly for reading however. **/ @@ -145,12 +152,9 @@ struct socket_interface { struct socket_data **session; - struct s_subnet *lan_subnet; ///< LAN subnets array - int lan_subnet_count; ///< LAN subnets count - struct s_subnet *trusted_ip; ///< Trusted IP ranges array - int trusted_ip_count; ///< Trusted IP ranges count - struct s_subnet *allowed_ip; ///< Allowed server IP ranges array - int allowed_ip_count; ///< Allowed server IP ranges count + struct s_subnet_vector lan_subnets; ///< LAN subnets. + struct s_subnet_vector trusted_ips; ///< Trusted IP ranges + struct s_subnet_vector allowed_ips; ///< Allowed server IP ranges /* */ void (*init) (void); @@ -189,7 +193,7 @@ struct socket_interface { uint32 (*lan_subnet_check) (uint32 ip, struct s_subnet *info); bool (*allowed_ip_check) (uint32 ip); bool (*trusted_ip_check) (uint32 ip); - int (*net_config_read_sub) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*net_config_read_sub) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); void (*net_config_read) (const char *filename); }; diff --git a/src/common/sql.c b/src/common/sql.c index ee759eb61..4262a10a1 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -7,7 +7,7 @@ #include "sql.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/timer.h" diff --git a/src/common/strlib.c b/src/common/strlib.c index fcd1b483b..fefabe52b 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -7,7 +7,7 @@ #include "strlib.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/showmsg.h" #include <errno.h> diff --git a/src/common/sysinfo.c b/src/common/sysinfo.c index d218e6e99..1baf33086 100644 --- a/src/common/sysinfo.c +++ b/src/common/sysinfo.c @@ -10,7 +10,7 @@ #include "common/cbasetypes.h" #include "common/core.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/strlib.h" #include <stdio.h> // fopen diff --git a/src/common/thread.c b/src/common/thread.c index d5bbd7f97..d9cd42aa6 100644 --- a/src/common/thread.c +++ b/src/common/thread.c @@ -11,7 +11,7 @@ #include "thread.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/showmsg.h" #include "common/sysinfo.h" // sysinfo->getpagesize() diff --git a/src/common/timer.c b/src/common/timer.c index 793706511..f31ae0ffe 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -8,7 +8,7 @@ #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/showmsg.h" #include "common/utils.h" @@ -239,6 +239,10 @@ int64 timer_gettick(void) { /// Adds a timer to the timer_heap static void push_timer_heap(int tid) { BHEAP_ENSURE(timer_heap, 1, 256); +#ifdef __clang_analyzer__ // Clang's static analyzer warns that BHEAP_ENSURE might set BHEAP_DATA(timer_heap) to NULL. +#include "assert.h" + assert(BHEAP_DATA(timer_heap) != NULL); +#endif // __clang_analyzer__ BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP, swap); } @@ -348,14 +352,21 @@ int64 timer_addtick(int tid, int64 tick) { return timer->settick(tid, timer_data[tid].tick+tick); } -/// Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one). -/// Returns the new tick value, or -1 if it fails. -int64 timer_settick(int tid, int64 tick) { - size_t i; +/** + * Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one). + * + * @param tid The timer ID. + * @param tick New expiration time. + * @return The new tick value. + * @retval -1 in case of failure. + */ +int64 timer_settick(int tid, int64 tick) +{ + int i; // search timer position ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid); - if( i == BHEAP_LENGTH(timer_heap) ) { + if (i == BHEAP_LENGTH(timer_heap)) { ShowError("timer_settick: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); return -1; } @@ -373,13 +384,18 @@ int64 timer_settick(int tid, int64 tick) { return tick; } -/// Executes all expired timers. -/// Returns the value of the smallest non-expired timer (or 1 second if there aren't any). -int do_timer(int64 tick) { +/** + * Executes all expired timers. + * + * @param tick The current tick. + * @return The value of the smallest non-expired timer (or 1 second if there aren't any). + */ +int do_timer(int64 tick) +{ int64 diff = TIMER_MAX_INTERVAL; // return value // process all timers one by one - while( BHEAP_LENGTH(timer_heap) ) { + while (BHEAP_LENGTH(timer_heap) > 0) { int tid = BHEAP_PEEK(timer_heap);// top element in heap (smallest tick) diff = DIFF_TICK(timer_data[tid].tick, tick); diff --git a/src/login/HPMlogin.c b/src/login/HPMlogin.c index 895cbad16..5ceb38283 100644 --- a/src/login/HPMlogin.c +++ b/src/login/HPMlogin.c @@ -17,7 +17,7 @@ #include "common/db.h" #include "common/des.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" @@ -32,13 +32,19 @@ // HPMDataCheck comes after all the other includes #include "common/HPMDataCheck.h" -bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) { - /* record address */ - switch( type ) { +/** + * HPM plugin data store validator sub-handler (login-server) + * + * @see HPM_interface::data_store_validate + */ +bool HPM_login_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize) +{ + switch (type) { + // No supported types at the moment default: - return false; + break; } - return true; + return false; } void HPM_login_plugin_load_sub(struct hplugin *plugin) { @@ -46,6 +52,8 @@ void HPM_login_plugin_load_sub(struct hplugin *plugin) { } void HPM_login_do_init(void) { + HPM->load_sub = HPM_login_plugin_load_sub; + HPM->data_store_validate_sub = HPM_login_data_store_validate; HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer); HPM_shared_symbols(SERVER_TYPE_LOGIN); } diff --git a/src/login/HPMlogin.h b/src/login/HPMlogin.h index 2a4d5c538..35d4bd01c 100644 --- a/src/login/HPMlogin.h +++ b/src/login/HPMlogin.h @@ -13,7 +13,7 @@ struct hplugin; -bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr); +bool HPM_login_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize); void HPM_login_plugin_load_sub(struct hplugin *plugin); diff --git a/src/login/account_sql.c b/src/login/account_sql.c index 37837fc35..4efa73e94 100644 --- a/src/login/account_sql.c +++ b/src/login/account_sql.c @@ -9,7 +9,7 @@ #include "common/cbasetypes.h" #include "common/console.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/login/login.c b/src/login/login.c index 572bd594f..3ec60f0aa 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -15,7 +15,7 @@ #include "common/conf.h" #include "common/core.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/md5calc.h" #include "common/nullpo.h" #include "common/random.h" @@ -768,7 +768,7 @@ void login_fromchar_parse_accinfo(int fd) //-------------------------------- int login_parse_fromchar(int fd) { - int j, id; + int id; uint32 ipl; char ip[16]; @@ -795,11 +795,12 @@ int login_parse_fromchar(int fd) while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - if( HPM->packetsc[hpParse_FromChar] ) { - if( (j = HPM->parse_packets(fd,hpParse_FromChar)) ) { - if( j == 1 ) continue; - if( j == 2 ) return 0; - } + if (VECTOR_LENGTH(HPM->packets[hpParse_FromChar]) > 0) { + int result = HPM->parse_packets(fd,hpParse_FromChar); + if (result == 1) + continue; + if (result == 2) + return 0; } switch( command ) { @@ -1574,7 +1575,6 @@ void login_parse_request_connection(int fd, struct login_session_data* sd, const int login_parse_login(int fd) { struct login_session_data* sd = (struct login_session_data*)sockt->session[fd]->session_data; - int result; char ip[16]; uint32 ipl = sockt->session[fd]->client_addr; @@ -1608,11 +1608,12 @@ int login_parse_login(int fd) while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - if( HPM->packetsc[hpParse_Login] ) { - if( (result = HPM->parse_packets(fd,hpParse_Login)) ) { - if( result == 1 ) continue; - if( result == 2 ) return 0; - } + if (VECTOR_LENGTH(HPM->packets[hpParse_Login]) > 0) { + int result = HPM->parse_packets(fd,hpParse_Login); + if (result == 1) + continue; + if (result == 2) + return 0; } switch( command ) { diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index ac78e8c84..ade685bf7 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -15,7 +15,7 @@ #include "common/db.h" #include "common/des.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mapindex.h" #include "common/mmo.h" #include "common/nullpo.h" @@ -85,57 +85,31 @@ struct HPM_atcommand_list { struct HPM_atcommand_list *atcommand_list = NULL; unsigned int atcommand_list_items = 0; -bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) { - /* record address */ - switch( type ) { +/** + * HPM plugin data store validator sub-handler (map-server) + * + * @see HPM_interface::data_store_validate + */ +bool HPM_map_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize) +{ + switch (type) { case HPDT_MSD: - ret->HPDataSRCPtr = (void**)(&((struct map_session_data *)ptr)->hdata); - ret->hdatac = &((struct map_session_data *)ptr)->hdatac; - break; case HPDT_NPCD: - ret->HPDataSRCPtr = (void**)(&((struct npc_data *)ptr)->hdata); - ret->hdatac = &((struct npc_data *)ptr)->hdatac; - break; case HPDT_MAP: - ret->HPDataSRCPtr = (void**)(&((struct map_data *)ptr)->hdata); - ret->hdatac = &((struct map_data *)ptr)->hdatac; - break; case HPDT_PARTY: - ret->HPDataSRCPtr = (void**)(&((struct party_data *)ptr)->hdata); - ret->hdatac = &((struct party_data *)ptr)->hdatac; - break; case HPDT_GUILD: - ret->HPDataSRCPtr = (void**)(&((struct guild *)ptr)->hdata); - ret->hdatac = &((struct guild *)ptr)->hdatac; - break; case HPDT_INSTANCE: - ret->HPDataSRCPtr = (void**)(&((struct instance_data *)ptr)->hdata); - ret->hdatac = &((struct instance_data *)ptr)->hdatac; - break; case HPDT_MOBDB: - ret->HPDataSRCPtr = (void**)(&((struct mob_db *)ptr)->hdata); - ret->hdatac = &((struct mob_db *)ptr)->hdatac; - break; case HPDT_MOBDATA: - ret->HPDataSRCPtr = (void**)(&((struct mob_data *)ptr)->hdata); - ret->hdatac = &((struct mob_data *)ptr)->hdatac; - break; case HPDT_ITEMDATA: - ret->HPDataSRCPtr = (void**)(&((struct item_data *)ptr)->hdata); - ret->hdatac = &((struct item_data *)ptr)->hdatac; - break; case HPDT_BGDATA: - ret->HPDataSRCPtr = (void**)(&((struct battleground_data *)ptr)->hdata); - ret->hdatac = &((struct battleground_data *)ptr)->hdatac; - break; case HPDT_AUTOTRADE_VEND: - ret->HPDataSRCPtr = (void**)(&((struct autotrade_vending *)ptr)->hdata); - ret->hdatac = &((struct autotrade_vending *)ptr)->hdatac; - break; + // Initialized by the caller. + return true; default: - return false; + break; } - return true; + return false; } void HPM_map_plugin_load_sub(struct hplugin *plugin) { @@ -188,7 +162,7 @@ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned in void HPM_map_do_init(void) { HPM->load_sub = HPM_map_plugin_load_sub; - HPM->grabHPDataSub = HPM_map_grabHPData; + HPM->data_store_validate_sub = HPM_map_data_store_validate; HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer); HPM_shared_symbols(SERVER_TYPE_MAP); } diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h index 00a8f43c3..b1957b139 100644 --- a/src/map/HPMmap.h +++ b/src/map/HPMmap.h @@ -15,7 +15,7 @@ struct hplugin; struct map_session_data; -bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr); +bool HPM_map_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize); bool HPM_map_add_atcommand(char *name, AtCommandFunc func); void HPM_map_atcommands(void); diff --git a/src/map/atcommand.c b/src/map/atcommand.c index beeccaddd..ff88f2c63 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -41,7 +41,7 @@ #include "common/cbasetypes.h" #include "common/conf.h" #include "common/core.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" // MAX_CARTS #include "common/nullpo.h" #include "common/random.h" @@ -242,16 +242,16 @@ ACMD(send) }\ } while(0) //define GET_VALUE - if (type > 0 && type < MAX_PACKET_DB) { + if (type >= MIN_PACKET_DB && type <= MAX_PACKET_DB) { int off = 2; if (len) { // show packet length - safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,904), type, packet_db[type].len); // Packet 0x%x length: %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,904), type, clif->packet(type)->len); // Packet 0x%x length: %d clif->message(fd, atcmd_output); return true; } - len=packet_db[type].len; + len = clif->packet(type)->len; if (len == 0) { // unknown packet - ERROR safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,905), type); // Unknown packet: 0x%x @@ -402,7 +402,7 @@ ACMD(send) SKIP_VALUE(message); } - if(packet_db[type].len == -1) {// send dynamic packet + if (clif->packet(type)->len == -1) { // send dynamic packet WFIFOW(sd->fd,2)=TOW(off); WFIFOSET(sd->fd,off); } else {// send static packet @@ -967,65 +967,64 @@ ACMD(hide) { /*========================================== * Changes a character's class *------------------------------------------*/ -ACMD(jobchange) { +ACMD(jobchange) +{ int job = 0, upper = 0; - const char* text; - - if (!*message || sscanf(message, "%12d %12d", &job, &upper) < 1) { - upper = 0; - - if (*message) { - int i; - bool found = false; + bool found = false; - // Normal Jobs - for( i = JOB_NOVICE; i < JOB_MAX_BASIC && !found; i++ ) { - if (strncmpi(message, pc->job_name(i), 16) == 0) { - job = i; - found = true; - } - } + if (*message == '\0') { // No message, just show the list + found = false; + } else if (sscanf(message, "%12d %12d", &job, &upper) >= 1) { // Numeric job ID + found = true; + } else { // Job name + int i; - // High Jobs, Babies and Third - for( i = JOB_NOVICE_HIGH; i < JOB_MAX && !found; i++ ){ - if (strncmpi(message, pc->job_name(i), 16) == 0) { - job = i; - found = true; - } + // Normal Jobs + for (i = JOB_NOVICE; !found && i < JOB_MAX_BASIC; i++) { + if (strncmpi(message, pc->job_name(i), 16) == 0) { + job = i; + found = true; + break; } + } - if (!found) { - text = atcommand_help_string(info); - if (text) - clif->messageln(fd, text); - return false; + // High Jobs, Babies and Third + for (i = JOB_NOVICE_HIGH; !found && i < JOB_MAX; i++) { + if (strncmpi(message, pc->job_name(i), 16) == 0) { + job = i; + found = true; + break; } } } - /* WHY DO WE LIST THEM THEN? */ + + if (!found || !pc->db_checkid(job)) { + const char *text = atcommand_help_string(info); + if (text) + clif->messageln(fd, text); + return false; + } + // Deny direct transformation into dummy jobs - if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2 || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER - || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2 || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2 || job == JOB_STAR_GLADIATOR2 - || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2) + if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2 + || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER + || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2 + || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2 + || job == JOB_STAR_GLADIATOR2 + || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) + || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2) ) { + /* WHY DO WE LIST THEM THEN? */ clif->message(fd, msg_fd(fd,923)); //"You can not change to this job by command." return true; } - if (pc->db_checkid(job)) { - if (pc->jobchange(sd, job, upper) == 0) - clif->message(fd, msg_fd(fd,12)); // Your job has been changed. - else { - clif->message(fd, msg_fd(fd,155)); // You are unable to change your job. - return false; - } - } else { - text = atcommand_help_string(info); - if (text) - clif->messageln(fd, text); + if (pc->jobchange(sd, job, upper) != 0) { + clif->message(fd, msg_fd(fd,155)); // You are unable to change your job. return false; } + clif->message(fd, msg_fd(fd,12)); // Your job has been changed. return true; } diff --git a/src/map/battle.c b/src/map/battle.c index e2f85e988..be508dae0 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -26,7 +26,7 @@ #include "common/HPM.h" #include "common/cbasetypes.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -2814,7 +2814,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam } if( sc->data[SC__MAELSTROM] && (flag&BF_MAGIC) && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL) ) { // {(Maelstrom Skill LevelxAbsorbed Skill Level)+(Caster's Job/5)}/2 - int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + sd->status.job_level / 5) / 2; + int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + (sd ? sd->status.job_level / 5 : 0)) / 2; status->heal(bl, 0, sp, 3); d->dmg_lv = ATK_BLOCK; return 0; @@ -7157,14 +7157,14 @@ void Hercules_report(char* date, char *time_c) { C_RENEWAL_EDP = 0x0400, C_RENEWAL_ASPD = 0x0800, C_SECURE_NPCTIMEOUT = 0x1000, - C_SQL_DB_ITEM = 0x2000, + //C_SQL_DB_ITEM = 0x2000, C_SQL_LOGS = 0x4000, C_MEMWATCH = 0x8000, C_DMALLOC = 0x10000, C_GCOLLECT = 0x20000, C_SEND_SHORTLIST = 0x40000, - C_SQL_DB_MOB = 0x80000, - C_SQL_DB_MOBSKILL = 0x100000, + //C_SQL_DB_MOB = 0x80000, + //C_SQL_DB_MOBSKILL = 0x100000, C_PACKETVER_RE = 0x200000, }; @@ -7229,13 +7229,6 @@ void Hercules_report(char* date, char *time_c) { #endif /* non-define part */ - if( map->db_use_sql_item_db ) - config |= C_SQL_DB_ITEM; - if( map->db_use_sql_mob_db ) - config |= C_SQL_DB_MOB; - if( map->db_use_sql_mob_skill_db ) - config |= C_SQL_DB_MOBSKILL; - if( logs->config.sql_logs ) config |= C_SQL_LOGS; diff --git a/src/map/battleground.c b/src/map/battleground.c index 5df05d301..cc5384d21 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -21,7 +21,7 @@ #include "common/cbasetypes.h" #include "common/conf.h" #include "common/HPM.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/socket.h" @@ -880,17 +880,9 @@ void do_init_battleground(bool minimal) { */ int bg_team_db_final(DBKey key, DBData *data, va_list ap) { struct battleground_data* bgd = DB->data2ptr(data); - int i; - nullpo_ret(bgd); - for(i = 0; i < bgd->hdatac; i++ ) { - if( bgd->hdata[i]->flag.free ) { - aFree(bgd->hdata[i]->data); - } - aFree(bgd->hdata[i]); - } - if( bgd->hdata ) - aFree(bgd->hdata); - + + HPM->data_store_destroy(&bgd->hdata); + return 0; } diff --git a/src/map/battleground.h b/src/map/battleground.h index 094037f43..dcf92d6d8 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -10,7 +10,7 @@ #include "common/db.h" #include "common/mmo.h" // struct party -struct HPluginData; +struct hplugin_data_store; struct block_list; struct map_session_data; @@ -53,9 +53,7 @@ struct battleground_data { // Logout Event char logout_event[EVENT_NAME_LENGTH]; char die_event[EVENT_NAME_LENGTH]; - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; struct bg_arena { diff --git a/src/map/channel.c b/src/map/channel.c index 196e5f770..023d22c06 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -14,7 +14,7 @@ #include "common/cbasetypes.h" #include "common/conf.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" diff --git a/src/map/chat.c b/src/map/chat.c index 976b1ce8e..aaf34a6f9 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -14,7 +14,7 @@ #include "map/pc.h" #include "map/skill.h" // ext_skill_unit_onplace() #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/showmsg.h" diff --git a/src/map/chrif.c b/src/map/chrif.c index 1e376e3bc..62ef52dbd 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -26,7 +26,7 @@ #include "common/HPM.h" #include "common/cbasetypes.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/socket.h" @@ -1351,7 +1351,7 @@ void chrif_skillid2idx(int fd) { * *------------------------------------------*/ int chrif_parse(int fd) { - int packet_len, cmd, r; + int packet_len, cmd; // only process data from the char-server if ( fd != chrif->fd ) { @@ -1375,22 +1375,22 @@ int chrif_parse(int fd) { } } - while ( RFIFOREST(fd) >= 2 ) { - - if( HPM->packetsc[hpChrif_Parse] ) { - if( (r = HPM->parse_packets(fd,hpChrif_Parse)) ) { - if( r == 1 ) continue; - if( r == 2 ) return 0; - } + while (RFIFOREST(fd) >= 2) { + if (VECTOR_LENGTH(HPM->packets[hpChrif_Parse]) > 0) { + int result = HPM->parse_packets(fd,hpChrif_Parse); + if (result == 1) + continue; + if (result == 2) + return 0; } cmd = RFIFOW(fd,0); if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(chrif->packet_len_table) || chrif->packet_len_table[cmd-0x2af8] == 0) { - r = intif->parse(fd); // Passed on to the intif + int result = intif->parse(fd); // Passed on to the intif - if (r == 1) continue; // Treated in intif - if (r == 2) return 0; // Didn't have enough data (len==-1) + if (result == 1) continue; // Treated in intif + if (result == 2) return 0; // Didn't have enough data (len==-1) ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, cmd); sockt->eof(fd); diff --git a/src/map/clif.c b/src/map/clif.c index 0d25be0a6..d499cf67f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -42,7 +42,7 @@ #include "common/conf.h" #include "common/ers.h" #include "common/grfio.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" // NEW_CARTS #include "common/nullpo.h" #include "common/random.h" @@ -10130,6 +10130,9 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) clif->message(fd, msg_fd(fd,1402)); } return; + } else if (strcmpi(&chname[1], channel->config->ally_name) == 0) { + clif->message(fd, msg_fd(fd,1294)); // You're not allowed to talk on this channel + return; } } @@ -18362,7 +18365,7 @@ void clif_openmergeitem(int fd, struct map_session_data *sd) for (i = 0; i < MAX_INVENTORY; i++) { struct item *item_data = &sd->status.inventory[i]; - if (item_data->nameid == 0 || !itemdb->isstackable(item_data->nameid)) + if (item_data->nameid == 0 || !itemdb->isstackable(item_data->nameid) || item_data->bound != IBT_NONE) continue; merge_items[n].nameid = item_data->nameid; @@ -18436,7 +18439,7 @@ void clif_ackmergeitems(int fd, struct map_session_data *sd) it = &sd->status.inventory[idx]; - if (it->nameid == 0 || !itemdb->isstackable(it->nameid)) + if (it->nameid == 0 || !itemdb->isstackable(it->nameid) || it->bound != IBT_NONE) continue; if (nameid == 0) @@ -18578,12 +18581,12 @@ int clif_parse(int fd) { if (RFIFOREST(fd) < 2) return 0; - if( HPM->packetsc[hpClif_Parse] ) { - int r; - if( (r = HPM->parse_packets(fd,hpClif_Parse)) ) { - if( r == 1 ) continue; - if( r == 2 ) return 0; - } + if (VECTOR_LENGTH(HPM->packets[hpClif_Parse]) > 0) { + int result = HPM->parse_packets(fd,hpClif_Parse); + if (result == 1) + continue; + if (result == 2) + return 0; } if( sd ) @@ -18680,6 +18683,19 @@ int clif_parse(int fd) { return 0; } +/** + * Returns information about the given packet ID. + * + * @param packet_id The packet ID. + * @return The corresponding packet_db entry, if any. + */ +const struct s_packet_db *clif_packet(int packet_id) +{ + if (packet_id < MIN_PACKET_DB || packet_id > MAX_PACKET_DB || packet_db[packet_id].len == 0) + return NULL; + return &packet_db[packet_id]; +} + static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...) { va_list va; int i; @@ -18815,6 +18831,7 @@ void clif_defaults(void) { clif->parse = clif_parse; clif->parse_cmd = clif_parse_cmd_optional; clif->decrypt_cmd = clif_decrypt_cmd; + clif->packet = clif_packet; /* auth */ clif->authok = clif_authok; clif->authrefuse = clif_authrefuse; diff --git a/src/map/clif.h b/src/map/clif.h index f6f0d4fe7..40610b7c1 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -597,6 +597,7 @@ struct clif_interface { int (*send_sub) (struct block_list *bl, va_list ap); int (*send_actual) (int fd, void *buf, int len); int (*parse) (int fd); + const struct s_packet_db *(*packet) (int packet_id); unsigned short (*parse_cmd) ( int fd, struct map_session_data *sd ); unsigned short (*decrypt_cmd) ( int cmd, struct map_session_data *sd ); /* auth */ @@ -1323,11 +1324,6 @@ struct clif_interface { }; #ifdef HERCULES_CORE -/** - * Vars - **/ -extern struct s_packet_db packet_db[MAX_PACKET_DB + 1]; - void clif_defaults(void); #endif // HERCULES_CORE diff --git a/src/map/elemental.c b/src/map/elemental.c index b629275e5..1ab93f6c5 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -26,7 +26,7 @@ #include "map/trade.h" #include "map/unit.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/random.h" diff --git a/src/map/guild.c b/src/map/guild.c index 7a187b625..6360e3e1f 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -23,7 +23,7 @@ #include "common/HPM.h" #include "common/cbasetypes.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mapindex.h" #include "common/nullpo.h" #include "common/showmsg.h" @@ -1763,16 +1763,7 @@ int guild_broken(int guild_id,int flag) if( g->instance ) aFree(g->instance); - if( g->hdata ) - { - for( i = 0; i < g->hdatac; i++ ) { - if( g->hdata[i]->flag.free ) { - aFree(g->hdata[i]->data); - } - aFree(g->hdata[i]); - } - aFree(g->hdata); - } + HPM->data_store_destroy(&g->hdata); idb_remove(guild->db,guild_id); return 0; @@ -2250,7 +2241,6 @@ void do_init_guild(bool minimal) { void do_final_guild(void) { DBIterator *iter = db_iterator(guild->db); struct guild *g; - int i; for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) { if( g->channel != NULL ) @@ -2259,16 +2249,7 @@ void do_final_guild(void) { aFree(g->instance); g->instance = NULL; } - if( g->hdata ) - { - for( i = 0; i < g->hdatac; i++ ) { - if( g->hdata[i]->flag.free ) { - aFree(g->hdata[i]->data); - } - aFree(g->hdata[i]); - } - aFree(g->hdata); - } + HPM->data_store_destroy(&g->hdata); } dbi_destroy(iter); diff --git a/src/map/homunculus.c b/src/map/homunculus.c index d0a4f6679..874d26fdb 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -27,7 +27,7 @@ #include "map/trade.h" #include "map/unit.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/random.h" diff --git a/src/map/instance.c b/src/map/instance.c index 300247fe7..545ffe1e7 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -17,7 +17,7 @@ #include "common/HPM.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/socket.h" @@ -588,19 +588,7 @@ void instance_destroy(int instance_id) { instance->list[instance_id].state = INSTANCE_FREE; instance->list[instance_id].num_map = 0; - if (instance->list[instance_id].hdata) - { - for( j = 0; j < instance->list[instance_id].hdatac; j++ ) { - if( instance->list[instance_id].hdata[j]->flag.free ) { - aFree(instance->list[instance_id].hdata[j]->data); - } - aFree(instance->list[instance_id].hdata[j]); - } - aFree(instance->list[instance_id].hdata); - } - - instance->list[instance_id].hdata = NULL; - instance->list[instance_id].hdatac = 0; + HPM->data_store_destroy(&instance->list[instance_id].hdata); } /*-------------------------------------- diff --git a/src/map/instance.h b/src/map/instance.h index 589e1a511..058cd2c3d 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -9,7 +9,7 @@ #include "common/hercules.h" #include "common/mmo.h" // struct point -struct HPluginData; +struct hplugin_data_store; struct block_list; struct map_session_data; @@ -52,10 +52,7 @@ struct instance_data { unsigned int original_progress_timeout; struct point respawn; ///< reload spawn - - /** HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; struct instance_interface { diff --git a/src/map/intif.c b/src/map/intif.c index 1795055c4..1664a8a09 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -22,7 +22,7 @@ #include "map/pet.h" #include "map/quest.h" #include "map/storage.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/socket.h" diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index f89bd2f1c..164242ff8 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -10,7 +10,7 @@ #include "map/map.h" #include "map/pc.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/random.h" #include "common/showmsg.h" #include "common/socket.h" diff --git a/src/map/itemdb.c b/src/map/itemdb.c index ccedee72a..efa9b18e5 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -14,7 +14,7 @@ #include "map/script.h" // item script processing #include "common/HPM.h" #include "common/conf.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -1502,112 +1502,8 @@ void itemdb_readdb_additional_fields(int itemid, config_setting_t *it, int n, co } /** - * Processes one itemdb entry from the sql backend, loading and inserting it - * into the item database. - * - * @param *handle MySQL connection handle. It is expected to have data - * available (i.e. already queried) and it won't be freed (it - * is care of the caller to do so) - * @param n Ordinal number of the entry, to be displayed in case of - * validation errors. - * @param *source Source of the entry (table name), to be displayed in case of - * validation errors. - * @return Nameid of the validated entry, or 0 in case of failure. - */ -int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) { - struct item_data id = { 0 }; - char *data = NULL; - - /* - * `id` smallint(5) unsigned NOT NULL DEFAULT '0' - * `name_english` varchar(50) NOT NULL DEFAULT '' - * `name_japanese` varchar(50) NOT NULL DEFAULT '' - * `type` tinyint(2) unsigned NOT NULL DEFAULT '0' - * `price_buy` mediumint(10) DEFAULT NULL - * `price_sell` mediumint(10) DEFAULT NULL - * `weight` smallint(5) unsigned DEFAULT NULL - * `atk` smallint(5) unsigned DEFAULT NULL - * `matk` smallint(5) unsigned DEFAULT NULL - * `defence` smallint(5) unsigned DEFAULT NULL - * `range` tinyint(2) unsigned DEFAULT NULL - * `slots` tinyint(2) unsigned DEFAULT NULL - * `equip_jobs` int(12) unsigned DEFAULT NULL - * `equip_upper` tinyint(8) unsigned DEFAULT NULL - * `equip_genders` tinyint(2) unsigned DEFAULT NULL - * `equip_locations` smallint(4) unsigned DEFAULT NULL - * `weapon_level` tinyint(2) unsigned DEFAULT NULL - * `equip_level_min` smallint(5) unsigned DEFAULT NULL - * `equip_level_max` smallint(5) unsigned DEFAULT NULL - * `refineable` tinyint(1) unsigned DEFAULT NULL - * `view` smallint(3) unsigned DEFAULT NULL - * `bindonequip` tinyint(1) unsigned DEFAULT NULL - * `buyingstore` tinyint(1) NOT NULL DEFAULT NULL - * `delay` mediumint(9) NOT NULL DEFAULT NULL - * `trade_flag` smallint(4) NOT NULL DEFAULT NULL - * `trade_group` smallint(4) NOT NULL DEFAULT NULL - * `nouse_flag` smallint(4) NOT NULL DEFAULT NULL - * `nouse_group` smallint(4) NOT NULL DEFAULT NULL - * `stack_amount` mediumint(6) NOT NULL DEFAULT NULL - * `stack_flag` smallint(2) NOT NULL DEFAULT NULL - * `sprite` mediumint(6) NOT NULL DEFAULT NULL - * `script` text - * `equip_script` text - * `unequip_script` text - */ - SQL->GetData(handle, 0, &data, NULL); id.nameid = (uint16)atoi(data); - SQL->GetData(handle, 1, &data, NULL); safestrncpy(id.name, data, sizeof(id.name)); - SQL->GetData(handle, 2, &data, NULL); safestrncpy(id.jname, data, sizeof(id.jname)); - SQL->GetData(handle, 3, &data, NULL); id.type = atoi(data); - SQL->GetData(handle, 4, &data, NULL); id.value_buy = data ? atoi(data) : -1; // Using invalid price -1 when missing, it'll be validated later - SQL->GetData(handle, 5, &data, NULL); id.value_sell = data ? atoi(data) : -1; - SQL->GetData(handle, 6, &data, NULL); id.weight = data ? atoi(data) : 0; - SQL->GetData(handle, 7, &data, NULL); id.atk = data ? atoi(data) : 0; - SQL->GetData(handle, 8, &data, NULL); id.matk = data ? atoi(data) : 0; - SQL->GetData(handle, 9, &data, NULL); id.def = data ? atoi(data) : 0; - SQL->GetData(handle, 10, &data, NULL); id.range = data ? atoi(data) : 0; - SQL->GetData(handle, 11, &data, NULL); id.slot = data ? atoi(data) : 0; - SQL->GetData(handle, 12, &data, NULL); itemdb->jobid2mapid(id.class_base, data ? (unsigned int)strtoul(data,NULL,0) : UINT_MAX); - SQL->GetData(handle, 13, &data, NULL); id.class_upper = data ? (unsigned int)atoi(data) : ITEMUPPER_ALL; - SQL->GetData(handle, 14, &data, NULL); id.sex = data ? atoi(data) : 2; - SQL->GetData(handle, 15, &data, NULL); id.equip = data ? atoi(data) : 0; - SQL->GetData(handle, 16, &data, NULL); id.wlv = data ? atoi(data) : 0; - SQL->GetData(handle, 17, &data, NULL); id.elv = data ? atoi(data) : 0; - SQL->GetData(handle, 18, &data, NULL); id.elvmax = data ? atoi(data) : 0; - SQL->GetData(handle, 19, &data, NULL); id.flag.no_refine = data && atoi(data) ? 0 : 1; - SQL->GetData(handle, 20, &data, NULL); id.look = data ? atoi(data) : 0; - SQL->GetData(handle, 21, &data, NULL); id.flag.bindonequip = data && atoi(data) ? 1 : 0; - SQL->GetData(handle, 22, &data, NULL); id.flag.force_serial = data && atoi(data) ? 1 : 0; - SQL->GetData(handle, 23, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0; - SQL->GetData(handle, 24, &data, NULL); id.delay = data ? atoi(data) : 0; - SQL->GetData(handle, 25, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE; - SQL->GetData(handle, 26, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0; - SQL->GetData(handle, 27, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE; - SQL->GetData(handle, 28, &data, NULL); id.item_usage.override = data ? atoi(data) : 0; - SQL->GetData(handle, 29, &data, NULL); id.stack.amount = data ? atoi(data) : 0; - SQL->GetData(handle, 30, &data, NULL); - if (data) { - int stack_flag = atoi(data); - id.stack.inventory = (stack_flag&1)!=0; - id.stack.cart = (stack_flag&2)!=0; - id.stack.storage = (stack_flag&4)!=0; - id.stack.guildstorage = (stack_flag&8)!=0; - } - SQL->GetData(handle, 31, &data, NULL); - if (data) { - id.view_id = atoi(data); - if (id.view_id) - id.flag.available = 1; - } - SQL->GetData(handle, 32, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; - SQL->GetData(handle, 33, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; - SQL->GetData(handle, 34, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; - - return itemdb->validate_entry(&id, n, source); -} - -/** - * Processes one itemdb entry from the sql backend, loading and inserting it - * into the item database. + * Processes one itemdb entry from the libconfig backend, loading and inserting + * it into the item database. * * @param *it Libconfig setting entry. It is expected to be valid and it * won't be freed (it is care of the caller to do so if @@ -1974,45 +1870,6 @@ int itemdb_readdb_libconfig(const char *filename) { return count; } -/** - * Reads from a sql itemdb table and inserts the found entries into the item - * database, overwriting duplicate ones (i.e. item_db2 overriding item_db.) - * - * @param *tablename Table name to query. - * @return The number of found entries. - */ -int itemdb_readdb_sql(const char *tablename) { - int i = 0, count = 0; - - // retrieve all rows from the item database - if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `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`, `bindonequip`, `forceserial`, `buyingstore`, `delay`," - " `trade_flag`, `trade_group`, `nouse_flag`, `nouse_group`," - " `stack_amount`, `stack_flag`, `sprite`, `script`," - " `equip_script`, `unequip_script`" - "FROM `%s`", tablename) ) { - Sql_ShowDebug(map->mysql_handle); - return 0; - } - - // process rows one by one - while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) { - if( itemdb->readdb_sql_sub(map->mysql_handle, i++, tablename) ) - count++; - } - - // free the query result - SQL->FreeResult(map->mysql_handle); - - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, tablename); - - return count; -} - /*========================================== * Unique item ID function * Only one operation by once @@ -2029,22 +1886,12 @@ void itemdb_read(bool minimal) { int i; DBData prev; - if (map->db_use_sql_item_db) { - const char* item_db_name[] = { - map->item_db_db, - map->item_db2_db - }; - for(i = 0; i < ARRAYLENGTH(item_db_name); i++) - itemdb->readdb_sql(item_db_name[i]); - } else { - const char* filename[] = { - DBPATH"item_db.conf", - "item_db2.conf", - }; - - for(i = 0; i < ARRAYLENGTH(filename); i++) - itemdb->readdb_libconfig(filename[i]); - } + const char *filename[] = { + DBPATH"item_db.conf", + "item_db2.conf", + }; + for (i = 0; i < ARRAYLENGTH(filename); i++) + itemdb->readdb_libconfig(filename[i]); for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) { if( itemdb->array[i] ) { @@ -2100,17 +1947,7 @@ void destroy_item_data(struct item_data* self, int free_self) script->free_code(self->unequip_script); if( self->combos ) aFree(self->combos); - if (self->hdata) - { - int i; - for (i = 0; i < self->hdatac; i++ ) { - if (self->hdata[i]->flag.free ) { - aFree(self->hdata[i]->data); - } - aFree(self->hdata[i]); - } - aFree(self->hdata); - } + HPM->data_store_destroy(&self->hdata); #if defined(DEBUG) // trash item memset(self, 0xDD, sizeof(struct item_data)); @@ -2369,10 +2206,8 @@ void itemdb_defaults(void) { itemdb->gendercheck = itemdb_gendercheck; itemdb->validate_entry = itemdb_validate_entry; itemdb->readdb_additional_fields = itemdb_readdb_additional_fields; - itemdb->readdb_sql_sub = itemdb_readdb_sql_sub; itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub; itemdb->readdb_libconfig = itemdb_readdb_libconfig; - itemdb->readdb_sql = itemdb_readdb_sql; itemdb->unique_id = itemdb_unique_id; itemdb->read = itemdb_read; itemdb->destroy_item_data = destroy_item_data; diff --git a/src/map/itemdb.h b/src/map/itemdb.h index a3edd451e..7b35e1ae1 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -10,9 +10,9 @@ #include "common/conf.h" #include "common/db.h" #include "common/mmo.h" // ITEM_NAME_LENGTH -#include "common/sql.h" struct script_code; +struct hplugin_data_store; /** * Defines @@ -488,10 +488,7 @@ struct item_data { /* TODO add a pointer to some sort of (struct extra) and gather all the not-common vals into it to save memory */ struct item_group *group; struct item_package *package; - - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; #define itemdb_name(n) (itemdb->search(n)->name) @@ -604,10 +601,8 @@ struct itemdb_interface { int (*gendercheck) (struct item_data *id); int (*validate_entry) (struct item_data *entry, int n, const char *source); void (*readdb_additional_fields) (int itemid, config_setting_t *it, 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_libconfig) (const char *filename); - int (*readdb_sql) (const char *tablename); uint64 (*unique_id) (struct map_session_data *sd); void (*read) (bool minimal); void (*destroy_item_data) (struct item_data *self, int free_self); diff --git a/src/map/map.c b/src/map/map.c index fe0922063..cd2ba17c2 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -48,7 +48,7 @@ #include "common/core.h" #include "common/ers.h" #include "common/grfio.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -3239,16 +3239,7 @@ void do_final_maps(void) { if( map->list[i].qi_data ) aFree(map->list[i].qi_data); - if( map->list[i].hdata ) - { - for( v = 0; v < map->list[i].hdatac; v++ ) { - if( map->list[i].hdata[v]->flag.free ) { - aFree(map->list[i].hdata[v]->data); - } - aFree(map->list[i].hdata[v]); - } - aFree(map->list[i].hdata); - } + HPM->data_store_destroy(&map->list[i].hdata); } map->zone_db_clear(); @@ -3711,21 +3702,8 @@ int inter_config_read(char *cfgName) { if (sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2) < 2) continue; - /* table names */ - if(strcmpi(w1,"item_db_db")==0) - safestrncpy(map->item_db_db, w2, sizeof(map->item_db_db)); - else if(strcmpi(w1,"mob_db_db")==0) - safestrncpy(map->mob_db_db, w2, sizeof(map->mob_db_db)); - else if(strcmpi(w1,"item_db2_db")==0) - safestrncpy(map->item_db2_db, w2, sizeof(map->item_db2_db)); - else if(strcmpi(w1,"mob_db2_db")==0) - safestrncpy(map->mob_db2_db, w2, sizeof(map->mob_db2_db)); - else if(strcmpi(w1, "mob_skill_db_db") == 0) - safestrncpy(map->mob_skill_db_db, w2, sizeof(map->mob_skill_db_db)); - else if(strcmpi(w1,"mob_skill_db2_db")==0) - safestrncpy(map->mob_skill_db2_db, w2, sizeof(map->mob_skill_db2_db)); /* map sql stuff */ - else if(strcmpi(w1,"map_server_ip")==0) + if(strcmpi(w1,"map_server_ip")==0) safestrncpy(map->server_ip, w2, sizeof(map->server_ip)); else if(strcmpi(w1,"map_server_port")==0) map->server_port=atoi(w2); @@ -3737,42 +3715,6 @@ int inter_config_read(char *cfgName) { safestrncpy(map->server_db, w2, sizeof(map->server_db)); else if(strcmpi(w1,"default_codepage")==0) safestrncpy(map->default_codepage, w2, sizeof(map->default_codepage)); - else if(strcmpi(w1,"use_sql_item_db")==0) { - map->db_use_sql_item_db = config_switch(w2); - ShowStatus ("Using item database as SQL: '%s'\n", w2); - if (map->db_use_sql_item_db) { - // Deprecated 2015-08-09 [Haru] - ShowWarning("Support for the SQL item database is deprecated and it will removed in future versions. " - "Please upgrade to the non-sql version as soon as possible. " - "Bug reports or pull requests concerning the SQL item database are no longer accepted.\n"); - ShowInfo("Resuming in 10 seconds...\n"); - HSleep(10); - } - } - else if(strcmpi(w1,"use_sql_mob_db")==0) { - map->db_use_sql_mob_db = config_switch(w2); - ShowStatus ("Using monster database as SQL: '%s'\n", w2); - if (map->db_use_sql_mob_db) { - // Deprecated 2015-08-09 [Haru] - ShowWarning("Support for the SQL monster database is deprecated and it will removed in future versions. " - "Please upgrade to the non-sql version as soon as possible. " - "Bug reports or pull requests concerning the SQL monster database are no longer accepted.\n"); - ShowInfo("Resuming in 10 seconds...\n"); - HSleep(10); - } - } - else if(strcmpi(w1,"use_sql_mob_skill_db")==0) { - map->db_use_sql_mob_skill_db = config_switch(w2); - ShowStatus ("Using monster skill database as SQL: '%s'\n", w2); - if (map->db_use_sql_mob_skill_db) { - // Deprecated 2015-08-09 [Haru] - ShowWarning("Support for the SQL monster skill database is deprecated and it will removed in future versions. " - "Please upgrade to the non-sql version as soon as possible. " - "Bug reports or pull requests concerning the SQL monster skill database are no longer accepted.\n"); - ShowInfo("Resuming in 10 seconds...\n"); - HSleep(10); - } - } else if(strcmpi(w1,"autotrade_merchants_db")==0) safestrncpy(map->autotrade_merchants_db, w2, sizeof(map->autotrade_merchants_db)); else if(strcmpi(w1,"autotrade_data_db")==0) @@ -3854,6 +3796,7 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone CREATE(zone, struct map_zone_data, 1); safestrncpy(zone->name, newzone, MAP_ZONE_NAME_LENGTH); + zone->merge_type = MZMT_NEVERMERGE; zone->disabled_skills_count = main->disabled_skills_count + other->disabled_skills_count; zone->disabled_items_count = main->disabled_items_count + other->disabled_items_count; zone->mapflags_count = main->mapflags_count + other->mapflags_count; @@ -3930,7 +3873,7 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone memcpy(zone->capped_skills[cursor], other->capped_skills[i], sizeof(struct map_zone_skill_damage_cap_entry)); } - zone->info.special = 2; + zone->info.merged = 1; strdb_put(map->zone_db, newzone, zone); return zone; } @@ -3941,13 +3884,13 @@ void map_zone_change2(int m, struct map_zone_data *zone) { if( map->list[m].zone == zone ) return; - if( map->list[m].zone->info.special != 2 ) /* we don't update it for merged zones! */ + if( !map->list[m].zone->info.merged ) /* we don't update it for merged zones! */ map->list[m].prev_zone = map->list[m].zone; if( map->list[m].zone_mf_count ) map->zone_remove(m); - if( zone->info.special ) { + if( zone->merge_type == MZMT_MERGEABLE && map->list[m].prev_zone->merge_type != MZMT_NEVERMERGE ) { zone = map->merge_zone(zone,map->list[m].prev_zone); } @@ -4899,12 +4842,15 @@ void read_map_zone_db(void) { /* is this the global template? */ if( strncmpi(zonename,MAP_ZONE_NORMAL_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) { zone = &map->zone_all; + zone->merge_type = MZMT_NEVERMERGE; is_all = true; } else if( strncmpi(zonename,MAP_ZONE_PK_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) { zone = &map->zone_pk; + zone->merge_type = MZMT_NEVERMERGE; is_all = true; } else { CREATE( zone, struct map_zone_data, 1 ); + zone->merge_type = MZMT_NORMAL; zone->disabled_skills_count = 0; zone->disabled_items_count = 0; } @@ -5257,11 +5203,11 @@ void read_map_zone_db(void) { /* post-load processing */ if( (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) ) - zone->info.special = 1; + zone->merge_type = MZMT_MERGEABLE; if( (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) ) - zone->info.special = 1; + zone->merge_type = MZMT_MERGEABLE; if( (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) ) - zone->info.special = 1; + zone->merge_type = MZMT_MERGEABLE; } /* not supposed to go in here but in skill_final whatever */ libconfig->destroy(&map_zone_db); @@ -5879,7 +5825,7 @@ int do_init(int argc, char *argv[]) map->nick_db = idb_alloc(DB_OPT_BASE); map->charid_db = idb_alloc(DB_OPT_BASE); map->regen_db = idb_alloc(DB_OPT_BASE); // efficient status_natural_heal processing - map->iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls + map->iwall_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls map->zone_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAP_ZONE_NAME_LENGTH); map->iterator_ers = ers_new(sizeof(struct s_mapiterator),"map.c::map_iterator_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); @@ -6024,17 +5970,6 @@ void map_defaults(void) { map->night_flag = 0; // 0=day, 1=night [Yor] map->enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex] - map->db_use_sql_item_db = 0; - map->db_use_sql_mob_db = 0; - map->db_use_sql_mob_skill_db = 0; - - sprintf(map->item_db_db, "item_db"); - sprintf(map->item_db2_db, "item_db2"); - sprintf(map->mob_db_db, "mob_db"); - sprintf(map->mob_db2_db, "mob_db2"); - sprintf(map->mob_skill_db_db, "mob_skill_db"); - sprintf(map->mob_skill_db2_db, "mob_skill_db2"); - map->INTER_CONF_NAME="conf/inter-server.conf"; map->LOG_CONF_NAME="conf/logs.conf"; map->MAP_CONF_NAME = "conf/map-server.conf"; diff --git a/src/map/map.h b/src/map/map.h index 39af13de8..974fbc4ba 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -19,6 +19,7 @@ struct mob_data; struct npc_data; struct channel_data; +struct hplugin_data_store; enum E_MAPSERVER_ST { MAPSERVER_ST_RUNNING = CORE_ST_LAST, @@ -549,6 +550,12 @@ struct map_zone_skill_damage_cap_entry { enum map_zone_skill_subtype subtype; }; +enum map_zone_merge_type { + MZMT_NORMAL = 0, ///< MZMT_MERGEABLE zones can merge *into* MZMT_NORMAL zones (but not the converse). + MZMT_MERGEABLE, ///< Can merge with other MZMT_MERGEABLE zones and *into* MZMT_NORMAL zones. + MZMT_NEVERMERGE, ///< Cannot merge with any zones. +}; + #define MAP_ZONE_NAME_LENGTH 60 #define MAP_ZONE_ALL_NAME "All" #define MAP_ZONE_NORMAL_NAME "Normal" @@ -560,6 +567,7 @@ struct map_zone_skill_damage_cap_entry { struct map_zone_data { char name[MAP_ZONE_NAME_LENGTH];/* 20'd */ + enum map_zone_merge_type merge_type; struct map_zone_disabled_skill_entry **disabled_skills; int disabled_skills_count; int *disabled_items; @@ -573,7 +581,7 @@ struct map_zone_data { struct map_zone_skill_damage_cap_entry **capped_skills; int capped_skills_count; struct { - unsigned int special : 2;/* 1: whether this is a mergeable zone; 2: whether it is a merged zone */ + unsigned int merged : 1; } info; }; @@ -729,10 +737,7 @@ struct map_data { /* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */ unsigned short hpmeter_visible; - - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; /// Stores information about a remote map (for multi-mapserver setups). @@ -853,16 +858,6 @@ struct map_interface { char *MSG_CONF_NAME; char *GRF_PATH_FILENAME; - int db_use_sql_item_db; - int db_use_sql_mob_db; - int db_use_sql_mob_skill_db; - - char item_db_db[32]; - char item_db2_db[32]; - char mob_db_db[32]; - char mob_db2_db[32]; - char mob_skill_db_db[32]; - char mob_skill_db2_db[32]; char autotrade_merchants_db[32]; char autotrade_data_db[32]; char npc_market_data_db[32]; diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 37c830e2e..93ac52f33 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -11,7 +11,7 @@ #include "common/cbasetypes.h" #include "common/db.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/showmsg.h" #include "common/sql.h" #include "common/strlib.h" diff --git a/src/map/mercenary.c b/src/map/mercenary.c index b26876d39..59a6f7a44 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -26,7 +26,7 @@ #include "map/trade.h" #include "map/unit.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/nullpo.h" #include "common/random.h" diff --git a/src/map/mob.c b/src/map/mob.c index 2fe9fe8fb..2b519462d 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -32,7 +32,7 @@ #include "common/cbasetypes.h" #include "common/db.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -3646,77 +3646,382 @@ void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust) *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; } } + /* (mob_parse_dbrow)_cap_value */ static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int value) { if( value > max ) { - ShowError("mob_parse_dbrow: for class '%d', field value '%d' is higher than the maximum '%d'! capping...\n", class_, value, max); + ShowError("mob_parse_dbrow_cap_value: for class '%d', field value '%d' is higher than the maximum '%d'! capping...\n", class_, value, max); return max; } else if ( value < min ) { - ShowError("mob_parse_dbrow: for class '%d', field value '%d' is lower than the minimum '%d'! capping...\n", class_, value, min); + ShowError("mob_parse_dbrow_cap_value: for class '%d', field value '%d' is lower than the minimum '%d'! capping...\n", class_, value, min); return min; } return value; } + +void mob_read_db_stats_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +{ + int i32; + if (mob->lookup_const(t, "Str", &i32) && i32 >= 0) { + mstatus->str = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + } + if (mob->lookup_const(t, "Agi", &i32) && i32 >= 0) { + mstatus->agi = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + } + if (mob->lookup_const(t, "Vit", &i32) && i32 >= 0) { + mstatus->vit = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + } + if (mob->lookup_const(t, "Int", &i32) && i32 >= 0) { + mstatus->int_ = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + } + if (mob->lookup_const(t, "Dex", &i32) && i32 >= 0) { + mstatus->dex = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + } + if (mob->lookup_const(t, "Luk", &i32) && i32 >= 0) { + mstatus->luk = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + } +} + +int mob_read_db_mode_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +{ + int mode = 0; + config_setting_t *t2; + + if ((t2 = libconfig->setting_get_member(t, "CanMove"))) + mode |= libconfig->setting_get_bool(t2) ? MD_CANMOVE : 0; + if ((t2 = libconfig->setting_get_member(t, "Looter"))) + mode |= libconfig->setting_get_bool(t2) ? MD_LOOTER : 0; + if ((t2 = libconfig->setting_get_member(t, "Aggressive"))) + mode |= libconfig->setting_get_bool(t2) ? MD_AGGRESSIVE : 0; + if ((t2 = libconfig->setting_get_member(t, "Assist"))) + mode |= libconfig->setting_get_bool(t2) ? MD_ASSIST : 0; + if ((t2 = libconfig->setting_get_member(t, "CastSensorIdle"))) + mode |= libconfig->setting_get_bool(t2) ? MD_CASTSENSOR_IDLE : 0; + if ((t2 = libconfig->setting_get_member(t, "Boss"))) + mode |= libconfig->setting_get_bool(t2) ? MD_BOSS : 0; + if ((t2 = libconfig->setting_get_member(t, "Plant"))) + mode |= libconfig->setting_get_bool(t2) ? MD_PLANT : 0; + if ((t2 = libconfig->setting_get_member(t, "CanAttack"))) + mode |= libconfig->setting_get_bool(t2) ? MD_CANATTACK : 0; + if ((t2 = libconfig->setting_get_member(t, "Detector"))) + mode |= libconfig->setting_get_bool(t2) ? MD_DETECTOR : 0; + if ((t2 = libconfig->setting_get_member(t, "CastSensorChase"))) + mode |= libconfig->setting_get_bool(t2) ? MD_CASTSENSOR_CHASE : 0; + if ((t2 = libconfig->setting_get_member(t, "ChangeChase"))) + mode |= libconfig->setting_get_bool(t2) ? MD_CHANGECHASE : 0; + if ((t2 = libconfig->setting_get_member(t, "Angry"))) + mode |= libconfig->setting_get_bool(t2) ? MD_ANGRY : 0; + if ((t2 = libconfig->setting_get_member(t, "ChangeTargetMelee"))) + mode |= libconfig->setting_get_bool(t2) ? MD_CHANGETARGET_MELEE : 0; + if ((t2 = libconfig->setting_get_member(t, "ChangeTargetChase"))) + mode |= libconfig->setting_get_bool(t2) ? MD_CHANGETARGET_CHASE : 0; + if ((t2 = libconfig->setting_get_member(t, "TargetWeak"))) + mode |= libconfig->setting_get_bool(t2) ? MD_TARGETWEAK : 0; + + return mode; +} + +void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +{ + config_setting_t *drop; + int i = 0; + int idx = 0; + int i32; + + while (idx < MAX_MVP_DROP && (drop = libconfig->setting_get_elem(t, i))) { + const char *name = config_setting_name(drop); + int rate_adjust = battle_config.item_rate_mvp; + struct item_data* id = itemdb->search_name(name); + int value = 0; + if (!id) + { + ShowWarning("mob_read_db: mvp drop item %s not found in monster %d\n", name, class_); + i ++; + continue; + } + if (mob->get_const(drop, &i32) && i32 >= 0) { + value = i32; + } + if (value <= 0) + { + ShowWarning("mob_read_db: wrong drop chance %d for mvp drop item %s in monster %d\n", value, name, class_); + i ++; + continue; + } + entry->mvpitem[idx].nameid = id->nameid; + if (!entry->mvpitem[idx].nameid) { + entry->mvpitem[idx].p = 0; //No item.... + i ++; + continue; + } + mob->item_dropratio_adjust(entry->mvpitem[idx].nameid, class_, &rate_adjust); + entry->mvpitem[idx].p = mob->drop_adjust(value, rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); + + //calculate and store Max available drop chance of the MVP item + if (entry->mvpitem[idx].p) { + if (id->maxchance == -1 || (id->maxchance < entry->mvpitem[idx].p/10 + 1) ) { + //item has bigger drop chance or sold in shops + id->maxchance = entry->mvpitem[idx].p/10 + 1; //reduce MVP drop info to not spoil common drop rate + } + } + i++; + idx++; + } + if (idx == MAX_MVP_DROP && libconfig->setting_get_elem(t, i)) { + ShowWarning("mob_read_db: Too many mvp drops in mob %d\n", class_); + } +} + +void mob_read_db_drops_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +{ + config_setting_t *drop; + int i = 0; + int idx = 0; + int i32; + int k; + + while (idx < MAX_MOB_DROP && (drop = libconfig->setting_get_elem(t, i))) { + const char *name = config_setting_name(drop); + int rate_adjust, type; + unsigned short ratemin, ratemax; + struct item_data* id = itemdb->search_name(name); + int value = 0; + if (!id) + { + ShowWarning("mob_read_db: drop item %s not found in monster %d\n", name, class_); + i ++; + continue; + } + if (mob->get_const(drop, &i32) && i32 >= 0) { + value = i32; + } + if (value <= 0) + { + ShowWarning("mob_read_db: wrong drop chance %d for drop item %s in monster %d\n", value, name, class_); + i ++; + continue; + } + + entry->dropitem[idx].nameid = id->nameid; + if (!entry->dropitem[idx].nameid) { + entry->dropitem[idx].p = 0; //No drop. + i ++; + continue; + } + type = id->type; + if ((class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946)) { + //Treasure box drop rates [Skotlex] + rate_adjust = battle_config.item_rate_treasure; + ratemin = battle_config.item_drop_treasure_min; + ratemax = battle_config.item_drop_treasure_max; + } + else switch (type) + { // Added support to restrict normal drops of MVP's [Reddozen] + case IT_HEALING: + rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal; + ratemin = battle_config.item_drop_heal_min; + ratemax = battle_config.item_drop_heal_max; + break; + case IT_USABLE: + case IT_CASH: + rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use; + ratemin = battle_config.item_drop_use_min; + ratemax = battle_config.item_drop_use_max; + break; + case IT_WEAPON: + case IT_ARMOR: + case IT_PETARMOR: + rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip; + ratemin = battle_config.item_drop_equip_min; + ratemax = battle_config.item_drop_equip_max; + break; + case IT_CARD: + rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card; + ratemin = battle_config.item_drop_card_min; + ratemax = battle_config.item_drop_card_max; + break; + default: + rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common; + ratemin = battle_config.item_drop_common_min; + ratemax = battle_config.item_drop_common_max; + break; + } + mob->item_dropratio_adjust(id->nameid, class_, &rate_adjust); + entry->dropitem[idx].p = mob->drop_adjust(value, rate_adjust, ratemin, ratemax); + + //calculate and store Max available drop chance of the item + if (entry->dropitem[idx].p && (class_ < 1324 || class_ > 1363) && (class_ < 1938 || class_ > 1946)) + { //Skip treasure chests. + if (id->maxchance == -1 || (id->maxchance < entry->dropitem[idx].p) ) { + id->maxchance = entry->dropitem[idx].p; //item has bigger drop chance or sold in shops + } + for (k = 0; k< MAX_SEARCH; k++) { + if (id->mob[k].chance <= entry->dropitem[idx].p) + break; + } + if (k == MAX_SEARCH) + { + i++; + idx++; + continue; + } + + if (id->mob[k].id != class_ && k != MAX_SEARCH - 1) + memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); + id->mob[k].chance = entry->dropitem[idx].p; + id->mob[k].id = class_; + } + i++; + idx++; + } + if (idx == MAX_MOB_DROP && libconfig->setting_get_elem(t, i)) { + ShowWarning("mob_read_db: Too many drops in mob %d\n", class_); + } +} + /*========================================== * processes one mobdb entry *------------------------------------------*/ -bool mob_parse_dbrow(char** str) { - struct mob_db *db, entry; +bool mob_read_db_sub(config_setting_t *mobt, int id, const char *source) +{ + struct mob_db *entry = NULL, tmpEntry; + config_setting_t *t = NULL; + int i32 = 0, value = 0, class_ = 0; struct status_data *mstatus; - int class_, i; - double exp, maxhp; struct mob_data data; - - class_ = atoi(str[0]); + const char *str = NULL; + double maxhp; + double exp; + bool inherit = false; + bool range2Updated = false; + bool range3Updated = false; + bool dmotionUpdated = false; + bool maxhpUpdated = false; + bool maxspUpdated = false; + + entry = &tmpEntry; + if (!libconfig->setting_lookup_int(mobt, "Id", &class_)) { + ShowWarning("mob_read_db_sub: Missing id in \"%s\", entry #%d, skipping.\n", source, class_); + return false; + } if (class_ <= 1000 || class_ > MAX_MOB_DB) { - ShowError("mob_parse_dbrow: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB); + ShowError("mob_read_db_sub: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB); return false; } if (pc->db_checkid(class_)) { - ShowError("mob_parse_dbrow: Invalid monster ID %d, reserved for player classes.\n", class_); + ShowError("mob_read_db_sub: Invalid monster ID %d, reserved for player classes.\n", class_); return false; } if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) { - ShowError("mob_parse_dbrow: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); + ShowError("mob_read_db_sub: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); return false; } - memset(&entry, 0, sizeof(entry)); + if ((t = libconfig->setting_get_member(mobt, "Inherit")) && (inherit = libconfig->setting_get_bool(t))) { + if (!mob->db_data[class_]) { + ShowWarning("mob_read_db_sub: Trying to inherit nonexistent mob %d, default values will be used instead.\n", class_); + inherit = false; + } else { + // Use old entry as default + struct mob_db *old_entry = mob->db_data[class_]; + memcpy(entry, old_entry, sizeof(struct mob_db)); + inherit = true; + } + } + if (!inherit) { + memset(&tmpEntry, 0, sizeof(tmpEntry)); + } - db = &entry; - mstatus = &db->status; + mstatus = &entry->status; - db->vd.class_ = class_; - safestrncpy(db->sprite, str[1], sizeof(db->sprite)); - safestrncpy(db->jname, str[2], sizeof(db->jname)); - safestrncpy(db->name, str[3], sizeof(db->name)); - db->lv = atoi(str[4]); - db->lv = cap_value(db->lv, 1, USHRT_MAX); - mstatus->max_hp = atoi(str[5]); - mstatus->max_sp = atoi(str[6]); + entry->vd.class_ = class_; - exp = (double)atoi(str[7]) * (double)battle_config.base_exp_rate / 100.; - db->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + if (!libconfig->setting_lookup_string(mobt, "SpriteName", &str) || !*str ) { + if (!inherit) { + ShowWarning("mob_read_db_sub: Missing SpriteName in mob %d of \"%s\", skipping.\n", class_, source); + return false; + } + } else { + safestrncpy(entry->sprite, str, sizeof(entry->sprite)); + } - exp = (double)atoi(str[8]) * (double)battle_config.job_exp_rate / 100.; - db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + if (!libconfig->setting_lookup_string(mobt, "Name", &str) || !*str ) { + if (!inherit) { + ShowWarning("mob_read_db_sub: Missing Name in mob %d of \"%s\", skipping.\n", class_, source); + return false; + } + } else { + safestrncpy(entry->name, str, sizeof(entry->name)); + safestrncpy(entry->jname, str, sizeof(entry->jname)); + } + + if (mob->lookup_const(mobt, "Lv", &i32) && i32 >= 0) { + entry->lv = i32; + entry->lv = cap_value(entry->lv, 1, USHRT_MAX); + } else if (!inherit) { + entry->lv = 1; + } + + if (mob->lookup_const(mobt, "Hp", &i32) && i32 >= 0) { + mstatus->max_hp = i32; + maxhpUpdated = true; + } else if (!inherit) { + mstatus->max_hp = 1; + maxhpUpdated = true; + } + + if (mob->lookup_const(mobt, "Sp", &i32) && i32 >= 0) { + mstatus->max_sp = i32; + maxspUpdated = true; + } else if (!inherit) { + maxspUpdated = true; + } + + if (mob->lookup_const(mobt, "Exp", &i32) && i32 >= 0) { + exp = (double)(i32) * (double)battle_config.base_exp_rate / 100.; + entry->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + } - mstatus->rhw.range = atoi(str[9]); + if (mob->lookup_const(mobt, "JExp", &i32) && i32 >= 0) { + exp = (double)(i32) * (double)battle_config.job_exp_rate / 100.; + entry->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + } - mstatus->rhw.atk = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[10])); - mstatus->rhw.atk2 = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[11])); + if (mob->lookup_const(mobt, "AttackRange", &i32) && i32 >= 0) { + mstatus->rhw.range = i32; + } else { + mstatus->rhw.range = 1; + } + + if ((t = libconfig->setting_get_member(mobt, "Attack"))) { + if (config_setting_is_aggregate(t)) { + if (libconfig->setting_length(t) >= 2) + mstatus->rhw.atk2 = libconfig->setting_get_int_elem(t, 1); + if (libconfig->setting_length(t) >= 1) + mstatus->rhw.atk = libconfig->setting_get_int_elem(t, 0); + } else if (mob->lookup_const(mobt, "Attack", &i32) && i32 >= 0) { + mstatus->rhw.atk = i32; + mstatus->rhw.atk2 = i32; + } + } - mstatus->def = mob_parse_dbrow_cap_value(class_,DEFTYPE_MIN,DEFTYPE_MAX,atoi(str[12])); - mstatus->mdef = mob_parse_dbrow_cap_value(class_,DEFTYPE_MIN,DEFTYPE_MAX,atoi(str[13])); + if (mob->lookup_const(mobt, "Def", &i32) && i32 >= 0) { + mstatus->def = mob_parse_dbrow_cap_value(class_, DEFTYPE_MIN, DEFTYPE_MAX, i32); + } + if (mob->lookup_const(mobt, "Mdef", &i32) && i32 >= 0) { + mstatus->mdef = mob_parse_dbrow_cap_value(class_, DEFTYPE_MIN, DEFTYPE_MAX, i32); + } - mstatus->str = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[14])); - mstatus->agi = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[15])); - mstatus->vit = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[16])); - mstatus->int_ = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[17])); - mstatus->dex = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[18])); - mstatus->luk = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[19])); + if ((t = libconfig->setting_get_member(mobt, "Stats"))) { + if (config_setting_is_group(t)) { + mob->read_db_stats_sub(entry, mstatus, class_, t); + } else if (mob->lookup_const(mobt, "Stats", &i32) && i32 >= 0) { + mstatus->str = mstatus->agi = mstatus->vit = mstatus->int_ = mstatus->dex = mstatus->luk = + mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + } + } /* * Disabled for renewal since difference of 0 and 1 still has an impact in the formulas @@ -3733,265 +4038,253 @@ bool mob_parse_dbrow(char** str) { #endif //Tests showed that chase range is effectively 2 cells larger than expected [Playtester] - if (db->range3 > 0) - db->range3 += 2; + if (entry->range3 > 0) + entry->range3 += 2; + + if (mob->lookup_const(mobt, "ViewRange", &i32) && i32 >= 0) { + entry->range2 = i32; + range2Updated = true; + } else if (!inherit) { + entry->range2 = 1; + range2Updated = true; + } + + if (mob->lookup_const(mobt, "ChaseRange", &i32) && i32 >= 0) { + entry->range3 = i32; + range3Updated = true; + } else if (!inherit) { + entry->range3 = 1; + range3Updated = true; + } + if (range2Updated) { + if (battle_config.view_range_rate != 100) { + entry->range2 = entry->range2 * battle_config.view_range_rate / 100; + if (entry->range2 < 1) + entry->range2 = 1; + } + } + if (range3Updated) { + if (battle_config.chase_range_rate != 100) { + entry->range3 = entry->range3 * battle_config.chase_range_rate / 100; + if (entry->range3 < entry->range2) + entry->range3 = entry->range2; + } + } - db->range2 = atoi(str[20]); - db->range3 = atoi(str[21]); - if (battle_config.view_range_rate != 100) { - db->range2 = db->range2 * battle_config.view_range_rate / 100; - if (db->range2 < 1) - db->range2 = 1; + if (mob->lookup_const(mobt, "Size", &i32) && i32 >= 0) { + mstatus->size = i32; + mstatus->size = cap_value(mstatus->size, 0, 2); + } else if (!inherit) { + mstatus->size = 0; } - if (battle_config.chase_range_rate != 100) { - db->range3 = db->range3 * battle_config.chase_range_rate / 100; - if (db->range3 < db->range2) - db->range3 = db->range2; + + if (mob->lookup_const(mobt, "Race", &i32) && i32 >= 0) { + mstatus->race = i32; + mstatus->race = cap_value(mstatus->race, 0, RC_MAX - 1); + } else if (!inherit) { + mstatus->race = 0; } - mstatus->size = atoi(str[22]); - mstatus->race = atoi(str[23]); + if ((t = libconfig->setting_get_member(mobt, "Element")) && config_setting_is_list(t)) { + if (mob->get_const(libconfig->setting_get_elem(t, 0), &i32) && mob->get_const(libconfig->setting_get_elem(t, 1), &value)) { + mstatus->def_ele = i32; + mstatus->ele_lv = value; + } + } else { + if (!inherit) { + ShowError("mob_read_db_sub: Missing element for monster ID %d.\n", class_); + return false; + } + } - i = atoi(str[24]); //Element - mstatus->def_ele = i%10; - mstatus->ele_lv = i/20; if (mstatus->def_ele >= ELE_MAX) { - ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", mstatus->def_ele, class_, ELE_MAX-1); - return false; + if (!inherit) { + ShowError("mob_read_db_sub: Invalid element type %d for monster ID %d (max=%d).\n", mstatus->def_ele, class_, ELE_MAX-1); + return false; + } } if (mstatus->ele_lv < 1 || mstatus->ele_lv > 4) { - ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", mstatus->ele_lv, class_); - return false; + if (!inherit) { + ShowError("mob_read_db_sub: Invalid element level %d for monster ID %d, must be in range 1-4.\n", mstatus->ele_lv, class_); + return false; + } + } + + if ((t = libconfig->setting_get_member(mobt, "Mode"))) { + if (config_setting_is_group(t)) { + mstatus->mode = mob->read_db_mode_sub(entry, mstatus, class_, t); + } else if (mob->lookup_const(mobt, "Mode", &i32) && i32 >= 0) { + mstatus->mode = i32; + } } - mstatus->mode = (int)strtol(str[25], NULL, 0); if (!battle_config.monster_active_enable) mstatus->mode &= ~MD_AGGRESSIVE; - mstatus->speed = atoi(str[26]); + if (mob->lookup_const(mobt, "MoveSpeed", &i32) && i32 >= 0) { + mstatus->speed = i32; + } + mstatus->aspd_rate = 1000; - i = atoi(str[27]); - mstatus->adelay = cap_value(i, battle_config.monster_max_aspd*2, 4000); - i = atoi(str[28]); - mstatus->amotion = cap_value(i, battle_config.monster_max_aspd, 2000); + + if (mob->lookup_const(mobt, "AttackDelay", &i32) && i32 >= 0) { + mstatus->adelay = cap_value(i32, battle_config.monster_max_aspd*2, 4000); + } else if (!inherit) { + mstatus->adelay = 4000; + } + + if (mob->lookup_const(mobt, "AttackMotion", &i32) && i32 >= 0) { + mstatus->amotion = cap_value(i32, battle_config.monster_max_aspd, 2000); + } else if (!inherit) { + mstatus->amotion = 2000; + } + //If the attack animation is longer than the delay, the client crops the attack animation! //On aegis there is no real visible effect of having a recharge-time less than amotion anyway. if (mstatus->adelay < mstatus->amotion) mstatus->adelay = mstatus->amotion; - mstatus->dmotion = atoi(str[29]); - if(battle_config.monster_damage_delay_rate != 100) + + if (mob->lookup_const(mobt, "DamageMotion", &i32) && i32 >= 0) { + mstatus->dmotion = i32; + dmotionUpdated = true; + } else if (!inherit) { + dmotionUpdated = true; + } + + if (dmotionUpdated && battle_config.monster_damage_delay_rate != 100) mstatus->dmotion = mstatus->dmotion * battle_config.monster_damage_delay_rate / 100; // Fill in remaining status data by using a dummy monster. data.bl.type = BL_MOB; - data.level = db->lv; + data.level = entry->lv; memcpy(&data.status, mstatus, sizeof(struct status_data)); - status->calc_misc(&data.bl, mstatus, db->lv); + status->calc_misc(&data.bl, mstatus, entry->lv); // MVP EXP Bonus: MEXP // Some new MVP's MEXP multiple by high exp-rate cause overflow. [LuzZza] - exp = (double)atoi(str[30]) * (double)battle_config.mvp_exp_rate / 100.; - db->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); - - //Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] - maxhp = (double)mstatus->max_hp; - if (db->mexp > 0) { //Mvp - if (battle_config.mvp_hp_rate != 100) - maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.; - } else //Normal mob - if (battle_config.monster_hp_rate != 100) - maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.; - - mstatus->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX); - if(mstatus->max_sp < 1) mstatus->max_sp = 1; + if (mob->lookup_const(mobt, "MvpExp", &i32) && i32 >= 0) { + exp = (double)i32 * (double)battle_config.mvp_exp_rate / 100.; + entry->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); + } else if (!inherit) { + exp = 0; + } + + if (maxhpUpdated) { + //Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] + maxhp = (double)mstatus->max_hp; + if (entry->mexp > 0) { //Mvp + if (battle_config.mvp_hp_rate != 100) + maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.; + } else { //Normal mob + if (battle_config.monster_hp_rate != 100) + maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.; + } + mstatus->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX); + } + if (maxspUpdated) { + if(mstatus->max_sp < 1) mstatus->max_sp = 1; + } //Since mobs always respawn with full life... mstatus->hp = mstatus->max_hp; mstatus->sp = mstatus->max_sp; - // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per - for(i = 0; i < MAX_MVP_DROP; i++) { - int rate_adjust = battle_config.item_rate_mvp;; - db->mvpitem[i].nameid = atoi(str[31+i*2]); - if (!db->mvpitem[i].nameid) { - db->mvpitem[i].p = 0; //No item.... - continue; - } - mob->item_dropratio_adjust(db->mvpitem[i].nameid, class_, &rate_adjust); - db->mvpitem[i].p = mob->drop_adjust(atoi(str[32+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); - - //calculate and store Max available drop chance of the MVP item - if (db->mvpitem[i].p) { - struct item_data *id; - id = itemdb->search(db->mvpitem[i].nameid); - if (id->maxchance == -1 || (id->maxchance < db->mvpitem[i].p/10 + 1) ) { - //item has bigger drop chance or sold in shops - id->maxchance = db->mvpitem[i].p/10 + 1; //reduce MVP drop info to not spoil common drop rate - } + if ((t = libconfig->setting_get_member(mobt, "MvpDrops"))) { + if (config_setting_is_group(t)) { + mob->read_db_mvpdrops_sub(entry, mstatus, class_, t); } } - for(i = 0; i < MAX_MOB_DROP; i++) { - int rate = 0, rate_adjust, type; - unsigned short ratemin, ratemax; - struct item_data *id; - int k = 31 + MAX_MVP_DROP*2 + i*2; - db->dropitem[i].nameid = atoi(str[k]); - if (!db->dropitem[i].nameid) { - db->dropitem[i].p = 0; //No drop. - continue; - } - id = itemdb->search(db->dropitem[i].nameid); - type = id->type; - rate = atoi(str[k+1]); - if( (class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946) ) { - //Treasure box drop rates [Skotlex] - rate_adjust = battle_config.item_rate_treasure; - ratemin = battle_config.item_drop_treasure_min; - ratemax = battle_config.item_drop_treasure_max; - } - else switch (type) - { // Added support to restrict normal drops of MVP's [Reddozen] - case IT_HEALING: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal; - ratemin = battle_config.item_drop_heal_min; - ratemax = battle_config.item_drop_heal_max; - break; - case IT_USABLE: - case IT_CASH: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use; - ratemin = battle_config.item_drop_use_min; - ratemax = battle_config.item_drop_use_max; - break; - case IT_WEAPON: - case IT_ARMOR: - case IT_PETARMOR: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip; - ratemin = battle_config.item_drop_equip_min; - ratemax = battle_config.item_drop_equip_max; - break; - case IT_CARD: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card; - ratemin = battle_config.item_drop_card_min; - ratemax = battle_config.item_drop_card_max; - break; - default: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common; - ratemin = battle_config.item_drop_common_min; - ratemax = battle_config.item_drop_common_max; - break; - } - mob->item_dropratio_adjust(id->nameid, class_, &rate_adjust); - db->dropitem[i].p = mob->drop_adjust(rate, rate_adjust, ratemin, ratemax); - - //calculate and store Max available drop chance of the item - if( db->dropitem[i].p && (class_ < 1324 || class_ > 1363) && (class_ < 1938 || class_ > 1946) ) - { //Skip treasure chests. - if (id->maxchance == -1 || (id->maxchance < db->dropitem[i].p) ) { - id->maxchance = db->dropitem[i].p; //item has bigger drop chance or sold in shops - } - for (k = 0; k< MAX_SEARCH; k++) { - if (id->mob[k].chance <= db->dropitem[i].p) - break; - } - if (k == MAX_SEARCH) - continue; - - if (id->mob[k].id != class_ && k != MAX_SEARCH - 1) - memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); - id->mob[k].chance = db->dropitem[i].p; - id->mob[k].id = class_; + if ((t = libconfig->setting_get_member(mobt, "Drops"))) { + if (config_setting_is_group(t)) { + mob->read_db_drops_sub(entry, mstatus, class_, t); } } + + mob->read_db_additional_fields(entry, class_, mobt, id, source); // Finally insert monster's data into the database. if (mob->db_data[class_] == NULL) mob->db_data[class_] = (struct mob_db*)aMalloc(sizeof(struct mob_db)); else //Copy over spawn data - memcpy(&db->spawn, mob->db_data[class_]->spawn, sizeof(db->spawn)); + memcpy(&entry->spawn, mob->db_data[class_]->spawn, sizeof(entry->spawn)); - memcpy(mob->db_data[class_], db, sizeof(struct mob_db)); + memcpy(mob->db_data[class_], entry, sizeof(struct mob_db)); return true; } -/*========================================== - * mob_db.txt reading - *------------------------------------------*/ -bool mob_readdb_sub(char* fields[], int columns, int current) { - return mob->parse_dbrow(fields); +void mob_read_db_additional_fields(struct mob_db *entry, int class_, config_setting_t *it, int n, const char *source) +{ + // do nothing. plugins can do own work } -void mob_readdb(void) { - const char* filename[] = { - DBPATH"mob_db.txt", - "mob_db2.txt" }; - int fi; - - for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { - if(fi > 0) { - char filepath[256]; - sprintf(filepath, "%s/%s", map->db_path, filename[fi]); - if(!exists(filepath)) { - continue; - } +bool mob_lookup_const(const config_setting_t *it, const char *name, int *value) +{ + if (libconfig->setting_lookup_int(it, name, value)) + { + return true; + } + else + { + const char *str = NULL; + if (libconfig->setting_lookup_string(it, name, &str)) + { + if (*str && script->get_constant(str, value)) + return true; } - - sv->readdb(map->db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, mob->readdb_sub); } - mob->name_constants(); + return false; } -/*========================================== - * mob_db table reading - *------------------------------------------*/ -int mob_read_sqldb(void) { - const char* mob_db_name[] = { - map->mob_db_db, - map->mob_db2_db - }; - int fi; - - for( fi = 0; fi < ARRAYLENGTH(mob_db_name); ++fi ) { - uint32 lines = 0, count = 0; +bool mob_get_const(const config_setting_t *it, int *value) +{ + const char *str = config_setting_get_string(it); + if (str && *str && script->get_constant(str, value)) + return true; - // retrieve all rows from the mob database - if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) { - Sql_ShowDebug(map->mysql_handle); - continue; - } + *value = libconfig->setting_get_int(it); + return true; +} - // process rows one by one - while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) { - // wrap the result into a TXT-compatible format - char line[1024]; - char* str[31+2*MAX_MVP_DROP+2*MAX_MOB_DROP]; - char* p; - int i; +/*========================================== + * mob_db.txt reading + *------------------------------------------*/ +void mob_readdb(void) { + const char* filename[] = { + DBPATH"mob_db.conf", + "mob_db2.conf" }; + int i; - lines++; - for(i = 0, p = line; i < 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP; i++) - { - char* data; - size_t len; - SQL->GetData(map->mysql_handle, i, &data, &len); + for (i = 0; i < ARRAYLENGTH(filename); ++i) { + mob->read_libconfig(filename[i], i > 0 ? true : false); + } + mob->name_constants(); +} - strcpy(p, data); - str[i] = p; - p+= len + 1; - } +int mob_read_libconfig(const char *filename, bool ignore_missing) +{ + config_t mob_db_conf; + char filepath[256]; + config_setting_t *mdb; + config_setting_t *t; + int i = 0; - if (!mob->parse_dbrow(str)) - continue; + nullpo_ret(filename); + sprintf(filepath, "%s/%s", map->db_path, filename); - count++; - } + if (ignore_missing && !exists(filepath)) + return 0; - // free the query result - SQL->FreeResult(map->mysql_handle); + if (libconfig->read_file(&mob_db_conf, filepath) || !(mdb = libconfig->setting_get_member(mob_db_conf.root, "mob_db"))) { + ShowError("can't read %s\n", filepath); + return -1; + } - ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]); + while ((t = libconfig->setting_get_elem(mdb, i++))) { + mob->read_db_sub(t, i - 1, filepath); } - mob->name_constants(); + libconfig->destroy(&mob_db_conf); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, filepath); return 0; } @@ -4515,59 +4808,6 @@ void mob_readskilldb(void) { } } -/** - * mob_skill_db table reading [CalciumKid] - * not overly sure if this is all correct - * seems to work though... - */ -int mob_read_sqlskilldb(void) { - const char* mob_skill_db_name[] = { - map->mob_skill_db_db, - map->mob_skill_db2_db - }; - int fi; - - if( battle_config.mob_skill_rate == 0 ) { - ShowStatus("Mob skill use disabled. Not reading mob skills.\n"); - return 0; - } - - for( fi = 0; fi < ARRAYLENGTH(mob_skill_db_name); ++fi ) { - uint32 lines = 0, count = 0; - - // retrieve all rows from the mob skill database - if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi]) ) { - Sql_ShowDebug(map->mysql_handle); - continue; - } - - // process rows one by one - while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) { - // wrap the result into a TXT-compatible format - char* str[19]; - char* dummy = ""; - int i; - ++lines; - for( i = 0; i < 19; ++i ) - { - SQL->GetData(map->mysql_handle, i, &str[i], NULL); - if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns - } - - if (!mob->parse_row_mobskilldb(str, 19, count)) - continue; - - count++; - } - - // free the query result - SQL->FreeResult(map->mysql_handle); - - ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_skill_db_name[fi]); - } - return 0; -} - /*========================================== * mob_race2_db.txt reading *------------------------------------------*/ @@ -4630,15 +4870,8 @@ void mob_load(bool minimal) { } sv->readdb(map->db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, mob->readdb_itemratio); // must be read before mobdb mob->readchatdb(); - if (map->db_use_sql_mob_db) { - mob->read_sqldb(); - } - if (map->db_use_sql_mob_skill_db) { - mob->read_sqlskilldb(); - } else { - mob->readdb(); - mob->readskilldb(); - } + mob->readdb(); + mob->readskilldb(); sv->readdb(map->db_path, "mob_avail.txt", ',', 2, 12, -1, mob->readdb_mobavail); mob->read_randommonster(); sv->readdb(map->db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, mob->readdb_race2); @@ -4708,16 +4941,7 @@ int do_init_mob(bool minimal) { void mob_destroy_mob_db(int index) { struct mob_db *data = mob->db_data[index]; - if (data->hdata) { - int i; - for (i = 0; i < data->hdatac; i++) { - if (data->hdata[i]->flag.free ) { - aFree(data->hdata[i]->data); - } - aFree(data->hdata[i]); - } - aFree(data->hdata); - } + HPM->data_store_destroy(&data->hdata); aFree(data); mob->db_data[index] = NULL; } @@ -4856,10 +5080,16 @@ void mob_defaults(void) { mob->clone_delete = mob_clone_delete; mob->drop_adjust = mob_drop_adjust; mob->item_dropratio_adjust = item_dropratio_adjust; - mob->parse_dbrow = mob_parse_dbrow; - mob->readdb_sub = mob_readdb_sub; + mob->lookup_const = mob_lookup_const; + mob->get_const = mob_get_const; mob->readdb = mob_readdb; - mob->read_sqldb = mob_read_sqldb; + mob->read_libconfig = mob_read_libconfig; + mob->read_db_additional_fields = mob_read_db_additional_fields; + mob->read_db_sub = mob_read_db_sub; + mob->read_db_drops_sub = mob_read_db_drops_sub; + mob->read_db_mvpdrops_sub = mob_read_db_mvpdrops_sub; + mob->read_db_mode_sub = mob_read_db_mode_sub; + mob->read_db_stats_sub = mob_read_db_stats_sub; mob->name_constants = mob_name_constants; mob->readdb_mobavail = mob_readdb_mobavail; mob->read_randommonster = mob_read_randommonster; @@ -4867,7 +5097,6 @@ void mob_defaults(void) { mob->readchatdb = mob_readchatdb; mob->parse_row_mobskilldb = mob_parse_row_mobskilldb; mob->readskilldb = mob_readskilldb; - mob->read_sqlskilldb = mob_read_sqlskilldb; mob->readdb_race2 = mob_readdb_race2; mob->readdb_itemratio = mob_readdb_itemratio; mob->load = mob_load; diff --git a/src/map/mob.h b/src/map/mob.h index 4b8a054b5..f7e071261 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -11,6 +11,8 @@ #include "common/hercules.h" #include "common/mmo.h" // struct item +struct hplugin_data_store; + #define MAX_RANDOMMONSTER 5 // Change this to increase the table size in your mob_db to accommodate a larger mob database. @@ -138,10 +140,7 @@ struct mob_db { int maxskill; struct mob_skill skill[MAX_MOBSKILL]; struct spawn_info spawn[10]; - - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; struct mob_data { @@ -208,14 +207,10 @@ struct mob_data { * MvP Tombstone NPC ID **/ int tomb_nid; - - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; - enum { MST_TARGET = 0, MST_RANDOM, //Random Target! @@ -368,10 +363,16 @@ struct mob_interface { int (*clone_delete) (struct mob_data *md); unsigned int (*drop_adjust) (int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max); void (*item_dropratio_adjust) (int nameid, int mob_id, int *rate_adjust); - bool (*parse_dbrow) (char **str); - bool (*readdb_sub) (char *fields[], int columns, int current); void (*readdb) (void); - int (*read_sqldb) (void); + bool (*lookup_const) (const config_setting_t *it, const char *name, int *value); + bool (*get_const) (const config_setting_t *it, int *value); + int (*read_libconfig) (const char *filename, bool ignore_missing); + void (*read_db_additional_fields) (struct mob_db *entry, int class_, config_setting_t *it, int n, const char *source); + bool (*read_db_sub) (config_setting_t *mobt, int id, const char *source); + void (*read_db_drops_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); + void (*read_db_mvpdrops_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); + int (*read_db_mode_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); + void (*read_db_stats_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); void (*name_constants) (void); bool (*readdb_mobavail) (char *str[], int columns, int current); int (*read_randommonster) (void); @@ -379,7 +380,6 @@ struct mob_interface { void (*readchatdb) (void); bool (*parse_row_mobskilldb) (char **str, int columns, int current); void (*readskilldb) (void); - int (*read_sqlskilldb) (void); bool (*readdb_race2) (char *fields[], int columns, int current); bool (*readdb_itemratio) (char *str[], int columns, int current); void (*load) (bool minimal); diff --git a/src/map/npc.c b/src/map/npc.c index a0c14a058..7044fefcf 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -27,7 +27,7 @@ #include "common/cbasetypes.h" #include "common/db.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/socket.h" @@ -2321,16 +2321,7 @@ int npc_unload(struct npc_data* nd, bool single) nd->ud = NULL; } - if (nd->hdata) { - unsigned int i; - for (i = 0; i < nd->hdatac; i++) { - if (nd->hdata[i]->flag.free) { - aFree(nd->hdata[i]->data); - } - aFree(nd->hdata[i]); - } - aFree(nd->hdata); - } + HPM->data_store_destroy(&nd->hdata); aFree(nd); diff --git a/src/map/npc.h b/src/map/npc.h index 14b89d128..bf3d1494d 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -11,7 +11,7 @@ #include "common/hercules.h" #include "common/db.h" -struct HPluginData; +struct hplugin_data_store; struct view_data; enum npc_parse_options { @@ -102,9 +102,7 @@ struct npc_data { char killer_name[NAME_LENGTH]; } tomb; } u; - /* HPData Support for npc_data */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index 503dbd845..edcd755bc 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -11,7 +11,7 @@ #include "map/mob.h" // struct mob_data #include "map/pc.h" // struct map_session_data #include "map/script.h" // set_var() -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/strlib.h" diff --git a/src/map/party.c b/src/map/party.c index db285a4b4..3a0b6d518 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -21,7 +21,7 @@ #include "map/status.h" #include "common/HPM.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -103,16 +103,7 @@ int party_db_final(DBKey key, DBData *data, va_list ap) { if (p->instance) aFree(p->instance); - if (p->hdata) { - int i; - for (i = 0; i < p->hdatac; i++) { - if (p->hdata[i]->flag.free) { - aFree(p->hdata[i]->data); - } - aFree(p->hdata[i]); - } - aFree(p->hdata); - } + HPM->data_store_destroy(&p->hdata); } return 0; } @@ -608,16 +599,8 @@ int party_broken(int party_id) if( p->instance ) aFree(p->instance); - if( p->hdata ) - { - for( j = 0; j < p->hdatac; j++ ) { - if( p->hdata[j]->flag.free ) { - aFree(p->hdata[j]->data); - } - aFree(p->hdata[j]); - } - aFree(p->hdata); - } + HPM->data_store_destroy(&p->hdata); + idb_remove(party->db,party_id); return 0; } diff --git a/src/map/party.h b/src/map/party.h index c7893add2..df7c03f05 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -15,7 +15,7 @@ #define PARTY_BOOKING_JOBS 6 #define PARTY_BOOKING_RESULTS 10 -struct HPluginData; +struct hplugin_data_store; struct party_member_data { struct map_session_data *sd; @@ -35,10 +35,7 @@ struct party_data { unsigned snovice :1; ///< There's a Super Novice unsigned tk : 1; ///< There's a taekwon } state; - - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; #define PB_NOTICE_LENGTH (36 + 1) diff --git a/src/map/path.c b/src/map/path.c index a482fc473..6d9b48837 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -10,7 +10,7 @@ #include "map/map.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -45,7 +45,7 @@ struct path_node { }; /// Binary heap of path nodes -BHEAP_STRUCT_DECL(node_heap, struct path_node*); +BHEAP_STRUCT_DECL(node_heap, struct path_node *); /// Comparator for binary heap of path nodes (minimum cost at top) #define NODE_MINTOPCMP(i,j) ((i)->f_cost - (j)->f_cost) diff --git a/src/map/pc.c b/src/map/pc.c index dc7014701..4d4f41521 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -41,7 +41,7 @@ #include "common/conf.h" #include "common/core.h" // get_svn_revision() #include "common/HPM.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" // NAME_LENGTH, MAX_CARTS, NEW_CARTS #include "common/nullpo.h" #include "common/random.h" @@ -2984,7 +2984,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) case 0: //Right hand ARR_FIND(0, ARRAYLENGTH(sd->right_weapon.add_dmg), i, sd->right_weapon.add_dmg[i].rate == 0 || sd->right_weapon.add_dmg[i].class_ == type2); if (i == ARRAYLENGTH(sd->right_weapon.add_dmg)) { - ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class dmg bonuses per character!\n", + ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->right_weapon.add_dmg)); break; } @@ -2998,7 +2998,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) case 1: //Left hand ARR_FIND(0, ARRAYLENGTH(sd->left_weapon.add_dmg), i, sd->left_weapon.add_dmg[i].rate == 0 || sd->left_weapon.add_dmg[i].class_ == type2); if (i == ARRAYLENGTH(sd->left_weapon.add_dmg)) { - ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class dmg bonuses per character!\n", + ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->left_weapon.add_dmg)); break; } @@ -3016,7 +3016,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->add_mdmg), i, sd->add_mdmg[i].rate == 0 || sd->add_mdmg[i].class_ == type2); if (i == ARRAYLENGTH(sd->add_mdmg)) { - ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg)); + ShowWarning("pc_bonus2: Reached max (%d) number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg)); break; } sd->add_mdmg[i].class_ = type2; @@ -3029,7 +3029,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->add_def), i, sd->add_def[i].rate == 0 || sd->add_def[i].class_ == type2); if (i == ARRAYLENGTH(sd->add_def)) { - ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def)); + ShowWarning("pc_bonus2: Reached max (%d) number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def)); break; } sd->add_def[i].class_ = type2; @@ -3042,7 +3042,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->add_mdef), i, sd->add_mdef[i].rate == 0 || sd->add_mdef[i].class_ == type2); if (i == ARRAYLENGTH(sd->add_mdef)) { - ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef)); + ShowWarning("pc_bonus2: Reached max (%d) number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef)); break; } sd->add_mdef[i].class_ = type2; @@ -3205,7 +3205,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == 0 || sd->skillatk[i].id == type2); if (i == ARRAYLENGTH(sd->skillatk)) { //Better mention this so the array length can be updated. [Skotlex] - ShowDebug("script->run: bonus2 bSkillAtk reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillAtk reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillatk), type2, val); break; } @@ -3222,7 +3222,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2); if (i == ARRAYLENGTH(sd->skillheal)) { // Better mention this so the array length can be updated. [Skotlex] - ShowDebug("script->run: bonus2 bSkillHeal reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillHeal reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal), type2, val); break; } @@ -3239,7 +3239,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2); if (i == ARRAYLENGTH(sd->skillheal2)) { // Better mention this so the array length can be updated. [Skotlex] - ShowDebug("script->run: bonus2 bSkillHeal2 reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillHeal2 reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal2), type2, val); break; } @@ -3256,7 +3256,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2); if (i == ARRAYLENGTH(sd->skillblown)) { //Better mention this so the array length can be updated. [Skotlex] - ShowDebug("script->run: bonus2 bSkillBlown reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillBlown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val); break; } @@ -3276,7 +3276,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2); if (i == ARRAYLENGTH(sd->skillcast)) { //Better mention this so the array length can be updated. [Skotlex] - ShowDebug("script->run: bonus2 %s reached its limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 %s reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", type == SP_CASTRATE ? "bCastRate" : "bVariableCastrate", ARRAYLENGTH(sd->skillcast), type2, val); break; @@ -3296,7 +3296,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2); if (i == ARRAYLENGTH(sd->skillfixcastrate)) { - ShowDebug("script->run: bonus2 bFixedCastrate reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bFixedCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcastrate), type2, val); break; } @@ -3347,7 +3347,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) //Standard item bonus. for(i=0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid && sd->itemhealrate[i].nameid != type2; i++); if (i == ARRAYLENGTH(sd->itemhealrate)) { - ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate)); + ShowWarning("pc_bonus2: Reached max (%d) number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate)); break; } sd->itemhealrate[i].nameid = type2; @@ -3524,7 +3524,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == 0 || sd->skillusesprate[i].id == type2); if (i == ARRAYLENGTH(sd->skillusesprate)) { - ShowDebug("script->run: bonus2 bSkillUseSPrate reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillUseSPrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesprate), type2, val); break; } @@ -3540,7 +3540,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2); if (i == ARRAYLENGTH(sd->skillcooldown)) { - ShowDebug("script->run: bonus2 bSkillCoolDown reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillCoolDown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val); break; } @@ -3556,7 +3556,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2); if (i == ARRAYLENGTH(sd->skillfixcast)) { - ShowDebug("script->run: bonus2 bSkillFixedCast reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillFixedCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val); break; } @@ -3572,7 +3572,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2); if (i == ARRAYLENGTH(sd->skillvarcast)) { - ShowDebug("script->run: bonus2 bSkillVariableCast reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillVariableCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val); break; } @@ -3589,7 +3589,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2); if (i == ARRAYLENGTH(sd->skillcast)) { - ShowDebug("script->run: bonus2 bVariableCastrate reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bVariableCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcast), type2, val); break; } @@ -3606,7 +3606,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2); if (i == ARRAYLENGTH(sd->skillusesp)) { - ShowDebug("script->run: bonus2 bSkillUseSP reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + ShowDebug("script->run: bonus2 bSkillUseSP reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val); break; } @@ -4112,7 +4112,10 @@ bool pc_can_insert_card(struct map_session_data* sd, int idx_card) } /*========================================== - * Append a card to an item ? + * Attempt to insert card into item. + * Return: + * 0 = fail + * 1 = success *------------------------------------------*/ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) { @@ -4143,6 +4146,7 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) sd->status.inventory[idx_equip].card[i] = nameid; logs->pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); clif->insert_card(sd,idx_equip,idx_card,0); + return 1; } return 0; @@ -11332,14 +11336,7 @@ void pc_autotrade_populate(struct map_session_data *sd) { pc->autotrade_update(sd,PAUC_START); - for(i = 0; i < data->hdatac; i++ ) { - if( data->hdata[i]->flag.free ) { - aFree(data->hdata[i]->data); - } - aFree(data->hdata[i]); - } - if( data->hdata ) - aFree(data->hdata); + HPM->data_store_destroy(&data->hdata); idb_remove(pc->at_db, sd->status.char_id); } @@ -11349,16 +11346,7 @@ void pc_autotrade_populate(struct map_session_data *sd) { */ int pc_autotrade_final(DBKey key, DBData *data, va_list ap) { struct autotrade_vending* at_v = DB->data2ptr(data); - int i; - for(i = 0; i < at_v->hdatac; i++ ) { - if( at_v->hdata[i]->flag.free ) { - aFree(at_v->hdata[i]->data); - } - aFree(at_v->hdata[i]); - } - if( at_v->hdata ) - aFree(at_v->hdata); - + HPM->data_store_destroy(&at_v->hdata); return 0; } diff --git a/src/map/pc.h b/src/map/pc.h index e6e95978d..2c8b24acf 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -539,10 +539,7 @@ END_ZEROED_BLOCK; unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd); ///< parse_cmd_func used by this player unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules] - - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store /* expiration_time timer id */ int expiration_tid; @@ -757,9 +754,7 @@ struct autotrade_vending { struct item list[MAX_VENDING]; struct s_vending vending[MAX_VENDING]; unsigned char vend_num; - /* HPM Custom Struct */ - struct HPluginData **hdata; - unsigned int hdatac; + struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; /*===================================== diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 7efcd7e26..f9633571c 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -13,7 +13,7 @@ #include "common/cbasetypes.h" #include "common/conf.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/strlib.h" // strcmp diff --git a/src/map/pet.c b/src/map/pet.c index 2865cc901..aed49df63 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -25,7 +25,7 @@ #include "map/unit.h" #include "common/db.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" diff --git a/src/map/quest.c b/src/map/quest.c index fe4014ae5..790e96253 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -21,7 +21,7 @@ #include "map/unit.h" #include "common/cbasetypes.h" #include "common/conf.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -507,7 +507,7 @@ int quest_read_db(void) const char *filename = "quest_db.conf"; sprintf(filepath, "%s/%s", map->db_path, filename); - if (libconfig->read_file(&quest_db_conf, filepath) || !(qdb = libconfig->setting_get_member(quest_db_conf.root, filename))) { + if (libconfig->read_file(&quest_db_conf, filepath) || !(qdb = libconfig->setting_get_member(quest_db_conf.root, "quest_db"))) { ShowError("can't read %s\n", filepath); return -1; } diff --git a/src/map/script.c b/src/map/script.c index face34d30..54d8d338d 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -39,7 +39,7 @@ #include "map/storage.h" #include "map/unit.h" #include "common/cbasetypes.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/md5calc.h" #include "common/mmo.h" // NEW_CARTS #include "common/nullpo.h" @@ -2628,6 +2628,38 @@ TBL_PC *script_rid2sd(struct script_state *st) { return sd; } +char *get_val_npcscope_str(struct script_state* st, struct reg_db *n, struct script_data* data) { + if (n) + return (char*)i64db_get(n->vars, reference_getuid(data)); + else + return NULL; +} + +char *get_val_instance_str(struct script_state* st, const char* name, struct script_data* data) { + if (st->instance_id >= 0) { + return (char*)i64db_get(instance->list[st->instance_id].regs.vars, reference_getuid(data)); + } else { + ShowWarning("script_get_val: cannot access instance variable '%s', defaulting to \"\"\n", name); + return NULL; + } +} + +int get_val_npcscope_num(struct script_state* st, struct reg_db *n, struct script_data* data) { + if (n) + return (int)i64db_iget(n->vars, reference_getuid(data)); + else + return 0; +} + +int get_val_instance_num(struct script_state* st, const char* name, struct script_data* data) { + if (st->instance_id >= 0) + return (int)i64db_iget(instance->list[st->instance_id].regs.vars, reference_getuid(data)); + else { + ShowWarning("script_get_val: cannot access instance variable '%s', defaulting to 0\n", name); + return 0; + } +} + /** * Dereferences a variable/constant, replacing it with a copy of the value. * @@ -2681,24 +2713,15 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) { data->u.str = pc_readaccountregstr(sd, data->u.num);// local break; case '.': - { - struct DBMap* n = data->ref ? - data->ref->vars : name[1] == '@' ? - st->stack->scope.vars : // instance/scope variable - st->script->local.vars; // npc variable - if( n ) - data->u.str = (char*)i64db_get(n,reference_getuid(data)); - else - data->u.str = NULL; - } + if (data->ref) + data->u.str = script->get_val_ref_str(st, data->ref, data); + else if (name[1] == '@') + data->u.str = script->get_val_scope_str(st, &st->stack->scope, data); + else + data->u.str = script->get_val_npc_str(st, &st->script->local, data); break; case '\'': - if ( st->instance_id >= 0 ) { - data->u.str = (char*)i64db_get(instance->list[st->instance_id].regs.vars, reference_getuid(data)); - } else { - ShowWarning("script_get_val: cannot access instance variable '%s', defaulting to \"\"\n", name); - data->u.str = NULL; - } + data->u.str = script->get_val_instance_str(st, name, data); break; default: data->u.str = pc_readglobalreg_str(sd, data->u.num); @@ -2736,24 +2759,15 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) { data->u.num = pc_readaccountreg(sd, data->u.num);// local break; case '.': - { - struct DBMap* n = data->ref ? - data->ref->vars : name[1] == '@' ? - st->stack->scope.vars : // instance/scope variable - st->script->local.vars; // npc variable - if( n ) - data->u.num = (int)i64db_iget(n,reference_getuid(data)); - else - data->u.num = 0; - } + if (data->ref) + data->u.num = script->get_val_ref_num(st, data->ref, data); + else if (name[1] == '@') + data->u.num = script->get_val_scope_num(st, &st->stack->scope, data); + else + data->u.num = script->get_val_npc_num(st, &st->script->local, data); break; case '\'': - if( st->instance_id >= 0 ) - data->u.num = (int)i64db_iget(instance->list[st->instance_id].regs.vars, reference_getuid(data)); - else { - ShowWarning("script_get_val: cannot access instance variable '%s', defaulting to 0\n", name); - data->u.num = 0; - } + data->u.num = script->get_val_instance_num(st, name, data); break; default: data->u.num = pc_readglobalreg(sd, data->u.num); @@ -2998,6 +3012,73 @@ void script_array_update(struct reg_db *src, int64 num, bool empty) { } } +void set_reg_npcscope_str(struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str) +{ + if (n) + { + if (str[0]) { + i64db_put(n->vars, num, aStrdup(str)); + if (script_getvaridx(num)) + script->array_update(n, num, false); + } else { + i64db_remove(n->vars, num); + if (script_getvaridx(num)) + script->array_update(n, num, true); + } + } +} + +void set_reg_npcscope_num(struct script_state* st, struct reg_db *n, int64 num, const char* name, int val) +{ + if (n) { + if (val != 0) { + i64db_iput(n->vars, num, val); + if (script_getvaridx(num)) + script->array_update(n, num, false); + } else { + i64db_remove(n->vars, num); + if (script_getvaridx(num)) + script->array_update(n, num, true); + } + } +} + +void set_reg_instance_str(struct script_state* st, int64 num, const char* name, const char *str) +{ + if (st->instance_id >= 0) { + if (str[0]) { + i64db_put(instance->list[st->instance_id].regs.vars, num, aStrdup(str)); + if (script_getvaridx(num)) + script->array_update(&instance->list[st->instance_id].regs, num, false); + } else { + i64db_remove(instance->list[st->instance_id].regs.vars, num); + if (script_getvaridx(num)) + script->array_update(&instance->list[st->instance_id].regs, num, true); + } + } else { + ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name); + script->reportsrc(st); + } +} + +void set_reg_instance_num(struct script_state* st, int64 num, const char* name, int val) +{ + if (st->instance_id >= 0) { + if (val != 0) { + i64db_iput(instance->list[st->instance_id].regs.vars, num, val); + if (script_getvaridx(num)) + script->array_update(&instance->list[st->instance_id].regs, num, false); + } else { + i64db_remove(instance->list[st->instance_id].regs.vars, num); + if (script_getvaridx(num)) + script->array_update(&instance->list[st->instance_id].regs, num, true); + } + } else { + ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name); + script->reportsrc(st); + } +} + /** * Stores the value of a script variable * @@ -3029,36 +3110,15 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co pc_setaccountreg2str(sd, num, str) : pc_setaccountregstr(sd, num, str); case '.': - { - struct reg_db *n = (ref) ? ref : (name[1] == '@') ? &st->stack->scope : &st->script->local; - if( n ) { - if (str[0]) { - i64db_put(n->vars, num, aStrdup(str)); - if( script_getvaridx(num) ) - script->array_update(n, num, false); - } else { - i64db_remove(n->vars, num); - if( script_getvaridx(num) ) - script->array_update(n, num, true); - } - } - } + if (ref) + script->set_reg_ref_str(st, ref, num, name, str); + else if (name[1] == '@') + script->set_reg_scope_str(st, &st->stack->scope, num, name, str); + else + script->set_reg_npc_str(st, &st->script->local, num, name, str); return 1; case '\'': - if( st->instance_id >= 0 ) { - if( str[0] ) { - i64db_put(instance->list[st->instance_id].regs.vars, num, aStrdup(str)); - if( script_getvaridx(num) ) - script->array_update(&instance->list[st->instance_id].regs, num, false); - } else { - i64db_remove(instance->list[st->instance_id].regs.vars, num); - if( script_getvaridx(num) ) - script->array_update(&instance->list[st->instance_id].regs, num, true); - } - } else { - ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name); - script->reportsrc(st); - } + set_reg_instance_str(st, num, name, str); return 1; default: return pc_setglobalreg_str(sd, num, str); @@ -3095,36 +3155,15 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co pc_setaccountreg2(sd, num, val) : pc_setaccountreg(sd, num, val); case '.': - { - struct reg_db *n = (ref) ? ref : (name[1] == '@') ? &st->stack->scope : &st->script->local; - if( n ) { - if( val != 0 ) { - i64db_iput(n->vars, num, val); - if( script_getvaridx(num) ) - script->array_update(n, num, false); - } else { - i64db_remove(n->vars, num); - if( script_getvaridx(num) ) - script->array_update(n, num, true); - } - } - } + if (ref) + script->set_reg_ref_num(st, ref, num, name, val); + else if (name[1] == '@') + script->set_reg_scope_num(st, &st->stack->scope, num, name, val); + else + script->set_reg_npc_num(st, &st->script->local, num, name, val); return 1; case '\'': - if( st->instance_id >= 0 ) { - if( val != 0 ) { - i64db_iput(instance->list[st->instance_id].regs.vars, num, val); - if( script_getvaridx(num) ) - script->array_update(&instance->list[st->instance_id].regs, num, false); - } else { - i64db_remove(instance->list[st->instance_id].regs.vars, num); - if( script_getvaridx(num) ) - script->array_update(&instance->list[st->instance_id].regs, num, true); - } - } else { - ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name); - script->reportsrc(st); - } + set_reg_instance_num(st, num, name, val); return 1; default: return pc_setglobalreg(sd, num, val); @@ -20613,6 +20652,14 @@ void script_defaults(void) { script->push_val = push_val; script->get_val = get_val; script->get_val2 = get_val2; + script->get_val_ref_str = get_val_npcscope_str; + script->get_val_scope_str = get_val_npcscope_str; + script->get_val_npc_str = get_val_npcscope_str; + script->get_val_instance_str = get_val_instance_str; + script->get_val_ref_num = get_val_npcscope_num; + script->get_val_scope_num = get_val_npcscope_num; + script->get_val_npc_num = get_val_npcscope_num; + script->get_val_instance_num = get_val_instance_num; script->push_str = push_str; script->push_copy = push_copy; script->pop_stack = pop_stack; @@ -20679,6 +20726,15 @@ void script_defaults(void) { script->print_line = script_print_line; script->errorwarning_sub = script_errorwarning_sub; script->set_reg = set_reg; + script->set_reg_ref_str = set_reg_npcscope_str; + script->set_reg_scope_str = set_reg_npcscope_str; + script->set_reg_npc_str = set_reg_npcscope_str; + script->set_reg_instance_str = set_reg_instance_str; + script->set_reg_ref_num = set_reg_npcscope_num; + script->set_reg_scope_num = set_reg_npcscope_num; + script->set_reg_npc_num = set_reg_npcscope_num; + script->set_reg_instance_num = set_reg_instance_num; + script->stack_expand = stack_expand; script->push_retinfo = push_retinfo; script->op_3 = op_3; diff --git a/src/map/script.h b/src/map/script.h index ad8ae82cb..ff660dec8 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -629,6 +629,14 @@ struct script_interface { void (*detach_rid) (struct script_state* st); struct script_data* (*push_val)(struct script_stack* stack, enum c_op type, int64 val, struct reg_db *ref); struct script_data *(*get_val) (struct script_state* st, struct script_data* data); + char* (*get_val_ref_str) (struct script_state* st, struct reg_db *n, struct script_data* data); + char* (*get_val_scope_str) (struct script_state* st, struct reg_db *n, struct script_data* data); + char* (*get_val_npc_str) (struct script_state* st, struct reg_db *n, struct script_data* data); + char* (*get_val_instance_str) (struct script_state* st, const char* name, struct script_data* data); + int (*get_val_ref_num) (struct script_state* st, struct reg_db *n, struct script_data* data); + int (*get_val_scope_num) (struct script_state* st, struct reg_db *n, struct script_data* data); + int (*get_val_npc_num) (struct script_state* st, struct reg_db *n, struct script_data* data); + int (*get_val_instance_num) (struct script_state* st, const char* name, struct script_data* data); void* (*get_val2) (struct script_state* st, int64 uid, struct reg_db *ref); struct script_data* (*push_str) (struct script_stack* stack, enum c_op type, char* str); struct script_data* (*push_copy) (struct script_stack* stack, int pos); @@ -696,6 +704,14 @@ struct script_interface { const char* (*print_line) (StringBuf *buf, const char *p, const char *mark, int line); void (*errorwarning_sub) (StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos); int (*set_reg) (struct script_state *st, TBL_PC *sd, int64 num, const char *name, const void *value, struct reg_db *ref); + void (*set_reg_ref_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str); + void (*set_reg_scope_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str); + void (*set_reg_npc_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str); + void (*set_reg_instance_str) (struct script_state* st, int64 num, const char* name, const char *str); + void (*set_reg_ref_num) (struct script_state* st, struct reg_db *n, int64 num, const char* name, int val); + void (*set_reg_scope_num) (struct script_state* st, struct reg_db *n, int64 num, const char* name, int val); + void (*set_reg_npc_num) (struct script_state* st, struct reg_db *n, int64 num, const char* name, int val); + void (*set_reg_instance_num) (struct script_state* st, int64 num, const char* name, int val); void (*stack_expand) (struct script_stack *stack); struct script_data* (*push_retinfo) (struct script_stack *stack, struct script_retinfo *ri, struct reg_db *ref); void (*op_3) (struct script_state *st, int op); diff --git a/src/map/searchstore.c b/src/map/searchstore.c index 46b102ad5..cdcf51b0e 100644 --- a/src/map/searchstore.c +++ b/src/map/searchstore.c @@ -10,7 +10,7 @@ #include "map/clif.h" // clif-"open_search_store_info, clif-"search_store_info_* #include "map/pc.h" // struct map_session_data #include "common/cbasetypes.h" -#include "common/malloc.h" // aMalloc, aRealloc, aFree +#include "common/memmgr.h" // aMalloc, aRealloc, aFree #include "common/showmsg.h" // ShowError, ShowWarning #include "common/strlib.h" // safestrncpy diff --git a/src/map/skill.c b/src/map/skill.c index a9ebf6998..cdf1c031f 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -31,7 +31,7 @@ #include "map/unit.h" #include "common/cbasetypes.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" diff --git a/src/map/status.c b/src/map/status.c index 3ba80e531..7a7a4f415 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -28,13 +28,14 @@ #include "map/vending.h" #include "common/cbasetypes.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/timer.h" #include "common/utils.h" +#include "common/conf.h" #include <math.h> #include <memory.h> @@ -8960,6 +8961,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t { int hp = status_get_hp(bl), sp = status_get_sp(bl), lv = 5; + if (sp < 1) sp = 1; + if (hp < 1) hp = 1; + if( rnd()%100 > (25 + 10 * val1) - status_get_int(bl) / 2) return 0; @@ -12263,38 +12267,136 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) return true; } -bool status_readdb_refine(char* fields[], int columns, int current) +/** + * Processes a refine_db.conf entry. + * + * @param *r Libconfig setting entry. It is expected to be valid and it + * won't be freed (it is care of the caller to do so if + * necessary) + * @param n Ordinal number of the entry, to be displayed in case of + * validation errors. + * @param *source Source of the entry (file name), to be displayed in case of + * validation errors. + * @return # of the validated entry, or 0 in case of failure. + */ +int status_readdb_refine_libconfig_sub(config_setting_t *r, const char *name, const char *source) { - int i, bonus_per_level, random_bonus, random_bonus_start_level; - - current = atoi(fields[0]); - - if (current < 0 || current >= REFINE_TYPE_MAX) - return false; - - bonus_per_level = atoi(fields[1]); - random_bonus_start_level = atoi(fields[2]); - random_bonus = atoi(fields[3]); - - for(i = 0; i < MAX_REFINE; i++) - { - char* delim; - - if (!(delim = strchr(fields[4+i], ':'))) - return false; - - *delim = '\0'; - - status->dbs->refine_info[current].chance[i] = atoi(fields[4+i]); + config_setting_t *rate = NULL; + int type = REFINE_TYPE_ARMOR, bonus_per_level = 0, rnd_bonus_v = 0, rnd_bonus_lv = 0; + char lv[4]; + nullpo_ret(r); + nullpo_ret(name); + nullpo_ret(source); + + if (strncmp(name, "Armors", 6) == 0) { + type = REFINE_TYPE_ARMOR; + } else if (strncmp(name, "WeaponLevel", 11) != 0 || !strspn(&name[strlen(name)-1], "0123456789") || (type = atoi(strncpy(lv, name+11, 2))) == REFINE_TYPE_ARMOR) { + ShowError("status_readdb_refine_libconfig_sub: Invalid key name for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (type < REFINE_TYPE_ARMOR || type >= REFINE_TYPE_MAX) { + ShowError("status_readdb_refine_libconfig_sub: Out of range level for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (!libconfig->setting_lookup_int(r, "StatsPerLevel", &bonus_per_level)) { + ShowWarning("status_readdb_refine_libconfig_sub: Missing StatsPerLevel for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (!libconfig->setting_lookup_int(r, "RandomBonusStartLevel", &rnd_bonus_lv)) { + ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusStartLevel for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (!libconfig->setting_lookup_int(r, "RandomBonusValue", &rnd_bonus_v)) { + ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusValue for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } - if (i >= random_bonus_start_level - 1) - status->dbs->refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); + if ((rate=libconfig->setting_get_member(r, "Rates")) != NULL && config_setting_is_group(rate)) { + config_setting_t *t = NULL; + bool duplicate[MAX_REFINE]; + int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE], chance[MAX_REFINE]; + int i; + memset(&duplicate, 0, sizeof(duplicate)); + memset(&bonus, 0, sizeof(bonus)); + memset(&rnd_bonus, 0, sizeof(rnd_bonus)); + + for (i = 0; i < MAX_REFINE; i++) { + chance[i] = 100; + } + i = 0; + while ((t = libconfig->setting_get_elem(rate,i++)) != NULL && config_setting_is_group(t)) { + int level = 0, i32; + char *rlvl = config_setting_name(t); + memset(&lv, 0, sizeof(lv)); + if (!strspn(&rlvl[strlen(rlvl)-1], "0123456789") || (level = atoi(strncpy(lv, rlvl+2, 3))) <= 0) { + ShowError("status_readdb_refine_libconfig_sub: Invalid refine level format '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); + continue; + } + if (level <= 0 || level > MAX_REFINE) { + ShowError("status_readdb_refine_libconfig_sub: Out of range refine level '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); + continue; + } + level--; + if (duplicate[level]) { + ShowWarning("status_readdb_refine_libconfig_sub: duplicate rate '%s' for entry %s in \"%s\", overwriting previous entry...\n", rlvl, name, source); + } else { + duplicate[level] = true; + } + if (libconfig->setting_lookup_int(t, "Chance", &i32)) + chance[level] = i32; + else + chance[level] = 100; + if (libconfig->setting_lookup_int(t, "Bonus", &i32)) + bonus[level] += i32; + if (level >= rnd_bonus_lv - 1) + rnd_bonus[level] = rnd_bonus_v * (level - rnd_bonus_lv + 2); + } + for (i = 0; i < MAX_REFINE; i++) { + status->dbs->refine_info[type].chance[i] = chance[i]; + status->dbs->refine_info[type].randombonus_max[i] = rnd_bonus[i]; + bonus[i] += bonus_per_level + (i > 0 ? bonus[i-1] : 0); + status->dbs->refine_info[type].bonus[i] = bonus[i]; + } + } else { + ShowWarning("status_readdb_refine_libconfig_sub: Missing refine rates for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + return type+1; +} - status->dbs->refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); - if (i > 0) - status->dbs->refine_info[current].bonus[i] += status->dbs->refine_info[current].bonus[i-1]; +/** + * Reads from a libconfig-formatted refine_db.conf file. + * + * @param *filename File name, relative to the database path. + * @return The number of found entries. + */ +int status_readdb_refine_libconfig(const char *filename) { + bool duplicate[REFINE_TYPE_MAX]; + config_t refine_db_conf; + config_setting_t *r; + char filepath[256]; + int i = 0, count = 0,type = 0; + + sprintf(filepath, "%s/%s", map->db_path, filename); + memset(&duplicate,0,sizeof(duplicate)); + if( libconfig->read_file(&refine_db_conf, filepath) ) { + ShowError("can't read %s\n", filepath); + return 0; } - return true; + + while((r = libconfig->setting_get_elem(refine_db_conf.root,i++))) { + char *name = config_setting_name(r); + if((type=status->readdb_refine_libconfig_sub(r, name, filename))) { + if( duplicate[type-1] ) { + ShowWarning("status_readdb_refine_libconfig: duplicate entry for %s in \"%s\", overwriting previous entry...\n", name, filename); + } else duplicate[type-1] = true; + count++; + } + } + libconfig->destroy(&refine_db_conf); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); + + return count; } bool status_readdb_scconfig(char* fields[], int columns, int current) { @@ -12357,7 +12459,7 @@ int status_readdb(void) // sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2); sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix); - sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->dbs->refine_info), status->readdb_refine); + status->readdb_refine_libconfig(DBPATH"refine_db.conf"); sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig); status->read_job_db(); @@ -12532,7 +12634,8 @@ void status_defaults(void) { status->natural_heal_timer = status_natural_heal_timer; status->readdb_job2 = status_readdb_job2; status->readdb_sizefix = status_readdb_sizefix; - status->readdb_refine = status_readdb_refine; + status->readdb_refine_libconfig = status_readdb_refine_libconfig; + status->readdb_refine_libconfig_sub = status_readdb_refine_libconfig_sub; status->readdb_scconfig = status_readdb_scconfig; status->read_job_db = status_read_job_db; status->read_job_db_sub = status_read_job_db_sub; diff --git a/src/map/status.h b/src/map/status.h index 274c64c5b..d49bca8b4 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -2077,7 +2077,8 @@ struct status_interface { int (*natural_heal_timer) (int tid, int64 tick, int id, intptr_t data); bool (*readdb_job2) (char *fields[], int columns, int current); bool (*readdb_sizefix) (char *fields[], int columns, int current); - bool (*readdb_refine) (char *fields[], int columns, int current); + int (*readdb_refine_libconfig) (const char *filename); + int (*readdb_refine_libconfig_sub) (config_setting_t *r, const char *name, const char *source); bool (*readdb_scconfig) (char *fields[], int columns, int current); void (*read_job_db) (void); void (*read_job_db_sub) (int idx, const char *name, config_setting_t *jdb); diff --git a/src/map/storage.c b/src/map/storage.c index fb6e2ed45..29f44f5e7 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -18,7 +18,7 @@ #include "map/pc.h" #include "common/cbasetypes.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include <stdio.h> diff --git a/src/map/unit.c b/src/map/unit.c index 04a8befc2..7c253c5c2 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -34,7 +34,7 @@ #include "map/vending.h" #include "common/HPM.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" @@ -2654,17 +2654,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) { sd->quest_log = NULL; sd->num_quests = sd->avail_quests = 0; } - - if (sd->hdata) { - unsigned int k; - for( k = 0; k < sd->hdatac; k++ ) { - if( sd->hdata[k]->flag.free ) { - aFree(sd->hdata[k]->data); - } - aFree(sd->hdata[k]); - } - aFree(sd->hdata); - } + HPM->data_store_destroy(&sd->hdata); break; } case BL_PET: @@ -2775,17 +2765,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) { if( md->tomb_nid ) mob->mvptomb_destroy(md); - if (md->hdata) - { - unsigned int k; - for (k = 0; k < md->hdatac; k++) { - if( md->hdata[k]->flag.free ) { - aFree(md->hdata[k]->data); - } - aFree(md->hdata[k]); - } - aFree(md->hdata); - } + HPM->data_store_destroy(&md->hdata); break; } case BL_HOM: diff --git a/src/plugins/HPMHooking.c b/src/plugins/HPMHooking.c index e5483da5b..a975c034e 100644 --- a/src/plugins/HPMHooking.c +++ b/src/plugins/HPMHooking.c @@ -4,7 +4,7 @@ #include "common/hercules.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/socket.h" @@ -89,7 +89,7 @@ #include "common/conf.h" #include "common/console.h" #include "common/db.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/socket.h" diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc index 2e35992bc..e113611e4 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc @@ -15775,15 +15775,15 @@ bool HP_sockt_trusted_ip_check(uint32 ip) { } return retVal___; } -int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) { +int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) { int hIndex = 0; int retVal___ = 0; if( HPMHooks.count.HP_sockt_net_config_read_sub_pre ) { - int (*preHookFunc) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*preHookFunc) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_pre[hIndex].func; - retVal___ = preHookFunc(t, list, count, filename, groupname); + retVal___ = preHookFunc(t, list, filename, groupname); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -15791,13 +15791,13 @@ int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, in } } { - retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, count, filename, groupname); + retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, filename, groupname); } if( HPMHooks.count.HP_sockt_net_config_read_sub_post ) { - int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_post[hIndex].func; - retVal___ = postHookFunc(retVal___, t, list, count, filename, groupname); + retVal___ = postHookFunc(retVal___, t, list, filename, groupname); } } return retVal___; diff --git a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc index 94b298d36..5d4fad4d8 100644 --- a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc @@ -5048,15 +5048,15 @@ bool HP_sockt_trusted_ip_check(uint32 ip) { } return retVal___; } -int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) { +int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) { int hIndex = 0; int retVal___ = 0; if( HPMHooks.count.HP_sockt_net_config_read_sub_pre ) { - int (*preHookFunc) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*preHookFunc) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_pre[hIndex].func; - retVal___ = preHookFunc(t, list, count, filename, groupname); + retVal___ = preHookFunc(t, list, filename, groupname); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -5064,13 +5064,13 @@ int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, in } } { - retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, count, filename, groupname); + retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, filename, groupname); } if( HPMHooks.count.HP_sockt_net_config_read_sub_post ) { - int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_post[hIndex].func; - retVal___ = postHookFunc(retVal___, t, list, count, filename, groupname); + retVal___ = postHookFunc(retVal___, t, list, filename, groupname); } } return retVal___; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index 408d7d0cd..258fc0512 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -497,6 +497,8 @@ struct { struct HPMHookPoint *HP_clif_send_actual_post; struct HPMHookPoint *HP_clif_parse_pre; struct HPMHookPoint *HP_clif_parse_post; + struct HPMHookPoint *HP_clif_packet_pre; + struct HPMHookPoint *HP_clif_packet_post; struct HPMHookPoint *HP_clif_parse_cmd_pre; struct HPMHookPoint *HP_clif_parse_cmd_post; struct HPMHookPoint *HP_clif_decrypt_cmd_pre; @@ -2687,14 +2689,10 @@ struct { struct HPMHookPoint *HP_itemdb_validate_entry_post; struct HPMHookPoint *HP_itemdb_readdb_additional_fields_pre; struct HPMHookPoint *HP_itemdb_readdb_additional_fields_post; - struct HPMHookPoint *HP_itemdb_readdb_sql_sub_pre; - struct HPMHookPoint *HP_itemdb_readdb_sql_sub_post; struct HPMHookPoint *HP_itemdb_readdb_libconfig_sub_pre; struct HPMHookPoint *HP_itemdb_readdb_libconfig_sub_post; struct HPMHookPoint *HP_itemdb_readdb_libconfig_pre; struct HPMHookPoint *HP_itemdb_readdb_libconfig_post; - struct HPMHookPoint *HP_itemdb_readdb_sql_pre; - struct HPMHookPoint *HP_itemdb_readdb_sql_post; struct HPMHookPoint *HP_itemdb_unique_id_pre; struct HPMHookPoint *HP_itemdb_unique_id_post; struct HPMHookPoint *HP_itemdb_read_pre; @@ -3437,14 +3435,26 @@ struct { struct HPMHookPoint *HP_mob_drop_adjust_post; struct HPMHookPoint *HP_mob_item_dropratio_adjust_pre; struct HPMHookPoint *HP_mob_item_dropratio_adjust_post; - struct HPMHookPoint *HP_mob_parse_dbrow_pre; - struct HPMHookPoint *HP_mob_parse_dbrow_post; - struct HPMHookPoint *HP_mob_readdb_sub_pre; - struct HPMHookPoint *HP_mob_readdb_sub_post; struct HPMHookPoint *HP_mob_readdb_pre; struct HPMHookPoint *HP_mob_readdb_post; - struct HPMHookPoint *HP_mob_read_sqldb_pre; - struct HPMHookPoint *HP_mob_read_sqldb_post; + struct HPMHookPoint *HP_mob_lookup_const_pre; + struct HPMHookPoint *HP_mob_lookup_const_post; + struct HPMHookPoint *HP_mob_get_const_pre; + struct HPMHookPoint *HP_mob_get_const_post; + struct HPMHookPoint *HP_mob_read_libconfig_pre; + struct HPMHookPoint *HP_mob_read_libconfig_post; + struct HPMHookPoint *HP_mob_read_db_additional_fields_pre; + struct HPMHookPoint *HP_mob_read_db_additional_fields_post; + struct HPMHookPoint *HP_mob_read_db_sub_pre; + struct HPMHookPoint *HP_mob_read_db_sub_post; + struct HPMHookPoint *HP_mob_read_db_drops_sub_pre; + struct HPMHookPoint *HP_mob_read_db_drops_sub_post; + struct HPMHookPoint *HP_mob_read_db_mvpdrops_sub_pre; + struct HPMHookPoint *HP_mob_read_db_mvpdrops_sub_post; + struct HPMHookPoint *HP_mob_read_db_mode_sub_pre; + struct HPMHookPoint *HP_mob_read_db_mode_sub_post; + struct HPMHookPoint *HP_mob_read_db_stats_sub_pre; + struct HPMHookPoint *HP_mob_read_db_stats_sub_post; struct HPMHookPoint *HP_mob_name_constants_pre; struct HPMHookPoint *HP_mob_name_constants_post; struct HPMHookPoint *HP_mob_readdb_mobavail_pre; @@ -3459,8 +3469,6 @@ struct { struct HPMHookPoint *HP_mob_parse_row_mobskilldb_post; struct HPMHookPoint *HP_mob_readskilldb_pre; struct HPMHookPoint *HP_mob_readskilldb_post; - struct HPMHookPoint *HP_mob_read_sqlskilldb_pre; - struct HPMHookPoint *HP_mob_read_sqlskilldb_post; struct HPMHookPoint *HP_mob_readdb_race2_pre; struct HPMHookPoint *HP_mob_readdb_race2_post; struct HPMHookPoint *HP_mob_readdb_itemratio_pre; @@ -4381,6 +4389,22 @@ struct { struct HPMHookPoint *HP_script_push_val_post; struct HPMHookPoint *HP_script_get_val_pre; struct HPMHookPoint *HP_script_get_val_post; + struct HPMHookPoint *HP_script_get_val_ref_str_pre; + struct HPMHookPoint *HP_script_get_val_ref_str_post; + struct HPMHookPoint *HP_script_get_val_scope_str_pre; + struct HPMHookPoint *HP_script_get_val_scope_str_post; + struct HPMHookPoint *HP_script_get_val_npc_str_pre; + struct HPMHookPoint *HP_script_get_val_npc_str_post; + struct HPMHookPoint *HP_script_get_val_instance_str_pre; + struct HPMHookPoint *HP_script_get_val_instance_str_post; + struct HPMHookPoint *HP_script_get_val_ref_num_pre; + struct HPMHookPoint *HP_script_get_val_ref_num_post; + struct HPMHookPoint *HP_script_get_val_scope_num_pre; + struct HPMHookPoint *HP_script_get_val_scope_num_post; + struct HPMHookPoint *HP_script_get_val_npc_num_pre; + struct HPMHookPoint *HP_script_get_val_npc_num_post; + struct HPMHookPoint *HP_script_get_val_instance_num_pre; + struct HPMHookPoint *HP_script_get_val_instance_num_post; struct HPMHookPoint *HP_script_get_val2_pre; struct HPMHookPoint *HP_script_get_val2_post; struct HPMHookPoint *HP_script_push_str_pre; @@ -4511,6 +4535,22 @@ struct { struct HPMHookPoint *HP_script_errorwarning_sub_post; struct HPMHookPoint *HP_script_set_reg_pre; struct HPMHookPoint *HP_script_set_reg_post; + struct HPMHookPoint *HP_script_set_reg_ref_str_pre; + struct HPMHookPoint *HP_script_set_reg_ref_str_post; + struct HPMHookPoint *HP_script_set_reg_scope_str_pre; + struct HPMHookPoint *HP_script_set_reg_scope_str_post; + struct HPMHookPoint *HP_script_set_reg_npc_str_pre; + struct HPMHookPoint *HP_script_set_reg_npc_str_post; + struct HPMHookPoint *HP_script_set_reg_instance_str_pre; + struct HPMHookPoint *HP_script_set_reg_instance_str_post; + struct HPMHookPoint *HP_script_set_reg_ref_num_pre; + struct HPMHookPoint *HP_script_set_reg_ref_num_post; + struct HPMHookPoint *HP_script_set_reg_scope_num_pre; + struct HPMHookPoint *HP_script_set_reg_scope_num_post; + struct HPMHookPoint *HP_script_set_reg_npc_num_pre; + struct HPMHookPoint *HP_script_set_reg_npc_num_post; + struct HPMHookPoint *HP_script_set_reg_instance_num_pre; + struct HPMHookPoint *HP_script_set_reg_instance_num_post; struct HPMHookPoint *HP_script_stack_expand_pre; struct HPMHookPoint *HP_script_stack_expand_post; struct HPMHookPoint *HP_script_push_retinfo_pre; @@ -5437,8 +5477,10 @@ struct { struct HPMHookPoint *HP_status_readdb_job2_post; struct HPMHookPoint *HP_status_readdb_sizefix_pre; struct HPMHookPoint *HP_status_readdb_sizefix_post; - struct HPMHookPoint *HP_status_readdb_refine_pre; - struct HPMHookPoint *HP_status_readdb_refine_post; + struct HPMHookPoint *HP_status_readdb_refine_libconfig_pre; + struct HPMHookPoint *HP_status_readdb_refine_libconfig_post; + struct HPMHookPoint *HP_status_readdb_refine_libconfig_sub_pre; + struct HPMHookPoint *HP_status_readdb_refine_libconfig_sub_post; struct HPMHookPoint *HP_status_readdb_scconfig_pre; struct HPMHookPoint *HP_status_readdb_scconfig_post; struct HPMHookPoint *HP_status_read_job_db_pre; @@ -6220,6 +6262,8 @@ struct { int HP_clif_send_actual_post; int HP_clif_parse_pre; int HP_clif_parse_post; + int HP_clif_packet_pre; + int HP_clif_packet_post; int HP_clif_parse_cmd_pre; int HP_clif_parse_cmd_post; int HP_clif_decrypt_cmd_pre; @@ -8410,14 +8454,10 @@ struct { int HP_itemdb_validate_entry_post; int HP_itemdb_readdb_additional_fields_pre; int HP_itemdb_readdb_additional_fields_post; - int HP_itemdb_readdb_sql_sub_pre; - int HP_itemdb_readdb_sql_sub_post; int HP_itemdb_readdb_libconfig_sub_pre; int HP_itemdb_readdb_libconfig_sub_post; int HP_itemdb_readdb_libconfig_pre; int HP_itemdb_readdb_libconfig_post; - int HP_itemdb_readdb_sql_pre; - int HP_itemdb_readdb_sql_post; int HP_itemdb_unique_id_pre; int HP_itemdb_unique_id_post; int HP_itemdb_read_pre; @@ -9160,14 +9200,26 @@ struct { int HP_mob_drop_adjust_post; int HP_mob_item_dropratio_adjust_pre; int HP_mob_item_dropratio_adjust_post; - int HP_mob_parse_dbrow_pre; - int HP_mob_parse_dbrow_post; - int HP_mob_readdb_sub_pre; - int HP_mob_readdb_sub_post; int HP_mob_readdb_pre; int HP_mob_readdb_post; - int HP_mob_read_sqldb_pre; - int HP_mob_read_sqldb_post; + int HP_mob_lookup_const_pre; + int HP_mob_lookup_const_post; + int HP_mob_get_const_pre; + int HP_mob_get_const_post; + int HP_mob_read_libconfig_pre; + int HP_mob_read_libconfig_post; + int HP_mob_read_db_additional_fields_pre; + int HP_mob_read_db_additional_fields_post; + int HP_mob_read_db_sub_pre; + int HP_mob_read_db_sub_post; + int HP_mob_read_db_drops_sub_pre; + int HP_mob_read_db_drops_sub_post; + int HP_mob_read_db_mvpdrops_sub_pre; + int HP_mob_read_db_mvpdrops_sub_post; + int HP_mob_read_db_mode_sub_pre; + int HP_mob_read_db_mode_sub_post; + int HP_mob_read_db_stats_sub_pre; + int HP_mob_read_db_stats_sub_post; int HP_mob_name_constants_pre; int HP_mob_name_constants_post; int HP_mob_readdb_mobavail_pre; @@ -9182,8 +9234,6 @@ struct { int HP_mob_parse_row_mobskilldb_post; int HP_mob_readskilldb_pre; int HP_mob_readskilldb_post; - int HP_mob_read_sqlskilldb_pre; - int HP_mob_read_sqlskilldb_post; int HP_mob_readdb_race2_pre; int HP_mob_readdb_race2_post; int HP_mob_readdb_itemratio_pre; @@ -10104,6 +10154,22 @@ struct { int HP_script_push_val_post; int HP_script_get_val_pre; int HP_script_get_val_post; + int HP_script_get_val_ref_str_pre; + int HP_script_get_val_ref_str_post; + int HP_script_get_val_scope_str_pre; + int HP_script_get_val_scope_str_post; + int HP_script_get_val_npc_str_pre; + int HP_script_get_val_npc_str_post; + int HP_script_get_val_instance_str_pre; + int HP_script_get_val_instance_str_post; + int HP_script_get_val_ref_num_pre; + int HP_script_get_val_ref_num_post; + int HP_script_get_val_scope_num_pre; + int HP_script_get_val_scope_num_post; + int HP_script_get_val_npc_num_pre; + int HP_script_get_val_npc_num_post; + int HP_script_get_val_instance_num_pre; + int HP_script_get_val_instance_num_post; int HP_script_get_val2_pre; int HP_script_get_val2_post; int HP_script_push_str_pre; @@ -10234,6 +10300,22 @@ struct { int HP_script_errorwarning_sub_post; int HP_script_set_reg_pre; int HP_script_set_reg_post; + int HP_script_set_reg_ref_str_pre; + int HP_script_set_reg_ref_str_post; + int HP_script_set_reg_scope_str_pre; + int HP_script_set_reg_scope_str_post; + int HP_script_set_reg_npc_str_pre; + int HP_script_set_reg_npc_str_post; + int HP_script_set_reg_instance_str_pre; + int HP_script_set_reg_instance_str_post; + int HP_script_set_reg_ref_num_pre; + int HP_script_set_reg_ref_num_post; + int HP_script_set_reg_scope_num_pre; + int HP_script_set_reg_scope_num_post; + int HP_script_set_reg_npc_num_pre; + int HP_script_set_reg_npc_num_post; + int HP_script_set_reg_instance_num_pre; + int HP_script_set_reg_instance_num_post; int HP_script_stack_expand_pre; int HP_script_stack_expand_post; int HP_script_push_retinfo_pre; @@ -11160,8 +11242,10 @@ struct { int HP_status_readdb_job2_post; int HP_status_readdb_sizefix_pre; int HP_status_readdb_sizefix_post; - int HP_status_readdb_refine_pre; - int HP_status_readdb_refine_post; + int HP_status_readdb_refine_libconfig_pre; + int HP_status_readdb_refine_libconfig_post; + int HP_status_readdb_refine_libconfig_sub_pre; + int HP_status_readdb_refine_libconfig_sub_post; int HP_status_readdb_scconfig_pre; int HP_status_readdb_scconfig_post; int HP_status_read_job_db_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index d0d97192e..f793c9505 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -260,6 +260,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(clif->send_sub, HP_clif_send_sub) }, { HP_POP(clif->send_actual, HP_clif_send_actual) }, { HP_POP(clif->parse, HP_clif_parse) }, + { HP_POP(clif->packet, HP_clif_packet) }, { HP_POP(clif->parse_cmd, HP_clif_parse_cmd) }, { HP_POP(clif->decrypt_cmd, HP_clif_decrypt_cmd) }, { HP_POP(clif->authok, HP_clif_authok) }, @@ -1368,10 +1369,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(itemdb->gendercheck, HP_itemdb_gendercheck) }, { HP_POP(itemdb->validate_entry, HP_itemdb_validate_entry) }, { HP_POP(itemdb->readdb_additional_fields, HP_itemdb_readdb_additional_fields) }, - { HP_POP(itemdb->readdb_sql_sub, HP_itemdb_readdb_sql_sub) }, { HP_POP(itemdb->readdb_libconfig_sub, HP_itemdb_readdb_libconfig_sub) }, { HP_POP(itemdb->readdb_libconfig, HP_itemdb_readdb_libconfig) }, - { HP_POP(itemdb->readdb_sql, HP_itemdb_readdb_sql) }, { HP_POP(itemdb->unique_id, HP_itemdb_unique_id) }, { HP_POP(itemdb->read, HP_itemdb_read) }, { HP_POP(itemdb->destroy_item_data, HP_itemdb_destroy_item_data) }, @@ -1753,10 +1752,16 @@ struct HookingPointData HookingPoints[] = { { HP_POP(mob->clone_delete, HP_mob_clone_delete) }, { HP_POP(mob->drop_adjust, HP_mob_drop_adjust) }, { HP_POP(mob->item_dropratio_adjust, HP_mob_item_dropratio_adjust) }, - { HP_POP(mob->parse_dbrow, HP_mob_parse_dbrow) }, - { HP_POP(mob->readdb_sub, HP_mob_readdb_sub) }, { HP_POP(mob->readdb, HP_mob_readdb) }, - { HP_POP(mob->read_sqldb, HP_mob_read_sqldb) }, + { HP_POP(mob->lookup_const, HP_mob_lookup_const) }, + { HP_POP(mob->get_const, HP_mob_get_const) }, + { HP_POP(mob->read_libconfig, HP_mob_read_libconfig) }, + { HP_POP(mob->read_db_additional_fields, HP_mob_read_db_additional_fields) }, + { HP_POP(mob->read_db_sub, HP_mob_read_db_sub) }, + { HP_POP(mob->read_db_drops_sub, HP_mob_read_db_drops_sub) }, + { HP_POP(mob->read_db_mvpdrops_sub, HP_mob_read_db_mvpdrops_sub) }, + { HP_POP(mob->read_db_mode_sub, HP_mob_read_db_mode_sub) }, + { HP_POP(mob->read_db_stats_sub, HP_mob_read_db_stats_sub) }, { HP_POP(mob->name_constants, HP_mob_name_constants) }, { HP_POP(mob->readdb_mobavail, HP_mob_readdb_mobavail) }, { HP_POP(mob->read_randommonster, HP_mob_read_randommonster) }, @@ -1764,7 +1769,6 @@ struct HookingPointData HookingPoints[] = { { HP_POP(mob->readchatdb, HP_mob_readchatdb) }, { HP_POP(mob->parse_row_mobskilldb, HP_mob_parse_row_mobskilldb) }, { HP_POP(mob->readskilldb, HP_mob_readskilldb) }, - { HP_POP(mob->read_sqlskilldb, HP_mob_read_sqlskilldb) }, { HP_POP(mob->readdb_race2, HP_mob_readdb_race2) }, { HP_POP(mob->readdb_itemratio, HP_mob_readdb_itemratio) }, { HP_POP(mob->load, HP_mob_load) }, @@ -2234,6 +2238,14 @@ struct HookingPointData HookingPoints[] = { { HP_POP(script->detach_rid, HP_script_detach_rid) }, { HP_POP(script->push_val, HP_script_push_val) }, { HP_POP(script->get_val, HP_script_get_val) }, + { HP_POP(script->get_val_ref_str, HP_script_get_val_ref_str) }, + { HP_POP(script->get_val_scope_str, HP_script_get_val_scope_str) }, + { HP_POP(script->get_val_npc_str, HP_script_get_val_npc_str) }, + { HP_POP(script->get_val_instance_str, HP_script_get_val_instance_str) }, + { HP_POP(script->get_val_ref_num, HP_script_get_val_ref_num) }, + { HP_POP(script->get_val_scope_num, HP_script_get_val_scope_num) }, + { HP_POP(script->get_val_npc_num, HP_script_get_val_npc_num) }, + { HP_POP(script->get_val_instance_num, HP_script_get_val_instance_num) }, { HP_POP(script->get_val2, HP_script_get_val2) }, { HP_POP(script->push_str, HP_script_push_str) }, { HP_POP(script->push_copy, HP_script_push_copy) }, @@ -2299,6 +2311,14 @@ struct HookingPointData HookingPoints[] = { { HP_POP(script->print_line, HP_script_print_line) }, { HP_POP(script->errorwarning_sub, HP_script_errorwarning_sub) }, { HP_POP(script->set_reg, HP_script_set_reg) }, + { HP_POP(script->set_reg_ref_str, HP_script_set_reg_ref_str) }, + { HP_POP(script->set_reg_scope_str, HP_script_set_reg_scope_str) }, + { HP_POP(script->set_reg_npc_str, HP_script_set_reg_npc_str) }, + { HP_POP(script->set_reg_instance_str, HP_script_set_reg_instance_str) }, + { HP_POP(script->set_reg_ref_num, HP_script_set_reg_ref_num) }, + { HP_POP(script->set_reg_scope_num, HP_script_set_reg_scope_num) }, + { HP_POP(script->set_reg_npc_num, HP_script_set_reg_npc_num) }, + { HP_POP(script->set_reg_instance_num, HP_script_set_reg_instance_num) }, { HP_POP(script->stack_expand, HP_script_stack_expand) }, { HP_POP(script->push_retinfo, HP_script_push_retinfo) }, { HP_POP(script->op_3, HP_script_op_3) }, @@ -2768,7 +2788,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(status->natural_heal_timer, HP_status_natural_heal_timer) }, { HP_POP(status->readdb_job2, HP_status_readdb_job2) }, { HP_POP(status->readdb_sizefix, HP_status_readdb_sizefix) }, - { HP_POP(status->readdb_refine, HP_status_readdb_refine) }, + { HP_POP(status->readdb_refine_libconfig, HP_status_readdb_refine_libconfig) }, + { HP_POP(status->readdb_refine_libconfig_sub, HP_status_readdb_refine_libconfig_sub) }, { HP_POP(status->readdb_scconfig, HP_status_readdb_scconfig) }, { HP_POP(status->read_job_db, HP_status_read_job_db) }, { HP_POP(status->read_job_db_sub, HP_status_read_job_db_sub) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 5602014eb..b0bc853b3 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -6672,6 +6672,33 @@ int HP_clif_parse(int fd) { } return retVal___; } +const struct s_packet_db* HP_clif_packet(int packet_id) { + int hIndex = 0; + const struct s_packet_db* retVal___ = NULL; + if( HPMHooks.count.HP_clif_packet_pre ) { + const struct s_packet_db* (*preHookFunc) (int *packet_id); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_packet_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_clif_packet_pre[hIndex].func; + retVal___ = preHookFunc(&packet_id); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.clif.packet(packet_id); + } + if( HPMHooks.count.HP_clif_packet_post ) { + const struct s_packet_db* (*postHookFunc) (const struct s_packet_db* retVal___, int *packet_id); + for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_packet_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_clif_packet_post[hIndex].func; + retVal___ = postHookFunc(retVal___, &packet_id); + } + } + return retVal___; +} unsigned short HP_clif_parse_cmd(int fd, struct map_session_data *sd) { int hIndex = 0; unsigned short retVal___ = 0; @@ -35604,33 +35631,6 @@ void HP_itemdb_readdb_additional_fields(int itemid, config_setting_t *it, int n, } return; } -int HP_itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) { - int hIndex = 0; - int retVal___ = 0; - if( HPMHooks.count.HP_itemdb_readdb_sql_sub_pre ) { - int (*preHookFunc) (Sql *handle, int *n, const char *source); - *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_readdb_sql_sub_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_itemdb_readdb_sql_sub_pre[hIndex].func; - retVal___ = preHookFunc(handle, &n, source); - } - if( *HPMforce_return ) { - *HPMforce_return = false; - return retVal___; - } - } - { - retVal___ = HPMHooks.source.itemdb.readdb_sql_sub(handle, n, source); - } - if( HPMHooks.count.HP_itemdb_readdb_sql_sub_post ) { - int (*postHookFunc) (int retVal___, Sql *handle, int *n, const char *source); - for(hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_readdb_sql_sub_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_itemdb_readdb_sql_sub_post[hIndex].func; - retVal___ = postHookFunc(retVal___, handle, &n, source); - } - } - return retVal___; -} int HP_itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) { int hIndex = 0; int retVal___ = 0; @@ -35685,33 +35685,6 @@ int HP_itemdb_readdb_libconfig(const char *filename) { } return retVal___; } -int HP_itemdb_readdb_sql(const char *tablename) { - int hIndex = 0; - int retVal___ = 0; - if( HPMHooks.count.HP_itemdb_readdb_sql_pre ) { - int (*preHookFunc) (const char *tablename); - *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_readdb_sql_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_itemdb_readdb_sql_pre[hIndex].func; - retVal___ = preHookFunc(tablename); - } - if( *HPMforce_return ) { - *HPMforce_return = false; - return retVal___; - } - } - { - retVal___ = HPMHooks.source.itemdb.readdb_sql(tablename); - } - if( HPMHooks.count.HP_itemdb_readdb_sql_post ) { - int (*postHookFunc) (int retVal___, const char *tablename); - for(hIndex = 0; hIndex < HPMHooks.count.HP_itemdb_readdb_sql_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_itemdb_readdb_sql_post[hIndex].func; - retVal___ = postHookFunc(retVal___, tablename); - } - } - return retVal___; -} uint64 HP_itemdb_unique_id(struct map_session_data *sd) { int hIndex = 0; uint64 retVal___ = 0; @@ -45894,15 +45867,41 @@ void HP_mob_item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust) { } return; } -bool HP_mob_parse_dbrow(char **str) { +void HP_mob_readdb(void) { + int hIndex = 0; + if( HPMHooks.count.HP_mob_readdb_pre ) { + void (*preHookFunc) (void); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_readdb_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_readdb_pre[hIndex].func; + preHookFunc(); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.mob.readdb(); + } + if( HPMHooks.count.HP_mob_readdb_post ) { + void (*postHookFunc) (void); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_readdb_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_readdb_post[hIndex].func; + postHookFunc(); + } + } + return; +} +bool HP_mob_lookup_const(const config_setting_t *it, const char *name, int *value) { int hIndex = 0; bool retVal___ = false; - if( HPMHooks.count.HP_mob_parse_dbrow_pre ) { - bool (*preHookFunc) (char **str); + if( HPMHooks.count.HP_mob_lookup_const_pre ) { + bool (*preHookFunc) (const config_setting_t *it, const char *name, int *value); *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_parse_dbrow_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_mob_parse_dbrow_pre[hIndex].func; - retVal___ = preHookFunc(str); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_lookup_const_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_lookup_const_pre[hIndex].func; + retVal___ = preHookFunc(it, name, value); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -45910,26 +45909,26 @@ bool HP_mob_parse_dbrow(char **str) { } } { - retVal___ = HPMHooks.source.mob.parse_dbrow(str); + retVal___ = HPMHooks.source.mob.lookup_const(it, name, value); } - if( HPMHooks.count.HP_mob_parse_dbrow_post ) { - bool (*postHookFunc) (bool retVal___, char **str); - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_parse_dbrow_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_mob_parse_dbrow_post[hIndex].func; - retVal___ = postHookFunc(retVal___, str); + if( HPMHooks.count.HP_mob_lookup_const_post ) { + bool (*postHookFunc) (bool retVal___, const config_setting_t *it, const char *name, int *value); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_lookup_const_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_lookup_const_post[hIndex].func; + retVal___ = postHookFunc(retVal___, it, name, value); } } return retVal___; } -bool HP_mob_readdb_sub(char *fields[], int columns, int current) { +bool HP_mob_get_const(const config_setting_t *it, int *value) { int hIndex = 0; bool retVal___ = false; - if( HPMHooks.count.HP_mob_readdb_sub_pre ) { - bool (*preHookFunc) (char *fields[], int *columns, int *current); + if( HPMHooks.count.HP_mob_get_const_pre ) { + bool (*preHookFunc) (const config_setting_t *it, int *value); *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_readdb_sub_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_mob_readdb_sub_pre[hIndex].func; - retVal___ = preHookFunc(fields, &columns, ¤t); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_get_const_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_get_const_pre[hIndex].func; + retVal___ = preHookFunc(it, value); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -45937,25 +45936,52 @@ bool HP_mob_readdb_sub(char *fields[], int columns, int current) { } } { - retVal___ = HPMHooks.source.mob.readdb_sub(fields, columns, current); + retVal___ = HPMHooks.source.mob.get_const(it, value); } - if( HPMHooks.count.HP_mob_readdb_sub_post ) { - bool (*postHookFunc) (bool retVal___, char *fields[], int *columns, int *current); - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_readdb_sub_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_mob_readdb_sub_post[hIndex].func; - retVal___ = postHookFunc(retVal___, fields, &columns, ¤t); + if( HPMHooks.count.HP_mob_get_const_post ) { + bool (*postHookFunc) (bool retVal___, const config_setting_t *it, int *value); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_get_const_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_get_const_post[hIndex].func; + retVal___ = postHookFunc(retVal___, it, value); } } return retVal___; } -void HP_mob_readdb(void) { +int HP_mob_read_libconfig(const char *filename, bool ignore_missing) { int hIndex = 0; - if( HPMHooks.count.HP_mob_readdb_pre ) { - void (*preHookFunc) (void); + int retVal___ = 0; + if( HPMHooks.count.HP_mob_read_libconfig_pre ) { + int (*preHookFunc) (const char *filename, bool *ignore_missing); *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_readdb_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_mob_readdb_pre[hIndex].func; - preHookFunc(); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_libconfig_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_read_libconfig_pre[hIndex].func; + retVal___ = preHookFunc(filename, &ignore_missing); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.mob.read_libconfig(filename, ignore_missing); + } + if( HPMHooks.count.HP_mob_read_libconfig_post ) { + int (*postHookFunc) (int retVal___, const char *filename, bool *ignore_missing); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_libconfig_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_read_libconfig_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, &ignore_missing); + } + } + return retVal___; +} +void HP_mob_read_db_additional_fields(struct mob_db *entry, int class_, config_setting_t *it, int n, const char *source) { + int hIndex = 0; + if( HPMHooks.count.HP_mob_read_db_additional_fields_pre ) { + void (*preHookFunc) (struct mob_db *entry, int *class_, config_setting_t *it, int *n, const char *source); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_additional_fields_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_read_db_additional_fields_pre[hIndex].func; + preHookFunc(entry, &class_, it, &n, source); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -45963,26 +45989,105 @@ void HP_mob_readdb(void) { } } { - HPMHooks.source.mob.readdb(); + HPMHooks.source.mob.read_db_additional_fields(entry, class_, it, n, source); } - if( HPMHooks.count.HP_mob_readdb_post ) { - void (*postHookFunc) (void); - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_readdb_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_mob_readdb_post[hIndex].func; - postHookFunc(); + if( HPMHooks.count.HP_mob_read_db_additional_fields_post ) { + void (*postHookFunc) (struct mob_db *entry, int *class_, config_setting_t *it, int *n, const char *source); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_additional_fields_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_read_db_additional_fields_post[hIndex].func; + postHookFunc(entry, &class_, it, &n, source); + } + } + return; +} +bool HP_mob_read_db_sub(config_setting_t *mobt, int id, const char *source) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_mob_read_db_sub_pre ) { + bool (*preHookFunc) (config_setting_t *mobt, int *id, const char *source); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_sub_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_read_db_sub_pre[hIndex].func; + retVal___ = preHookFunc(mobt, &id, source); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.mob.read_db_sub(mobt, id, source); + } + if( HPMHooks.count.HP_mob_read_db_sub_post ) { + bool (*postHookFunc) (bool retVal___, config_setting_t *mobt, int *id, const char *source); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_sub_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_read_db_sub_post[hIndex].func; + retVal___ = postHookFunc(retVal___, mobt, &id, source); + } + } + return retVal___; +} +void HP_mob_read_db_drops_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) { + int hIndex = 0; + if( HPMHooks.count.HP_mob_read_db_drops_sub_pre ) { + void (*preHookFunc) (struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_drops_sub_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_read_db_drops_sub_pre[hIndex].func; + preHookFunc(entry, mstatus, &class_, t); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.mob.read_db_drops_sub(entry, mstatus, class_, t); + } + if( HPMHooks.count.HP_mob_read_db_drops_sub_post ) { + void (*postHookFunc) (struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_drops_sub_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_read_db_drops_sub_post[hIndex].func; + postHookFunc(entry, mstatus, &class_, t); + } + } + return; +} +void HP_mob_read_db_mvpdrops_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) { + int hIndex = 0; + if( HPMHooks.count.HP_mob_read_db_mvpdrops_sub_pre ) { + void (*preHookFunc) (struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_mvpdrops_sub_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_read_db_mvpdrops_sub_pre[hIndex].func; + preHookFunc(entry, mstatus, &class_, t); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.mob.read_db_mvpdrops_sub(entry, mstatus, class_, t); + } + if( HPMHooks.count.HP_mob_read_db_mvpdrops_sub_post ) { + void (*postHookFunc) (struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_mvpdrops_sub_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_read_db_mvpdrops_sub_post[hIndex].func; + postHookFunc(entry, mstatus, &class_, t); } } return; } -int HP_mob_read_sqldb(void) { +int HP_mob_read_db_mode_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) { int hIndex = 0; int retVal___ = 0; - if( HPMHooks.count.HP_mob_read_sqldb_pre ) { - int (*preHookFunc) (void); + if( HPMHooks.count.HP_mob_read_db_mode_sub_pre ) { + int (*preHookFunc) (struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_sqldb_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_mob_read_sqldb_pre[hIndex].func; - retVal___ = preHookFunc(); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_mode_sub_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_read_db_mode_sub_pre[hIndex].func; + retVal___ = preHookFunc(entry, mstatus, &class_, t); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -45990,17 +46095,43 @@ int HP_mob_read_sqldb(void) { } } { - retVal___ = HPMHooks.source.mob.read_sqldb(); + retVal___ = HPMHooks.source.mob.read_db_mode_sub(entry, mstatus, class_, t); } - if( HPMHooks.count.HP_mob_read_sqldb_post ) { - int (*postHookFunc) (int retVal___); - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_sqldb_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_mob_read_sqldb_post[hIndex].func; - retVal___ = postHookFunc(retVal___); + if( HPMHooks.count.HP_mob_read_db_mode_sub_post ) { + int (*postHookFunc) (int retVal___, struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_mode_sub_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_read_db_mode_sub_post[hIndex].func; + retVal___ = postHookFunc(retVal___, entry, mstatus, &class_, t); } } return retVal___; } +void HP_mob_read_db_stats_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) { + int hIndex = 0; + if( HPMHooks.count.HP_mob_read_db_stats_sub_pre ) { + void (*preHookFunc) (struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_stats_sub_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_mob_read_db_stats_sub_pre[hIndex].func; + preHookFunc(entry, mstatus, &class_, t); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.mob.read_db_stats_sub(entry, mstatus, class_, t); + } + if( HPMHooks.count.HP_mob_read_db_stats_sub_post ) { + void (*postHookFunc) (struct mob_db *entry, struct status_data *mstatus, int *class_, config_setting_t *t); + for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_db_stats_sub_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_mob_read_db_stats_sub_post[hIndex].func; + postHookFunc(entry, mstatus, &class_, t); + } + } + return; +} void HP_mob_name_constants(void) { int hIndex = 0; if( HPMHooks.count.HP_mob_name_constants_pre ) { @@ -46187,33 +46318,6 @@ void HP_mob_readskilldb(void) { } return; } -int HP_mob_read_sqlskilldb(void) { - int hIndex = 0; - int retVal___ = 0; - if( HPMHooks.count.HP_mob_read_sqlskilldb_pre ) { - int (*preHookFunc) (void); - *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_sqlskilldb_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_mob_read_sqlskilldb_pre[hIndex].func; - retVal___ = preHookFunc(); - } - if( *HPMforce_return ) { - *HPMforce_return = false; - return retVal___; - } - } - { - retVal___ = HPMHooks.source.mob.read_sqlskilldb(); - } - if( HPMHooks.count.HP_mob_read_sqlskilldb_post ) { - int (*postHookFunc) (int retVal___); - for(hIndex = 0; hIndex < HPMHooks.count.HP_mob_read_sqlskilldb_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_mob_read_sqlskilldb_post[hIndex].func; - retVal___ = postHookFunc(retVal___); - } - } - return retVal___; -} bool HP_mob_readdb_race2(char *fields[], int columns, int current) { int hIndex = 0; bool retVal___ = false; @@ -58677,6 +58781,222 @@ struct script_data* HP_script_get_val(struct script_state *st, struct script_dat } return retVal___; } +char* HP_script_get_val_ref_str(struct script_state *st, struct reg_db *n, struct script_data *data) { + int hIndex = 0; + char* retVal___ = NULL; + if( HPMHooks.count.HP_script_get_val_ref_str_pre ) { + char* (*preHookFunc) (struct script_state *st, struct reg_db *n, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_ref_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_ref_str_pre[hIndex].func; + retVal___ = preHookFunc(st, n, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_ref_str(st, n, data); + } + if( HPMHooks.count.HP_script_get_val_ref_str_post ) { + char* (*postHookFunc) (char* retVal___, struct script_state *st, struct reg_db *n, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_ref_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_ref_str_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, n, data); + } + } + return retVal___; +} +char* HP_script_get_val_scope_str(struct script_state *st, struct reg_db *n, struct script_data *data) { + int hIndex = 0; + char* retVal___ = NULL; + if( HPMHooks.count.HP_script_get_val_scope_str_pre ) { + char* (*preHookFunc) (struct script_state *st, struct reg_db *n, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_scope_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_scope_str_pre[hIndex].func; + retVal___ = preHookFunc(st, n, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_scope_str(st, n, data); + } + if( HPMHooks.count.HP_script_get_val_scope_str_post ) { + char* (*postHookFunc) (char* retVal___, struct script_state *st, struct reg_db *n, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_scope_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_scope_str_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, n, data); + } + } + return retVal___; +} +char* HP_script_get_val_npc_str(struct script_state *st, struct reg_db *n, struct script_data *data) { + int hIndex = 0; + char* retVal___ = NULL; + if( HPMHooks.count.HP_script_get_val_npc_str_pre ) { + char* (*preHookFunc) (struct script_state *st, struct reg_db *n, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_npc_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_npc_str_pre[hIndex].func; + retVal___ = preHookFunc(st, n, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_npc_str(st, n, data); + } + if( HPMHooks.count.HP_script_get_val_npc_str_post ) { + char* (*postHookFunc) (char* retVal___, struct script_state *st, struct reg_db *n, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_npc_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_npc_str_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, n, data); + } + } + return retVal___; +} +char* HP_script_get_val_instance_str(struct script_state *st, const char *name, struct script_data *data) { + int hIndex = 0; + char* retVal___ = NULL; + if( HPMHooks.count.HP_script_get_val_instance_str_pre ) { + char* (*preHookFunc) (struct script_state *st, const char *name, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_instance_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_instance_str_pre[hIndex].func; + retVal___ = preHookFunc(st, name, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_instance_str(st, name, data); + } + if( HPMHooks.count.HP_script_get_val_instance_str_post ) { + char* (*postHookFunc) (char* retVal___, struct script_state *st, const char *name, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_instance_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_instance_str_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, name, data); + } + } + return retVal___; +} +int HP_script_get_val_ref_num(struct script_state *st, struct reg_db *n, struct script_data *data) { + int hIndex = 0; + int retVal___ = 0; + if( HPMHooks.count.HP_script_get_val_ref_num_pre ) { + int (*preHookFunc) (struct script_state *st, struct reg_db *n, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_ref_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_ref_num_pre[hIndex].func; + retVal___ = preHookFunc(st, n, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_ref_num(st, n, data); + } + if( HPMHooks.count.HP_script_get_val_ref_num_post ) { + int (*postHookFunc) (int retVal___, struct script_state *st, struct reg_db *n, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_ref_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_ref_num_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, n, data); + } + } + return retVal___; +} +int HP_script_get_val_scope_num(struct script_state *st, struct reg_db *n, struct script_data *data) { + int hIndex = 0; + int retVal___ = 0; + if( HPMHooks.count.HP_script_get_val_scope_num_pre ) { + int (*preHookFunc) (struct script_state *st, struct reg_db *n, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_scope_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_scope_num_pre[hIndex].func; + retVal___ = preHookFunc(st, n, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_scope_num(st, n, data); + } + if( HPMHooks.count.HP_script_get_val_scope_num_post ) { + int (*postHookFunc) (int retVal___, struct script_state *st, struct reg_db *n, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_scope_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_scope_num_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, n, data); + } + } + return retVal___; +} +int HP_script_get_val_npc_num(struct script_state *st, struct reg_db *n, struct script_data *data) { + int hIndex = 0; + int retVal___ = 0; + if( HPMHooks.count.HP_script_get_val_npc_num_pre ) { + int (*preHookFunc) (struct script_state *st, struct reg_db *n, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_npc_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_npc_num_pre[hIndex].func; + retVal___ = preHookFunc(st, n, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_npc_num(st, n, data); + } + if( HPMHooks.count.HP_script_get_val_npc_num_post ) { + int (*postHookFunc) (int retVal___, struct script_state *st, struct reg_db *n, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_npc_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_npc_num_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, n, data); + } + } + return retVal___; +} +int HP_script_get_val_instance_num(struct script_state *st, const char *name, struct script_data *data) { + int hIndex = 0; + int retVal___ = 0; + if( HPMHooks.count.HP_script_get_val_instance_num_pre ) { + int (*preHookFunc) (struct script_state *st, const char *name, struct script_data *data); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_instance_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_get_val_instance_num_pre[hIndex].func; + retVal___ = preHookFunc(st, name, data); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.script.get_val_instance_num(st, name, data); + } + if( HPMHooks.count.HP_script_get_val_instance_num_post ) { + int (*postHookFunc) (int retVal___, struct script_state *st, const char *name, struct script_data *data); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_get_val_instance_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_get_val_instance_num_post[hIndex].func; + retVal___ = postHookFunc(retVal___, st, name, data); + } + } + return retVal___; +} void* HP_script_get_val2(struct script_state *st, int64 uid, struct reg_db *ref) { int hIndex = 0; void* retVal___ = NULL; @@ -60400,6 +60720,214 @@ int HP_script_set_reg(struct script_state *st, TBL_PC *sd, int64 num, const char } return retVal___; } +void HP_script_set_reg_ref_str(struct script_state *st, struct reg_db *n, int64 num, const char *name, const char *str) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_ref_str_pre ) { + void (*preHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, const char *str); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_ref_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_ref_str_pre[hIndex].func; + preHookFunc(st, n, &num, name, str); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_ref_str(st, n, num, name, str); + } + if( HPMHooks.count.HP_script_set_reg_ref_str_post ) { + void (*postHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, const char *str); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_ref_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_ref_str_post[hIndex].func; + postHookFunc(st, n, &num, name, str); + } + } + return; +} +void HP_script_set_reg_scope_str(struct script_state *st, struct reg_db *n, int64 num, const char *name, const char *str) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_scope_str_pre ) { + void (*preHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, const char *str); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_scope_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_scope_str_pre[hIndex].func; + preHookFunc(st, n, &num, name, str); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_scope_str(st, n, num, name, str); + } + if( HPMHooks.count.HP_script_set_reg_scope_str_post ) { + void (*postHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, const char *str); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_scope_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_scope_str_post[hIndex].func; + postHookFunc(st, n, &num, name, str); + } + } + return; +} +void HP_script_set_reg_npc_str(struct script_state *st, struct reg_db *n, int64 num, const char *name, const char *str) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_npc_str_pre ) { + void (*preHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, const char *str); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_npc_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_npc_str_pre[hIndex].func; + preHookFunc(st, n, &num, name, str); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_npc_str(st, n, num, name, str); + } + if( HPMHooks.count.HP_script_set_reg_npc_str_post ) { + void (*postHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, const char *str); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_npc_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_npc_str_post[hIndex].func; + postHookFunc(st, n, &num, name, str); + } + } + return; +} +void HP_script_set_reg_instance_str(struct script_state *st, int64 num, const char *name, const char *str) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_instance_str_pre ) { + void (*preHookFunc) (struct script_state *st, int64 *num, const char *name, const char *str); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_instance_str_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_instance_str_pre[hIndex].func; + preHookFunc(st, &num, name, str); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_instance_str(st, num, name, str); + } + if( HPMHooks.count.HP_script_set_reg_instance_str_post ) { + void (*postHookFunc) (struct script_state *st, int64 *num, const char *name, const char *str); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_instance_str_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_instance_str_post[hIndex].func; + postHookFunc(st, &num, name, str); + } + } + return; +} +void HP_script_set_reg_ref_num(struct script_state *st, struct reg_db *n, int64 num, const char *name, int val) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_ref_num_pre ) { + void (*preHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, int *val); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_ref_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_ref_num_pre[hIndex].func; + preHookFunc(st, n, &num, name, &val); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_ref_num(st, n, num, name, val); + } + if( HPMHooks.count.HP_script_set_reg_ref_num_post ) { + void (*postHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, int *val); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_ref_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_ref_num_post[hIndex].func; + postHookFunc(st, n, &num, name, &val); + } + } + return; +} +void HP_script_set_reg_scope_num(struct script_state *st, struct reg_db *n, int64 num, const char *name, int val) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_scope_num_pre ) { + void (*preHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, int *val); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_scope_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_scope_num_pre[hIndex].func; + preHookFunc(st, n, &num, name, &val); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_scope_num(st, n, num, name, val); + } + if( HPMHooks.count.HP_script_set_reg_scope_num_post ) { + void (*postHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, int *val); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_scope_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_scope_num_post[hIndex].func; + postHookFunc(st, n, &num, name, &val); + } + } + return; +} +void HP_script_set_reg_npc_num(struct script_state *st, struct reg_db *n, int64 num, const char *name, int val) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_npc_num_pre ) { + void (*preHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, int *val); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_npc_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_npc_num_pre[hIndex].func; + preHookFunc(st, n, &num, name, &val); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_npc_num(st, n, num, name, val); + } + if( HPMHooks.count.HP_script_set_reg_npc_num_post ) { + void (*postHookFunc) (struct script_state *st, struct reg_db *n, int64 *num, const char *name, int *val); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_npc_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_npc_num_post[hIndex].func; + postHookFunc(st, n, &num, name, &val); + } + } + return; +} +void HP_script_set_reg_instance_num(struct script_state *st, int64 num, const char *name, int val) { + int hIndex = 0; + if( HPMHooks.count.HP_script_set_reg_instance_num_pre ) { + void (*preHookFunc) (struct script_state *st, int64 *num, const char *name, int *val); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_instance_num_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_script_set_reg_instance_num_pre[hIndex].func; + preHookFunc(st, &num, name, &val); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.script.set_reg_instance_num(st, num, name, val); + } + if( HPMHooks.count.HP_script_set_reg_instance_num_post ) { + void (*postHookFunc) (struct script_state *st, int64 *num, const char *name, int *val); + for(hIndex = 0; hIndex < HPMHooks.count.HP_script_set_reg_instance_num_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_script_set_reg_instance_num_post[hIndex].func; + postHookFunc(st, &num, name, &val); + } + } + return; +} void HP_script_stack_expand(struct script_stack *stack) { int hIndex = 0; if( HPMHooks.count.HP_script_stack_expand_pre ) { @@ -69319,15 +69847,15 @@ bool HP_sockt_trusted_ip_check(uint32 ip) { } return retVal___; } -int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) { +int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) { int hIndex = 0; int retVal___ = 0; if( HPMHooks.count.HP_sockt_net_config_read_sub_pre ) { - int (*preHookFunc) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*preHookFunc) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_pre[hIndex].func; - retVal___ = preHookFunc(t, list, count, filename, groupname); + retVal___ = preHookFunc(t, list, filename, groupname); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -69335,13 +69863,13 @@ int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, in } } { - retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, count, filename, groupname); + retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, filename, groupname); } if( HPMHooks.count.HP_sockt_net_config_read_sub_post ) { - int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname); + int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname); for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_post[hIndex].func; - retVal___ = postHookFunc(retVal___, t, list, count, filename, groupname); + retVal___ = postHookFunc(retVal___, t, list, filename, groupname); } } return retVal___; @@ -73131,15 +73659,15 @@ bool HP_status_readdb_sizefix(char *fields[], int columns, int current) { } return retVal___; } -bool HP_status_readdb_refine(char *fields[], int columns, int current) { +int HP_status_readdb_refine_libconfig(const char *filename) { int hIndex = 0; - bool retVal___ = false; - if( HPMHooks.count.HP_status_readdb_refine_pre ) { - bool (*preHookFunc) (char *fields[], int *columns, int *current); + int retVal___ = 0; + if( HPMHooks.count.HP_status_readdb_refine_libconfig_pre ) { + int (*preHookFunc) (const char *filename); *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_status_readdb_refine_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_status_readdb_refine_pre[hIndex].func; - retVal___ = preHookFunc(fields, &columns, ¤t); + for(hIndex = 0; hIndex < HPMHooks.count.HP_status_readdb_refine_libconfig_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_status_readdb_refine_libconfig_pre[hIndex].func; + retVal___ = preHookFunc(filename); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -73147,13 +73675,40 @@ bool HP_status_readdb_refine(char *fields[], int columns, int current) { } } { - retVal___ = HPMHooks.source.status.readdb_refine(fields, columns, current); + retVal___ = HPMHooks.source.status.readdb_refine_libconfig(filename); } - if( HPMHooks.count.HP_status_readdb_refine_post ) { - bool (*postHookFunc) (bool retVal___, char *fields[], int *columns, int *current); - for(hIndex = 0; hIndex < HPMHooks.count.HP_status_readdb_refine_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_status_readdb_refine_post[hIndex].func; - retVal___ = postHookFunc(retVal___, fields, &columns, ¤t); + if( HPMHooks.count.HP_status_readdb_refine_libconfig_post ) { + int (*postHookFunc) (int retVal___, const char *filename); + for(hIndex = 0; hIndex < HPMHooks.count.HP_status_readdb_refine_libconfig_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_status_readdb_refine_libconfig_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename); + } + } + return retVal___; +} +int HP_status_readdb_refine_libconfig_sub(config_setting_t *r, const char *name, const char *source) { + int hIndex = 0; + int retVal___ = 0; + if( HPMHooks.count.HP_status_readdb_refine_libconfig_sub_pre ) { + int (*preHookFunc) (config_setting_t *r, const char *name, const char *source); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_status_readdb_refine_libconfig_sub_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_status_readdb_refine_libconfig_sub_pre[hIndex].func; + retVal___ = preHookFunc(r, name, source); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.status.readdb_refine_libconfig_sub(r, name, source); + } + if( HPMHooks.count.HP_status_readdb_refine_libconfig_sub_post ) { + int (*postHookFunc) (int retVal___, config_setting_t *r, const char *name, const char *source); + for(hIndex = 0; hIndex < HPMHooks.count.HP_status_readdb_refine_libconfig_sub_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_status_readdb_refine_libconfig_sub_post[hIndex].func; + retVal___ = postHookFunc(retVal___, r, name, source); } } return retVal___; diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c index 79eda0e5e..6d4a7789c 100644 --- a/src/plugins/db2sql.c +++ b/src/plugins/db2sql.c @@ -6,7 +6,7 @@ #include "common/hercules.h" #include "common/cbasetypes.h" #include "common/conf.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/strlib.h" #include "common/timer.h" @@ -290,11 +290,6 @@ void totable(void) { "\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; - } - /* link */ itemdb_readdb_libconfig_sub = itemdb->readdb_libconfig_sub; itemdb->readdb_libconfig_sub = db2sql; @@ -305,7 +300,7 @@ void do_db2sql(void) { return; } - tosql.db_name = map->item_db_db; + tosql.db_name = "item_db"; totable(); memset(&tosql.buf, 0, sizeof(tosql.buf) ); @@ -320,7 +315,7 @@ void do_db2sql(void) { return; } - tosql.db_name = map->item_db_db; + tosql.db_name = "item_db"; totable(); itemdb->clear(false); @@ -333,7 +328,7 @@ void do_db2sql(void) { return; } - tosql.db_name = map->item_db2_db; + tosql.db_name = "item_db2"; totable(); itemdb->clear(false); diff --git a/src/plugins/sample.c b/src/plugins/sample.c index 275edb129..fea25514b 100644 --- a/src/plugins/sample.c +++ b/src/plugins/sample.c @@ -3,7 +3,7 @@ // Sample Hercules Plugin #include "common/hercules.h" /* Should always be the first Hercules file included! (if you don't make it first, you won't be able to use interfaces) */ -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/socket.h" #include "common/strlib.h" diff --git a/src/test/Makefile.in b/src/test/Makefile.in index 8f999fb37..4d8f55e1f 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -24,10 +24,12 @@ MT19937AR_D = $(THIRDPARTY_D)/mt19937ar MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o MT19937AR_H = $(MT19937AR_D)/mt19937ar.h -TEST_SPINLOCK_OBJ = obj/test_spinlock.o -TEST_SPINLOCK_C = test_spinlock.c -TEST_SPINLOCK_H = -TEST_SPINLOCK_DEPENDS = $(TEST_SPINLOCK_OBJ) $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ $(SYSINFO_INC)) +TEST_C = test_libconfig.c test_spinlock.c +TEST_OBJ = $(addprefix obj/, $(patsubst %c,%o,%(TEST_C))) +TEST_H = +TEST_DEPENDS = $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(SYSINFO_INC) + +TESTS_ALL = test_libconfig test_spinlock @SET_MAKE@ @@ -35,9 +37,9 @@ CC = @CC@ export CC ##################################################################### -.PHONY: all test_spinlock clean buildclean +.PHONY: all $(TESTS_ALL) clean buildclean -all: test_spinlock Makefile +all: $(TESTS_ALL) Makefile buildclean: @echo " CLEAN test (build temp files)" @@ -45,14 +47,14 @@ buildclean: clean: buildclean @echo " CLEAN test" - @rm -rf ../../test_spinlock@EXEEXT@ + @rm -rf ../../test_*@EXEEXT@ ##################################################################### Makefile: Makefile.in @$(MAKE) -C ../.. src/test/Makefile -$(SYSINFO_INC): $(TEST_SPINLOCK_C) $(TEST_SPINLOCK_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) +$(SYSINFO_INC): $(TEST_C) $(TEST_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) @echo " MAKE $@" @$(MAKE) -C ../.. sysinfo @@ -62,17 +64,21 @@ obj: @echo " MKDIR obj" @-mkdir obj -#executables +# executables + +$(TESTS_ALL): test_%: ../../test_%@EXEEXT@ + @echo " TEST $@" -test_spinlock: $(TEST_SPINLOCK_DEPENDS) Makefile - @echo " LD $@" - @$(CC) @LDFLAGS@ -o ../../test_spinlock@EXEEXT@ $(TEST_SPINLOCK_DEPENDS) @LIBS@ @MYSQL_LIBS@ +../../test_%@EXEEXT@: obj/test_%.o $(TEST_DEPENDS) Makefile + @echo " LD $(notdir $@)" + @$(CC) @STATIC@ @LDFLAGS@ -o $@ $< $(COMMON_D)/obj_sql/common_sql.a \ + $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ # object files -obj/%.o: %.c $(TEST_SPINLOCK_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj +obj/%.o: %.c $(TEST_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj @echo " CC $<" - @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files $(COMMON_D)/obj_all/common.a: diff --git a/src/test/libconfig/test.conf b/src/test/libconfig/test.conf new file mode 100644 index 000000000..bbdc2cd96 --- /dev/null +++ b/src/test/libconfig/test.conf @@ -0,0 +1 @@ +Test: true diff --git a/src/test/test_libconfig.c b/src/test/test_libconfig.c new file mode 100644 index 000000000..e0b5b3fca --- /dev/null +++ b/src/test/test_libconfig.c @@ -0,0 +1,842 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Base author: Haru <haru@dotalux.com> +#define HERCULES_CORE + +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/core.h" +#include "common/showmsg.h" +#include "common/strlib.h" + +#include <stdlib.h> + +#define TEST(name, function, ...) do { \ + const char *message = NULL; \ + ShowMessage("-------------------------------------------------------------------------------\n"); \ + ShowNotice("Testing %s...\n", (name)); \ + if ((message = (function)(##__VA_ARGS__)) != NULL) { \ + ShowError("Failed. %s\n", message); \ + ShowMessage("===============================================================================\n"); \ + ShowFatalError("Failure. Aborting further tests.\n"); \ + exit(EXIT_FAILURE); \ + } \ + ShowInfo("Test passed.\n"); \ +} while (false) + +static const char *test_libconfig_truefalse(void) +{ + if (CONFIG_TRUE != true) { + return "CONFIG_TRUE != true"; + } + if (CONFIG_FALSE != false) { + return "CONFIG_FALSE != false"; + } + return NULL; +} + +static const char *test_libconfig_defaults(void) +{ + if (libconfig == NULL) { + return "Unable to find libconfig interface."; + } + if (libconfig->init == NULL) { + return "Unable to find libconfig methods"; + } + if (libconfig->read_file_src == NULL) { + return "Unable to find libconfig core methods"; + } + return NULL; +} + +static const char *test_libconfig_init_destroy(void) +{ + config_t config; + libconfig->init(&config); + if (config.root == NULL || config.root != config_root_setting(&config)) { + return "Unable to create config."; + } + libconfig->destroy(&config); + if (config.root != NULL) { + return "Unable to destroy config."; + } + return NULL; +} + +static const char *test_libconfig_read_file_src(void) +{ + config_t config; +#define FILENAME "src/test/libconfig/test.conf" + if (libconfig->read_file_src(&config, FILENAME) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to read file '" FILENAME "'."; + } +#undef FILENAME + if (config.root == NULL) { + libconfig->destroy(&config); + return "Invalid config."; + } + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_read(void) +{ + config_t config; +#define FILENAME "src/test/libconfig/test.conf" + FILE *fp = fopen(FILENAME, "r"); + if (!fp) { + return "File not found: '" FILENAME "'."; + } + if (libconfig->read(&config, fp) == CONFIG_FALSE) { + fclose(fp); + libconfig->destroy(&config); + return "Unable to read from file '" FILENAME "'."; + } +#undef FILENAME + if (config.root == NULL) { + libconfig->destroy(&config); + return "Invalid config."; + } + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_read_file(void) +{ + config_t config; +#define FILENAME "src/test/libconfig/test.conf" + if (libconfig->read_file(&config, FILENAME) != 0) { + return "Unable to read file '" FILENAME "'."; + } +#undef FILENAME + if (config.root == NULL || !config_setting_is_root(config.root)) { + libconfig->destroy(&config); + return "Invalid config."; + } + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_write(void) +{ + //void (*write) (const config_t *config, FILE *stream); + return "TEST NOT IMPLEMENTED"; +} + +static const char *test_libconfig_write_file(void) +{ + //int (*write_file) (config_t *config, const char *filename); + return "TEST NOT IMPLEMENTED"; +} + +static const char *test_libconfig_read_string(void) +{ + config_t config; + if (libconfig->read_string(&config, "") == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to read from string."; + } + if (config.root == NULL) { + libconfig->destroy(&config); + return "Invalid config."; + } + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_syntax(void) +{ + config_t config; + const char *input = "/* Test File */\n" + "Setting_Int: 1;\n" + "Setting_Int64: 1L;\n" + "Setting_Float: 1.0;\n" + "Setting_Bool: true;\n" + "Setting_String: \"1\";\n" + "Setting_Array: [ ];\n" + "Setting_Group: { };\n" + "Setting_List: ( );\n" + "/* End test file */\n"; + + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to read from string."; + } + if (config.root == NULL) { + libconfig->destroy(&config); + return "Invalid config."; + } + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_set_include_dir(void) +{ + //void (*set_include_dir) (config_t *config, const char *include_dir); + return "TEST NOT IMPLEMENTED"; +} + +static const char *test_libconfig_lookup(void) +{ + config_t config; + config_setting_t *t = NULL; + int32 i32; + int64 i64; + double f; + const char *str; + const char *input = "/* Test File */\n" + "Setting_Int: 1;\n" + "Setting_Int64: 1L;\n" + "Setting_Float: 1.0;\n" + "Setting_Bool: true;\n" + "Setting_String: \"1\";\n" + "Setting_Array: [ ];\n" + "Setting_Group: { };\n" + "Setting_List: ( );\n" + "/* End test file */\n"; + + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if ((t = libconfig->lookup(&config, "Setting_Int")) == NULL) { + libconfig->destroy(&config); + return "libconfig->lookup failed."; + } + + if ((t = libconfig->lookup_from(config.root, "Setting_Int")) == NULL) { + libconfig->destroy(&config); + return "libconfig->lookup_from failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Int", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "libconfig->lookup_int failed."; + } + + if (libconfig->lookup_int64(&config, "Setting_Int64", &i64) == CONFIG_FALSE || i64 != 1) { + libconfig->destroy(&config); + return "libconfig->lookup_int64 failed."; + } + + if (libconfig->lookup_float(&config, "Setting_Float", &f) == CONFIG_FALSE || f < 1.0 - 0.1 || f > 1.0 + 0.1) { + libconfig->destroy(&config); + return "libconfig->lookup_float failed."; + } + + if (libconfig->lookup_bool(&config, "Setting_Bool", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "libconfig->lookup_bool failed."; + } + + if (libconfig->lookup_string(&config, "Setting_String", &str) == CONFIG_FALSE || str == NULL || str[0] != '1' || str[1] != '\0') { + libconfig->destroy(&config); + return "libconfig->lookup_string failed."; + } + + libconfig->destroy(&config); + + return NULL; +} + +static const char *test_libconfig_setting_get(void) +{ + config_t config; + config_setting_t *t = NULL; + double f; + const char *str; + const char *input = "/* Test File */\n" + "Setting_Int: 1;\n" + "Setting_Int64: 1L;\n" + "Setting_Float: 1.0;\n" + "Setting_Bool: true;\n" + "Setting_String: \"1\";\n" + "Setting_Array: [ ];\n" + "Setting_Group: { };\n" + "Setting_List: ( );\n" + "/* End test file */\n"; + + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if ((t = libconfig->lookup(&config, "Setting_Int")) == NULL || libconfig->setting_get_int(t) != 1) { + libconfig->destroy(&config); + return "libconfig->setting_get_int failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Int64")) == NULL || libconfig->setting_get_int64(t) != 1) { + libconfig->destroy(&config); + return "libconfig->lookup_int64 failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Float")) == NULL || (f = libconfig->setting_get_float(t)) < 1.0 - 0.1 || f > 1.0 + 0.1) { + libconfig->destroy(&config); + return "libconfig->lookup_float failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Bool")) == NULL || libconfig->setting_get_bool(t) != 1) { + libconfig->destroy(&config); + return "libconfig->lookup_bool failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_String")) == NULL || (str = libconfig->setting_get_string(t)) == NULL || str[0] != '1' || str[1] != '\0') { + libconfig->destroy(&config); + return "libconfig->lookup_string failed."; + } + + t = config_root_setting(&config); + + if (libconfig->setting_get_int_elem(t, 0) != 1) { + libconfig->destroy(&config); + return "libconfig->setting_get_int_elem failed."; + } + + if (libconfig->setting_get_int64_elem(t, 1) != 1) { + libconfig->destroy(&config); + return "libconfig->setting_get_int64_elem failed."; + } + + if ((f = libconfig->setting_get_float_elem(t, 2)) < 1.0 - 0.1 || f > 1.0 + 0.1) { + libconfig->destroy(&config); + return "libconfig->setting_get_float_elem failed."; + } + + if (libconfig->setting_get_bool_elem(t, 3) != 1) { + libconfig->destroy(&config); + return "libconfig->setting_get_bool_elem failed."; + } + + if ((str = libconfig->setting_get_string_elem(t, 4)) == NULL || str[0] != '1' || str[1] != '\0') { + libconfig->destroy(&config); + return "libconfig->setting_get_string_elem failed."; + } + + if ((t = libconfig->setting_get_elem(config.root, 0)) == NULL || libconfig->setting_get_int(t) != 1) { + libconfig->destroy(&config); + return "libconfig->setting_get_elem failed."; + } + + if ((t = libconfig->setting_get_member(config.root, "Setting_Int")) == NULL || libconfig->setting_get_int(t) != 1 || strcmp(config_setting_name(t), "Setting_Int") != 0) { + libconfig->destroy(&config); + return "libconfig->setting_get_member failed."; + } + + if ((t = libconfig->setting_get_elem(config.root, 0)) == NULL || strcmp(config_setting_name(t), "Setting_Int") != 0) { + libconfig->destroy(&config); + return "config_setting_name failed."; + } + + if ((t = libconfig->setting_get_member(config.root, "Setting_Int")) == NULL || libconfig->setting_index(t) != 0) { + libconfig->destroy(&config); + return "libconfig->setting_index failed."; + } + + if (libconfig->setting_length(config.root) != 8) { + libconfig->destroy(&config); + return "libconfig->setting_length failed."; + } + + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_set(void) +{ + //int (*setting_set_int) (config_setting_t *setting ,int value); + //int (*setting_set_int64) (config_setting_t *setting, long long value); + //int (*setting_set_float) (config_setting_t *setting, double value); + //int (*setting_set_bool) (config_setting_t *setting, int value); + //int (*setting_set_string) (config_setting_t *setting, const char *value); + return "TEST NOT IMPLEMENTED"; +} + +static const char *test_libconfig_setting_lookup(void) +{ + config_t config; + int32 i32; + int64 i64; + double f; + const char *str; + const char *input = "/* Test File */\n" + "Setting_Int: 1;\n" + "Setting_Int64: 1L;\n" + "Setting_Float: 1.0;\n" + "Setting_Bool: true;\n" + "Setting_String: \"1\";\n" + "Setting_Array: [ ];\n" + "Setting_Group: { };\n" + "Setting_List: ( );\n" + "/* End test file */\n"; + + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if (libconfig->setting_lookup_int(config.root, "Setting_Int", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "libconfig->setting_lookup_int failed."; + } + + if (libconfig->setting_lookup_int64(config.root, "Setting_Int64", &i64) == CONFIG_FALSE || i64 != 1) { + libconfig->destroy(&config); + return "libconfig->setting_lookup_int64 failed."; + } + + if (libconfig->setting_lookup_float(config.root, "Setting_Float", &f) == CONFIG_FALSE || f < 1.0 - 0.1 || f > 1.0 + 0.1) { + libconfig->destroy(&config); + return "libconfig->setting_lookup_float failed."; + } + + if (libconfig->setting_lookup_bool(config.root, "Setting_Bool", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "libconfig->setting_lookup_bool failed."; + } + + if (libconfig->setting_lookup_string(config.root, "Setting_String", &str) == CONFIG_FALSE || str == NULL || str[0] != '1' || str[1] != '\0') { + libconfig->destroy(&config); + return "libconfig->setting_lookup_string failed."; + } + + libconfig->destroy(&config); + + return NULL; +} + +static const char *test_libconfig_setting_types(void) +{ + config_t config; + config_setting_t *t; + const char *input = "/* Test File */\n" + "Setting_Int: 1;\n" + "Setting_Int64: 1L;\n" + "Setting_Float: 1.0;\n" + "Setting_Bool: true;\n" + "Setting_String: \"1\";\n" + "Setting_Array: [ ];\n" + "Setting_Group: { };\n" + "Setting_List: ( );\n" + "/* End test file */\n"; + + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if (config_setting_type(config.root) != CONFIG_TYPE_GROUP) { + libconfig->destroy(&config); + return "CONFIG_TYPE_GROUP failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Int")) == NULL || config_setting_type(t) != CONFIG_TYPE_INT + || config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t) + || config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || !config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_INT failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Int64")) == NULL || config_setting_type(t) != CONFIG_TYPE_INT64 + || config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t) + || config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || !config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_INT64 failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Float")) == NULL || config_setting_type(t) != CONFIG_TYPE_FLOAT + || config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t) + || config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || !config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_FLOAT failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Bool")) == NULL || config_setting_type(t) != CONFIG_TYPE_BOOL + || config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t) + || config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_BOOL failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_String")) == NULL || config_setting_type(t) != CONFIG_TYPE_STRING + || config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t) + || config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_STRING failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Array")) == NULL || config_setting_type(t) != CONFIG_TYPE_ARRAY + || config_setting_is_group(t) || !config_setting_is_array(t) || config_setting_is_list(t) + || !config_setting_is_aggregate(t) || config_setting_is_scalar(t) || config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_ARRAY failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Group")) == NULL || config_setting_type(t) != CONFIG_TYPE_GROUP + || !config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t) + || !config_setting_is_aggregate(t) || config_setting_is_scalar(t) || config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_GROUP failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_List")) == NULL || config_setting_type(t) != CONFIG_TYPE_LIST + || config_setting_is_group(t) || config_setting_is_array(t) || !config_setting_is_list(t) + || !config_setting_is_aggregate(t) || config_setting_is_scalar(t) || config_setting_is_number(t) + ) { + libconfig->destroy(&config); + return "CONFIG_TYPE_LIST failed."; + } + + libconfig->destroy(&config); + + return NULL; +} + +static const char *test_libconfig_values(void) +{ + config_t config; + int32 i32; + int64 i64; + const char *input = "/* Test File */\n" + "Setting_Int1: 1;\n" + "Setting_IntHex: 0x10;\n" + "Setting_IntNegative: -1;\n" + "Setting_Int64: 1L;\n" + "Setting_Int64Hex: 0x10L;\n" + "Setting_Int64Negative: -1L;\n" + "Setting_IntSignedMax: 0x7fffffff;\n" + "/* End test file */\n"; + + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if (libconfig->setting_lookup_int(config.root, "Setting_Int1", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "(int) 1 failed."; + } + + if (libconfig->setting_lookup_int(config.root, "Setting_IntHex", &i32) == CONFIG_FALSE || i32 != 0x10) { + libconfig->destroy(&config); + return "(int) 0x10 failed."; + } + + if (libconfig->setting_lookup_int(config.root, "Setting_IntNegative", &i32) == CONFIG_FALSE || i32 != -1) { + libconfig->destroy(&config); + return "(int) -1 failed."; + } + + if (libconfig->setting_lookup_int64(config.root, "Setting_Int64", &i64) == CONFIG_FALSE || i64 != 1) { + libconfig->destroy(&config); + return "(int64) 1 failed."; + } + + if (libconfig->setting_lookup_int64(config.root, "Setting_Int64Hex", &i64) == CONFIG_FALSE || i64 != 0x10) { + libconfig->destroy(&config); + return "(int64) 0x10 failed."; + } + + if (libconfig->setting_lookup_int64(config.root, "Setting_Int64Negative", &i64) == CONFIG_FALSE || i64 != -1) { + libconfig->destroy(&config); + return "(int64) -1 failed."; + } + + if (libconfig->setting_lookup_int(config.root, "Setting_IntSignedMax", &i32) == CONFIG_FALSE || i32 != INT32_MAX) { + libconfig->destroy(&config); + return "(int) INT32_MAX failed."; + } + + libconfig->destroy(&config); + + return NULL; +} + +static const char *test_libconfig_path_lookup(void) +{ + config_t config; + int32 i32; + const char *input = "/* Test File */\n" + "Setting_Array: [1, 2, 3];\n" + "Setting_Group: {\n" + " Group_Nested1: 4;\n" + " Group_Nested2: 5;\n" + " Group_Nested3: 6;\n" + " Group_Nested4: 7;\n" + "};\n" + "Setting_List: (\n" + " (\"List_Nested1\", 8),\n" + " (\"List_Nested2\", 9),\n" + " 10,\n" + ");\n" + "/* End test file */\n"; + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if (libconfig->lookup_int(&config, "Setting_Array/[0]", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "Setting_Array/[0] failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Array:[0]", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "Setting_Array:[0] failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Array/[1]", &i32) == CONFIG_FALSE || i32 != 2) { + ShowDebug("%d\n", i32); + libconfig->destroy(&config); + return "Setting_Array/[1] failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Array/[2]", &i32) == CONFIG_FALSE || i32 != 3) { + libconfig->destroy(&config); + return "Setting_Array/[2] failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Group/Group_Nested1", &i32) == CONFIG_FALSE || i32 != 4) { + libconfig->destroy(&config); + return "Setting_Group/Group_Nested1 failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Group/Group_Nested2", &i32) == CONFIG_FALSE || i32 != 5) { + libconfig->destroy(&config); + return "Setting_Group/Group_Nested2 failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Group/Group_Nested3", &i32) == CONFIG_FALSE || i32 != 6) { + libconfig->destroy(&config); + return "Setting_Group/Group_Nested3 failed."; + } + + if (libconfig->lookup_int(&config, "Setting_Group/Group_Nested4", &i32) == CONFIG_FALSE || i32 != 7) { + libconfig->destroy(&config); + return "Setting_Group/Group_Nested4 failed."; + } + + if (libconfig->lookup_int(&config, "Setting_List/[0]/[1]", &i32) == CONFIG_FALSE || i32 != 8) { + libconfig->destroy(&config); + return "Setting_List/[0]/[1] failed."; + } + + if (libconfig->lookup_int(&config, "Setting_List/[1]/[1]", &i32) == CONFIG_FALSE || i32 != 9) { + libconfig->destroy(&config); + return "Setting_List/[1]/[1] failed."; + } + + if (libconfig->lookup_int(&config, "Setting_List/[2]", &i32) == CONFIG_FALSE || i32 != 10) { + libconfig->destroy(&config); + return "Setting_List/[2] failed."; + } + + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_setting_names(void) +{ + config_t config; + int32 i32; + const char *input = "/* Test File */\n" + "Setting'with'apostrophes: 1;\n" + "Setting.with.periods: 2;\n" + "Setting: {\n" + " with: {\n" + " periods: 3;\n" + " };\n" + " nested: {\n" + " in: {\n" + " groups: 4;\n" + " };\n" + " };\n" + "};\n" + "1st_setting_with_numbers: 5;\n" + "/* End test file */\n"; + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if (libconfig->lookup_int(&config, "Setting'with'apostrophes", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "Setting'with'apostrophes failed."; + } + + if (libconfig->lookup_int(&config, "Setting.with.periods", &i32) == CONFIG_FALSE || i32 != 2) { + libconfig->destroy(&config); + return "Setting.with.periods failed."; + } + + if (libconfig->lookup_int(&config, "Setting:with:periods", &i32) == CONFIG_FALSE || i32 != 3) { + libconfig->destroy(&config); + return "Setting:with:periods failed."; + } + + if (libconfig->lookup_int(&config, "Setting:nested:in:groups", &i32) == CONFIG_FALSE || i32 != 4) { + libconfig->destroy(&config); + return "Setting:nested:in:groups failed."; + } + + if (libconfig->lookup_int(&config, "Setting/nested/in/groups", &i32) == CONFIG_FALSE || i32 != 4) { + libconfig->destroy(&config); + return "Setting/nested/in/groups failed."; + } + + if (libconfig->lookup_int(&config, "1st_setting_with_numbers", &i32) == CONFIG_FALSE || i32 != 5) { + libconfig->destroy(&config); + return "1st_setting_with_numbers failed."; + } + + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_duplicate_keys(void) +{ + config_t config; + int32 i32; + config_setting_t *t, *tt; + int i = 0; + const char *input = "/* Test File */\n" + "Setting_Group: {\n" + " Duplicate: 1;\n" + " Duplicate: 2;\n" + " Duplicate: 3;\n" + " Duplicate: 4;\n" + "};\n" + "/* End test file */\n"; + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if (libconfig->lookup_int(&config, "Setting_Group/Duplicate", &i32) == CONFIG_FALSE || i32 != 1) { + libconfig->destroy(&config); + return "Setting_Group/Duplicate failed."; + } + + if ((t = libconfig->lookup(&config, "Setting_Group")) == NULL) { + libconfig->destroy(&config); + return "Setting_Group failed."; + } + + if (libconfig->setting_length(t) != 4) { + libconfig->destroy(&config); + return "Wrong amount of duplicates."; + } + + while ((tt = libconfig->setting_get_elem(t, i++)) != NULL) { + if (i != libconfig->setting_get_int(tt)) { + libconfig->destroy(&config); + return "Duplicate ordering error."; + } + } + + if (i != 5) { + libconfig->destroy(&config); + return "Wrong amount of duplicates scanned."; + } + + + libconfig->destroy(&config); + return NULL; +} + +static const char *test_libconfig_special_string_syntax(void) +{ + config_t config; + const char *str; + const char *input = "/* Test File */\n" + "SpecialString: <\"This is an \"Item_Script\" Special String\n\tWith a line-break inside.\">;\n" + "/* End test file */\n"; + if (libconfig->read_string(&config, input) == CONFIG_FALSE) { + libconfig->destroy(&config); + return "Unable to parse configuration."; + } + + if (libconfig->lookup_string(&config, "SpecialString", &str) == CONFIG_FALSE || str == NULL) { + libconfig->destroy(&config); + return "String lookup failed."; + } + + if (strcmp("This is an \"Item_Script\" Special String\n\tWith a line-break inside.", str) != 0) { + libconfig->destroy(&config); + return "String mismatch."; + } + + libconfig->destroy(&config); + return NULL; +} + +int do_init(int argc, char **argv) +{ + ShowMessage("===============================================================================\n"); + ShowStatus("Starting tests.\n"); + + TEST("CONFIG_TRUE and CONFIG_FALSE", test_libconfig_truefalse); + TEST("libconfig availability", test_libconfig_defaults); + TEST("libconfig->init and libconfig->destroy", test_libconfig_init_destroy); + TEST("libconfig->read_file_src", test_libconfig_read_file_src); + TEST("libconfig->read", test_libconfig_read); + TEST("libconfig->read_file", test_libconfig_read_file); + (void)test_libconfig_write; //TEST("libconfig->write", test_libconfig_write); + (void)test_libconfig_write_file; //TEST("libconfig->write_file", test_libconfig_write_file); + TEST("libconfig->read_string", test_libconfig_read_string); + TEST("libconfig syntax", test_libconfig_syntax); + (void)test_libconfig_set_include_dir; //TEST("libconfig->set_include_dir", test_libconfig_set_include_dir); + //int (*setting_set_format) (config_setting_t *setting, short format); + //short (*setting_get_format) (const config_setting_t *setting); + //config_setting_t * (*setting_set_int_elem) (config_setting_t *setting, int idx, int value); + //config_setting_t * (*setting_set_int64_elem) (config_setting_t *setting, int idx, long long value); + //config_setting_t * (*setting_set_float_elem) (config_setting_t *setting, int idx, double value); + //config_setting_t * (*setting_set_bool_elem) (config_setting_t *setting, int idx, int value); + //config_setting_t * (*setting_set_string_elem) (config_setting_t *setting, int idx, const char *value); + //config_setting_t * (*setting_add) (config_setting_t *parent, const char *name, int type); + //int (*setting_remove) (config_setting_t *parent, const char *name); + //int (*setting_remove_elem) (config_setting_t *parent, unsigned int idx); + //void (*setting_set_hook) (config_setting_t *setting, void *hook); + //void (*set_destructor) (config_t *config, void (*destructor)(void *)); + TEST("libconfig->lookup_*", test_libconfig_lookup); + TEST("libconfig->setting_get_*", test_libconfig_setting_get); + (void)test_libconfig_set; //TEST("libconfig->setting_set_*", test_libconfig_setting_set); + TEST("libconfig->setting_lookup_*", test_libconfig_setting_lookup); + TEST("setting types", test_libconfig_setting_types); + //void (*setting_copy_simple) (config_setting_t *parent, const config_setting_t *src); + //void (*setting_copy_elem) (config_setting_t *parent, const config_setting_t *src); + //void (*setting_copy_aggregate) (config_setting_t *parent, const config_setting_t *src); + //int (*setting_copy) (config_setting_t *parent, const config_setting_t *src); + TEST("values", test_libconfig_values); + TEST("path lookup", test_libconfig_path_lookup); + TEST("setting key names", test_libconfig_setting_names); + TEST("duplicate keys", test_libconfig_duplicate_keys); + TEST("special string syntax", test_libconfig_special_string_syntax); + + core->runflag = CORE_ST_STOP; + return EXIT_SUCCESS; +} + +int do_final(void) { + ShowMessage("===============================================================================\n"); + ShowStatus("All tests passed.\n"); + return EXIT_SUCCESS; +} + +void do_abort(void) { } + +void set_server_type(void) +{ + SERVER_TYPE = SERVER_TYPE_UNKNOWN; +} + +void cmdline_args_init_local(void) { } diff --git a/src/test/test_spinlock.c b/src/test/test_spinlock.c index a11f8643b..d4b2c48f9 100644 --- a/src/test/test_spinlock.c +++ b/src/test/test_spinlock.c @@ -103,3 +103,5 @@ int do_final(void) { int parse_console(const char* command){ return 0; }//end: parse_console + +void cmdline_args_init_local(void) { } diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c index 72457b73a..6356867e2 100644 --- a/src/tool/mapcache.c +++ b/src/tool/mapcache.c @@ -6,7 +6,7 @@ #include "common/cbasetypes.h" #include "common/core.h" #include "common/grfio.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/mmo.h" #include "common/showmsg.h" #include "common/strlib.h" |