diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/atcommand.c | 2 | ||||
-rw-r--r-- | src/map/battle.c | 156 | ||||
-rw-r--r-- | src/map/battle.h | 9 | ||||
-rw-r--r-- | src/map/log.c | 323 | ||||
-rw-r--r-- | src/map/log.h | 7 | ||||
-rw-r--r-- | src/map/map.c | 759 | ||||
-rw-r--r-- | src/map/map.h | 17 | ||||
-rw-r--r-- | src/map/mapreg.h | 6 | ||||
-rw-r--r-- | src/map/mapreg_sql.c | 21 | ||||
-rw-r--r-- | src/map/script.c | 85 | ||||
-rw-r--r-- | src/map/script.h | 8 |
11 files changed, 945 insertions, 448 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 8d4aa317f..3f916eb42 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3611,7 +3611,7 @@ ACMD(reloadbattleconf) struct Battle_Config prev_config; memcpy(&prev_config, &battle_config, sizeof(prev_config)); - battle->config_read(map->BATTLE_CONF_FILENAME); + battle->config_read(map->BATTLE_CONF_FILENAME, false); if (prev_config.feature_roulette == 0 && battle_config.feature_roulette == 1 && !clif->parse_roulette_db()) battle_config.feature_roulette = 0; diff --git a/src/map/battle.c b/src/map/battle.c index 908f0364b..c564b81cd 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -41,6 +41,7 @@ #include "map/status.h" #include "common/HPM.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/ers.h" #include "common/memmgr.h" #include "common/nullpo.h" @@ -7018,7 +7019,7 @@ static const struct battle_data { { "show_steal_in_same_party", &battle_config.show_steal_in_same_party, 0, 0, 1, }, { "party_hp_mode", &battle_config.party_hp_mode, 0, 0, 1, }, { "show_party_share_picker", &battle_config.party_show_share_picker, 1, 0, 1, }, - { "show_picker.item_type", &battle_config.show_picker_item_type, 112, 0, INT_MAX, }, + { "show_picker_item_type", &battle_config.show_picker_item_type, 112, 0, INT_MAX, }, { "party_update_interval", &battle_config.party_update_interval, 1000, 100, INT_MAX, }, { "party_item_share_type", &battle_config.party_share_type, 0, 0, 1|2|3, }, { "attack_attr_none", &battle_config.attack_attr_none, ~BL_PC, BL_NUL, BL_ALL, }, @@ -7177,14 +7178,14 @@ static const struct battle_data { { "display_status_timers", &battle_config.display_status_timers, 1, 0, 1, }, { "skill_add_heal_rate", &battle_config.skill_add_heal_rate, 7, 0, INT_MAX, }, { "eq_single_target_reflectable", &battle_config.eq_single_target_reflectable, 1, 0, 1, }, - { "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, }, + { "invincible_nodamage", &battle_config.invincible_nodamage, 0, 0, 1, }, { "mob_slave_keep_target", &battle_config.mob_slave_keep_target, 0, 0, 1, }, { "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, }, { "knockback_left", &battle_config.knockback_left, 1, 0, 1, }, { "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, }, { "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, }, - { "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, }, - { "feature.search_stores", &battle_config.feature_search_stores, 1, 0, 1, }, + { "features/buying_store", &battle_config.feature_buying_store, 1, 0, 1, }, + { "features/search_stores", &battle_config.feature_search_stores, 1, 0, 1, }, { "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, }, { "searchstore_maxresults", &battle_config.searchstore_maxresults, 30, 1, INT_MAX, }, { "display_party_name", &battle_config.display_party_name, 0, 0, 1, }, @@ -7204,7 +7205,7 @@ static const struct battle_data { { "atcommand_max_stat_bypass", &battle_config.atcommand_max_stat_bypass, 0, 0, 100, }, { "skill_amotion_leniency", &battle_config.skill_amotion_leniency, 90, 0, 300 }, { "mvp_tomb_enabled", &battle_config.mvp_tomb_enabled, 1, 0, 1 }, - { "feature.atcommand_suggestions", &battle_config.atcommand_suggestions_enabled, 0, 0, 1 }, + { "features/atcommand_suggestions", &battle_config.atcommand_suggestions_enabled, 0, 0, 1 }, { "min_npc_vendchat_distance", &battle_config.min_npc_vendchat_distance, 3, 0, 100 }, { "vendchat_near_hiddennpc", &battle_config.vendchat_near_hiddennpc, 0, 0, 1 }, { "atcommand_mobinfo_type", &battle_config.atcommand_mobinfo_type, 0, 0, 1 }, @@ -7225,8 +7226,8 @@ static const struct battle_data { { "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, INT_MAX, }, { "snovice_call_type", &battle_config.snovice_call_type, 0, 0, 1, }, { "guild_notice_changemap", &battle_config.guild_notice_changemap, 2, 0, 2, }, - { "feature.banking", &battle_config.feature_banking, 1, 0, 1, }, - { "feature.auction", &battle_config.feature_auction, 0, 0, 2, }, + { "features/banking", &battle_config.feature_banking, 1, 0, 1, }, + { "features/auction", &battle_config.feature_auction, 0, 0, 2, }, { "idletime_criteria", &battle_config.idletime_criteria, 0x25, 1, INT_MAX, }, { "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, }, { "case_sensitive_aegisnames", &battle_config.case_sensitive_aegisnames, 1, 0, 1, }, @@ -7238,7 +7239,7 @@ static const struct battle_data { { "monster_chase_refresh", &battle_config.mob_chase_refresh, 1, 0, 30, }, { "mob_icewall_walk_block", &battle_config.mob_icewall_walk_block, 75, 0, 255, }, { "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, }, - { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, }, + { "features/roulette", &battle_config.feature_roulette, 1, 0, 1, }, { "show_monster_hp_bar", &battle_config.show_monster_hp_bar, 1, 0, 1, }, { "fix_warp_hit_delay_abuse", &battle_config.fix_warp_hit_delay_abuse, 0, 0, 1, }, { "costume_refine_def", &battle_config.costume_refine_def, 1, 0, 1, }, @@ -7413,28 +7414,36 @@ static int Hercules_report_timer(int tid, int64 tick, int id, intptr_t data) { } #endif -int battle_set_value(const char* w1, const char* w2) +bool battle_set_value_sub(int index, int value) { - int val = config_switch(w2); + Assert_retr(false, index >= 0); + if (value < battle_data[index].min || value > battle_data[index].max) { + ShowWarning("Value for setting '%s': %d is invalid (min:%d max:%d)! Defaulting to %d...\n", + battle_data[index].str, value, battle_data[index].min, battle_data[index].max, battle_data[index].defval); + value = battle_data[index].defval; + } + *battle_data[index].val = value; + return true; +} + +bool battle_set_value(const char *param, const char *value) +{ + int val; int i; - nullpo_retr(1, w1); - nullpo_retr(1, w2); - ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); - if (i == ARRAYLENGTH(battle_data)) { - if( HPM->parseConf(w1,w2,HPCT_BATTLE) ) /* if plugin-owned, succeed */ - return 1; - return 0; // not found - } + nullpo_retr(false, param); + nullpo_retr(false, value); - if (val < battle_data[i].min || val > battle_data[i].max) - { - ShowWarning("Value for setting '%s': %s is invalid (min:%i max:%i)! Defaulting to %i...\n", w1, w2, battle_data[i].min, battle_data[i].max, battle_data[i].defval); - val = battle_data[i].defval; + val = config_switch(value); + + ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(param, battle_data[i].str) == 0); + if (i == ARRAYLENGTH(battle_data)) { + if (HPM->parseConf(param, value, HPCT_BATTLE)) /* if plugin-owned, succeed */ + return true; + return false; // not found } - *battle_data[i].val = val; - return 1; + return battle->config_set_value_sub(i, val); } bool battle_get_value(const char *w1, int *value) @@ -7485,36 +7494,36 @@ void battle_adjust_conf(void) { #if PACKETVER < 20100427 if( battle_config.feature_buying_store ) { - ShowWarning("conf/battle/feature.conf buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n"); + ShowWarning("conf/map/battle/feature.conf buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n"); battle_config.feature_buying_store = 0; } #endif #if PACKETVER < 20100803 if( battle_config.feature_search_stores ) { - ShowWarning("conf/battle/feature.conf search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n"); + ShowWarning("conf/map/battle/feature.conf search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n"); battle_config.feature_search_stores = 0; } #endif #if PACKETVER < 20130724 if( battle_config.feature_banking ) { - ShowWarning("conf/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n"); + ShowWarning("conf/map/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n"); battle_config.feature_banking = 0; } #endif #if PACKETVER < 20141022 if( battle_config.feature_roulette ) { - ShowWarning("conf/battle/feature.conf roulette is enabled but it requires PACKETVER 2014-10-22 or newer, disabling...\n"); + ShowWarning("conf/map/battle/feature.conf roulette is enabled but it requires PACKETVER 2014-10-22 or newer, disabling...\n"); battle_config.feature_roulette = 0; } #endif #if PACKETVER > 20120000 && PACKETVER < 20130515 /* exact date (when it started) not known */ if( battle_config.feature_auction == 1 ) { - ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n"); - ShowWarning("conf/battle/feature.conf:feature.auction change value to '2' to silence this warning and maintain it enabled\n"); + ShowWarning("conf/map/battle/feature.conf:features/auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n"); + ShowWarning("conf/map/battle/feature.conf:features/auction change value to '2' to silence this warning and maintain it enabled\n"); battle_config.feature_auction = 0; } #endif @@ -7525,48 +7534,78 @@ void battle_adjust_conf(void) { #endif } -int battle_config_read(const char* cfgName) +/** + * Dynamically reads battle configuration and initializes required variables. + * + * @param filename Path to configuration file. + * @param imported Whether the current config is imported from another file. + * @retval false in case of error. + */ +bool battle_config_read(const char *filename, bool imported) { - FILE* fp; - static int count = 0; + struct config_t config; + const struct config_setting_t *setting = NULL; + int i; + const char *import = NULL; + bool retval = true; + + nullpo_retr(false, filename); - nullpo_ret(cfgName); + if (!libconfig->load_file(&config, filename)) + return false; // Error message is already shown by libconfig->load_file() - if (count == 0) + if (!imported) battle->config_set_defaults(); - count++; + for (i = 0; i < ARRAYLENGTH(battle_data); i++) { + int type, val; + char config_name[256]; + safesnprintf(config_name, sizeof config_name, "battle_configuration/%s", battle_data[i].str); - fp = fopen(cfgName,"r"); - if (fp == NULL) - ShowError("File not found: %s\n", cfgName); - else - { - char line[1024], w1[1024], w2[1024]; - while(fgets(line, sizeof(line), fp)) - { - if (line[0] == '/' && line[1] == '/') - continue; - if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2) - continue; - if (strcmpi(w1, "import") == 0) - battle->config_read(w2); - else - if (battle->config_set_value(w1, w2) == 0) - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + if ((setting = libconfig->lookup(&config, config_name)) == NULL) { + if (!imported) { + ShowWarning("Missing configuration '%s' in file %s!\n", config_name, filename); + retval = false; + } + continue; } - fclose(fp); + switch ((type = config_setting_type(setting))) { + case CONFIG_TYPE_INT: + val = libconfig->setting_get_int(setting); + break; + case CONFIG_TYPE_BOOL: + val = libconfig->setting_get_bool(setting); + break; + default: // Unsupported type + ShowWarning("Setting %s has unsupported type %d, ignoring...\n", config_name, type); + retval = false; + continue; + } + + if (!battle->config_set_value_sub(i, val)) + retval = false; } - count--; + if (!HPM->parse_battle_conf(&config, filename, imported)) + retval = false; + + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, map->BATTLE_CONF_FILENAME) == 0) { + ShowWarning("battle_config_read: Loop detected! Skipping 'import'...\n"); + } else { + if (!battle->config_read(import, true)) + retval = false; + } + } - if (count == 0) { + libconfig->destroy(&config); + if (!imported) { battle->config_adjust(); clif->bc_ready(); } - - return 0; + return retval; } void do_init_battle(bool minimal) { @@ -7645,6 +7684,7 @@ void battle_defaults(void) { battle->calc_drain = battle_calc_drain; battle->config_read = battle_config_read; battle->config_set_defaults = battle_set_defaults; + battle->config_set_value_sub = battle_set_value_sub; battle->config_set_value = battle_set_value; battle->config_get_value = battle_get_value; battle->config_adjust = battle_adjust_conf; diff --git a/src/map/battle.h b/src/map/battle.h index e04a713ae..ebfa0e305 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -663,10 +663,11 @@ struct battle_interface { int (*adjust_skill_damage) (int m, unsigned short skill_id); int64 (*add_mastery) (struct map_session_data *sd,struct block_list *target,int64 dmg,int type); int (*calc_drain) (int64 damage, int rate, int per); - /* - battle_config */ - int (*config_read) (const char *cfgName); + /* battle_config */ + bool (*config_read) (const char *filename, bool imported); void (*config_set_defaults) (void); - int (*config_set_value) (const char *w1, const char *w2); + bool (*config_set_value_sub) (int index, int value); + bool (*config_set_value) (const char *param, const char *value); bool (*config_get_value) (const char *w1, int *value); void (*config_adjust) (void); /* ----------------------------------------- */ diff --git a/src/map/log.c b/src/map/log.c index c19190d90..6131f9cf4 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ #include "map/mob.h" #include "map/pc.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/nullpo.h" #include "common/showmsg.h" #include "common/sql.h" // SQL_INNODB @@ -479,119 +480,250 @@ void log_sql_final(void) { logs->mysql_handle = NULL; } -void log_set_defaults(void) { +/** + * Initializes logs->config variables + */ +void log_set_defaults(void) +{ memset(&logs->config, 0, sizeof(logs->config)); - //LOG FILTER Default values + //map_log default values + logs->config.enable_logs = 0xFFFFF; + logs->config.commands = true; + + //map_log/database default values + logs->config.sql_logs = true; + // file/table names defaults are defined inside log_config_read_database + + //map_log/filter/item default values + logs->config.filter = 1; // logs any item logs->config.refine_items_log = 5; // log refined items, with refine >= +5 logs->config.rare_items_log = 100; // log rare items. drop chance <= 1% logs->config.price_items_log = 1000; // 1000z logs->config.amount_items_log = 100; } -int log_config_read(const char* cfgName) { - static int count = 0; - char line[1024], w1[1024], w2[1024]; - FILE *fp; +/** + * Reads 'map_log/database' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool log_config_read_database(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "map_log/database")) == NULL) { + if (imported) + return true; + ShowError("log_config_read: map_log/database was not found in %s!\n", filename); + return false; + } + libconfig->setting_lookup_bool_real(setting, "use_sql", &logs->config.sql_logs); + + // map_log.database defaults are defined in order to not make unecessary calls to safestrncpy [Panikon] + if (libconfig->setting_lookup_mutable_string(setting, "log_branch_db", + logs->config.log_branch, sizeof(logs->config.log_branch)) == CONFIG_FALSE) + safestrncpy(logs->config.log_branch, "branchlog", sizeof(logs->config.log_branch)); + + if (libconfig->setting_lookup_mutable_string(setting, "log_pick_db", + logs->config.log_pick, sizeof(logs->config.log_pick)) == CONFIG_FALSE) + safestrncpy(logs->config.log_pick, "picklog", sizeof(logs->config.log_pick)); + + if (libconfig->setting_lookup_mutable_string(setting, "log_zeny_db", + logs->config.log_zeny, sizeof(logs->config.log_zeny)) == CONFIG_FALSE) + safestrncpy(logs->config.log_zeny, "zenylog", sizeof(logs->config.log_zeny)); + + if (libconfig->setting_lookup_mutable_string(setting, "log_mvpdrop_db", + logs->config.log_mvpdrop, sizeof(logs->config.log_mvpdrop)) == CONFIG_FALSE) + safestrncpy(logs->config.log_mvpdrop, "mvplog", sizeof(logs->config.log_mvpdrop)); + + if (libconfig->setting_lookup_mutable_string(setting, "log_gm_db", + logs->config.log_gm, sizeof(logs->config.log_gm)) == CONFIG_FALSE) + safestrncpy(logs->config.log_gm, "atcommandlog", sizeof(logs->config.log_gm)); + + if (libconfig->setting_lookup_mutable_string(setting, "log_npc_db", + logs->config.log_npc, sizeof(logs->config.log_npc)) == CONFIG_FALSE) + safestrncpy(logs->config.log_npc, "npclog", sizeof(logs->config.log_npc)); + + if (libconfig->setting_lookup_mutable_string(setting, "log_chat_db", + logs->config.log_chat, sizeof(logs->config.log_chat)) == CONFIG_FALSE) + safestrncpy(logs->config.log_chat, "chatlog", sizeof(logs->config.log_chat)); + + return true; +} + +/** + * Reads 'map_log/filter/item' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool log_config_read_filter_item(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); - nullpo_retr(1, cfgName); - if( count++ == 0 ) + if ((setting = libconfig->lookup(config, "map_log/filter/item")) == NULL) { + if (!imported) + ShowError("log_config_read: map_log/filter/item was not found in %s!\n", filename); + return false; + } + libconfig->setting_lookup_int(setting, "log_filter", &logs->config.filter); + libconfig->setting_lookup_int(setting, "refine_items_log", &logs->config.refine_items_log); + libconfig->setting_lookup_int(setting, "rare_items_log", &logs->config.rare_items_log); + libconfig->setting_lookup_int(setting, "price_items_log", &logs->config.price_items_log); + libconfig->setting_lookup_int(setting, "amount_items_log", &logs->config.amount_items_log); + return true; +} + +/** + * Reads 'map_log.filter.chat' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool log_config_read_filter_chat(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "map_log/filter/chat")) == NULL) { + if (!imported) + ShowError("log_config_read: map_log/filter/chat was not found in %s!\n", filename); + return false; + } + libconfig->setting_lookup_int(setting, "log_chat", &logs->config.chat); + libconfig->setting_lookup_bool_real(setting, "log_chat_woe_disable", &logs->config.log_chat_woe_disable); + return true; +} + +/** + * Reads 'map_log.filter' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool log_config_read_filter(const char *filename, struct config_t *config, bool imported) +{ + bool retval = true; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if (!log_config_read_filter_item(filename, config, imported)) + retval = false; + if (!log_config_read_filter_chat(filename, config, imported)) + retval = false; + + return retval; +} + +/** + * Reads 'map_log' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool log_config_read(const char *filename, bool imported) +{ + struct config_t config; + struct config_setting_t *setting = NULL; + const char *import; + const char *target; // Type of storage 'file'/'table' + int temp; + bool retval = true; + + nullpo_retr(false, filename); + + if (!imported) log_set_defaults(); - if( ( fp = fopen(cfgName, "r") ) == NULL ) { - ShowError("Log configuration file not found at: %s\n", cfgName); - return 1; + if (!libconfig->load_file(&config, filename)) + return false; + + if ((setting = libconfig->lookup(&config, "map_log")) == NULL) { + libconfig->destroy(&config); + if (imported) + return true; + ShowError("log_config_read: map_log was not found in %s!\n", filename); + return false; } - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - - if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) == 2) { - if( strcmpi(w1, "enable_logs") == 0 ) - logs->config.enable_logs = (e_log_pick_type)config_switch(w2); - else if( strcmpi(w1, "sql_logs") == 0 ) - logs->config.sql_logs = (bool)config_switch(w2); -//start of common filter settings - else if( strcmpi(w1, "rare_items_log") == 0 ) - logs->config.rare_items_log = atoi(w2); - else if( strcmpi(w1, "refine_items_log") == 0 ) - logs->config.refine_items_log = atoi(w2); - else if( strcmpi(w1, "price_items_log") == 0 ) - logs->config.price_items_log = atoi(w2); - else if( strcmpi(w1, "amount_items_log") == 0 ) - logs->config.amount_items_log = atoi(w2); -//end of common filter settings - else if( strcmpi(w1, "log_branch") == 0 ) - logs->config.branch = config_switch(w2); - else if( strcmpi(w1, "log_filter") == 0 ) - logs->config.filter = config_switch(w2); - else if( strcmpi(w1, "log_zeny") == 0 ) - logs->config.zeny = config_switch(w2); - else if( strcmpi(w1, "log_commands") == 0 ) - logs->config.commands = config_switch(w2); - else if( strcmpi(w1, "log_npc") == 0 ) - logs->config.npc = config_switch(w2); - else if( strcmpi(w1, "log_chat") == 0 ) - logs->config.chat = config_switch(w2); - else if( strcmpi(w1, "log_mvpdrop") == 0 ) - logs->config.mvpdrop = config_switch(w2); - else if( strcmpi(w1, "log_chat_woe_disable") == 0 ) - logs->config.log_chat_woe_disable = (bool)config_switch(w2); - else if( strcmpi(w1, "log_branch_db") == 0 ) - safestrncpy(logs->config.log_branch, w2, sizeof(logs->config.log_branch)); - else if( strcmpi(w1, "log_pick_db") == 0 ) - safestrncpy(logs->config.log_pick, w2, sizeof(logs->config.log_pick)); - else if( strcmpi(w1, "log_zeny_db") == 0 ) - safestrncpy(logs->config.log_zeny, w2, sizeof(logs->config.log_zeny)); - else if( strcmpi(w1, "log_mvpdrop_db") == 0 ) - safestrncpy(logs->config.log_mvpdrop, w2, sizeof(logs->config.log_mvpdrop)); - else if( strcmpi(w1, "log_gm_db") == 0 ) - safestrncpy(logs->config.log_gm, w2, sizeof(logs->config.log_gm)); - else if( strcmpi(w1, "log_npc_db") == 0 ) - safestrncpy(logs->config.log_npc, w2, sizeof(logs->config.log_npc)); - else if( strcmpi(w1, "log_chat_db") == 0 ) - safestrncpy(logs->config.log_chat, w2, sizeof(logs->config.log_chat)); - //support the import command, just like any other config - else if( strcmpi(w1,"import") == 0 ) - logs->config_read(w2); - else if (HPM->parseConf(w1, w2, HPCT_LOG)) - ; // handled by plugins - else - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - } + if (libconfig->setting_lookup_int(setting, "enable", &temp) == CONFIG_TRUE) { + logs->config.enable_logs = temp&LOG_TYPE_ALL; // e_log_pick_type } + libconfig->setting_lookup_int(setting, "log_zeny", &logs->config.zeny); + libconfig->setting_lookup_bool_real(setting, "log_branch", &logs->config.branch); + libconfig->setting_lookup_bool_real(setting, "log_mvpdrop", &logs->config.mvpdrop); + libconfig->setting_lookup_bool_real(setting, "log_commands", &logs->config.commands); + libconfig->setting_lookup_bool_real(setting, "log_npc", &logs->config.npc); - fclose(fp); + if (!log_config_read_database(filename, &config, imported)) + retval = false; + if (!log_config_read_filter(filename, &config, imported)) + retval = false; - if( --count == 0 ) {// report final logging state - const char* target = logs->config.sql_logs ? "table" : "file"; + // TODO HPM->parseConf(w1, w2, HPCT_LOG); - if( logs->config.enable_logs && logs->config.filter ) { - ShowInfo("Logging item transactions to %s '%s'.\n", target, logs->config.log_pick); - } - if( logs->config.branch ) { - ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, logs->config.log_pick); - } - if( logs->config.chat ) { - ShowInfo("Logging chat to %s '%s'.\n", target, logs->config.log_chat); - } - if( logs->config.commands ) { - ShowInfo("Logging commands to %s '%s'.\n", target, logs->config.log_gm); - } - if( logs->config.mvpdrop ) { - ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, logs->config.log_mvpdrop); - } - if( logs->config.npc ) { - ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, logs->config.log_npc); - } - if( logs->config.zeny ) { - ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, logs->config.log_zeny); + target = logs->config.sql_logs ? "table" : "file"; + + if (logs->config.enable_logs && logs->config.filter) + ShowInfo("Logging item transactions to %s '%s'.\n", target, logs->config.log_pick); + + if (logs->config.branch) + ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, logs->config.log_branch); + + if (logs->config.chat) + ShowInfo("Logging chat to %s '%s'.\n", target, logs->config.log_chat); + + if (logs->config.commands) + ShowInfo("Logging commands to %s '%s'.\n", target, logs->config.log_gm); + + if (logs->config.mvpdrop) + ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, logs->config.log_mvpdrop); + + if (logs->config.npc) + ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, logs->config.log_npc); + + if (logs->config.zeny) + ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, logs->config.log_zeny); + + logs->config_done(); + + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, map->LOG_CONF_NAME) == 0) { + ShowWarning("log_config_read: Loop detected! Skipping 'import'...\n"); + } else { + if (!logs->config_read(import, true)) + retval = false; } - logs->config_done(); } - return 0; + libconfig->destroy(&config); + return retval; } void log_config_complete(void) { @@ -606,6 +738,9 @@ void log_config_complete(void) { } } +/** + * Initializes the log interface to the default values. + */ void log_defaults(void) { logs = &log_s; diff --git a/src/map/log.h b/src/map/log.h index 0a5e13208..7ff36d126 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -118,7 +118,8 @@ struct log_interface { bool sql_logs; bool log_chat_woe_disable; int rare_items_log,refine_items_log,price_items_log,amount_items_log; - int branch, mvpdrop, zeny, commands, npc, chat; + int zeny, chat; + bool branch, mvpdrop, commands, npc; char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64]; } config; /* */ @@ -146,7 +147,7 @@ struct log_interface { void (*branch_sub) (struct map_session_data* sd); void (*mvpdrop_sub) (struct map_session_data* sd, int monster_id, int* log_mvp); - int (*config_read) (const char* cfgName); + bool (*config_read) (const char *filename, bool imported); void (*config_done) (void); void (*sql_init) (void); void (*sql_final) (void); diff --git a/src/map/map.c b/src/map/map.c index d6425b94e..40bcd9263 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -79,6 +79,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #ifndef _WIN32 #include <unistd.h> #endif @@ -3330,20 +3331,42 @@ int map_readfromcache(struct map_data *m, char *buffer) { return 0; // Not found } -int map_addmap(const char* mapname) { +/** + * Adds a new empty map to the map list. + * + * Assumes that there's enough space in the map list. + * + * @param mapname The new map's name. + * @return success state. + */ +int map_addmap(const char *mapname) +{ map->list[map->count].instance_id = -1; mapindex->getmapname(mapname, map->list[map->count++].name); return 0; } -void map_delmapid(int id) { +/** + * Removes a map from the map list. + * + * @param id The map ID. + */ +void map_delmapid(int id) +{ Assert_retv(id >= 0 && id < map->count); ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map->list[id].name); memmove(map->list+id, map->list+id+1, sizeof(map->list[0])*(map->count-id-1)); map->count--; } -int map_delmap(char* mapname) { +/** + * Removes a map fromt he map list. + * + * @param mapname The name of the map to remove. + * @return the number of removed maps. + */ +int map_delmap(const char *mapname) +{ int i; char map_name[MAP_NAME_LENGTH]; @@ -3798,181 +3821,383 @@ int map_readallmaps (void) { return 0; } -/*========================================== - * Read map server configuration files (conf/map_server.conf...) - *------------------------------------------*/ -int map_config_read(char *cfgName) { - char line[1024], w1[1024], w2[1024]; - FILE *fp; +/** + * Reads 'map_configuration/console' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool map_config_read_console(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; - nullpo_retr(1, cfgName); + nullpo_retr(false, filename); + nullpo_retr(false, config); - fp = fopen(cfgName,"r"); - if( fp == NULL ) { - ShowError("Map configuration file not found at: %s\n", cfgName); - return 1; + if ((setting = libconfig->lookup(config, "map_configuration/console")) == NULL) { + if (imported) + return true; + ShowError("map_config_read: map_configuration/console was not found in %s!\n", filename); + return false; } - while (fgets(line, sizeof(line), fp)) { - char* ptr; + libconfig->setting_lookup_bool_real(setting, "stdout_with_ansisequence", &showmsg->stdout_with_ansisequence); + if (libconfig->setting_lookup_int(setting, "console_silent", &showmsg->silent) == CONFIG_TRUE) { + if (showmsg->silent) // only bother if its actually enabled + ShowInfo("Console Silent Setting: %d\n", showmsg->silent); + } + libconfig->setting_lookup_mutable_string(setting, "timestamp_format", showmsg->timestamp_format, sizeof(showmsg->timestamp_format)); + libconfig->setting_lookup_int(setting, "console_msg_log", &showmsg->console_log); - if (line[0] == '/' && line[1] == '/') - continue; - if ((ptr = strstr(line, "//")) != NULL) - *ptr = '\n'; //Strip comments - if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2) - continue; + return true; +} - //Strip trailing spaces - ptr = w2 + strlen(w2); - while (--ptr >= w2 && *ptr == ' '); - ptr++; - *ptr = '\0'; - - if(strcmpi(w1,"timestamp_format")==0) - safestrncpy(showmsg->timestamp_format, w2, 20); - else if(strcmpi(w1,"stdout_with_ansisequence")==0) - showmsg->stdout_with_ansisequence = config_switch(w2) ? true : false; - else if(strcmpi(w1,"console_silent")==0) { - showmsg->silent = atoi(w2); - if (showmsg->silent) // only bother if its actually enabled - ShowInfo("Console Silent Setting: %d\n", atoi(w2)); - } else if (strcmpi(w1, "userid")==0) - chrif->setuserid(w2); - else if (strcmpi(w1, "passwd") == 0) - chrif->setpasswd(w2); - else if (strcmpi(w1, "char_ip") == 0) - map->char_ip_set = chrif->setip(w2); - else if (strcmpi(w1, "char_port") == 0) - chrif->setport(atoi(w2)); - else if (strcmpi(w1, "map_ip") == 0) - map->ip_set = clif->setip(w2); - else if (strcmpi(w1, "bind_ip") == 0) - clif->setbindip(w2); - else if (strcmpi(w1, "map_port") == 0) { - clif->setport(atoi(w2)); - map->port = (atoi(w2)); - } else if (strcmpi(w1, "map") == 0) - map->count++; - else if (strcmpi(w1, "delmap") == 0) - map->count--; - else if (strcmpi(w1, "npc") == 0) - npc->addsrcfile(w2); - else if (strcmpi(w1, "delnpc") == 0) - npc->delsrcfile(w2); - else if (strcmpi(w1, "autosave_time") == 0) { - map->autosave_interval = atoi(w2); - if (map->autosave_interval < 1) //Revert to default saving. - map->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; - else - map->autosave_interval *= 1000; //Pass from sec to ms - } else if (strcmpi(w1, "minsave_time") == 0) { - map->minsave_interval= atoi(w2); - if (map->minsave_interval < 1) - map->minsave_interval = 1; - } else if (strcmpi(w1, "save_settings") == 0) - map->save_settings = atoi(w2); - else if (strcmpi(w1, "help_txt") == 0) - strcpy(map->help_txt, w2); - else if (strcmpi(w1, "help2_txt") == 0) - strcpy(map->help2_txt, w2); - else if (strcmpi(w1, "charhelp_txt") == 0) - strcpy(map->charhelp_txt, w2); - else if(strcmpi(w1,"db_path") == 0) - safestrncpy(map->db_path,w2,255); - else if (strcmpi(w1, "enable_spy") == 0) - map->enable_spy = config_switch(w2); - else if (strcmpi(w1, "use_grf") == 0) - map->enable_grf = config_switch(w2); - else if (strcmpi(w1, "console_msg_log") == 0) - showmsg->console_log = atoi(w2);//[Ind] - else if (strcmpi(w1, "default_language") == 0) - safestrncpy(map->default_lang_str, w2, sizeof(map->default_lang_str)); - else if (strcmpi(w1, "import") == 0) - map->config_read(w2); +/** + * Reads 'map_configuration/sql_connection' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool map_config_read_connection(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "map_configuration/sql_connection")) == NULL) { + if (imported) + return true; + ShowError("map_config_read: map_configuration/sql_connection was not found in %s!\n", filename); + ShowWarning("map_config_read_connection: Defaulting sql_connection...\n"); + return false; + } + + libconfig->setting_lookup_int(setting, "db_port", &map->server_port); + libconfig->setting_lookup_mutable_string(setting, "db_hostname", map->server_ip, sizeof(map->server_ip)); + libconfig->setting_lookup_mutable_string(setting, "db_username", map->server_id, sizeof(map->server_id)); + libconfig->setting_lookup_mutable_string(setting, "db_password", map->server_pw, sizeof(map->server_pw)); + libconfig->setting_lookup_mutable_string(setting, "db_database", map->server_db, sizeof(map->server_db)); + libconfig->setting_lookup_mutable_string(setting, "default_codepage", map->default_codepage, sizeof(map->default_codepage)); + return true; +} + +/** + * Reads 'map_configuration/inter' and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool map_config_read_inter(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + const char *str = NULL; + char temp[24]; + uint16 port; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "map_configuration/inter")) == NULL) { + if (imported) + return true; + ShowError("map_config_read: map_configuration/inter was not found in %s!\n", filename); + return false; + } + + // Login information + if (libconfig->setting_lookup_mutable_string(setting, "userid", temp, sizeof(temp)) == CONFIG_TRUE) + chrif->setuserid(temp); + if (libconfig->setting_lookup_mutable_string(setting, "passwd", temp, sizeof(temp)) == CONFIG_TRUE) + chrif->setpasswd(temp); + + // Char and map-server information + if (libconfig->setting_lookup_string(setting, "char_ip", &str) == CONFIG_TRUE) + map->char_ip_set = chrif->setip(str); + if (libconfig->setting_lookup_uint16(setting, "char_port", &port) == CONFIG_TRUE) + chrif->setport(port); + + if (libconfig->setting_lookup_string(setting, "map_ip", &str) == CONFIG_TRUE) + map->ip_set = clif->setip(str); + if (libconfig->setting_lookup_uint16(setting, "map_port", &port) == CONFIG_TRUE) { + clif->setport(port); + map->port = port; + } + if (libconfig->setting_lookup_string(setting, "bind_ip", &str) == CONFIG_TRUE) + clif->setbindip(str); + + return true; +} + +/** + * Reads 'map_configuration/database' and initializes required variables + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool map_config_read_database(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "map_configuration/database")) == NULL) { + if (imported) + return true; + ShowError("map_config_read: map_configuration/database was not found in %s!\n", filename); + return false; + } + libconfig->setting_lookup_mutable_string(setting, "db_path", map->db_path, sizeof(map->db_path)); + libconfig->setting_lookup_int(setting, "save_settings", &map->save_settings); + + if (libconfig->setting_lookup_int(setting, "autosave_time", &map->autosave_interval) == CONFIG_TRUE) { + if (map->autosave_interval < 1) // Revert to default saving + map->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; else - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + map->autosave_interval *= 1000; // Pass from s to ms + } + if (libconfig->setting_lookup_int(setting, "minsave_time", &map->minsave_interval) == CONFIG_TRUE) { + if (map->minsave_interval < 1) + map->minsave_interval = 1; } - fclose(fp); - return 0; + return true; } -int map_config_read_sub(char *cfgName) { - char line[1024], w1[1024], w2[1024]; - FILE *fp; - nullpo_retr(1, cfgName); - fp = fopen(cfgName,"r"); - if (fp == NULL) { - ShowError("Map configuration file not found at: %s\n", cfgName); - return 1; +/** + * Reads 'map_configuration/map_list'/'map_configuration/map_removed' and adds + * or removes maps from map-server. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool map_config_read_map_list(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + int i, count = 0; + struct DBMap *deleted_maps; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + deleted_maps = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY, MAP_NAME_LENGTH); + + // Remove maps + if ((setting = libconfig->lookup(config, "map_configuration/map_removed")) != NULL) { + count = libconfig->setting_length(setting); + for (i = 0; i < count; i++) { + const char *mapname; + + if ((mapname = libconfig->setting_get_string_elem(setting, i)) == NULL || mapname[0] == '\0') + continue; + + strdb_put(deleted_maps, mapname, NULL); + + if (imported) // Map list is empty on the first run, only do this for imported files. + map->delmap(mapname); + } + } + + if ((setting = libconfig->lookup(config, "map_configuration/map_list")) == NULL) { + db_destroy(deleted_maps); + if (imported) + return true; + ShowError("map_config_read_map_list: map_configuration/map_list was not found in %s!\n", filename); + return false; } - while (fgets(line, sizeof(line), fp)) { - char* ptr; + // Add maps to map->list + count = libconfig->setting_length(setting); - if (line[0] == '/' && line[1] == '/') + if (count <= 0) { + db_destroy(deleted_maps); + if (imported) + return true; + ShowWarning("map_config_read_map_list: no maps found in %s!\n", filename); + return false; + } + + RECREATE(map->list, struct map_data, map->count + count); // TODO: VECTOR candidate + + for (i = 0; i < count; i++) { + const char *mapname; + + if ((mapname = libconfig->setting_get_string_elem(setting, i)) == NULL || mapname[0] == '\0') continue; - if ((ptr = strstr(line, "//")) != NULL) - *ptr = '\n'; //Strip comments - if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2) + + if (strdb_exists(deleted_maps, mapname)) continue; - //Strip trailing spaces - ptr = w2 + strlen(w2); - while (--ptr >= w2 && *ptr == ' '); - ptr++; - *ptr = '\0'; + map->addmap(mapname); + } + + RECREATE(map->list, struct map_data, map->count); + + db_destroy(deleted_maps); + return true; +} + +/** + * Reads map-server configuration files (map-server.conf) and initialises + * required variables. + * + * @param filename Path to configuration file. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool map_config_read(const char *filename, bool imported) +{ + struct config_t config; + struct config_setting_t *setting = NULL; + const char *import = NULL; + bool retval = true; + + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; - if (strcmpi(w1, "map") == 0) - map->addmap(w2); - else if (strcmpi(w1, "delmap") == 0) - map->delmap(w2); - else if (strcmpi(w1, "import") == 0) - map->config_read_sub(w2); + if ((setting = libconfig->lookup(&config, "map_configuration")) == NULL) { + libconfig->destroy(&config); + if (imported) + return true; + ShowError("map_config_read: map_configuration was not found in %s!\n", filename); + return false; } - fclose(fp); - return 0; + libconfig->setting_lookup_mutable_string(setting, "help_txt", map->help_txt, sizeof(map->help_txt)); + libconfig->setting_lookup_mutable_string(setting, "charhelp_txt", map->charhelp_txt, sizeof(map->charhelp_txt)); + libconfig->setting_lookup_bool(setting, "enable_spy", &map->enable_spy); + libconfig->setting_lookup_bool(setting, "use_grf", &map->enable_grf); + libconfig->setting_lookup_mutable_string(setting, "default_language", map->default_lang_str, sizeof(map->default_lang_str)); + + if (!map_config_read_console(filename, &config, imported)) + retval = false; + if (!map_config_read_connection(filename, &config, imported)) + retval = false; + if (!map_config_read_inter(filename, &config, imported)) + retval = false; + if (!map_config_read_database(filename, &config, imported)) + retval = false; + if (!map_config_read_map_list(filename, &config, imported)) + retval = false; + + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, map->MAP_CONF_NAME) == 0) { + ShowWarning("map_config_read: Loop detected! Skipping 'import'...\n"); + } else { + if (!map->config_read(import, true)) + retval = false; + } + } + + libconfig->destroy(&config); + return retval; } -void map_reloadnpc_sub(char *cfgName) { - char line[1024], w1[1024], w2[1024]; - FILE *fp; - nullpo_retv(cfgName); - fp = fopen(cfgName,"r"); - if (fp == NULL) { - ShowError("Map configuration file not found at: %s\n", cfgName); - return; +/** + * Reads 'npc_global_list'/'npc_removed_list' and adds or removes NPC sources + * from map-server. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool map_read_npclist(const char *filename, bool imported) +{ + struct config_t config; + struct config_setting_t *setting = NULL; + const char *import = NULL; + bool retval = true; + + struct DBMap *deleted_npcs; + + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; + + deleted_npcs = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY, MAP_NAME_LENGTH); + + // Remove maps + if ((setting = libconfig->lookup(&config, "npc_removed_list")) != NULL) { + int i, del_count = libconfig->setting_length(setting); + for (i = 0; i < del_count; i++) { + const char *scriptname; + + if ((scriptname = libconfig->setting_get_string_elem(setting, i)) == NULL || scriptname[0] == '\0') + continue; + + strdb_put(deleted_npcs, scriptname, NULL); + + if (imported) // Map list is empty on the first run, only do this for imported files. + npc->delsrcfile(scriptname); + } } - while (fgets(line, sizeof(line), fp)) { - char* ptr; + if ((setting = libconfig->lookup(&config, "npc_global_list")) != NULL) { + int i, count = libconfig->setting_length(setting); + if (count <= 0) { + if (!imported) { + ShowWarning("map_read_npclist: no NPCs found in %s!\n", filename); + retval = false; + } + } + for (i = 0; i < count; i++) { + const char *scriptname; - if (line[0] == '/' && line[1] == '/') - continue; - if ((ptr = strstr(line, "//")) != NULL) - *ptr = '\n'; //Strip comments - if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2) - continue; + if ((scriptname = libconfig->setting_get_string_elem(setting, i)) == NULL || scriptname[0] == '\0') + continue; - //Strip trailing spaces - ptr = w2 + strlen(w2); - while (--ptr >= w2 && *ptr == ' '); - ptr++; - *ptr = '\0'; - - if (strcmpi(w1, "npc") == 0) - npc->addsrcfile(w2); - else if (strcmpi(w1, "import") == 0) - map->reloadnpc_sub(w2); - else if (strcmpi(w1, "delnpc") == 0) - npc->delsrcfile(w2); - else - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + if (strdb_exists(deleted_npcs, scriptname)) + continue; + + npc->addsrcfile(scriptname); + } + } else { + ShowError("map_read_npclist: npc_global_list was not found in %s!\n", filename); + retval = false; } - fclose(fp); + db_destroy(deleted_npcs); + + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + const char *base_npclist = NULL; +#ifdef RENEWAL + base_npclist = "npc/re/scripts_main.conf"; +#else + base_npclist = "npc/pre-re/scripts_main.conf"; +#endif + if (strcmp(import, filename) == 0 || strcmp(import, base_npclist) == 0) { + ShowWarning("map_read_npclist: Loop detected! Skipping 'import'...\n"); + } else { + if (!map->read_npclist(import, true)) + retval = false; + } + } + + libconfig->destroy(&config); + return retval; } /** @@ -3986,9 +4211,9 @@ void map_reloadnpc(bool clear) { npc->addsrcfile("clear"); // this will clear the current script list #ifdef RENEWAL - map->reloadnpc_sub("npc/re/scripts_main.conf"); + map->read_npclist("npc/re/scripts_main.conf", false); #else - map->reloadnpc_sub("npc/pre-re/scripts_main.conf"); + map->read_npclist("npc/pre-re/scripts_main.conf", false); #endif // Append extra scripts @@ -3997,63 +4222,125 @@ void map_reloadnpc(bool clear) { } } -int inter_config_read(char *cfgName) { - char line[1024],w1[1024],w2[1024]; - FILE *fp; +/** + * Reads inter-server.conf and initializes required variables. + * + * @param filename Path to configuration file + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool inter_config_read(const char *filename, bool imported) +{ + struct config_t config; + const struct config_setting_t *setting = NULL; + const char *import = NULL; + bool retval = true; + + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; + + if ((setting = libconfig->lookup(&config, "inter_configuration")) == NULL) { + libconfig->destroy(&config); + if (imported) + return true; + ShowError("inter_config_read: inter_configuration was not found in %s!\n", filename); + return false; + } + + if (!map->inter_config_read_database_names(filename, &config, imported)) + retval = false; + if (!map->inter_config_read_connection(filename, &config, imported)) + retval = false; + + // TODO HPM->parseConf(w1, w2, HPCT_MAP_INTER); + + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, map->INTER_CONF_NAME) == 0) { + ShowWarning("inter_config_read: Loop detected in %s! Skipping 'import'...\n", filename); + } else { + if (!map->inter_config_read(import, true)) + retval = false; + } + } + + libconfig->destroy(&config); + return retval; +} + +/** + * Reads the 'inter_configuration/log/sql_connection' config entry and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool inter_config_read_connection(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting = NULL; - nullpo_retr(1, cfgName); - if (!(fp = fopen(cfgName,"r"))) { - ShowError("File not found: %s\n",cfgName); - return 1; + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "inter_configuration/log/sql_connection")) == NULL) { + if (imported) + return true; + ShowError("inter_config_read: inter_configuration/log/sql_connection was not found in %s!\n", filename); + return false; } - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - if (sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2) < 2) - continue; - /* map sql stuff */ - if(strcmpi(w1,"map_server_ip")==0) - safestrncpy(map->server_ip, w2, sizeof(map->server_ip)); - else if(strcmpi(w1,"map_server_port")==0) - map->server_port=atoi(w2); - else if(strcmpi(w1,"map_server_id")==0) - safestrncpy(map->server_id, w2, sizeof(map->server_id)); - else if(strcmpi(w1,"map_server_pw")==0) - safestrncpy(map->server_pw, w2, sizeof(map->server_pw)); - else if(strcmpi(w1,"map_server_db")==0) - safestrncpy(map->server_db, w2, sizeof(map->server_db)); - else if(strcmpi(w1,"default_codepage")==0) - safestrncpy(map->default_codepage, w2, sizeof(map->default_codepage)); - else if(strcmpi(w1,"autotrade_merchants_db")==0) - safestrncpy(map->autotrade_merchants_db, w2, sizeof(map->autotrade_merchants_db)); - else if(strcmpi(w1,"autotrade_data_db")==0) - safestrncpy(map->autotrade_data_db, w2, sizeof(map->autotrade_data_db)); - else if(strcmpi(w1,"npc_market_data_db")==0) - safestrncpy(map->npc_market_data_db, w2, sizeof(map->npc_market_data_db)); - /* sql log db */ - else if(strcmpi(w1,"log_db_ip")==0) - safestrncpy(logs->db_ip, w2, sizeof(logs->db_ip)); - else if(strcmpi(w1,"log_db_id")==0) - safestrncpy(logs->db_id, w2, sizeof(logs->db_id)); - else if(strcmpi(w1,"log_db_pw")==0) - safestrncpy(logs->db_pw, w2, sizeof(logs->db_pw)); - else if(strcmpi(w1,"log_db_port")==0) - logs->db_port = atoi(w2); - else if(strcmpi(w1,"log_db_db")==0) - safestrncpy(logs->db_name, w2, sizeof(logs->db_name)); - /* mapreg */ - else if( mapreg->config_read(w1,w2) ) - continue; - /* import */ - else if(strcmpi(w1,"import")==0) - map->inter_config_read(w2); - else - HPM->parseConf(w1, w2, HPCT_MAP_INTER); + libconfig->setting_lookup_int(setting, "port", &logs->db_port); + libconfig->setting_lookup_mutable_string(setting, "db_hostname", logs->db_ip, sizeof(logs->db_ip)); + libconfig->setting_lookup_mutable_string(setting, "db_username", logs->db_id, sizeof(logs->db_id)); + libconfig->setting_lookup_mutable_string(setting, "db_password", logs->db_pw, sizeof(logs->db_pw)); + libconfig->setting_lookup_mutable_string(setting, "db_database", logs->db_name, sizeof(logs->db_name)); + + return true; +} + +/** + * Reads the 'inter_configuration/database_names' config entry and initializes required variables. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool inter_config_read_database_names(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting = NULL; + bool retval = true; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "inter_configuration/database_names")) == NULL) { + if (imported) + return true; + ShowError("inter_config_read: inter_configuration/database_names was not found in %s!\n", filename); + return false; } - fclose(fp); - return 0; + libconfig->setting_lookup_mutable_string(setting, "autotrade_merchants_db", map->autotrade_merchants_db, sizeof(map->autotrade_merchants_db)); + libconfig->setting_lookup_mutable_string(setting, "autotrade_data_db", map->autotrade_data_db, sizeof(map->autotrade_data_db)); + libconfig->setting_lookup_mutable_string(setting, "npc_market_data_db", map->npc_market_data_db, sizeof(map->npc_market_data_db)); + + if (!mapreg->config_read(filename, setting, imported)) + retval = false; + + if ((setting = libconfig->lookup(config, "inter_configuration/database_names/registry")) == NULL) { + if (imported) + return retval; + ShowError("inter_config_read: inter_configuration/database_names/registry was not found in %s!\n", filename); + return false; + } + return retval; } /*======================================= @@ -6077,12 +6364,12 @@ int do_init(int argc, char *argv[]) map_load_defaults(); - map->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); - map->LOG_CONF_NAME = aStrdup("conf/logs.conf"); - map->MAP_CONF_NAME = aStrdup("conf/map-server.conf"); - map->BATTLE_CONF_FILENAME = aStrdup("conf/battle.conf"); + map->INTER_CONF_NAME = aStrdup("conf/common/inter-server.conf"); + map->LOG_CONF_NAME = aStrdup("conf/map/logs.conf"); + map->MAP_CONF_NAME = aStrdup("conf/map/map-server.conf"); + map->BATTLE_CONF_FILENAME = aStrdup("conf/map/battle.conf"); map->ATCOMMAND_CONF_FILENAME = aStrdup("conf/atcommand.conf"); - map->SCRIPT_CONF_NAME = aStrdup("conf/script.conf"); + map->SCRIPT_CONF_NAME = aStrdup("conf/map/script.conf"); map->MSG_CONF_NAME = aStrdup("conf/messages.conf"); map->GRF_PATH_FILENAME = aStrdup("conf/grf-files.txt"); @@ -6095,10 +6382,30 @@ int do_init(int argc, char *argv[]) cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); minimal = map->minimal;/* temp (perhaps make minimal a mask with options of what to load? e.g. plugin 1 does minimal |= mob_db; */ if (!minimal) { - map->config_read(map->MAP_CONF_NAME); - CREATE(map->list,struct map_data,map->count); - map->count = 0; - map->config_read_sub(map->MAP_CONF_NAME); + map->config_read(map->MAP_CONF_NAME, false); + + { + // TODO: Remove this when no longer needed. +#define CHECK_OLD_LOCAL_CONF(oldname, newname) do { \ + if (stat((oldname), &fileinfo) == 0 && fileinfo.st_size > 0) { \ + ShowWarning("An old configuration file \"%s\" was found.\n", (oldname)); \ + ShowWarning("If it contains settings you wish to keep, please merge them into \"%s\".\n", (newname)); \ + ShowWarning("Otherwise, just delete it.\n"); \ + ShowInfo("Resuming in 10 seconds...\n"); \ + HSleep(10); \ + } \ +} while (0) + struct stat fileinfo; + + CHECK_OLD_LOCAL_CONF("conf/import/map_conf.txt", "conf/import/map-server.conf"); + CHECK_OLD_LOCAL_CONF("conf/import/inter_conf.txt", "conf/import/inter-server.conf"); + CHECK_OLD_LOCAL_CONF("conf/import/log_conf.txt", "conf/import/logs.conf"); + CHECK_OLD_LOCAL_CONF("conf/import/script_conf.txt", "conf/import/script.conf"); + CHECK_OLD_LOCAL_CONF("conf/import/packet_conf.txt", "conf/import/socket.conf"); + CHECK_OLD_LOCAL_CONF("conf/import/battle_conf.txt", "conf/import/battle.conf"); + +#undef CHECK_OLD_LOCAL_CONF + } // loads npcs map->reloadnpc(false); @@ -6110,7 +6417,7 @@ int do_init(int argc, char *argv[]) sockt->ip2str(sockt->addr_[0], ip_str); #ifndef BUILDBOT - ShowWarning("Not all IP addresses in /conf/map-server.conf configured, auto-detecting...\n"); + ShowWarning("Not all IP addresses in /conf/map/map-server.conf configured, auto-detecting...\n"); #endif if (sockt->naddr_ == 0) @@ -6126,12 +6433,12 @@ int do_init(int argc, char *argv[]) chrif->setip(ip_str); } - battle->config_read(map->BATTLE_CONF_FILENAME); + battle->config_read(map->BATTLE_CONF_FILENAME, false); atcommand->msg_read(map->MSG_CONF_NAME, false); - map->inter_config_read(map->INTER_CONF_NAME); - logs->config_read(map->LOG_CONF_NAME); + map->inter_config_read(map->INTER_CONF_NAME, false); + logs->config_read(map->LOG_CONF_NAME, false); } - script->config_read(map->SCRIPT_CONF_NAME); + script->config_read(map->SCRIPT_CONF_NAME, false); map->id_db = idb_alloc(DB_OPT_BASE); map->pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map->id2sd() use. [Skotlex] @@ -6275,7 +6582,6 @@ void map_defaults(void) { sprintf(map->db_path ,"db"); sprintf(map->help_txt ,"conf/help.txt"); - sprintf(map->help2_txt ,"conf/help2.txt"); sprintf(map->charhelp_txt ,"conf/charhelp.txt"); sprintf(map->wisp_server_name ,"Server"); // can be modified in char-server configuration file @@ -6288,12 +6594,12 @@ void map_defaults(void) { map->night_flag = 0; // 0=day, 1=night [Yor] map->enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex] - map->INTER_CONF_NAME="conf/inter-server.conf"; - map->LOG_CONF_NAME="conf/logs.conf"; - map->MAP_CONF_NAME = "conf/map-server.conf"; - map->BATTLE_CONF_FILENAME = "conf/battle.conf"; + map->INTER_CONF_NAME="conf/common/inter-server.conf"; + map->LOG_CONF_NAME="conf/map/logs.conf"; + map->MAP_CONF_NAME = "conf/map/map-server.conf"; + map->BATTLE_CONF_FILENAME = "conf/map/battle.conf"; map->ATCOMMAND_CONF_FILENAME = "conf/atcommand.conf"; - map->SCRIPT_CONF_NAME = "conf/script.conf"; + map->SCRIPT_CONF_NAME = "conf/map/script.conf"; map->MSG_CONF_NAME = "conf/messages.conf"; map->GRF_PATH_FILENAME = "conf/grf-files.txt"; @@ -6499,9 +6805,10 @@ void map_defaults(void) { map->readgat = map_readgat; map->readallmaps = map_readallmaps; map->config_read = map_config_read; - map->config_read_sub = map_config_read_sub; - map->reloadnpc_sub = map_reloadnpc_sub; + map->read_npclist = map_read_npclist; map->inter_config_read = inter_config_read; + map->inter_config_read_database_names = inter_config_read_database_names; + map->inter_config_read_connection = inter_config_read_connection; map->sql_init = map_sql_init; map->sql_close = map_sql_close; map->zone_mf_cache = map_zone_mf_cache; diff --git a/src/map/map.h b/src/map/map.h index dbd30febf..723691971 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -33,6 +33,7 @@ /* Forward Declarations */ struct Sql; // common/sql.h +struct config_t; // common/conf.h struct mob_data; struct npc_data; struct channel_data; @@ -967,7 +968,6 @@ struct map_interface { char db_path[256]; char help_txt[256]; - char help2_txt[256]; char charhelp_txt[256]; char wisp_server_name[NAME_LENGTH]; @@ -996,7 +996,7 @@ struct map_interface { char server_db[32]; struct Sql *mysql_handle; - int port; + uint16 port; int users; int enable_grf; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89] bool ip_set; @@ -1147,7 +1147,7 @@ END_ZEROED_BLOCK; int (*cleanup_sub) (struct block_list *bl, va_list ap); - int (*delmap) (char* mapname); + int (*delmap) (const char *mapname); void (*flags_init) (void); bool (*iwall_set) (int16 m, int16 x, int16 y, int size, int8 dir, bool shootable, const char* wall_name); @@ -1187,10 +1187,11 @@ END_ZEROED_BLOCK; int (*waterheight) (char *mapname); int (*readgat) (struct map_data *m); int (*readallmaps) (void); - int (*config_read) (char *cfgName); - int (*config_read_sub) (char *cfgName); - void (*reloadnpc_sub) (char *cfgName); - int (*inter_config_read) (char *cfgName); + bool (*config_read) (const char *filename, bool imported); + bool (*read_npclist) (const char *filename, bool imported); + bool (*inter_config_read) (const char *filename, bool imported); + bool (*inter_config_read_database_names) (const char *filename, const struct config_t *config, bool imported); + bool (*inter_config_read_connection) (const char *filename, const struct config_t *config, bool imported); int (*sql_init) (void); int (*sql_close) (void); bool (*zone_mf_cache) (int m, char *flag, char *params); diff --git a/src/map/mapreg.h b/src/map/mapreg.h index d19b2bb80..642bce48e 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -25,6 +25,8 @@ #include "common/hercules.h" #include "common/db.h" +/* Forward Declarations */ +struct config_setting_t; // common/conf.h struct eri; /** Container for a mapreg value */ @@ -61,7 +63,7 @@ struct mapreg_interface { int (*save_timer) (int tid, int64 tick, int id, intptr_t data); int (*destroyreg) (union DBKey key, struct DBData *data, va_list ap); void (*reload) (void); - bool (*config_read) (const char *w1, const char *w2); + bool (*config_read) (const char *filename, const struct config_setting_t *config, bool imported); }; #ifdef HERCULES_CORE diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 82ce39d64..4cdb91b21 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -25,6 +25,7 @@ #include "map/map.h" // map-"mysql_handle #include "map/script.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/db.h" #include "common/ers.h" #include "common/memmgr.h" @@ -349,13 +350,19 @@ void mapreg_init(void) { /** * Loads the mapreg configuration file. + * + * @param filename Path to configuration file (used in error and warning messages). + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. */ -bool mapreg_config_read(const char* w1, const char* w2) { - nullpo_retr(false, w1); - nullpo_retr(false, w2); - if(!strcmpi(w1, "mapreg_db")) - safestrncpy(mapreg->table, w2, sizeof(mapreg->table)); - else +bool mapreg_config_read(const char *filename, const struct config_setting_t *config, bool imported) +{ + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if (libconfig->setting_lookup_mutable_string(config, "mapreg_db", mapreg->table, sizeof(mapreg->table)) != CONFIG_TRUE) return false; return true; diff --git a/src/map/script.c b/src/map/script.c index 353d57a67..09cefa500 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -4521,52 +4521,55 @@ void run_script_main(struct script_state *st) { } } -int script_config_read(char *cfgName) { - int i; - char line[1024],w1[1024],w2[1024]; - FILE *fp; +/** + * Reads 'script_configuration' and initializes required variables. + * + * @param filename Path to configuration file. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool script_config_read(const char *filename, bool imported) +{ + struct config_t config; + struct config_setting_t * setting = NULL; + const char *import = NULL; + bool retval = true; - if( !( fp = fopen(cfgName,"r") ) ) { - ShowError("File not found: %s\n", cfgName); - return 1; + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; + + if ((setting = libconfig->lookup(&config, "script_configuration")) == NULL) { + libconfig->destroy(&config); + if (imported) + return true; + ShowError("script_config_read: script_configuration was not found in %s!\n", filename); + return false; } - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - i = sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2); - if(i!=2) - continue; - if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) { - script->config.warn_func_mismatch_paramnum = config_switch(w2); - } - else if(strcmpi(w1,"check_cmdcount")==0) { - script->config.check_cmdcount = config_switch(w2); - } - else if(strcmpi(w1,"check_gotocount")==0) { - script->config.check_gotocount = config_switch(w2); - } - else if(strcmpi(w1,"input_min_value")==0) { - script->config.input_min_value = config_switch(w2); - } - else if(strcmpi(w1,"input_max_value")==0) { - script->config.input_max_value = config_switch(w2); - } - else if(strcmpi(w1,"warn_func_mismatch_argtypes")==0) { - script->config.warn_func_mismatch_argtypes = config_switch(w2); - } - else if(strcmpi(w1,"import")==0) { - script->config_read(w2); - } - else if(HPM->parseConf(w1, w2, HPCT_SCRIPT)) { - ; // handled by plugin + libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_paramnum", &script->config.warn_func_mismatch_paramnum); + libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_argtypes", &script->config.warn_func_mismatch_argtypes); + libconfig->setting_lookup_int(setting, "check_cmdcount", &script->config.check_cmdcount); + libconfig->setting_lookup_int(setting, "check_gotocount", &script->config.check_gotocount); + libconfig->setting_lookup_int(setting, "input_min_value", &script->config.input_min_value); + libconfig->setting_lookup_int(setting, "input_max_value", &script->config.input_max_value); + + // TODO HPM->parseConf(w1, w2, HPCT_SCRIPT)); + + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, map->SCRIPT_CONF_NAME) == 0) { + ShowWarning("script_config_read: Loop detected! Skipping 'import'...\n"); } else { - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + if (!script->config_read(import, true)) + retval = false; } } - fclose(fp); - return 0; + libconfig->destroy(&config); + return retval; } /** @@ -21449,8 +21452,8 @@ void script_defaults(void) { script->getfuncname = script_getfuncname; /* script_config base */ - script->config.warn_func_mismatch_argtypes = 1; - script->config.warn_func_mismatch_paramnum = 1; + script->config.warn_func_mismatch_argtypes = true; + script->config.warn_func_mismatch_paramnum = true; script->config.check_cmdcount = 65535; script->config.check_gotocount = 2048; script->config.input_min_value = 0; diff --git a/src/map/script.h b/src/map/script.h index 86cb20226..c4c082263 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -343,8 +343,8 @@ enum { **/ struct Script_Config { - unsigned warn_func_mismatch_argtypes : 1; - unsigned warn_func_mismatch_paramnum : 1; + bool warn_func_mismatch_argtypes; + bool warn_func_mismatch_paramnum; int check_cmdcount; int check_gotocount; int input_min_value; @@ -692,7 +692,7 @@ struct script_interface { void (*run_autobonus) (const char *autobonus,int id, int pos); void (*cleararray_pc) (struct map_session_data* sd, const char* varname, void* value); void (*setarray_pc) (struct map_session_data* sd, const char* varname, uint32 idx, void* value, int* refcache); - int (*config_read) (char *cfgName); + bool (*config_read) (const char *filename, bool imported); int (*add_str) (const char* p); const char* (*get_str) (int id); int (*search_str) (const char* p); |