From 6be7aab17d958e0f5a4be0413b26c7dd81185af6 Mon Sep 17 00:00:00 2001 From: Haru Date: Mon, 15 Feb 2016 16:19:38 +0100 Subject: Renamed some char and inter server variables - `int save_log` -> `bool chr->show_save_log` - `bool char_new` -> `bool enable_char_creation` - `int log_char` -> `bool chr->enable_logs` - `int log_inter` -> `bool inter->enable_logs` - `int chr->new_display` -> `int16 chr->new_display` - `int char_aegis_delete` -> `bool char_aegis_delete` Split and improved from Panikon's commit 832fb27d4f767e4bc8b68c432d0da00b7cb7a4f9 Signed-off-by: Haru --- src/char/char.c | 80 +++++++++++++++++++++++------------------------- src/char/char.h | 9 +++--- src/char/int_elemental.c | 4 +-- src/char/int_guild.c | 28 ++++++++--------- src/char/int_homun.c | 4 +-- src/char/int_mercenary.c | 4 +-- src/char/int_party.c | 6 ++-- src/char/int_pet.c | 6 ++-- src/char/inter.c | 5 +-- src/char/inter.h | 3 +- 10 files changed, 75 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/char/char.c b/src/char/char.c index 2851d3eba..571aad566 100644 --- a/src/char/char.c +++ b/src/char/char.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 @@ -110,9 +110,6 @@ char char_reg_num_db[32] = "char_reg_num_db"; struct char_interface char_s; struct char_interface *chr; -// show loading/saving messages -int save_log = 1; - char db_path[1024] = "db"; char wisp_server_name[NAME_LENGTH] = "Server"; @@ -123,7 +120,7 @@ char char_ip_str[128]; char bind_ip_str[128]; uint32 bind_ip = INADDR_ANY; int char_maintenance_min_group_id = 0; -bool char_new = true; +bool enable_char_creation = true; ///< Whether to allow character creation. bool name_ignoring_case = false; // Allow or not identical name for characters but with a different case by [Yor] int char_name_option = 0; // Option to know which letters/symbols are authorized in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] @@ -131,13 +128,9 @@ char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the request #define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex] char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) in a character name. by [Yor] -int char_del_level = 0; //From which level u can delete character [Lupus] +int char_del_level = 0; ///< From which level you can delete character [Lupus] int char_del_delay = 86400; - -int log_char = 1; // logging char or not [devil] -int log_inter = 1; // logging inter or not [devil] - -int char_aegis_delete = 0; // Verify if char is in guild/party or char and reacts as Aegis does (doesn't allow deletion), see chr->delete2_req for more information +bool char_aegis_delete = false; ///< Verify if char is in guild/party or char and reacts as Aegis does (disallow deletion), @see chr->delete2_req. int max_connect_user = -1; int gm_allow_group = -1; @@ -690,7 +683,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) #endif StrBuf->Destroy(&buf); - if (save_status[0]!='\0' && save_log) + if (chr->show_save_log && save_status[0] != '\0') ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status); if (!errors) memcpy(cp, p, sizeof(struct mmo_charstatus)); @@ -1043,7 +1036,8 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every memset(p, 0, sizeof(struct mmo_charstatus)); - if (save_log) ShowInfo("Char load request (%d)\n", char_id); + if (chr->show_save_log) + ShowInfo("Char load request (%d)\n", char_id); stmt = SQL->StmtMalloc(inter->sql_handle); if( stmt == NULL ) @@ -1336,7 +1330,8 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every if( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) strcat(t_msg, " accdata"); - if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfully! + if (chr->show_save_log) + ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfully! SQL->StmtFree(stmt); StrBuf->Destroy(&buf); @@ -1463,12 +1458,11 @@ int char_rename_char_sql(struct char_session_data *sd, int char_id) memset(sd->new_name,0,sizeof(sd->new_name)); // log change - if( log_char ) - { - if( SQL_ERROR == SQL->Query(inter->sql_handle, - "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" - "VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')", - charlog_db, "change char name", sd->account_id, char_dat.char_id, char_dat.slot, esc_name) ) + if (chr->enable_logs) { + if (SQL_ERROR == SQL->Query(inter->sql_handle, + "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + "VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')", + charlog_db, "change char name", sd->account_id, char_dat.char_id, char_dat.slot, esc_name)) Sql_ShowDebug(inter->sql_handle); } @@ -1606,10 +1600,11 @@ int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int return -2; // Validation success, log result - if (log_char) { - if( SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" - "VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db, "make new char", sd->account_id, char_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) ) + if (chr->enable_logs) { + if (SQL_ERROR == SQL->Query(inter->sql_handle, + "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + "VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", + charlog_db, "make new char", sd->account_id, char_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color)) Sql_ShowDebug(inter->sql_handle); } @@ -1804,13 +1799,13 @@ int char_delete_char_sql(int char_id) #endif /* delete character */ - if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id)) { Sql_ShowDebug(inter->sql_handle); - else if( log_char ) { - if( SQL_ERROR == SQL->Query(inter->sql_handle, - "INSERT INTO `%s`(`time`, `account_id`, `char_id`, `char_num`, `char_msg`, `name`)" - " VALUES (NOW(), '%d', '%d', '%d', 'Deleted character', '%s')", - charlog_db, account_id, char_id, 0, esc_name) ) + } else if (chr->enable_logs) { + if (SQL_ERROR == SQL->Query(inter->sql_handle, + "INSERT INTO `%s`(`time`, `account_id`, `char_id`, `char_num`, `char_msg`, `name`)" + " VALUES (NOW(), '%d', '%d', '%d', 'Deleted character', '%s')", + charlog_db, account_id, char_id, 0, esc_name)) Sql_ShowDebug(inter->sql_handle); } @@ -2015,7 +2010,7 @@ int char_mmo_char_send_characters(int fd, struct char_session_data* sd) #if PACKETVER >= 20100413 offset += 3; #endif - if (save_log) + if (chr->show_save_log) ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); j = 24 + offset; // offset @@ -4516,13 +4511,13 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl) if( cd->sex == 99 ) cd->sex = sd->sex; - if (log_char) { + if (chr->enable_logs) { char esc_name[NAME_LENGTH*2+1]; // FIXME: Why are we re-escaping the name if it was already escaped in rename/make_new_char? [Panikon] SQL->EscapeStringLen(inter->sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH)); - if( SQL_ERROR == SQL->Query(inter->sql_handle, - "INSERT INTO `%s`(`time`, `account_id`, `char_id`, `char_num`, `name`) VALUES (NOW(), '%d', '%d', '%d', '%s')", - charlog_db, sd->account_id, cd->char_id, slot, esc_name) ) + if (SQL_ERROR == SQL->Query(inter->sql_handle, + "INSERT INTO `%s`(`time`, `account_id`, `char_id`, `char_num`, `name`) VALUES (NOW(), '%d', '%d', '%d', '%s')", + charlog_db, sd->account_id, cd->char_id, slot, esc_name)) Sql_ShowDebug(inter->sql_handle); } ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name); @@ -4615,7 +4610,7 @@ void char_parse_char_create_new_char(int fd, struct char_session_data* sd) __att void char_parse_char_create_new_char(int fd, struct char_session_data* sd) { int result; - if( !char_new ) { + if (!enable_char_creation) { //turn character creation on/off [Kevin] result = -2; } else { @@ -5525,7 +5520,7 @@ int char_config_read(const char* cfgName) } else if (strcmpi(w1, "char_server_type") == 0) { chr->server_type = atoi(w2); } else if (strcmpi(w1, "char_new") == 0) { - char_new = (bool)atoi(w2); + enable_char_creation = atoi(w2) ? true : false; } else if (strcmpi(w1, "char_new_display") == 0) { chr->new_display = atoi(w2); } else if (strcmpi(w1, "max_connect_user") == 0) { @@ -5539,7 +5534,7 @@ int char_config_read(const char* cfgName) if (autosave_interval <= 0) autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; } else if (strcmpi(w1, "save_log") == 0) { - save_log = config_switch(w2); + chr->show_save_log = config_switch(w2) ? true : false; } #ifdef RENEWAL else if (strcmpi(w1, "start_point_re") == 0) { @@ -5596,8 +5591,8 @@ int char_config_read(const char* cfgName) start_zeny = atoi(w2); if (start_zeny < 0) start_zeny = 0; - } else if(strcmpi(w1,"log_char")==0) { - log_char = atoi(w2); //log char or not [devil] + } else if(strcmpi(w1,"log_char") == 0) { + chr->enable_logs = atoi(w2) ? true : false; } else if (strcmpi(w1, "unknown_char_name") == 0) { safestrncpy(unknown_char_name, w2, sizeof(unknown_char_name)); unknown_char_name[NAME_LENGTH-1] = '\0'; @@ -5612,7 +5607,7 @@ int char_config_read(const char* cfgName) } else if (strcmpi(w1, "char_del_delay") == 0) { char_del_delay = atoi(w2); } else if (strcmpi(w1, "char_aegis_delete") == 0) { - char_aegis_delete = atoi(w2); + char_aegis_delete = atoi(w2) ? true : false; } else if(strcmpi(w1,"db_path")==0) { safestrncpy(db_path, w2, sizeof(db_path)); } else if (strcmpi(w1, "fame_list_alchemist") == 0) { @@ -5947,6 +5942,9 @@ void char_defaults(void) chr->server_type = 0; chr->new_display = 0; + chr->show_save_log = true; + chr->enable_logs = true; + chr->waiting_disconnect = char_waiting_disconnect; chr->delete_char_sql = char_delete_char_sql; chr->create_online_char_data = char_create_online_char_data; diff --git a/src/char/char.h b/src/char/char.h index a0cfb3bd7..b94226859 100644 --- a/src/char/char.h +++ b/src/char/char.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 @@ -110,13 +110,16 @@ struct char_interface { uint32 ip; uint16 port; int server_type; - int new_display; + int16 new_display; ///< Display 'New' in the server list. char *CHAR_CONF_NAME; char *NET_CONF_NAME; ///< Network config filename char *SQL_CONF_NAME; char *INTER_CONF_NAME; + bool show_save_log; ///< Show loading/saving messages. + bool enable_logs; ///< Whether to log char server operations. + int (*waiting_disconnect) (int tid, int64 tick, int id, intptr_t data); int (*delete_char_sql) (int char_id); struct DBData (*create_online_char_data) (union DBKey key, va_list args); @@ -282,7 +285,6 @@ extern int char_name_option; extern char char_name_letters[]; extern bool char_gm_read; extern int autosave_interval; -extern int save_log; extern char db_path[]; extern char char_db[256]; extern char scdata_db[256]; @@ -318,7 +320,6 @@ extern char char_reg_str_db[32]; extern char char_reg_num_db[32]; extern int guild_exp_rate; -extern int log_inter; void char_load_defaults(void); void char_defaults(void); diff --git a/src/char/int_elemental.c b/src/char/int_elemental.c index c25cfa5c8..aed25febd 100644 --- a/src/char/int_elemental.c +++ b/src/char/int_elemental.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 @@ -128,7 +128,7 @@ bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) { SQL->GetData(inter->sql_handle, 13, &data, NULL); ele->hit = atoi(data); SQL->GetData(inter->sql_handle, 14, &data, NULL); ele->life_time = atoi(data); SQL->FreeResult(inter->sql_handle); - if( save_log ) + if (chr->show_save_log) ShowInfo("Elemental loaded (%d - %d).\n", ele->elemental_id, ele->char_id); return true; diff --git a/src/char/int_guild.c b/src/char/int_guild.c index d2507a2f9..dcc1ed7cb 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.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 @@ -83,9 +83,9 @@ int inter_guild_save_timer(int tid, int64 tick, int id, intptr_t data) { state++; } - if( g->save_flag == GS_REMOVE ) - {// Nothing to save, guild is ready for removal. - if (save_log) + if (g->save_flag == GS_REMOVE) { + // Nothing to save, guild is ready for removal. + if (chr->show_save_log) ShowInfo("Guild Unloaded (%d - %s)\n", g->guild_id, g->name); db_remove(inter_guild->guild_db, key); } @@ -337,8 +337,8 @@ int inter_guild_tosql(struct guild *g,int flag) } } - if (save_log) - ShowInfo("Saved guild (%d - %s):%s\n",g->guild_id,g->name,t_info); + if (chr->show_save_log) + ShowInfo("Saved guild (%d - %s):%s\n", g->guild_id, g->name, t_info); return 1; } @@ -525,7 +525,7 @@ struct guild * inter_guild_fromsql(int guild_id) idb_put(inter_guild->guild_db, guild_id, g); //Add to cache g->save_flag |= GS_REMOVE; //But set it to be removed, in case it is not needed for long. - if (save_log) + if (chr->show_save_log) ShowInfo("Guild loaded (%d - %s)\n", guild_id, g->name); return g; @@ -548,7 +548,7 @@ int inter_guild_castle_tosql(struct guild_castle *gc) if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) Sql_ShowDebug(inter->sql_handle); - else if(save_log) + else if (chr->show_save_log) ShowInfo("Saved guild castle (%d)\n", gc->castle_id); StrBuf->Destroy(&buf); @@ -600,7 +600,7 @@ struct guild_castle* inter_guild_castle_fromsql(int castle_id) idb_put(inter_guild->castle_db, castle_id, gc); - if (save_log) + if (chr->show_save_log) ShowInfo("Loaded guild castle (%d - guild %d)\n", castle_id, gc->guild_id); return gc; @@ -1233,9 +1233,9 @@ int mapif_parse_CreateGuild(int fd, int account_id, const char *name, const stru mapif->guild_created(fd,account_id,g); mapif->guild_info(fd,g); - if(log_inter) + if (inter->enable_logs) inter->log("guild %s (id=%d) created by master %s (id=%d)\n", - name, g->guild_id, master->name, master->account_id ); + name, g->guild_id, master->name, master->account_id); return 0; } @@ -1442,8 +1442,8 @@ int mapif_parse_BreakGuild(int fd, int guild_id) mapif->guild_broken(guild_id,0); - if(log_inter) - inter->log("guild %s (id=%d) broken\n",g->name,guild_id); + if (inter->enable_logs) + inter->log("guild %s (id=%d) broken\n", g->name, guild_id); //Remove the guild from memory. [Skotlex] idb_remove(inter_guild->guild_db, guild_id); @@ -1821,7 +1821,7 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) switch (index) { case 1: - if (log_inter && gc->guild_id != value) { + if (inter->enable_logs && gc->guild_id != value) { int gid = (value) ? value : gc->guild_id; struct guild *g = idb_get(inter_guild->guild_db, gid); inter->log("guild %s (id=%d) %s castle id=%d\n", diff --git a/src/char/int_homun.c b/src/char/int_homun.c index 90643699c..04f4c8f21 100644 --- a/src/char/int_homun.c +++ b/src/char/int_homun.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 @@ -262,7 +262,7 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) } SQL->FreeResult(inter->sql_handle); - if( save_log ) + if (chr->show_save_log) ShowInfo("Homunculus loaded (%d - %s).\n", hd->hom_id, hd->name); return true; diff --git a/src/char/int_mercenary.c b/src/char/int_mercenary.c index 0bc3c0909..f96e45a50 100644 --- a/src/char/int_mercenary.c +++ b/src/char/int_mercenary.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 @@ -168,7 +168,7 @@ bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc) SQL->GetData(inter->sql_handle, 3, &data, NULL); merc->kill_count = atoi(data); SQL->GetData(inter->sql_handle, 4, &data, NULL); merc->life_time = atoi(data); SQL->FreeResult(inter->sql_handle); - if( save_log ) + if (chr->show_save_log) ShowInfo("Mercenary loaded (%d - %d).\n", merc->mercenary_id, merc->char_id); return true; diff --git a/src/char/int_party.c b/src/char/int_party.c index 684d846d4..e2be9f3ca 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.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 @@ -190,7 +190,7 @@ int inter_party_tosql(struct party *p, int flag, int index) Sql_ShowDebug(inter->sql_handle); } - if( save_log ) + if (chr->show_save_log) ShowInfo("Party Saved (%d - %s)\n", party_id, p->name); return 1; } @@ -257,7 +257,7 @@ struct party_data *inter_party_fromsql(int party_id) } SQL->FreeResult(inter->sql_handle); - if( save_log ) + if (chr->show_save_log) ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name); //Add party to memory. CREATE(p, struct party_data, 1); diff --git a/src/char/int_pet.c b/src/char/int_pet.c index eb9bda8d0..489b10e3e 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.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 @@ -85,7 +85,7 @@ int inter_pet_tosql(const struct s_pet *p) pet_id = p->pet_id; } - if (save_log) + if (chr->show_save_log) ShowInfo("Pet saved %d - %s.\n", pet_id, p->name); return pet_id; @@ -130,7 +130,7 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p) p->hungry = cap_value(p->hungry, 0, 100); p->intimate = cap_value(p->intimate, 0, 1000); - if( save_log ) + if (chr->show_save_log) ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name); } return 0; diff --git a/src/char/inter.c b/src/char/inter.c index 5fb35e6aa..d1b885eed 100644 --- a/src/char/inter.c +++ b/src/char/inter.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 @@ -826,7 +826,7 @@ static int inter_config_read(const char* cfgName) } else if(!strcmpi(w1,"party_share_level")) party_share_level = atoi(w2); else if(!strcmpi(w1,"log_inter")) - log_inter = atoi(w2); + inter->enable_logs = atoi(w2) ? true : false; else if(!strcmpi(w1,"import")) inter->config_read(w2); } @@ -1364,6 +1364,7 @@ void inter_defaults(void) { inter = &inter_s; + inter->enable_logs = true; inter->sql_handle = NULL; inter->msg_txt = inter_msg_txt; diff --git a/src/char/inter.h b/src/char/inter.h index 4e8d113ce..db50fd645 100644 --- a/src/char/inter.h +++ b/src/char/inter.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 @@ struct Sql; // common/sql.h * inter interface **/ struct inter_interface { + bool enable_logs; ///< Whether to log inter-server operations. struct Sql *sql_handle; const char* (*msg_txt) (int msg_number); bool (*msg_config_read) (const char *cfg_name, bool allow_override); -- cgit v1.2.3-70-g09d2 From c84a4473cc0491edbf6ac3e7efd062d8c57e5a2c Mon Sep 17 00:00:00 2001 From: Haru Date: Sun, 6 Sep 2015 18:08:14 +0200 Subject: Ported char-server.conf to libconfig Fixed issue: 8115, now start items can be equipped as well Ported to modern Hercules and cleaned up from Panikon's commits: c6482e9870645ffe59a6a059b819574d4ac79fd9, 832fb27d4f767e4bc8b68c432d0da00b7cb7a4f9, f81b579899e3a15bd472ca8c6a6e0116c43bec92, e23723725499b617def03d05661eca637edaeabd, 0b783a83d82e588efd760f7f4baec0c8074a6fd1, 1b7de91308a57ea07b158ed95a2515a3c8cc36bd, 677d3430cbda0962b320a60cf499e9dadf637d00 Signed-off-by: Haru --- .gitignore | 10 +- conf/char-server.conf | 188 ---------- conf/char/char-server.conf | 233 ++++++++++++ conf/global/console.conf | 59 +++ conf/import-tmpl/char-server.conf | 32 ++ conf/import-tmpl/char_conf.txt | 0 doc/global_configuration.txt | 69 ++++ src/char/char.c | 747 +++++++++++++++++++++++++++----------- src/char/char.h | 20 +- src/char/pincode.c | 68 ++-- src/char/pincode.h | 6 +- src/common/mmo.h | 6 +- tools/configconverter.pl | 298 +++++++++++++++ 13 files changed, 1309 insertions(+), 427 deletions(-) delete mode 100644 conf/char-server.conf create mode 100644 conf/char/char-server.conf create mode 100644 conf/global/console.conf create mode 100644 conf/import-tmpl/char-server.conf delete mode 100644 conf/import-tmpl/char_conf.txt create mode 100644 doc/global_configuration.txt create mode 100755 tools/configconverter.pl (limited to 'src') diff --git a/.gitignore b/.gitignore index d3c4fe51a..5eccd9969 100644 --- a/.gitignore +++ b/.gitignore @@ -59,7 +59,15 @@ Thumbs.db /cache/ # /conf/ -/conf/import +/conf/import/*.conf +/conf/import/battle_conf.txt +/conf/import/inter_conf.txt +/conf/import/log_conf.txt +/conf/import/login_conf.txt +/conf/import/map_conf.txt +/conf/import/msg_conf.txt +/conf/import/packet_conf.txt +/conf/import/script_conf.txt # /log/ /log/*.log diff --git a/conf/char-server.conf b/conf/char-server.conf deleted file mode 100644 index eb2b9a63d..000000000 --- a/conf/char-server.conf +++ /dev/null @@ -1,188 +0,0 @@ -// Character Server configuration file. - -// Note: "Comments" are all text on the right side of a double slash "//" -// Whatever text is commented will not be parsed by the servers, and serves -// only as information/reference. - -// Server Communication username and password. -userid: s1 -passwd: p1 - -// Server name, use alternative character such as ASCII 160 for spaces. -// NOTE: Do not use spaces or any of these characters which are not allowed in -// Windows filenames \/:*?"<>| -// ... or else guild emblems won't work client-side! -server_name: Hercules - -// Wisp name for server: used to send wisp from server to players (between 4 to 23 characters) -wisp_server_name: Server - -// Login Server IP -// The character server connects to the login server using this IP address. -// NOTE: This is useful when you are running behind a firewall or are on -// a machine with multiple interfaces. -//login_ip: 127.0.0.1 - -// The character server listens on the interface with this IP address. -// NOTE: This allows you to run multiple servers on multiple interfaces -// while using the same ports for each server. -//bind_ip: 127.0.0.1 - -// Login Server Port -login_port: 6900 - -// Character Server IP -// The IP address which clients will use to connect. -// Set this to what your server's public IP address is. -//char_ip: 127.0.0.1 - -// Character Server Port -char_port: 6121 - -//Time-stamp format which will be printed before all messages. -//Can at most be 20 characters long. -//Common formats: -// %I:%M:%S %p (hour:minute:second 12 hour, AM/PM format) -// %H:%M:%S (hour:minute:second, 24 hour format) -// %d/%b/%Y (day/Month/year) -//For full format information, consult the strftime() manual. -//timestamp_format: [%d/%b %H:%M] - -//If redirected output contains escape sequences (color codes) -stdout_with_ansisequence: no - -//Makes server output more silent by ommitting certain types of messages: -//1: Hide Information messages -//2: Hide Status messages -//4: Hide Notice Messages -//8: Hide Warning Messages -//16: Hide Error and SQL Error messages. -//32: Hide Debug Messages -//Example: "console_silent: 7" Hides information, status and notice messages (1+2+4) -console_silent: 0 - -// Type of server. -// No functional side effects at the moment. -// Displayed next to the server name in the client. -// 0=normal, 1=maintenance, 2=over 18, 3=paying, 4=F2P -char_server_type: 0 - -// Minimum Group ID to join char server when it is on char_server_type 1 (maintenance) -char_maintenance_min_group_id: 99 - -// Enable or disable creation of new characters. -// Now it is actually supported [Kevin] -char_new: 1 - -// Display (New) in the server list. -char_new_display: 0 - -// Maximum users able to connect to the server. -// Set to 0 to disable users to log-in. (-1 means unlimited) -max_connect_user: -1 - -// Group ID that is allowed to bypass the server limit of users. -// Default: -1 = nobody (there are no groups with ID < 0) -// See: conf/groups.conf -gm_allow_group: -1 - -// How often should the server save all files? (In seconds) -// Note: Applies to all data files on TXT servers. -// On SQL servers, it applies to guilds (character save interval is defined on the map config) -autosave_time: 60 - -// Display information on the console whenever characters/guilds/parties/pets are loaded/saved? -save_log: yes - -// Start point, Map name followed by coordinates (x,y) -start_point_re: iz_int,97,90 -start_point_pre: new_1-1,53,111 - -// Starting items for new characters -// Format is: id1,quantity1,stackable1,idN,quantityN,stackableN -// stackable: -// 0 - Not stackable (weapon, armor, egg, pet armor) -// 1 - Stackable -start_items: 1201,1,0,2301,1,0 - -// Starting zeny for new characters -start_zeny: 0 - -// Size for the fame-lists -fame_list_alchemist: 10 -fame_list_blacksmith: 10 -fame_list_taekwon: 10 - -// Guild earned exp modifier. -// Adjusts taxed exp before adding it to the guild's exp. For example, if set -// to 200, the guild receives double the player's taxed exp. -guild_exp_rate: 100 - -// Name used for unknown characters -unknown_char_name: Unknown - -// To log the character server? -log_char: 1 - -// Allow or not identical name for characters but with a different case (upper/lower): -// example: Test-test-TEST-TesT; Value: 0 not allowed (default), 1 allowed -name_ignoring_case: no - -// Manage possible letters/symbol in the name of charater. Control character (0x00-0x1f) are never accepted. Possible values are: -// NOTE: Applies to character, party and guild names. -// 0: no restriction (default) -// 1: only letters/symbols in 'char_name_letters' option. -// 2: Letters/symbols in 'char_name_letters' option are forbidden. All others are possibles. -char_name_option: 1 - -// Set the letters/symbols that you want use with the 'char_name_option' option. -// Note: Don't add spaces unless you mean to add 'space' to the list. -char_name_letters: abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 - -// Restrict character deletion by BaseLevel -// 0: no restriction (players can delete characters of any level) -// -X: you can't delete chars with BaseLevel <= X -// Y: you can't delete chars with BaseLevel >= Y -// e.g. char_del_level: 80 (players can't delete characters with 80+ BaseLevel) -char_del_level: 0 - -// Amount of time in seconds by which the character deletion is delayed. -// Default: 86400 (24 hours) -// NOTE: Requires client 2010-08-03aragexeRE or newer. -char_del_delay: 86400 - -// Block deletion if character is inside a guild or a party? (BOOL) -// default: 0 official: 1 -// !!This check is imposed by Aegis to avoid dead entries in databases and _is_not_needed_ as we clear data properly!! -char_aegis_delete: 0 - -// What folder the DB files are in (item_db.conf, etc.) -db_path: db - -//================================================================== -// Pincode system -//================================================================== - -// A window is opened before you can select your character and you will have to enter a pincode by using only your mouse -// NOTE: Requires client 2011-03-09aragexeRE or newer. -// 0: disabled -// 1: enabled -pincode_enabled: 1 - -// Request Pincode only on login or on everytime char select is accessed? -// 0: only on login (default) -// 1: everytime the char select window is accessed -pincode_charselect: 0 - -// How often does a user have to change his pincode? -// Default: 0 -// 0: never -// X: every X minutes -pincode_changetime: 0 - -// How often can a user enter the wrong password? -// Default: 3 -// NOTE: The maximum on clientside is 3 -pincode_maxtry: 3 - -import: conf/import/char_conf.txt diff --git a/conf/char/char-server.conf b/conf/char/char-server.conf new file mode 100644 index 000000000..576925872 --- /dev/null +++ b/conf/char/char-server.conf @@ -0,0 +1,233 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Character Server configuration file. +//========================================================================= + +char_configuration: { + @include "conf/global/console.conf" + + // Server name, use alternative character such as ASCII 160 for spaces. + // NOTE: Do not use spaces or any of these characters which are not allowed in + // Windows filenames \/:*?"<>| + // ... or else guild emblems won't work client-side! + server_name: "Hercules" + + // Wisp name for server: used to send wisp from server to players (between 4 to 23 characters) + wisp_server_name: "Server" + + // Guild earned exp modifier. + // Adjusts taxed exp before adding it to the guild's exp. For example, + // if set to 200, the guild receives double the player's taxed exp. + guild_exp_rate: 100 + + // Information related to inter-server behavior + inter: { + // Server Communication username and password. + userid: "s1" + passwd: "p1" + // Login Server IP + // The character server connects to the login server using this IP address. + // NOTE: This is useful when you are running behind a firewall or are on + // a machine with multiple interfaces. + //login_ip: "127.0.0.1" + + // The character server listens on the interface with this IP address. + // NOTE: This allows you to run multiple servers on multiple interfaces + // while using the same ports for each server. + //bind_ip: "127.0.0.1" + + // Login Server Port + login_port: 6900 + + // Character Server IP + // The IP address which clients will use to connect. + // Set this to what your server's public IP address is. + //char_ip: "127.0.0.1" + + // Character Server Port + char_port: 6121 + } + + // Connection permission + permission: { + // Enable or disable creation of new characters. + enable_char_creation: true + + // Display (New) in the server list. + display_new: false + + // Maximum users able to connect to the server. + // Set to 0 to disable users to log-in. (-1 means unlimited) + max_connect_user: -1 + + // Group ID that is allowed to bypass the server limit of users. + // Default: -1 = nobody (there are no groups with ID < 0) + // See: conf/groups.conf + gm_allow_group: -1 + + // Type of server. + // No functional side effects at the moment. + // Displayed next to the server name in the client. + // 0=normal, 1=maintenance, 2=over 18, 3=paying, 4=F2P + server_type: 0 + + // Minimum Group ID to join char server when it is on char_server_type 1 (maintenance) + maintenance_min_group_id: 99 + } + + // Player-related configuration + player: { + new: { + // Start point (Renewal) + start_point_re: { + map: "iz_int" + x: 97 + y: 90 + } + // Start point (Pre-Renewal) + start_point_pre: { + map: "new_1-1" + x: 53 + y: 111 + } + + // Starting items for new characters + //{ + // id: Item id + // amount: Item amount + // loc: Item position, same as in item_db if you want the item to be equipped, otherwise 0 (optional) + // stackable: Is stackable? (not stackable item types: weapon, armor, egg, pet armor) + //}, + start_items: ( + { + id: 1201 // Knife + amount: 1 + loc: 2 + stackable: false + }, + { + id: 2301 // Cotton_Shirt + amount: 1 + loc: 16 + stackable: false + }, + ) + + // Starting zeny + zeny: 0 + } + + // Character name configuration + name: { + // Name used for unknown characters + unknown_char_name: "Unknown" + + // Allow or not identical name for characters but with a different case (upper/lower): + // example: Test-test-TEST-TesT; Value: 0 not allowed (default), 1 allowed + name_ignoring_case: false + + // Manage possible letters/symbol in the name of charater. Control character (0x00-0x1f) are never accepted. Possible values are: + // NOTE: Applies to character, party and guild names. + // 0: no restriction (default) + // 1: only letters/symbols in 'name_letters' option. + // 2: Letters/symbols in 'name_letters' option are forbidden. All others are possibles. + name_option: 1 + + // Set the letters/symbols that you want use with the 'char_name_option' option. + // Note: Don't add spaces unless you mean to add 'space' to the list. + name_letters: "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" + } + + deletion: { + // Restrict character deletion by BaseLevel + // 0: no restriction (players can delete characters of any level) + // -X: you can't delete chars with BaseLevel <= X + // Y: you can't delete chars with BaseLevel >= Y + // e.g. char_del_level: 80 (players can't delete characters with 80+ BaseLevel) + level: 0 + + // Amount of time in seconds by which the character deletion is delayed. + // Default: 86400 (24 hours) + // NOTE: Requires client 2010-08-03aragexeRE or newer. + delay: 86400 + + // Block deletion if character is inside a guild or a party? (BOOL) + // default: false official: true + // !!This check is imposed by Aegis to avoid dead entries in databases and _is_not_needed_ as we clear data properly!! + use_aegis_delete: false + } + + // Size for the fame-lists + fame: { + alchemist: 10 + blacksmith: 10 + taekwon: 10 + } + } + + database: { + // How often should server save all guild related information? (character save interval is defined on the map config) + // (in seconds) + autosave_time: 60 + + // What folder the DB files are in (abra_db.txt, etc.) + db_path: "db" + + // To log the character server? + log_char: true + } + + //================================================================== + // Pincode system + //================================================================== + pincode: { + // A window is opened before you can select your character and you will have to enter a pincode by using only your mouse + // NOTE: Requires client 2011-03-09aragexeRE or newer. + // 0: disabled + // 1: enabled + enabled: true + + // Request Pincode only on login or on everytime char select is accessed? + // 0: only on login (default) + // 1: everytime the char select window is accessed + request: 0 + + // How often does a user have to change his pincode? + // Default: 0 + // 0: never + // X: every X minutes + change_time: 0 + + // How often can a user enter the wrong password? + // Default: 3 + // Maximum allowed by clientside: 3 + max_tries: 3 + } + +} + +import: "conf/import/char-server.conf" diff --git a/conf/global/console.conf b/conf/global/console.conf new file mode 100644 index 000000000..d26c48352 --- /dev/null +++ b/conf/global/console.conf @@ -0,0 +1,59 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Server Console configuration file. +//========================================================================= +// This file affects how ALL server consoles work, unless explictly defined +// so in the server configuration file (See doc/global_configuration.txt +// for more information). +//========================================================================= + +console: { + //Time-stamp format which will be printed before all messages. + //Can at most be 20 characters long. + //Common formats: + // %I:%M:%S %p (hour:minute:second 12 hour, AM/PM format) + // %H:%M:%S (hour:minute:second, 24 hour format) + // %d/%b/%Y (day/Month/year) + //For full format information, consult the strftime() manual. + //timestamp_format: "[%d/%b %H:%M]" + + //If redirected output contains escape sequences (color codes) + stdout_with_ansisequence: false + + //Makes server output more silent by omitting certain types of messages: + //1: Hide Information messages + //2: Hide Status messages + //4: Hide Notice Messages + //8: Hide Warning Messages + //16: Hide Error and SQL Error messages. + //32: Hide Debug Messages + //Example: "console_silent: 7" Hides information, status and notice messages (1+2+4) + console_silent: 0 + + // [CHAR] Display information on the console whenever characters/guilds/parties/pets are loaded/saved? + save_log: true +} diff --git a/conf/import-tmpl/char-server.conf b/conf/import-tmpl/char-server.conf new file mode 100644 index 000000000..6bfb308b5 --- /dev/null +++ b/conf/import-tmpl/char-server.conf @@ -0,0 +1,32 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Character Server local configuration file. +//========================================================================= + +char_configuration: { + // See conf/char/char-server.conf for details +} diff --git a/conf/import-tmpl/char_conf.txt b/conf/import-tmpl/char_conf.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/doc/global_configuration.txt b/doc/global_configuration.txt new file mode 100644 index 000000000..23be19031 --- /dev/null +++ b/doc/global_configuration.txt @@ -0,0 +1,69 @@ +//===== Hercules Documentation =============================== +//= Global configuration reference +//===== By: ================================================== +//= Panikon (Hercules Dev. Team) +//===== Current Version: ===================================== +//= 20140616 +//===== Description: ========================================= +//= Global configurations found in /conf/global/ +//============================================================ + +- What are global configurations? + +Global configurations are configurations that can be shared between servers, +but can also be set independently in each server. + +- How do they work? + +They work by using an include system that is available with libconfig: + + "A configuration file may "include" the contents of another file using an + include directive. This directive has the effect of inlining the contents of + the named file at the point of inclusion. + + An include directive must appear on its own line in the input. It has the + form: + + @include "filename" + + Any backslashes or double quotes in the filename must be escaped as '\\' and + '\"', respectively." + From libconfig's documentation + +So each file that is included is actually inside each one of the main +configuration files and thus a change in the first will be a change in the +latter. +Note: the @include directive is read by the server executable, so any path +should be from were it is and NOT from where the main configuration file is! + +- How do I stop using global configurations? + +To stop using global configurations is very simple, all you have to do is copy +the contents that are inside the global configuration file and put them +_exactly_ where the include directive were in the main configuration file. + +E.g. + Find in any file: + @include "conf/global/sql_connection.conf" + Replace it with: + sql_connection: { + // [INTER] You can specify the codepage to use in your mySQL tables here. + // (Note that this feature requires MySQL 4.1+) + //default_codepage: "" + + // [LOGIN] Is `userid` in account_db case sensitive? + //case_sensitive: false + + // For IPs, ideally under linux, you want to use localhost instead of 127.0.0.1 + // Under windows, you want to use 127.0.0.1. If you see a message like + // "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)" + // and you have localhost, switch it to 127.0.0.1 + db_hostname: "127.0.0.1" + db_port: 3306 + db_username: "ragnarok" + db_password: "ragnarok" + db_database: "ragnarok" + //codepage:"" + } + If the main configuration file belongs to the map server, for instance, you + don't need to include default_codepage and case_sensitive. diff --git a/src/char/char.c b/src/char/char.c index 571aad566..2b5c837c5 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -42,6 +42,7 @@ #include "common/HPM.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/console.h" #include "common/core.h" #include "common/db.h" @@ -61,6 +62,7 @@ #include #include #include +#include // stat() #if MAX_MAP_SERVERS > 1 # ifdef _MSC_VER @@ -136,7 +138,16 @@ int max_connect_user = -1; int gm_allow_group = -1; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; int start_zeny = 0; -int start_items[MAX_START_ITEMS*3]; + +/// Start items for new characters +struct start_item_s { + int id; + int amount; + int loc; + bool stackable; +}; +VECTOR_DECL(struct start_item_s) start_items; + int guild_exp_rate = 100; //Custom limits for the fame lists. [Skotlex] @@ -1537,7 +1548,7 @@ int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int { char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1]; - int char_id, flag, k, l; + int char_id, flag, i; nullpo_retr(-2, sd); nullpo_retr(-2, name_); @@ -1609,24 +1620,20 @@ int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int } //Give the char the default items - for (k = 0; k < ARRAYLENGTH(start_items) && start_items[k] != 0; k += 3) { - // FIXME: How to define if an item is stackable without having to lookup itemdb? [panikon] - if( start_items[k+2] == 1 ) - { - if( SQL_ERROR == SQL->Query(inter->sql_handle, - "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `identify`) VALUES ('%d', '%d', '%d', '%d')", - inventory_db, char_id, start_items[k], start_items[k + 1], 1) ) - Sql_ShowDebug(inter->sql_handle); - } - else if( start_items[k+2] == 0 ) - { + for (i = 0; i < VECTOR_LENGTH(start_items); i++) { + struct start_item_s *item = &VECTOR_INDEX(start_items, i); + if (item->stackable) { + if (SQL_ERROR == SQL->Query(inter->sql_handle, + "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `identify`) VALUES ('%d', '%d', '%d', '%d')", + inventory_db, char_id, item->id, item->amount, 1)) + Sql_ShowDebug(inter->sql_handle); + } else { // Non-stackable items should have their own entries (issue: 7279) - for( l = 0; l < start_items[k+1]; l++ ) - { - if( SQL_ERROR == SQL->Query(inter->sql_handle, - "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `identify`) VALUES ('%d', '%d', '%d', '%d')", - inventory_db, char_id, start_items[k], 1, 1) - ) + int l, loc = item->loc; + for (l = 0; l < item->amount; l++) { + if (SQL_ERROR == SQL->Query(inter->sql_handle, + "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", + inventory_db, char_id, item->id, 1, loc, 1)) Sql_ShowDebug(inter->sql_handle); } } @@ -2176,7 +2183,7 @@ int char_parse_fromlogin_connection_state(int fd) ShowError("Can not connect to login-server.\n"); ShowError("The server communication passwords (default s1/p1) are probably invalid.\n"); ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n"); - ShowError("The communication passwords are set in /conf/map-server.conf and /conf/char-server.conf\n"); + ShowError("The communication passwords are set in /conf/map-server.conf and /conf/char/char-server.conf\n"); sockt->eof(fd); return 1; } else { @@ -5441,206 +5448,504 @@ void char_sql_config_read(const char* cfgName) ShowInfo("Done reading %s.\n", cfgName); } -void char_config_dispatch(char *w1, char *w2) { - bool (*dispatch_to[]) (char *w1, char *w2) = { - /* as many as it needs */ - pincode->config_read - }; - int i, len = ARRAYLENGTH(dispatch_to); - for(i = 0; i < len; i++) { - if( (*dispatch_to[i])(w1,w2) ) - break;/* we found who this belongs to, can stop */ +/** + * Reads the 'char_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_config_read(const char *filename, bool imported) +{ + struct config_t config; + const char *import = NULL; + bool retval = true; + + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; // Error message is already shown by libconfig->load_file + + if (!chr->config_read_top(filename, &config, imported)) + retval = false; + if (!chr->config_read_inter(filename, &config, imported)) + retval = false; + if (!chr->config_read_permission(filename, &config, imported)) + retval = false; + if (!chr->config_read_player(filename, &config, imported)) + retval = false; + if (!chr->config_read_console(filename, &config, imported)) + retval = false; + if (!chr->config_read_database(filename, &config, imported)) + retval = false; + if (!pincode->config_read(filename, &config, imported)) + retval = false; + + // TODO HPM->parseConf(w1, w2, HPCT_CHAR); + + 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->CHAR_CONF_NAME) == 0) { + ShowWarning("char_config_read: Loop detected in %s! Skipping 'import'...\n", filename); + } else { + if (!chr->config_read(import, true)) + retval = false; + } } - if (i == len) - HPM->parseConf(w1, w2, HPCT_CHAR); + + libconfig->destroy(&config); + return retval; } -int char_config_read(const char* cfgName) +/** + * Reads the 'char_configuration' top level 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_config_read_top(const char *filename, const struct config_t *config, bool imported) { - char line[1024], w1[1024], w2[1024]; - FILE* fp = fopen(cfgName, "r"); + const struct config_setting_t *setting = NULL; - if (fp == NULL) { - ShowError("Configuration file not found: %s.\n", cfgName); - return 1; + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "char_configuration")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration was not found in %s!\n", filename); + return false; + } + + // char_configuration/server_name + if (libconfig->setting_lookup_mutable_string(setting, "server_name", chr->server_name, sizeof(chr->server_name)) == CONFIG_TRUE) { + ShowInfo("server name %s\n", chr->server_name); + } else if (!imported) { + ShowWarning("char_config_read: server_name was not set! Defaulting to 'Hercules'.\n"); + safestrncpy(chr->server_name, "Hercules", sizeof(chr->server_name)); + } + // char_configuration/wisp_server_name + if (libconfig->setting_lookup_mutable_string(setting, "wisp_server_name", wisp_server_name, sizeof(wisp_server_name)) == CONFIG_TRUE) { + // wisp_server_name should _always_ be equal or bigger than 4 characters! + if (strlen(wisp_server_name) < 4) { // TODO: This length should be a #define (i.e. MIN_NAME_LENGTH) + ShowWarning("char_config_read: char_configuration/wisp_server_name is too small! Defaulting to: Server.\n"); + safestrncpy(chr->server_name, "Server", sizeof(chr->server_name)); + } + } + // char_configuration/guild_exp_rate + libconfig->setting_lookup_int(setting, "guild_exp_rate", &guild_exp_rate); + + return true; +} + +/** + * Reads the 'char_configuration/inter' 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_config_read_inter(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting = NULL; + const char *str = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "char_configuration/inter")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/inter was not found in %s!\n", filename); + return false; + } + + // Login information + libconfig->setting_lookup_mutable_string(setting, "userid", chr->userid, sizeof(chr->userid)); + libconfig->setting_lookup_mutable_string(setting, "passwd", chr->passwd, sizeof(chr->passwd)); + + // Login-server and character-server information + if (libconfig->setting_lookup_string(setting, "login_ip", &str) == CONFIG_TRUE) + chr->config_set_ip("Login server", str, &login_ip, login_ip_str); + + if (libconfig->setting_lookup_string(setting, "char_ip", &str) == CONFIG_TRUE) + chr->config_set_ip("Character server", str, &chr->ip, char_ip_str); + + if (libconfig->setting_lookup_string(setting, "bind_ip", &str) == CONFIG_TRUE) + chr->config_set_ip("Character server binding", str, &bind_ip, bind_ip_str); + + libconfig->setting_lookup_uint16(setting, "login_port", &login_port); + libconfig->setting_lookup_uint16(setting, "char_port", &chr->port); + + return true; +} + +/** + * Reads the 'char_configuration/database' 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_config_read_database(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, "char_configuration/database")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/database was not found in %s!\n", filename); + return false; + } + if (libconfig->setting_lookup_int(setting, "autosave_time", &autosave_interval) == CONFIG_TRUE) { + autosave_interval *= 1000; + if (autosave_interval <= 0) + autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; + } + libconfig->setting_lookup_mutable_string(setting, "db_path", db_path, sizeof(db_path)); + libconfig->setting_lookup_bool_real(setting, "log_char", &chr->enable_logs); + return true; +} + +/** + * Reads the 'char_configuration/console' 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_config_read_console(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "char_configuration/console")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/console was not found in %s!\n", filename); + return false; + } + libconfig->setting_lookup_bool_real(setting, "stdout_with_ansisequence", &showmsg->stdout_with_ansisequence); + libconfig->setting_lookup_bool_real(setting, "save_log", &chr->show_save_log); + 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)); + + return true; +} + +/** + * Reads the 'char_configuration/player' 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_config_read_player(const char *filename, const struct config_t *config, bool imported) +{ + bool retval = true; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if (!chr->config_read_player_new(filename, config, imported)) + retval = false; + if (!chr->config_read_player_name(filename, config, imported)) + retval = false; + if (!chr->config_read_player_deletion(filename, config, imported)) + retval = false; + if (!chr->config_read_player_fame(filename, config, imported)) + retval = false; + + return retval; +} + +/** + * Reads the 'char_configuration/player/fame' 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_config_read_player_fame(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, "char_configuration/player/fame")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/player/fame was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_int(setting, "alchemist", &fame_list_size_chemist); + if (fame_list_size_chemist > MAX_FAME_LIST) { + ShowWarning("Max fame list size is %d (fame_list_alchemist)\n", MAX_FAME_LIST); + fame_list_size_chemist = MAX_FAME_LIST; + } + + libconfig->setting_lookup_int(setting, "blacksmith", &fame_list_size_smith); + if (fame_list_size_smith > MAX_FAME_LIST) { + ShowWarning("Max fame list size is %d (fame_list_blacksmith)\n", MAX_FAME_LIST); + fame_list_size_smith = MAX_FAME_LIST; + } + + libconfig->setting_lookup_int(setting, "taekwon", &fame_list_size_taekwon); + if (fame_list_size_taekwon > MAX_FAME_LIST) { + ShowWarning("Max fame list size is %d (fame_list_taekwon)\n", MAX_FAME_LIST); + fame_list_size_taekwon = MAX_FAME_LIST; + } + + return true; +} + +/** + * Reads the 'char_configuration/player/deletion' 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_config_read_player_deletion(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, "char_configuration/player/deletion")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/player/deletion was not found in %s!\n", filename); + return false; + } + libconfig->setting_lookup_int(setting, "level", &char_del_level); + libconfig->setting_lookup_int(setting, "delay", &char_del_delay); + libconfig->setting_lookup_bool_real(setting, "use_aegis_delete", &char_aegis_delete); + + return true; +} + +/** + * Reads the 'char_configuration/player/name' 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_config_read_player_name(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, "char_configuration/player/name")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/player/name was not found in %s!\n", filename); + return false; } + libconfig->setting_lookup_mutable_string(setting, "unknown_char_name", unknown_char_name, sizeof(unknown_char_name)); + libconfig->setting_lookup_mutable_string(setting, "name_letters", char_name_letters, sizeof(char_name_letters)); + libconfig->setting_lookup_int(setting, "name_option", &char_name_option); + libconfig->setting_lookup_bool_real(setting, "name_ignoring_case", &name_ignoring_case); + + return true; +} + +/** + * Defines start_items based on '(...)/player/new/start_item'. + * + * @param setting The already retrieved start_item setting. + */ +void char_config_set_start_item(const struct config_setting_t *setting) +{ + int i, count; - while(fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') + nullpo_retv(setting); + + VECTOR_CLEAR(start_items); + + count = libconfig->setting_length(setting); + if (!count) + return; + + VECTOR_ENSURE(start_items, count, 1); + + for (i = 0; i < count; i++) { + const struct config_setting_t *t = libconfig->setting_get_elem(setting, i); + struct start_item_s start_item = { 0 }; + + if (t == NULL) continue; - if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) != 2) + if (libconfig->setting_lookup_int(t, "id", &start_item.id) != CONFIG_TRUE) { + ShowWarning("char_config_read: entry (%d) is missing id! Ignoring...\n", i); continue; + } + if (libconfig->setting_lookup_int(t, "amount", &start_item.amount) != CONFIG_TRUE) { + ShowWarning("char_config_read: entry (%d) is missing amount! Defaulting to 1...\n", i); + start_item.amount = 1; + } + if (libconfig->setting_lookup_bool_real(t, "stackable", &start_item.stackable) != CONFIG_TRUE) { + // Without knowing if the item is stackable or not we can't add it! + ShowWarning("char_config_read: entry (%d) is missing stackable! Ignoring...\n", i); + continue; + } + if (libconfig->setting_lookup_int(t, "loc", &start_item.loc) != CONFIG_TRUE) + start_item.loc = 0; + VECTOR_PUSH(start_items, start_item); + } +} - remove_control_chars(w1); - remove_control_chars(w2); - if(strcmpi(w1,"timestamp_format") == 0) { - safestrncpy(showmsg->timestamp_format, w2, sizeof(showmsg->timestamp_format)); - } 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,"stdout_with_ansisequence")==0){ - showmsg->stdout_with_ansisequence = config_switch(w2) ? true : false; - } else if (strcmpi(w1, "userid") == 0) { - safestrncpy(chr->userid, w2, sizeof(chr->userid)); - } else if (strcmpi(w1, "passwd") == 0) { - safestrncpy(chr->passwd, w2, sizeof(chr->passwd)); - } else if (strcmpi(w1, "server_name") == 0) { - safestrncpy(chr->server_name, w2, sizeof(chr->server_name)); - } else if (strcmpi(w1, "wisp_server_name") == 0) { - if (strlen(w2) >= 4) { - safestrncpy(wisp_server_name, w2, sizeof(wisp_server_name)); - } - } else if (strcmpi(w1, "login_ip") == 0) { - login_ip = sockt->host2ip(w2); - if (login_ip) { - char ip_str[16]; - safestrncpy(login_ip_str, w2, sizeof(login_ip_str)); - ShowStatus("Login server IP address : %s -> %s\n", w2, sockt->ip2str(login_ip, ip_str)); - } - } else if (strcmpi(w1, "login_port") == 0) { - login_port = atoi(w2); - } else if (strcmpi(w1, "char_ip") == 0) { - chr->ip = sockt->host2ip(w2); - if (chr->ip) { - char ip_str[16]; - safestrncpy(char_ip_str, w2, sizeof(char_ip_str)); - ShowStatus("Character server IP address : %s -> %s\n", w2, sockt->ip2str(chr->ip, ip_str)); - } - } else if (strcmpi(w1, "bind_ip") == 0) { - bind_ip = sockt->host2ip(w2); - if (bind_ip) { - char ip_str[16]; - safestrncpy(bind_ip_str, w2, sizeof(bind_ip_str)); - ShowStatus("Character server binding IP address : %s -> %s\n", w2, sockt->ip2str(bind_ip, ip_str)); - } - } else if (strcmpi(w1, "char_port") == 0) { - chr->port = atoi(w2); - } else if (strcmpi(w1, "char_server_type") == 0) { - chr->server_type = atoi(w2); - } else if (strcmpi(w1, "char_new") == 0) { - enable_char_creation = atoi(w2) ? true : false; - } else if (strcmpi(w1, "char_new_display") == 0) { - chr->new_display = atoi(w2); - } else if (strcmpi(w1, "max_connect_user") == 0) { - max_connect_user = atoi(w2); - if (max_connect_user < -1) - max_connect_user = -1; // unlimited online players - } else if(strcmpi(w1, "gm_allow_group") == 0) { - gm_allow_group = atoi(w2); - } else if (strcmpi(w1, "autosave_time") == 0) { - autosave_interval = atoi(w2) * 1000; - if (autosave_interval <= 0) - autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; - } else if (strcmpi(w1, "save_log") == 0) { - chr->show_save_log = config_switch(w2) ? true : false; +/** + * Reads the 'char_configuration/player/new' 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_config_read_player_new(const char *filename, const struct config_t *config, bool imported) +{ + const struct config_setting_t *setting = NULL, *setting2 = NULL; +#ifdef RENEWAL + const char *start_point_setting = "start_point_re"; +#else + const char *start_point_setting = "start_point_pre"; +#endif + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "char_configuration/player/new")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/player/new was not found in %s!\n", filename); + return false; + } + + if (libconfig->setting_lookup_int(setting, "zeny", &start_zeny) == CONFIG_TRUE) { + if (start_zeny > MAX_ZENY) { + ShowWarning("char_config_read: player/new/zeny is too big! Capping to MAX_ZENY.\n"); + start_zeny = MAX_ZENY; } - #ifdef RENEWAL - else if (strcmpi(w1, "start_point_re") == 0) { - char map[MAP_NAME_LENGTH_EXT]; - int x, y; - if (sscanf(w2, "%15[^,],%d,%d", map, &x, &y) < 3) - continue; - start_point.map = mapindex->name2id(map); - if (!start_point.map) - ShowError("Specified start_point_re '%s' not found in map-index cache.\n", map); - start_point.x = x; - start_point.y = y; - } - #else - else if (strcmpi(w1, "start_point_pre") == 0) { - char map[MAP_NAME_LENGTH_EXT]; - int x, y; - if (sscanf(w2, "%15[^,],%d,%d", map, &x, &y) < 3) - continue; - start_point.map = mapindex->name2id(map); - if (!start_point.map) - ShowError("Specified start_point_pre '%s' not found in map-index cache.\n", map); - start_point.x = x; - start_point.y = y; - } - #endif - else if (strcmpi(w1, "start_items") == 0) { - int i; - char *split; + } - i = 0; - split = strtok(w2, ","); - while (split != NULL && i < MAX_START_ITEMS * 3) { - char *split2 = split; - split = strtok(NULL, ","); - start_items[i] = atoi(split2); + if ((setting2 = libconfig->setting_get_member(setting, "start_items"))) + chr->config_set_start_item(setting2); - if (start_items[i] < 0) - start_items[i] = 0; + // start_point / start_point_pre + if ((setting2 = libconfig->setting_get_member(setting, start_point_setting))) { + const char *str = NULL; + if (libconfig->setting_lookup_string(setting2, "map", &str) == CONFIG_TRUE) { + start_point.map = mapindex->name2id(str); + if (start_point.map == 0) + ShowError("char_config_read_player_new: Specified start_point %s not found in map-index cache.\n", str); + libconfig->setting_lookup_int16(setting2, "x", &start_point.x); + libconfig->setting_lookup_int16(setting2, "y", &start_point.y); + } + } - ++i; - } + return true; +} - // Format is: id1,quantity1,stackable1,idN,quantityN,stackableN - if( i%3 ) - { - ShowWarning("chr->config_read: There are not enough parameters in start_items, ignoring last item...\n"); - if( i%3 == 1 ) - start_items[i-1] = 0; - else - start_items[i-2] = 0; - } - } else if (strcmpi(w1, "start_zeny") == 0) { - start_zeny = atoi(w2); - if (start_zeny < 0) - start_zeny = 0; - } else if(strcmpi(w1,"log_char") == 0) { - chr->enable_logs = atoi(w2) ? true : false; - } else if (strcmpi(w1, "unknown_char_name") == 0) { - safestrncpy(unknown_char_name, w2, sizeof(unknown_char_name)); - unknown_char_name[NAME_LENGTH-1] = '\0'; - } else if (strcmpi(w1, "name_ignoring_case") == 0) { - name_ignoring_case = (bool)config_switch(w2); - } else if (strcmpi(w1, "char_name_option") == 0) { - char_name_option = atoi(w2); - } else if (strcmpi(w1, "char_name_letters") == 0) { - safestrncpy(char_name_letters, w2, sizeof(char_name_letters)); - } else if (strcmpi(w1, "char_del_level") == 0) { //disable/enable char deletion by its level condition [Lupus] - char_del_level = atoi(w2); - } else if (strcmpi(w1, "char_del_delay") == 0) { - char_del_delay = atoi(w2); - } else if (strcmpi(w1, "char_aegis_delete") == 0) { - char_aegis_delete = atoi(w2) ? true : false; - } else if(strcmpi(w1,"db_path")==0) { - safestrncpy(db_path, w2, sizeof(db_path)); - } else if (strcmpi(w1, "fame_list_alchemist") == 0) { - fame_list_size_chemist = atoi(w2); - if (fame_list_size_chemist > MAX_FAME_LIST) { - ShowWarning("Max fame list size is %d (fame_list_alchemist)\n", MAX_FAME_LIST); - fame_list_size_chemist = MAX_FAME_LIST; - } - } else if (strcmpi(w1, "fame_list_blacksmith") == 0) { - fame_list_size_smith = atoi(w2); - if (fame_list_size_smith > MAX_FAME_LIST) { - ShowWarning("Max fame list size is %d (fame_list_blacksmith)\n", MAX_FAME_LIST); - fame_list_size_smith = MAX_FAME_LIST; - } - } else if (strcmpi(w1, "fame_list_taekwon") == 0) { - fame_list_size_taekwon = atoi(w2); - if (fame_list_size_taekwon > MAX_FAME_LIST) { - ShowWarning("Max fame list size is %d (fame_list_taekwon)\n", MAX_FAME_LIST); - fame_list_size_taekwon = MAX_FAME_LIST; - } - } else if (strcmpi(w1, "guild_exp_rate") == 0) { - guild_exp_rate = atoi(w2); - } else if (strcmpi(w1, "char_maintenance_min_group_id") == 0) { - char_maintenance_min_group_id = atoi(w2); - } else if (strcmpi(w1, "import") == 0) { - chr->config_read(w2); - } else - chr->config_dispatch(w1,w2); +/** + * Reads the 'char_configuration/permission' 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_config_read_permission(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, "char_configuration/permission")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/permission was not found in %s!\n", filename); + return false; } - fclose(fp); - ShowInfo("Done reading %s.\n", cfgName); - return 0; + libconfig->setting_lookup_bool_real(setting, "enable_char_creation", &enable_char_creation); + libconfig->setting_lookup_int16(setting, "display_new", &chr->new_display); + libconfig->setting_lookup_int(setting, "max_connect_user", &max_connect_user); + libconfig->setting_lookup_int(setting, "gm_allow_group", &gm_allow_group); + libconfig->setting_lookup_int(setting, "maintenance_min_group_id", &char_maintenance_min_group_id); + if (libconfig->setting_lookup_int(setting, "server_type", &chr->server_type) == CONFIG_TRUE) { + if (chr->server_type < CST_NORMAL || chr->server_type >= CST_MAX) { + ShowWarning("char_config_read: Invalid permission/server_type %d, defaulting to CST_NORMAL.\n", chr->server_type); + chr->server_type = CST_NORMAL; + } + } + + return true; +} + +/** + * Loads an IP into 'out_ip' and shows status. + * + * @param type[in] String containing the type of IP being set (for logging purposes). + * @param value[in] New ip value to parse. + * @param out_ip[in] Pointer to numeric value that will be changed. + * @param out_ip_str[in,out] Pointer to str value that will be changed (expected to be already initialized, to display previous value, if any). + * + * @retval false in case of error. + */ +bool char_config_set_ip(const char *type, const char *value, uint32 *out_ip, char *out_ip_str) +{ + uint32 ip = 0; + + nullpo_retr(false, type); + nullpo_retr(false, value); + nullpo_retr(false, out_ip); + nullpo_retr(false, out_ip_str); + + if ((ip = sockt->host2ip(value)) == 0) + return false; + *out_ip = ip; + + ShowStatus("%s IP address : %s -> %s\n", type, out_ip_str[0] ? out_ip_str : "0.0.0.0", sockt->ip2str(ip, NULL)); + safestrncpy(out_ip_str, value, sizeof(out_ip_str)); + return true; } int do_final(void) { @@ -5680,6 +5985,8 @@ int do_final(void) { for (i = 0; i < MAX_MAP_SERVERS; i++) VECTOR_CLEAR(chr->server[i].maps); + VECTOR_CLEAR(start_items); + aFree(chr->CHAR_CONF_NAME); aFree(chr->NET_CONF_NAME); aFree(chr->SQL_CONF_NAME); @@ -5786,11 +6093,13 @@ int do_init(int argc, char **argv) { char_load_defaults(); - chr->CHAR_CONF_NAME = aStrdup("conf/char-server.conf"); + 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"); + VECTOR_INIT(start_items); + for (i = 0; i < MAX_MAP_SERVERS; i++) VECTOR_INIT(chr->server[i].maps); @@ -5808,16 +6117,31 @@ int do_init(int argc, char **argv) { start_point.map = mapindex->name2id("new_1-1"); #endif + safestrncpy(chr->userid, "s1", sizeof(chr->userid)); + safestrncpy(chr->passwd, "p1", sizeof(chr->passwd)); + cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); - chr->config_read(chr->CHAR_CONF_NAME); + chr->config_read(chr->CHAR_CONF_NAME, false); sockt->net_config_read(chr->NET_CONF_NAME); chr->sql_config_read(chr->SQL_CONF_NAME); + { + // TODO: Remove this when no longer needed. + 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); + } + } + #ifndef BUILDBOT if (strcmp(chr->userid, "s1")==0 && strcmp(chr->passwd, "p1")==0) { ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n"); ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n"); - ShowNotice("And then change the user/password to use in conf/char-server.conf (or conf/import/char_conf.txt)\n"); + ShowNotice("And then change the user/password to use in conf/char/char-server.conf (or conf/import/char-server.conf)\n"); } #endif @@ -6101,6 +6425,17 @@ 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->config_dispatch = char_config_dispatch; chr->config_read = char_config_read; + chr->config_read_database = char_config_read_database; + chr->config_read_console = char_config_read_console; + chr->config_read_player_fame = char_config_read_player_fame; + chr->config_read_player_deletion = char_config_read_player_deletion; + chr->config_read_player_name = char_config_read_player_name; + chr->config_set_start_item = char_config_set_start_item; + chr->config_read_player_new = char_config_read_player_new; + chr->config_read_player = char_config_read_player; + chr->config_read_permission = char_config_read_permission; + chr->config_set_ip = char_config_set_ip; + chr->config_read_inter = char_config_read_inter; + chr->config_read_top = char_config_read_top; } diff --git a/src/char/char.h b/src/char/char.h index b94226859..74478b747 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -26,6 +26,10 @@ #include "common/db.h" #include "common/mmo.h" +/* Forward Declarations */ +struct config_setting_t; // common/conf.h +struct config_t; // common/conf.h + enum E_CHARSERVER_ST { CHARSERVER_ST_RUNNING = CORE_ST_LAST, CHARSERVER_ST_SHUTDOWN, @@ -276,8 +280,20 @@ struct char_interface { 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); - void (*config_dispatch) (char *w1, char *w2); - int (*config_read) (const char* cfgName); + + 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); + bool (*config_read_player_fame) (const char *filename, const struct config_t *config, bool imported); + bool (*config_read_player_deletion) (const char *filename, const struct config_t *config, bool imported); + bool (*config_read_player_name) (const char *filename, const struct config_t *config, bool imported); + void (*config_set_start_item) (const struct config_setting_t *setting); + bool (*config_read_player_new) (const char *filename, const struct config_t *config, bool imported); + bool (*config_read_player) (const char *filename, const struct config_t *config, bool imported); + bool (*config_read_permission) (const char *filename, const struct config_t *config, bool imported); + bool (*config_set_ip) (const char *type, const char *value, uint32 *out_ip, char *out_ip_str); + bool (*config_read_inter) (const char *filename, const struct config_t *config, bool imported); + bool (*config_read_top) (const char *filename, const struct config_t *config, bool imported); }; #ifdef HERCULES_CORE diff --git a/src/char/pincode.c b/src/char/pincode.c index 6930a7a57..fc1a4c037 100644 --- a/src/char/pincode.c +++ b/src/char/pincode.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 @@ -24,6 +24,7 @@ #include "char/char.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/db.h" #include "common/mmo.h" #include "common/nullpo.h" @@ -178,33 +179,52 @@ void pincode_decrypt(unsigned int userSeed, char* pin) { sprintf(pin, "%d%d%d%d", pin[0], pin[1], pin[2], pin[3]); } -bool pincode_config_read(char *w1, char *w2) { +/** + * Reads the 'char_configuration/pincode' 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 pincode_config_read(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, "char_configuration/pincode")) == NULL) { + if (imported) + return true; + ShowError("char_config_read: char_configuration/pincode was not found in %s!\n", filename); + return false; + } - nullpo_ret(w1); - nullpo_ret(w2); - while ( true ) { - if ( strcmpi(w1, "pincode_enabled") == 0 ) { - pincode->enabled = atoi(w2); + if (libconfig->setting_lookup_bool(setting, "enabled", &pincode->enabled) == CONFIG_TRUE) { #if PACKETVER < 20110309 - if( pincode->enabled ) { - ShowWarning("pincode_enabled requires PACKETVER 20110309 or higher. disabling...\n"); - pincode->enabled = 0; - } + if (pincode->enabled) { + ShowWarning("pincode_enabled requires PACKETVER 20110309 or higher. disabling...\n"); + pincode->enabled = 0; + } #endif - } else if ( strcmpi(w1, "pincode_changetime") == 0 ) { - pincode->changetime = atoi(w2)*60; - } else if ( strcmpi(w1, "pincode_maxtry") == 0 ) { - pincode->maxtry = atoi(w2); - if( pincode->maxtry > 3 ) { - ShowWarning("pincode_maxtry is too high (%d); maximum allowed: 3! capping to 3...\n", pincode->maxtry); - pincode->maxtry = 3; - } - } else if ( strcmpi(w1, "pincode_charselect") == 0 ) { - pincode->charselect = atoi(w2); - } else { - return false; + } + + if (libconfig->setting_lookup_int(setting, "change_time", &pincode->changetime) == CONFIG_TRUE) + pincode->changetime *= 60; + + if (libconfig->setting_lookup_int(setting, "max_tries", &pincode->maxtry) == CONFIG_TRUE) { + if (pincode->maxtry > 3) { + ShowWarning("pincode_maxtry is too high (%d); Maximum allowed: 3! Capping to 3...\n",pincode->maxtry); + pincode->maxtry = 3; + } + } + + if (libconfig->setting_lookup_int(setting, "request", &pincode->charselect) == CONFIG_TRUE) { + if (pincode->charselect != 1 && pincode->charselect != 0) { + ShowWarning("Invalid pincode/request! Defaulting to 0\n"); + pincode->charselect = 0; } - break; } return true; diff --git a/src/char/pincode.h b/src/char/pincode.h index fb0c1a9c4..cffaa3054 100644 --- a/src/char/pincode.h +++ b/src/char/pincode.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 @@ -23,7 +23,9 @@ #include "common/hercules.h" +/* Forward Declarations */ struct char_session_data; +struct config_t; // common/conf.h enum PincodeResponseCode { PINCODE_OK = 0, @@ -55,7 +57,7 @@ struct pincode_interface { void (*change) (int fd, struct char_session_data* sd); int (*compare) (int fd, struct char_session_data* sd, char* pin); void (*check) (int fd, struct char_session_data* sd); - bool (*config_read) (char *w1, char *w2); + bool (*config_read) (const char *filename, const struct config_t *config, bool imported); }; #ifdef HERCULES_CORE diff --git a/src/common/mmo.h b/src/common/mmo.h index 0a5d9d053..77f706f0d 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -185,9 +185,6 @@ #ifndef MAX_QUEST_OBJECTIVES #define MAX_QUEST_OBJECTIVES 3 // Max quest objectives for a quest #endif -#ifndef MAX_START_ITEMS -#define MAX_START_ITEMS 32 // Max number of items allowed to be given to a char whenever it's created. [mkbu95] -#endif // for produce #define MIN_ATTRIBUTE 0 @@ -360,7 +357,7 @@ enum equip_pos { struct point { unsigned short map; - short x,y; + int16 x, y; }; enum e_skill_flag @@ -1068,6 +1065,7 @@ enum e_char_server_type { CST_OVER18 = 2, CST_PAYING = 3, CST_F2P = 4, + CST_MAX, }; enum e_pc_reg_loading { diff --git a/tools/configconverter.pl b/tools/configconverter.pl new file mode 100755 index 000000000..2849270de --- /dev/null +++ b/tools/configconverter.pl @@ -0,0 +1,298 @@ +#!/usr/bin/perl +# +# This file is part of Hercules. +# http://herc.ws - http://github.com/HerculesWS/Hercules +# +# Copyright (C) 2016 Hercules Dev Team +# Copyright (C) 2016 Haru +# +# Hercules is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +use strict; +use warnings; + +my $silent = 0; +my $confpath = 'conf'; + +sub parse_config($$) { + my ($input, $defaults) = @_; + + my %output = (); + + for my $line (<$input>) { + chomp $line; + $line =~ s/^\s*//; $line =~ s/\s*$//; + if ($line =~ /^([a-z0-9A-Z_.]+)\s*:\s*(.*)$/) { + my ($variable, $value) = ($1, $2); + if ($defaults->{$variable}) { + next if $defaults->{$variable}->{parse}->($variable, $value, $defaults->{$variable}, \%output); + print "Error: Invalid value for setting '$variable: $value'\n"; + next; + } else { + print "Found unhandled configuration setting: '$variable: $value'\n"; + next; + } + } elsif ($line =~ m{^\s*(?://.*)?$}) { + next; + } else { + print "Error: Unable to parse line '$line'\n"; + } + } + return \%output; +} + +sub cfg_add($$$$) { + my ($variable, $value, $default, $output) = @_; + $output->{$variable} = {value => $value, print => $default->{print}, path => $default->{path}} unless $value eq $default->{default}; +} + +sub parsecfg_string($$$$) { + my ($variable, $value, $default, $output) = @_; + if ($value =~ m{\s*"((?:\\"|.)*)"\s*(?://.*)?$}i) { + cfg_add($variable, $1, $default, $output); + return 1; + } elsif ($value =~ m{\s*((?:\\"|.)*)\s*(?://.*)?$}i) { + cfg_add($variable, $1, $default, $output); + return 1; + } + return 0; +} + +sub parsecfg_int($$$$) { + my ($variable, $value, $default, $output) = @_; + if ($value =~ m{\s*(-?[0-9]+)\s*(?://.*)?$}) { + cfg_add($variable, int $1, $default, $output); + return 1; + } elsif ($value =~ m{\s*(0x[0-9A-F]+)\s*(?://.*)?$}) { + cfg_add($variable, hex $1, $default, $output); + return 1; + } elsif ($value =~ m{\s*(no|false|off)\s*(?://.*)?$}) { + cfg_add($variable, 0, $default, $output); + return 1; + } + return 0; +} + +sub parsecfg_bool($$$$) { + my ($variable, $value, $default, $output) = @_; + if ($value =~ m{\s*(yes|true|1|on)\s*(?://.*)?$}i) { + cfg_add($variable, "true", $default, $output); + return 1; + } elsif ($value =~ m{\s*(no|false|0|off)\s*(?://.*)?$}i) { + cfg_add($variable, "false", $default, $output); + return 1; + } + return 0; +} + +sub print_config($) { + my ($config) = @_; + + for my $variable (keys %$config) { + my $fullpath = $config->{$variable}->{path}; + $fullpath .= $variable if $fullpath =~ m{[:/]$}; + my ($filename, $configpath) = split(/:/, $fullpath, 2); + next unless $filename and $configpath; + my @path = split(/\//, $configpath); + next unless @path; + + my %output = (); + + my $setting = \%output; + while (scalar @path > 1) { + my $nodename = shift @path; + $setting->{$nodename} = {print => \&printcfg_tree, value => {}} unless $setting->{$nodename}; + $setting = $setting->{$nodename}->{value}; + } + $setting->{$path[0]} = {print => $config->{$variable}->{print}, value => $config->{$variable}->{value}}; + verbose("- Found setting: '$variable'.\n Please manually move the setting to '$filename.conf' as in the following example:\n", + "- '$filename.conf': (from $variable)\n"); + $output{$_}->{print}->($_, $output{$_}->{value}, 0) for keys %output; + } +} + +sub indent($$) { + my ($message, $nestlevel) = @_; + return print "\t" x ($nestlevel + 1) . $message; +} + +sub printcfg_tree($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: {\n", $nestlevel); + $value->{$_}{print}->($_, $value->{$_}{value}, $nestlevel + 1) for keys %$value; + indent("}\n", $nestlevel); +} + +sub printcfg_nil($$$) { +} + +sub printcfg_string($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: \"$value\"\n", $nestlevel); +} + +sub printcfg_int($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: $value\n", $nestlevel); +} + +sub printcfg_bool($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: $value\n", $nestlevel); +} + +sub printcfg_point($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: {\n", $nestlevel); + + my @point = split(/,/, $value, 3); + indent("map: \"$point[0]\"\n", $nestlevel + 1); + indent("x: $point[1]\n", $nestlevel + 1); + indent("y: $point[2]\n", $nestlevel + 1); + + indent("}\n", $nestlevel); +} + +sub printcfg_items($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: (\n", $nestlevel); + + my @items = split(/,/, $value); + while (scalar @items >= 3) { + my $id = shift @items; + my $amount = shift @items; + my $stackable = (shift @items) ? "true" : "false"; + indent("{\n", $nestlevel); + indent("id: $id\n", $nestlevel + 1); + indent("amount: $amount\n", $nestlevel + 1); + indent("stackable: $stackable\n", $nestlevel + 1); + indent("},\n", $nestlevel); + } + + indent(")\n", $nestlevel); +} + +sub process_conf($$) { + my ($files, $defaults) = @_; + my $found = 0; + for my $file (@$files) { + print "\nChecking $file..."; + print " Ok\n" and next unless open my $FH, '<', $file; # File not found or already converted + print " Old file is still present\n"; + my $output = parse_config($FH, $defaults); + close($FH); + my $count = scalar keys %$output; + print "$count non-default settings found."; + verbose(" The file '$file' is no longer used by Hercules and can be deleted.\n", "\n") and next unless $count; + verbose(" Please review and migrate the settings as described, then delete the file '$file', as it is no longer used by Hercules.\n", "\n"); + print_config($output); + $found = 1; + } + return $found; +} + +sub verbose($;$) { + my ($verbose_message, $silent_message) = @_; + return print $verbose_message unless $silent; + return print $silent_message if defined $silent_message; + return 1; +} + +my @defaults = ( + { + files => ['char-server.conf', 'import/char_conf.txt'], + settings => { + autosave_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/database/", default => 60}, + bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"}, + char_aegis_delete => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/player/deletion/use_aegis_delete", default => "false"}, + char_del_delay => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/deletion/delay", default => 86400}, + char_del_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/deletion/level", default => 0}, + char_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"}, + char_maintenance_min_group_id => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/maintenance_min_group_id", default => 99}, + char_name_letters => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/player/name/name_letters", default => "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"}, + char_name_option => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/name/name_option", default => 1}, + char_new => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/permission/enable_char_creation", default => "true"}, + char_new_display => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/permission/display_new", default => "false"}, + char_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/inter/", default => 6121}, + char_server_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/server_type", default => 0}, + console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0}, + db_path => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/database/", default => "db"}, + fame_list_alchemist => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/alchemist", default => 10}, + fame_list_blacksmith => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/blacksmith", default => 10}, + fame_list_taekwon => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/fame/taekwon", default => 10}, + gm_allow_group => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/", default => -1}, + guild_exp_rate => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/", default => 100}, + log_char => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/database/", default => "true"}, + login_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "127.0.0.1"}, + login_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/inter/", default => 6900}, + max_connect_user => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/permission/", default => -1}, + name_ignoring_case => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/player/name/", default => "false"}, + passwd => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "p1"}, + pincode_changetime => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/change_time", default => 0}, + pincode_charselect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/request", default => 0}, + pincode_enabled => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "char-server:char_configuration/pincode/enabled", default => "true"}, + pincode_maxtry => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/pincode/max_tries", default => 3}, + save_log => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "true"}, + server_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/", default => "Hercules"}, + start_items => {parse => \&parsecfg_string, print => \&printcfg_items, path => "char-server:char_configuration/player/new/", default => "1201,1,0,2301,1,0"}, + start_point_pre => {parse => \&parsecfg_string, print => \&printcfg_point, path => "char-server:char_configuration/player/new/", default => "new_1-1,53,111"}, + start_point_re => {parse => \&parsecfg_string, print => \&printcfg_point, path => "char-server:char_configuration/player/new/", default => "iz_int,97,90"}, + start_zeny => {parse => \&parsecfg_int, print => \&printcfg_int, path => "char-server:char_configuration/player/new/zeny", default => 0}, + stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"}, + timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"}, + unknown_char_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/player/name/", default => "Unknown"}, + userid => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/inter/", default => "s1"}, + wisp_server_name => {parse => \&parsecfg_string, print => \&printcfg_string, path => "char-server:char_configuration/", default => "Server"}, + import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/char_conf.txt"}, + } + }, +); + +for (@ARGV) { + if (/^-q$/) { $silent = 1; } + elsif (/^-v$/) { $silent = 0; } + elsif (-d) { $confpath = $_; } + else { undef $confpath } +} + +verbose(<<'EOF'); +=============== Hercules Configuration Migration Helper =============== += _ _ _ = += | | | | | | = += | |_| | ___ _ __ ___ _ _| | ___ ___ = += | _ |/ _ \ '__/ __| | | | |/ _ \/ __| = += | | | | __/ | | (__| |_| | | __/\__ \ = += \_| |_/\___|_| \___|\__,_|_|\___||___/ = +======================================================================= +This tool will assist you through the migration of the old (txt-based) +configuration files to the new (libconfig-based) format. +Please follow the displayed instructions. +======================================================================= + +EOF + +die "Usage: ./$0 [-q | -v] [path to the conf directory]\nIf no options are passed, it acts as if called as ./$0 conf\n" unless defined $confpath and -d $confpath; + +my $count = 0; +for (@defaults) { + my @files = map { $confpath . '/' . $_ } @{$_->{files}}; + $count += process_conf(\@files, $_->{settings}) +} +verbose("\nThere are no files to migrate.\n") unless $count; -- cgit v1.2.3-70-g09d2 From 9783ce1d536d0f3f5d7e34d90717a65779ff923a Mon Sep 17 00:00:00 2001 From: Haru Date: Sun, 6 Sep 2015 17:58:28 +0200 Subject: HPM Hooks Update --- src/plugins/HPMHooking/HPMHooking.Defs.inc | 34 +- .../HPMHooking/HPMHooking_char.HPMHooksCore.inc | 52 ++- .../HPMHooking/HPMHooking_char.HookingPoints.inc | 13 +- src/plugins/HPMHooking/HPMHooking_char.Hooks.inc | 359 +++++++++++++++++++-- 4 files changed, 416 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 2023730f7..52db3c182 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -660,10 +660,32 @@ typedef int (*HPMHOOK_pre_chr_online_data_cleanup) (int *tid, int64 *tick, int * typedef int (*HPMHOOK_post_chr_online_data_cleanup) (int retVal___, int tid, int64 tick, int id, intptr_t data); typedef void (*HPMHOOK_pre_chr_sql_config_read) (const char **cfgName); typedef void (*HPMHOOK_post_chr_sql_config_read) (const char *cfgName); -typedef void (*HPMHOOK_pre_chr_config_dispatch) (char **w1, char **w2); -typedef void (*HPMHOOK_post_chr_config_dispatch) (char *w1, char *w2); -typedef int (*HPMHOOK_pre_chr_config_read) (const char **cfgName); -typedef int (*HPMHOOK_post_chr_config_read) (int retVal___, const char *cfgName); +typedef bool (*HPMHOOK_pre_chr_config_read) (const char **filename, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read) (bool retVal___, const char *filename, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_database) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_database) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_console) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_console) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_player_fame) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_player_fame) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_player_deletion) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_player_deletion) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_player_name) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_player_name) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef void (*HPMHOOK_pre_chr_config_set_start_item) (const struct config_setting_t **setting); +typedef void (*HPMHOOK_post_chr_config_set_start_item) (const struct config_setting_t *setting); +typedef bool (*HPMHOOK_pre_chr_config_read_player_new) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_player_new) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_player) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_player) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_permission) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_permission) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_set_ip) (const char **type, const char **value, uint32 **out_ip, char **out_ip_str); +typedef bool (*HPMHOOK_post_chr_config_set_ip) (bool retVal___, const char *type, const char *value, uint32 *out_ip, char *out_ip_str); +typedef bool (*HPMHOOK_pre_chr_config_read_inter) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_inter) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_config_read_top) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_config_read_top) (bool retVal___, const char *filename, const struct config_t *config, bool imported); #endif // CHAR_CHAR_H #ifdef MAP_CHAT_H /* chat */ typedef bool (*HPMHOOK_pre_chat_create_pc_chat) (struct map_session_data **sd, const char **title, const char **pass, int *limit, bool *pub); @@ -5682,8 +5704,8 @@ typedef int (*HPMHOOK_pre_pincode_compare) (int *fd, struct char_session_data ** typedef int (*HPMHOOK_post_pincode_compare) (int retVal___, int fd, struct char_session_data *sd, char *pin); typedef void (*HPMHOOK_pre_pincode_check) (int *fd, struct char_session_data **sd); typedef void (*HPMHOOK_post_pincode_check) (int fd, struct char_session_data *sd); -typedef bool (*HPMHOOK_pre_pincode_config_read) (char **w1, char **w2); -typedef bool (*HPMHOOK_post_pincode_config_read) (bool retVal___, char *w1, char *w2); +typedef bool (*HPMHOOK_pre_pincode_config_read) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_pincode_config_read) (bool retVal___, const char *filename, const struct config_t *config, bool imported); #endif // CHAR_PINCODE_H #ifdef MAP_QUEST_H /* quest */ typedef void (*HPMHOOK_pre_quest_init) (bool *minimal); diff --git a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc index f51ddcffc..a2a7ce1a7 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc @@ -344,10 +344,32 @@ struct { struct HPMHookPoint *HP_chr_online_data_cleanup_post; struct HPMHookPoint *HP_chr_sql_config_read_pre; struct HPMHookPoint *HP_chr_sql_config_read_post; - struct HPMHookPoint *HP_chr_config_dispatch_pre; - struct HPMHookPoint *HP_chr_config_dispatch_post; struct HPMHookPoint *HP_chr_config_read_pre; struct HPMHookPoint *HP_chr_config_read_post; + struct HPMHookPoint *HP_chr_config_read_database_pre; + struct HPMHookPoint *HP_chr_config_read_database_post; + struct HPMHookPoint *HP_chr_config_read_console_pre; + struct HPMHookPoint *HP_chr_config_read_console_post; + struct HPMHookPoint *HP_chr_config_read_player_fame_pre; + struct HPMHookPoint *HP_chr_config_read_player_fame_post; + struct HPMHookPoint *HP_chr_config_read_player_deletion_pre; + struct HPMHookPoint *HP_chr_config_read_player_deletion_post; + struct HPMHookPoint *HP_chr_config_read_player_name_pre; + struct HPMHookPoint *HP_chr_config_read_player_name_post; + struct HPMHookPoint *HP_chr_config_set_start_item_pre; + struct HPMHookPoint *HP_chr_config_set_start_item_post; + struct HPMHookPoint *HP_chr_config_read_player_new_pre; + struct HPMHookPoint *HP_chr_config_read_player_new_post; + struct HPMHookPoint *HP_chr_config_read_player_pre; + struct HPMHookPoint *HP_chr_config_read_player_post; + struct HPMHookPoint *HP_chr_config_read_permission_pre; + struct HPMHookPoint *HP_chr_config_read_permission_post; + struct HPMHookPoint *HP_chr_config_set_ip_pre; + struct HPMHookPoint *HP_chr_config_set_ip_post; + struct HPMHookPoint *HP_chr_config_read_inter_pre; + struct HPMHookPoint *HP_chr_config_read_inter_post; + struct HPMHookPoint *HP_chr_config_read_top_pre; + struct HPMHookPoint *HP_chr_config_read_top_post; struct HPMHookPoint *HP_cmdline_init_pre; struct HPMHookPoint *HP_cmdline_init_post; struct HPMHookPoint *HP_cmdline_final_pre; @@ -1817,10 +1839,32 @@ struct { int HP_chr_online_data_cleanup_post; int HP_chr_sql_config_read_pre; int HP_chr_sql_config_read_post; - int HP_chr_config_dispatch_pre; - int HP_chr_config_dispatch_post; int HP_chr_config_read_pre; int HP_chr_config_read_post; + int HP_chr_config_read_database_pre; + int HP_chr_config_read_database_post; + int HP_chr_config_read_console_pre; + int HP_chr_config_read_console_post; + int HP_chr_config_read_player_fame_pre; + int HP_chr_config_read_player_fame_post; + int HP_chr_config_read_player_deletion_pre; + int HP_chr_config_read_player_deletion_post; + int HP_chr_config_read_player_name_pre; + int HP_chr_config_read_player_name_post; + int HP_chr_config_set_start_item_pre; + int HP_chr_config_set_start_item_post; + int HP_chr_config_read_player_new_pre; + int HP_chr_config_read_player_new_post; + int HP_chr_config_read_player_pre; + int HP_chr_config_read_player_post; + int HP_chr_config_read_permission_pre; + int HP_chr_config_read_permission_post; + int HP_chr_config_set_ip_pre; + int HP_chr_config_set_ip_post; + int HP_chr_config_read_inter_pre; + int HP_chr_config_read_inter_post; + int HP_chr_config_read_top_pre; + int HP_chr_config_read_top_post; int HP_cmdline_init_pre; int HP_cmdline_init_post; int HP_cmdline_final_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc index 4371cf81a..3c5c4fd66 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc @@ -187,8 +187,19 @@ struct HookingPointData HookingPoints[] = { { HP_POP(chr->online_data_cleanup_sub, HP_chr_online_data_cleanup_sub) }, { HP_POP(chr->online_data_cleanup, HP_chr_online_data_cleanup) }, { HP_POP(chr->sql_config_read, HP_chr_sql_config_read) }, - { HP_POP(chr->config_dispatch, HP_chr_config_dispatch) }, { HP_POP(chr->config_read, HP_chr_config_read) }, + { HP_POP(chr->config_read_database, HP_chr_config_read_database) }, + { HP_POP(chr->config_read_console, HP_chr_config_read_console) }, + { HP_POP(chr->config_read_player_fame, HP_chr_config_read_player_fame) }, + { HP_POP(chr->config_read_player_deletion, HP_chr_config_read_player_deletion) }, + { HP_POP(chr->config_read_player_name, HP_chr_config_read_player_name) }, + { HP_POP(chr->config_set_start_item, HP_chr_config_set_start_item) }, + { HP_POP(chr->config_read_player_new, HP_chr_config_read_player_new) }, + { HP_POP(chr->config_read_player, HP_chr_config_read_player) }, + { HP_POP(chr->config_read_permission, HP_chr_config_read_permission) }, + { HP_POP(chr->config_set_ip, HP_chr_config_set_ip) }, + { HP_POP(chr->config_read_inter, HP_chr_config_read_inter) }, + { HP_POP(chr->config_read_top, HP_chr_config_read_top) }, /* cmdline_interface */ { HP_POP(cmdline->init, HP_cmdline_init) }, { HP_POP(cmdline->final, HP_cmdline_final) }, diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc index aecffbecd..1676f1a2b 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc @@ -4242,14 +4242,176 @@ void HP_chr_sql_config_read(const char *cfgName) { } return; } -void HP_chr_config_dispatch(char *w1, char *w2) { +bool HP_chr_config_read(const char *filename, bool imported) { int hIndex = 0; - if( HPMHooks.count.HP_chr_config_dispatch_pre ) { - void (*preHookFunc) (char **w1, char **w2); + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_pre ) { + bool (*preHookFunc) (const char **filename, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read(filename, imported); + } + if( HPMHooks.count.HP_chr_config_read_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_database(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_database_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_database_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_database_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_database(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_database_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_database_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_database_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_console(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_console_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_console_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_console_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_console(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_console_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_console_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_console_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_player_fame(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_player_fame_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_fame_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_player_fame_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_player_fame(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_player_fame_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_fame_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_player_fame_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_player_deletion(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_player_deletion_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_deletion_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_player_deletion_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_player_deletion(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_player_deletion_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_deletion_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_player_deletion_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_player_name(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_player_name_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_dispatch_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_chr_config_dispatch_pre[hIndex].func; - preHookFunc(&w1, &w2); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_name_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_player_name_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_player_name(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_player_name_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_name_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_player_name_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +void HP_chr_config_set_start_item(const struct config_setting_t *setting) { + int hIndex = 0; + if( HPMHooks.count.HP_chr_config_set_start_item_pre ) { + void (*preHookFunc) (const struct config_setting_t **setting); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_set_start_item_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_set_start_item_pre[hIndex].func; + preHookFunc(&setting); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -4257,26 +4419,26 @@ void HP_chr_config_dispatch(char *w1, char *w2) { } } { - HPMHooks.source.chr.config_dispatch(w1, w2); + HPMHooks.source.chr.config_set_start_item(setting); } - if( HPMHooks.count.HP_chr_config_dispatch_post ) { - void (*postHookFunc) (char *w1, char *w2); - for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_dispatch_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_chr_config_dispatch_post[hIndex].func; - postHookFunc(w1, w2); + if( HPMHooks.count.HP_chr_config_set_start_item_post ) { + void (*postHookFunc) (const struct config_setting_t *setting); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_set_start_item_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_set_start_item_post[hIndex].func; + postHookFunc(setting); } } return; } -int HP_chr_config_read(const char *cfgName) { +bool HP_chr_config_read_player_new(const char *filename, const struct config_t *config, bool imported) { int hIndex = 0; - int retVal___ = 0; - if( HPMHooks.count.HP_chr_config_read_pre ) { - int (*preHookFunc) (const char **cfgName); + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_player_new_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_chr_config_read_pre[hIndex].func; - retVal___ = preHookFunc(&cfgName); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_new_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_player_new_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -4284,13 +4446,148 @@ int HP_chr_config_read(const char *cfgName) { } } { - retVal___ = HPMHooks.source.chr.config_read(cfgName); + retVal___ = HPMHooks.source.chr.config_read_player_new(filename, config, imported); } - if( HPMHooks.count.HP_chr_config_read_post ) { - int (*postHookFunc) (int retVal___, const char *cfgName); - for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_chr_config_read_post[hIndex].func; - retVal___ = postHookFunc(retVal___, cfgName); + if( HPMHooks.count.HP_chr_config_read_player_new_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_new_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_player_new_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_player(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_player_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_player_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_player(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_player_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_player_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_player_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_permission(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_permission_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_permission_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_permission_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_permission(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_permission_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_permission_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_permission_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_set_ip(const char *type, const char *value, uint32 *out_ip, char *out_ip_str) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_set_ip_pre ) { + bool (*preHookFunc) (const char **type, const char **value, uint32 **out_ip, char **out_ip_str); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_set_ip_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_set_ip_pre[hIndex].func; + retVal___ = preHookFunc(&type, &value, &out_ip, &out_ip_str); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_set_ip(type, value, out_ip, out_ip_str); + } + if( HPMHooks.count.HP_chr_config_set_ip_post ) { + bool (*postHookFunc) (bool retVal___, const char *type, const char *value, uint32 *out_ip, char *out_ip_str); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_set_ip_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_set_ip_post[hIndex].func; + retVal___ = postHookFunc(retVal___, type, value, out_ip, out_ip_str); + } + } + return retVal___; +} +bool HP_chr_config_read_inter(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_inter_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_inter_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_inter_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_inter(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_inter_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_inter_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_inter_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_config_read_top(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_config_read_top_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_top_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_config_read_top_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.config_read_top(filename, config, imported); + } + if( HPMHooks.count.HP_chr_config_read_top_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_config_read_top_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_config_read_top_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); } } return retVal___; @@ -15726,15 +16023,15 @@ void HP_pincode_check(int fd, struct char_session_data *sd) { } return; } -bool HP_pincode_config_read(char *w1, char *w2) { +bool HP_pincode_config_read(const char *filename, const struct config_t *config, bool imported) { int hIndex = 0; bool retVal___ = false; if( HPMHooks.count.HP_pincode_config_read_pre ) { - bool (*preHookFunc) (char **w1, char **w2); + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_config_read_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_pincode_config_read_pre[hIndex].func; - retVal___ = preHookFunc(&w1, &w2); + retVal___ = preHookFunc(&filename, &config, &imported); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -15742,13 +16039,13 @@ bool HP_pincode_config_read(char *w1, char *w2) { } } { - retVal___ = HPMHooks.source.pincode.config_read(w1, w2); + retVal___ = HPMHooks.source.pincode.config_read(filename, config, imported); } if( HPMHooks.count.HP_pincode_config_read_post ) { - bool (*postHookFunc) (bool retVal___, char *w1, char *w2); + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_config_read_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_pincode_config_read_post[hIndex].func; - retVal___ = postHookFunc(retVal___, w1, w2); + retVal___ = postHookFunc(retVal___, filename, config, imported); } } return retVal___; -- cgit v1.2.3-70-g09d2 From ea9ceb17bdf4ea4acf28dca84508b62bd7e94fd4 Mon Sep 17 00:00:00 2001 From: Haru Date: Mon, 7 Sep 2015 01:42:31 +0200 Subject: Ported inter-server.conf to libconfig Ported to modern Hercules and cleaned up from Panikon's commits: 40f9ec33868e2240cab013308897898ed252b3e0, a9d646da19e25ab6fcf44dbd1ae7d90c30f6686c, 1aa8581a0aecbfd53e877686c399ffb731dcd75e, 72c645b015ae6130ca7d4309d0fb1413340e7f23, f8c906a0496b9acdae1d8244b1544fa03592061e, 51d88a58983c9552dfd1a0f059e5a031742aed61, 443684b3c77f4c32fe7877a7f8d62debf73b1e93, cf93eafef1f322cd1583226272b7d4008f562da4 Signed-off-by: Haru --- .gitignore | 1 - conf/char/char-server.conf | 1 + conf/common/inter-server.conf | 119 ++++++++++++++++ conf/global/sql_connection.conf | 49 +++++++ conf/import-tmpl/inter-server.conf | 32 +++++ conf/import-tmpl/inter_conf.txt | 0 conf/inter-server.conf | 125 ----------------- src/char/char.c | 279 ++++++++++++++++++++++++------------- src/char/char.h | 5 +- src/char/inter.c | 114 +++++++++------ src/char/inter.h | 6 +- src/common/sql.c | 96 +++++++------ src/common/sql.h | 2 +- src/map/map.c | 174 +++++++++++++++-------- src/map/map.h | 7 +- src/map/mapreg.h | 6 +- src/map/mapreg_sql.c | 21 ++- tools/configconverter.pl | 77 ++++++++++ 18 files changed, 738 insertions(+), 376 deletions(-) create mode 100644 conf/common/inter-server.conf create mode 100644 conf/global/sql_connection.conf create mode 100644 conf/import-tmpl/inter-server.conf delete mode 100644 conf/import-tmpl/inter_conf.txt delete mode 100644 conf/inter-server.conf (limited to 'src') diff --git a/.gitignore b/.gitignore index 5eccd9969..3302e44cf 100644 --- a/.gitignore +++ b/.gitignore @@ -61,7 +61,6 @@ Thumbs.db # /conf/ /conf/import/*.conf /conf/import/battle_conf.txt -/conf/import/inter_conf.txt /conf/import/log_conf.txt /conf/import/login_conf.txt /conf/import/map_conf.txt diff --git a/conf/char/char-server.conf b/conf/char/char-server.conf index 576925872..4c6ef0348 100644 --- a/conf/char/char-server.conf +++ b/conf/char/char-server.conf @@ -29,6 +29,7 @@ char_configuration: { @include "conf/global/console.conf" + @include "conf/global/sql_connection.conf" // Server name, use alternative character such as ASCII 160 for spaces. // NOTE: Do not use spaces or any of these characters which are not allowed in diff --git a/conf/common/inter-server.conf b/conf/common/inter-server.conf new file mode 100644 index 000000000..fd55b27e5 --- /dev/null +++ b/conf/common/inter-server.conf @@ -0,0 +1,119 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Hercules Inter Server configuration file. +//========================================================================= +// Settings that are shared by more than one of the main servers +//========================================================================= + +inter_configuration: { + // Level range for sharing within a party + party_share_level: 15 // FIXME: Split RE and pre-RE + + // Log configuration + log: { + // Log Inter Connections, etc.? + log_inter: true + + // Inter Log Filename + inter_log_filename: "log/inter.log" + + // Log database SQL connection + @include "conf/global/sql_connection.conf" + } + + mysql_reconnect: { + // == MySQL Reconnect Settings + // =========================== + // - mysql_reconnect_type + // - 1: when mysql disconnects during runtime, the server tries to reconnect mysql_reconnect_count times and, + // -- if unsuccessful, the server is shut down + // - 2: when mysql disconnects during runtime it tries to reconnect indefinitely + type: 2 + + // - mysql_reconnect_count + // - number of reconnect attempts the server should do when the database disconnects during runtime + // - only used when mysql_reconnect_type is 1 + count: 1 + } + + // ALL MySQL Database Table names + // DO NOT CHANGE ANYTHING BEYOND THIS LINE UNLESS YOU KNOW YOUR DATABASE DAMN WELL + // this is meant for people who KNOW their stuff, and for some reason want to change their + // database layout. [CLOWNISIUS] + database_names: { + char_db: "char" + interlog_db: "interlog" + ragsrvinfo_db: "ragsrvinfo" + registry: { + acc_reg_num_db: "acc_reg_num_db" + acc_reg_str_db: "acc_reg_str_db" + char_reg_str_db: "char_reg_str_db" + char_reg_num_db: "char_reg_num_db" + + global_acc_reg_num_db: "global_acc_reg_num_db" + global_acc_reg_str_db: "global_acc_reg_str_db" + } + pc: { + hotkey_db: "hotkey" + scdata_db: "sc_data" + cart_db: "cart_inventory" + inventory_db: "inventory" + charlog_db: "charlog" + storage_db: "storage" + skill_db: "skill" + memo_db: "memo" + party_db: "party" + pet_db: "pet" + friend_db: "friends" + mail_db: "mail" + auction_db: "auction" + quest_db: "quest" + homunculus_db: "homunculus" + skill_homunculus_db: "skill_homunculus" + mercenary_db: "mercenary" + mercenary_owner_db: "mercenary_owner" + elemental_db: "elemental" + account_data_db: "account_data" + } + guild: { + main_db: "guild" + alliance_db: "guild_alliance" + castle_db: "guild_castle" + expulsion_db: "guild_expulsion" + member_db: "guild_member" + skill_db: "guild_skill" + position_db: "guild_position" + storage_db: "guild_storage" + } + mapreg_db: "mapreg" + autotrade_merchants_db: "autotrade_merchants" + autotrade_data_db: "autotrade_data" + npc_market_data_db: "npc_market_data" + } +} + +import: "conf/import/inter-server.conf" diff --git a/conf/global/sql_connection.conf b/conf/global/sql_connection.conf new file mode 100644 index 000000000..58c9e6d08 --- /dev/null +++ b/conf/global/sql_connection.conf @@ -0,0 +1,49 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= SQL connection configuration file. +//========================================================================= +// This file affects how ALL server sql connections work, unless explictly +// defined so in the server configuration file (See +// doc/global_configuration.txt for more information). +//========================================================================= + +sql_connection: { + // [INTER] You can specify the codepage to use in your mySQL tables here. + // (Note that this feature requires MySQL 4.1+) + //default_codepage: "" + + // For IPs, ideally under linux, you want to use localhost instead of 127.0.0.1. + // Under windows, you want to use 127.0.0.1. If you see a message like + // "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)" + // and you have localhost, switch it to 127.0.0.1 + db_hostname: "127.0.0.1" + db_port: 3306 + db_username: "ragnarok" + db_password: "ragnarok" + db_database: "ragnarok" + //codepage:"" +} diff --git a/conf/import-tmpl/inter-server.conf b/conf/import-tmpl/inter-server.conf new file mode 100644 index 000000000..243dda4ea --- /dev/null +++ b/conf/import-tmpl/inter-server.conf @@ -0,0 +1,32 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Hercules Inter Server local configuration file. +//========================================================================= + +inter_configuration: { + // See conf/common/inter-server.conf +} diff --git a/conf/import-tmpl/inter_conf.txt b/conf/import-tmpl/inter_conf.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/conf/inter-server.conf b/conf/inter-server.conf deleted file mode 100644 index 704d5fc12..000000000 --- a/conf/inter-server.conf +++ /dev/null @@ -1,125 +0,0 @@ -// Hercules InterServer (settings shared/used by more than 1 server) configuration. - -// Options for both versions - -// Log Inter Connections, etc.? -log_inter: 1 - -// Inter Log Filename -inter_log_filename: log/inter.log - -// Level range for sharing within a party -party_share_level: 15 - -// SQL version options only - -// You can specify the codepage to use in your mySQL tables here. -// (Note that this feature requires MySQL 4.1+) -//default_codepage: - - -// For IPs, ideally under linux, you want to use localhost instead of 127.0.0.1 -// Under windows, you want to use 127.0.0.1. If you see a message like -// "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)" -// and you have localhost, switch it to 127.0.0.1 - -// Global SQL settings -// overridden by local settings when the hostname is defined there -// (currently only the login-server reads/obeys these settings) -sql.db_hostname: 127.0.0.1 -sql.db_port: 3306 -sql.db_username: ragnarok -sql.db_password: ragnarok -sql.db_database: ragnarok -sql.codepage: - -// MySQL Character SQL server -char_server_ip: 127.0.0.1 -char_server_port: 3306 -char_server_id: ragnarok -char_server_pw: ragnarok -char_server_db: ragnarok - -// MySQL Map SQL Server -map_server_ip: 127.0.0.1 -map_server_port: 3306 -map_server_id: ragnarok -map_server_pw: ragnarok -map_server_db: ragnarok - -// MySQL Log SQL Database -log_db_ip: 127.0.0.1 -log_db_port: 3306 -log_db_id: ragnarok -log_db_pw: ragnarok -log_db_db: ragnarok -log_codepage: -log_login_db: loginlog - -// == MySQL Reconnect Settings -// =========================== -// - mysql_reconnect_type -// - 1: when mysql disconnects during runtime, the server tries to reconnect mysql_reconnect_count times and, -// -- if unsuccessful, the server is shut down -// - 2: when mysql disconnects during runtime it tries to reconnect indefinitely -mysql_reconnect_type:2 -// - mysql_reconnect_count -// - number of reconnect attempts the server should do when the database disconnects during runtime -// - only used when mysql_reconnect_type is 1 -mysql_reconnect_count:1 - -// DO NOT CHANGE ANYTHING BEYOND THIS LINE UNLESS YOU KNOW YOUR DATABASE DAMN WELL -// this is meant for people who KNOW their stuff, and for some reason want to change their -// database layout. [CLOWNISIUS] - -// ALL MySQL Database Table names - -//Shared -interreg_db: interreg -global_acc_reg_num_db: global_acc_reg_num_db -global_acc_reg_str_db: global_acc_reg_str_db - -// Char Database Tables -char_db: char -hotkey_db: hotkey -scdata_db: sc_data -cart_db: cart_inventory -inventory_db: inventory -charlog_db: charlog -storage_db: storage -skill_db: skill -interlog_db: interlog -memo_db: memo -guild_db: guild -guild_alliance_db: guild_alliance -guild_castle_db: guild_castle -guild_expulsion_db: guild_expulsion -guild_member_db: guild_member -guild_skill_db: guild_skill -guild_position_db: guild_position -guild_storage_db: guild_storage -party_db: party -pet_db: pet -friend_db: friends -mail_db: mail -auction_db: auction -quest_db: quest -homunculus_db: homunculus -skill_homunculus_db: skill_homunculus -mercenary_db: mercenary -mercenary_owner_db: mercenary_owner -ragsrvinfo_db: ragsrvinfo -elemental_db: elemental -account_data_db: account_data -acc_reg_num_db: acc_reg_num_db -acc_reg_str_db: acc_reg_str_db -char_reg_str_db: char_reg_str_db -char_reg_num_db: char_reg_num_db - -// Map Database Tables -mapreg_db: mapreg -autotrade_merchants_db: autotrade_merchants -autotrade_data_db: autotrade_data -npc_market_data_db: npc_market_data - -import: conf/import/inter_conf.txt 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; diff --git a/tools/configconverter.pl b/tools/configconverter.pl index 2849270de..c49dc95d9 100755 --- a/tools/configconverter.pl +++ b/tools/configconverter.pl @@ -263,6 +263,83 @@ my @defaults = ( import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/char_conf.txt"}, } }, + { + files => ['inter-server.conf', 'import/inter_conf.txt'], + settings => { + party_share_level => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/", default => 15}, + log_inter => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "inter-server:inter_configuration/log/", default => "true"}, + inter_log_filename => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/log/", default => "log/inter.log"}, + mysql_reconnect_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/type", default => 2}, + mysql_reconnect_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/count", default => 1}, + log_login_db => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "inter-server:inter_configuration/database_names/login_db", default => "loginlog"}, + char_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "char"}, + interlog_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "interlog"}, + ragsrvinfo_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "ragsrvinfo"}, + acc_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "acc_reg_num_db"}, + acc_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "acc_reg_str_db"}, + char_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "char_reg_num_db"}, + char_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "char_reg_str_db"}, + global_acc_reg_num_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "global_acc_reg_num_db"}, + global_acc_reg_str_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/registry/", default => "global_acc_reg_str_db"}, + hotkey_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "hotkey"}, + scdata_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "sc_data"}, + cart_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "cart_inventory"}, + inventory_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "inventory"}, + charlog_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "charlog"}, + storage_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "storage"}, + skill_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "skill"}, + memo_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "memo"}, + party_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "party"}, + pet_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "pet"}, + friend_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "friends"}, + mail_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mail"}, + auction_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "auction"}, + quest_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "quest"}, + homunculus_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "homunculus"}, + skill_homunculus_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "skill_homunculus"}, + mercenary_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mercenary"}, + mercenary_owner_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "mercenary_owner"}, + elemental_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "elemental"}, + account_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/pc/", default => "account_data"}, + guild_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/main_db", default => "guild"}, + guild_alliance_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/alliance_db", default => "guild_alliance"}, + guild_castle_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/castle_db", default => "guild_castle"}, + guild_expulsion_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/expulsion_db", default => "guild_expulsion"}, + guild_member_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/member_db", default => "guild_member"}, + guild_skill_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/skill_db", default => "guild_skill"}, + guild_position_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/position_db", default => "guild_position"}, + guild_storage_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/guild/storage_db", default => "guild_storage"}, + mapreg_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "mapreg"}, + autotrade_merchants_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "autotrade_merchants"}, + autotrade_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "autotrade_data"}, + npc_market_data_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "npc_market_data"}, + default_codepage => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/", default => ""}, + 'sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + char_server_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + map_server_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + log_db_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + 'sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + char_server_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + map_server_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + log_db_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + 'sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + char_server_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + map_server_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + log_db_id => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + 'sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + char_server_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + map_server_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + log_db_pw => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + 'sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + char_server_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + map_server_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + log_db_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + 'sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + log_codepage => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + interreg_db => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "interreg"}, + import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/inter_conf.txt"}, + } + }, ); for (@ARGV) { -- cgit v1.2.3-70-g09d2 From 3c84a4df688a63577236d02b4d972775964f71ca Mon Sep 17 00:00:00 2001 From: Haru Date: Mon, 7 Sep 2015 01:39:50 +0200 Subject: HPM Hooks Update --- src/plugins/HPMHooking/HPMHooking.Defs.inc | 28 +++- .../HPMHooking/HPMHooking_char.HPMHooksCore.inc | 24 ++- .../HPMHooking/HPMHooking_char.HookingPoints.inc | 6 +- src/plugins/HPMHooking/HPMHooking_char.Hooks.inc | 179 +++++++++++++++++---- .../HPMHooking/HPMHooking_map.HPMHooksCore.inc | 8 + .../HPMHooking/HPMHooking_map.HookingPoints.inc | 2 + src/plugins/HPMHooking/HPMHooking_map.Hooks.inc | 80 +++++++-- 7 files changed, 266 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 52db3c182..31571f724 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -658,8 +658,14 @@ typedef int (*HPMHOOK_pre_chr_online_data_cleanup_sub) (union DBKey *key, struct typedef int (*HPMHOOK_post_chr_online_data_cleanup_sub) (int retVal___, union DBKey key, struct DBData *data, va_list ap); typedef int (*HPMHOOK_pre_chr_online_data_cleanup) (int *tid, int64 *tick, int *id, intptr_t *data); typedef int (*HPMHOOK_post_chr_online_data_cleanup) (int retVal___, int tid, int64 tick, int id, intptr_t data); -typedef void (*HPMHOOK_pre_chr_sql_config_read) (const char **cfgName); -typedef void (*HPMHOOK_post_chr_sql_config_read) (const char *cfgName); +typedef bool (*HPMHOOK_pre_chr_sql_config_read) (const char **filename, bool *imported); +typedef bool (*HPMHOOK_post_chr_sql_config_read) (bool retVal___, const char *filename, bool imported); +typedef bool (*HPMHOOK_pre_chr_sql_config_read_registry) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_sql_config_read_registry) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_sql_config_read_pc) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_sql_config_read_pc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_chr_sql_config_read_guild) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_chr_sql_config_read_guild) (bool retVal___, const char *filename, const struct config_t *config, bool imported); typedef bool (*HPMHOOK_pre_chr_config_read) (const char **filename, bool *imported); typedef bool (*HPMHOOK_post_chr_config_read) (bool retVal___, const char *filename, bool imported); typedef bool (*HPMHOOK_pre_chr_config_read_database) (const char **filename, const struct config_t **config, bool *imported); @@ -2850,8 +2856,6 @@ typedef void (*HPMHOOK_pre_inter_savereg) (int *account_id, int *char_id, const typedef void (*HPMHOOK_post_inter_savereg) (int account_id, int char_id, const char *key, unsigned int index, intptr_t val, bool is_string); typedef int (*HPMHOOK_pre_inter_accreg_fromsql) (int *account_id, int *char_id, int *fd, int *type); typedef int (*HPMHOOK_post_inter_accreg_fromsql) (int retVal___, int account_id, int char_id, int fd, int type); -typedef int (*HPMHOOK_pre_inter_config_read) (const char **cfgName); -typedef int (*HPMHOOK_post_inter_config_read) (int retVal___, const char *cfgName); typedef int (*HPMHOOK_pre_inter_vlog) (char **fmt, va_list ap); typedef int (*HPMHOOK_post_inter_vlog) (int retVal___, char *fmt, va_list ap); typedef int (*HPMHOOK_pre_inter_init_sql) (const char **file); @@ -2868,6 +2872,10 @@ typedef int (*HPMHOOK_pre_inter_parse_frommap) (int *fd); typedef int (*HPMHOOK_post_inter_parse_frommap) (int retVal___, int fd); typedef void (*HPMHOOK_pre_inter_final) (void); typedef void (*HPMHOOK_post_inter_final) (void); +typedef bool (*HPMHOOK_pre_inter_config_read) (const char **filename, bool *imported); +typedef bool (*HPMHOOK_post_inter_config_read) (bool retVal___, const char *filename, bool imported); +typedef bool (*HPMHOOK_pre_inter_config_read_connection) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_inter_config_read_connection) (bool retVal___, const char *filename, const struct config_t *config, bool imported); #endif // CHAR_INTER_H #ifdef CHAR_INT_MAIL_H /* inter_mail */ typedef int (*HPMHOOK_pre_inter_mail_sql_init) (void); @@ -4034,8 +4042,12 @@ typedef int (*HPMHOOK_pre_map_config_read_sub) (char **cfgName); typedef int (*HPMHOOK_post_map_config_read_sub) (int retVal___, char *cfgName); typedef void (*HPMHOOK_pre_map_reloadnpc_sub) (char **cfgName); typedef void (*HPMHOOK_post_map_reloadnpc_sub) (char *cfgName); -typedef int (*HPMHOOK_pre_map_inter_config_read) (char **cfgName); -typedef int (*HPMHOOK_post_map_inter_config_read) (int retVal___, char *cfgName); +typedef bool (*HPMHOOK_pre_map_inter_config_read) (const char **filename, bool *imported); +typedef bool (*HPMHOOK_post_map_inter_config_read) (bool retVal___, const char *filename, bool imported); +typedef bool (*HPMHOOK_pre_map_inter_config_read_database_names) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_map_inter_config_read_database_names) (bool retVal___, const char *filename, const struct config_t *config, bool imported); +typedef bool (*HPMHOOK_pre_map_inter_config_read_connection) (const char **filename, const struct config_t **config, bool *imported); +typedef bool (*HPMHOOK_post_map_inter_config_read_connection) (bool retVal___, const char *filename, const struct config_t *config, bool imported); typedef int (*HPMHOOK_pre_map_sql_init) (void); typedef int (*HPMHOOK_post_map_sql_init) (int retVal___); typedef int (*HPMHOOK_pre_map_sql_close) (void); @@ -4470,8 +4482,8 @@ typedef int (*HPMHOOK_pre_mapreg_destroyreg) (union DBKey *key, struct DBData ** typedef int (*HPMHOOK_post_mapreg_destroyreg) (int retVal___, union DBKey key, struct DBData *data, va_list ap); typedef void (*HPMHOOK_pre_mapreg_reload) (void); typedef void (*HPMHOOK_post_mapreg_reload) (void); -typedef bool (*HPMHOOK_pre_mapreg_config_read) (const char **w1, const char **w2); -typedef bool (*HPMHOOK_post_mapreg_config_read) (bool retVal___, const char *w1, const char *w2); +typedef bool (*HPMHOOK_pre_mapreg_config_read) (const char **filename, const struct config_setting_t **config, bool *imported); +typedef bool (*HPMHOOK_post_mapreg_config_read) (bool retVal___, const char *filename, const struct config_setting_t *config, bool imported); #endif // MAP_MAPREG_H #ifdef COMMON_MD5CALC_H /* md5 */ typedef void (*HPMHOOK_pre_md5_string) (const char **string, char **output); diff --git a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc index a2a7ce1a7..44b56143f 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc @@ -344,6 +344,12 @@ struct { struct HPMHookPoint *HP_chr_online_data_cleanup_post; struct HPMHookPoint *HP_chr_sql_config_read_pre; struct HPMHookPoint *HP_chr_sql_config_read_post; + struct HPMHookPoint *HP_chr_sql_config_read_registry_pre; + struct HPMHookPoint *HP_chr_sql_config_read_registry_post; + struct HPMHookPoint *HP_chr_sql_config_read_pc_pre; + struct HPMHookPoint *HP_chr_sql_config_read_pc_post; + struct HPMHookPoint *HP_chr_sql_config_read_guild_pre; + struct HPMHookPoint *HP_chr_sql_config_read_guild_post; struct HPMHookPoint *HP_chr_config_read_pre; struct HPMHookPoint *HP_chr_config_read_post; struct HPMHookPoint *HP_chr_config_read_database_pre; @@ -528,8 +534,6 @@ struct { struct HPMHookPoint *HP_inter_savereg_post; struct HPMHookPoint *HP_inter_accreg_fromsql_pre; struct HPMHookPoint *HP_inter_accreg_fromsql_post; - struct HPMHookPoint *HP_inter_config_read_pre; - struct HPMHookPoint *HP_inter_config_read_post; struct HPMHookPoint *HP_inter_vlog_pre; struct HPMHookPoint *HP_inter_vlog_post; struct HPMHookPoint *HP_inter_init_sql_pre; @@ -546,6 +550,10 @@ struct { struct HPMHookPoint *HP_inter_parse_frommap_post; struct HPMHookPoint *HP_inter_final_pre; struct HPMHookPoint *HP_inter_final_post; + struct HPMHookPoint *HP_inter_config_read_pre; + struct HPMHookPoint *HP_inter_config_read_post; + struct HPMHookPoint *HP_inter_config_read_connection_pre; + struct HPMHookPoint *HP_inter_config_read_connection_post; struct HPMHookPoint *HP_inter_mail_sql_init_pre; struct HPMHookPoint *HP_inter_mail_sql_init_post; struct HPMHookPoint *HP_inter_mail_sql_final_pre; @@ -1839,6 +1847,12 @@ struct { int HP_chr_online_data_cleanup_post; int HP_chr_sql_config_read_pre; int HP_chr_sql_config_read_post; + int HP_chr_sql_config_read_registry_pre; + int HP_chr_sql_config_read_registry_post; + int HP_chr_sql_config_read_pc_pre; + int HP_chr_sql_config_read_pc_post; + int HP_chr_sql_config_read_guild_pre; + int HP_chr_sql_config_read_guild_post; int HP_chr_config_read_pre; int HP_chr_config_read_post; int HP_chr_config_read_database_pre; @@ -2023,8 +2037,6 @@ struct { int HP_inter_savereg_post; int HP_inter_accreg_fromsql_pre; int HP_inter_accreg_fromsql_post; - int HP_inter_config_read_pre; - int HP_inter_config_read_post; int HP_inter_vlog_pre; int HP_inter_vlog_post; int HP_inter_init_sql_pre; @@ -2041,6 +2053,10 @@ struct { int HP_inter_parse_frommap_post; int HP_inter_final_pre; int HP_inter_final_post; + int HP_inter_config_read_pre; + int HP_inter_config_read_post; + int HP_inter_config_read_connection_pre; + int HP_inter_config_read_connection_post; int HP_inter_mail_sql_init_pre; int HP_inter_mail_sql_init_post; int HP_inter_mail_sql_final_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc index 3c5c4fd66..35f9044d5 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc @@ -187,6 +187,9 @@ struct HookingPointData HookingPoints[] = { { HP_POP(chr->online_data_cleanup_sub, HP_chr_online_data_cleanup_sub) }, { HP_POP(chr->online_data_cleanup, HP_chr_online_data_cleanup) }, { HP_POP(chr->sql_config_read, HP_chr_sql_config_read) }, + { HP_POP(chr->sql_config_read_registry, HP_chr_sql_config_read_registry) }, + { HP_POP(chr->sql_config_read_pc, HP_chr_sql_config_read_pc) }, + { HP_POP(chr->sql_config_read_guild, HP_chr_sql_config_read_guild) }, { HP_POP(chr->config_read, HP_chr_config_read) }, { HP_POP(chr->config_read_database, HP_chr_config_read_database) }, { HP_POP(chr->config_read_console, HP_chr_config_read_console) }, @@ -290,7 +293,6 @@ struct HookingPointData HookingPoints[] = { { HP_POP(inter->vmsg_to_fd, HP_inter_vmsg_to_fd) }, { HP_POP(inter->savereg, HP_inter_savereg) }, { HP_POP(inter->accreg_fromsql, HP_inter_accreg_fromsql) }, - { HP_POP(inter->config_read, HP_inter_config_read) }, { HP_POP(inter->vlog, HP_inter_vlog) }, { HP_POP(inter->init_sql, HP_inter_init_sql) }, { HP_POP(inter->mapif_init, HP_inter_mapif_init) }, @@ -299,6 +301,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(inter->check_length, HP_inter_check_length) }, { HP_POP(inter->parse_frommap, HP_inter_parse_frommap) }, { HP_POP(inter->final, HP_inter_final) }, + { HP_POP(inter->config_read, HP_inter_config_read) }, + { HP_POP(inter->config_read_connection, HP_inter_config_read_connection) }, /* inter_mail_interface */ { HP_POP(inter_mail->sql_init, HP_inter_mail_sql_init) }, { HP_POP(inter_mail->sql_final, HP_inter_mail_sql_final) }, diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc index 1676f1a2b..3669b2da8 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc @@ -4216,31 +4216,113 @@ int HP_chr_online_data_cleanup(int tid, int64 tick, int id, intptr_t data) { } return retVal___; } -void HP_chr_sql_config_read(const char *cfgName) { +bool HP_chr_sql_config_read(const char *filename, bool imported) { int hIndex = 0; + bool retVal___ = false; if( HPMHooks.count.HP_chr_sql_config_read_pre ) { - void (*preHookFunc) (const char **cfgName); + bool (*preHookFunc) (const char **filename, bool *imported); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_chr_sql_config_read_pre[hIndex].func; - preHookFunc(&cfgName); + retVal___ = preHookFunc(&filename, &imported); } if( *HPMforce_return ) { *HPMforce_return = false; - return; + return retVal___; } } { - HPMHooks.source.chr.sql_config_read(cfgName); + retVal___ = HPMHooks.source.chr.sql_config_read(filename, imported); } if( HPMHooks.count.HP_chr_sql_config_read_post ) { - void (*postHookFunc) (const char *cfgName); + bool (*postHookFunc) (bool retVal___, const char *filename, bool imported); for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_chr_sql_config_read_post[hIndex].func; - postHookFunc(cfgName); + retVal___ = postHookFunc(retVal___, filename, imported); } } - return; + return retVal___; +} +bool HP_chr_sql_config_read_registry(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_sql_config_read_registry_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_registry_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_sql_config_read_registry_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.sql_config_read_registry(filename, config, imported); + } + if( HPMHooks.count.HP_chr_sql_config_read_registry_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_registry_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_sql_config_read_registry_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_sql_config_read_pc(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_sql_config_read_pc_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_pc_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_sql_config_read_pc_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.sql_config_read_pc(filename, config, imported); + } + if( HPMHooks.count.HP_chr_sql_config_read_pc_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_pc_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_sql_config_read_pc_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_chr_sql_config_read_guild(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_chr_sql_config_read_guild_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_guild_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_sql_config_read_guild_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.sql_config_read_guild(filename, config, imported); + } + if( HPMHooks.count.HP_chr_sql_config_read_guild_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_sql_config_read_guild_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_sql_config_read_guild_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; } bool HP_chr_config_read(const char *filename, bool imported) { int hIndex = 0; @@ -6724,33 +6806,6 @@ int HP_inter_accreg_fromsql(int account_id, int char_id, int fd, int type) { } return retVal___; } -int HP_inter_config_read(const char *cfgName) { - int hIndex = 0; - int retVal___ = 0; - if( HPMHooks.count.HP_inter_config_read_pre ) { - int (*preHookFunc) (const char **cfgName); - *HPMforce_return = false; - for(hIndex = 0; hIndex < HPMHooks.count.HP_inter_config_read_pre; hIndex++ ) { - preHookFunc = HPMHooks.list.HP_inter_config_read_pre[hIndex].func; - retVal___ = preHookFunc(&cfgName); - } - if( *HPMforce_return ) { - *HPMforce_return = false; - return retVal___; - } - } - { - retVal___ = HPMHooks.source.inter.config_read(cfgName); - } - if( HPMHooks.count.HP_inter_config_read_post ) { - int (*postHookFunc) (int retVal___, const char *cfgName); - for(hIndex = 0; hIndex < HPMHooks.count.HP_inter_config_read_post; hIndex++ ) { - postHookFunc = HPMHooks.list.HP_inter_config_read_post[hIndex].func; - retVal___ = postHookFunc(retVal___, cfgName); - } - } - return retVal___; -} int HP_inter_vlog(char *fmt, va_list ap) { int hIndex = 0; int retVal___ = 0; @@ -6978,6 +7033,60 @@ void HP_inter_final(void) { } return; } +bool HP_inter_config_read(const char *filename, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_inter_config_read_pre ) { + bool (*preHookFunc) (const char **filename, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_inter_config_read_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_inter_config_read_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.inter.config_read(filename, imported); + } + if( HPMHooks.count.HP_inter_config_read_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_inter_config_read_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_inter_config_read_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, imported); + } + } + return retVal___; +} +bool HP_inter_config_read_connection(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_inter_config_read_connection_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_inter_config_read_connection_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_inter_config_read_connection_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.inter.config_read_connection(filename, config, imported); + } + if( HPMHooks.count.HP_inter_config_read_connection_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_inter_config_read_connection_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_inter_config_read_connection_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} /* inter_mail_interface */ int HP_inter_mail_sql_init(void) { int hIndex = 0; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index 06c4acc50..b4a0087e2 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -3240,6 +3240,10 @@ struct { struct HPMHookPoint *HP_map_reloadnpc_sub_post; struct HPMHookPoint *HP_map_inter_config_read_pre; struct HPMHookPoint *HP_map_inter_config_read_post; + struct HPMHookPoint *HP_map_inter_config_read_database_names_pre; + struct HPMHookPoint *HP_map_inter_config_read_database_names_post; + struct HPMHookPoint *HP_map_inter_config_read_connection_pre; + struct HPMHookPoint *HP_map_inter_config_read_connection_post; struct HPMHookPoint *HP_map_sql_init_pre; struct HPMHookPoint *HP_map_sql_init_post; struct HPMHookPoint *HP_map_sql_close_pre; @@ -9291,6 +9295,10 @@ struct { int HP_map_reloadnpc_sub_post; int HP_map_inter_config_read_pre; int HP_map_inter_config_read_post; + int HP_map_inter_config_read_database_names_pre; + int HP_map_inter_config_read_database_names_post; + int HP_map_inter_config_read_connection_pre; + int HP_map_inter_config_read_connection_post; int HP_map_sql_init_pre; int HP_map_sql_init_post; int HP_map_sql_close_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index 2cef7f135..1f231b653 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -1662,6 +1662,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(map->config_read_sub, HP_map_config_read_sub) }, { HP_POP(map->reloadnpc_sub, HP_map_reloadnpc_sub) }, { HP_POP(map->inter_config_read, HP_map_inter_config_read) }, + { HP_POP(map->inter_config_read_database_names, HP_map_inter_config_read_database_names) }, + { HP_POP(map->inter_config_read_connection, HP_map_inter_config_read_connection) }, { HP_POP(map->sql_init, HP_map_sql_init) }, { HP_POP(map->sql_close, HP_map_sql_close) }, { HP_POP(map->zone_mf_cache, HP_map_zone_mf_cache) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 9ef56800f..6889e2658 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -42814,15 +42814,15 @@ void HP_map_reloadnpc_sub(char *cfgName) { } return; } -int HP_map_inter_config_read(char *cfgName) { +bool HP_map_inter_config_read(const char *filename, bool imported) { int hIndex = 0; - int retVal___ = 0; + bool retVal___ = false; if( HPMHooks.count.HP_map_inter_config_read_pre ) { - int (*preHookFunc) (char **cfgName); + bool (*preHookFunc) (const char **filename, bool *imported); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_map_inter_config_read_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_map_inter_config_read_pre[hIndex].func; - retVal___ = preHookFunc(&cfgName); + retVal___ = preHookFunc(&filename, &imported); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -42830,13 +42830,67 @@ int HP_map_inter_config_read(char *cfgName) { } } { - retVal___ = HPMHooks.source.map.inter_config_read(cfgName); + retVal___ = HPMHooks.source.map.inter_config_read(filename, imported); } if( HPMHooks.count.HP_map_inter_config_read_post ) { - int (*postHookFunc) (int retVal___, char *cfgName); + bool (*postHookFunc) (bool retVal___, const char *filename, bool imported); for(hIndex = 0; hIndex < HPMHooks.count.HP_map_inter_config_read_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_map_inter_config_read_post[hIndex].func; - retVal___ = postHookFunc(retVal___, cfgName); + retVal___ = postHookFunc(retVal___, filename, imported); + } + } + return retVal___; +} +bool HP_map_inter_config_read_database_names(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_map_inter_config_read_database_names_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_map_inter_config_read_database_names_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_map_inter_config_read_database_names_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.map.inter_config_read_database_names(filename, config, imported); + } + if( HPMHooks.count.HP_map_inter_config_read_database_names_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_map_inter_config_read_database_names_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_map_inter_config_read_database_names_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); + } + } + return retVal___; +} +bool HP_map_inter_config_read_connection(const char *filename, const struct config_t *config, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if( HPMHooks.count.HP_map_inter_config_read_connection_pre ) { + bool (*preHookFunc) (const char **filename, const struct config_t **config, bool *imported); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_map_inter_config_read_connection_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_map_inter_config_read_connection_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &config, &imported); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.map.inter_config_read_connection(filename, config, imported); + } + if( HPMHooks.count.HP_map_inter_config_read_connection_post ) { + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_t *config, bool imported); + for(hIndex = 0; hIndex < HPMHooks.count.HP_map_inter_config_read_connection_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_map_inter_config_read_connection_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, config, imported); } } return retVal___; @@ -44050,15 +44104,15 @@ void HP_mapreg_reload(void) { } return; } -bool HP_mapreg_config_read(const char *w1, const char *w2) { +bool HP_mapreg_config_read(const char *filename, const struct config_setting_t *config, bool imported) { int hIndex = 0; bool retVal___ = false; if( HPMHooks.count.HP_mapreg_config_read_pre ) { - bool (*preHookFunc) (const char **w1, const char **w2); + bool (*preHookFunc) (const char **filename, const struct config_setting_t **config, bool *imported); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_config_read_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_mapreg_config_read_pre[hIndex].func; - retVal___ = preHookFunc(&w1, &w2); + retVal___ = preHookFunc(&filename, &config, &imported); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -44066,13 +44120,13 @@ bool HP_mapreg_config_read(const char *w1, const char *w2) { } } { - retVal___ = HPMHooks.source.mapreg.config_read(w1, w2); + retVal___ = HPMHooks.source.mapreg.config_read(filename, config, imported); } if( HPMHooks.count.HP_mapreg_config_read_post ) { - bool (*postHookFunc) (bool retVal___, const char *w1, const char *w2); + bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_setting_t *config, bool imported); for(hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_config_read_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_mapreg_config_read_post[hIndex].func; - retVal___ = postHookFunc(retVal___, w1, w2); + retVal___ = postHookFunc(retVal___, filename, config, imported); } } return retVal___; -- cgit v1.2.3-70-g09d2 From f56264d23d9cc86a87331401496e206639cdd6e3 Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 11 Feb 2016 00:41:54 +0100 Subject: Ported login-server.conf to libconfig Ported to modern Hercules and cleaned up from Panikon's commits: ceb8a486ac47c2ed9aae4baa1ec39a11f31e9368, c1049123a4ea6ae6f0992ffe766db8aed7435ab5, 6feb097046355610d2288670a569ccc175358580, 9f6e27a96d655f2b4555310786d9d10898754404, 21fa5d24255ba026f96b1dbedf74ac5ef831d3ae, e22a56ad4def8ca22e94d44377a5364b9db1a425, f753a754923140bfec02057c16e6e8429b863d0e, 25dde7e46524ace330b83cb4bf0255cc4d796792 Signed-off-by: Haru --- .gitignore | 1 - conf/common/inter-server.conf | 3 + conf/global/sql_connection.conf | 3 + conf/import-tmpl/login-server.conf | 32 +++ conf/import-tmpl/login_conf.txt | 0 conf/login-server.conf | 156 ----------- conf/login/login-server.conf | 187 +++++++++++++ doc/md5_hashcheck.txt | 24 +- src/login/account.h | 10 +- src/login/account_sql.c | 243 +++++++--------- src/login/ipban.h | 9 +- src/login/ipban_sql.c | 281 ++++++++++--------- src/login/login.c | 547 ++++++++++++++++++++++++++++--------- src/login/login.h | 17 +- src/login/loginlog.h | 4 +- src/login/loginlog_sql.c | 198 +++++++------- tools/configconverter.pl | 110 +++++++- 17 files changed, 1142 insertions(+), 683 deletions(-) create mode 100644 conf/import-tmpl/login-server.conf delete mode 100644 conf/import-tmpl/login_conf.txt delete mode 100644 conf/login-server.conf create mode 100644 conf/login/login-server.conf (limited to 'src') diff --git a/.gitignore b/.gitignore index 3302e44cf..bd33fac60 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,6 @@ Thumbs.db /conf/import/*.conf /conf/import/battle_conf.txt /conf/import/log_conf.txt -/conf/import/login_conf.txt /conf/import/map_conf.txt /conf/import/msg_conf.txt /conf/import/packet_conf.txt diff --git a/conf/common/inter-server.conf b/conf/common/inter-server.conf index fd55b27e5..888d4ad80 100644 --- a/conf/common/inter-server.conf +++ b/conf/common/inter-server.conf @@ -65,6 +65,9 @@ inter_configuration: { // this is meant for people who KNOW their stuff, and for some reason want to change their // database layout. [CLOWNISIUS] database_names: { + account_db: "login" + login_db: "loginlog" + ipban_table: "ipbanlist" char_db: "char" interlog_db: "interlog" ragsrvinfo_db: "ragsrvinfo" diff --git a/conf/global/sql_connection.conf b/conf/global/sql_connection.conf index 58c9e6d08..60fea5656 100644 --- a/conf/global/sql_connection.conf +++ b/conf/global/sql_connection.conf @@ -36,6 +36,9 @@ sql_connection: { // (Note that this feature requires MySQL 4.1+) //default_codepage: "" + // [LOGIN] Is `userid` in account_db case sensitive? + //case_sensitive: false + // For IPs, ideally under linux, you want to use localhost instead of 127.0.0.1. // Under windows, you want to use 127.0.0.1. If you see a message like // "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)" diff --git a/conf/import-tmpl/login-server.conf b/conf/import-tmpl/login-server.conf new file mode 100644 index 000000000..feadef976 --- /dev/null +++ b/conf/import-tmpl/login-server.conf @@ -0,0 +1,32 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Login Server local configuration file. +//========================================================================= + +login_configuration: { + // See conf/login/login-server.conf for details +} diff --git a/conf/import-tmpl/login_conf.txt b/conf/import-tmpl/login_conf.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/conf/login-server.conf b/conf/login-server.conf deleted file mode 100644 index 620fae327..000000000 --- a/conf/login-server.conf +++ /dev/null @@ -1,156 +0,0 @@ -// Hercules Login Server configuration file. -// Translated by Peter Kieser - -// Note: "Comments" are all text on the right side of a double slash "//" -// Whatever text is commented will not be parsed by the servers, and serves -// only as information/reference. - -// The login server listens on the interface with this IP address. -// NOTE: This allows you to run multiple servers on multiple interfaces -// while using the same ports for each server. -//bind_ip: 127.0.0.1 - -// Login Server Port -login_port: 6900 - -//Time-stamp format which will be printed before all messages. -//Can at most be 20 characters long. -//Common formats: -// %I:%M:%S %p (hour:minute:second 12 hour, AM/PM format) -// %H:%M:%S (hour:minute:second, 24 hour format) -// %d/%b/%Y (day/Month/year) -//For full format information, consult the strftime() manual. -//timestamp_format: [%d/%b %H:%M] - -//If redirected output contains escape sequences (color codes) -stdout_with_ansisequence: no - -//Makes server output more silent by omitting certain types of messages: -//1: Hide Information messages -//2: Hide Status messages -//4: Hide Notice Messages -//8: Hide Warning Messages -//16: Hide Error and SQL Error messages. -//32: Hide Debug Messages -//Example: "console_silent: 7" Hides information, status and notice messages (1+2+4) -console_silent: 0 - -// Can you use _M/_F to make new accounts on the server? -new_account: yes - -//If new_account is enabled, minimum length to userid and passwords should be 4? -//Must be 'Yes' unless your client uses both 'Disable 4 LetterUserID/Password' Diffs -new_acc_length_limit: yes - -// Account registration flood protection system -// allowed_regs is the number of registrations allowed in time_allowed (in seconds) -allowed_regs: 1 -time_allowed: 10 - -// To log the login server? -// NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans. -log_login: yes - -// Indicate how to display date in logs, to players, etc. -date_format: %Y-%m-%d %H:%M:%S - -// Required account group id to connect to server. -// -1: disabled -// 0 or more: group id -group_id_to_connect: -1 - -// Minimum account group id required to connect to server. -// Will not function if group_id_to_connect config is enabled. -// -1: disabled -// 0 or more: group id -min_group_id_to_connect: -1 - -// Starting additional sec from now for the limited time at creation of account -// -1: new account are created with UNlimited time (default value) -// 0 or more: new accounts was created by addition of the value (in sec) to the actual time (to set first limited time) -start_limited_time: -1 - -// Check The clientversion set in the clientinfo ? -check_client_version: no - -// What version we would allow to connect? (if the options above is enabled..) -client_version_to_connect: 20 - -// Store passwords as MD5 hashes instead of plaintext ? -// NOTE: Will not work with clients that use -use_MD5_passwords: no - -// Ipban features (SQL only) -ipban.enable: yes -//ipban.sql.db_hostname: 127.0.0.1 -//ipban.sql.db_port: 3306 -//ipban.sql.db_username: ragnarok -//ipban.sql.db_password: ragnarok -//ipban.sql.db_database: ragnarok -//ipban.sql.codepage: -//ipban.sql.ipban_table: ipbanlist -// Dynamic password failure ipban system -ipban.dynamic_pass_failure_ban: yes -ipban.dynamic_pass_failure_ban_interval: 5 -ipban.dynamic_pass_failure_ban_limit: 7 -ipban.dynamic_pass_failure_ban_duration: 5 - -// Interval (in seconds) to clean up expired IP bans. 0 = disabled. default = 60. -// NOTE: Even if this is disabled, expired IP bans will be cleaned up on login server start/stop. -// Players will still be able to login if an ipban entry exists but the expiration time has already passed. -ipban_cleanup_interval: 60 - -// Interval (in minutes) to execute a DNS/IP update. Disabled by default. -// Enable it if your server uses a dynamic IP which changes with time. -//ip_sync_interval: 10 - -// DNS Blacklist Blocking -// If enabled, each incoming connection will be tested against the blacklists -// on the specified dnsbl_servers (comma-separated list) -use_dnsbl: no -dnsbl_servers: bl.blocklist.de, socks.dnsbl.sorbs.net -// Here are some free DNS Blacklist Services: http://en.wikipedia.org/wiki/Comparison_of_DNS_blacklists -//============================================================================== -// dnsbl_servers Description -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// bl.blocklist.de IP-Addresses who attack other servers/honeypots over SSH, FTP, IMAP, etc. -// ircbl.ahbl.org AHBL (open proxies, compromised machines, comment spammers) -// safe.dnsbl.sorbs.net All zones in dnsbl.sorbs.net except "recent" and "escalations" -// sbl-xbl.spamhaus.org Spamhaus blacklist (spammers, open proxies) -// socks.dnsbl.sorbs.net Open SOCKS proxy servers -// tor.ahbl.org Current tor relay and exit nodes - - -// Account data storage configuration -// SQL -//account.sql.db_hostname: 127.0.0.1 -//account.sql.db_port: 3306 -//account.sql.db_username: ragnarok -//account.sql.db_password: ragnarok -//account.sql.db_database: ragnarok -//account.sql.codepage: -//account.sql.case_sensitive: no -//account.sql.account_db: login -//account.sql.accreg_db: global_reg_value - -// Client MD5 hash check -// If turned on, the login server will check if the client's hash matches -// the value below, and will not connect tampered clients. -// Note: see doc/md5_hashcheck.txt for more details. -client_hash_check: off - -// Client MD5 hashes -// The client with the specified hash can be used to log in by players with -// a group_id equal to or greater than the given value. -// If you specify 'disabled' as hash, players with a group_id greater than or -// equal to the given value will be able to log in regardless of hash (and even -// if their client does not send a hash at all.) -// Format: group_id, hash -// Note: see doc/md5_hashcheck.txt for more details. -//client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5 -//client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae -//client_hash: 99, disabled - - -import: conf/inter-server.conf -import: conf/import/login_conf.txt diff --git a/conf/login/login-server.conf b/conf/login/login-server.conf new file mode 100644 index 000000000..71928e3d0 --- /dev/null +++ b/conf/login/login-server.conf @@ -0,0 +1,187 @@ +//================= Hercules Configuration ================================ +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License =============================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2016 Hercules Dev Team +//= +//= Hercules is free software: you can redistribute it and/or modify +//= it under the terms of the GNU General Public License as published by +//= the Free Software Foundation, either version 3 of the License, or +//= (at your option) any later version. +//= +//= This program is distributed in the hope that it will be useful, +//= but WITHOUT ANY WARRANTY; without even the implied warranty of +//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//= GNU General Public License for more details. +//= +//= You should have received a copy of the GNU General Public License +//= along with this program. If not, see . +//========================================================================= +//= Login Server configuration file. +//========================================================================= + +login_configuration: { + // Login-server's console configuration + @include "conf/global/console.conf" + + inter: { + // The login server listens on the interface with this IP address. + // NOTE: This allows you to run multiple servers on multiple interfaces + // while using the same ports for each server. + //bind_ip: "127.0.0.1" + + // Login Server Port + login_port: 6900 + + // Interval (in minutes) to execute a DNS/IP update. Disabled by default. + // Enable it if your server uses a dynamic IP which changes with time. + //ip_sync_interval: 10 + } + + log: { + // To log the login server? + // NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans. + log_login: true + + // Indicate how to display date in logs, to players, etc. + date_format: "%Y-%m-%d %H:%M:%S" + } + + // Account engine configuration + account: { + // Can you use _M/_F to make new accounts on the server? + new_account: true + + //If new_account is enabled, minimum length to userid and passwords should be 4? + //Must be 'true' unless your client uses both 'Disable 4 LetterUserID/Password' Diffs + new_acc_length_limit: true + + // Account registration flood protection system + // allowed_regs is the number of registrations allowed in time_allowed (in seconds) + allowed_regs: 1 + time_allowed: 10 + + // Starting additional sec from now for the limited time at creation of account + // -1: new account are created with UNlimited time (default value) + // 0 or more: new accounts was created by addition of the value (in sec) to the actual time (to set first limited time) + start_limited_time: -1 + + // Store passwords as MD5 hashes instead of plaintext ? + // NOTE: Will not work with clients that use + use_MD5_passwords: false + + // Account data engine storage configuration + @include "conf/global/sql_connection.conf" + + //================================================================== + // IP banning system + //================================================================== + ipban: { + enabled: true + + // Interval (in seconds) to clean up expired IP bans. 0 = disabled. default = 60. + // NOTE: Even if this is disabled, expired IP bans will be cleaned up on login server start/stop. + // Players will still be able to login if an ipban entry exists but the expiration time has already passed. + cleanup_interval: 60 + + // SQL connection settings + @include "conf/global/sql_connection.conf" + + // Dynamic password failure ipban system + dynamic_pass_failure: { + enabled: true + + // Interval in minutes between failed tries + // Only failed tries between this interval will be accounted when banning + ban_interval: 5 + + // How many failures before adding a temporary ban entry? + ban_limit: 7 + + // Duration of the ban in minutes + ban_duration: 5 + } + } // login_configuration.account.ipban + } // login_configuration.account + + permission: { + // Required account group id to connect to server. + // -1: disabled + // 0 or more: group id + group_id_to_connect: -1 + + // Minimum account group id required to connect to server. + // Will not function if group_id_to_connect config is enabled. + // -1: disabled + // 0 or more: group id + min_group_id_to_connect: -1 + + // Check The clientversion set in the clientinfo ? + check_client_version: false + + // What version we would allow to connect? (if check_client_version is enabled) + client_version_to_connect: 20 + + //================================================================== + // Client hash checking system + //================================================================== + // Note: see doc/md5_hashcheck.txt for more details. + hash: { + // Client MD5 hash check + // If turned on, the login server will check if the client's hash matches + // the value below, and will not connect tampered clients. + enabled: false + + // Client MD5 hashes + // The client with the specified hash can be used to log in by players with + // a group_id equal to or greater than the given value. + // If you specify 'disabled' as hash, players with a group_id greater than or + // equal to the given value will be able to log in regardless of hash (and even + // if their client does not send a hash at all.) + MD5_hashes: ( + //{ + // group_id: group id + // hash: client hash + //}, + //{ + // group_id: 0 + // hash: "113e195e6c051bb1cfb12a644bb084c5" + //}, + //{ + // group_id: 10 + // hash: "cb1ea78023d337c38e8ba5124e2338ae" + //}, + //{ + // group_id: 99 + // hash: "disabled" + //}, + ) + } // login_configuration.permission.hash + + DNS_blacklist: { + // DNS Blacklist Blocking + // If enabled, each incoming connection will be tested against the blacklists + // on the specified dnsbl_servers + enabled: false + + dnsbl_servers: ( + // Here are some free DNS Blacklist Services: http://en.wikipedia.org/wiki/Comparison_of_DNS_blacklists + "bl.blocklist.de", // IP-Addresses who attack other servers/honeypots over SSH, FTP, IMAP, etc. + //"ircbl.ahbl.org", // AHBL (open proxies, compromised machines, comment spammers) + //"safe.dnsbl.sorbs.net", // All zones in dnsbl.sorbs.net except "recent" and "escalations" + //"sbl-xbl.spamhaus.org", // Spamhaus blacklist (spammers, open proxies) + "socks.dnsbl.sorbs.net", // Open SOCKS proxy servers + //"tor.ahbl.org", // Current tor relay and exit nodes + ) + } // login_configuration.DNS_blacklist + } // login_configuration.permission +} + +import: "conf/import/login-server.conf" diff --git a/doc/md5_hashcheck.txt b/doc/md5_hashcheck.txt index d9064b1ab..b386559b5 100644 --- a/doc/md5_hashcheck.txt +++ b/doc/md5_hashcheck.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= Hercules Dev Team //===== Current Version: ===================================== -//= 20140208 +//= 20160210 //===== Description: ========================================= //= This file outlines the login server's MD5 hash check. //============================================================ @@ -20,27 +20,9 @@ Please refer to your client diff tool manual for the appropriate patch tools or diffs it may have similar names.) The serverside settings for the hash check are located in -conf/login.conf: +conf/login.conf::login_configuration.permission.hash -// Client MD5 hash check -// If turned on, the login server will check if the client's hash matches -// the value below, and will not connect tampered clients. -// Note: see doc/md5_hashcheck.txt for more details. -client_hash_check: off - -// Client MD5 hashes -// The client with the specified hash can be used to log in by players with -// a group_id equal to or greater than the given value. -// If you specify 'disabled' as hash, players with a group_id greater than or -// equal to the given value will be able to log in regardless of hash (and even -// if their client does not send a hash at all.) -// Format: group_id, hash -// Note: see doc/md5_hashcheck.txt for more details. -client_hash: 0, 113e195e6c051bb1cfb12a644bb084c5 -client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae -client_hash: 99, disabled - -To enable MD5 hash checks, set 'client_hash_check' to 'on' and add one +To enable MD5 hash checks, set 'client_hash_check' to 'true' and add one 'client_hash' entry for each client you want to use. The group_id can be any of the groups in conf/groups.conf, and it is useful in case if you want to allow GMs to use a different client diff --git a/src/login/account.h b/src/login/account.h index 7e1930ad4..9bb07fda3 100644 --- a/src/login/account.h +++ b/src/login/account.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 @@ -27,6 +27,9 @@ /* Forward declarations */ struct Sql; // common/sql.h +/* Forward Declarations */ +struct config_t; // common/conf.h + typedef struct AccountDB AccountDB; typedef struct AccountDBIterator AccountDBIterator; @@ -107,10 +110,9 @@ struct AccountDB /// Sets a property in this database. /// /// @param self Database - /// @param key Property name - /// @param value Property value + /// @param config Configuration node /// @return true if successful - bool (*set_property)(AccountDB* self, const char* key, const char* value); + bool (*set_property)(AccountDB* self, struct config_t *config, bool imported); /// Creates a new account in this database. /// If acc->account_id is not -1, the provided value will be used. diff --git a/src/login/account_sql.c b/src/login/account_sql.c index 2e128e8bf..70d4f3dfb 100644 --- a/src/login/account_sql.c +++ b/src/login/account_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 @@ -24,6 +24,7 @@ #include "account.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/console.h" #include "common/memmgr.h" #include "common/mmo.h" @@ -45,14 +46,7 @@ typedef struct AccountDB_SQL struct Sql *accounts; // SQL accounts storage - // global sql settings - char global_db_hostname[32]; - uint16 global_db_port; - char global_db_username[32]; - char global_db_password[100]; - char global_db_database[32]; - char global_codepage[32]; - // local sql settings + // Sql settings char db_hostname[32]; uint16 db_port; char db_username[32]; @@ -81,7 +75,7 @@ typedef struct AccountDBIterator_SQL static bool account_db_sql_init(AccountDB* self); static void account_db_sql_destroy(AccountDB* self); static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen); -static bool account_db_sql_set_property(AccountDB* self, const char* option, const char* value); +static bool account_db_sql_set_property(AccountDB* self, struct config_t *config, bool imported); static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc); static bool account_db_sql_remove(AccountDB* self, const int account_id); static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc); @@ -113,19 +107,12 @@ AccountDB* account_db_sql(void) // initialize to default values db->accounts = NULL; - // global sql settings - safestrncpy(db->global_db_hostname, "127.0.0.1", sizeof(db->global_db_hostname)); - db->global_db_port = 3306; - safestrncpy(db->global_db_username, "ragnarok", sizeof(db->global_db_username)); - safestrncpy(db->global_db_password, "ragnarok", sizeof(db->global_db_password)); - safestrncpy(db->global_db_database, "ragnarok", sizeof(db->global_db_database)); - safestrncpy(db->global_codepage, "", sizeof(db->global_codepage)); - // local sql settings - safestrncpy(db->db_hostname, "", sizeof(db->db_hostname)); + // Sql settings + safestrncpy(db->db_hostname, "127.0.0.1", sizeof(db->db_hostname)); db->db_port = 3306; - safestrncpy(db->db_username, "", sizeof(db->db_username)); - safestrncpy(db->db_password, "", sizeof(db->db_password)); - safestrncpy(db->db_database, "", sizeof(db->db_database)); + safestrncpy(db->db_username, "ragnarok", sizeof(db->db_username)); + safestrncpy(db->db_password, "ragnarok", sizeof(db->db_password)); + safestrncpy(db->db_database, "ragnarok", sizeof(db->db_database)); safestrncpy(db->codepage, "", sizeof(db->codepage)); // other settings db->case_sensitive = false; @@ -144,46 +131,22 @@ AccountDB* account_db_sql(void) static bool account_db_sql_init(AccountDB* self) { AccountDB_SQL* db = (AccountDB_SQL*)self; - struct Sql *sql_handle; - const char* username; - const char* password; - const char* hostname; - uint16 port; - const char* database; - const char* codepage; + struct Sql *sql_handle = NULL; nullpo_ret(db); + db->accounts = SQL->Malloc(); sql_handle = db->accounts; - if( db->db_hostname[0] != '\0' ) - {// local settings - username = db->db_username; - password = db->db_password; - hostname = db->db_hostname; - port = db->db_port; - database = db->db_database; - codepage = db->codepage; - } - else - {// global settings - username = db->global_db_username; - password = db->global_db_password; - hostname = db->global_db_hostname; - port = db->global_db_port; - database = db->global_db_database; - codepage = db->global_codepage; - } - - if( SQL_ERROR == SQL->Connect(sql_handle, username, password, hostname, port, database) ) - { + if (SQL_ERROR == SQL->Connect(sql_handle, db->db_username, db->db_password, + db->db_hostname, db->db_port, db->db_database)) { Sql_ShowDebug(sql_handle); SQL->Free(db->accounts); db->accounts = NULL; return false; } - if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) ) + if (db->codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, db->codepage)) Sql_ShowDebug(sql_handle); Sql_HerculesUpdateCheck(db->accounts); @@ -207,6 +170,15 @@ static void account_db_sql_destroy(AccountDB* self) /// Gets a property from this database. static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen) { + /* TODO: + * This functionality is not being used as of now, it was removed in + * commit 5479f9631f8579d03fbfd14d8a49c7976226a156, it is meant to get + * engine properties when more than one engine is available. I'll + * re-add it as soon as I can, following the new standards. If anyone + * is interested in this functionality you can contact me in our boards + * and I'll try to add it sooner (Pan) [Panikon] + */ +#if 0 AccountDB_SQL* db = (AccountDB_SQL*)self; const char* signature; @@ -230,32 +202,6 @@ static bool account_db_sql_get_property(AccountDB* self, const char* key, char* return true; } - signature = "sql."; - if( strncmpi(key, signature, strlen(signature)) == 0 ) - { - key += strlen(signature); - if( strcmpi(key, "db_hostname") == 0 ) - safesnprintf(buf, buflen, "%s", db->global_db_hostname); - else - if( strcmpi(key, "db_port") == 0 ) - safesnprintf(buf, buflen, "%d", db->global_db_port); - else - if( strcmpi(key, "db_username") == 0 ) - safesnprintf(buf, buflen, "%s", db->global_db_username); - else - if( strcmpi(key, "db_password") == 0 ) - safesnprintf(buf, buflen, "%s", db->global_db_password); - else - if( strcmpi(key, "db_database") == 0 ) - safesnprintf(buf, buflen, "%s", db->global_db_database); - else - if( strcmpi(key, "codepage") == 0 ) - safesnprintf(buf, buflen, "%s", db->global_codepage); - else - return false;// not found - return true; - } - signature = "account.sql."; if( strncmpi(key, signature, strlen(signature)) == 0 ) { @@ -295,82 +241,91 @@ static bool account_db_sql_get_property(AccountDB* self, const char* key, char* } return false;// not found +#endif // 0 + return false; } -/// if the option is supported, adjusts the internal state -static bool account_db_sql_set_property(AccountDB* self, const char* key, const char* value) +/** + * Reads the 'inter_configuration' config file and initializes required variables. + * + * @param db Self. + * @param filename Path to configuration file + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +bool account_db_read_inter(AccountDB_SQL *db, const char *filename, bool imported) +{ + struct config_t config; + struct config_setting_t *setting = NULL; + + nullpo_retr(false, db); + 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("account_db_sql_set_property: inter_configuration/database_names was not found!\n"); + return false; + } + libconfig->setting_lookup_mutable_string(setting, "account_db", db->account_db, sizeof(db->account_db)); + + if ((setting = libconfig->lookup(&config, "inter_configuration/database_names/registry")) == NULL) { + libconfig->destroy(&config); + if (imported) + return true; + ShowError("account_db_sql_set_property: inter_configuration/database_names/registry was not found!\n"); + return false; + } + libconfig->setting_lookup_mutable_string(setting, "global_acc_reg_str_db", db->global_acc_reg_str_db, sizeof(db->global_acc_reg_str_db)); + libconfig->setting_lookup_mutable_string(setting, "global_acc_reg_num_db", db->global_acc_reg_num_db, sizeof(db->global_acc_reg_num_db)); + + // TODO: Proper import mechanism for this file + + libconfig->destroy(&config); + return true; +} + +/** + * Loads the sql configuration. + * + * @param self Self. + * @param config The current config being parsed. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +static bool account_db_sql_set_property(AccountDB* self, struct config_t *config, bool imported) { AccountDB_SQL* db = (AccountDB_SQL*)self; - const char* signature; + struct config_setting_t *setting = NULL; nullpo_ret(db); - nullpo_ret(key); - nullpo_ret(value); - signature = "sql."; - if( strncmp(key, signature, strlen(signature)) == 0 ) - { - key += strlen(signature); - if( strcmpi(key, "db_hostname") == 0 ) - safestrncpy(db->global_db_hostname, value, sizeof(db->global_db_hostname)); - else - if( strcmpi(key, "db_port") == 0 ) - db->global_db_port = (uint16)strtoul(value, NULL, 10); - else - if( strcmpi(key, "db_username") == 0 ) - safestrncpy(db->global_db_username, value, sizeof(db->global_db_username)); - else - if( strcmpi(key, "db_password") == 0 ) - safestrncpy(db->global_db_password, value, sizeof(db->global_db_password)); - else - if( strcmpi(key, "db_database") == 0 ) - safestrncpy(db->global_db_database, value, sizeof(db->global_db_database)); - else - if( strcmpi(key, "codepage") == 0 ) - safestrncpy(db->global_codepage, value, sizeof(db->global_codepage)); - else - return false;// not found - return true; - } + nullpo_ret(config); - signature = "account.sql."; - if( strncmp(key, signature, strlen(signature)) == 0 ) - { - key += strlen(signature); - if( strcmpi(key, "db_hostname") == 0 ) - safestrncpy(db->db_hostname, value, sizeof(db->db_hostname)); - else - if( strcmpi(key, "db_port") == 0 ) - db->db_port = (uint16)strtoul(value, NULL, 10); - else - if( strcmpi(key, "db_username") == 0 ) - safestrncpy(db->db_username, value, sizeof(db->db_username)); - else - if( strcmpi(key, "db_password") == 0 ) - safestrncpy(db->db_password, value, sizeof(db->db_password)); - else - if( strcmpi(key, "db_database") == 0 ) - safestrncpy(db->db_database, value, sizeof(db->db_database)); - else - if( strcmpi(key, "codepage") == 0 ) - safestrncpy(db->codepage, value, sizeof(db->codepage)); - else - if( strcmpi(key, "case_sensitive") == 0 ) - db->case_sensitive = (bool)config_switch(value); - else - if( strcmpi(key, "account_db") == 0 ) - safestrncpy(db->account_db, value, sizeof(db->account_db)); - else - if( strcmpi(key, "global_acc_reg_str_db") == 0 ) - safestrncpy(db->global_acc_reg_str_db, value, sizeof(db->global_acc_reg_str_db)); - else - if( strcmpi(key, "global_acc_reg_num_db") == 0 ) - safestrncpy(db->global_acc_reg_num_db, value, sizeof(db->global_acc_reg_num_db)); - else - return false;// not found - return true; + if ((setting = libconfig->lookup(config, "login_configuration/account/sql_connection")) == NULL) { + if (imported) + return true; + ShowError("account_db_sql_set_property: login_configuration/account/sql_connection was not found!\n"); + ShowWarning("account_db_sql_set_property: Defaulting sql_connection...\n"); + return false; } - return false;// not found + libconfig->setting_lookup_mutable_string(setting, "db_hostname", db->db_hostname, sizeof(db->db_hostname)); + libconfig->setting_lookup_mutable_string(setting, "db_username", db->db_username, sizeof(db->db_username)); + libconfig->setting_lookup_mutable_string(setting, "db_password", db->db_password, sizeof(db->db_password)); + libconfig->setting_lookup_mutable_string(setting, "db_database", db->db_database, sizeof(db->db_database)); + libconfig->setting_lookup_mutable_string(setting, "codepage", db->codepage, sizeof(db->codepage)); // FIXME: Why do we need both codepage and default_codepage? + libconfig->setting_lookup_uint16(setting, "db_port", &db->db_port); + libconfig->setting_lookup_bool_real(setting, "case_sensitive", &db->case_sensitive); + + account_db_read_inter(db, "conf/common/inter-server.conf", imported); + + return true; } /// create a new account entry diff --git a/src/login/ipban.h b/src/login/ipban.h index 85cf3873c..104e3a8a3 100644 --- a/src/login/ipban.h +++ b/src/login/ipban.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 @@ -23,6 +23,9 @@ #include "common/cbasetypes.h" +/* Forward Declarations */ +struct config_t; // common/conf.h + #ifdef HERCULES_CORE // TODO: Interface // initialize @@ -37,8 +40,8 @@ bool ipban_check(uint32 ip); // increases failure count for the specified IP void ipban_log(uint32 ip); -// parses configuration option -bool ipban_config_read(const char *key, const char* value); +// parses configuration options +bool ipban_config_read(const char *filename, struct config_t *config, bool imported); #endif // HERCULES_CORE #endif /* LOGIN_IPBAN_H */ diff --git a/src/login/ipban_sql.c b/src/login/ipban_sql.c index bec0217f4..d74e6c4fa 100644 --- a/src/login/ipban_sql.c +++ b/src/login/ipban_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,26 +25,21 @@ #include "login/login.h" #include "login/loginlog.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/nullpo.h" +#include "common/showmsg.h" #include "common/sql.h" #include "common/strlib.h" #include "common/timer.h" #include -// global sql settings -static char global_db_hostname[32] = "127.0.0.1"; -static uint16 global_db_port = 3306; -static char global_db_username[32] = "ragnarok"; -static char global_db_password[100] = "ragnarok"; -static char global_db_database[32] = "ragnarok"; -static char global_codepage[32] = ""; -// local sql settings -static char ipban_db_hostname[32] = ""; -static uint16 ipban_db_port = 0; -static char ipban_db_username[32] = ""; -static char ipban_db_password[100] = ""; -static char ipban_db_database[32] = ""; +// Sql settings +static char ipban_db_hostname[32] = "127.0.0.1"; +static uint16 ipban_db_port = 3306; +static char ipban_db_username[32] = "ragnarok"; +static char ipban_db_password[100] = "ragnarok"; +static char ipban_db_database[32] = "ragnarok"; static char ipban_codepage[32] = ""; static char ipban_table[32] = "ipbanlist"; @@ -59,54 +54,30 @@ int ipban_cleanup(int tid, int64 tick, int id, intptr_t data); // initialize void ipban_init(void) { - const char* username; - const char* password; - const char* hostname; - uint16 port; - const char* database; - const char* codepage; - ipban_inited = true; if (!login->config->ipban) return;// ipban disabled - if( ipban_db_hostname[0] != '\0' ) - {// local settings - username = ipban_db_username; - password = ipban_db_password; - hostname = ipban_db_hostname; - port = ipban_db_port; - database = ipban_db_database; - codepage = ipban_codepage; - } - else - {// global settings - username = global_db_username; - password = global_db_password; - hostname = global_db_hostname; - port = global_db_port; - database = global_db_database; - codepage = global_codepage; - } - // establish connections sql_handle = SQL->Malloc(); - if( SQL_ERROR == SQL->Connect(sql_handle, username, password, hostname, port, database) ) - { + if (SQL_ERROR == SQL->Connect(sql_handle, ipban_db_username, ipban_db_password, + ipban_db_hostname, ipban_db_port, ipban_db_database)) { Sql_ShowDebug(sql_handle); SQL->Free(sql_handle); exit(EXIT_FAILURE); } - if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) ) + if (ipban_codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, ipban_codepage)) Sql_ShowDebug(sql_handle); - if (login->config->ipban_cleanup_interval > 0) - { // set up periodic cleanup of connection history and active bans + if (login->config->ipban_cleanup_interval > 0) { + // set up periodic cleanup of connection history and active bans timer->add_func_list(ipban_cleanup, "ipban_cleanup"); cleanup_timer_id = timer->add_interval(timer->gettick()+10, ipban_cleanup, 0, 0, login->config->ipban_cleanup_interval*1000); - } else // make sure it gets cleaned up on login-server start regardless of interval-based cleanups + } else { + // make sure it gets cleaned up on login-server start regardless of interval-based cleanups ipban_cleanup(0,0,0,0); + } } // finalize @@ -126,95 +97,153 @@ void ipban_final(void) sql_handle = NULL; } -// load configuration options -bool ipban_config_read(const char* key, const char* value) +/** + * Reads 'inter_configuration' and initializes required variables/Sets global + * configuration. + * + * @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 ipban_config_read_inter(const char *filename, bool imported) { - const char* signature; + struct config_t config; + struct config_setting_t *setting = NULL; + const char *import = NULL; + bool retval = true; - nullpo_ret(key); - nullpo_ret(value); - if( ipban_inited ) - return false;// settings can only be changed before init + nullpo_retr(false, filename); - signature = "sql."; - if( strncmpi(key, signature, strlen(signature)) == 0 ) - { - key += strlen(signature); - if( strcmpi(key, "db_hostname") == 0 ) - safestrncpy(global_db_hostname, value, sizeof(global_db_hostname)); - else - if( strcmpi(key, "db_port") == 0 ) - global_db_port = (uint16)strtoul(value, NULL, 10); - else - if( strcmpi(key, "db_username") == 0 ) - safestrncpy(global_db_username, value, sizeof(global_db_username)); - else - if( strcmpi(key, "db_password") == 0 ) - safestrncpy(global_db_password, value, sizeof(global_db_password)); - else - if( strcmpi(key, "db_database") == 0 ) - safestrncpy(global_db_database, value, sizeof(global_db_database)); - else - if( strcmpi(key, "codepage") == 0 ) - safestrncpy(global_codepage, value, sizeof(global_codepage)); - else - return false;// not found - return true; + if (!libconfig->load_file(&config, filename)) + return false; // Error message is already shown by libconfig->read_file + + if ((setting = libconfig->lookup(&config, "inter_configuration/database_names")) == NULL) { + libconfig->destroy(&config); + if (imported) + return true; + ShowError("ipban_config_read: inter_configuration/database_names was not found!\n"); + return false; + } + libconfig->setting_lookup_mutable_string(setting, "ipban_table", ipban_table, sizeof(ipban_table)); + + // 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) { + ShowWarning("ipban_config_read_inter: Loop detected! Skipping 'import'...\n"); + } else { + if (!ipban_config_read_inter(import, true)) + retval = false; + } } - signature = "ipban.sql."; - if( strncmpi(key, signature, strlen(signature)) == 0 ) - { - key += strlen(signature); - if( strcmpi(key, "db_hostname") == 0 ) - safestrncpy(ipban_db_hostname, value, sizeof(ipban_db_hostname)); - else - if( strcmpi(key, "db_port") == 0 ) - ipban_db_port = (uint16)strtoul(value, NULL, 10); - else - if( strcmpi(key, "db_username") == 0 ) - safestrncpy(ipban_db_username, value, sizeof(ipban_db_username)); - else - if( strcmpi(key, "db_password") == 0 ) - safestrncpy(ipban_db_password, value, sizeof(ipban_db_password)); - else - if( strcmpi(key, "db_database") == 0 ) - safestrncpy(ipban_db_database, value, sizeof(ipban_db_database)); - else - if( strcmpi(key, "codepage") == 0 ) - safestrncpy(ipban_codepage, value, sizeof(ipban_codepage)); - else - if( strcmpi(key, "ipban_table") == 0 ) - safestrncpy(ipban_table, value, sizeof(ipban_table)); - else - return false;// not found - return true; + libconfig->destroy(&config); + return retval; +} + +/** + * Reads login_configuration/account/ipban/sql_connection and loads configuration options. + * + * @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 ipban_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, "login_configuration/account/ipban/sql_connection")) == NULL) { + if (imported) + return true; + ShowError("account_db_sql_set_property: login_configuration/account/ipban/sql_connection was not found in %s!\n", filename); + return false; } - signature = "ipban."; - if( strncmpi(key, signature, strlen(signature)) == 0 ) - { - key += strlen(signature); - if( strcmpi(key, "enable") == 0 ) - login->config->ipban = (bool)config_switch(value); - else - if( strcmpi(key, "dynamic_pass_failure_ban") == 0 ) - login->config->dynamic_pass_failure_ban = (bool)config_switch(value); - else - if( strcmpi(key, "dynamic_pass_failure_ban_interval") == 0 ) - login->config->dynamic_pass_failure_ban_interval = atoi(value); - else - if( strcmpi(key, "dynamic_pass_failure_ban_limit") == 0 ) - login->config->dynamic_pass_failure_ban_limit = atoi(value); - else - if( strcmpi(key, "dynamic_pass_failure_ban_duration") == 0 ) - login->config->dynamic_pass_failure_ban_duration = atoi(value); - else - return false;// not found - return true; + libconfig->setting_lookup_mutable_string(setting, "db_hostname", ipban_db_hostname, sizeof(ipban_db_hostname)); + libconfig->setting_lookup_mutable_string(setting, "db_database", ipban_db_database, sizeof(ipban_db_database)); + + libconfig->setting_lookup_mutable_string(setting, "db_username", ipban_db_username, sizeof(ipban_db_username)); + libconfig->setting_lookup_mutable_string(setting, "db_password", ipban_db_password, sizeof(ipban_db_password)); + libconfig->setting_lookup_mutable_string(setting, "codepage", ipban_codepage, sizeof(ipban_codepage)); + libconfig->setting_lookup_uint16(setting, "db_port", &ipban_db_port); + + return true; +} + +/** + * Reads login_configuration/account/ipban/dynamic_pass_failure and loads configuration options. + * + * @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 ipban_config_read_dynamic(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, "login_configuration/account/ipban/dynamic_pass_failure")) == NULL) { + if (imported) + return true; + ShowError("account_db_sql_set_property: login_configuration/account/ipban/dynamic_pass_failure was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_bool_real(setting, "enabled", &login->config->dynamic_pass_failure_ban); + libconfig->setting_lookup_uint32(setting, "ban_interval", &login->config->dynamic_pass_failure_ban_interval); + libconfig->setting_lookup_uint32(setting, "ban_limit", &login->config->dynamic_pass_failure_ban_limit); + libconfig->setting_lookup_uint32(setting, "ban_duration", &login->config->dynamic_pass_failure_ban_duration); + + return true; +} + +/** + * Reads login_configuration.account.ipban and loads configuration options. + * + * @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 ipban_config_read(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + bool retval = true; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if (ipban_inited) + return false; // settings can only be changed before init + + if ((setting = libconfig->lookup(config, "login_configuration/account/ipban")) == NULL) { + if (!imported) + ShowError("login_config_read: login_configuration/log was not found in %s!\n", filename); + return false; } - return false;// not found + libconfig->setting_lookup_bool_real(setting, "enabled", &login->config->ipban); + libconfig->setting_lookup_uint32(setting, "cleanup_interval", &login->config->ipban_cleanup_interval); + + if (!ipban_config_read_inter("conf/common/inter-server.conf", imported)) + retval = false; + if (!ipban_config_read_connection(filename, config, imported)) + retval = false; + if (!ipban_config_read_dynamic(filename, config, imported)) + retval = false; + + return retval; } // check ip against active bans list diff --git a/src/login/login.c b/src/login/login.c index 6b422eef2..f1302b673 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -29,6 +29,7 @@ #include "login/lclif.h" #include "common/HPM.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/core.h" #include "common/db.h" #include "common/memmgr.h" @@ -43,6 +44,7 @@ #include #include +#include // stat() /** @file * Implementation of the login interface. @@ -1064,13 +1066,14 @@ int login_mmo_auth(struct login_session_data* sd, bool isServer) { if (login->config->use_dnsbl) { char r_ip[16]; char ip_dnsbl[256]; - char* dnsbl_serv; uint8* sin_addr = (uint8*)&sockt->session[sd->fd]->client_addr; + int i; sprintf(r_ip, "%u.%u.%u.%u", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); - for (dnsbl_serv = strtok(login->config->dnsbl_servs,","); dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",")) { - sprintf(ip_dnsbl, "%s.%s", r_ip, trim(dnsbl_serv)); + for (i = 0; i < VECTOR_LENGTH(login->config->dnsbl_servers); i++) { + char *dnsbl_server = VECTOR_INDEX(login->config->dnsbl_servers, i); + sprintf(ip_dnsbl, "%s.%s", r_ip, trim(dnsbl_server)); if (sockt->host2ip(ip_dnsbl)) { ShowInfo("DNSBL: (%s) Blacklisted. User Kicked.\n", r_ip); return 3; @@ -1450,150 +1453,431 @@ void login_config_set_defaults(void) login->config->dynamic_pass_failure_ban_limit = 7; login->config->dynamic_pass_failure_ban_duration = 5; login->config->use_dnsbl = false; - safestrncpy(login->config->dnsbl_servs, "", sizeof(login->config->dnsbl_servs)); + VECTOR_INIT(login->config->dnsbl_servers); login->config->client_hash_check = 0; login->config->client_hash_nodes = NULL; } -//----------------------------------- -// Reading main configuration file -//----------------------------------- -int login_config_read(const char *cfgName) +/** + * Reads 'login_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 login_config_read_inter(const char *filename, struct config_t *config, bool imported) { - char line[1024], w1[1024], w2[1024]; - FILE* fp; - nullpo_retr(1, cfgName); - fp = fopen(cfgName, "r"); - if (fp == NULL) { - ShowError("Configuration file (%s) not found.\n", cfgName); - return 1; + struct config_setting_t *setting = NULL; + const char *str = NULL; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "login_configuration/inter")) == NULL) { + if (imported) + return true; + ShowError("login_config_read: login_configuration/inter 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) + libconfig->setting_lookup_uint16(setting, "login_port", &login->config->login_port); + + if (libconfig->setting_lookup_uint32(setting, "ip_sync_interval", &login->config->ip_sync_interval) == CONFIG_TRUE) + login->config->ip_sync_interval *= 1000*60; // In minutes + + if (libconfig->setting_lookup_string(setting, "bind_ip", &str) == CONFIG_TRUE) { + char old_ip_str[16]; + sockt->ip2str(login->config->login_ip, old_ip_str); + + if ((login->config->login_ip = sockt->host2ip(str)) != 0) + ShowStatus("Login server binding IP address : %s -> %s\n", old_ip_str, str); + } + + return true; +} + +/** + * Reads 'login_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 login_config_read_console(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, "login_configuration/console")) == NULL) { + if (imported) + return true; + ShowError("login_config_read: login_configuration/console was not found in %s!\n", filename); + return false; + } + + 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)); + + return true; +} + +/** + * Reads 'login_configuration.log' 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 login_config_read_log(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, "login_configuration/log")) == NULL) { + if (imported) + return true; + ShowError("login_config_read: login_configuration/log was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_bool_real(setting, "log_login", &login->config->log_login); + libconfig->setting_lookup_mutable_string(setting, "date_format", login->config->date_format, sizeof(login->config->date_format)); + return true; +} + +/** + * Reads 'login_configuration.account' 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 login_config_read_account(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + AccountDB *db = account_engine[0].db; + bool retval = true; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "login_configuration/account")) == NULL) { + if (imported) + return true; + ShowError("login_config_read: login_configuration/account was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_bool_real(setting, "new_account", &login->config->new_account_flag); + libconfig->setting_lookup_bool_real(setting, "new_acc_length_limit", &login->config->new_acc_length_limit); + + libconfig->setting_lookup_int(setting, "allowed_regs", &login->config->allowed_regs); + libconfig->setting_lookup_int(setting, "time_allowed", &login->config->time_allowed); + libconfig->setting_lookup_int(setting, "start_limited_time", &login->config->start_limited_time); + libconfig->setting_lookup_bool_real(setting, "use_MD5_passwords", &login->config->use_md5_passwds); + + if (!db->set_property(db, config, imported)) + retval = false; + if (!ipban_config_read(filename, config, imported)) + retval = false; + + return retval; +} + +/** + * Frees login->config->client_hash_nodes + **/ +void clear_client_hash_nodes(void) +{ + struct client_hash_node *node = login->config->client_hash_nodes; + + while (node != NULL) { + struct client_hash_node *next = node->next; + aFree(node); + node = next; + } + + login->config->client_hash_nodes = NULL; +} + +/** + * Reads information from login_configuration.permission.hash.md5_hashes. + * + * @param setting The setting to read from. + */ +void login_config_set_md5hash(struct config_setting_t *setting) +{ + int i; + int count = libconfig->setting_length(setting); + + clear_client_hash_nodes(); + + // There's no need to parse if it's disabled or if there's no list + if (count <= 0 || !login->config->client_hash_check) + return; + + for (i = 0; i < count; i++) { + int j; + int group_id = 0; + char md5hash[33]; + struct client_hash_node *nnode = NULL; + struct config_setting_t *item = libconfig->setting_get_elem(setting, i); + + if (item == NULL) continue; - if(!strcmpi(w1,"timestamp_format")) - safestrncpy(showmsg->timestamp_format, w2, 20); - else if(!strcmpi(w1,"stdout_with_ansisequence")) - showmsg->stdout_with_ansisequence = config_switch(w2) ? true : false; - else if(!strcmpi(w1,"console_silent")) { - showmsg->silent = atoi(w2); - if (showmsg->silent) /* only bother if we actually have this enabled */ - ShowInfo("Console Silent Setting: %d\n", atoi(w2)); - } - else if( !strcmpi(w1, "bind_ip") ) { - login->config->login_ip = sockt->host2ip(w2); - if (login->config->login_ip) { - char ip_str[16]; - ShowStatus("Login server binding IP address : %s -> %s\n", w2, sockt->ip2str(login->config->login_ip, ip_str)); - } + if (libconfig->setting_lookup_int(item, "group_id", &group_id) != CONFIG_TRUE) { + ShowWarning("login_config_set_md5hash: entry (%d) is missing group_id! Ignoring...\n", i); + continue; } - else if( !strcmpi(w1, "login_port") ) { - login->config->login_port = (uint16)atoi(w2); + + if (libconfig->setting_lookup_mutable_string(item, "hash", md5hash, sizeof(md5hash)) != CONFIG_TRUE) { + ShowWarning("login_config_set_md5hash: entry (%d) is missing hash! Ignoring...\n", i); + continue; } - else if(!strcmpi(w1, "log_login")) - login->config->log_login = (bool)config_switch(w2); - - else if(!strcmpi(w1, "new_account")) - login->config->new_account_flag = (bool)config_switch(w2); - else if(!strcmpi(w1, "new_acc_length_limit")) - login->config->new_acc_length_limit = (bool)config_switch(w2); - else if(!strcmpi(w1, "start_limited_time")) - login->config->start_limited_time = atoi(w2); - else if(!strcmpi(w1, "check_client_version")) - login->config->check_client_version = (bool)config_switch(w2); - else if(!strcmpi(w1, "client_version_to_connect")) - login->config->client_version_to_connect = (unsigned int)strtoul(w2, NULL, 10); - else if(!strcmpi(w1, "use_MD5_passwords")) - login->config->use_md5_passwds = (bool)config_switch(w2); - else if(!strcmpi(w1, "group_id_to_connect")) - login->config->group_id_to_connect = atoi(w2); - else if(!strcmpi(w1, "min_group_id_to_connect")) - login->config->min_group_id_to_connect = atoi(w2); - else if(!strcmpi(w1, "date_format")) - safestrncpy(login->config->date_format, w2, sizeof(login->config->date_format)); - else if(!strcmpi(w1, "allowed_regs")) //account flood protection system - login->config->allowed_regs = atoi(w2); - else if(!strcmpi(w1, "time_allowed")) - login->config->time_allowed = atoi(w2); - else if(!strcmpi(w1, "use_dnsbl")) - login->config->use_dnsbl = (bool)config_switch(w2); - else if(!strcmpi(w1, "dnsbl_servers")) - safestrncpy(login->config->dnsbl_servs, w2, sizeof(login->config->dnsbl_servs)); - else if(!strcmpi(w1, "ipban_cleanup_interval")) - login->config->ipban_cleanup_interval = (unsigned int)atoi(w2); - else if(!strcmpi(w1, "ip_sync_interval")) - login->config->ip_sync_interval = (unsigned int)1000*60*atoi(w2); //w2 comes in minutes. - else if(!strcmpi(w1, "client_hash_check")) - login->config->client_hash_check = config_switch(w2); - else if(!strcmpi(w1, "client_hash")) { - int group = 0; - char md5hash[33]; - memset(md5hash, '\0', 33); - - if (sscanf(w2, "%d, %32s", &group, md5hash) == 2) { - struct client_hash_node *nnode; - CREATE(nnode, struct client_hash_node, 1); - - if (strcmpi(md5hash, "disabled") == 0) { - nnode->hash[0] = '\0'; - } else { - int i; - for (i = 0; i < 32; i += 2) { - char buf[3]; - unsigned int byte; - - memcpy(buf, &md5hash[i], 2); - buf[2] = 0; - - sscanf(buf, "%x", &byte); - nnode->hash[i / 2] = (uint8)(byte & 0xFF); - } - } - - nnode->group_id = group; - nnode->next = login->config->client_hash_nodes; - - login->config->client_hash_nodes = nnode; + + CREATE(nnode, struct client_hash_node, 1); + if (strcmpi(md5hash, "disabled") == 0) { + nnode->hash[0] = '\0'; + } else { + for (j = 0; j < 32; j += 2) { + char buf[3]; + unsigned int byte; + + memcpy(buf, &md5hash[j], 2); + buf[2] = 0; + + sscanf(buf, "%x", &byte); + nnode->hash[j / 2] = (uint8)(byte & 0xFF); } } - else if(!strcmpi(w1, "import")) - login_config_read(w2); - else - { - AccountDB* db = account_engine[0].db; - if (db) - db->set_property(db, w1, w2); - ipban_config_read(w1, w2); - loginlog_config_read(w1, w2); - HPM->parseConf(w1, w2, HPCT_LOGIN); + nnode->group_id = group_id; + nnode->next = login->config->client_hash_nodes; // login->config->client_hash_nodes is initialized before calling this function + login->config->client_hash_nodes = nnode; + } + + return; +} + +/** + * Reads 'login_configuration/permission/hash' 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 login_config_read_permission_hash(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, "login_configuration/permission/hash")) == NULL) { + if (imported) + return true; + ShowError("login_config_read: login_configuration/permission/hash was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_bool_real(setting, "enabled", &login->config->client_hash_check); + + if ((setting = libconfig->lookup(config, "login_configuration/permission/hash/MD5_hashes")) != NULL) + login_config_set_md5hash(setting); + + return true; +} + +/** + * Clears login->config->dnsbl_servers, freeing any allocated memory. + */ +void clear_dnsbl_servers(void) +{ + while (VECTOR_LENGTH(login->config->dnsbl_servers) > 0) { + aFree(&VECTOR_POP(login->config->dnsbl_servers)); + } + VECTOR_CLEAR(login->config->dnsbl_servers); +} + +/** + * Reads information from login_config/permission/DNS_blacklist/dnsbl_servers. + * + * @param setting The configuration setting to read from. + */ +void login_config_set_dnsbl_servers(struct config_setting_t *setting) +{ + int i; + int count = libconfig->setting_length(setting); + + clear_dnsbl_servers(); + + // There's no need to parse if it's disabled + if (count <= 0 || !login->config->use_dnsbl) + return; + + VECTOR_ENSURE(login->config->dnsbl_servers, count, 1); + + for (i = 0; i < count; i++) { + const char *string = libconfig->setting_get_string_elem(setting, i); + + if (string == NULL || string[0] == '\0') + continue; + + VECTOR_PUSH(login->config->dnsbl_servers, aStrdup(string)); + } +} + +/** + * Reads 'login_configuration/permission/DNS_blacklist' 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 login_config_read_permission_blacklist(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, "login_configuration/permission/DNS_blacklist")) == NULL) { + if (imported) + return true; + ShowError("login_config_read: login_configuration/permission/DNS_blacklist was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_bool_real(setting, "enabled", &login->config->use_dnsbl); + + if ((setting = libconfig->lookup(config, "login_configuration/permission/DNS_blacklist/dnsbl_servers")) != NULL) + login_config_set_dnsbl_servers(setting); + + return true; +} + +/** + * Reads 'login_configuration.permission' 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 login_config_read_permission(const char *filename, struct config_t *config, bool imported) +{ + struct config_setting_t *setting = NULL; + bool retval = true; + + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "login_configuration/permission")) == NULL) { + if (imported) + return true; + ShowError("login_config_read: login_configuration/permission was not found in %s!\n", filename); + return false; + } + + libconfig->setting_lookup_int(setting, "group_id_to_connect", &login->config->group_id_to_connect); + libconfig->setting_lookup_int(setting, "min_group_id_to_connect", &login->config->min_group_id_to_connect); + libconfig->setting_lookup_bool_real(setting, "check_client_version", &login->config->check_client_version); + libconfig->setting_lookup_uint32(setting, "client_version_to_connect", &login->config->client_version_to_connect); + + if (!login_config_read_permission_hash(filename, config, imported)) + retval = false; + if (!login_config_read_permission_blacklist(filename, config, imported)) + retval = false; + + return retval; +} + +/** + * Reads the 'login-config' configuration 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 login_config_read(const char *filename, bool imported) +{ + struct config_t config; + const char *import = NULL; + bool retval = true; + + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; // Error message is already shown by libconfig->load_file + + if (!login_config_read_inter(filename, &config, imported)) + retval = false; + if (!login_config_read_console(filename, &config, imported)) + retval = false; + if (!login_config_read_log(filename, &config, imported)) + retval = false; + if (!login_config_read_account(filename, &config, imported)) + retval = false; + if (!login_config_read_permission(filename, &config, imported)) + retval = false; + + if (!loginlog_config_read("conf/common/inter-server.conf", imported)) // Only inter-server + retval = false; + + // TODO HPM->parseConf(w1, w2, HPCT_LOGIN); + + ShowInfo("Finished 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, login->LOGIN_CONF_NAME) == 0) { + ShowWarning("login_config_read: Loop detected in %s! Skipping 'import'...\n", filename); + } else { + if (!login->config_read(import, true)) + retval = false; } } - fclose(fp); - ShowInfo("Finished reading %s.\n", cfgName); - return 0; + + config_destroy(&config); + return retval; } //-------------------------------------- // Function called at exit of the server //-------------------------------------- -int do_final(void) { +int do_final(void) +{ int i; - struct client_hash_node *hn = login->config->client_hash_nodes; ShowStatus("Terminating...\n"); HPM->event(HPET_FINAL); - while (hn) { - struct client_hash_node *tmp = hn; - hn = hn->next; - aFree(tmp); - } + clear_client_hash_nodes(); + clear_dnsbl_servers(); login_log(0, "login server", 100, "login server shutdown"); @@ -1730,9 +2014,28 @@ int do_init(int argc, char** argv) // read login-server configuration login->config_set_defaults(); - login->LOGIN_CONF_NAME = aStrdup("conf/login-server.conf"); + login->LOGIN_CONF_NAME = aStrdup("conf/login/login-server.conf"); login->NET_CONF_NAME = aStrdup("conf/network.conf"); + { + // 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/login_conf.txt", "conf/import/login-server.conf"); + CHECK_OLD_LOCAL_CONF("conf/import/inter_conf.txt", "conf/import/inter-server.conf"); + +#undef CHECK_OLD_LOCAL_CONF + } + lclif->init(); HPM_login_do_init(); @@ -1741,7 +2044,7 @@ int do_init(int argc, char** argv) HPM->event(HPET_PRE_INIT); cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); - login_config_read(login->LOGIN_CONF_NAME); + login->config_read(login->LOGIN_CONF_NAME, false); sockt->net_config_read(login->NET_CONF_NAME); for( i = 0; i < ARRAYLENGTH(server); ++i ) diff --git a/src/login/login.h b/src/login/login.h index 36085ae91..5632e6529 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -97,8 +97,8 @@ struct Login_Config { uint32 login_ip; ///< the address to bind to uint16 login_port; ///< the port to bind to - unsigned int ipban_cleanup_interval; ///< interval (in seconds) to clean up expired IP bans - unsigned int ip_sync_interval; ///< interval (in minutes) to execute a DNS/IP update (for dynamic IPs) + uint32 ipban_cleanup_interval; ///< interval (in seconds) to clean up expired IP bans + uint32 ip_sync_interval; ///< interval (in minutes) to execute a DNS/IP update (for dynamic IPs) bool log_login; ///< whether to log login server actions or not char date_format[32]; ///< date format used in messages bool new_account_flag,new_acc_length_limit; ///< auto-registration via _M/_F ? / if yes minimum length is 4? @@ -113,13 +113,14 @@ struct Login_Config { bool ipban; ///< perform IP blocking (via contents of `ipbanlist`) ? bool dynamic_pass_failure_ban; ///< automatic IP blocking due to failed login attemps ? - unsigned int dynamic_pass_failure_ban_interval; ///< how far to scan the loginlog for password failures - unsigned int dynamic_pass_failure_ban_limit; ///< number of failures needed to trigger the ipban - unsigned int dynamic_pass_failure_ban_duration; ///< duration of the ipban + uint32 dynamic_pass_failure_ban_interval; ///< how far to scan the loginlog for password failures + uint32 dynamic_pass_failure_ban_limit; ///< number of failures needed to trigger the ipban + uint32 dynamic_pass_failure_ban_duration; ///< duration of the ipban bool use_dnsbl; ///< dns blacklist blocking ? - char dnsbl_servs[1024]; ///< comma-separated list of dnsbl servers + VECTOR_DECL(char *) dnsbl_servers; ///< dnsbl servers - int client_hash_check; ///< flags for checking client md5 + bool client_hash_check; ///< flags for checking client md5 + // TODO: VECTOR candidate struct client_hash_node *client_hash_nodes; ///< linked list containg md5 hash for each gm group }; @@ -207,7 +208,7 @@ struct login_interface { void (*char_server_connection_status) (int fd, struct login_session_data* sd, uint8 status); void (*parse_request_connection) (int fd, struct login_session_data* sd, const char *ip, uint32 ipl); void (*config_set_defaults) (void); - int (*config_read) (const char *cfgName); + bool (*config_read) (const char *filename, bool included); char *LOGIN_CONF_NAME; char *NET_CONF_NAME; ///< Network configuration filename }; diff --git a/src/login/loginlog.h b/src/login/loginlog.h index efb0873bd..589bc4fa1 100644 --- a/src/login/loginlog.h +++ b/src/login/loginlog.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 @@ -29,7 +29,7 @@ unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes); void login_log(uint32 ip, const char* username, int rcode, const char* message); bool loginlog_init(void); bool loginlog_final(void); -bool loginlog_config_read(const char* w1, const char* w2); +bool loginlog_config_read(const char *filename, bool imported); #endif // HERCULES_CORE #endif /* LOGIN_LOGINLOG_H */ diff --git a/src/login/loginlog_sql.c b/src/login/loginlog_sql.c index 16accfada..7dff14990 100644 --- a/src/login/loginlog_sql.c +++ b/src/login/loginlog_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,27 +23,22 @@ #include "loginlog.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/mmo.h" #include "common/nullpo.h" +#include "common/showmsg.h" #include "common/socket.h" #include "common/sql.h" #include "common/strlib.h" #include // exit -// global sql settings (in ipban_sql.c) -static char global_db_hostname[32] = "127.0.0.1"; -static uint16 global_db_port = 3306; -static char global_db_username[32] = "ragnarok"; -static char global_db_password[100] = "ragnarok"; -static char global_db_database[32] = "ragnarok"; -static char global_codepage[32] = ""; -// local sql settings -static char log_db_hostname[32] = ""; -static uint16 log_db_port = 0; -static char log_db_username[32] = ""; -static char log_db_password[100] = ""; -static char log_db_database[32] = ""; +// Sql settings +static char log_db_hostname[32] = "127.0.0.1"; +static uint16 log_db_port = 3306; +static char log_db_username[32] = "ragnarok"; +static char log_db_password[100] = "ragnarok"; +static char log_db_database[32] = "ragnarok"; static char log_codepage[32] = ""; static char log_login_db[256] = "loginlog"; @@ -102,42 +97,16 @@ void login_log(uint32 ip, const char* username, int rcode, const char* message) bool loginlog_init(void) { - const char* username; - const char* password; - const char* hostname; - uint16 port; - const char* database; - const char* codepage; - - if( log_db_hostname[0] != '\0' ) - {// local settings - username = log_db_username; - password = log_db_password; - hostname = log_db_hostname; - port = log_db_port; - database = log_db_database; - codepage = log_codepage; - } - else - {// global settings - username = global_db_username; - password = global_db_password; - hostname = global_db_hostname; - port = global_db_port; - database = global_db_database; - codepage = global_codepage; - } - sql_handle = SQL->Malloc(); - if( SQL_ERROR == SQL->Connect(sql_handle, username, password, hostname, port, database) ) - { + if (SQL_ERROR == SQL->Connect(sql_handle, log_db_username, log_db_password, + log_db_hostname, log_db_port, log_db_database)) { Sql_ShowDebug(sql_handle); SQL->Free(sql_handle); exit(EXIT_FAILURE); } - if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) ) + if (log_codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, log_codepage)) Sql_ShowDebug(sql_handle); enabled = true; @@ -152,60 +121,105 @@ bool loginlog_final(void) return true; } -bool loginlog_config_read(const char* key, const char* value) +/** + * Reads 'inter_configuration/database_names' and initializes required + * variables/Sets global configuration. + * + * @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 loginlog_config_read_names(const char *filename, struct config_t *config, bool imported) { - const char* signature; + struct config_setting_t *setting = NULL; - nullpo_ret(key); - nullpo_ret(value); - signature = "sql."; - if( strncmpi(key, signature, strlen(signature)) == 0 ) - { - key += strlen(signature); - if( strcmpi(key, "db_hostname") == 0 ) - safestrncpy(global_db_hostname, value, sizeof(global_db_hostname)); - else - if( strcmpi(key, "db_port") == 0 ) - global_db_port = (uint16)strtoul(value, NULL, 10); - else - if( strcmpi(key, "db_username") == 0 ) - safestrncpy(global_db_username, value, sizeof(global_db_username)); - else - if( strcmpi(key, "db_password") == 0 ) - safestrncpy(global_db_password, value, sizeof(global_db_password)); - else - if( strcmpi(key, "db_database") == 0 ) - safestrncpy(global_db_database, value, sizeof(global_db_database)); - else - if( strcmpi(key, "codepage") == 0 ) - safestrncpy(global_codepage, value, sizeof(global_codepage)); - else - return false;// not found - return true; + nullpo_retr(false, filename); + nullpo_retr(false, config); + + if ((setting = libconfig->lookup(config, "inter_configuration/database_names")) == NULL) { + if (imported) + return true; + ShowError("loginlog_config_read: inter_configuration/database_names was not found in %s!\n", filename); + return false; } - if( strcmpi(key, "log_db_ip") == 0 ) - safestrncpy(log_db_hostname, value, sizeof(log_db_hostname)); - else - if( strcmpi(key, "log_db_port") == 0 ) - log_db_port = (uint16)strtoul(value, NULL, 10); - else - if( strcmpi(key, "log_db_id") == 0 ) - safestrncpy(log_db_username, value, sizeof(log_db_username)); - else - if( strcmpi(key, "log_db_pw") == 0 ) - safestrncpy(log_db_password, value, sizeof(log_db_password)); - else - if( strcmpi(key, "log_db_db") == 0 ) - safestrncpy(log_db_database, value, sizeof(log_db_database)); - else - if( strcmpi(key, "log_codepage") == 0 ) - safestrncpy(log_codepage, value, sizeof(log_codepage)); - else - if( strcmpi(key, "log_login_db") == 0 ) - safestrncpy(log_login_db, value, sizeof(log_login_db)); - else + libconfig->setting_lookup_mutable_string(setting, "login_db", log_login_db, sizeof(log_login_db)); + + return true; +} + +/** + * Reads 'inter_configuration.log' and initializes required variables/Sets + * global configuration. + * + * @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 loginlog_config_read_log(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, "inter_configuration/log/sql_connection")) == NULL) { + if (imported) + return true; + ShowError("loginlog_config_read: inter_configuration/log/sql_connection was not found in %s!\n", filename); return false; + } + + libconfig->setting_lookup_mutable_string(setting, "db_hostname", log_db_hostname, sizeof(log_db_hostname)); + libconfig->setting_lookup_mutable_string(setting, "db_database", log_db_database, sizeof(log_db_database)); + libconfig->setting_lookup_mutable_string(setting, "db_username", log_db_username, sizeof(log_db_username)); + libconfig->setting_lookup_mutable_string(setting, "db_password", log_db_password, sizeof(log_db_password)); + + libconfig->setting_lookup_uint16(setting, "db_port", &log_db_port); + libconfig->setting_lookup_mutable_string(setting, "codepage", log_codepage, sizeof(log_codepage)); return true; } + +/** + * Reads 'inter_configuration' and initializes required variables/Sets global + * configuration. + * + * @param filename Path to configuration file. + * @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 loginlog_config_read(const char *filename, bool imported) +{ + struct config_t config; + const char *import = NULL; + bool retval = true; + + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; // Error message is already shown by libconfig->load_file + + if (!loginlog_config_read_names(filename, &config, imported)) + retval = false; + if (!loginlog_config_read_log(filename, &config, imported)) + retval = false; + + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, "conf/common/inter-server.conf") == 0) { + ShowWarning("inter_config_read: Loop detected! Skipping 'import'...\n"); + } else { + if (!loginlog_config_read(import, true)) + retval = false; + } + } + + libconfig->destroy(&config); + return retval; +} diff --git a/tools/configconverter.pl b/tools/configconverter.pl index c49dc95d9..435e4b246 100755 --- a/tools/configconverter.pl +++ b/tools/configconverter.pl @@ -57,18 +57,37 @@ sub cfg_add($$$$) { $output->{$variable} = {value => $value, print => $default->{print}, path => $default->{path}} unless $value eq $default->{default}; } -sub parsecfg_string($$$$) { +sub cfg_append($$$$) { my ($variable, $value, $default, $output) = @_; + for my $default_value (@{$default->{default}}) { + return if $value eq $default_value; + } + $output->{$variable} = {value => [], print => $default->{print}, path => $default->{path}} unless $output->{$variable}; + push(@{$output->{$variable}->{value}}, $value); +} + +sub parsecfg_string_sub($$$$$) { + my ($variable, $value, $default, $output, $func) = @_; if ($value =~ m{\s*"((?:\\"|.)*)"\s*(?://.*)?$}i) { - cfg_add($variable, $1, $default, $output); + $func->($variable, $1, $default, $output); return 1; } elsif ($value =~ m{\s*((?:\\"|.)*)\s*(?://.*)?$}i) { - cfg_add($variable, $1, $default, $output); + $func->($variable, $1, $default, $output); return 1; } return 0; } +sub parsecfg_string($$$$) { + my ($variable, $value, $default, $output) = @_; + return parsecfg_string_sub($variable, $value, $default, $output, \&cfg_add); +} + +sub parsecfg_stringarr($$$$) { + my ($variable, $value, $default, $output) = @_; + return parsecfg_string_sub($variable, $value, $default, $output, \&cfg_append); +} + sub parsecfg_int($$$$) { my ($variable, $value, $default, $output) = @_; if ($value =~ m{\s*(-?[0-9]+)\s*(?://.*)?$}) { @@ -189,6 +208,39 @@ sub printcfg_items($$$) { indent(")\n", $nestlevel); } +sub printcfg_md5hash($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: (\n", $nestlevel); + + for (@$value) { + my ($group_id, $hash) = split(/,/, $_, 2); + $group_id =~ s/\s*$//; $group_id =~ s/^\s*//; + $hash =~ s/\s*$//; $hash =~ s/^\s*//; + + indent("{\n", $nestlevel); + indent("group_id: $group_id\n", $nestlevel + 1); + indent("hash: \"$hash\"\n", $nestlevel + 1); + indent("},\n", $nestlevel); + } + + indent(")\n", $nestlevel); +} + +sub printcfg_strlist($$$) { + my ($variable, $value, $nestlevel) = @_; + + indent("$variable: (\n", $nestlevel); + + for my $string (split(/,/, $value)) { + $string =~ s/\s*$//; $string =~ s/^\s*//; + + indent("\"$string\",\n", $nestlevel + 1); + } + + indent(")\n", $nestlevel); +} + sub process_conf($$) { my ($files, $defaults) = @_; my $found = 0; @@ -271,7 +323,7 @@ my @defaults = ( inter_log_filename => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/log/", default => "log/inter.log"}, mysql_reconnect_type => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/type", default => 2}, mysql_reconnect_count => {parse => \&parsecfg_int, print => \&printcfg_int, path => "inter-server:inter_configuration/mysql_reconnect/count", default => 1}, - log_login_db => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "inter-server:inter_configuration/database_names/login_db", default => "loginlog"}, + log_login_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/login_db", default => "loginlog"}, char_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "char"}, interlog_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "interlog"}, ragsrvinfo_db => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/", default => "ragsrvinfo"}, @@ -340,6 +392,56 @@ my @defaults = ( import => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "conf/import/inter_conf.txt"}, } }, + { + files => ['login-server.conf', 'import/login_conf.txt'], + settings => { + bind_ip => {parse => \&parsecfg_string, print => \&printcfg_string, path => "login-server:login_configuration/inter/", default => "127.0.0.1"}, + login_port => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/inter/", default => 6900}, + timestamp_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "console:console/", default => "[%d/%b %H:%M]"}, + stdout_with_ansisequence => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "console:console/", default => "false"}, + console_silent => {parse => \&parsecfg_int, print => \&printcfg_int, path => "console:console/", default => 0}, + new_account => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "true"}, + new_acc_length_limit => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "true"}, + allowed_regs => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => 1}, + time_allowed => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => 10}, + log_login => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/log/", default => "true"}, + date_format => {parse => \&parsecfg_string, print => \&printcfg_string, path => "login-server:login_configuration/log/", default => "%Y-%m-%d %H:%M:%S"}, + group_id_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => -1}, + min_group_id_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => -1}, + start_limited_time => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/", default => -1}, + check_client_version => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/", default => "false"}, + client_version_to_connect => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/permission/", default => 20}, + use_MD5_passwords => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/", default => "false"}, + 'ipban.enable' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/ipban/enabled", default => "true"}, + 'ipban.sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + 'ipban.sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + 'ipban.sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + 'ipban.sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + 'ipban.sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + 'ipban.sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + 'ipban.sql.ipban_table' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/ipban_table", default => "ipbanlist"}, + 'ipban.dynamic_pass_failure_ban' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/enabled", default => "true"}, + 'ipban.dynamic_pass_failure_ban_interval' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_interval", default => 5}, + 'ipban.dynamic_pass_failure_ban_limit' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_limit", default => 7}, + 'ipban.dynamic_pass_failure_ban_duration' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/dynamic_pass_failure/ban_duration", default => 5}, + ipban_cleanup_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/account/ipban/cleanup_interval", default => 60}, + ip_sync_interval => {parse => \&parsecfg_int, print => \&printcfg_int, path => "login-server:login_configuration/inter/ip_sync_interval", default => 10}, + use_dnsbl => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/DNS_blacklist/enabled", default => "false"}, + dnsbl_servers => {parse => \&parsecfg_string, print => \&printcfg_strlist, path => "login-server:login_configuration/permission/DNS_blacklist/dnsbl_servers", default => "bl.blocklist.de, socks.dnsbl.sorbs.net"}, + 'account.sql.db_hostname' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_hostname", default => "127.0.0.1"}, + 'account.sql.db_port' => {parse => \&parsecfg_int, print => \&printcfg_int, path => "sql_connection:sql_connection/db_port", default => 3306}, + 'account.sql.db_username' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_username", default => "ragnarok"}, + 'account.sql.db_password' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_password", default => "ragnarok"}, + 'account.sql.db_database' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/db_database", default => "ragnarok"}, + 'account.sql.codepage' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "sql_connection:sql_connection/codepage", default => ""}, + 'account.sql.case_sensitive' => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "sql_connection:sql_connection/case_sensitive", default => "false"}, + 'account.sql.account_db' => {parse => \&parsecfg_string, print => \&printcfg_string, path => "inter-server:inter_configuration/database_names/account_db", default => "login"}, + client_hash_check => {parse => \&parsecfg_bool, print => \&printcfg_bool, path => "login-server:login_configuration/permission/hash/enabled", default => "false"}, + client_hash => {parse => \&parsecfg_stringarr, print => \&printcfg_md5hash, path => "login-server:login_configuration/permission/hash/MD5_hashes", default => []}, + 'account.sql.accreg_db' => {parse => \&parsecfg_string, print => \&printcfg_nil, path => "", default => "global_reg_value"}, + import => {parse => \&parsecfg_stringarr, print => \&printcfg_nil, path => "", default => ["conf/inter-server.conf", "conf/import/login_conf.txt"]}, + } + } ); for (@ARGV) { -- cgit v1.2.3-70-g09d2 From 9d70a6f590dbbd267e90bff3acee9e70eab2643c Mon Sep 17 00:00:00 2001 From: Haru Date: Sun, 21 Feb 2016 01:02:00 +0100 Subject: HPM Hooks Update --- src/plugins/HPMHooking/HPMHooking.Defs.inc | 4 ++-- src/plugins/HPMHooking/HPMHooking_login.Hooks.inc | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 31571f724..cc3724a13 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -3730,8 +3730,8 @@ typedef void (*HPMHOOK_pre_login_parse_request_connection) (int *fd, struct logi typedef void (*HPMHOOK_post_login_parse_request_connection) (int fd, struct login_session_data *sd, const char *ip, uint32 ipl); typedef void (*HPMHOOK_pre_login_config_set_defaults) (void); typedef void (*HPMHOOK_post_login_config_set_defaults) (void); -typedef int (*HPMHOOK_pre_login_config_read) (const char **cfgName); -typedef int (*HPMHOOK_post_login_config_read) (int retVal___, const char *cfgName); +typedef bool (*HPMHOOK_pre_login_config_read) (const char **filename, bool *included); +typedef bool (*HPMHOOK_post_login_config_read) (bool retVal___, const char *filename, bool included); #endif // LOGIN_LOGIN_H #ifdef CHAR_LOGINIF_H /* loginif */ typedef void (*HPMHOOK_pre_loginif_init) (void); diff --git a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc index 013a56104..290c2283a 100644 --- a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc @@ -4689,15 +4689,15 @@ void HP_login_config_set_defaults(void) { } return; } -int HP_login_config_read(const char *cfgName) { +bool HP_login_config_read(const char *filename, bool included) { int hIndex = 0; - int retVal___ = 0; + bool retVal___ = false; if( HPMHooks.count.HP_login_config_read_pre ) { - int (*preHookFunc) (const char **cfgName); + bool (*preHookFunc) (const char **filename, bool *included); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_login_config_read_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_login_config_read_pre[hIndex].func; - retVal___ = preHookFunc(&cfgName); + retVal___ = preHookFunc(&filename, &included); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -4705,13 +4705,13 @@ int HP_login_config_read(const char *cfgName) { } } { - retVal___ = HPMHooks.source.login.config_read(cfgName); + retVal___ = HPMHooks.source.login.config_read(filename, included); } if( HPMHooks.count.HP_login_config_read_post ) { - int (*postHookFunc) (int retVal___, const char *cfgName); + bool (*postHookFunc) (bool retVal___, const char *filename, bool included); for(hIndex = 0; hIndex < HPMHooks.count.HP_login_config_read_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_login_config_read_post[hIndex].func; - retVal___ = postHookFunc(retVal___, cfgName); + retVal___ = postHookFunc(retVal___, filename, included); } } return retVal___; -- cgit v1.2.3-70-g09d2 From 85d10885379bbe52930c233f02bf1c94ec86ac30 Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 11 Feb 2016 13:28:18 +0100 Subject: Ported map-server.conf to libconfig Ported to modern Hercules and cleaned up from Panikon's commits: ee48838b12d15902fc14738cfa46d58b39080d11, 55498ebb7ac5d28444d0b01506c88ef6874f6055, 6d1f8f50b0e7349bdab2c53bb172d0b036e47c04, 25dde7e46524ace330b83cb4bf0255cc4d796792 Signed-off-by: Haru --- .gitignore | 1 - conf/atcommand.conf | 2 +- conf/charhelp.txt | 28 - conf/global/console.conf | 8 + conf/help.txt | 307 ---------- conf/import-tmpl/map-server.conf | 32 + conf/import-tmpl/map_conf.txt | 0 conf/map-server.conf | 119 ---- conf/map/charhelp.txt | 28 + conf/map/help.txt | 307 ++++++++++ conf/map/map-server.conf | 117 ++++ conf/map/maps.conf | 1252 ++++++++++++++++++++++++++++++++++++++ conf/maps.conf | 1225 ------------------------------------- src/map/map.c | 449 ++++++++++---- src/map/map.h | 7 +- tools/configconverter.pl | 35 +- 16 files changed, 2111 insertions(+), 1806 deletions(-) delete mode 100644 conf/charhelp.txt delete mode 100644 conf/help.txt create mode 100644 conf/import-tmpl/map-server.conf delete mode 100644 conf/import-tmpl/map_conf.txt delete mode 100644 conf/map-server.conf create mode 100644 conf/map/charhelp.txt create mode 100644 conf/map/help.txt create mode 100644 conf/map/map-server.conf create mode 100644 conf/map/maps.conf delete mode 100644 conf/maps.conf (limited to 'src') diff --git a/.gitignore b/.gitignore index bd33fac60..eaf7a3aa3 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,6 @@ Thumbs.db /conf/import/*.conf /conf/import/battle_conf.txt /conf/import/log_conf.txt -/conf/import/map_conf.txt /conf/import/msg_conf.txt /conf/import/packet_conf.txt /conf/import/script_conf.txt diff --git a/conf/atcommand.conf b/conf/atcommand.conf index df4972067..175286eb0 100644 --- a/conf/atcommand.conf +++ b/conf/atcommand.conf @@ -68,5 +68,5 @@ nolog: { /* Commands help file */ help: { - @include "conf/help.txt" + @include "conf/map/help.txt" } diff --git a/conf/charhelp.txt b/conf/charhelp.txt deleted file mode 100644 index e3acddbb4..000000000 --- a/conf/charhelp.txt +++ /dev/null @@ -1,28 +0,0 @@ - 40:--- CHARACTER CMD --- - 40:#statsall - Set all stats of a player to maximum. - 40:#itemlist - Displays all items of a player. - 40:#storagelist - Displays all items of a player's storage. - 40:#stats - Displays a characters stats. - 60:#option - Like @option command but only to target character. - 50:#mountpeco - Give/remove to a player a peco (Class is required, but not skill). - 50:#petrename - Re-enable pet rename to a player. - 60:#save - Changes the target players respawn point. - 60:#baselvl/#blvl <#> - Change a characters base level. - 60:#joblvl/#jlvl <#> - Change a characters job level. - 60:#job/#jobchange - Changes target characters job. - 60:#zeny - Give/take a players Zeny - 60:#cash - Give/take a player cash points - 60:#points - Give/take a player Kafra points - 60:#stpoint - Give/take a players stat points - 60:#skpoint - give/take a players skill points - 60:#skreset - Reset skills of a character. - 60:#streset - Reset stats of a character. - 60:#reset - Reset stats AND skills of a character. - 60:#questskill <#> - Gives to a player the specified quest skill. - 60:#lostskill <#> - Takes away the specified quest skill from the player. - 60:#delitem - Remove items from a character - 50:#model - Changes a player's model - 60:#disguise - Changes disguise of a player - 60:#undisguise - Cancels disguise of a player - 60:#changesex - Changes sex of a player (all characters of the account) - 60:#warp/#rura+ - Warps character to location of choice diff --git a/conf/global/console.conf b/conf/global/console.conf index d26c48352..21ee46bd0 100644 --- a/conf/global/console.conf +++ b/conf/global/console.conf @@ -56,4 +56,12 @@ console: { // [CHAR] Display information on the console whenever characters/guilds/parties/pets are loaded/saved? save_log: true + + // [MAP] Makes server log selected message types to a file in the /log/ folder + //1: Log Warning Messages + //2: Log Error and SQL Error messages. + //4: Log Debug Messages + //Example: "console_msg_log: 7" logs all 3 kinds + //Messages logged by this overrides console_silent setting + console_msg_log: 0 } diff --git a/conf/help.txt b/conf/help.txt deleted file mode 100644 index a65c7de70..000000000 --- a/conf/help.txt +++ /dev/null @@ -1,307 +0,0 @@ -// This is help file that contains help messages for atcommands/charcommands. - -// Format: -// : "" - -// This file uses libconfig syntax. - -help: "Params: \n" "Shows help for specified command." -noask: "Auto rejects deals/invites." -me: "Params: \n" "Displays normal text as a message in this format: *name message* (like /me in mIRC)." -fakename: "Params: \n" "Changes your name to your choice temporarily." -npctalk: "Params: \n" "Forces a NPC to display a message in normal chat." -broadcast: "Params: \n" "Broadcasts a message with your name (in yellow)." -kami: "Params: \n" "Broadcasts a message without your name (in yellow)." -kamib: "Params: \n" "Broadcasts a message without your name (in blue)." -localbroadcast: "Params: \n" "Broadcasts a message with your name (in yellow) only on your map." -commands: "Displays a list of commands that you can use." -rates: "Displays the server's current rates." -uptime: "Displays how long the server has been online." -showdelay: "Shows/hides the \"There is a delay after this skill\" message." -exp: "Displays current levels and % progress." -mobinfo: "Params: \n" "Shows monster info (stats, exp, drops etc)." -iteminfo: "Params: \n" "Shows item info (type, price etc)." -whodrops: "Params: \n" "Shows who drops an item (monster with highest drop rates)." -version: "Displays SVN version of the server." -email: "Params: \n" "Changes your account e-mail address." -where: "Params: \n" "Tells you the location of a character." -time: "Shows the date and time of the server." -showexp: "Displays/hides experience gained." -showzeny: "Displays/hides Zeny gained." -mobsearch: "Params: \n" "Shows the location of a certain mob on the current map." -who: "Params: []\n" "Shows a list of online players and their party and guild." -who2: "Params: []\n" "Shows a list of online players and their job." -who3: "Params: []\n" "Shows a list of online players and their location." -whomap: "@whomap/@whomap2/@whomap3 [map] - like @who/@who2/@who3 but only for specified map." -whogm: "Params: [match_text] - Like @who+@who2+who3, but only for GM." -guildspy: "Params: - You will receive all messages of the guild channel (Chat logging must be enabled)" -partyspy: "@partyspy - You will receive all messages of the party channel (Chat logging must be enabled)" -mapinfo: "Params: [<0-3> [map]] - Give information about a map (general info +: 0: no more, 1: players, 2: NPC, 3: shops/chat)." -go: "Params: \n" "Warps you to a city.\n" - " -3: (Memo point 2) 14: louyang 31: mora\n" - " -2: (Memo point 1) 15: start point 32: dewata\n" - " -1: (Memo point 0) 16: prison/jail 33: malangdo island\n" - " 0: prontera 17: jawaii 34: malaya port\n" - " 1: morocc 18: ayothaya 35: eclage\n" - " 2: geffen 19: einbroch\n" - " 3: payon 20: lighthalzen\n" - " 4: alberta 21: einbech\n" - " 5: izlude 22: hugel\n" - " 6: aldebaran 23: rachel\n" - " 7: xmas (lutie) 24: veins\n" - " 8: comodo 25: moscovia\n" - " 9: yuno 26: midgard camp\n" - " 10: amatsu 27: manuk\n" - " 11: gonryun 28: splendide\n" - " 12: umbala 29: brasilis\n" - " 13: niflheim 30: el dicastes\n" -jumpto: "Params: \n" "Warps you to selected character." -follow: "Params: \n" "Follow a player." -mount: "Give/remove you a peco (Class is required, but not skill)" -disguise: "Params: \n" "Change your appearence to other players to a mob." -undisguise: "Restore your normal appearance." -disguiseguild: "Disguises all online characters of a guild." -undisguiseguild: "Restore the normal appearance of all characters of a guild." -model: "Params: - Changes your characters appearence." -size: "Params: <1-3> Changes your size (1-Smallest 2-Biggest 3-Normal)" -sizeall: "Changes the size of all players." -sizeguild: "Changes the size of all online characters of a guild." -hide: "Makes you character invisible (GM invisibility). Type again to become visible." -save: "Sets respawn point to current spot." -load: "Warps you to your save point." -warp: "Params: [ ]\n" "Warps you to the selected map and position." -jump: "Params: [ []]\n" "Randomly warps you like a flywing." -jobchange: "Params: \n" "Changes your job.\n" - "----- Novice / 1st Class -----\n" - " 0 Novice 1 Swordman 2 Magician 3 Archer\n" - " 4 Acolyte 5 Merchant 6 Thief\n" - "----- 2nd Class -----\n" - " 7 Knight 8 Priest 9 Wizard 10 Blacksmith\n" - " 11 Hunter 12 Assassin 14 Crusader 15 Monk\n" - " 16 Sage 17 Rogue 18 Alchemist 19 Bard\n" - " 20 Dancer\n" - "----- High Novice / High 1st Class -----\n" - "4001 Novice High 4002 Swordman High 4003 Magician High 4004 Archer High\n" - "4005 Acolyte High 4006 Merchant High 4007 Thief High\n" - "----- Transcendent 2nd Class -----\n" - "4008 Lord Knight 4009 High Priest 4010 High Wizard 4011 Whitesmith\n" - "4012 Sniper 4013 Assassin Cross 4015 Paladin 4016 Champion\n" - "4017 Professor 4018 Stalker 4019 Creator 4020 Clown\n" - "4021 Gypsy\n" - "----- 3rd Class (Regular) -----\n" - "4054 Rune Knight 4055 Warlock 4056 Ranger 4057 Arch Bishop\n" - "4058 Mechanic 4059 Guillotine Cross 4066 Royal Guard 4067 Sorcerer\n" - "4068 Minstrel 4069 Wanderer 4070 Sura 4071 Genetic\n" - "4072 Shadow Chaser\n" - "----- 3rd Class (Transcendent) -----\n" - "4060 Rune Knight 4061 Warlock 4062 Ranger 4063 Arch Bishop\n" - "4064 Mechanic 4065 Guillotine Cross 4073 Royal Guard 4074 Sorcerer\n" - "4075 Minstrel 4076 Wanderer 4077 Sura 4078 Genetic\n" - "4079 Shadow Chaser\n" - "----- Expanded Class -----\n" - " 23 Super Novice 24 Gunslinger 25 Ninja 4045 Super Baby\n" - "4046 Taekwon 4047 Star Gladiator 4049 Soul Linker 4050 Gangsi\n" - "4051 Death Knight 4052 Dark Collector 4190 Ex. Super Novice 4191 Ex. Super Baby\n" - "4211 Kagerou 4212 Oboro 4215 Rebellion\n" - "----- Baby Novice And Baby 1st Class -----\n" - "4023 Baby Novice 4024 Baby Swordman 4025 Baby Magician 4026 Baby Archer\n" - "4027 Baby Acolyte 4028 Baby Merchant 4029 Baby Thief\n" - "---- Baby 2nd Class ----\n" - "4030 Baby Knight 4031 Baby Priest 4032 Baby Wizard 4033 Baby Blacksmith\n" - "4034 Baby Hunter 4035 Baby Assassin 4037 Baby Crusader 4038 Baby Monk\n" - "4039 Baby Sage 4040 Baby Rogue 4041 Baby Alchemist 4042 Baby Bard\n" - "4043 Baby Dancer\n" - "---- Baby 3rd Class ----\n" - "4096 Baby Rune Knight 4097 Baby Warlock 4098 Baby Ranger 4099 Baby Arch Bishop\n" - "4100 Baby Mechanic 4101 Baby Glt. Cross 4102 Baby Royal Guard 4103 Baby Sorcerer\n" - "4104 Baby Minstrel 4105 Baby Wanderer 4106 Baby Sura 4107 Baby Genetic\n" - "4108 Baby Shadow Chaser\n" - "---- Modes And Others ----\n" - " 22 Wedding 26 Christmas 27 Summer 4048 Star Gladiator (Union)\n" -option: "Params: (stackable) (stackable)\n" "Adds different visual effects on or around your character.\n" -" \n" -"01: Stone 01: Sight 01: Sight 512: Cart Lv. 4\n" -"02: Frozen 02: Curse 02: Hiding 1024: Cart Lv. 5\n" -"03: Stun 04: Silence 04: Cloaking 2048: Orc Head\n" -"04: Sleep 08: Signum 08: Cart Lv. 1 4096: Wedding\n" -"06: Petrify 16: Blind 16: Falcon 8192: Ruwach\n" -"07: Burning 32: Angelus 32: Riding 16384: Chasewalk\n" -"08: Imprison 64: Bleeding 64: Invisible\n" -"16: (Nothing) 128: D. Poison 128: Cart Lv. 2\n" -"32: (Nothing) 256: Fear 256: Cart Lv. 3" -heal: "Params: [ ]\n" "Heals the desired amount of HP and SP. No value specified will do a full heal." -dye: "Params: \n" "Changes your characters clothes color." -hairstyle: "Params: \n" "Changes your hair style." -haircolor: "Params \n" "Changes your hair color." -speed: "Params: <1-1000>\n" "Changes you walking speed. 1 being the fastest and 1000 the slowest. Default is 150." -effect: "Params: []\n" "Give an effect to your character." -dropall: "Throws all your possession on the ground." -storeall: "Puts all your possessions in storage." -killable: "Make your character killable." -memo: "Params: [memo position]\n" "Set/change a memo location (no position: display memo points)." -spiritball: "Params: <1-100>\n" "Gives you \"spirit spheres\" like from the skill \"Call Spirits\".\n" -questskill: "Params: <#>\n" "Gives you the specified quest skill\n" -"Novice = 142: First Aid, 143: Act Dead\n" -"Archer = 147: Create Arrow, 148: Charge Arrow\n" -"Swordman = 144: Moving HP Recovery, 145: Attack Weak Point, 146: Auto Berserk\n" -"Acolyte = 156: Holy Light\n" -"Thief = 149: Throw Sand, 150: Back Sliding, 151: Take Stone, 152: Throw Stone\n" -"Merchant = 153: Cart Revolution, 154: Change Cart, 155: Crazy Uproar, 2535: Open Buying Store\n" -"Magician = 157: Energy Coat\n" -"Hunter = 1009: Phantasmic Arrow\n" -"Bard = 1010: Pang Voice\n" -"Dancer = 1011: Wink of Charm\n" -"Knight = 1001: Charge Attack\n" -"Crusader = 1002: Shrink\n" -"Priest = 1014: Redemptio\n" -"Monk = 1015: Ki Translation, 1016: Ki Explosio\n" -"Assassin = 1003: Sonic Acceleration, 1004: Throw Venom Knife\n" -"Rogue = 1005: Close Confine\n" -"Blacksmith = 1012: Unfair Trick, 1013: Greed\n" -"Alchemist = 238: Basis of Life\n" -"Wizard = 1006: Sight Blaster\n" -"Sage = 1007: Create Elemental Converter, 1008: Elemental Change (Water), 1017: Elemental Change (Earth), 1018: Elemental Change (Fire), 1019: Elemental Change (Wind)" -lostskill: "Params: <#>\n" "Takes away the specified quest skill from you\n" -"Novice = 142: First Aid, 143: Act Dead\n" -"Archer = 147: Create Arrow, 148: Charge Arrow\n" -"Swordman = 144: Moving HP Recovery, 145: Attack Weak Point, 146: Auto Berserk\n" -"Acolyte = 156: Holy Light\n" -"Thief = 149: Throw Sand, 150: Back Sliding, 151: Take Stone, 152: Throw Stone\n" -"Merchant = 153: Cart Revolution, 154: Change Cart, 155: Crazy Uproar, 2535: Open Buying Store\n" -"Magician = 157: Energy Coat\n" -"Hunter = 1009: Phantasmic Arrow\n" -"Bard = 1010: Pang Voice\n" -"Dancer = 1011: Wink of Charm\n" -"Knight = 1001: Charge Attack\n" -"Crusader = 1002: Shrink\n" -"Priest = 1014: Redemptio\n" -"Monk = 1015: Ki Translation, 1016: Ki Explosio\n" -"Assassin = 1003: Sonic Acceleration, 1004: Throw Venom Knife\n" -"Rogue = 1005: Close Confine\n" -"Blacksmith = 1012: Unfair Trick, 1013: Greed\n" -"Alchemist = 238: Basis of Life\n" -"Wizard = 1006: Sight Blaster\n" -"Sage = 1007: Create Elemental Converter, 1008: Elemental Change (Water), 1017: Elemental Change (Earth), 1018: Elemental Change (Fire), 1019: Elemental Change (Wind)" -skillid: "Params: \n" "Look up a skill by name" -useskill: "Params: \n" "Use a skill on target" -skilltree: "Params: \n" "Prints the skill tree needed to get a skill for the target player." -marry: "Params: \n" "Marry another player." -divorce: "Divorce player." -alive: "Revives yourself from death." -blvl: "Params: \n" "Raises your base level the desired number of levels." -jlvl: "Params: \n" "Raises your job level the desired number of levels." -allskill: "Give you all skills." -stpoint: "Params: - Gives you the desired number of stat points." -skpoint: "Params: - Gives you the desired number of skill points." -zeny: "Params: - Gives you desired amount of Zeny." -cash: "Params: - Gives you the specified amount of cash points." -points: "Params: - Gives you the specified amount of Kafra Points." -str: "Params: \n" "Raises STR by given amount." -agi: "Params: \n" "Raises AGI by given amount." -dex: "Params: \n" "Raises DEX by given amount." -vit: "Params: \n" "Raises VIT by given amount." -int: "Params: \n" "Raises INT by given amount." -luk: "Params: \n" "Raises LUK by given amount." -allstats: "Params: \n" "Adds value in all stats (maximum if no value)." -addwarp: "Params: \n" -killmonster2: "Kills all monsters of your map (without drops)." -monster: "Params: [ [ [ []]]]\n" - "@monster2 [ [ []]]\n" -"@spawn/@monster/@summon/@monster2 \"desired monster name\" [ [ []]]\n" -"@spawn/@monster/@summon/@monster2 \"desired monster name\" [ [ []]]\n" -" Spawns the desired monster with any desired name." -monstersmall: "Params: \n" "Spawns a smaller version of a monster." -monsterbig: "Params: \n" "Spawns a larger version of a monster." -killmonster: "Params: \n" "Kill all monsters of the map (they drop)" -autoloot: "Params: \n" "Makes items go straight into your inventory." -autotrade: "Allows you to vend while you are offline." -changegm: "Params: \n" "Changes the leader of your guild (You must be guild leader)" -changeleader: "Params: \n" "Changes the leader of your party (You must be party leader)" -request: "Params: \n" "Sends a message to all connected GMs (via the gm whisper system)" -sound: "Params: \n" "Plays a sound from the data folder or GRF file located on the client." -clone: "Params: \n" "Spawns a supportive clone of the given player." -slaveclone: "Params: \n" "Spawns a supportive clone of the given player that follows the creator around." -evilclone: "Params: \n" "Spawns an aggressive clone of the given player." -changesex: "Changes your gender." -duel: "Starts a duel." -invite: "Invites a player to a duel." -accept: "Accepts an invitation to a duel." -reject: "Rejects an invitation to a duel." -leave: "Leaves a duel." -mail: "Open mail box." -storage: "Opens storage." -itemreset: "Remove all your items." -guildstorage: "Opens guild storage." -idsearch: "Params: \n" "Search all items that name have part_of_item_name" -refine: "Params: <+/- amount>" -produce: "Params: <# of very's>\n" -" Element: 0=None 1=Ice 2=Earth 3=Fire 4=Wind\n" -" You can add up to 3 Star Crumbs and 1 element\n" -repairall: "Repair all items of your inventory" -item: "Params: \n" "Gives you the desired item." -item2: "Params: \n" "Gives you the desired item." -pvpon: "Turns pvp on on the current map" -pvpoff: "Turns pvp off on the current map" -gvgon: "Turns gvg on on the current map" -gvgoff: "Turns gvg off on the current map" -agitstart: "Starts War of Emperium" -agitend: "End War of Emperium" -party: "Params: \n" "Create a party." -guild: "Params: \n" "Create a guild." -glvl: "Params: <# of levels>\n" "Raise Guild by desired number of levels" -guildrecall: "Params: \n" "Warps all online characters of a guild to you." -partyrecall: "Params: \n" "Warps all online characters of a party to you." -petrename: "Re-enable pet rename" -pettalk: "Params: \n" "Makes your pet say a message." -petfriendly: "Params: <#>\n" "Set pet friendly amount (0-1000) 1000 = Max" -pethungry: "Params: <#>\n" "Set pet hungry amount (0-100) 100 = Max" -hatch: "Create a pet from your inventory eggs list." -makeegg: "Params: \n" "Gives pet egg for monster number in pet DB" -kick: "Params: \n" "Kicks specified character off the server" -unjail: "Params: \n" "Discharges specified character/prisoner" -kill: "Params: \n" "Kills player." -recall: "Params: \n" "Warps target character to you." -raise: "Params: \n" "Revives target character." -block: "Params: \n" "Permanently blocks an account." -unblock: "Params: \n" "Unblocks an account." -ban: "Params: