diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/char/char.c | 279 | ||||
-rw-r--r-- | src/char/char.h | 5 | ||||
-rw-r--r-- | src/char/inter.c | 114 | ||||
-rw-r--r-- | src/char/inter.h | 6 | ||||
-rw-r--r-- | src/common/sql.c | 96 | ||||
-rw-r--r-- | src/common/sql.h | 2 | ||||
-rw-r--r-- | src/map/map.c | 174 | ||||
-rw-r--r-- | src/map/map.h | 7 | ||||
-rw-r--r-- | src/map/mapreg.h | 6 | ||||
-rw-r--r-- | src/map/mapreg_sql.c | 21 |
10 files changed, 460 insertions, 250 deletions
diff --git a/src/char/char.c b/src/char/char.c index 2b5c837c5..62b1d8f4c 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -5350,102 +5350,171 @@ static int char_online_data_cleanup(int tid, int64 tick, int id, intptr_t data) return 0; } -void char_sql_config_read(const char* cfgName) +/** + * Reads the 'inter_configuration' config file 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 char_sql_config_read(const char *filename, bool imported) { - char line[1024], w1[1024], w2[1024]; - FILE* fp; + struct config_t config; + const struct config_setting_t *setting = NULL; + const char *import = NULL; + bool retval = true; - if ((fp = fopen(cfgName, "r")) == NULL) { - ShowError("File not found: %s\n", cfgName); - return; + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; // Error message is already shown by libconfig->load_file + + if ((setting = libconfig->lookup(&config, "inter_configuration/database_names")) == NULL) { + libconfig->destroy(&config); + if (imported) + return true; + ShowError("sql_config_read: inter_configuration/database_names was not found in %s!\n", filename); + return false; } + libconfig->setting_lookup_mutable_string(setting, "char_db", char_db, sizeof(char_db)); + libconfig->setting_lookup_mutable_string(setting, "interlog_db", interlog_db, sizeof(interlog_db)); + libconfig->setting_lookup_mutable_string(setting, "ragsrvinfo_db", ragsrvinfo_db, sizeof(ragsrvinfo_db)); - while(fgets(line, sizeof(line), fp)) - { - if(line[0] == '/' && line[1] == '/') - continue; + if (!chr->sql_config_read_registry(filename, &config, imported)) + retval = false; + if (!chr->sql_config_read_pc(filename, &config, imported)) + retval = false; + if (!chr->sql_config_read_guild(filename, &config, imported)) + retval = false; - if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) != 2) - continue; + ShowInfo("Done reading %s.\n", filename); + // 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, chr->SQL_CONF_NAME) == 0) { + ShowWarning("sql_config_read: Loop detected in %s! Skipping 'import'...\n", filename); + } else { + if (!chr->sql_config_read(import, true)) + retval = false; + } + } - if(!strcmpi(w1,"char_db")) - safestrncpy(char_db, w2, sizeof(char_db)); - else if(!strcmpi(w1,"scdata_db")) - safestrncpy(scdata_db, w2, sizeof(scdata_db)); - else if(!strcmpi(w1,"cart_db")) - safestrncpy(cart_db, w2, sizeof(cart_db)); - else if(!strcmpi(w1,"inventory_db")) - safestrncpy(inventory_db, w2, sizeof(inventory_db)); - else if(!strcmpi(w1,"charlog_db")) - safestrncpy(charlog_db, w2, sizeof(charlog_db)); - else if(!strcmpi(w1,"storage_db")) - safestrncpy(storage_db, w2, sizeof(storage_db)); - else if(!strcmpi(w1,"skill_db")) - safestrncpy(skill_db, w2, sizeof(skill_db)); - else if(!strcmpi(w1,"interlog_db")) - safestrncpy(interlog_db, w2, sizeof(interlog_db)); - else if(!strcmpi(w1,"memo_db")) - safestrncpy(memo_db, w2, sizeof(memo_db)); - else if(!strcmpi(w1,"guild_db")) - safestrncpy(guild_db, w2, sizeof(guild_db)); - else if(!strcmpi(w1,"guild_alliance_db")) - safestrncpy(guild_alliance_db, w2, sizeof(guild_alliance_db)); - else if(!strcmpi(w1,"guild_castle_db")) - safestrncpy(guild_castle_db, w2, sizeof(guild_castle_db)); - else if(!strcmpi(w1,"guild_expulsion_db")) - safestrncpy(guild_expulsion_db, w2, sizeof(guild_expulsion_db)); - else if(!strcmpi(w1,"guild_member_db")) - safestrncpy(guild_member_db, w2, sizeof(guild_member_db)); - else if(!strcmpi(w1,"guild_skill_db")) - safestrncpy(guild_skill_db, w2, sizeof(guild_skill_db)); - else if(!strcmpi(w1,"guild_position_db")) - safestrncpy(guild_position_db, w2, sizeof(guild_position_db)); - else if(!strcmpi(w1,"guild_storage_db")) - safestrncpy(guild_storage_db, w2, sizeof(guild_storage_db)); - else if(!strcmpi(w1,"party_db")) - safestrncpy(party_db, w2, sizeof(party_db)); - else if(!strcmpi(w1,"pet_db")) - safestrncpy(pet_db, w2, sizeof(pet_db)); - else if(!strcmpi(w1,"mail_db")) - safestrncpy(mail_db, w2, sizeof(mail_db)); - else if(!strcmpi(w1,"auction_db")) - safestrncpy(auction_db, w2, sizeof(auction_db)); - else if(!strcmpi(w1,"friend_db")) - safestrncpy(friend_db, w2, sizeof(friend_db)); - else if(!strcmpi(w1,"hotkey_db")) - safestrncpy(hotkey_db, w2, sizeof(hotkey_db)); - else if(!strcmpi(w1,"quest_db")) - safestrncpy(quest_db,w2,sizeof(quest_db)); - else if(!strcmpi(w1,"homunculus_db")) - safestrncpy(homunculus_db,w2,sizeof(homunculus_db)); - else if(!strcmpi(w1,"skill_homunculus_db")) - safestrncpy(skill_homunculus_db,w2,sizeof(skill_homunculus_db)); - else if(!strcmpi(w1,"mercenary_db")) - safestrncpy(mercenary_db,w2,sizeof(mercenary_db)); - else if(!strcmpi(w1,"mercenary_owner_db")) - safestrncpy(mercenary_owner_db,w2,sizeof(mercenary_owner_db)); - else if(!strcmpi(w1,"ragsrvinfo_db")) - safestrncpy(ragsrvinfo_db,w2,sizeof(ragsrvinfo_db)); - else if(!strcmpi(w1,"elemental_db")) - safestrncpy(elemental_db,w2,sizeof(elemental_db)); - else if(!strcmpi(w1,"account_data_db")) - safestrncpy(account_data_db,w2,sizeof(account_data_db)); - else if(!strcmpi(w1,"char_reg_num_db")) - safestrncpy(char_reg_num_db, w2, sizeof(char_reg_num_db)); - else if(!strcmpi(w1,"char_reg_str_db")) - safestrncpy(char_reg_str_db, w2, sizeof(char_reg_str_db)); - else if(!strcmpi(w1,"acc_reg_str_db")) - safestrncpy(acc_reg_str_db, w2, sizeof(acc_reg_str_db)); - else if(!strcmpi(w1,"acc_reg_num_db")) - safestrncpy(acc_reg_num_db, w2, sizeof(acc_reg_num_db)); - //support the import command, just like any other config - else if(!strcmpi(w1,"import")) - chr->sql_config_read(w2); - else - HPM->parseConf(w1, w2, HPCT_CHAR_INTER); + // TODO HPM->parseConf(w1, w2, HPCT_CHAR_INTER); + + libconfig->destroy(&config); + return retval; +} + +/** + * Reads the 'inter_configuration/database_names/registry' 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 char_sql_config_read_registry(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "inter_configuration/database_names/registry")) == NULL) { + if (imported) + return true; + ShowError("sql_config_read: inter_configuration/database_names/registry was not found in %s!\n", filename); + return false; } - fclose(fp); - ShowInfo("Done reading %s.\n", cfgName); + // Not all registries are read by char-server + libconfig->setting_lookup_mutable_string(setting, "char_reg_num_db", char_reg_num_db, sizeof(char_reg_num_db)); + libconfig->setting_lookup_mutable_string(setting, "char_reg_str_db", char_reg_str_db, sizeof(char_reg_str_db)); + libconfig->setting_lookup_mutable_string(setting, "acc_reg_str_db", acc_reg_str_db, sizeof(acc_reg_str_db)); + libconfig->setting_lookup_mutable_string(setting, "acc_reg_num_db", acc_reg_num_db, sizeof(acc_reg_num_db)); + + return true; +} + +/** + * Reads the 'inter_configuration/database_names/pc' 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 char_sql_config_read_pc(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "inter_configuration/database_names/pc")) == NULL) { + if (imported) + return true; + ShowError("sql_config_read: inter_configuration/database_names/pc was not found in %s!\n", filename); + return false; + } + libconfig->setting_lookup_mutable_string(setting, "hotkey_db", hotkey_db, sizeof(hotkey_db)); + libconfig->setting_lookup_mutable_string(setting, "scdata_db", scdata_db, sizeof(scdata_db)); + libconfig->setting_lookup_mutable_string(setting, "inventory_db", inventory_db, sizeof(inventory_db)); + libconfig->setting_lookup_mutable_string(setting, "cart_db", cart_db, sizeof(cart_db)); + libconfig->setting_lookup_mutable_string(setting, "charlog_db", charlog_db, sizeof(charlog_db)); + libconfig->setting_lookup_mutable_string(setting, "storage_db", storage_db, sizeof(storage_db)); + libconfig->setting_lookup_mutable_string(setting, "skill_db", skill_db, sizeof(skill_db)); + libconfig->setting_lookup_mutable_string(setting, "memo_db", memo_db, sizeof(memo_db)); + libconfig->setting_lookup_mutable_string(setting, "party_db", party_db, sizeof(party_db)); + libconfig->setting_lookup_mutable_string(setting, "pet_db", pet_db, sizeof(pet_db)); + libconfig->setting_lookup_mutable_string(setting, "friend_db", friend_db, sizeof(friend_db)); + libconfig->setting_lookup_mutable_string(setting, "mail_db", mail_db, sizeof(mail_db)); + libconfig->setting_lookup_mutable_string(setting, "auction_db", auction_db, sizeof(auction_db)); + libconfig->setting_lookup_mutable_string(setting, "quest_db", quest_db, sizeof(quest_db)); + libconfig->setting_lookup_mutable_string(setting, "homunculus_db", homunculus_db, sizeof(homunculus_db)); + libconfig->setting_lookup_mutable_string(setting, "skill_homunculus_db", skill_homunculus_db, sizeof(skill_homunculus_db)); + libconfig->setting_lookup_mutable_string(setting, "mercenary_db", mercenary_db, sizeof(mercenary_db)); + libconfig->setting_lookup_mutable_string(setting, "mercenary_owner_db", mercenary_owner_db, sizeof(mercenary_owner_db)); + libconfig->setting_lookup_mutable_string(setting, "elemental_db", elemental_db, sizeof(elemental_db)); + libconfig->setting_lookup_mutable_string(setting, "account_data_db", account_data_db, sizeof(account_data_db)); + + return true; +} + +/** + * Reads the 'inter_configuration/database_names/guild' 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 char_sql_config_read_guild(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "inter_configuration/database_names/guild")) == NULL) { + if (imported) + return true; + ShowError("sql_config_read: inter_configuration/database_names/guild was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_mutable_string(setting, "main_db", guild_db, sizeof(guild_db)); + libconfig->setting_lookup_mutable_string(setting, "alliance_db", guild_alliance_db, sizeof(guild_alliance_db)); + libconfig->setting_lookup_mutable_string(setting, "castle_db", guild_castle_db, sizeof(guild_castle_db)); + libconfig->setting_lookup_mutable_string(setting, "expulsion_db", guild_expulsion_db, sizeof(guild_expulsion_db)); + libconfig->setting_lookup_mutable_string(setting, "member_db", guild_member_db, sizeof(guild_member_db)); + libconfig->setting_lookup_mutable_string(setting, "skill_db", guild_skill_db, sizeof(guild_skill_db)); + libconfig->setting_lookup_mutable_string(setting, "position_db", guild_position_db, sizeof(guild_position_db)); + libconfig->setting_lookup_mutable_string(setting, "storage_db", guild_storage_db, sizeof(guild_storage_db)); + + return true; } /** @@ -5479,6 +5548,8 @@ bool char_config_read(const char *filename, bool imported) retval = false; if (!chr->config_read_database(filename, &config, imported)) retval = false; + if (!inter->config_read_connection(filename, &config, imported)) + retval = false; if (!pincode->config_read(filename, &config, imported)) retval = false; @@ -6095,8 +6166,8 @@ int do_init(int argc, char **argv) { chr->CHAR_CONF_NAME = aStrdup("conf/char/char-server.conf"); chr->NET_CONF_NAME = aStrdup("conf/network.conf"); - chr->SQL_CONF_NAME = aStrdup("conf/inter-server.conf"); - chr->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); + chr->SQL_CONF_NAME = aStrdup("conf/common/inter-server.conf"); + chr->INTER_CONF_NAME = aStrdup("conf/common/inter-server.conf"); VECTOR_INIT(start_items); @@ -6123,18 +6194,25 @@ int do_init(int argc, char **argv) { cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); chr->config_read(chr->CHAR_CONF_NAME, false); sockt->net_config_read(chr->NET_CONF_NAME); - chr->sql_config_read(chr->SQL_CONF_NAME); + chr->sql_config_read(chr->SQL_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; - if (stat("conf/import/char_conf.txt", &fileinfo) == 0 && fileinfo.st_size > 0) { - ShowWarning("An old configuration file \"conf/import/char_conf.txt\" was found.\n"); - ShowWarning("If it contains settings you wish to keep, please merge them into \"conf/import/char-server_local.conf\".\n"); - ShowWarning("Otherwise, just delete it.\n"); - ShowInfo("Resuming in 10 seconds...\n"); - HSleep(10); - } + + CHECK_OLD_LOCAL_CONF("conf/import/char_conf.txt", "conf/import/char-server.conf"); + CHECK_OLD_LOCAL_CONF("conf/import/inter_conf.txt", "conf/import/inter-server.conf"); + +#undef CHECK_OLD_LOCAL_CONF } #ifndef BUILDBOT @@ -6425,6 +6503,9 @@ void char_defaults(void) chr->online_data_cleanup_sub = char_online_data_cleanup_sub; chr->online_data_cleanup = char_online_data_cleanup; chr->sql_config_read = char_sql_config_read; + chr->sql_config_read_registry = char_sql_config_read_registry; + chr->sql_config_read_pc = char_sql_config_read_pc; + chr->sql_config_read_guild = char_sql_config_read_guild; chr->config_read = char_config_read; chr->config_read_database = char_config_read_database; chr->config_read_console = char_config_read_console; diff --git a/src/char/char.h b/src/char/char.h index 74478b747..4dbdfd9db 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -279,8 +279,11 @@ struct char_interface { int (*check_connect_login_server) (int tid, int64 tick, int id, intptr_t data); int (*online_data_cleanup_sub) (union DBKey key, struct DBData *data, va_list ap); int (*online_data_cleanup) (int tid, int64 tick, int id, intptr_t data); - void (*sql_config_read) (const char* cfgName); + bool (*sql_config_read) (const char *filename, bool imported); + bool (*sql_config_read_registry) (const char *filename, const struct config_t *config, bool imported); + bool (*sql_config_read_pc) (const char *filename, const struct config_t *config, bool imported); + bool (*sql_config_read_guild) (const char *filename, const struct config_t *config, bool imported); bool (*config_read) (const char *filename, bool imported); bool (*config_read_database) (const char *filename, const struct config_t *config, bool imported); bool (*config_read_console) (const char *filename, const struct config_t *config, bool imported); diff --git a/src/char/inter.c b/src/char/inter.c index d1b885eed..4c5eb05e5 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -36,6 +36,7 @@ #include "char/int_storage.h" #include "char/mapif.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/db.h" #include "common/memmgr.h" #include "common/mmo.h" @@ -62,7 +63,7 @@ char char_server_pw[100] = "ragnarok"; char char_server_db[32] = "ragnarok"; char default_codepage[32] = ""; //Feature by irmin. -unsigned int party_share_level = 10; +int party_share_level = 10; // recv. packet list int inter_recv_packet_length[] = { @@ -791,50 +792,84 @@ int inter_accreg_fromsql(int account_id,int char_id, int fd, int type) return 1; } -/*========================================== - * read config file - *------------------------------------------*/ -static int inter_config_read(const char* cfgName) +/** + * Reads the 'char_configuration/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) { - char line[1024], w1[1024], w2[1024]; - FILE* fp; + const struct config_setting_t *setting = NULL; - nullpo_retr(1, cfgName); - fp = fopen(cfgName, "r"); - if(fp == NULL) { - ShowError("File not found: %s\n", cfgName); - return 1; + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "char_configuration/sql_connection")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/sql_connection was not found in %s!\n", filename); + ShowWarning("inter_config_read_connection: Defaulting sql_connection...\n"); + return false; } - while (fgets(line, sizeof(line), fp)) { - int i = sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2); - if(i != 2) - continue; + libconfig->setting_lookup_int(setting, "db_port", &char_server_port); + libconfig->setting_lookup_mutable_string(setting, "db_hostname", char_server_ip, sizeof(char_server_ip)); + libconfig->setting_lookup_mutable_string(setting, "db_username", char_server_id, sizeof(char_server_id)); + libconfig->setting_lookup_mutable_string(setting, "db_password", char_server_pw, sizeof(char_server_pw)); + libconfig->setting_lookup_mutable_string(setting, "db_database", char_server_db, sizeof(char_server_db)); + libconfig->setting_lookup_mutable_string(setting, "default_codepage", default_codepage, sizeof(default_codepage)); + + return true; +} - if(!strcmpi(w1,"char_server_ip")) { - safestrncpy(char_server_ip, w2, sizeof(char_server_ip)); - } else if(!strcmpi(w1,"char_server_port")) { - char_server_port = atoi(w2); - } else if(!strcmpi(w1,"char_server_id")) { - safestrncpy(char_server_id, w2, sizeof(char_server_id)); - } else if(!strcmpi(w1,"char_server_pw")) { - safestrncpy(char_server_pw, w2, sizeof(char_server_pw)); - } else if(!strcmpi(w1,"char_server_db")) { - safestrncpy(char_server_db, w2, sizeof(char_server_db)); - } else if(!strcmpi(w1,"default_codepage")) { - safestrncpy(default_codepage, w2, sizeof(default_codepage)); - } else if(!strcmpi(w1,"party_share_level")) - party_share_level = atoi(w2); - else if(!strcmpi(w1,"log_inter")) - inter->enable_logs = atoi(w2) ? true : false; - else if(!strcmpi(w1,"import")) - inter->config_read(w2); +/** + * Reads the 'inter_configuration' config file and initializes required variables. + * + * @param filename Path to configuration file + * @param imported Whether the current config is from an imported 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; } - fclose(fp); + libconfig->setting_lookup_int(setting, "party_share_level", &party_share_level); + libconfig->setting_lookup_bool_real(setting, "log_inter", &inter->enable_logs); - ShowInfo ("Done reading %s.\n", cfgName); + ShowInfo("Done reading %s.\n", filename); - return 0; + // 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, chr->INTER_CONF_NAME) == 0) { + ShowWarning("inter_config_read: Loop detected in %s! Skipping 'import'...\n", filename); + } else { + if (!inter->config_read(import, true)) + retval = false; + } + } + + libconfig->destroy(&config); + return retval; } /** @@ -879,9 +914,7 @@ int inter_log(char* fmt, ...) // initialize int inter_init_sql(const char *file) { - //int i; - - inter->config_read(file); + inter->config_read(file, false); //DB connection initialized inter->sql_handle = SQL->Malloc(); @@ -1385,4 +1418,5 @@ void inter_defaults(void) inter->check_length = inter_check_length; inter->parse_frommap = inter_parse_frommap; inter->final = inter_final; + inter->config_read_connection = inter_config_read_connection; } diff --git a/src/char/inter.h b/src/char/inter.h index db50fd645..57d1db86c 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -28,6 +28,7 @@ /* Forward Declarations */ struct Sql; // common/sql.h +struct config_t; // common/conf.h /** * inter interface @@ -43,7 +44,6 @@ struct inter_interface { void (*msg_to_fd) (int fd, int u_fd, int aid, char *msg, ...) __attribute__((format(printf, 4, 5))); void (*savereg) (int account_id, int char_id, const char *key, unsigned int index, intptr_t val, bool is_string); int (*accreg_fromsql) (int account_id,int char_id, int fd, int type); - int (*config_read) (const char* cfgName); int (*vlog) (char* fmt, va_list ap); int (*log) (char* fmt, ...); int (*init_sql) (const char *file); @@ -53,10 +53,12 @@ struct inter_interface { int (*check_length) (int fd, int length); int (*parse_frommap) (int fd); void (*final) (void); + bool (*config_read) (const char *filename, bool imported); + bool (*config_read_connection) (const char *filename, const struct config_t *config, bool imported); }; #ifdef HERCULES_CORE -extern unsigned int party_share_level; +extern int party_share_level; ///< Share range for parties. void inter_defaults(void); #endif // HERCULES_CORE diff --git a/src/common/sql.c b/src/common/sql.c index 9a90f9807..be0bd43e3 100644 --- a/src/common/sql.c +++ b/src/common/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 @@ -23,7 +23,9 @@ #include "sql.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/memmgr.h" +#include "common/nullpo.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/timer.h" @@ -37,8 +39,8 @@ void hercules_mysql_error_handler(unsigned int ecode); -int mysql_reconnect_type; -unsigned int mysql_reconnect_count; +int mysql_reconnect_type = 2; +int mysql_reconnect_count = 1; struct sql_interface sql_s; struct sql_interface *SQL; @@ -868,55 +870,67 @@ void hercules_mysql_error_handler(unsigned int ecode) { switch( ecode ) { case 2003:/* Can't connect to MySQL (this error only happens here when failing to reconnect) */ if( mysql_reconnect_type == 1 ) { - static unsigned int retry = 1; + static int retry = 1; if( ++retry > mysql_reconnect_count ) { - ShowFatalError("MySQL has been unreachable for too long, %u reconnects were attempted. Shutting Down\n", retry); + ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry); exit(EXIT_FAILURE); } } break; } } -void Sql_inter_server_read(const char* cfgName, bool first) { - char line[1024], w1[1024], w2[1024]; - FILE* fp; - - fp = fopen(cfgName, "r"); - if(fp == NULL) { - if( first ) { - ShowFatalError("File not found: %s\n", cfgName); - exit(EXIT_FAILURE); - } else - ShowError("File not found: %s\n", cfgName); - return; + +/** + * Parses mysql_reconnect from inter_configuration. + * + * @param filename Path to configuration file. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool Sql_inter_server_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/mysql_reconnect")) == NULL) { + config_destroy(&config); + if (imported) + return true; + ShowError("Sql_inter_server_read: inter_configuration/mysql_reconnect was not found in %s!\n", filename); + return false; } - while (fgets(line, sizeof(line), fp)) { - int i = sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2); - if (i != 2) - continue; + if (libconfig->setting_lookup_int(setting, "type", &mysql_reconnect_type) == CONFIG_TRUE) { + if (mysql_reconnect_type != 1 && mysql_reconnect_type != 2) { + ShowError("%s::inter_configuration/mysql_reconnect/type is set to %d which is not valid, defaulting to 1...\n", filename, mysql_reconnect_type); + mysql_reconnect_type = 1; + } + } + if (libconfig->setting_lookup_int(setting, "count", &mysql_reconnect_count) == CONFIG_TRUE) { + if (mysql_reconnect_count < 1) + mysql_reconnect_count = 1; + } - if(!strcmpi(w1,"mysql_reconnect_type")) { - mysql_reconnect_type = atoi(w2); - switch( mysql_reconnect_type ) { - case 1: - case 2: - break; - default: - ShowError("%s::mysql_reconnect_type is set to %d which is not valid, defaulting to 1...\n", cfgName, mysql_reconnect_type); - mysql_reconnect_type = 1; - break; - } - } else if(!strcmpi(w1,"mysql_reconnect_count")) { - mysql_reconnect_count = atoi(w2); - if( mysql_reconnect_count < 1 ) - mysql_reconnect_count = 1; - } else if(!strcmpi(w1,"import")) - Sql_inter_server_read(w2,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, "conf/common/inter-server.conf") == 0) { // FIXME: Hardcoded path + ShowWarning("Sql_inter_server_read: Loop detected in %s! Skipping 'import'...\n", filename); + } else { + if (!Sql_inter_server_read(import, true)) + retval = false; + } } - fclose(fp); - return; + libconfig->destroy(&config); + return retval; } void Sql_HerculesUpdateCheck(struct Sql *self) @@ -1019,7 +1033,7 @@ void Sql_HerculesUpdateSkip(struct Sql *self, const char *filename) } void Sql_Init(void) { - Sql_inter_server_read("conf/inter-server.conf",true); + Sql_inter_server_read("conf/common/inter-server.conf", false); // FIXME: Hardcoded path } void sql_defaults(void) { SQL = &sql_s; diff --git a/src/common/sql.h b/src/common/sql.h index 07be829fc..4d9a12cc1 100644 --- a/src/common/sql.h +++ b/src/common/sql.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 diff --git a/src/map/map.c b/src/map/map.c index d6425b94e..56af8113b 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3997,63 +3997,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(1, cfgName); - 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, "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; } - 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); + 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; + } } - fclose(fp); - return 0; + 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(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; + } + + 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; + } + + 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,7 +6139,7 @@ int do_init(int argc, char *argv[]) map_load_defaults(); - map->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); + map->INTER_CONF_NAME = aStrdup("conf/common/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"); @@ -6128,7 +6190,7 @@ int do_init(int argc, char *argv[]) battle->config_read(map->BATTLE_CONF_FILENAME); atcommand->msg_read(map->MSG_CONF_NAME, false); - map->inter_config_read(map->INTER_CONF_NAME); + map->inter_config_read(map->INTER_CONF_NAME, false); logs->config_read(map->LOG_CONF_NAME); } script->config_read(map->SCRIPT_CONF_NAME); @@ -6288,7 +6350,7 @@ 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->INTER_CONF_NAME="conf/common/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"; @@ -6502,6 +6564,8 @@ void map_defaults(void) { map->config_read_sub = map_config_read_sub; map->reloadnpc_sub = map_reloadnpc_sub; 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..f98e1cb7f 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; @@ -1190,7 +1191,9 @@ END_ZEROED_BLOCK; int (*config_read) (char *cfgName); int (*config_read_sub) (char *cfgName); void (*reloadnpc_sub) (char *cfgName); - int (*inter_config_read) (char *cfgName); + 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; |