From c2d3e2125124836e7cc329f3a782e3a42336c501 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 13 Oct 2015 22:28:03 +0300 Subject: Return actual result from pc_insert_card. --- src/map/pc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/map') diff --git a/src/map/pc.c b/src/map/pc.c index ffe43ab8f..fe339c457 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -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; -- cgit v1.2.3-70-g09d2 From 54f34f9f772f49913370f46d2a6628af6c6c6d6b Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sat, 17 Oct 2015 14:37:26 +0300 Subject: Fix crash while removing invisible wall. --- src/map/map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/map') diff --git a/src/map/map.c b/src/map/map.c index b142ed1f3..c64ab86b9 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -5874,7 +5874,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); -- cgit v1.2.3-70-g09d2 From 296c1ca3793caa4ef99d39df161c676cd9cb1ea9 Mon Sep 17 00:00:00 2001 From: Haru Date: Sat, 17 Oct 2015 18:29:05 +0200 Subject: Fixed an error in the refine_db loader - Fixes #800, special thanks to kyeme. - Also replaced some hardcoded numbers with constants. Signed-off-by: Haru --- src/map/status.c | 85 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 33 deletions(-) (limited to 'src/map') diff --git a/src/map/status.c b/src/map/status.c index 25c7e13dc..d37dfc057 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -12279,64 +12279,83 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) * 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 status_readdb_refine_libconfig_sub(config_setting_t *r, const char *name, const char *source) +{ config_setting_t *rate = NULL; - int i=0, type=0, bonus_per_level=0, rnd_bonus_v=0, rnd_bonus_lv=0; + 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)) { - type = 0; - } else if(strncmp(name, "WeaponLevel", 11) || !strspn(&name[strlen(name)-1], "0123456789") || !(type = atoi(strncpy(lv, name+11, 2)))) { + 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) { + 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; - } else if(!libconfig->setting_lookup_int(r, "StatsPerLevel", &bonus_per_level)) { + } + 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; - } else if(!libconfig->setting_lookup_int(r, "RandomBonusStartLevel", &rnd_bonus_lv)) { + } + 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; - } else if(!libconfig->setting_lookup_int(r, "RandomBonusValue", &rnd_bonus_v)) { + } + 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((rate=libconfig->setting_get_member(r, "Rates")) && config_setting_is_group(rate)) { + 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]; - - memset(&duplicate,0,sizeof(duplicate)); - memset(&bonus_,0,sizeof(bonus_)); - memset(&rnd_bonus,0,sizeof(rnd_bonus)); - memset(&chance_,0,sizeof(chance_)); - i=0; - while( (t = libconfig->setting_get_elem(rate,i++)) && config_setting_is_group(t) ) { - int level=0, chance=0, bonus=0; + 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) { + 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; - } else if(level <= 0 || level > MAX_REFINE) { + } + 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; - } else if(duplicate[level-1]) { - ShowWarning("status_readdb_refine_libconfig_sub: duplicate rate '%s' for entry %s in \"%s\", overwriting previous entry...\n", rlvl, name, source); - } else duplicate[level-1] = true; + } level--; - chance_[level] = libconfig->setting_lookup_int(t, "Chance", &chance)?chance:100; - bonus_[level] = bonus_per_level + libconfig->setting_lookup_int(t, "Bonus", &bonus)?bonus:0; - 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]?chance_[i]:100; + 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] += i?bonus_[i-1]:0; - status->dbs->refine_info[type].bonus[i] = bonus_[i]?bonus_[i]:0; + 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); -- cgit v1.2.3-70-g09d2 From 54d1c8b93adbeee5838b8dadabeb789b9fa6c511 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sat, 17 Oct 2015 20:12:15 +0300 Subject: rename malloc.c/h to memmgr. --- Hercules.xcodeproj/project.pbxproj | 24 +- src/char/HPMchar.c | 2 +- src/char/char.c | 2 +- src/char/geoip.c | 2 +- src/char/int_auction.c | 2 +- src/char/int_elemental.c | 2 +- src/char/int_guild.c | 2 +- src/char/int_homun.c | 2 +- src/char/int_mail.c | 2 +- src/char/int_mercenary.c | 2 +- src/char/int_party.c | 2 +- src/char/int_pet.c | 2 +- src/char/int_quest.c | 2 +- src/char/int_storage.c | 2 +- src/char/inter.c | 2 +- src/common/HPM.c | 2 +- src/common/Makefile.in | 8 +- src/common/console.c | 2 +- src/common/core.c | 2 +- src/common/db.c | 2 +- src/common/ers.c | 2 +- src/common/grfio.c | 2 +- src/common/malloc.c | 897 --------------------------------- src/common/malloc.h | 89 ---- src/common/memmgr.c | 897 +++++++++++++++++++++++++++++++++ src/common/memmgr.h | 89 ++++ src/common/mutex.c | 2 +- src/common/socket.c | 2 +- src/common/sql.c | 2 +- src/common/strlib.c | 2 +- src/common/sysinfo.c | 2 +- src/common/thread.c | 2 +- src/common/timer.c | 2 +- src/login/HPMlogin.c | 2 +- src/login/account_sql.c | 2 +- src/login/login.c | 2 +- src/map/HPMmap.c | 2 +- src/map/atcommand.c | 2 +- src/map/battle.c | 2 +- src/map/battleground.c | 2 +- src/map/channel.c | 2 +- src/map/chat.c | 2 +- src/map/chrif.c | 2 +- src/map/clif.c | 2 +- src/map/elemental.c | 2 +- src/map/guild.c | 2 +- src/map/homunculus.c | 2 +- src/map/instance.c | 2 +- src/map/intif.c | 2 +- src/map/irc-bot.c | 2 +- src/map/itemdb.c | 2 +- src/map/map.c | 2 +- src/map/mapreg_sql.c | 2 +- src/map/mercenary.c | 2 +- src/map/mob.c | 2 +- src/map/npc.c | 2 +- src/map/npc_chat.c | 2 +- src/map/party.c | 2 +- src/map/path.c | 2 +- src/map/pc.c | 2 +- src/map/pc_groups.c | 2 +- src/map/pet.c | 2 +- src/map/quest.c | 2 +- src/map/script.c | 2 +- src/map/searchstore.c | 2 +- src/map/skill.c | 2 +- src/map/status.c | 2 +- src/map/storage.c | 2 +- src/map/unit.c | 2 +- src/plugins/HPMHooking.c | 4 +- src/plugins/db2sql.c | 2 +- src/plugins/sample.c | 2 +- src/tool/mapcache.c | 2 +- vcproj-10/char-server.vcxproj | 4 +- vcproj-10/char-server.vcxproj.filters | 4 +- vcproj-10/login-server.vcxproj | 4 +- vcproj-10/login-server.vcxproj.filters | 4 +- vcproj-10/map-server.vcxproj | 4 +- vcproj-10/map-server.vcxproj.filters | 4 +- vcproj-10/mapcache.vcxproj | 4 +- vcproj-10/mapcache.vcxproj.filters | 4 +- vcproj-11/char-server.vcxproj | 4 +- vcproj-11/char-server.vcxproj.filters | 4 +- vcproj-11/login-server.vcxproj | 4 +- vcproj-11/login-server.vcxproj.filters | 4 +- vcproj-11/map-server.vcxproj | 4 +- vcproj-11/map-server.vcxproj.filters | 4 +- vcproj-11/mapcache.vcxproj | 4 +- vcproj-11/mapcache.vcxproj.filters | 4 +- vcproj-12/char-server.vcxproj | 4 +- vcproj-12/char-server.vcxproj.filters | 4 +- vcproj-12/login-server.vcxproj | 4 +- vcproj-12/login-server.vcxproj.filters | 4 +- vcproj-12/map-server.vcxproj | 4 +- vcproj-12/map-server.vcxproj.filters | 4 +- vcproj-12/mapcache.vcxproj | 4 +- vcproj-12/mapcache.vcxproj.filters | 4 +- vcproj-14/char-server.vcxproj | 4 +- vcproj-14/char-server.vcxproj.filters | 4 +- vcproj-14/login-server.vcxproj | 4 +- vcproj-14/login-server.vcxproj.filters | 4 +- vcproj-14/map-server.vcxproj | 4 +- vcproj-14/map-server.vcxproj.filters | 4 +- vcproj-14/mapcache.vcxproj | 4 +- vcproj-14/mapcache.vcxproj.filters | 4 +- 105 files changed, 1134 insertions(+), 1134 deletions(-) delete mode 100644 src/common/malloc.c delete mode 100644 src/common/malloc.h create mode 100644 src/common/memmgr.c create mode 100644 src/common/memmgr.h (limited to 'src/map') diff --git a/Hercules.xcodeproj/project.pbxproj b/Hercules.xcodeproj/project.pbxproj index 1472c088a..07967e965 100644 --- a/Hercules.xcodeproj/project.pbxproj +++ b/Hercules.xcodeproj/project.pbxproj @@ -11,7 +11,7 @@ A5380CD81856CE8A0090CBC4 /* console.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC692185643BB009EB79C /* console.c */; }; A5380CD91856CF4A0090CBC4 /* core.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC694185643BB009EB79C /* core.c */; }; A5380CDA1856D0650090CBC4 /* socket.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6BA185643BB009EB79C /* socket.c */; }; - A5380CDB1856D0690090CBC4 /* malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* malloc.c */; }; + A5380CDB1856D0690090CBC4 /* memmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* memmgr.c */; }; A5467AD31A16FCB4008AFAA6 /* loginif.c in Sources */ = {isa = PBXBuildFile; fileRef = A5467AD11A16FCB4008AFAA6 /* loginif.c */; }; A5467AD61A16FCDC008AFAA6 /* mapif.c in Sources */ = {isa = PBXBuildFile; fileRef = A5467AD41A16FCDC008AFAA6 /* mapif.c */; }; A5467AD91A16FD08008AFAA6 /* geoip.c in Sources */ = {isa = PBXBuildFile; fileRef = A5467AD71A16FD08008AFAA6 /* geoip.c */; }; @@ -50,9 +50,9 @@ A56CC6E1185643BB009EB79C /* HPM.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A0185643BB009EB79C /* HPM.c */; }; A56CC6E2185643BB009EB79C /* HPM.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A0185643BB009EB79C /* HPM.c */; }; A56CC6E3185643BB009EB79C /* HPM.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A0185643BB009EB79C /* HPM.c */; }; - A56CC6E4185643BB009EB79C /* malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* malloc.c */; }; - A56CC6E5185643BB009EB79C /* malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* malloc.c */; }; - A56CC6E6185643BB009EB79C /* malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* malloc.c */; }; + A56CC6E4185643BB009EB79C /* memmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* memmgr.c */; }; + A56CC6E5185643BB009EB79C /* memmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* memmgr.c */; }; + A56CC6E6185643BB009EB79C /* memmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A3185643BB009EB79C /* memmgr.c */; }; A56CC6E7185643BB009EB79C /* mapindex.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A5185643BB009EB79C /* mapindex.c */; }; A56CC6E8185643BB009EB79C /* mapindex.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A5185643BB009EB79C /* mapindex.c */; }; A56CC6E9185643BB009EB79C /* mapindex.c in Sources */ = {isa = PBXBuildFile; fileRef = A56CC6A5185643BB009EB79C /* mapindex.c */; }; @@ -256,8 +256,8 @@ A56CC6A0185643BB009EB79C /* HPM.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HPM.c; path = src/common/HPM.c; sourceTree = ""; }; A56CC6A1185643BB009EB79C /* HPM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HPM.h; path = src/common/HPM.h; sourceTree = ""; }; A56CC6A2185643BB009EB79C /* HPMi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HPMi.h; path = src/common/HPMi.h; sourceTree = ""; }; - A56CC6A3185643BB009EB79C /* malloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = malloc.c; path = src/common/malloc.c; sourceTree = ""; }; - A56CC6A4185643BB009EB79C /* malloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = malloc.h; path = src/common/malloc.h; sourceTree = ""; }; + A56CC6A3185643BB009EB79C /* memmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = memmgr.c; path = src/common/memmgr.c; sourceTree = ""; }; + A56CC6A4185643BB009EB79C /* memmgr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memmgr.h; path = src/common/memmgr.h; sourceTree = ""; }; A56CC6A5185643BB009EB79C /* mapindex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mapindex.c; path = src/common/mapindex.c; sourceTree = ""; }; A56CC6A6185643BB009EB79C /* mapindex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mapindex.h; path = src/common/mapindex.h; sourceTree = ""; }; A56CC6A7185643BB009EB79C /* md5calc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5calc.c; path = src/common/md5calc.c; sourceTree = ""; }; @@ -719,8 +719,8 @@ A56CC6A0185643BB009EB79C /* HPM.c */, A56CC6A1185643BB009EB79C /* HPM.h */, A56CC6A2185643BB009EB79C /* HPMi.h */, - A56CC6A3185643BB009EB79C /* malloc.c */, - A56CC6A4185643BB009EB79C /* malloc.h */, + A56CC6A3185643BB009EB79C /* memmgr.c */, + A56CC6A4185643BB009EB79C /* memmgr.h */, A56CC6A5185643BB009EB79C /* mapindex.c */, A56CC6A6185643BB009EB79C /* mapindex.h */, A56CC6A7185643BB009EB79C /* md5calc.c */, @@ -1170,7 +1170,7 @@ A5380CDA1856D0650090CBC4 /* socket.c in Sources */, A55AED7C1B8153F100149CF8 /* scanner.c in Sources */, A58A5A17185800A40099683E /* showmsg.c in Sources */, - A5380CDB1856D0690090CBC4 /* malloc.c in Sources */, + A5380CDB1856D0690090CBC4 /* memmgr.c in Sources */, A55AED7B1B8153EF00149CF8 /* scanctx.c in Sources */, A55AED791B8153EA00149CF8 /* grammar.c in Sources */, A55AED7D1B8153F300149CF8 /* strbuf.c in Sources */, @@ -1208,7 +1208,7 @@ A56CC72E18564C05009EB79C /* grammar.c in Sources */, A56CC705185643BB009EB79C /* socket.c in Sources */, A56CC68918564387009EB79C /* account_sql.c in Sources */, - A56CC6E4185643BB009EB79C /* malloc.c in Sources */, + A56CC6E4185643BB009EB79C /* memmgr.c in Sources */, A56CC6E1185643BB009EB79C /* HPM.c in Sources */, A56CC6FF185643BB009EB79C /* random.c in Sources */, A56CC73418564C05009EB79C /* scanctx.c in Sources */, @@ -1241,7 +1241,7 @@ A5B894AD1A03CDFA005AD22E /* HPMchar.c in Sources */, A56CC761185657D9009EB79C /* int_homun.c in Sources */, A56CC6FA185643BB009EB79C /* nullpo.c in Sources */, - A56CC6E5185643BB009EB79C /* malloc.c in Sources */, + A56CC6E5185643BB009EB79C /* memmgr.c in Sources */, A56CC6E2185643BB009EB79C /* HPM.c in Sources */, A56CC765185657D9009EB79C /* int_pet.c in Sources */, A56CC769185657D9009EB79C /* pincode.c in Sources */, @@ -1314,7 +1314,7 @@ A56CC7D318565812009EB79C /* path.c in Sources */, A56CC7C218565812009EB79C /* elemental.c in Sources */, A56CC6FB185643BB009EB79C /* nullpo.c in Sources */, - A56CC6E6185643BB009EB79C /* malloc.c in Sources */, + A56CC6E6185643BB009EB79C /* memmgr.c in Sources */, A56CC7D418565812009EB79C /* pc_groups.c in Sources */, A56CC6E3185643BB009EB79C /* HPM.c in Sources */, A56CC7DD18565812009EB79C /* trade.c in Sources */, diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c index d3150bc11..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" diff --git a/src/char/char.c b/src/char/char.c index 1e0428a3d..7cc6aa91a 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" 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 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/common/HPM.c b/src/common/HPM.c index 5373c8b6a..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" 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/console.c b/src/common/console.c index c8ca4ae87..f4f18b799 100644 --- a/src/common/console.c +++ b/src/common/console.c @@ -16,7 +16,7 @@ #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" diff --git a/src/common/core.c b/src/common/core.c index 8564b8acc..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" 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/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/malloc.c deleted file mode 100644 index 63de90cb3..000000000 --- a/src/common/malloc.c +++ /dev/null @@ -1,897 +0,0 @@ -// Copyright (c) Hercules Dev Team, licensed under GNU GPL. -// See the LICENSE file -// Portions Copyright (c) Athena Dev Teams - -#define HERCULES_CORE - -#include "malloc.h" - -#include "common/cbasetypes.h" -#include "common/core.h" -#include "common/showmsg.h" -#include "common/sysinfo.h" - -#include -#include -#include - -struct malloc_interface iMalloc_s; -struct malloc_interface *iMalloc; - -////////////// Memory Libraries ////////////////// - -#if defined(MEMWATCH) - -# include -# include -# define MALLOC(n,file,line,func) mwMalloc((n),(file),(line)) -# define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line)) -# define REALLOC(p,n,file,line,func) mwRealloc((p),(n),(file),(line)) -# define STRDUP(p,file,line,func) mwStrdup((p),(file),(line)) -# define FREE(p,file,line,func) mwFree((p),(file),(line)) -# define MEMORY_USAGE() (size_t)0 -# define MEMORY_VERIFY(ptr) mwIsSafeAddr((ptr), 1) -# define MEMORY_CHECK() CHECK() - -#elif defined(DMALLOC) - -# include -# include -# include -# define MALLOC(n,file,line,func) dmalloc_malloc((file),(line),(n),DMALLOC_FUNC_MALLOC,0,0) -# define CALLOC(m,n,file,line,func) dmalloc_malloc((file),(line),(m)*(n),DMALLOC_FUNC_CALLOC,0,0) -# define REALLOC(p,n,file,line,func) dmalloc_realloc((file),(line),(p),(n),DMALLOC_FUNC_REALLOC,0) -# define STRDUP(p,file,line,func) strdup(p) -# define FREE(p,file,line,func) free(p) -# define MEMORY_USAGE() dmalloc_memory_allocated() -# define MEMORY_VERIFY(ptr) (dmalloc_verify(ptr) == DMALLOC_VERIFY_NOERROR) -# define MEMORY_CHECK() do { dmalloc_log_stats(); dmalloc_log_unfreed() } while(0) - -#elif defined(GCOLLECT) - -# include -# ifdef GC_ADD_CALLER -# define RETURN_ADDR 0, -# else -# define RETURN_ADDR -# endif -# define MALLOC(n,file,line,func) GC_debug_malloc((n), RETURN_ADDR (file),(line)) -# define CALLOC(m,n,file,line,func) GC_debug_malloc((m)*(n), RETURN_ADDR (file),(line)) -# define REALLOC(p,n,file,line,func) GC_debug_realloc((p),(n), RETURN_ADDR (file),(line)) -# define STRDUP(p,file,line,func) GC_debug_strdup((p), RETURN_ADDR (file),(line)) -# define FREE(p,file,line,func) GC_debug_free(p) -# define MEMORY_USAGE() GC_get_heap_size() -# define MEMORY_VERIFY(ptr) (GC_base(ptr) != NULL) -# define MEMORY_CHECK() GC_gcollect() - -# undef RETURN_ADDR - -#else - -# define MALLOC(n,file,line,func) malloc(n) -# define CALLOC(m,n,file,line,func) calloc((m),(n)) -# define REALLOC(p,n,file,line,func) realloc((p),(n)) -# define STRDUP(p,file,line,func) strdup(p) -# define FREE(p,file,line,func) free(p) -# define MEMORY_USAGE() (size_t)0 -# define MEMORY_VERIFY(ptr) true -# define MEMORY_CHECK() - -#endif - -void* aMalloc_(size_t size, const char *file, int line, const char *func) -{ - void *ret = MALLOC(size, file, line, func); - // ShowMessage("%s:%d: in func %s: aMalloc %d\n",file,line,func,size); - if (ret == NULL){ - ShowFatalError("%s:%d: in func %s: aMalloc error out of memory!\n",file,line,func); - exit(EXIT_FAILURE); - } - - return ret; -} -void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func) -{ - void *ret = CALLOC(num, size, file, line, func); - // ShowMessage("%s:%d: in func %s: aCalloc %d %d\n",file,line,func,num,size); - if (ret == NULL){ - ShowFatalError("%s:%d: in func %s: aCalloc error out of memory!\n", file, line, func); - exit(EXIT_FAILURE); - } - return ret; -} -void* aRealloc_(void *p, size_t size, const char *file, int line, const char *func) -{ - void *ret = REALLOC(p, size, file, line, func); - // ShowMessage("%s:%d: in func %s: aRealloc %p %d\n",file,line,func,p,size); - 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); - // ShowMessage("%s:%d: in func %s: aStrdup %p\n",file,line,func,p); - if (ret == NULL){ - ShowFatalError("%s:%d: in func %s: aStrdup error out of memory!\n", file, line, func); - exit(EXIT_FAILURE); - } - return ret; -} -void aFree_(void *p, const char *file, int line, const char *func) -{ - // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p); - if (p) - FREE(p, file, line, func); - //p = NULL; -} - - -#ifdef USE_MEMMGR - -#if defined(DEBUG) -#define DEBUG_MEMMGR -#endif - -/* USE_MEMMGR */ - -/* -* Memory manager -* able to handle malloc and free efficiently -* Since the complex processing, I might be slightly heavier. -* -* (I'm sorry for the poor description ^ ^;) such as data structures -* Divided into "blocks" of a plurality of memory, "unit" of a plurality of blocks further -* I have to divide. Size of the unit, a plurality of distribution equal to the capacity of one block -* That's what you have. For example, if one unit of 32KB, one block 1 Yu 32Byte -* Knit, or are able to gather 1024, gathered 512 units 64Byte -* I can be or have. (Excluding padding, the unit_head) -* -* Lead-linked list (block_prev, block_next) in each other is the same size block -* Linked list (hash_prev, hash_nect) even among such one in the block with the figure -* I like to have. Thus, reuse of memory no longer needed can be performed efficiently. -*/ - -/* Alignment of the block */ -#define BLOCK_ALIGNMENT1 16 -#define BLOCK_ALIGNMENT2 64 - -/* Amount of data entering a block */ -#define BLOCK_DATA_COUNT1 128 -#define BLOCK_DATA_COUNT2 608 - -/* The size of the block: 16*128 + 64*576 = 40KB */ -#define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 ) -#define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 ) -#define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 ) - -/* The number of blocks to be allocated at a time. */ -#define BLOCK_ALLOC 104 - -/* block */ -struct block { - struct block *block_next; ///< Then the allocated area - struct block *unfill_prev; ///< The previous area not filled - struct block *unfill_next; ///< The next area not filled - unsigned short unit_size; ///< The size of the unit - unsigned short unit_hash; ///< The hash of the unit - unsigned short unit_count; ///< The number of units - unsigned short unit_used; ///< The number of used units - unsigned short unit_unfill; ///< The number of unused units - unsigned short unit_maxused; ///< The maximum value of units used - char data[BLOCK_DATA_SIZE]; -}; - -struct unit_head { - struct block *block; - const char* file; - unsigned short line; - unsigned short size; - long checksum; -}; - -static struct block* hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1]; -static struct block* block_first, *block_last, block_head; - -/* Data for areas that do not use the memory be turned */ -struct unit_head_large { - size_t size; - struct unit_head_large* prev; - struct unit_head_large* next; - struct unit_head unit_head; -}; - -static struct unit_head_large *unit_head_large_first = NULL; - -static struct block* block_malloc(unsigned short hash); -static void block_free(struct block* p); -static size_t memmgr_usage_bytes; -static size_t memmgr_usage_bytes_t; - - -#define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ])) -#define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0) - -static unsigned short size2hash( size_t size ) -{ - if( size <= BLOCK_DATA_SIZE1 ) { - return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1; - } else if( size <= BLOCK_DATA_SIZE ){ - return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2 - + BLOCK_DATA_COUNT1; - } else { - return 0xffff; // If it exceeds the block length hash I do not - } -} - -static size_t hash2size( unsigned short hash ) -{ - if( hash <= BLOCK_DATA_COUNT1) { - return hash * BLOCK_ALIGNMENT1; - } else { - return (hash - BLOCK_DATA_COUNT1) * BLOCK_ALIGNMENT2 + BLOCK_DATA_SIZE1; - } -} - -void *mmalloc_(size_t size, const char *file, int line, const char *func) { - struct block *block; - short size_hash = size2hash( size ); - struct unit_head *head; - - if (((long) size) < 0) { - ShowError("mmalloc_: %"PRIdS"\n", size); - return NULL; - } - - if(size == 0) { - return NULL; - } - memmgr_usage_bytes += size; - - /* To ensure the area that exceeds the length of the block, using malloc () to */ - /* At that time, the distinction by assigning NULL to unit_head.block */ - if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { - struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); - memmgr_usage_bytes_t += size+sizeof(struct unit_head_large); - if(p != NULL) { - p->size = size; - p->unit_head.block = NULL; - p->unit_head.size = 0; - p->unit_head.file = file; - p->unit_head.line = (unsigned short)line; - p->prev = NULL; - if (unit_head_large_first == NULL) - p->next = NULL; - else { - unit_head_large_first->prev = p; - p->next = unit_head_large_first; - } - unit_head_large_first = p; - *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; - return (char *)p + sizeof(struct unit_head_large) - sizeof(long); - } else { - ShowFatalError("Memory manager::memmgr_alloc failed (allocating %"PRIuS"+%"PRIuS" bytes at %s:%d).\n", - sizeof(struct unit_head_large), size, file, line); - exit(EXIT_FAILURE); - } - } - - /* When a block of the same size is not ensured, to ensure a new */ - if(hash_unfill[size_hash]) { - block = hash_unfill[size_hash]; - } else { - block = block_malloc(size_hash); - } - - if( block->unit_unfill == 0xFFFF ) { - // there are no more free space that - memmgr_assert(block->unit_used < block->unit_count); - memmgr_assert(block->unit_used == block->unit_maxused); - head = block2unit(block, block->unit_maxused); - block->unit_used++; - block->unit_maxused++; - } else { - head = block2unit(block, block->unit_unfill); - block->unit_unfill = head->size; - block->unit_used++; - } - - if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { - // Since I ran out of the unit, removed from the list unfill - if( block->unfill_prev == &block_head) { - hash_unfill[ size_hash ] = block->unfill_next; - } else { - block->unfill_prev->unfill_next = block->unfill_next; - } - if( block->unfill_next ) { - block->unfill_next->unfill_prev = block->unfill_prev; - } - block->unfill_prev = NULL; - } - -#ifdef DEBUG_MEMMGR - { - size_t i, sz = hash2size( size_hash ); - for( i=0; iline != 0xfdfd ) - { - ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); - } - else - { - ShowError("Memory manager: not-allocated-data is changed.\n"); - } - break; - } - } - memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz ); - } -#endif - - head->block = block; - head->file = file; - head->line = (unsigned short)line; - head->size = (unsigned short)size; - *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; - return (char *)head + sizeof(struct unit_head) - sizeof(long); -} - -void *mcalloc_(size_t num, size_t size, const char *file, int line, const char *func) { - void *p = iMalloc->malloc(num * size,file,line,func); - if (p) - memset(p, 0, num * size); - return p; -} - -void *mrealloc_(void *memblock, size_t size, const char *file, int line, const char *func) { - size_t old_size; - if(memblock == NULL) { - return iMalloc->malloc(size,file,line,func); - } - - old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size; - if( old_size == 0 ) { - old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size; - } - if(old_size > size) { - // Size reduction - return> as it is (negligence) - return memblock; - } else { - // Size Large - void *p = iMalloc->malloc(size,file,line,func); - if(p != NULL) { - memcpy(p,memblock,old_size); - } - iMalloc->free(memblock,file,line,func); - return p; - } -} - -/* a mrealloc_ clone with the difference it 'z'eroes the newly created memory */ -void *mreallocz_(void *memblock, size_t size, const char *file, int line, const char *func) { - size_t old_size; - void *p = NULL; - - if(memblock == NULL) { - p = iMalloc->malloc(size,file,line,func); - memset(p,0,size); - return p; - } - - old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size; - if( old_size == 0 ) { - old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size; - } - if(old_size > size) { - // Size reduction - return> as it is (negligence) - return memblock; - } else { - // Size Large - p = iMalloc->malloc(size,file,line,func); - if(p != NULL) { - memcpy(p,memblock,old_size); - memset((char*)p+old_size,0,size-old_size); - } - iMalloc->free(memblock,file,line,func); - return p; - } -} - - -char *mstrdup_(const char *p, const char *file, int line, const char *func) { - if(p == NULL) { - return NULL; - } else { - size_t len = strlen(p); - char *string = (char *)iMalloc->malloc(len + 1,file,line,func); - memcpy(string,p,len+1); - return string; - } -} - -void mfree_(void *ptr, const char *file, int line, const char *func) { - struct unit_head *head; - - if (ptr == NULL) - return; - - head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long)); - if(head->size == 0) { - /* area that is directly secured by malloc () */ - struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long)); - if( - *(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size) - != 0xdeadbeaf) - { - ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); - } else { - head->size = 0xFFFF; - if(head_large->prev) { - head_large->prev->next = head_large->next; - } else { - unit_head_large_first = head_large->next; - } - if(head_large->next) { - head_large->next->prev = head_large->prev; - } - memmgr_usage_bytes -= head_large->size; - memmgr_usage_bytes_t -= head_large->size + sizeof(struct unit_head_large); -#ifdef DEBUG_MEMMGR - // set freed memory to 0xfd - memset(ptr, 0xfd, head_large->size); -#endif - FREE(head_large,file,line,func); - } - } else { - /* Release unit */ - struct block *block = head->block; - if( (char*)head - (char*)block > sizeof(struct block) ) { - ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line); - } else if(head->block == NULL) { - ShowError("Memory manager: args of aFree 0x%p is freed pointer %s:%d@%s\n", ptr, file, line, func); - } else if(*(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + head->size) != 0xdeadbeaf) { - ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); - } else { - memmgr_usage_bytes -= head->size; - head->block = NULL; -#ifdef DEBUG_MEMMGR - memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long) ); - head->file = file; - head->line = (unsigned short)line; -#endif - memmgr_assert( block->unit_used > 0 ); - if(--block->unit_used == 0) { - /* Release of the block */ - block_free(block); - } else { - if( block->unfill_prev == NULL) { - // add to unfill list - if( hash_unfill[ block->unit_hash ] ) { - hash_unfill[ block->unit_hash ]->unfill_prev = block; - } - block->unfill_prev = &block_head; - block->unfill_next = hash_unfill[ block->unit_hash ]; - hash_unfill[ block->unit_hash ] = block; - } - head->size = block->unit_unfill; - block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size); - } - } - } -} - -/* Allocating blocks */ -static struct block* block_malloc(unsigned short hash) -{ - struct block *p; - if(hash_unfill[0] != NULL) { - /* Space for the block has already been secured */ - p = hash_unfill[0]; - hash_unfill[0] = hash_unfill[0]->unfill_next; - } else { - int i; - /* Newly allocated space for the block */ - p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ ); - memmgr_usage_bytes_t += sizeof(struct block) * (BLOCK_ALLOC); - if(p == NULL) { - ShowFatalError("Memory manager::block_alloc failed.\n"); - exit(EXIT_FAILURE); - } - - if(block_first == NULL) { - /* First ensure */ - block_first = p; - } else { - block_last->block_next = p; - } - block_last = &p[BLOCK_ALLOC - 1]; - block_last->block_next = NULL; - /* Linking the block */ - for(i=0;iunfill_prev = &block_head; - p->unfill_next = NULL; - p->unit_size = (unsigned short)(hash2size( hash ) + sizeof(struct unit_head)); - p->unit_hash = hash; - p->unit_count = BLOCK_DATA_SIZE / p->unit_size; - p->unit_used = 0; - p->unit_unfill = 0xFFFF; - p->unit_maxused = 0; -#ifdef DEBUG_MEMMGR - memset( p->data, 0xfd, sizeof(p->data) ); -#endif - return p; -} - -static void block_free(struct block* p) -{ - if( p->unfill_prev ) { - if( p->unfill_prev == &block_head) { - hash_unfill[ p->unit_hash ] = p->unfill_next; - } else { - p->unfill_prev->unfill_next = p->unfill_next; - } - if( p->unfill_next ) { - p->unfill_next->unfill_prev = p->unfill_prev; - } - p->unfill_prev = NULL; - } - - p->unfill_next = hash_unfill[0]; - hash_unfill[0] = p; -} - -size_t memmgr_usage (void) -{ - return memmgr_usage_bytes / 1024; -} - -#ifdef LOG_MEMMGR -static char memmer_logfile[128]; -static FILE *log_fp; - -static void memmgr_log(char *buf, char *vcsinfo) { - if( !log_fp ) { - time_t raw; - struct tm* t; - - log_fp = fopen(memmer_logfile,"at"); - if (!log_fp) log_fp = stdout; - - time(&raw); - t = localtime(&raw); - fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (%s).\n", - (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, vcsinfo); - } - fprintf(log_fp, "%s", buf); - return; -} -#endif /* LOG_MEMMGR */ - -/// Returns true if the memory location is active. -/// Active means it is allocated and points to a usable part. -/// -/// @param ptr Pointer to the memory -/// @return true if the memory is active -bool memmgr_verify(void* ptr) -{ - struct block* block = block_first; - struct unit_head_large* large = unit_head_large_first; - - if( ptr == NULL ) - return false;// never valid - - // search small blocks - while( block ) - { - if( (char*)ptr >= (char*)block && (char*)ptr < ((char*)block) + sizeof(struct block) ) - {// found memory block - if( block->unit_used && (char*)ptr >= block->data ) - {// memory block is being used and ptr points to a sub-unit - size_t i = (size_t)((char*)ptr - block->data)/block->unit_size; - struct unit_head* head = block2unit(block, i); - if( i < block->unit_maxused && head->block != NULL ) - {// memory unit is allocated, check if ptr points to the usable part - return ( (char*)ptr >= ((char*)head) + sizeof(struct unit_head) - sizeof(long) - && (char*)ptr < ((char*)head) + sizeof(struct unit_head) - sizeof(long) + head->size ); - } - } - return false; - } - block = block->block_next; - } - - // search large blocks - while( large ) - { - if( (char*)ptr >= (char*)large && (char*)ptr < ((char*)large) + large->size ) - {// found memory block, check if ptr points to the usable part - return ( (char*)ptr >= ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) - && (char*)ptr < ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) + large->size ); - } - large = large->next; - } - return false; -} - -static void memmgr_final (void) -{ - struct block *block = block_first; - struct unit_head_large *large = unit_head_large_first; - char vcsinfo[256]; -#ifdef LOG_MEMMGR - int count = 0; -#endif /* LOG_MEMMGR */ - snprintf(vcsinfo, sizeof(vcsinfo), "%s rev '%s'", sysinfo->vcstype(), sysinfo->vcsrevision_src()); // Cache VCS info before we free() it - sysinfo->final(); - - while (block) { - if (block->unit_used) { - int i; - for (i = 0; i < block->unit_maxused; i++) { - struct unit_head *head = block2unit(block, i); - if(head->block != NULL) { - char* ptr = (char *)head + sizeof(struct unit_head) - sizeof(long); -#ifdef LOG_MEMMGR - char buf[1024]; - sprintf (buf, - "%04d : %s line %d size %lu address 0x%p\n", ++count, - head->file, head->line, (unsigned long)head->size, ptr); - memmgr_log(buf, vcsinfo); -#endif /* LOG_MEMMGR */ - // get block pointer and free it [celest] - iMalloc->free(ptr, ALC_MARK); - } - } - } - block = block->block_next; - } - - while(large) { - struct unit_head_large *large2; -#ifdef LOG_MEMMGR - char buf[1024]; - sprintf (buf, - "%04d : %s line %d size %lu address 0x%p\n", ++count, - large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum); - memmgr_log(buf, vcsinfo); -#endif /* LOG_MEMMGR */ - large2 = large->next; - FREE(large,file,line,func); - large = large2; - } -#ifdef LOG_MEMMGR - if(count == 0) { - ShowInfo("Memory manager: No memory leaks found.\n"); - } else { - ShowWarning("Memory manager: Memory leaks found and fixed.\n"); - fclose(log_fp); - } -#endif /* LOG_MEMMGR */ -} -/* [Ind/Hercules] */ -void memmgr_report (int extra) { - struct block *block = block_first; - struct unit_head_large *large = unit_head_large_first; - unsigned int count = 0, size = 0; - int j; - unsigned short msize = 1024; - struct { - const char *file; - unsigned short line; - size_t size; - unsigned int count; - } data[100]; - memset(&data, 0, sizeof(data)); - - if( extra != 0 ) - msize = extra; - - while (block) { - if (block->unit_used) { - int i; - for (i = 0; i < block->unit_maxused; i++) { - struct unit_head *head = block2unit(block, i); - if( head->block != NULL && head->size > msize ) { - for( j = 0; j < 100; j++ ) { - if( data[j].file == head->file && data[j].line == head->line ) { - data[j].size += head->size; - data[j].count += 1; - break; - } else if( data[j].size == 0 ) { - data[j].file = head->file; - data[j].line = head->line; - data[j].size = head->size; - data[j].count += 1; - break; - } - } - size += (unsigned int)head->size; - count++; - } - } - } - block = block->block_next; - } - - while(large) { - if( large->size > msize ) { - for( j = 0; j < 100; j++ ) { - if( data[j].file == large->unit_head.file && data[j].line == large->unit_head.line ) { - data[j].size += large->size; - data[j].count += 1; - break; - } else if( data[j].size == 0 ) { - data[j].file = large->unit_head.file; - data[j].line = large->unit_head.line; - data[j].size = large->size; - data[j].count += 1; - break; - } - } - size += (unsigned int)large->size; - count++; - } - large = large->next; - } - for( j = 0; j < 100; j++ ) { - if( data[j].size != 0 ) { - ShowMessage("[malloc] : "CL_WHITE"%s"CL_RESET":"CL_WHITE"%d"CL_RESET" %d instances => %.2f MB\n",data[j].file,data[j].line,data[j].count,(double)((data[j].size)/1024)/1024); - } - } - ShowMessage("[malloc] : reporting %u instances | %.2f MB\n",count,(double)((size)/1024)/1024); - ShowMessage("[malloc] : internal usage %.2f MB | %.2f MB\n",(double)((memmgr_usage_bytes_t-memmgr_usage_bytes)/1024)/1024,(double)((memmgr_usage_bytes_t)/1024)/1024); - - if (extra) { - ShowMessage("[malloc] : unit_head_large: %"PRIuS" bytes\n", sizeof(struct unit_head_large)); - ShowMessage("[malloc] : unit_head: %"PRIuS" bytes\n", sizeof(struct unit_head)); - ShowMessage("[malloc] : block: %"PRIuS" bytes\n", sizeof(struct block)); - } - -} - -/** - * Initializes the Memory Manager. - */ -static void memmgr_init(void) -{ -#ifdef LOG_MEMMGR - memset(hash_unfill, 0, sizeof(hash_unfill)); -#endif /* LOG_MEMMGR */ -} - -/** - * Prints initialization messages from the Memory Manager. - */ -static void memmgr_init_messages(void) -{ -#ifdef LOG_MEMMGR - sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME); - ShowStatus("Memory manager initialized: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); -#endif /* LOG_MEMMGR */ -} -#endif /* USE_MEMMGR */ - - -/*====================================== -* Initialize -*-------------------------------------- -*/ - - -/// Tests the memory for errors and memory leaks. -void malloc_memory_check(void) -{ - MEMORY_CHECK(); -} - - -/// Returns true if a pointer is valid. -/// The check is best-effort, false positives are possible. -bool malloc_verify_ptr(void* ptr) { -#ifdef USE_MEMMGR - return memmgr_verify(ptr) && MEMORY_VERIFY(ptr); -#else - return MEMORY_VERIFY(ptr); -#endif -} - - -size_t malloc_usage (void) { -#ifdef USE_MEMMGR - return memmgr_usage (); -#else - return MEMORY_USAGE(); -#endif -} - -void malloc_final (void) { -#ifdef USE_MEMMGR - memmgr_final (); -#endif - MEMORY_CHECK(); - if( iMalloc->post_shutdown ) - iMalloc->post_shutdown(); -} - -/** - * Prints initialization status messages. - * - * This is separated from malloc_init() in order to be run after giving the - * chance to other modules to initialize, in case they want to silence any - * status messages, but at the same time require malloc. - */ -void malloc_init_messages(void) -{ -#ifdef USE_MEMMGR - memmgr_init_messages(); -#endif -} - -void malloc_init(void) -{ -#ifdef USE_MEMMGR - memmgr_usage_bytes_t = 0; - memmgr_usage_bytes = 0; -#endif -#if defined(DMALLOC) && defined(CYGWIN) - // http://dmalloc.com/docs/latest/online/dmalloc_19.html - dmalloc_debug_setup(getenv("DMALLOC_OPTIONS")); -#endif -#ifdef GCOLLECT - // don't garbage collect, only report inaccessible memory that was not deallocated - GC_find_leak = 1; - GC_INIT(); -#endif -#ifdef USE_MEMMGR - memmgr_init(); -#endif -} - -void malloc_defaults(void) { - iMalloc = &iMalloc_s; - iMalloc->init = malloc_init; - iMalloc->final = malloc_final; - iMalloc->memory_check = malloc_memory_check; - iMalloc->usage = malloc_usage; - iMalloc->verify_ptr = malloc_verify_ptr; - -// Athena's built-in Memory Manager -#ifdef USE_MEMMGR - iMalloc->malloc = mmalloc_; - iMalloc->calloc = mcalloc_; - iMalloc->realloc = mrealloc_; - iMalloc->reallocz = mreallocz_; - iMalloc->astrdup = mstrdup_; - iMalloc->free = mfree_; -#else - 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->astrdup = aStrdup_; - iMalloc->free = aFree_; -#endif - iMalloc->post_shutdown = NULL; - iMalloc->init_messages = malloc_init_messages; -} diff --git a/src/common/malloc.h b/src/common/malloc.h deleted file mode 100644 index b194c7cf3..000000000 --- a/src/common/malloc.h +++ /dev/null @@ -1,89 +0,0 @@ -// 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 - -#include "common/hercules.h" - -#define ALC_MARK __FILE__, __LINE__, __func__ - - -// default use of the built-in memory manager -#if !defined(NO_MEMMGR) && !defined(USE_MEMMGR) -#if defined(MEMWATCH) || defined(DMALLOC) || defined(GCOLLECT) -// disable built-in memory manager when using another memory library -#define NO_MEMMGR -#else -// use built-in memory manager by default -#define USE_MEMMGR -#endif -#endif - - -////////////////////////////////////////////////////////////////////// -// Enable memory manager logging by default -#define LOG_MEMMGR - -// no logging for minicore -#if defined(MINICORE) && defined(LOG_MEMMGR) - #undef LOG_MEMMGR -#endif - -# define aMalloc(n) (iMalloc->malloc((n),ALC_MARK)) -# define aCalloc(m,n) (iMalloc->calloc((m),(n),ALC_MARK)) -# define aRealloc(p,n) (iMalloc->realloc((p),(n),ALC_MARK)) -# define aReallocz(p,n) (iMalloc->reallocz((p),(n),ALC_MARK)) -# define aStrdup(p) (iMalloc->astrdup((p),ALC_MARK)) -# define aFree(p) (iMalloc->free((p),ALC_MARK)) - -/////////////// Buffer Creation ///////////////// -// Full credit for this goes to Shinomori [Ajarn] - -#ifdef __GNUC__ // GCC has variable length arrays - -#define CREATE_BUFFER(name, type, size) type name[size] -#define DELETE_BUFFER(name) - -#else // others don't, so we emulate them - -#define CREATE_BUFFER(name, type, size) type *name = (type *) aCalloc((size), sizeof(type)) -#define DELETE_BUFFER(name) aFree(name) - -#endif - -////////////// Others ////////////////////////// -// should be merged with any of above later -#define CREATE(result, type, number) ((result) = (type *) aCalloc((number), sizeof(type))) -#define RECREATE(result, type, number) ((result) = (type *) aReallocz((result), sizeof(type) * (number))) - -//////////////////////////////////////////////// - -struct malloc_interface { - void (*init) (void); - void (*final) (void); - /* */ - void* (*malloc)(size_t size, const char *file, int line, const char *func); - void* (*calloc)(size_t num, size_t size, const char *file, int line, const char *func); - void* (*realloc)(void *p, size_t size, const char *file, int line, const char *func); - void* (*reallocz)(void *p, size_t size, const char *file, int line, const char *func); - char* (*astrdup)(const char *p, const char *file, int line, const char *func); - void (*free)(void *p, const char *file, int line, const char *func); - /* */ - void (*memory_check)(void); - bool (*verify_ptr)(void* ptr); - size_t (*usage) (void); - /* */ - void (*post_shutdown) (void); - void (*init_messages) (void); -}; - -#ifdef HERCULES_CORE -void malloc_defaults(void); - -void memmgr_report(int extra); -#endif // HERCULES_CORE - -HPShared struct malloc_interface *iMalloc; - -#endif /* COMMON_MALLOC_H */ diff --git a/src/common/memmgr.c b/src/common/memmgr.c new file mode 100644 index 000000000..18caef95f --- /dev/null +++ b/src/common/memmgr.c @@ -0,0 +1,897 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams + +#define HERCULES_CORE + +#include "memmgr.h" + +#include "common/cbasetypes.h" +#include "common/core.h" +#include "common/showmsg.h" +#include "common/sysinfo.h" + +#include +#include +#include + +struct malloc_interface iMalloc_s; +struct malloc_interface *iMalloc; + +////////////// Memory Libraries ////////////////// + +#if defined(MEMWATCH) + +# include +# include +# define MALLOC(n,file,line,func) mwMalloc((n),(file),(line)) +# define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line)) +# define REALLOC(p,n,file,line,func) mwRealloc((p),(n),(file),(line)) +# define STRDUP(p,file,line,func) mwStrdup((p),(file),(line)) +# define FREE(p,file,line,func) mwFree((p),(file),(line)) +# define MEMORY_USAGE() (size_t)0 +# define MEMORY_VERIFY(ptr) mwIsSafeAddr((ptr), 1) +# define MEMORY_CHECK() CHECK() + +#elif defined(DMALLOC) + +# include +# include +# include +# define MALLOC(n,file,line,func) dmalloc_malloc((file),(line),(n),DMALLOC_FUNC_MALLOC,0,0) +# define CALLOC(m,n,file,line,func) dmalloc_malloc((file),(line),(m)*(n),DMALLOC_FUNC_CALLOC,0,0) +# define REALLOC(p,n,file,line,func) dmalloc_realloc((file),(line),(p),(n),DMALLOC_FUNC_REALLOC,0) +# define STRDUP(p,file,line,func) strdup(p) +# define FREE(p,file,line,func) free(p) +# define MEMORY_USAGE() dmalloc_memory_allocated() +# define MEMORY_VERIFY(ptr) (dmalloc_verify(ptr) == DMALLOC_VERIFY_NOERROR) +# define MEMORY_CHECK() do { dmalloc_log_stats(); dmalloc_log_unfreed() } while(0) + +#elif defined(GCOLLECT) + +# include +# ifdef GC_ADD_CALLER +# define RETURN_ADDR 0, +# else +# define RETURN_ADDR +# endif +# define MALLOC(n,file,line,func) GC_debug_malloc((n), RETURN_ADDR (file),(line)) +# define CALLOC(m,n,file,line,func) GC_debug_malloc((m)*(n), RETURN_ADDR (file),(line)) +# define REALLOC(p,n,file,line,func) GC_debug_realloc((p),(n), RETURN_ADDR (file),(line)) +# define STRDUP(p,file,line,func) GC_debug_strdup((p), RETURN_ADDR (file),(line)) +# define FREE(p,file,line,func) GC_debug_free(p) +# define MEMORY_USAGE() GC_get_heap_size() +# define MEMORY_VERIFY(ptr) (GC_base(ptr) != NULL) +# define MEMORY_CHECK() GC_gcollect() + +# undef RETURN_ADDR + +#else + +# define MALLOC(n,file,line,func) malloc(n) +# define CALLOC(m,n,file,line,func) calloc((m),(n)) +# define REALLOC(p,n,file,line,func) realloc((p),(n)) +# define STRDUP(p,file,line,func) strdup(p) +# define FREE(p,file,line,func) free(p) +# define MEMORY_USAGE() (size_t)0 +# define MEMORY_VERIFY(ptr) true +# define MEMORY_CHECK() + +#endif + +void* aMalloc_(size_t size, const char *file, int line, const char *func) +{ + void *ret = MALLOC(size, file, line, func); + // ShowMessage("%s:%d: in func %s: aMalloc %d\n",file,line,func,size); + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aMalloc error out of memory!\n",file,line,func); + exit(EXIT_FAILURE); + } + + return ret; +} +void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func) +{ + void *ret = CALLOC(num, size, file, line, func); + // ShowMessage("%s:%d: in func %s: aCalloc %d %d\n",file,line,func,num,size); + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aCalloc error out of memory!\n", file, line, func); + exit(EXIT_FAILURE); + } + return ret; +} +void* aRealloc_(void *p, size_t size, const char *file, int line, const char *func) +{ + void *ret = REALLOC(p, size, file, line, func); + // ShowMessage("%s:%d: in func %s: aRealloc %p %d\n",file,line,func,p,size); + 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); + // ShowMessage("%s:%d: in func %s: aStrdup %p\n",file,line,func,p); + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aStrdup error out of memory!\n", file, line, func); + exit(EXIT_FAILURE); + } + return ret; +} +void aFree_(void *p, const char *file, int line, const char *func) +{ + // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p); + if (p) + FREE(p, file, line, func); + //p = NULL; +} + + +#ifdef USE_MEMMGR + +#if defined(DEBUG) +#define DEBUG_MEMMGR +#endif + +/* USE_MEMMGR */ + +/* +* Memory manager +* able to handle malloc and free efficiently +* Since the complex processing, I might be slightly heavier. +* +* (I'm sorry for the poor description ^ ^;) such as data structures +* Divided into "blocks" of a plurality of memory, "unit" of a plurality of blocks further +* I have to divide. Size of the unit, a plurality of distribution equal to the capacity of one block +* That's what you have. For example, if one unit of 32KB, one block 1 Yu 32Byte +* Knit, or are able to gather 1024, gathered 512 units 64Byte +* I can be or have. (Excluding padding, the unit_head) +* +* Lead-linked list (block_prev, block_next) in each other is the same size block +* Linked list (hash_prev, hash_nect) even among such one in the block with the figure +* I like to have. Thus, reuse of memory no longer needed can be performed efficiently. +*/ + +/* Alignment of the block */ +#define BLOCK_ALIGNMENT1 16 +#define BLOCK_ALIGNMENT2 64 + +/* Amount of data entering a block */ +#define BLOCK_DATA_COUNT1 128 +#define BLOCK_DATA_COUNT2 608 + +/* The size of the block: 16*128 + 64*576 = 40KB */ +#define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 ) +#define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 ) +#define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 ) + +/* The number of blocks to be allocated at a time. */ +#define BLOCK_ALLOC 104 + +/* block */ +struct block { + struct block *block_next; ///< Then the allocated area + struct block *unfill_prev; ///< The previous area not filled + struct block *unfill_next; ///< The next area not filled + unsigned short unit_size; ///< The size of the unit + unsigned short unit_hash; ///< The hash of the unit + unsigned short unit_count; ///< The number of units + unsigned short unit_used; ///< The number of used units + unsigned short unit_unfill; ///< The number of unused units + unsigned short unit_maxused; ///< The maximum value of units used + char data[BLOCK_DATA_SIZE]; +}; + +struct unit_head { + struct block *block; + const char* file; + unsigned short line; + unsigned short size; + long checksum; +}; + +static struct block* hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1]; +static struct block* block_first, *block_last, block_head; + +/* Data for areas that do not use the memory be turned */ +struct unit_head_large { + size_t size; + struct unit_head_large* prev; + struct unit_head_large* next; + struct unit_head unit_head; +}; + +static struct unit_head_large *unit_head_large_first = NULL; + +static struct block* block_malloc(unsigned short hash); +static void block_free(struct block* p); +static size_t memmgr_usage_bytes; +static size_t memmgr_usage_bytes_t; + + +#define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ])) +#define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0) + +static unsigned short size2hash( size_t size ) +{ + if( size <= BLOCK_DATA_SIZE1 ) { + return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1; + } else if( size <= BLOCK_DATA_SIZE ){ + return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2 + + BLOCK_DATA_COUNT1; + } else { + return 0xffff; // If it exceeds the block length hash I do not + } +} + +static size_t hash2size( unsigned short hash ) +{ + if( hash <= BLOCK_DATA_COUNT1) { + return hash * BLOCK_ALIGNMENT1; + } else { + return (hash - BLOCK_DATA_COUNT1) * BLOCK_ALIGNMENT2 + BLOCK_DATA_SIZE1; + } +} + +void *mmalloc_(size_t size, const char *file, int line, const char *func) { + struct block *block; + short size_hash = size2hash( size ); + struct unit_head *head; + + if (((long) size) < 0) { + ShowError("mmalloc_: %"PRIdS"\n", size); + return NULL; + } + + if(size == 0) { + return NULL; + } + memmgr_usage_bytes += size; + + /* To ensure the area that exceeds the length of the block, using malloc () to */ + /* At that time, the distinction by assigning NULL to unit_head.block */ + if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { + struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); + memmgr_usage_bytes_t += size+sizeof(struct unit_head_large); + if(p != NULL) { + p->size = size; + p->unit_head.block = NULL; + p->unit_head.size = 0; + p->unit_head.file = file; + p->unit_head.line = (unsigned short)line; + p->prev = NULL; + if (unit_head_large_first == NULL) + p->next = NULL; + else { + unit_head_large_first->prev = p; + p->next = unit_head_large_first; + } + unit_head_large_first = p; + *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; + return (char *)p + sizeof(struct unit_head_large) - sizeof(long); + } else { + ShowFatalError("Memory manager::memmgr_alloc failed (allocating %"PRIuS"+%"PRIuS" bytes at %s:%d).\n", + sizeof(struct unit_head_large), size, file, line); + exit(EXIT_FAILURE); + } + } + + /* When a block of the same size is not ensured, to ensure a new */ + if(hash_unfill[size_hash]) { + block = hash_unfill[size_hash]; + } else { + block = block_malloc(size_hash); + } + + if( block->unit_unfill == 0xFFFF ) { + // there are no more free space that + memmgr_assert(block->unit_used < block->unit_count); + memmgr_assert(block->unit_used == block->unit_maxused); + head = block2unit(block, block->unit_maxused); + block->unit_used++; + block->unit_maxused++; + } else { + head = block2unit(block, block->unit_unfill); + block->unit_unfill = head->size; + block->unit_used++; + } + + if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { + // Since I ran out of the unit, removed from the list unfill + if( block->unfill_prev == &block_head) { + hash_unfill[ size_hash ] = block->unfill_next; + } else { + block->unfill_prev->unfill_next = block->unfill_next; + } + if( block->unfill_next ) { + block->unfill_next->unfill_prev = block->unfill_prev; + } + block->unfill_prev = NULL; + } + +#ifdef DEBUG_MEMMGR + { + size_t i, sz = hash2size( size_hash ); + for( i=0; iline != 0xfdfd ) + { + ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); + } + else + { + ShowError("Memory manager: not-allocated-data is changed.\n"); + } + break; + } + } + memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz ); + } +#endif + + head->block = block; + head->file = file; + head->line = (unsigned short)line; + head->size = (unsigned short)size; + *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; + return (char *)head + sizeof(struct unit_head) - sizeof(long); +} + +void *mcalloc_(size_t num, size_t size, const char *file, int line, const char *func) { + void *p = iMalloc->malloc(num * size,file,line,func); + if (p) + memset(p, 0, num * size); + return p; +} + +void *mrealloc_(void *memblock, size_t size, const char *file, int line, const char *func) { + size_t old_size; + if(memblock == NULL) { + return iMalloc->malloc(size,file,line,func); + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size; + if( old_size == 0 ) { + old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size; + } + if(old_size > size) { + // Size reduction - return> as it is (negligence) + return memblock; + } else { + // Size Large + void *p = iMalloc->malloc(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + } + iMalloc->free(memblock,file,line,func); + return p; + } +} + +/* a mrealloc_ clone with the difference it 'z'eroes the newly created memory */ +void *mreallocz_(void *memblock, size_t size, const char *file, int line, const char *func) { + size_t old_size; + void *p = NULL; + + if(memblock == NULL) { + p = iMalloc->malloc(size,file,line,func); + memset(p,0,size); + return p; + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size; + if( old_size == 0 ) { + old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size; + } + if(old_size > size) { + // Size reduction - return> as it is (negligence) + return memblock; + } else { + // Size Large + p = iMalloc->malloc(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + memset((char*)p+old_size,0,size-old_size); + } + iMalloc->free(memblock,file,line,func); + return p; + } +} + + +char *mstrdup_(const char *p, const char *file, int line, const char *func) { + if(p == NULL) { + return NULL; + } else { + size_t len = strlen(p); + char *string = (char *)iMalloc->malloc(len + 1,file,line,func); + memcpy(string,p,len+1); + return string; + } +} + +void mfree_(void *ptr, const char *file, int line, const char *func) { + struct unit_head *head; + + if (ptr == NULL) + return; + + head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long)); + if(head->size == 0) { + /* area that is directly secured by malloc () */ + struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long)); + if( + *(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size) + != 0xdeadbeaf) + { + ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); + } else { + head->size = 0xFFFF; + if(head_large->prev) { + head_large->prev->next = head_large->next; + } else { + unit_head_large_first = head_large->next; + } + if(head_large->next) { + head_large->next->prev = head_large->prev; + } + memmgr_usage_bytes -= head_large->size; + memmgr_usage_bytes_t -= head_large->size + sizeof(struct unit_head_large); +#ifdef DEBUG_MEMMGR + // set freed memory to 0xfd + memset(ptr, 0xfd, head_large->size); +#endif + FREE(head_large,file,line,func); + } + } else { + /* Release unit */ + struct block *block = head->block; + if( (char*)head - (char*)block > sizeof(struct block) ) { + ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line); + } else if(head->block == NULL) { + ShowError("Memory manager: args of aFree 0x%p is freed pointer %s:%d@%s\n", ptr, file, line, func); + } else if(*(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + head->size) != 0xdeadbeaf) { + ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); + } else { + memmgr_usage_bytes -= head->size; + head->block = NULL; +#ifdef DEBUG_MEMMGR + memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long) ); + head->file = file; + head->line = (unsigned short)line; +#endif + memmgr_assert( block->unit_used > 0 ); + if(--block->unit_used == 0) { + /* Release of the block */ + block_free(block); + } else { + if( block->unfill_prev == NULL) { + // add to unfill list + if( hash_unfill[ block->unit_hash ] ) { + hash_unfill[ block->unit_hash ]->unfill_prev = block; + } + block->unfill_prev = &block_head; + block->unfill_next = hash_unfill[ block->unit_hash ]; + hash_unfill[ block->unit_hash ] = block; + } + head->size = block->unit_unfill; + block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size); + } + } + } +} + +/* Allocating blocks */ +static struct block* block_malloc(unsigned short hash) +{ + struct block *p; + if(hash_unfill[0] != NULL) { + /* Space for the block has already been secured */ + p = hash_unfill[0]; + hash_unfill[0] = hash_unfill[0]->unfill_next; + } else { + int i; + /* Newly allocated space for the block */ + p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ ); + memmgr_usage_bytes_t += sizeof(struct block) * (BLOCK_ALLOC); + if(p == NULL) { + ShowFatalError("Memory manager::block_alloc failed.\n"); + exit(EXIT_FAILURE); + } + + if(block_first == NULL) { + /* First ensure */ + block_first = p; + } else { + block_last->block_next = p; + } + block_last = &p[BLOCK_ALLOC - 1]; + block_last->block_next = NULL; + /* Linking the block */ + for(i=0;iunfill_prev = &block_head; + p->unfill_next = NULL; + p->unit_size = (unsigned short)(hash2size( hash ) + sizeof(struct unit_head)); + p->unit_hash = hash; + p->unit_count = BLOCK_DATA_SIZE / p->unit_size; + p->unit_used = 0; + p->unit_unfill = 0xFFFF; + p->unit_maxused = 0; +#ifdef DEBUG_MEMMGR + memset( p->data, 0xfd, sizeof(p->data) ); +#endif + return p; +} + +static void block_free(struct block* p) +{ + if( p->unfill_prev ) { + if( p->unfill_prev == &block_head) { + hash_unfill[ p->unit_hash ] = p->unfill_next; + } else { + p->unfill_prev->unfill_next = p->unfill_next; + } + if( p->unfill_next ) { + p->unfill_next->unfill_prev = p->unfill_prev; + } + p->unfill_prev = NULL; + } + + p->unfill_next = hash_unfill[0]; + hash_unfill[0] = p; +} + +size_t memmgr_usage (void) +{ + return memmgr_usage_bytes / 1024; +} + +#ifdef LOG_MEMMGR +static char memmer_logfile[128]; +static FILE *log_fp; + +static void memmgr_log(char *buf, char *vcsinfo) { + if( !log_fp ) { + time_t raw; + struct tm* t; + + log_fp = fopen(memmer_logfile,"at"); + if (!log_fp) log_fp = stdout; + + time(&raw); + t = localtime(&raw); + fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (%s).\n", + (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, vcsinfo); + } + fprintf(log_fp, "%s", buf); + return; +} +#endif /* LOG_MEMMGR */ + +/// Returns true if the memory location is active. +/// Active means it is allocated and points to a usable part. +/// +/// @param ptr Pointer to the memory +/// @return true if the memory is active +bool memmgr_verify(void* ptr) +{ + struct block* block = block_first; + struct unit_head_large* large = unit_head_large_first; + + if( ptr == NULL ) + return false;// never valid + + // search small blocks + while( block ) + { + if( (char*)ptr >= (char*)block && (char*)ptr < ((char*)block) + sizeof(struct block) ) + {// found memory block + if( block->unit_used && (char*)ptr >= block->data ) + {// memory block is being used and ptr points to a sub-unit + size_t i = (size_t)((char*)ptr - block->data)/block->unit_size; + struct unit_head* head = block2unit(block, i); + if( i < block->unit_maxused && head->block != NULL ) + {// memory unit is allocated, check if ptr points to the usable part + return ( (char*)ptr >= ((char*)head) + sizeof(struct unit_head) - sizeof(long) + && (char*)ptr < ((char*)head) + sizeof(struct unit_head) - sizeof(long) + head->size ); + } + } + return false; + } + block = block->block_next; + } + + // search large blocks + while( large ) + { + if( (char*)ptr >= (char*)large && (char*)ptr < ((char*)large) + large->size ) + {// found memory block, check if ptr points to the usable part + return ( (char*)ptr >= ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) + && (char*)ptr < ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) + large->size ); + } + large = large->next; + } + return false; +} + +static void memmgr_final (void) +{ + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; + char vcsinfo[256]; +#ifdef LOG_MEMMGR + int count = 0; +#endif /* LOG_MEMMGR */ + snprintf(vcsinfo, sizeof(vcsinfo), "%s rev '%s'", sysinfo->vcstype(), sysinfo->vcsrevision_src()); // Cache VCS info before we free() it + sysinfo->final(); + + while (block) { + if (block->unit_used) { + int i; + for (i = 0; i < block->unit_maxused; i++) { + struct unit_head *head = block2unit(block, i); + if(head->block != NULL) { + char* ptr = (char *)head + sizeof(struct unit_head) - sizeof(long); +#ifdef LOG_MEMMGR + char buf[1024]; + sprintf (buf, + "%04d : %s line %d size %lu address 0x%p\n", ++count, + head->file, head->line, (unsigned long)head->size, ptr); + memmgr_log(buf, vcsinfo); +#endif /* LOG_MEMMGR */ + // get block pointer and free it [celest] + iMalloc->free(ptr, ALC_MARK); + } + } + } + block = block->block_next; + } + + while(large) { + struct unit_head_large *large2; +#ifdef LOG_MEMMGR + char buf[1024]; + sprintf (buf, + "%04d : %s line %d size %lu address 0x%p\n", ++count, + large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum); + memmgr_log(buf, vcsinfo); +#endif /* LOG_MEMMGR */ + large2 = large->next; + FREE(large,file,line,func); + large = large2; + } +#ifdef LOG_MEMMGR + if(count == 0) { + ShowInfo("Memory manager: No memory leaks found.\n"); + } else { + ShowWarning("Memory manager: Memory leaks found and fixed.\n"); + fclose(log_fp); + } +#endif /* LOG_MEMMGR */ +} +/* [Ind/Hercules] */ +void memmgr_report (int extra) { + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; + unsigned int count = 0, size = 0; + int j; + unsigned short msize = 1024; + struct { + const char *file; + unsigned short line; + size_t size; + unsigned int count; + } data[100]; + memset(&data, 0, sizeof(data)); + + if( extra != 0 ) + msize = extra; + + while (block) { + if (block->unit_used) { + int i; + for (i = 0; i < block->unit_maxused; i++) { + struct unit_head *head = block2unit(block, i); + if( head->block != NULL && head->size > msize ) { + for( j = 0; j < 100; j++ ) { + if( data[j].file == head->file && data[j].line == head->line ) { + data[j].size += head->size; + data[j].count += 1; + break; + } else if( data[j].size == 0 ) { + data[j].file = head->file; + data[j].line = head->line; + data[j].size = head->size; + data[j].count += 1; + break; + } + } + size += (unsigned int)head->size; + count++; + } + } + } + block = block->block_next; + } + + while(large) { + if( large->size > msize ) { + for( j = 0; j < 100; j++ ) { + if( data[j].file == large->unit_head.file && data[j].line == large->unit_head.line ) { + data[j].size += large->size; + data[j].count += 1; + break; + } else if( data[j].size == 0 ) { + data[j].file = large->unit_head.file; + data[j].line = large->unit_head.line; + data[j].size = large->size; + data[j].count += 1; + break; + } + } + size += (unsigned int)large->size; + count++; + } + large = large->next; + } + for( j = 0; j < 100; j++ ) { + if( data[j].size != 0 ) { + ShowMessage("[malloc] : "CL_WHITE"%s"CL_RESET":"CL_WHITE"%d"CL_RESET" %d instances => %.2f MB\n",data[j].file,data[j].line,data[j].count,(double)((data[j].size)/1024)/1024); + } + } + ShowMessage("[malloc] : reporting %u instances | %.2f MB\n",count,(double)((size)/1024)/1024); + ShowMessage("[malloc] : internal usage %.2f MB | %.2f MB\n",(double)((memmgr_usage_bytes_t-memmgr_usage_bytes)/1024)/1024,(double)((memmgr_usage_bytes_t)/1024)/1024); + + if (extra) { + ShowMessage("[malloc] : unit_head_large: %"PRIuS" bytes\n", sizeof(struct unit_head_large)); + ShowMessage("[malloc] : unit_head: %"PRIuS" bytes\n", sizeof(struct unit_head)); + ShowMessage("[malloc] : block: %"PRIuS" bytes\n", sizeof(struct block)); + } + +} + +/** + * Initializes the Memory Manager. + */ +static void memmgr_init(void) +{ +#ifdef LOG_MEMMGR + memset(hash_unfill, 0, sizeof(hash_unfill)); +#endif /* LOG_MEMMGR */ +} + +/** + * Prints initialization messages from the Memory Manager. + */ +static void memmgr_init_messages(void) +{ +#ifdef LOG_MEMMGR + sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME); + ShowStatus("Memory manager initialized: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); +#endif /* LOG_MEMMGR */ +} +#endif /* USE_MEMMGR */ + + +/*====================================== +* Initialize +*-------------------------------------- +*/ + + +/// Tests the memory for errors and memory leaks. +void malloc_memory_check(void) +{ + MEMORY_CHECK(); +} + + +/// Returns true if a pointer is valid. +/// The check is best-effort, false positives are possible. +bool malloc_verify_ptr(void* ptr) { +#ifdef USE_MEMMGR + return memmgr_verify(ptr) && MEMORY_VERIFY(ptr); +#else + return MEMORY_VERIFY(ptr); +#endif +} + + +size_t malloc_usage (void) { +#ifdef USE_MEMMGR + return memmgr_usage (); +#else + return MEMORY_USAGE(); +#endif +} + +void malloc_final (void) { +#ifdef USE_MEMMGR + memmgr_final (); +#endif + MEMORY_CHECK(); + if( iMalloc->post_shutdown ) + iMalloc->post_shutdown(); +} + +/** + * Prints initialization status messages. + * + * This is separated from malloc_init() in order to be run after giving the + * chance to other modules to initialize, in case they want to silence any + * status messages, but at the same time require malloc. + */ +void malloc_init_messages(void) +{ +#ifdef USE_MEMMGR + memmgr_init_messages(); +#endif +} + +void malloc_init(void) +{ +#ifdef USE_MEMMGR + memmgr_usage_bytes_t = 0; + memmgr_usage_bytes = 0; +#endif +#if defined(DMALLOC) && defined(CYGWIN) + // http://dmalloc.com/docs/latest/online/dmalloc_19.html + dmalloc_debug_setup(getenv("DMALLOC_OPTIONS")); +#endif +#ifdef GCOLLECT + // don't garbage collect, only report inaccessible memory that was not deallocated + GC_find_leak = 1; + GC_INIT(); +#endif +#ifdef USE_MEMMGR + memmgr_init(); +#endif +} + +void malloc_defaults(void) { + iMalloc = &iMalloc_s; + iMalloc->init = malloc_init; + iMalloc->final = malloc_final; + iMalloc->memory_check = malloc_memory_check; + iMalloc->usage = malloc_usage; + iMalloc->verify_ptr = malloc_verify_ptr; + +// Athena's built-in Memory Manager +#ifdef USE_MEMMGR + iMalloc->malloc = mmalloc_; + iMalloc->calloc = mcalloc_; + iMalloc->realloc = mrealloc_; + iMalloc->reallocz = mreallocz_; + iMalloc->astrdup = mstrdup_; + iMalloc->free = mfree_; +#else + 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->astrdup = aStrdup_; + iMalloc->free = aFree_; +#endif + iMalloc->post_shutdown = NULL; + iMalloc->init_messages = malloc_init_messages; +} diff --git a/src/common/memmgr.h b/src/common/memmgr.h new file mode 100644 index 000000000..b194c7cf3 --- /dev/null +++ b/src/common/memmgr.h @@ -0,0 +1,89 @@ +// 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 + +#include "common/hercules.h" + +#define ALC_MARK __FILE__, __LINE__, __func__ + + +// default use of the built-in memory manager +#if !defined(NO_MEMMGR) && !defined(USE_MEMMGR) +#if defined(MEMWATCH) || defined(DMALLOC) || defined(GCOLLECT) +// disable built-in memory manager when using another memory library +#define NO_MEMMGR +#else +// use built-in memory manager by default +#define USE_MEMMGR +#endif +#endif + + +////////////////////////////////////////////////////////////////////// +// Enable memory manager logging by default +#define LOG_MEMMGR + +// no logging for minicore +#if defined(MINICORE) && defined(LOG_MEMMGR) + #undef LOG_MEMMGR +#endif + +# define aMalloc(n) (iMalloc->malloc((n),ALC_MARK)) +# define aCalloc(m,n) (iMalloc->calloc((m),(n),ALC_MARK)) +# define aRealloc(p,n) (iMalloc->realloc((p),(n),ALC_MARK)) +# define aReallocz(p,n) (iMalloc->reallocz((p),(n),ALC_MARK)) +# define aStrdup(p) (iMalloc->astrdup((p),ALC_MARK)) +# define aFree(p) (iMalloc->free((p),ALC_MARK)) + +/////////////// Buffer Creation ///////////////// +// Full credit for this goes to Shinomori [Ajarn] + +#ifdef __GNUC__ // GCC has variable length arrays + +#define CREATE_BUFFER(name, type, size) type name[size] +#define DELETE_BUFFER(name) + +#else // others don't, so we emulate them + +#define CREATE_BUFFER(name, type, size) type *name = (type *) aCalloc((size), sizeof(type)) +#define DELETE_BUFFER(name) aFree(name) + +#endif + +////////////// Others ////////////////////////// +// should be merged with any of above later +#define CREATE(result, type, number) ((result) = (type *) aCalloc((number), sizeof(type))) +#define RECREATE(result, type, number) ((result) = (type *) aReallocz((result), sizeof(type) * (number))) + +//////////////////////////////////////////////// + +struct malloc_interface { + void (*init) (void); + void (*final) (void); + /* */ + void* (*malloc)(size_t size, const char *file, int line, const char *func); + void* (*calloc)(size_t num, size_t size, const char *file, int line, const char *func); + void* (*realloc)(void *p, size_t size, const char *file, int line, const char *func); + void* (*reallocz)(void *p, size_t size, const char *file, int line, const char *func); + char* (*astrdup)(const char *p, const char *file, int line, const char *func); + void (*free)(void *p, const char *file, int line, const char *func); + /* */ + void (*memory_check)(void); + bool (*verify_ptr)(void* ptr); + size_t (*usage) (void); + /* */ + void (*post_shutdown) (void); + void (*init_messages) (void); +}; + +#ifdef HERCULES_CORE +void malloc_defaults(void); + +void memmgr_report(int extra); +#endif // HERCULES_CORE + +HPShared struct malloc_interface *iMalloc; + +#endif /* COMMON_MALLOC_H */ 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 b4b67da40..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" 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 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 // 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 f6ce00d54..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" diff --git a/src/login/HPMlogin.c b/src/login/HPMlogin.c index b900f28fe..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" 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 1d8ef489a..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" diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index edbe74039..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" diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 15422a74a..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" diff --git a/src/map/battle.c b/src/map/battle.c index 5b147de9c..1f9d75a64 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" diff --git a/src/map/battleground.c b/src/map/battleground.c index be6b7a863..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" 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 a27038ff7..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" diff --git a/src/map/clif.c b/src/map/clif.c index 9c7d327e6..bbd2f8c7f 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" 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 f8798f821..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" 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 0936a5ace..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" 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 ccfff2246..3afb10bec 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" diff --git a/src/map/map.c b/src/map/map.c index c64ab86b9..9a7cbe163 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" 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 01f585b6f..a14fa02df 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" diff --git a/src/map/npc.c b/src/map/npc.c index 24b22beb3..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" 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 f7e7d431c..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" diff --git a/src/map/path.c b/src/map/path.c index 29701d445..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" diff --git a/src/map/pc.c b/src/map/pc.c index fe339c457..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" 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 4958644ee..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" diff --git a/src/map/script.c b/src/map/script.c index 5dbe62df3..006daf7b9 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" 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 d37dfc057..7a7a4f415 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -28,7 +28,7 @@ #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" 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 diff --git a/src/map/unit.c b/src/map/unit.c index dcb5ec900..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" 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/db2sql.c b/src/plugins/db2sql.c index 79eda0e5e..50781f319 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" 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/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" diff --git a/vcproj-10/char-server.vcxproj b/vcproj-10/char-server.vcxproj index 34d983d95..f17eb6cd4 100644 --- a/vcproj-10/char-server.vcxproj +++ b/vcproj-10/char-server.vcxproj @@ -145,7 +145,7 @@ - + @@ -191,7 +191,7 @@ - + diff --git a/vcproj-10/char-server.vcxproj.filters b/vcproj-10/char-server.vcxproj.filters index b3b9e49cd..2f232b2cc 100644 --- a/vcproj-10/char-server.vcxproj.filters +++ b/vcproj-10/char-server.vcxproj.filters @@ -19,7 +19,7 @@ common - + common @@ -153,7 +153,7 @@ common - + common diff --git a/vcproj-10/login-server.vcxproj b/vcproj-10/login-server.vcxproj index 941a2f859..b7b020b03 100644 --- a/vcproj-10/login-server.vcxproj +++ b/vcproj-10/login-server.vcxproj @@ -154,7 +154,7 @@ - + @@ -187,7 +187,7 @@ - + diff --git a/vcproj-10/login-server.vcxproj.filters b/vcproj-10/login-server.vcxproj.filters index 6d83824eb..27bad5e85 100644 --- a/vcproj-10/login-server.vcxproj.filters +++ b/vcproj-10/login-server.vcxproj.filters @@ -28,7 +28,7 @@ common - + common @@ -126,7 +126,7 @@ common - + common diff --git a/vcproj-10/map-server.vcxproj b/vcproj-10/map-server.vcxproj index 338865a52..cbd4706c4 100644 --- a/vcproj-10/map-server.vcxproj +++ b/vcproj-10/map-server.vcxproj @@ -144,7 +144,7 @@ - + @@ -222,7 +222,7 @@ - + diff --git a/vcproj-10/map-server.vcxproj.filters b/vcproj-10/map-server.vcxproj.filters index bd43e0d00..997a2970d 100644 --- a/vcproj-10/map-server.vcxproj.filters +++ b/vcproj-10/map-server.vcxproj.filters @@ -136,7 +136,7 @@ common - + common @@ -348,7 +348,7 @@ common - + common diff --git a/vcproj-10/mapcache.vcxproj b/vcproj-10/mapcache.vcxproj index 3cdb7b96a..980f31d10 100644 --- a/vcproj-10/mapcache.vcxproj +++ b/vcproj-10/mapcache.vcxproj @@ -127,7 +127,7 @@ - + @@ -141,7 +141,7 @@ - + diff --git a/vcproj-10/mapcache.vcxproj.filters b/vcproj-10/mapcache.vcxproj.filters index fd376830e..903d34522 100644 --- a/vcproj-10/mapcache.vcxproj.filters +++ b/vcproj-10/mapcache.vcxproj.filters @@ -13,7 +13,7 @@ common - + common @@ -51,7 +51,7 @@ common - + common diff --git a/vcproj-11/char-server.vcxproj b/vcproj-11/char-server.vcxproj index 073b37e5a..49666e898 100644 --- a/vcproj-11/char-server.vcxproj +++ b/vcproj-11/char-server.vcxproj @@ -148,7 +148,7 @@ - + @@ -194,7 +194,7 @@ - + diff --git a/vcproj-11/char-server.vcxproj.filters b/vcproj-11/char-server.vcxproj.filters index b3b9e49cd..2f232b2cc 100644 --- a/vcproj-11/char-server.vcxproj.filters +++ b/vcproj-11/char-server.vcxproj.filters @@ -19,7 +19,7 @@ common - + common @@ -153,7 +153,7 @@ common - + common diff --git a/vcproj-11/login-server.vcxproj b/vcproj-11/login-server.vcxproj index aafa462e1..44b5d6381 100644 --- a/vcproj-11/login-server.vcxproj +++ b/vcproj-11/login-server.vcxproj @@ -158,7 +158,7 @@ - + @@ -191,7 +191,7 @@ - + diff --git a/vcproj-11/login-server.vcxproj.filters b/vcproj-11/login-server.vcxproj.filters index 50a6645f8..c429a223d 100644 --- a/vcproj-11/login-server.vcxproj.filters +++ b/vcproj-11/login-server.vcxproj.filters @@ -34,7 +34,7 @@ common - + common @@ -132,7 +132,7 @@ common - + common diff --git a/vcproj-11/map-server.vcxproj b/vcproj-11/map-server.vcxproj index f837c682c..e4a932d65 100644 --- a/vcproj-11/map-server.vcxproj +++ b/vcproj-11/map-server.vcxproj @@ -148,7 +148,7 @@ - + @@ -226,7 +226,7 @@ - + diff --git a/vcproj-11/map-server.vcxproj.filters b/vcproj-11/map-server.vcxproj.filters index bd43e0d00..997a2970d 100644 --- a/vcproj-11/map-server.vcxproj.filters +++ b/vcproj-11/map-server.vcxproj.filters @@ -136,7 +136,7 @@ common - + common @@ -348,7 +348,7 @@ common - + common diff --git a/vcproj-11/mapcache.vcxproj b/vcproj-11/mapcache.vcxproj index 3ad70626f..2779ae778 100644 --- a/vcproj-11/mapcache.vcxproj +++ b/vcproj-11/mapcache.vcxproj @@ -131,7 +131,7 @@ - + @@ -145,7 +145,7 @@ - + diff --git a/vcproj-11/mapcache.vcxproj.filters b/vcproj-11/mapcache.vcxproj.filters index d5c2fbb83..957cabac8 100644 --- a/vcproj-11/mapcache.vcxproj.filters +++ b/vcproj-11/mapcache.vcxproj.filters @@ -13,7 +13,7 @@ common - + common @@ -51,7 +51,7 @@ common - + common diff --git a/vcproj-12/char-server.vcxproj b/vcproj-12/char-server.vcxproj index 5a86a402f..ad2f60c34 100644 --- a/vcproj-12/char-server.vcxproj +++ b/vcproj-12/char-server.vcxproj @@ -147,7 +147,7 @@ - + @@ -193,7 +193,7 @@ - + diff --git a/vcproj-12/char-server.vcxproj.filters b/vcproj-12/char-server.vcxproj.filters index b3b9e49cd..2f232b2cc 100644 --- a/vcproj-12/char-server.vcxproj.filters +++ b/vcproj-12/char-server.vcxproj.filters @@ -19,7 +19,7 @@ common - + common @@ -153,7 +153,7 @@ common - + common diff --git a/vcproj-12/login-server.vcxproj b/vcproj-12/login-server.vcxproj index 1ea0b5ec9..dfc35bf20 100644 --- a/vcproj-12/login-server.vcxproj +++ b/vcproj-12/login-server.vcxproj @@ -158,7 +158,7 @@ - + @@ -191,7 +191,7 @@ - + diff --git a/vcproj-12/login-server.vcxproj.filters b/vcproj-12/login-server.vcxproj.filters index 50a6645f8..c429a223d 100644 --- a/vcproj-12/login-server.vcxproj.filters +++ b/vcproj-12/login-server.vcxproj.filters @@ -34,7 +34,7 @@ common - + common @@ -132,7 +132,7 @@ common - + common diff --git a/vcproj-12/map-server.vcxproj b/vcproj-12/map-server.vcxproj index b08c43cf7..3d8d53f9d 100644 --- a/vcproj-12/map-server.vcxproj +++ b/vcproj-12/map-server.vcxproj @@ -148,7 +148,7 @@ - + @@ -226,7 +226,7 @@ - + diff --git a/vcproj-12/map-server.vcxproj.filters b/vcproj-12/map-server.vcxproj.filters index bd43e0d00..997a2970d 100644 --- a/vcproj-12/map-server.vcxproj.filters +++ b/vcproj-12/map-server.vcxproj.filters @@ -136,7 +136,7 @@ common - + common @@ -348,7 +348,7 @@ common - + common diff --git a/vcproj-12/mapcache.vcxproj b/vcproj-12/mapcache.vcxproj index 37f4a161d..54713b098 100644 --- a/vcproj-12/mapcache.vcxproj +++ b/vcproj-12/mapcache.vcxproj @@ -131,7 +131,7 @@ - + @@ -145,7 +145,7 @@ - + diff --git a/vcproj-12/mapcache.vcxproj.filters b/vcproj-12/mapcache.vcxproj.filters index d5c2fbb83..957cabac8 100644 --- a/vcproj-12/mapcache.vcxproj.filters +++ b/vcproj-12/mapcache.vcxproj.filters @@ -13,7 +13,7 @@ common - + common @@ -51,7 +51,7 @@ common - + common diff --git a/vcproj-14/char-server.vcxproj b/vcproj-14/char-server.vcxproj index 565b99ce6..dd3f53526 100644 --- a/vcproj-14/char-server.vcxproj +++ b/vcproj-14/char-server.vcxproj @@ -146,7 +146,7 @@ - + @@ -192,7 +192,7 @@ - + diff --git a/vcproj-14/char-server.vcxproj.filters b/vcproj-14/char-server.vcxproj.filters index b3b9e49cd..2f232b2cc 100644 --- a/vcproj-14/char-server.vcxproj.filters +++ b/vcproj-14/char-server.vcxproj.filters @@ -19,7 +19,7 @@ common - + common @@ -153,7 +153,7 @@ common - + common diff --git a/vcproj-14/login-server.vcxproj b/vcproj-14/login-server.vcxproj index ca8d0cf23..5589cc35d 100644 --- a/vcproj-14/login-server.vcxproj +++ b/vcproj-14/login-server.vcxproj @@ -156,7 +156,7 @@ - + @@ -189,7 +189,7 @@ - + diff --git a/vcproj-14/login-server.vcxproj.filters b/vcproj-14/login-server.vcxproj.filters index fff84ea41..0d27feaea 100644 --- a/vcproj-14/login-server.vcxproj.filters +++ b/vcproj-14/login-server.vcxproj.filters @@ -34,7 +34,7 @@ common - + common @@ -132,7 +132,7 @@ common - + common diff --git a/vcproj-14/map-server.vcxproj b/vcproj-14/map-server.vcxproj index 264bd2365..425c864f6 100644 --- a/vcproj-14/map-server.vcxproj +++ b/vcproj-14/map-server.vcxproj @@ -146,7 +146,7 @@ - + @@ -224,7 +224,7 @@ - + diff --git a/vcproj-14/map-server.vcxproj.filters b/vcproj-14/map-server.vcxproj.filters index 8347c134a..40ace58c8 100644 --- a/vcproj-14/map-server.vcxproj.filters +++ b/vcproj-14/map-server.vcxproj.filters @@ -136,7 +136,7 @@ common - + common @@ -349,7 +349,7 @@ common - + common diff --git a/vcproj-14/mapcache.vcxproj b/vcproj-14/mapcache.vcxproj index 1d08545e9..7304b8df4 100644 --- a/vcproj-14/mapcache.vcxproj +++ b/vcproj-14/mapcache.vcxproj @@ -129,7 +129,7 @@ - + @@ -143,7 +143,7 @@ - + diff --git a/vcproj-14/mapcache.vcxproj.filters b/vcproj-14/mapcache.vcxproj.filters index d5c2fbb83..957cabac8 100644 --- a/vcproj-14/mapcache.vcxproj.filters +++ b/vcproj-14/mapcache.vcxproj.filters @@ -13,7 +13,7 @@ common - + common @@ -51,7 +51,7 @@ common - + common -- cgit v1.2.3-70-g09d2 From 3feef93f71b52c90ff0ef46af65962d55ef37fed Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 7 Oct 2015 18:32:33 +0300 Subject: Add support for mob_db in conf format. --- src/map/mob.c | 778 ++++++++++++++++++++++++++++++++++++++++------------------ src/map/mob.h | 12 +- 2 files changed, 548 insertions(+), 242 deletions(-) (limited to 'src/map') diff --git a/src/map/mob.c b/src/map/mob.c index a14fa02df..a94abbd97 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -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; + + entry->vd.class_ = class_; + + 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)); + } - 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]); + 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)); + } - exp = (double)atoi(str[7]) * (double)battle_config.base_exp_rate / 100.; - db->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + 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; + } - exp = (double)atoi(str[8]) * (double)battle_config.job_exp_rate / 100.; - db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + if (mob->lookup_const(mobt, "Hp", &i32) && i32 >= 0) { + mstatus->max_hp = i32; + maxhpUpdated = true; + } else if (!inherit) { + mstatus->max_hp = 1; + maxhpUpdated = true; + } - mstatus->rhw.range = atoi(str[9]); + if (mob->lookup_const(mobt, "Sp", &i32) && i32 >= 0) { + mstatus->max_sp = i32; + maxspUpdated = true; + } else if (!inherit) { + maxspUpdated = true; + } - 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, "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->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, "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->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 (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; + } + } + + 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); + } + + 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,257 @@ 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; +} + +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 +} + +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; + } + } + return false; +} + +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; + + *value = libconfig->setting_get_int(it); return true; } /*========================================== * mob_db.txt reading *------------------------------------------*/ -bool mob_readdb_sub(char* fields[], int columns, int current) { - return mob->parse_dbrow(fields); -} - void mob_readdb(void) { const char* filename[] = { - DBPATH"mob_db.txt", - "mob_db2.txt" }; - int fi; + DBPATH"mob_db.conf", + "mob_db2.conf" }; + int i; - 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)) { + for (i = 0; i < ARRAYLENGTH(filename); ++i) { + if (i > 0) { + if (!exists(filename[i])) { continue; } } - 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->read_libconfig(filename[i]); } mob->name_constants(); } -/*========================================== - * 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; - - // 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; - } - - // 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; - 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); - - strcpy(p, data); - str[i] = p; - p+= len + 1; - } - - if (!mob->parse_dbrow(str)) - continue; +int mob_read_libconfig(const char *filename) +{ + config_t mob_db_conf; + char filepath[256]; + config_setting_t *mdb; + config_setting_t *t; + int i = 0; - count++; - } + nullpo_ret(filename); + sprintf(filepath, "%s/%s", map->db_path, filename); - // 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; } @@ -4630,13 +4927,10 @@ 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(); - } + mob->readdb(); if (map->db_use_sql_mob_skill_db) { mob->read_sqlskilldb(); } else { - mob->readdb(); mob->readskilldb(); } sv->readdb(map->db_path, "mob_avail.txt", ',', 2, 12, -1, mob->readdb_mobavail); @@ -4847,10 +5141,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; diff --git a/src/map/mob.h b/src/map/mob.h index bb26258c6..c20453cde 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -363,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); + 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); -- cgit v1.2.3-70-g09d2 From dea96bda4ba64b7bec3738bd5ab93ee435caa717 Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 20 Oct 2015 12:31:00 +0200 Subject: Fixed an issue preventing the mob_db2 from being loaded Follow-up to 3feef93 (thanks to kyeme) Signed-off-by: Haru --- src/map/mob.c | 13 +++++-------- src/map/mob.h | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'src/map') diff --git a/src/map/mob.c b/src/map/mob.c index a94abbd97..94d68df88 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -4256,19 +4256,13 @@ void mob_readdb(void) { int i; for (i = 0; i < ARRAYLENGTH(filename); ++i) { - if (i > 0) { - if (!exists(filename[i])) { - continue; - } - } - - mob->read_libconfig(filename[i]); + mob->read_libconfig(filename[i], i > 0 ? true : false); } mob->name_constants(); } -int mob_read_libconfig(const char *filename) +int mob_read_libconfig(const char *filename, bool ignore_missing) { config_t mob_db_conf; char filepath[256]; @@ -4279,6 +4273,9 @@ int mob_read_libconfig(const char *filename) nullpo_ret(filename); sprintf(filepath, "%s/%s", map->db_path, filename); + if (ignore_missing && !exists(filepath)) + return 0; + 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; diff --git a/src/map/mob.h b/src/map/mob.h index c20453cde..cc81c2fc3 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -366,7 +366,7 @@ struct mob_interface { void (*readdb) (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); + 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); -- cgit v1.2.3-70-g09d2