From af5561086ad33bd4d166104d758f48d1d3cc6186 Mon Sep 17 00:00:00 2001 From: lighta Date: Mon, 28 Apr 2014 13:35:57 -0400 Subject: [PATCH 1/7] Merging char-refact part 1 This is just a temporary not totally nor functionnal merge of char- refact. DO NOT use for prod unless edit. --- src/char/CMakeLists.txt | 8 + src/char/Makefile.in | 6 +- src/char/char.c | 1975 +++++++++++++------------------------- src/char/char.h | 301 ++++-- src/char/char_clif.c | 1116 +++++++++++++++++++++ src/char/char_clif.h | 65 ++ src/char/char_cnslif.c | 77 ++ src/char/char_cnslif.h | 25 + src/char/char_logif.c | 653 +++++++++++++ src/char/char_logif.h | 52 + src/char/char_mapif.c | 1278 ++++++++++++++++++++++++ src/char/char_mapif.h | 66 ++ src/char/int_auction.c | 11 +- src/char/int_elemental.c | 28 +- src/char/int_guild.c | 131 +-- src/char/int_homun.c | 25 +- src/char/int_mail.c | 27 +- src/char/int_mercenary.c | 20 +- src/char/int_party.c | 73 +- src/char/int_pet.c | 12 +- src/char/int_quest.c | 8 +- src/char/int_storage.c | 24 +- src/char/inter.c | 49 +- src/common/cli.c | 66 +- src/common/cli.h | 14 +- src/common/evdp.h | 2 +- src/common/malloc.c | 2 + src/common/mmo.h | 1 + src/common/mutex.c | 2 +- src/common/timer.h | 1 + 30 files changed, 4521 insertions(+), 1597 deletions(-) create mode 100644 src/char/char_clif.c create mode 100644 src/char/char_clif.h create mode 100644 src/char/char_cnslif.c create mode 100644 src/char/char_cnslif.h create mode 100644 src/char/char_logif.c create mode 100644 src/char/char_logif.h create mode 100644 src/char/char_mapif.c create mode 100644 src/char/char_mapif.h diff --git a/src/char/CMakeLists.txt b/src/char/CMakeLists.txt index 22b793bef9..03e6980f6e 100644 --- a/src/char/CMakeLists.txt +++ b/src/char/CMakeLists.txt @@ -12,6 +12,10 @@ if( BUILD_SQL_SERVERS ) message( STATUS "Creating target char-server_sql" ) set( SQL_CHAR_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/char.h" + "${CMAKE_CURRENT_SOURCE_DIR}/char_clif.h" + "${CMAKE_CURRENT_SOURCE_DIR}/char_cnslif.h" + "${CMAKE_CURRENT_SOURCE_DIR}/char_logif.h" + "${CMAKE_CURRENT_SOURCE_DIR}/char_mapif.h" "${CMAKE_CURRENT_SOURCE_DIR}/int_auction.h" "${CMAKE_CURRENT_SOURCE_DIR}/int_elemental.h" "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.h" @@ -26,6 +30,10 @@ set( SQL_CHAR_HEADERS ) set( SQL_CHAR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/char.c" + "${CMAKE_CURRENT_SOURCE_DIR}/char_clif.c" + "${CMAKE_CURRENT_SOURCE_DIR}/char_cnslif.c" + "${CMAKE_CURRENT_SOURCE_DIR}/char_logif.c" + "${CMAKE_CURRENT_SOURCE_DIR}/char_mapif.c" "${CMAKE_CURRENT_SOURCE_DIR}/int_auction.c" "${CMAKE_CURRENT_SOURCE_DIR}/int_elemental.c" "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.c" diff --git a/src/char/Makefile.in b/src/char/Makefile.in index 97a406aa22..b180880274 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -15,8 +15,9 @@ LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_H = ../common/sql.h -CHAR_OBJ = char.o inter.o int_party.o int_guild.o \ - int_storage.o int_pet.o int_homun.o int_mail.o int_auction.o int_quest.o int_mercenary.o int_elemental.o +CHAR_OBJ = $(shell ls *.c | sed -e "s/.c/.o/g") +#CHAR_OBJ = char.o char_clif.o char_logif.o char_mapif.o char_cnslif.o \ + inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o int_mail.o int_auction.o int_quest.o int_mercenary.o int_elemental.o CHAR_SQL_OBJ = $(CHAR_OBJ:%=obj_sql/%) CHAR_H = $(shell ls ../char/*.h) @@ -50,6 +51,7 @@ help: ##################################################################### + char-server: obj_sql $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a @echo " LD @OCHR@@EXEEXT@" @@CC@ @LDFLAGS@ -o ../../@OCHR@@EXEEXT@ $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ diff --git a/src/char/char.c b/src/char/char.c index 55a2435622..7fc0512a74 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1,6 +1,15 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder + +#include +#include +#include +#include +#include +#include +#include + #include "../common/cbasetypes.h" #include "../common/core.h" #include "../common/db.h" @@ -21,98 +30,42 @@ #include "int_elemental.h" #include "int_party.h" #include "int_storage.h" -#include "char.h" #include "inter.h" +#include "char_logif.h" +#include "char_mapif.h" +#include "char_cnslif.h" +#include "char_clif.h" +#include "char.h" -#include -#include -#include -#include -#include -#include -#include +//definition of exported var declared in .h +int login_fd=-1; //login file descriptor +int char_fd=-1; //char file descriptor +struct Schema_Config schema_config; +struct CharServ_Config charserv_config; +struct mmo_map_server map_server[MAX_MAP_SERVERS]; +//Custom limits for the fame lists. [Skotlex] +int fame_list_size_chemist = MAX_FAME_LIST; +int fame_list_size_smith = MAX_FAME_LIST; +int fame_list_size_taekwon = MAX_FAME_LIST; +// Char-server-side stored fame lists [DracoRPG] +struct fame_list smith_fame_list[MAX_FAME_LIST]; +struct fame_list chemist_fame_list[MAX_FAME_LIST]; +struct fame_list taekwon_fame_list[MAX_FAME_LIST]; -#define MAX_STARTITEM 32 //max number of items a new players can start with #define CHAR_MAX_MSG 300 //max number of msg_conf static char* msg_table[CHAR_MAX_MSG]; // Login Server messages_conf -char char_db[256] = "char"; -char scdata_db[256] = "sc_data"; -char skillcooldown_db[256] = "skillcooldown"; -char cart_db[256] = "cart_inventory"; -char inventory_db[256] = "inventory"; -char charlog_db[256] = "charlog"; -char storage_db[256] = "storage"; -char interlog_db[256] = "interlog"; -char reg_db[256] = "global_reg_value"; -char skill_db[256] = "skill"; -char memo_db[256] = "memo"; -char guild_db[256] = "guild"; -char guild_alliance_db[256] = "guild_alliance"; -char guild_castle_db[256] = "guild_castle"; -char guild_expulsion_db[256] = "guild_expulsion"; -char guild_member_db[256] = "guild_member"; -char guild_position_db[256] = "guild_position"; -char guild_skill_db[256] = "guild_skill"; -char guild_storage_db[256] = "guild_storage"; -char party_db[256] = "party"; -char pet_db[256] = "pet"; -char mail_db[256] = "mail"; // MAIL SYSTEM -char auction_db[256] = "auction"; // Auctions System -char friend_db[256] = "friends"; -char hotkey_db[256] = "hotkey"; -char quest_db[256] = "quest"; -char homunculus_db[256] = "homunculus"; -char skill_homunculus_db[256] = "skill_homunculus"; -char mercenary_db[256] = "mercenary"; -char mercenary_owner_db[256] = "mercenary_owner"; -char elemental_db[256] = "elemental"; -char ragsrvinfo_db[256] = "ragsrvinfo"; -char bonus_script_db[256] = "bonus_script"; +// check for exit signal +// 0 is saving complete +// other is char_id +unsigned int save_flag = 0; -// show loading/saving messages -int save_log = 1; -static DBMap* char_db_; /// int char_id -> struct mmo_charstatus* -int db_use_sqldbs; - -struct mmo_map_server { - int fd; - uint32 ip; - uint16 port; - int users; - unsigned short map[MAX_MAP_PER_SERVER]; -} server[MAX_MAP_SERVERS]; - -int login_fd=-1, char_fd=-1; -char userid[24]; -char passwd[24]; -char server_name[20]; -char wisp_server_name[NAME_LENGTH] = "Server"; -char login_ip_str[128]; -uint32 login_ip = 0; -uint16 login_port = 6900; -char char_ip_str[128]; -uint32 char_ip = 0; -char bind_ip_str[128]; -uint32 bind_ip = INADDR_ANY; -uint16 char_port = 6121; -int char_maintenance = 0; -bool char_new = true; -int char_new_display = 0; - -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 authorised 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] -char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the requested name cannot be determined -#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 you can delete character [Lupus] -int char_del_delay = 86400; -int char_del_option = 2; // Character deletion type, email = 1, birthdate = 2 (default) - -int log_char = 1; // loggin char or not [devil] -int log_inter = 1; // loggin inter or not [devil] -int char_check_db = 1; ///cheking sql-table at begining ? +#define MAX_STARTITEM 32 +struct startitem { + int nameid; //Item ID + int amount; //Number of items + int pos; //Position (for auto-equip) +} start_items[MAX_STARTITEM+1]; // Advanced subnet check [LuzZza] struct s_subnet { @@ -122,76 +75,11 @@ struct s_subnet { } subnet[16]; int subnet_count = 0; -struct char_session_data { - bool auth; // whether the session is authed or not - int account_id, login_id1, login_id2, sex; - int found_char[MAX_CHARS]; // ids of chars on this account - char email[40]; // e-mail (default: a@a.com) by [Yor] - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - int group_id; // permission - uint8 char_slots; // total number of characters that can be created - uint8 chars_vip; - uint8 chars_billing; - uint32 version; - uint8 clienttype; - char new_name[NAME_LENGTH]; - char birthdate[10+1]; // YYYY-MM-DD - // Pincode system - char pincode[PINCODE_LENGTH+1]; - uint32 pincode_seed; - time_t pincode_change; - uint16 pincode_try; - // Addon system - int bank_vault; - unsigned int char_moves[MAX_CHARS]; // character moves left - uint8 isvip; - time_t unban_time[MAX_CHARS]; - int charblock_timer; -}; - -struct startitem { - int nameid; //Item ID - int amount; //Number of items - int pos; //Position (for auto-equip) -} start_items[MAX_STARTITEM+1]; - -int max_connect_user = -1; -int gm_allow_group = -1; -int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; -int start_zeny = 0; -int guild_exp_rate = 100; - -// Pincode system -#define PINCODE_OK 0 -#define PINCODE_ASK 1 -#define PINCODE_NOTSET 2 -#define PINCODE_EXPIRED 3 -#define PINCODE_NEW 4 -#define PINCODE_PASSED 7 -#define PINCODE_WRONG 8 - -bool pincode_enabled = true; -int pincode_changetime = 0; -int pincode_maxtry = 3; -bool pincode_force = true; - -void pincode_check( int fd, struct char_session_data* sd ); -void pincode_change( int fd, struct char_session_data* sd ); -void pincode_setnew( int fd, struct char_session_data* sd ); -void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state ); -void pincode_notifyLoginPinUpdate( int account_id, char* pin ); -void pincode_notifyLoginPinError( int account_id ); -void pincode_decrypt( uint32 userSeed, char* pin ); -int pincode_compare( int fd, struct char_session_data* sd, char* pin ); - int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid); int loginif_reqvipdata(uint32 aid, uint8 type, int add_vip_time, int mapfd); int loginif_parse_vipack(int fd); // Addon system -bool char_move_enabled = true; -bool char_movetoused = true; -bool char_moves_unlimited = false; void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to ); void moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ); @@ -200,75 +88,29 @@ int loginif_BankingReq(int32 account_id, int8 type, int32 data); int loginif_parse_BankingAck(int fd); int mapif_BankingAck(int32 account_id, int32 bank_vault); -//Custom limits for the fame lists. [Skotlex] -int fame_list_size_chemist = MAX_FAME_LIST; -int fame_list_size_smith = MAX_FAME_LIST; -int fame_list_size_taekwon = MAX_FAME_LIST; - -// Char-server-side stored fame lists [DracoRPG] -struct fame_list smith_fame_list[MAX_FAME_LIST]; -struct fame_list chemist_fame_list[MAX_FAME_LIST]; -struct fame_list taekwon_fame_list[MAX_FAME_LIST]; //Bonus Script void bonus_script_get(int fd);///Get bonus_script data void bonus_script_save(int fd); ///Save bonus_script data -// check for exit signal -// 0 is saving complete -// other is char_id -unsigned int save_flag = 0; -// Initial position (it's possible to set it in conf file) -struct point start_point = { 0, 53, 111 }; - -int console = 0; - -//----------------------------------------------------- -// Auth database -//----------------------------------------------------- -#define AUTH_TIMEOUT 30000 - -struct auth_node { - int account_id; - int char_id; - uint32 login_id1; - uint32 login_id2; - uint32 ip; - int sex; - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - int group_id; - unsigned changing_mapservers : 1; - uint8 version; -}; - -static DBMap* auth_db; // int account_id -> struct auth_node* - -//----------------------------------------------------- -// Online User Database -//----------------------------------------------------- - -struct online_char_data { - int account_id; - int char_id; - int fd; - int waiting_disconnect; - short server; // -2: unknown server, -1: not connected, 0+: id of server - bool pincode_success; -}; - -static DBMap* online_char_db; // int account_id -> struct online_char_data* -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); +int char_chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); int delete_char_sql(int char_id); +DBMap* auth_db; // int account_id -> struct auth_node* +DBMap* online_char_db; // int account_id -> struct online_char_data* +DBMap* char_db_; // int char_id -> struct mmo_charstatus* +DBMap* char_get_authdb() { return auth_db; } +DBMap* char_get_onlinedb() { return online_char_db; } +DBMap* char_get_chardb() { return char_db_; } + int loginif_isconnected(); #define loginif_check(a) { if(!loginif_isconnected()) return a; } /** * @see DBCreateData */ -static DBData create_online_char_data(DBKey key, va_list args) -{ +DBData char_create_online_data(DBKey key, va_list args){ struct online_char_data* character; CREATE(character, struct online_char_data, 1); character->account_id = key.i; @@ -279,50 +121,42 @@ static DBData create_online_char_data(DBKey key, va_list args) return db_ptr2data(character); } -void set_char_charselect(int account_id) -{ +void char_set_charselect(int account_id) { struct online_char_data* character; - character = (struct online_char_data*)idb_ensure(online_char_db, account_id, create_online_char_data); + character = (struct online_char_data*)idb_ensure(online_char_db, account_id, char_create_online_data); if( character->server > -1 ) - if( server[character->server].users > 0 ) // Prevent this value from going negative. - server[character->server].users--; + if( map_server[character->server].users > 0 ) // Prevent this value from going negative. + map_server[character->server].users--; character->char_id = -1; character->server = -1; if(character->waiting_disconnect != INVALID_TIMER) { - delete_timer(character->waiting_disconnect, chardb_waiting_disconnect); + delete_timer(character->waiting_disconnect, char_chardb_waiting_disconnect); character->waiting_disconnect = INVALID_TIMER; } - if (loginif_isconnected()) - { - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x272b; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); - } + chlogif_send_setacconline(account_id); } -void set_char_online(int map_id, int char_id, int account_id) -{ +void char_set_char_online(int map_id, int char_id, int account_id) { struct online_char_data* character; struct mmo_charstatus *cp; //Update DB - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) ) Sql_ShowDebug(sql_handle); //Check to see for online conflicts - character = (struct online_char_data*)idb_ensure(online_char_db, account_id, create_online_char_data); + character = (struct online_char_data*)idb_ensure(online_char_db, account_id, char_create_online_data); if( character->char_id != -1 && character->server > -1 && character->server != map_id ) { ShowNotice("set_char_online: Character %d:%d marked in map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, map_id, account_id, char_id); - mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); + mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); } //Update state data @@ -330,11 +164,11 @@ void set_char_online(int map_id, int char_id, int account_id) character->server = map_id; if( character->server > -1 ) - server[character->server].users++; + map_server[character->server].users++; //Get rid of disconnect timer if(character->waiting_disconnect != INVALID_TIMER) { - delete_timer(character->waiting_disconnect, chardb_waiting_disconnect); + delete_timer(character->waiting_disconnect, char_chardb_waiting_disconnect); character->waiting_disconnect = INVALID_TIMER; } @@ -343,22 +177,15 @@ void set_char_online(int map_id, int char_id, int account_id) inter_guild_CharOnline(char_id, cp?cp->guild_id:-1); //Notify login server - if (loginif_isconnected()) - { - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x272b; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); - } + chlogif_send_setacconline(account_id); } -void set_char_offline(int char_id, int account_id) -{ +void char_set_char_offline(int char_id, int account_id){ struct online_char_data* character; if ( char_id == -1 ) { - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", schema_config.char_db, account_id) ) Sql_ShowDebug(sql_handle); } else @@ -368,18 +195,18 @@ void set_char_offline(int char_id, int account_id) if (cp) idb_remove(char_db_,char_id); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, char_id) ) Sql_ShowDebug(sql_handle); } if ((character = (struct online_char_data*)idb_get(online_char_db, account_id)) != NULL) { //We don't free yet to avoid aCalloc/aFree spamming during char change. [Skotlex] if( character->server > -1 ) - if( server[character->server].users > 0 ) // Prevent this value from going negative. - server[character->server].users--; + if( map_server[character->server].users > 0 ) // Prevent this value from going negative. + map_server[character->server].users--; if(character->waiting_disconnect != INVALID_TIMER){ - delete_timer(character->waiting_disconnect, chardb_waiting_disconnect); + delete_timer(character->waiting_disconnect, char_chardb_waiting_disconnect); character->waiting_disconnect = INVALID_TIMER; } @@ -395,27 +222,22 @@ void set_char_offline(int char_id, int account_id) } //Remove char if 1- Set all offline, or 2- character is no longer connected to char-server. - if (loginif_isconnected() && (char_id == -1 || character == NULL || character->fd == -1)) - { - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x272c; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); + if (char_id == -1 || character == NULL || character->fd == -1){ + chlogif_send_setaccoffline(login_fd,account_id); } } /** * @see DBApply */ -static int char_db_setoffline(DBKey key, DBData *data, va_list ap) -{ +int char_db_setoffline(DBKey key, DBData *data, va_list ap) { struct online_char_data* character = (struct online_char_data*)db_data2ptr(data); int server = va_arg(ap, int); if (server == -1) { character->char_id = -1; character->server = -1; if(character->waiting_disconnect != INVALID_TIMER){ - delete_timer(character->waiting_disconnect, chardb_waiting_disconnect); + delete_timer(character->waiting_disconnect, char_chardb_waiting_disconnect); character->waiting_disconnect = INVALID_TIMER; } } else if (character->server == server) @@ -426,8 +248,7 @@ static int char_db_setoffline(DBKey key, DBData *data, va_list ap) /** * @see DBApply */ -static int char_db_kickoffline(DBKey key, DBData *data, va_list ap) -{ +static int char_db_kickoffline(DBKey key, DBData *data, va_list ap){ struct online_char_data* character = (struct online_char_data*)db_data2ptr(data); int server_id = va_arg(ap, int); @@ -436,17 +257,16 @@ static int char_db_kickoffline(DBKey key, DBData *data, va_list ap) //Kick out any connected characters, and set them offline as appropriate. if (character->server > -1) - mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1); + mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 1); else if (character->waiting_disconnect == INVALID_TIMER) - set_char_offline(character->char_id, character->account_id); + char_set_char_offline(character->char_id, character->account_id); else return 0; // fail return 1; } -void set_all_offline(int id) -{ +void char_set_all_offline(int id){ if (id < 0) ShowNotice("Sending all users offline.\n"); else @@ -456,37 +276,32 @@ void set_all_offline(int id) if (id >= 0 || !loginif_isconnected()) return; //Tell login-server to also mark all our characters as offline. - WFIFOHEAD(login_fd,2); - WFIFOW(login_fd,0) = 0x2737; - WFIFOSET(login_fd,2); + chlogif_send_setallaccoffline(login_fd); } -void set_all_offline_sql(void) -{ +void char_set_all_offline_sql(void){ //Set all players to 'OFFLINE' - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", char_db) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", schema_config.char_db) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", guild_member_db) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", schema_config.guild_member_db) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", guild_db) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", schema_config.guild_db) ) Sql_ShowDebug(sql_handle); } /** * @see DBCreateData */ -static DBData create_charstatus(DBKey key, va_list args) -{ +static DBData char_create_charstatus(DBKey key, va_list args) { struct mmo_charstatus *cp; cp = (struct mmo_charstatus *) aCalloc(1,sizeof(struct mmo_charstatus)); cp->char_id = key.i; return db_ptr2data(cp); } -int inventory_to_sql(const struct item items[], int max, int id); +int char_inventory_to_sql(const struct item items[], int max, int id); -int mmo_char_tosql(int char_id, struct mmo_charstatus* p) -{ +int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p){ int i = 0; int count = 0; int diff = 0; @@ -497,14 +312,14 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) if (char_id!=p->char_id) return 0; - cp = idb_ensure(char_db_, char_id, create_charstatus); + cp = idb_ensure(char_db_, char_id, char_create_charstatus); StringBuf_Init(&buf); memset(save_status, 0, sizeof(save_status)); //map inventory data if( memcmp(p->inventory, cp->inventory, sizeof(p->inventory)) ) { - if (!inventory_to_sql(p->inventory, MAX_INVENTORY, p->char_id)) + if (!char_inventory_to_sql(p->inventory, MAX_INVENTORY, p->char_id)) strcat(save_status, " inventory"); else errors++; @@ -512,7 +327,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) //map cart data if( memcmp(p->cart, cp->cart, sizeof(p->cart)) ) { - if (!memitemdata_to_sql(p->cart, MAX_CART, p->char_id, TABLE_CART)) + if (!char_memitemdata_to_sql(p->cart, MAX_CART, p->char_id, TABLE_CART)) strcat(save_status, " cart"); else errors++; @@ -520,11 +335,12 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) //map storage data if( memcmp(p->storage.items, cp->storage.items, sizeof(p->storage.items)) ) { - if (!memitemdata_to_sql(p->storage.items, MAX_STORAGE, p->account_id, TABLE_STORAGE)) + if (!char_memitemdata_to_sql(p->storage.items, MAX_STORAGE, p->account_id, TABLE_STORAGE)) strcat(save_status, " storage"); else errors++; } + if ( (p->base_exp != cp->base_exp) || (p->base_level != cp->base_level) || (p->job_level != cp->job_level) || (p->job_exp != cp->job_exp) || @@ -552,8 +368,8 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," "`delete_date`='%lu',`robe`='%d',`moves`='%d'" - " WHERE `account_id`='%d' AND `char_id` = '%d'", - char_db, p->base_level, p->job_level, + " WHERE `account_id`='%d' AND `char_id` = '%d'", + schema_config.char_db, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, @@ -586,7 +402,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) "`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d'," "`karma`='%d',`manner`='%d', `fame`='%d'" " WHERE `account_id`='%d' AND `char_id` = '%d'", - char_db, p->class_, + schema_config.char_db, p->class_, p->hair, p->hair_color, p->clothes_color, p->partner_id, p->father, p->mother, p->child, p->karma, p->manner, p->fame, @@ -616,7 +432,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) char esc_mapname[NAME_LENGTH*2+1]; //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, p->char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.memo_db, p->char_id) ) { Sql_ShowDebug(sql_handle); errors++; @@ -624,7 +440,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) //insert here. StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db); + StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", schema_config.memo_db); for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i ) { if( p->memo_point[i].map ) @@ -657,14 +473,14 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) if( memcmp(p->skill, cp->skill, sizeof(p->skill)) ) { //`skill` (`char_id`, `id`, `lv`) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.skill_db, p->char_id) ) { Sql_ShowDebug(sql_handle); errors++; } StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", skill_db); + StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", schema_config.skill_db); //insert here. for( i = 0, count = 0; i < MAX_SKILL; ++i ) { if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) { @@ -704,14 +520,14 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) if(diff == 1) { //Save friends - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.friend_db, char_id) ) { Sql_ShowDebug(sql_handle); errors++; } StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", schema_config.friend_db); for( i = 0, count = 0; i < MAX_FRIENDS; ++i ) { if( p->friends[i].char_id > 0 ) @@ -736,7 +552,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) #ifdef HOTKEY_SAVING // hotkeys StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db); + StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", schema_config.hotkey_db); diff = 0; for(i = 0; i < ARRAYLENGTH(p->hotkeys); i++){ if(memcmp(&p->hotkeys[i], &cp->hotkeys[i], sizeof(struct hotkey))) @@ -757,7 +573,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) } #endif StringBuf_Destroy(&buf); - if (save_status[0]!='\0' && save_log) + if (save_status[0]!='\0' && charserv_config.save_log) ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status); if (!errors) memcpy(cp, p, sizeof(struct mmo_charstatus)); @@ -765,8 +581,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) } /// Saves an array of 'item' entries into the specified table. -int memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch) -{ +int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch){ StringBuf buf; SqlStmt* stmt; int i; @@ -779,10 +594,10 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit int errors = 0; switch (tableswitch) { - case TABLE_INVENTORY: tablename = inventory_db; selectoption = "char_id"; break; - case TABLE_CART: tablename = cart_db; selectoption = "char_id"; break; - case TABLE_STORAGE: tablename = storage_db; selectoption = "account_id"; break; - case TABLE_GUILD_STORAGE: tablename = guild_storage_db; selectoption = "guild_id"; break; + case TABLE_INVENTORY: tablename = schema_config.inventory_db; selectoption = "char_id"; break; + case TABLE_CART: tablename = schema_config.cart_db; selectoption = "char_id"; break; + case TABLE_STORAGE: tablename = schema_config.storage_db; selectoption = "account_id"; break; + case TABLE_GUILD_STORAGE: tablename = schema_config.guild_storage_db; selectoption = "guild_id"; break; default: ShowError("Invalid table name!\n"); return 1; @@ -924,7 +739,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit } /* pretty much a copy of memitemdata_to_sql except it handles inventory_db exclusively, * - this is required because inventory db is the only one with the 'favorite' column. */ -int inventory_to_sql(const struct item items[], int max, int id) { +int char_inventory_to_sql(const struct item items[], int max, int id) { StringBuf buf; SqlStmt* stmt; int i; @@ -944,7 +759,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, id); stmt = SqlStmt_Malloc(sql_handle); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) @@ -1000,7 +815,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { // update all fields. StringBuf_Clear(&buf); StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d', `bound`='%d'", - inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound); + schema_config.inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); @@ -1016,7 +831,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { } } if( !found ) {// Item not present in inventory, remove it. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", inventory_db, item.id) ) { + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", schema_config.inventory_db, item.id) ) { Sql_ShowDebug(sql_handle); errors++; } @@ -1025,7 +840,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { SqlStmt_Free(stmt); StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", inventory_db); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", schema_config.inventory_db); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); StringBuf_AppendStr(&buf, ") VALUES "); @@ -1064,12 +879,11 @@ int inventory_to_sql(const struct item items[], int max, int id) { } -int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p); +int char_mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p); //===================================================================================================== // Loads the basic character rooster for the given account. Returns total buffer used. -int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) -{ +int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) { SqlStmt* stmt; struct mmo_charstatus p; int j = 0, i; @@ -1095,7 +909,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) "`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`," "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`," "`robe`,`moves`, `unban_time`" - " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS) + " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", schema_config.char_db, sd->account_id, MAX_CHARS) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UCHAR, &p.slot, 0, NULL, NULL) @@ -1147,7 +961,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) p.last_point.map = mapindex_name2id(last_map); sd->found_char[p.slot] = p.char_id; sd->unban_time[p.slot] = p.unban_time; - j += mmo_char_tobuf(WBUFP(buf, j), &p); + j += char_mmo_char_tobuf(WBUFP(buf, j), &p); // Addon System // store the required info into the session @@ -1161,8 +975,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) } //===================================================================================================== -int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything) -{ +int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything) { int i,j; char t_msg[128] = ""; struct mmo_charstatus* cp; @@ -1182,7 +995,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything memset(p, 0, sizeof(struct mmo_charstatus)); - if (save_log) ShowInfo("Char load request (%d)\n", char_id); + if (charserv_config.save_log) ShowInfo("Char load request (%d)\n", char_id); stmt = SqlStmt_Malloc(sql_handle); if( stmt == NULL ) @@ -1198,7 +1011,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`," "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`, `unban_time`" - " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db) + " FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p->char_id, 0, NULL, NULL) @@ -1292,7 +1105,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read memo data //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", memo_db, MAX_MEMOPOINTS) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", schema_config.memo_db, MAX_MEMOPOINTS) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &point_map, sizeof(point_map), NULL, NULL) @@ -1313,7 +1126,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`"); for( i = 0; i < MAX_SLOTS; ++i ) StringBuf_Printf(&buf, ", `card%d`", i); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.inventory_db, MAX_INVENTORY); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) @@ -1345,7 +1158,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.cart_db, MAX_CART); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) @@ -1375,7 +1188,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read skill //`skill` (`char_id`, `id`, `lv`) - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.skill_db, MAX_SKILL) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id , 0, NULL, NULL) @@ -1397,7 +1210,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read friends //`friends` (`char_id`, `friend_account`, `friend_id`) - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", char_db, friend_db, MAX_FRIENDS) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", schema_config.char_db, schema_config.friend_db, MAX_FRIENDS) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_friend.account_id, 0, NULL, NULL) @@ -1412,7 +1225,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything #ifdef HOTKEY_SAVING //read hotkeys //`hotkey` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl` - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", hotkey_db) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", schema_config.hotkey_db) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &hotkey_num, 0, NULL, NULL) @@ -1436,20 +1249,21 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything strcat(t_msg, " mercenary"); - if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly! + if (charserv_config.save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly! SqlStmt_Free(stmt); StringBuf_Destroy(&buf); - cp = idb_ensure(char_db_, char_id, create_charstatus); + cp = idb_ensure(char_db_, char_id, char_create_charstatus); memcpy(cp, p, sizeof(struct mmo_charstatus)); return 1; } //========================================================================================================== -int mmo_char_sql_init(void) -{ +int char_mmo_sql_init(void) { char_db_= idb_alloc(DB_OPT_RELEASE_DATA); + ShowStatus("Characters per Account: '%d'.\n", charserv_config.char_config.char_per_account); + //the 'set offline' part is now in check_login_conn ... //if the server connects to loginserver //it will dc all off players @@ -1457,7 +1271,7 @@ int mmo_char_sql_init(void) // Force all users offline in sql when starting char-server // (useful when servers crashs and don't clean the database) - set_all_offline_sql(); + char_set_all_offline_sql(); return 0; } @@ -1465,7 +1279,7 @@ int mmo_char_sql_init(void) //----------------------------------- // Function to change chararcter's names //----------------------------------- -int rename_char_sql(struct char_session_data *sd, int char_id) +int char_rename_char_sql(struct char_session_data *sd, int char_id) { struct mmo_charstatus char_dat; char esc_name[NAME_LENGTH*2+1]; @@ -1473,7 +1287,7 @@ int rename_char_sql(struct char_session_data *sd, int char_id) if( sd->new_name[0] == 0 ) // Not ready for rename return 2; - if( !mmo_char_fromsql(char_id, &char_dat, false) ) // Only the short data is needed. + if( !char_mmo_char_fromsql(char_id, &char_dat, false) ) // Only the short data is needed. return 2; if( char_dat.rename == 0 ) @@ -1482,13 +1296,13 @@ int rename_char_sql(struct char_session_data *sd, int char_id) Sql_EscapeStringLen(sql_handle, esc_name, sd->new_name, strnlen(sd->new_name, NAME_LENGTH)); // check if the char exist - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", char_db, esc_name) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", schema_config.char_db, esc_name) ) { Sql_ShowDebug(sql_handle); return 4; } - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", char_db, esc_name, --char_dat.rename, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", schema_config.char_db, esc_name, --char_dat.rename, char_id) ) { Sql_ShowDebug(sql_handle); return 3; @@ -1502,18 +1316,18 @@ int 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( charserv_config.log_char ) { if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')", - charlog_db, "change char name", sd->account_id, char_dat.slot, esc_name) ) + schema_config.charlog_db, "change char name", sd->account_id, char_dat.slot, esc_name) ) Sql_ShowDebug(sql_handle); } return 0; } -int check_char_name(char * name, char * esc_name) +int char_check_char_name(char * name, char * esc_name) { int i; @@ -1531,29 +1345,29 @@ int check_char_name(char * name, char * esc_name) return -2; // control chars in name // check for reserved names - if( strcmpi(name, wisp_server_name) == 0 ) + if( strcmpi(name, charserv_config.wisp_server_name) == 0 ) return -1; // nick reserved for internal server messages // Check Authorised letters/symbols in the name of the character - if( char_name_option == 1 ) + if( charserv_config.char_config.char_name_option == 1 ) { // only letters/symbols in char_name_letters are authorised for( i = 0; i < NAME_LENGTH && name[i]; i++ ) - if( strchr(char_name_letters, name[i]) == NULL ) + if( strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL ) return -2; } - else if( char_name_option == 2 ) + else if( charserv_config.char_config.char_name_option == 2 ) { // letters/symbols in char_name_letters are forbidden for( i = 0; i < NAME_LENGTH && name[i]; i++ ) - if( strchr(char_name_letters, name[i]) != NULL ) + if( strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL ) return -2; } - if( name_ignoring_case ) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name) ) { + if( charserv_config.char_config.name_ignoring_case ) { + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", schema_config.char_db, esc_name) ) { Sql_ShowDebug(sql_handle); return -2; } } else { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name) ) { + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", schema_config.char_db, esc_name) ) { Sql_ShowDebug(sql_handle); return -2; } @@ -1568,12 +1382,11 @@ int check_char_name(char * name, char * esc_name) // Function to create a new character //----------------------------------- #if PACKETVER >= 20120307 -int make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int hair_color, int hair_style) { +int char_make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int hair_color, int hair_style) { int str = 1, agi = 1, vit = 1, int_ = 1, dex = 1, luk = 1; #else -int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style) { +int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style) { #endif - char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1]; int char_id, flag, k; @@ -1582,7 +1395,7 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag normalize_name(name,TRIM_CHARS); Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - flag = check_char_name(name,esc_name); + flag = char_check_char_name(name,esc_name); if( flag < 0 ) return flag; @@ -1603,22 +1416,22 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag // check the number of already existing chars in this account - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", schema_config.char_db, sd->account_id) ) Sql_ShowDebug(sql_handle); if( Sql_NumRows(sql_handle) >= sd->char_slots ) return -2; // character account limit exceeded // check char slot - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", char_db, sd->account_id, slot) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", schema_config.char_db, sd->account_id, slot) ) Sql_ShowDebug(sql_handle); if( Sql_NumRows(sql_handle) > 0 ) return -2; // slot already in use // validation success, log result - if (log_char) { + if (charserv_config.log_char) { if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db, "make new char", sd->account_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) ) + schema_config.charlog_db, "make new char", sd->account_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) ) Sql_ShowDebug(sql_handle); } #if PACKETVER >= 20120307 @@ -1626,9 +1439,9 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `status_point`,`str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" "'%d', '%d', '%s', '%d', '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", - char_db, sd->account_id , slot, esc_name, start_zeny, 48, str, agi, vit, int_, dex, luk, + schema_config.char_db, sd->account_id , slot, esc_name, charserv_config.start_zeny, 48, str, agi, vit, int_, dex, luk, (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color, - mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) ) + mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y, mapindex_id2name(charserv_config.start_point.map), charserv_config.start_point.x, charserv_config.start_point.y) ) { Sql_ShowDebug(sql_handle); return -2; //No, stop the procedure! @@ -1636,11 +1449,11 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag #else //Insert the new char entry to the database if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," - "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" - "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", - char_db, sd->account_id , slot, esc_name, start_zeny, str, agi, vit, int_, dex, luk, - (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color, - mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) ) + "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" + "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", + char_db, sd->account_id , slot, esc_name, start_zeny, str, agi, vit, int_, dex, luk, + (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color, + mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) ) { Sql_ShowDebug(sql_handle); return -2; //No, stop the procedure! @@ -1650,7 +1463,7 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag char_id = (int)Sql_LastInsertId(sql_handle); //Give the char the default items for (k = 0; k <= MAX_STARTITEM && start_items[k].nameid != 0; k ++) { - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, start_items[k].nameid, start_items[k].amount, start_items[k].pos, 1) ) + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", schema_config.inventory_db, char_id, start_items[k].nameid, start_items[k].amount, start_items[k].pos, 1) ) Sql_ShowDebug(sql_handle); } @@ -1661,20 +1474,12 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag /*----------------------------------------------------------------------------------------------------------*/ /* Divorce Players */ /*----------------------------------------------------------------------------------------------------------*/ -int divorce_char_sql(int partner_id1, int partner_id2) -{ - unsigned char buf[64]; - - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", char_db, partner_id1, partner_id2) ) +int char_divorce_char_sql(int partner_id1, int partner_id2){ + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", schema_config.char_db, partner_id1, partner_id2) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", schema_config.inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) ) Sql_ShowDebug(sql_handle); - - WBUFW(buf,0) = 0x2b12; - WBUFL(buf,2) = partner_id1; - WBUFL(buf,6) = partner_id2; - mapif_sendall(buf,10); - + chmapif_send_ackdivorce(partner_id1, partner_id2); return 0; } @@ -1684,15 +1489,14 @@ int divorce_char_sql(int partner_id1, int partner_id2) /* Returns 0 if successful * Returns < 0 for error */ -int delete_char_sql(int char_id) -{ +int char_delete_char_sql(int char_id){ char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1]; //Name needs be escaped. int account_id, party_id, guild_id, hom_id, base_level, partner_id, father_id, mother_id, elemental_id; char *data; size_t len; - if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", char_db, char_id)) + if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id)) Sql_ShowDebug(sql_handle); if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) @@ -1718,8 +1522,8 @@ int delete_char_sql(int char_id) //check for config char del condition [Lupus] // TODO: Move this out to packet processing (0x68/0x1fb). - if( ( char_del_level > 0 && base_level >= char_del_level ) - || ( char_del_level < 0 && base_level <= -char_del_level ) + if( ( charserv_config.char_config.char_del_level > 0 && base_level >= charserv_config.char_config.char_del_level ) + || ( charserv_config.char_config.char_del_level < 0 && base_level <= -charserv_config.char_config.char_del_level ) ) { ShowInfo("Char deletion aborted: %s, BaseLevel: %i\n", name, base_level); return -1; @@ -1727,23 +1531,23 @@ int delete_char_sql(int char_id) /* Divorce [Wizputer] */ if( partner_id ) - divorce_char_sql(char_id, partner_id); + char_divorce_char_sql(char_id, partner_id); /* De-addopt [Zephyrus] */ if( father_id || mother_id ) { // Char is Baby unsigned char buf[64]; - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", char_db, father_id, mother_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", schema_config.char_db, father_id, mother_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", skill_db, father_id, mother_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", schema_config.skill_db, father_id, mother_id) ) Sql_ShowDebug(sql_handle); WBUFW(buf,0) = 0x2b25; WBUFL(buf,2) = father_id; WBUFL(buf,6) = mother_id; WBUFL(buf,10) = char_id; // Baby - mapif_sendall(buf,14); + chmapif_sendall(buf,14); } //Make the character leave the party [Skotlex] @@ -1752,13 +1556,13 @@ int delete_char_sql(int char_id) /* delete char's pet */ //Delete the hatched pet if you have one... - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", pet_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", schema_config.pet_db, char_id) ) Sql_ShowDebug(sql_handle); //Delete all pets that are stored in eggs (inventory + cart) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, inventory_db, inventory_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", schema_config.pet_db, schema_config.pet_db, schema_config.inventory_db, schema_config.inventory_db, char_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, cart_db, cart_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", schema_config.pet_db, schema_config.pet_db, schema_config.cart_db, schema_config.cart_db, char_id) ) Sql_ShowDebug(sql_handle); /* remove homunculus */ @@ -1773,62 +1577,62 @@ int delete_char_sql(int char_id) mercenary_owner_delete(char_id); /* delete char's friends list */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", friend_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.friend_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete char from other's friend list */ //NOTE: Won't this cause problems for people who are already online? [Skotlex] - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", friend_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", schema_config.friend_db, char_id) ) Sql_ShowDebug(sql_handle); #ifdef HOTKEY_SAVING /* delete hotkeys */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.hotkey_db, char_id) ) Sql_ShowDebug(sql_handle); #endif /* delete inventory */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.inventory_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete cart inventory */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", cart_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.cart_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete memo areas */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.memo_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete character registry */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", schema_config.reg_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete skills */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.skill_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete mails (only received) */ - if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", mail_db, char_id)) + if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", schema_config.mail_db, char_id)) Sql_ShowDebug(sql_handle); #ifdef ENABLE_SC_SAVING /* status changes */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, account_id, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, account_id, char_id) ) Sql_ShowDebug(sql_handle); #endif /* bonus_scripts */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", bonus_script_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.bonus_script_db, char_id) ) Sql_ShowDebug(sql_handle); - if (log_char) { + if (charserv_config.log_char) { if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')", - charlog_db, account_id, 0, char_id, esc_name) ) + schema_config.charlog_db, account_id, 0, char_id, esc_name) ) Sql_ShowDebug(sql_handle); } /* delete character */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) ) Sql_ShowDebug(sql_handle); /* No need as we used inter_guild_leave [Skotlex] @@ -1837,7 +1641,7 @@ int delete_char_sql(int char_id) Sql_ShowDebug(sql_handle); */ - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", guild_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.guild_db, char_id) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) > 0 ) mapif_parse_BreakGuild(0,guild_id); @@ -1846,17 +1650,18 @@ int delete_char_sql(int char_id) return 0; } -//--------------------------------------------------------------------- -// This function return the number of online players in all map-servers -//--------------------------------------------------------------------- -int count_users(void) +/** + * This function parse all map-serv attached to this char-serv and increase user count + * @return numbers of total users + */ +int char_count_users(void) { int i, users; users = 0; - for(i = 0; i < ARRAYLENGTH(server); i++) { - if (server[i].fd > 0) { - users += server[i].users; + for(i = 0; i < ARRAYLENGTH(map_server); i++) { + if (map_server[i].fd > 0) { + users += map_server[i].users; } } return users; @@ -1865,8 +1670,7 @@ int count_users(void) // Writes char data to the buffer in the format used by the client. // Used in packets 0x6b (chars info) and 0x6d (new char info) // Returns the size -#define MAX_CHAR_BUF 144 //Max size (for WFIFOHEAD calls) -int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) +int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) { unsigned short offset = 0; uint8* buf; @@ -1936,9 +1740,9 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) #if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity. #if PACKETVER >= 20110928 // change slot feature (0 = disabled, otherwise enabled) - if( !char_move_enabled ) + if( (charserv_config.charmove_config.char_move_enabled)==0 ) WBUFL(buf,132) = 0; - else if( char_moves_unlimited ) + else if( charserv_config.charmove_config.char_moves_unlimited ) WBUFL(buf,132) = 1; else WBUFL(buf,132) = max( 0, (int)p->character_moves ); @@ -2017,7 +1821,7 @@ void char_block_character( int fd, struct char_session_data* sd){ else { WFIFOL(fd, 4+j*24) = 0; sd->unban_time[i] = 0; - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time`='0' WHERE `char_id`='%d' LIMIT 1", char_db, sd->found_char[i]) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time`='0' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, sd->found_char[i]) ) Sql_ShowDebug(sql_handle); } len+=24; @@ -2038,7 +1842,7 @@ void char_block_character( int fd, struct char_session_data* sd){ void mmo_char_send099d(int fd, struct char_session_data *sd) { WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF)); WFIFOW(fd,0) = 0x99d; - WFIFOW(fd,2) = mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4; + WFIFOW(fd,2) = char_mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4; WFIFOSET(fd,WFIFOW(fd,2)); } @@ -2055,7 +1859,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd){ bool newvers = (sd->version >= date2version(20100413)); if(newvers) //20100413 offset += 3; - if (save_log) + if ( charserv_config.save_log ) ShowInfo("Loading Char Data 6b ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); j = 24 + offset; // offset @@ -2072,7 +1876,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd){ /* this+0x14 char dummy2_endbilling[7] */ } memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes 4-24 7-27 - j+=mmo_chars_fromsql(sd, WFIFOP(fd,j)); + j+=char_mmo_chars_fromsql(sd, WFIFOP(fd,j)); WFIFOW(fd,2) = j; // packet len WFIFOSET(fd,j); @@ -2083,7 +1887,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd){ // Notify client about charselect window data [Ind] //---------------------------------------- void mmo_char_send082d(int fd, struct char_session_data* sd) { - if (save_log) + if (charserv_config.save_log) ShowInfo("Loading Char Data 82d ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); WFIFOHEAD(fd,29); WFIFOW(fd,0) = 0x82d; @@ -2112,7 +1916,7 @@ void mmo_char_send(int fd, struct char_session_data* sd){ int char_married(int pl1, int pl2) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, pl1) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { @@ -2131,7 +1935,7 @@ int char_married(int pl1, int pl2) int char_child(int parent_id, int child_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, parent_id) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { @@ -2150,7 +1954,7 @@ int char_child(int parent_id, int child_id) int char_family(int cid1, int cid2, int cid3) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, cid1, cid2, cid3) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", schema_config.char_db, cid1, cid2, cid3) ) Sql_ShowDebug(sql_handle); else while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { @@ -2178,58 +1982,47 @@ int char_family(int cid1, int cid2, int cid3) //---------------------------------------------------------------------- // Force disconnection of an online player (with account value) by [Yor] //---------------------------------------------------------------------- -void disconnect_player(int account_id) +void char_disconnect_player(int account_id) { int i; struct char_session_data* sd; // disconnect player if online on char-server - ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == account_id); + ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == account_id ); if( i < fd_max ) set_eof(i); } -static void char_auth_ok(int fd, struct char_session_data *sd) -{ + + +void char_auth_ok(int fd, struct char_session_data *sd) { struct online_char_data* character; if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) != NULL ) { // check if character is not online already. [Skotlex] if (character->server > -1) { //Character already online. KICK KICK KICK - mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); + mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == INVALID_TIMER) - character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 8; - WFIFOSET(fd,3); + character->waiting_disconnect = add_timer(gettick()+20000, char_chardb_waiting_disconnect, character->account_id, 0); + chclif_send_auth_result(fd,8); return; } if (character->fd >= 0 && character->fd != fd) { //There's already a connection from this account that hasn't picked a char yet. - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 8; - WFIFOSET(fd,3); + chclif_send_auth_result(fd,8); return; } character->fd = fd; } - if (loginif_isconnected()) { - // request account data - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x2716; - WFIFOL(login_fd,2) = sd->account_id; - WFIFOSET(login_fd,6); - } + chlogif_send_reqaccdata(login_fd,sd); // request account data // mark session as 'authed' sd->auth = true; // set char online on charserver - set_char_charselect(sd->account_id); + char_set_charselect(sd->account_id); // continues when account data is received... } @@ -2282,7 +2075,7 @@ int mapif_BankingAck(int32 account_id, int32 bank_vault){ WBUFW(buf,0) = 0x2b29; WBUFL(buf,2) = account_id; WBUFL(buf,6) = bank_vault; - mapif_sendall(buf, 10); //inform all maps-attached + chmapif_sendall(buf, 10); //inform all maps-attached return 1; } @@ -2299,7 +2092,7 @@ int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm WBUFB(buf,10) = isvip; WBUFB(buf,11) = isgm; WBUFL(buf,12) = groupid; - mapif_send(mapfd,buf,16); // inform the mapserv back + chmapif_send(mapfd,buf,16); // inform the mapserv back #endif return 0; } @@ -2359,7 +2152,7 @@ void loginif_reset(void) { int id; // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS] - for( id = 0; id < ARRAYLENGTH(server); ++id ) + for( id = 0; id < ARRAYLENGTH(map_server); ++id ) mapif_server_reset(id); flush_fifos(); exit(EXIT_FAILURE); @@ -2395,381 +2188,11 @@ void loginif_on_ready(void) send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0); // if no map-server already connected, display a message... - ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] ); - if( i == ARRAYLENGTH(server) ) + ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd > 0 && map_server[i].map[0] ); + if( i == ARRAYLENGTH(map_server) ) ShowStatus("Awaiting maps from map-server.\n"); } -int loginif_parse_reqpincode(int fd, struct char_session_data *sd){ -#if PACKETVER >= 20110309 - if( pincode_enabled ){ - // PIN code system enabled - if( sd->pincode[0] == '\0' ){ - // No PIN code has been set yet - if( pincode_force ) pincode_sendstate( fd, sd, PINCODE_NEW ); - else pincode_sendstate( fd, sd, PINCODE_PASSED ); - } else { - if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){ - struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id ); - if( node != NULL && node->pincode_success ){ // User has already passed the check - pincode_sendstate( fd, sd, PINCODE_PASSED ); - }else{ - // Ask user for his PIN code - pincode_sendstate( fd, sd, PINCODE_ASK ); - } - }else{ // User hasnt changed his PIN code too long - pincode_sendstate( fd, sd, PINCODE_EXPIRED ); - } - } - } else { // PIN code system disabled - pincode_sendstate( fd, sd, PINCODE_OK ); - } -#endif - return 0; -} - -int parse_fromlogin(int fd) { - struct char_session_data* sd = NULL; - int i; - - // only process data from the login-server - if( fd != login_fd ) { - ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd); - do_close(fd); - return 0; - } - - if( session[fd]->flag.eof ) { - do_close(fd); - login_fd = -1; - loginif_on_disconnect(); - return 0; - } else if ( session[fd]->flag.ping ) {/* we've reached stall time */ - if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */ - set_eof(fd); - return 0; - } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */ - WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718) - WFIFOW(fd,0) = 0x2719; - WFIFOSET(fd,2); - - session[fd]->flag.ping = 2; - } - } - - sd = (struct char_session_data*)session[fd]->session_data; - - while(RFIFOREST(fd) >= 2) { - uint16 command = RFIFOW(fd,0); - - switch( command ) - { - case 0x2741: loginif_parse_BankingAck(fd); break; - case 0x2743: loginif_parse_vipack(fd); break; - - // acknowledgement of connect-to-loginserver request - case 0x2711: - if (RFIFOREST(fd) < 3) - return 0; - - if (RFIFOB(fd,2)) { - //printf("connect login server error : %d\n", RFIFOB(fd,2)); - 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 map_athena.conf and char_athena.conf\n"); - set_eof(fd); - return 0; - } else { - ShowStatus("Connected to login-server (connection #%d).\n", fd); - loginif_on_ready(); - } - RFIFOSKIP(fd,3); - break; - - // acknowledgement of account authentication request - case 0x2713: - if (RFIFOREST(fd) < 25) - return 0; - { - int account_id = RFIFOL(fd,2); - uint32 login_id1 = RFIFOL(fd,6); - uint32 login_id2 = RFIFOL(fd,10); - uint8 sex = RFIFOB(fd,14); - uint8 result = RFIFOB(fd,15); - int request_id = RFIFOL(fd,16); - uint32 version = RFIFOL(fd,20); - uint8 clienttype = RFIFOB(fd,24); - RFIFOSKIP(fd,25); - - if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) && - !sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex ) - { - int client_fd = request_id; - sd->version = version; - sd->clienttype = clienttype; - if(sd->version != date2version(PACKETVER)) - ShowWarning("s aid=%d has an incorect version=%d in clientinfo. Server compiled for %d\n", - sd->account_id,sd->version,date2version(PACKETVER)); - - switch( result ) - { - case 0:// ok - char_auth_ok(client_fd, sd); - break; - case 1:// auth failed - WFIFOHEAD(client_fd,3); - WFIFOW(client_fd,0) = 0x6c; - WFIFOB(client_fd,2) = 0;// rejected from server - WFIFOSET(client_fd,3); - break; - } - } - } - break; - - case 0x2717: // account data - if (RFIFOREST(fd) < 79) - return 0; - - // find the authenticated session with this account id - ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) ); - if( i < fd_max ) - { - int server_id; - memcpy(sd->email, RFIFOP(fd,6), 40); - sd->expiration_time = (time_t)RFIFOL(fd,46); - sd->group_id = RFIFOB(fd,50); - sd->char_slots = RFIFOB(fd,51); - if( sd->char_slots > MAX_CHARS ) { - ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots); - sd->char_slots = MAX_CHARS;/* cap to maximum */ - } else if ( !sd->char_slots )/* no value aka 0 in sql */ - sd->char_slots = MIN_CHARS;/* cap to minimum */ - safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate)); - safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode)); - sd->pincode_change = (time_t)RFIFOL(fd,68); - sd->bank_vault = RFIFOL(fd,72); - sd->isvip = RFIFOB(fd,76); - sd->chars_vip = RFIFOB(fd,77); - sd->chars_billing = RFIFOB(fd,78); - ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] ); - // continued from char_auth_ok... - if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359 - (max_connect_user == 0 && sd->group_id != gm_allow_group) || - ( max_connect_user > 0 && count_users() >= max_connect_user && sd->group_id != gm_allow_group ) || - (char_maintenance && sd->group_id < gm_allow_group) ) { - // refuse connection (over populated) - WFIFOHEAD(i,3); - WFIFOW(i,0) = 0x6c; - WFIFOW(i,2) = 0; - WFIFOSET(i,3); - } else { - // send characters to player - mmo_char_send(i, sd); - loginif_parse_reqpincode(i, sd); - } - } - RFIFOSKIP(fd,79); - break; - - // login-server alive packet - case 0x2718: - if (RFIFOREST(fd) < 2) - return 0; - RFIFOSKIP(fd,2); - session[fd]->flag.ping = 0; - break; - - // changesex reply - case 0x2723: - if (RFIFOREST(fd) < 7) - return 0; - { - unsigned char buf[7]; - - int acc = RFIFOL(fd,2); - int sex = RFIFOB(fd,6); - RFIFOSKIP(fd,7); - - if( acc > 0 ) - {// TODO: Is this even possible? - int char_id[MAX_CHARS]; - int class_[MAX_CHARS]; - int guild_id[MAX_CHARS]; - int num; - char* data; - - struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc); - if( node != NULL ) - node->sex = sex; - - // get characters - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) ) - Sql_ShowDebug(sql_handle); - for( i = 0; i < MAX_CHARS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) - { - Sql_GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data); - } - num = i; - for( i = 0; i < num; ++i ) - { - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || - class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || - class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER || - class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER || - class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T || - class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER || - class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) - { - // job modification - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) - class_[i] = (sex ? JOB_BARD : JOB_DANCER); - else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) - class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); - else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) - class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); - else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ) - class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER); - else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ) - class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T); - else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ) - class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); - else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) - class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); - } - - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) ) - Sql_ShowDebug(sql_handle); - - if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] - inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); - } - Sql_FreeResult(sql_handle); - - // disconnect player if online on char-server - disconnect_player(acc); - } - - // notify all mapservers about this change - WBUFW(buf,0) = 0x2b0d; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = sex; - mapif_sendall(buf, 7); - } - break; - - // reply to an account_reg2 registry request - case 0x2729: - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - - { //Receive account_reg2 registry, forward to map servers. - unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)]; - memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2)); - WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex] - mapif_sendall(buf, WBUFW(buf,2)); - RFIFOSKIP(fd, RFIFOW(fd,2)); - } - break; - - // State change of account/ban notification (from login-server) - case 0x2731: - if (RFIFOREST(fd) < 11) - return 0; - - { // send to all map-servers to disconnect the player - unsigned char buf[11]; - WBUFW(buf,0) = 0x2b14; - WBUFL(buf,2) = RFIFOL(fd,2); - WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban - WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment - mapif_sendall(buf, 11); - } - // disconnect player if online on char-server - disconnect_player(RFIFOL(fd,2)); - - RFIFOSKIP(fd,11); - break; - - // Login server request to kick a character out. [Skotlex] - case 0x2734: - if (RFIFOREST(fd) < 6) - return 0; - { - int aid = RFIFOL(fd,2); - struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid); - RFIFOSKIP(fd,6); - if( character != NULL ) - {// account is already marked as online! - if( character->server > -1 ) - { //Kick it from the map server it is on. - mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); - if (character->waiting_disconnect == INVALID_TIMER) - character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0); - } - else - {// Manual kick from char server. - struct char_session_data *tsd; - int i; - ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid ); - if( i < fd_max ) - { - WFIFOHEAD(i,3); - WFIFOW(i,0) = 0x81; - WFIFOB(i,2) = 2; // "Someone has already logged in with this id" - WFIFOSET(i,3); - set_eof(i); - } - else // still moving to the map-server - set_char_offline(-1, aid); - } - } - idb_remove(auth_db, aid);// reject auth attempts from map-server - } - break; - - // ip address update signal from login server - case 0x2735: - { - unsigned char buf[2]; - uint32 new_ip = 0; - - WBUFW(buf,0) = 0x2b1e; - mapif_sendall(buf, 2); - - new_ip = host2ip(login_ip_str); - if (new_ip && new_ip != login_ip) - login_ip = new_ip; //Update login ip, too. - - new_ip = host2ip(char_ip_str); - if (new_ip && new_ip != char_ip) - { //Update ip. - char_ip = new_ip; - ShowInfo("Updating IP for [%s].\n", char_ip_str); - // notify login server about the change - WFIFOHEAD(fd,6); - WFIFOW(fd,0) = 0x2736; - WFIFOL(fd,2) = htonl(char_ip); - WFIFOSET(fd,6); - } - - RFIFOSKIP(fd,2); - } - break; - - default: - ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command); - set_eof(fd); - return 0; - } - } - - RFIFOFLUSH(fd); - return 0; -} int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data); int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); @@ -2830,7 +2253,7 @@ void char_read_fame_list(void) memset(chemist_fame_list, 0, sizeof(chemist_fame_list)); memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list)); // Build Blacksmith ranking list - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) ) Sql_ShowDebug(sql_handle); for( i = 0; i < fame_list_size_smith && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { @@ -2845,7 +2268,7 @@ void char_read_fame_list(void) memcpy(smith_fame_list[i].name, data, min(len, NAME_LENGTH)); } // Build Alchemist ranking list - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) ) Sql_ShowDebug(sql_handle); for( i = 0; i < fame_list_size_chemist && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { @@ -2860,7 +2283,7 @@ void char_read_fame_list(void) memcpy(chemist_fame_list[i].name, data, min(len, NAME_LENGTH)); } // Build Taekwon ranking list - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_TAEKWON, fame_list_size_taekwon) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", schema_config.char_db, JOB_TAEKWON, fame_list_size_taekwon) ) Sql_ShowDebug(sql_handle); for( i = 0; i < fame_list_size_taekwon && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { @@ -2907,9 +2330,9 @@ int char_send_fame_list(int fd) WBUFW(buf, 2) = len; if (fd != -1) - mapif_send(fd, buf, len); + chmapif_send(fd, buf, len); else - mapif_sendall(buf, len); + chmapif_sendall(buf, len); return 0; } @@ -2921,17 +2344,16 @@ void char_update_fame_list(int type, int index, int fame) WBUFB(buf,2) = type; WBUFB(buf,3) = index; WBUFL(buf,4) = fame; - mapif_sendall(buf, 8); + chmapif_sendall(buf, 8); } //Loads a character's name and stores it in the buffer given (must be NAME_LENGTH in size) //Returns 1 on found, 0 on not found (buffer is filled with Unknown char name) -int char_loadName(int char_id, char* name) -{ +int char_loadName(int char_id, char* name){ char* data; size_t len; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { @@ -2941,7 +2363,7 @@ int char_loadName(int char_id, char* name) } else { - safestrncpy(name, unknown_char_name, NAME_LENGTH); + safestrncpy(name, charserv_config.char_config.unknown_char_name, NAME_LENGTH); } return 0; } @@ -2952,18 +2374,18 @@ int search_mapserver(unsigned short map, uint32 ip, uint16 port); /// Initializes a server structure. void mapif_server_init(int id) { - memset(&server[id], 0, sizeof(server[id])); - server[id].fd = -1; + memset(&map_server[id], 0, sizeof(map_server[id])); + map_server[id].fd = -1; } /// Destroys a server structure. void mapif_server_destroy(int id) { - if( server[id].fd == -1 ) + if( map_server[id].fd == -1 ) { - do_close(server[id].fd); - server[id].fd = -1; + do_close(map_server[id].fd); + map_server[id].fd = -1; } } @@ -2973,20 +2395,20 @@ void mapif_server_reset(int id) { int i,j; unsigned char buf[16384]; - int fd = server[id].fd; + int fd = map_server[id].fd; //Notify other map servers that this one is gone. [Skotlex] WBUFW(buf,0) = 0x2b20; - WBUFL(buf,4) = htonl(server[id].ip); - WBUFW(buf,8) = htons(server[id].port); + WBUFL(buf,4) = htonl(map_server[id].ip); + WBUFW(buf,8) = htons(map_server[id].port); j = 0; for(i = 0; i < MAX_MAP_PER_SERVER; i++) - if (server[id].map[i]) - WBUFW(buf,10+(j++)*4) = server[id].map[i]; + if (map_server[id].map[i]) + WBUFW(buf,10+(j++)*4) = map_server[id].map[i]; if (j > 0) { WBUFW(buf,2) = j * 4 + 10; - mapif_sendallwos(fd, buf, WBUFW(buf,2)); + chmapif_sendallwos(fd, buf, WBUFW(buf,2)); } - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", ragsrvinfo_db, server[id].fd) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", schema_config.ragsrvinfo_db, map_server[id].fd) ) Sql_ShowDebug(sql_handle); online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. mapif_server_destroy(id); @@ -3010,7 +2432,7 @@ int mapif_parse_reqcharban(int fd){ const char* name = (char*)RFIFOP(fd,10); // name of the target character RFIFOSKIP(fd,10+NAME_LENGTH); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", char_db, name) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, name) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) == 0 ){ return -1; // 1-player not found @@ -3038,7 +2460,7 @@ int mapif_parse_reqcharban(int fd){ if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `unban_time` = ? WHERE `char_id` = ? LIMIT 1", - char_db) + schema_config.char_db) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_LONG, (void*)&unban_time, sizeof(unban_time)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_INT, (void*)&t_cid, sizeof(t_cid)) || SQL_SUCCESS != SqlStmt_Execute(stmt) @@ -3057,7 +2479,7 @@ int mapif_parse_reqcharban(int fd){ WBUFL(buf,2) = t_cid; WBUFB(buf,6) = 2; WBUFL(buf,7) = (unsigned int)unban_time; - mapif_sendall(buf, 11); + chmapif_sendall(buf, 11); // disconnect player if online on char-server disconnect_player(t_aid); } @@ -3073,7 +2495,7 @@ int mapif_parse_reqcharunban(int fd){ int cid = RFIFOL(fd,2); RFIFOSKIP(fd,6); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time` = '0' WHERE `char_id` = '%d' LIMIT 1", char_db, cid) ) { + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time` = '0' WHERE `char_id` = '%d' LIMIT 1", schema_config.char_db, cid) ) { Sql_ShowDebug(sql_handle); return -1; } @@ -3103,7 +2525,7 @@ int mapif_parse_req_alter_acc(int fd) { RFIFOSKIP(fd,44); Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, esc_name) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) == 0 ) { result = 1; // 1-player not found @@ -3192,8 +2614,8 @@ int parse_frommap(int fd) int i, j; int id; - ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd ); - if( id == ARRAYLENGTH(server) ) + ARR_FIND( 0, ARRAYLENGTH(map_server), id, map_server[id].fd == fd ); + if( id == ARRAYLENGTH(map_server) ) {// not a map server ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd); do_close(fd); @@ -3202,7 +2624,7 @@ int parse_frommap(int fd) if( session[fd]->flag.eof ) { do_close(fd); - server[id].fd = -1; + map_server[id].fd = -1; mapif_on_disconnect(id); return 0; } @@ -3214,22 +2636,22 @@ int parse_frommap(int fd) if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; - memset(server[id].map, 0, sizeof(server[id].map)); + memset(map_server[id].map, 0, sizeof(map_server[id].map)); j = 0; for(i = 4; i < RFIFOW(fd,2); i += 4) { - server[id].map[j] = RFIFOW(fd,i); + map_server[id].map[j] = RFIFOW(fd,i); j++; } ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", - id, j, CONVIP(server[id].ip), server[id].port); + id, j, CONVIP(map_server[id].ip), map_server[id].port); ShowStatus("Map-server %d loading complete.\n", id); // send name for wisp to player WFIFOHEAD(fd, 3 + NAME_LENGTH); WFIFOW(fd,0) = 0x2afb; WFIFOB(fd,2) = 0; - memcpy(WFIFOP(fd,3), wisp_server_name, NAME_LENGTH); + memcpy(WFIFOP(fd,3), charserv_config.wisp_server_name, NAME_LENGTH); WFIFOSET(fd,3+NAME_LENGTH); char_send_fame_list(fd); //Send fame list. @@ -3243,22 +2665,22 @@ int parse_frommap(int fd) // Transmitting maps information to the other map-servers WBUFW(buf,0) = 0x2b04; WBUFW(buf,2) = j * 4 + 10; - WBUFL(buf,4) = htonl(server[id].ip); - WBUFW(buf,8) = htons(server[id].port); + WBUFL(buf,4) = htonl(map_server[id].ip); + WBUFW(buf,8) = htons(map_server[id].port); memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4); - mapif_sendallwos(fd, buf, WBUFW(buf,2)); + chmapif_sendallwos(fd, buf, WBUFW(buf,2)); } // Transmitting the maps of the other map-servers to the new map-server - for(x = 0; x < ARRAYLENGTH(server); x++) { - if (server[x].fd > 0 && x != id) { - WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server[x].map)); + for(x = 0; x < ARRAYLENGTH(map_server); x++) { + if (map_server[x].fd > 0 && x != id) { + WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map)); WFIFOW(fd,0) = 0x2b04; - WFIFOL(fd,4) = htonl(server[x].ip); - WFIFOW(fd,8) = htons(server[x].port); + WFIFOL(fd,4) = htonl(map_server[x].ip); + WFIFOW(fd,8) = htons(map_server[x].port); j = 0; - for(i = 0; i < ARRAYLENGTH(server[x].map); i++) - if (server[x].map[i]) - WFIFOW(fd,10+(j++)*4) = server[x].map[i]; + for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++) + if (map_server[x].map[i]) + WFIFOW(fd,10+(j++)*4) = map_server[x].map[i]; if (j > 0) { WFIFOW(fd,2) = j * 4 + 10; WFIFOSET(fd,WFIFOW(fd,2)); @@ -3278,7 +2700,7 @@ int parse_frommap(int fd) aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", - scdata_db, aid, cid) ) + schema_config.scdata_db, aid, cid) ) { Sql_ShowDebug(sql_handle); break; @@ -3326,7 +2748,7 @@ int parse_frommap(int fd) aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT skill, tick FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", - skillcooldown_db, aid, cid) ) + schema_config.skillcooldown_db, aid, cid) ) { Sql_ShowDebug(sql_handle); break; @@ -3355,7 +2777,7 @@ int parse_frommap(int fd) WFIFOW(fd,12) = count; WFIFOSET(fd,WFIFOW(fd,2)); //Clear the data once loaded. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", skillcooldown_db, aid, cid) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.skillcooldown_db, aid, cid) ) Sql_ShowDebug(sql_handle); } } @@ -3366,9 +2788,9 @@ int parse_frommap(int fd) case 0x2afe: //set MAP user count if (RFIFOREST(fd) < 4) return 0; - if (RFIFOW(fd,2) != server[id].users) { - server[id].users = RFIFOW(fd,2); - ShowInfo("User Count: %d (Server: %d)\n", server[id].users, id); + if (RFIFOW(fd,2) != map_server[id].users) { + map_server[id].users = RFIFOW(fd,2); + ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id); } RFIFOSKIP(fd, 4); break; @@ -3381,17 +2803,17 @@ int parse_frommap(int fd) int aid, cid; struct online_char_data* character; - server[id].users = RFIFOW(fd,4); + map_server[id].users = RFIFOW(fd,4); online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown' - for(i = 0; i < server[id].users; i++) { + for(i = 0; i < map_server[id].users; i++) { aid = RFIFOL(fd,6+i*8); cid = RFIFOL(fd,6+i*8+4); - character = idb_ensure(online_char_db, aid, create_online_char_data); + character = idb_ensure(online_char_db, aid, char_create_online_data); if( character->server > -1 && character->server != id ) { ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, id, aid, cid); - mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); + mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); } character->server = id; character->char_id = cid; @@ -3502,7 +2924,7 @@ int parse_frommap(int fd) map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. if (map_id >= 0) - map_fd = server[map_id].fd; + map_fd = map_server[map_id].fd; //Char should just had been saved before this packet, so this should be safe. [Skotlex] char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); if (char_data == NULL) { //Really shouldn't happen. @@ -3536,7 +2958,7 @@ int parse_frommap(int fd) node->changing_mapservers = 1; idb_put(auth_db, RFIFOL(fd,2), node); - data = idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data); + data = idb_ensure(online_char_db, RFIFOL(fd,2), char_create_online_data); data->char_id = char_data->char_id; data->server = map_id; //Update server where char is. @@ -3564,7 +2986,7 @@ int parse_frommap(int fd) char_id = RFIFOL(fd,2); friend_id = RFIFOL(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1", - friend_db, char_id, friend_id) ) { + schema_config.friend_db, char_id, friend_id) ) { Sql_ShowDebug(sql_handle); break; } @@ -3664,12 +3086,12 @@ int parse_frommap(int fd) if( RFIFOREST(fd) < 14 ) return 0; { - char esc_server_name[sizeof(server_name)*2+1]; + char esc_server_name[sizeof(charserv_config.server_name)*2+1]; - Sql_EscapeString(sql_handle, esc_server_name, server_name); + Sql_EscapeString(sql_handle, esc_server_name, charserv_config.server_name); if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d'", - ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) ) + schema_config.ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) ) Sql_ShowDebug(sql_handle); RFIFOSKIP(fd,14); } @@ -3714,7 +3136,7 @@ int parse_frommap(int fd) count = RFIFOW(fd, 12); // Whatever comes from the mapserver, now is the time to drop previous entries - if( Sql_Query( sql_handle, "DELETE FROM `%s` where `account_id` = %d and `char_id` = %d;", scdata_db, aid, cid ) != SQL_SUCCESS ){ + if( Sql_Query( sql_handle, "DELETE FROM `%s` where `account_id` = %d and `char_id` = %d;", schema_config.scdata_db, aid, cid ) != SQL_SUCCESS ){ Sql_ShowDebug( sql_handle ); }else if( count > 0 ){ struct status_change_data data; @@ -3722,7 +3144,7 @@ int parse_frommap(int fd) int i; StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", schema_config.scdata_db); for( i = 0; i < count; ++i ) { memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); @@ -3755,7 +3177,7 @@ int parse_frommap(int fd) int i; StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", skillcooldown_db); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", schema_config.skillcooldown_db); for( i = 0; i < count; ++i ) { memcpy(&data,RFIFOP(fd,14+i*sizeof(struct skill_cooldown_data)),sizeof(struct skill_cooldown_data)); @@ -3870,8 +3292,8 @@ int parse_frommap(int fd) case 0x2736: // ip address update if (RFIFOREST(fd) < 6) return 0; - server[id].ip = ntohl(RFIFOL(fd, 2)); - ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(server[id].ip)); + map_server[id].ip = ntohl(RFIFOL(fd, 2)); + ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(map_server[id].ip)); RFIFOSKIP(fd,6); break; @@ -3924,31 +3346,30 @@ int parse_frommap(int fd) void do_init_mapif(void) { int i; - for( i = 0; i < ARRAYLENGTH(server); ++i ) + for( i = 0; i < ARRAYLENGTH(map_server); ++i ) mapif_server_init(i); } void do_final_mapif(void) { int i; - for( i = 0; i < ARRAYLENGTH(server); ++i ) + for( i = 0; i < ARRAYLENGTH(map_server); ++i ) mapif_server_destroy(i); } // Searches for the mapserver that has a given map (and optionally ip/port, if not -1). // If found, returns the server's index in the 'server' array (otherwise returns -1). -int search_mapserver(unsigned short map, uint32 ip, uint16 port) -{ +int char_search_mapserver(unsigned short map, uint32 ip, uint16 port){ int i, j; - for(i = 0; i < ARRAYLENGTH(server); i++) + for(i = 0; i < ARRAYLENGTH(map_server); i++) { - if (server[i].fd > 0 - && (ip == (uint32)-1 || server[i].ip == ip) - && (port == (uint16)-1 || server[i].port == port)) + if (map_server[i].fd > 0 + && (ip == (uint32)-1 || map_server[i].ip == ip) + && (port == (uint16)-1 || map_server[i].port == port)) { - for (j = 0; server[i].map[j]; j++) - if (server[i].map[j] == map) + for (j = 0; map_server[i].map[j]; j++) + if (map_server[i].map[j] == map) return i; } } @@ -3962,11 +3383,12 @@ static int char_mapif_init(int fd) return inter_mapif_init(fd); } -//-------------------------------------------- -// Test to know if an IP come from LAN or WAN. -//-------------------------------------------- -int lan_subnetcheck(uint32 ip) -{ +/** + * Test to know if an IP come from LAN or WAN. + * @param ip: ip to check if in auth network + * @return 0 if from wan, or subnet_map_ip if lan + **/ +int char_lan_subnetcheck(uint32 ip){ int i; ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) ); if( i < subnet_count ) { @@ -4057,7 +3479,7 @@ static void char_delete2_req(int fd, struct char_session_data* sd) return; } - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); char_delete2_ack(fd, char_id, 3, 0); @@ -4089,9 +3511,9 @@ static void char_delete2_req(int fd, struct char_session_data* sd) */ // success - delete_date = time(NULL)+char_del_delay; + delete_date = time(NULL)+charserv_config.char_config.char_del_delay; - if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", char_db, (unsigned long)delete_date, char_id) ) + if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", schema_config.char_db, (unsigned long)delete_date, char_id) ) { Sql_ShowDebug(sql_handle); char_delete2_ack(fd, char_id, 3, 0); @@ -4132,7 +3554,7 @@ static void char_delete2_accept(int fd, struct char_session_data* sd) return; } - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) {// data error Sql_ShowDebug(sql_handle); char_delete2_accept_ack(fd, char_id, 3); @@ -4154,9 +3576,9 @@ static void char_delete2_accept(int fd, struct char_session_data* sd) return; } - if( ( char_del_level > 0 && base_level >= (unsigned int)char_del_level ) - || ( char_del_level < 0 && base_level <= (unsigned int)(-char_del_level) ) - || !(char_del_option&2) ) + if( ( charserv_config.char_config.char_del_level > 0 && base_level >= (unsigned int)charserv_config.char_config.char_del_level ) + || ( charserv_config.char_config.char_del_level < 0 && base_level <= (unsigned int)(-charserv_config.char_config.char_del_level) ) + || !(charserv_config.char_config.char_del_option&2) ) {// character level config restriction char_delete2_accept_ack(fd, char_id, 2); return; @@ -4195,7 +3617,7 @@ static void char_delete2_cancel(int fd, struct char_session_data* sd) // there is no need to check, whether or not the character was // queued for deletion, as the client prints an error message by // itself, if it was not the case (@see char_delete2_cancel_ack) - if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", char_db, char_id) ) + if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", schema_config.char_db, char_id) ) { Sql_ShowDebug(sql_handle); char_delete2_cancel_ack(fd, char_id, 2); @@ -4337,7 +3759,7 @@ int parse_char(int fd) int slot = RFIFOB(fd,2); RFIFOSKIP(fd,3); - if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot) + if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", schema_config.char_db, sd->account_id, slot) || SQL_SUCCESS != Sql_NextRow(sql_handle) || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) ) { //Not found?? May be forged packet. @@ -4378,12 +3800,12 @@ int parse_char(int fd) cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); cd->sex = sd->sex; - if (log_char) { + if (charserv_config.log_char) { char esc_name[NAME_LENGTH*2+1]; Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH)); if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", - charlog_db, sd->account_id, slot, esc_name) ) + schema_config.charlog_db, sd->account_id, slot, esc_name) ) Sql_ShowDebug(sql_handle); } ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name); @@ -4395,8 +3817,8 @@ int parse_char(int fd) if (i < 0 || !cd->last_point.map) { unsigned short j; //First check that there's actually a map server online. - ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] ); - if (j == ARRAYLENGTH(server)) { + ARR_FIND( 0, ARRAYLENGTH(map_server), j, map_server[j].fd >= 0 && map_server[j].map[0] ); + if (j == ARRAYLENGTH(map_server)) { ShowInfo("Connection Closed. No map servers available.\n"); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; @@ -4436,11 +3858,11 @@ int parse_char(int fd) //Send NEW auth packet [Kevin] //FIXME: is this case even possible? [ultramage] - if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL) + if ((map_fd = map_server[i].fd) < 1 || session[map_fd] == NULL) { ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); - server[i].fd = -1; - memset(&server[i], 0, sizeof(struct mmo_map_server)); + map_server[i].fd = -1; + memset(&map_server[i], 0, sizeof(struct mmo_map_server)); //Send server closed. WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; @@ -4454,9 +3876,9 @@ int parse_char(int fd) WFIFOW(fd,0) = 0x71; WFIFOL(fd,2) = cd->char_id; mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); - subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] - WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip); - WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!] + subnet_map_ip = char_lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : map_server[i].ip); + WFIFOW(fd,26) = ntows(htons(map_server[i].port)); // [!] LE byte order here [!] WFIFOSET(fd,28); // create temporary auth entry @@ -4485,7 +3907,7 @@ int parse_char(int fd) FIFOSD_CHECK(37); #endif - if( !char_new ) //turn character creation on/off [Kevin] + if( !charserv_config.char_new ) //turn character creation on/off [Kevin] i = -2; else #if PACKETVER >= 20120307 @@ -4551,7 +3973,7 @@ int parse_char(int fd) strcmp("a@a.com", sd->email) || //it is not default email, or (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default )) - || !(char_del_option&1) + || !(charserv_config.char_config.char_del_option&1) ) { //Fail WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x70; @@ -4618,7 +4040,7 @@ int parse_char(int fd) normalize_name(name,TRIM_CHARS); Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( !check_char_name(name,esc_name) ) { + if( !check_char_name(name,esc_name) ) { i = 1; safestrncpy(sd->new_name, name, NAME_LENGTH); } else @@ -4742,11 +4164,11 @@ int parse_char(int fd) char* l_pass = (char*)RFIFOP(fd,26); l_user[23] = '\0'; l_pass[23] = '\0'; - ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 ); + ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd <= 0 ); if( runflag != CHARSERVER_ST_RUNNING || - i == ARRAYLENGTH(server) || - strcmp(l_user, userid) != 0 || - strcmp(l_pass, passwd) != 0 ) + i == ARRAYLENGTH(map_server) || + strcmp(l_user, charserv_config.userid) != 0 || + strcmp(l_pass, charserv_config.passwd) != 0 ) { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2af9; @@ -4758,11 +4180,11 @@ int parse_char(int fd) WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - server[i].fd = fd; - server[i].ip = ntohl(RFIFOL(fd,54)); - server[i].port = ntohs(RFIFOW(fd,58)); - server[i].users = 0; - memset(server[i].map, 0, sizeof(server[i].map)); + map_server[i].fd = fd; + map_server[i].ip = ntohl(RFIFOL(fd,54)); + map_server[i].port = ntohs(RFIFOW(fd,58)); + map_server[i].users = 0; + memset(map_server[i].map, 0, sizeof(map_server[i].map)); session[fd]->func_parse = parse_frommap; session[fd]->flag.server = 1; realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); @@ -4776,8 +4198,8 @@ int parse_char(int fd) case 0x8b8: if( RFIFOREST(fd) < 10 ) return 0; - if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ) - pincode_check( fd, sd ); + if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ) + chclif_parse_pincode_check( fd, sd ); RFIFOSKIP(fd,10); break; @@ -4785,7 +4207,7 @@ int parse_char(int fd) case 0x8c5: if( RFIFOREST(fd) < 6 ) return 0; - if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ){ + if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ){ if( sd->pincode[0] == '\0' ){ pincode_sendstate( fd, sd, PINCODE_NEW ); }else{ @@ -4800,7 +4222,7 @@ int parse_char(int fd) if( RFIFOREST(fd) < 14 ) return 0; - if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ) + if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ) pincode_change( fd, sd ); RFIFOSKIP(fd,14); @@ -4810,7 +4232,7 @@ int parse_char(int fd) case 0x8ba: if( RFIFOREST(fd) < 10 ) return 0; - if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ) + if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ) pincode_setnew( fd, sd ); RFIFOSKIP(fd,10); break; @@ -4881,62 +4303,12 @@ int parse_console(const char* buf) return 0; } -int mapif_sendall(unsigned char *buf, unsigned int len) -{ - int i, c; - c = 0; - for(i = 0; i < ARRAYLENGTH(server); i++) { - int fd; - if ((fd = server[i].fd) > 0) { - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - c++; - } - } - return c; -} - -int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len) -{ - int i, c; - - c = 0; - for(i = 0; i < ARRAYLENGTH(server); i++) { - int fd; - if ((fd = server[i].fd) > 0 && fd != sfd) { - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - c++; - } - } - - return c; -} - -int mapif_send(int fd, unsigned char *buf, unsigned int len) -{ - if (fd >= 0) { - int i; - ARR_FIND( 0, ARRAYLENGTH(server), i, fd == server[i].fd ); - if( i < ARRAYLENGTH(server) ) - { - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - return 1; - } - } - return 0; -} - -int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) +int char_broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) { uint8 buf[6]; - int users = count_users(); + int users = char_count_users(); // only send an update when needed static int prev_users = 0; @@ -4956,7 +4328,7 @@ int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) // send number of players to all map-servers WBUFW(buf,0) = 0x2b00; WBUFL(buf,2) = users; - mapif_sendall(buf,6); + chmapif_sendall(buf,6); return 0; } @@ -5011,27 +4383,27 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data return 0; ShowInfo("Attempt to connect to login-server...\n"); - login_fd = make_connection(login_ip, login_port, false,10); + login_fd = make_connection(charserv_config.login_ip, charserv_config.login_port, false,10); if (login_fd == -1) { //Try again later. [Skotlex] login_fd = 0; return 0; } - session[login_fd]->func_parse = parse_fromlogin; + session[login_fd]->func_parse = chlogif_parse; session[login_fd]->flag.server = 1; realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); WFIFOHEAD(login_fd,86); WFIFOW(login_fd,0) = 0x2710; - memcpy(WFIFOP(login_fd,2), userid, 24); - memcpy(WFIFOP(login_fd,26), passwd, 24); + memcpy(WFIFOP(login_fd,2), charserv_config.userid, 24); + memcpy(WFIFOP(login_fd,26), charserv_config.passwd, 24); WFIFOL(login_fd,50) = 0; - WFIFOL(login_fd,54) = htonl(char_ip); - WFIFOW(login_fd,58) = htons(char_port); - memcpy(WFIFOP(login_fd,60), server_name, 20); + WFIFOL(login_fd,54) = htonl(charserv_config.char_ip); + WFIFOW(login_fd,58) = htons(charserv_config.char_port); + memcpy(WFIFOP(login_fd,60), charserv_config.server_name, 20); WFIFOW(login_fd,80) = 0; - WFIFOW(login_fd,82) = char_maintenance; - WFIFOW(login_fd,84) = char_new_display; //only display (New) if they want to [Kevin] + WFIFOW(login_fd,82) = charserv_config.char_maintenance; + WFIFOW(login_fd,84) = charserv_config.char_new_display; //only display (New) if they want to [Kevin] WFIFOSET(login_fd,86); return 1; @@ -5040,20 +4412,6 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data //------------------------------------------------ //Pincode system //------------------------------------------------ -void pincode_check( int fd, struct char_session_data* sd ){ - char pin[PINCODE_LENGTH+1]; - - memset(pin,0,PINCODE_LENGTH+1); - - strncpy((char*)pin, (char*)RFIFOP(fd, 6), PINCODE_LENGTH); - - pincode_decrypt(sd->pincode_seed, pin ); - - if( pincode_compare( fd, sd, pin ) ){ - pincode_sendstate( fd, sd, PINCODE_PASSED ); - } -} - int pincode_compare( int fd, struct char_session_data* sd, char* pin ){ if( strcmp( sd->pincode, pin ) == 0 ){ sd->pincode_try = 0; @@ -5061,84 +4419,16 @@ int pincode_compare( int fd, struct char_session_data* sd, char* pin ){ }else{ pincode_sendstate( fd, sd, PINCODE_WRONG ); - if( pincode_maxtry && ++sd->pincode_try >= pincode_maxtry ){ - pincode_notifyLoginPinError( sd->account_id ); + if( charserv_config.pincode_config.pincode_maxtry && ++sd->pincode_try >= charserv_config.pincode_config.pincode_maxtry ){ + chlogif_pincode_notifyLoginPinError( sd->account_id ); } return 0; } } -void pincode_change( int fd, struct char_session_data* sd ){ - char oldpin[PINCODE_LENGTH+1]; - char newpin[PINCODE_LENGTH+1]; - memset(oldpin,0,PINCODE_LENGTH+1); - memset(newpin,0,PINCODE_LENGTH+1); - - strncpy(oldpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH); - pincode_decrypt(sd->pincode_seed,oldpin); - - if( !pincode_compare( fd, sd, oldpin ) ) - return; - - strncpy(newpin, (char*)RFIFOP(fd,10), PINCODE_LENGTH); - pincode_decrypt(sd->pincode_seed,newpin); - - pincode_notifyLoginPinUpdate( sd->account_id, newpin ); - strncpy(sd->pincode, newpin, sizeof(newpin)); - - pincode_sendstate( fd, sd, PINCODE_PASSED ); -} - -void pincode_setnew( int fd, struct char_session_data* sd ){ - char newpin[PINCODE_LENGTH+1]; - - memset(newpin,0,PINCODE_LENGTH+1); - - strncpy( newpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH ); - pincode_decrypt( sd->pincode_seed, newpin ); - - pincode_notifyLoginPinUpdate( sd->account_id, newpin ); - strncpy( sd->pincode, newpin, strlen( newpin ) ); - - pincode_sendstate( fd, sd, PINCODE_PASSED ); -} - -// 0 = disabled / pin is correct -// 1 = ask for pin - client sends 0x8b8 -// 2 = create new pin - client sends 0x8ba -// 3 = pin must be changed - client 0x8be -// 4 = create new pin - client sends 0x8ba -// 5 = client shows msgstr(1896) -// 6 = client shows msgstr(1897) Unable to use your KSSN number -// 7 = char select window shows a button - client sends 0x8c5 -// 8 = pincode was incorrect -void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state ){ - WFIFOHEAD(fd, 12); - WFIFOW(fd, 0) = 0x8b9; - WFIFOL(fd, 2) = sd->pincode_seed = rnd() % 0xFFFF; - WFIFOL(fd, 6) = sd->account_id; - WFIFOW(fd,10) = state; - WFIFOSET(fd,12); -} - -void pincode_notifyLoginPinUpdate( int account_id, char* pin ){ - WFIFOHEAD(login_fd,11); - WFIFOW(login_fd,0) = 0x2738; - WFIFOL(login_fd,2) = account_id; - strncpy( (char*)WFIFOP(login_fd,6), pin, PINCODE_LENGTH+1 ); - WFIFOSET(login_fd,11); -} - -void pincode_notifyLoginPinError( int account_id ){ - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x2739; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); -} - -void pincode_decrypt( uint32 userSeed, char* pin ){ +void char_pincode_decrypt( uint32 userSeed, char* pin ){ int i, pos; char tab[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; char *buf; @@ -5168,7 +4458,7 @@ void pincode_decrypt( uint32 userSeed, char* pin ){ //------------------------------------------------ void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to ){ // Have we changed to often or is it disabled? - if( !char_move_enabled || ( !char_moves_unlimited && sd->char_moves[from] <= 0 ) ){ + if( !charserv_config.charmove_config.char_move_enabled || ( !charserv_config.charmove_config.char_moves_unlimited && sd->char_moves[from] <= 0 ) ){ moveCharSlotReply( fd, sd, from, 1 ); return; } @@ -5181,11 +4471,11 @@ void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, un if( sd->found_char[to] > 0 ){ // We want to move to a used position - if( char_movetoused ){ // TODO: check if the target is in deletion process + if( charserv_config.charmove_config.char_movetoused ){ // TODO: check if the target is in deletion process // Admin is friendly and uses triangle exchange if( SQL_ERROR == Sql_QueryStr(sql_handle, "START TRANSACTION") - || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", char_db, to, sd->found_char[from] ) - || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", char_db, from, sd->found_char[to] ) + || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, to, sd->found_char[from] ) + || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, from, sd->found_char[to] ) || SQL_ERROR == Sql_QueryStr(sql_handle, "COMMIT") ){ moveCharSlotReply( fd, sd, from, 1 ); @@ -5198,15 +4488,15 @@ void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, un moveCharSlotReply( fd, sd, from, 1 ); return; } - }else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", char_db, to, sd->found_char[from] ) ){ + }else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", schema_config.char_db, to, sd->found_char[from] ) ){ Sql_ShowDebug(sql_handle); moveCharSlotReply( fd, sd, from, 1 ); return; } - if( !char_moves_unlimited ){ + if( ! charserv_config.charmove_config.char_moves_unlimited ){ sd->char_moves[from]--; - Sql_Query(sql_handle, "UPDATE `%s` SET `moves`='%d' WHERE `char_id`='%d'", char_db, sd->char_moves[from], sd->found_char[from] ); + Sql_Query(sql_handle, "UPDATE `%s` SET `moves`='%d' WHERE `char_id`='%d'", schema_config.char_db, sd->char_moves[from], sd->found_char[from] ); } // We successfully moved the char - time to notify the client @@ -5214,17 +4504,6 @@ void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, un mmo_char_send(fd, sd); } -// reason -// 0: success -// 1: failed -void moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ){ - WFIFOHEAD(fd,8); - WFIFOW(fd,0) = 0x8d5; - WFIFOW(fd,2) = 8; - WFIFOW(fd,4) = reason; - WFIFOW(fd,6) = sd->char_moves[index]; - WFIFOSET(fd,8); -} /** [Cydh] * Get bonus_script data(s) from table to load @@ -5239,7 +4518,7 @@ void bonus_script_get(int fd) { RFIFOSKIP(fd,6); if (SQL_ERROR == Sql_Query(sql_handle,"SELECT `script`, `tick`, `flag`, `type`, `icon` FROM `%s` WHERE `char_id`='%d'", - bonus_script_db,cid)) + schema_config.bonus_script_db,cid)) { Sql_ShowDebug(sql_handle); return; @@ -5268,7 +4547,7 @@ void bonus_script_get(int fd) { WFIFOSET(fd,WFIFOW(fd,2)); //Clear the data once loaded. - if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id`='%d'",bonus_script_db,cid)) + if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id`='%d'",schema_config.bonus_script_db,cid)) Sql_ShowDebug(sql_handle); ShowInfo("Loaded %d bonus_script for char_id: %d\n",count,cid); } @@ -5297,7 +4576,7 @@ void bonus_script_save(int fd) { char esc_script[MAX_BONUS_SCRIPT_LENGTH] = ""; StringBuf_Init(&buf); - StringBuf_Printf(&buf,"INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ",bonus_script_db); + StringBuf_Printf(&buf,"INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ",schema_config.bonus_script_db); for (i = 0; i < count; ++i) { memcpy(&bs,RFIFOP(fd,10+i*sizeof(struct bonus_script_data)),sizeof(struct bonus_script_data)); Sql_EscapeString(sql_handle,esc_script,bs.script); @@ -5314,17 +4593,18 @@ void bonus_script_save(int fd) { } } + //------------------------------------------------ //Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't //replies/disconnect the player we tried to kick. [Skotlex] //------------------------------------------------ -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data) +int char_chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data) { struct online_char_data* character; if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid) { //Mark it offline due to timeout. character->waiting_disconnect = INVALID_TIMER; - set_char_offline(character->char_id, character->account_id); + char_set_char_offline(character->char_id, character->account_id); } return 0; } @@ -5332,33 +4612,33 @@ static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_ /** * @see DBApply */ -static int online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) +static int char_online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) { struct online_char_data *character= db_data2ptr(data); if (character->fd != -1) return 0; //Character still connected if (character->server == -2) //Unknown server.. set them offline - set_char_offline(character->char_id, character->account_id); + char_set_char_offline(character->char_id, character->account_id); if (character->server < 0) //Free data from players that have not been online for a while. db_remove(online_char_db, key); return 0; } -static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data) -{ - online_char_db->foreach(online_char_db, online_data_cleanup_sub); +static int char_online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data){ + online_char_db->foreach(online_char_db, char_online_data_cleanup_sub); return 0; } + + //---------------------------------- // Reading Lan Support configuration // Rewrote: Anvanced subnet check [LuzZza] //---------------------------------- -int char_lan_config_read(const char *lancfgName) -{ +int char_lan_config_read(const char *lancfgName) { FILE *fp; - int line_num = 0; + int line_num = 0, s_subnet=ARRAYLENGTH(subnet); char line[1024], w1[64], w2[64], w3[64], w4[64]; if((fp = fopen(lancfgName, "r")) == NULL) { @@ -5382,18 +4662,19 @@ int char_lan_config_read(const char *lancfgName) remove_control_chars(w3); remove_control_chars(w4); - if( strcmpi(w1, "subnet") == 0 ) - { + if( strcmpi(w1, "subnet") == 0 ){ + if(subnet_count>=s_subnet) { //We skip instead of break in case we want to add other conf in that file. + ShowError("%s: Too many subnets defined, skipping line %d...\n", lancfgName, line_num); + continue; + } subnet[subnet_count].mask = str2ip(w2); subnet[subnet_count].char_ip = str2ip(w3); subnet[subnet_count].map_ip = str2ip(w4); - if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) ) { ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4); continue; } - subnet_count++; } } @@ -5413,10 +4694,16 @@ int char_lan_config_read(const char *lancfgName) bool char_checkdb(void){ int i; const char* sqltable[] = { - char_db, hotkey_db, scdata_db, cart_db, inventory_db, charlog_db, storage_db, reg_db, skill_db, interlog_db, memo_db, - guild_db, guild_alliance_db, guild_castle_db, guild_expulsion_db, guild_member_db, guild_skill_db, guild_position_db, guild_storage_db, - party_db, pet_db, friend_db, mail_db, auction_db, quest_db, homunculus_db, skill_homunculus_db, mercenary_db, mercenary_owner_db, - elemental_db, ragsrvinfo_db, skillcooldown_db, bonus_script_db + schema_config.char_db, schema_config.hotkey_db, schema_config.scdata_db, schema_config.cart_db, + schema_config.inventory_db, schema_config.charlog_db, schema_config.storage_db, + schema_config.reg_db, schema_config.skill_db, schema_config.interlog_db, schema_config.memo_db, + schema_config.guild_db, schema_config.guild_alliance_db, schema_config.guild_castle_db, + schema_config.guild_expulsion_db, schema_config.guild_member_db, + schema_config.guild_skill_db, schema_config.guild_position_db, schema_config.guild_storage_db, + schema_config.party_db, schema_config.pet_db, schema_config.friend_db, schema_config.mail_db, + schema_config.auction_db, schema_config.quest_db, schema_config.homunculus_db, schema_config.skill_homunculus_db, + schema_config.mercenary_db, schema_config.mercenary_owner_db, + schema_config.elemental_db, schema_config.ragsrvinfo_db, schema_config.skillcooldown_db, schema_config.bonus_script_db }; ShowInfo("Start checking DB integrity\n"); for (i=0; i= 4) { - safestrncpy(wisp_server_name, w2, sizeof(wisp_server_name)); + safestrncpy(charserv_config.wisp_server_name, w2, sizeof(charserv_config.wisp_server_name)); } } else if (strcmpi(w1, "login_ip") == 0) { - login_ip = host2ip(w2); - if (login_ip) { + charserv_config.login_ip = host2ip(w2); + if (charserv_config.login_ip) { char ip_str[16]; - safestrncpy(login_ip_str, w2, sizeof(login_ip_str)); - ShowStatus("Login server IP address : %s -> %s\n", w2, ip2str(login_ip, ip_str)); + safestrncpy(charserv_config.login_ip_str, w2, sizeof(charserv_config.login_ip_str)); + ShowStatus("Login server IP address : %s -> %s\n", w2, ip2str(charserv_config.login_ip, ip_str)); } } else if (strcmpi(w1, "login_port") == 0) { - login_port = atoi(w2); + charserv_config.login_port = atoi(w2); } else if (strcmpi(w1, "char_ip") == 0) { - char_ip = host2ip(w2); - if (char_ip) { + charserv_config.char_ip = host2ip(w2); + if (charserv_config.char_ip) { char ip_str[16]; - safestrncpy(char_ip_str, w2, sizeof(char_ip_str)); - ShowStatus("Character server IP address : %s -> %s\n", w2, ip2str(char_ip, ip_str)); + safestrncpy(charserv_config.char_ip_str, w2, sizeof(charserv_config.char_ip_str)); + ShowStatus("Character server IP address : %s -> %s\n", w2, ip2str(charserv_config.char_ip, ip_str)); } } else if (strcmpi(w1, "bind_ip") == 0) { - bind_ip = host2ip(w2); - if (bind_ip) { + charserv_config.bind_ip = host2ip(w2); + if (charserv_config.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, ip2str(bind_ip, ip_str)); + safestrncpy(charserv_config.bind_ip_str, w2, sizeof(charserv_config.bind_ip_str)); + ShowStatus("Character server binding IP address : %s -> %s\n", w2, ip2str(charserv_config.bind_ip, ip_str)); } } else if (strcmpi(w1, "char_port") == 0) { - char_port = atoi(w2); + charserv_config.char_port = atoi(w2); } else if (strcmpi(w1, "char_maintenance") == 0) { - char_maintenance = atoi(w2); + charserv_config.char_maintenance = atoi(w2); } else if (strcmpi(w1, "char_new") == 0) { - char_new = (bool)atoi(w2); + charserv_config.char_new = (bool)atoi(w2); } else if (strcmpi(w1, "char_new_display") == 0) { - char_new_display = atoi(w2); + charserv_config.char_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; + charserv_config.max_connect_user = atoi(w2); + if (charserv_config.max_connect_user < -1) + charserv_config.max_connect_user = -1; } else if(strcmpi(w1, "gm_allow_group") == 0) { - gm_allow_group = atoi(w2); + charserv_config.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; + charserv_config.autosave_interval = atoi(w2)*1000; + if (charserv_config.autosave_interval <= 0) + charserv_config.autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; } else if (strcmpi(w1, "save_log") == 0) { - save_log = config_switch(w2); + charserv_config.save_log = config_switch(w2); } else if (strcmpi(w1, "start_point") == 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) + charserv_config.start_point.map = mapindex_name2id(map); + if (!charserv_config.start_point.map) ShowError("Specified start_point %s not found in map-index cache.\n", map); - start_point.x = x; - start_point.y = y; + charserv_config.start_point.x = x; + charserv_config.start_point.y = y; } else if (strcmpi(w1, "start_zeny") == 0) { - start_zeny = atoi(w2); - if (start_zeny < 0) - start_zeny = 0; + charserv_config.start_zeny = atoi(w2); + if (charserv_config.start_zeny < 0) + charserv_config.start_zeny = 0; } else if (strcmpi(w1, "start_items") == 0) { int i=0, n=0; char *lineitem, **fields; @@ -5843,26 +5220,26 @@ int char_config_read(const char* cfgName) } aFree(fields); } else if(strcmpi(w1,"log_char")==0) { //log char or not [devil] - log_char = atoi(w2); + charserv_config.log_char = atoi(w2); } else if (strcmpi(w1, "unknown_char_name") == 0) { - safestrncpy(unknown_char_name, w2, sizeof(unknown_char_name)); - unknown_char_name[NAME_LENGTH-1] = '\0'; + safestrncpy(charserv_config.char_config.unknown_char_name, w2, sizeof(charserv_config.char_config.unknown_char_name)); + charserv_config.char_config.unknown_char_name[NAME_LENGTH-1] = '\0'; } else if (strcmpi(w1, "name_ignoring_case") == 0) { - name_ignoring_case = (bool)config_switch(w2); + charserv_config.char_config.name_ignoring_case = (bool)config_switch(w2); } else if (strcmpi(w1, "char_name_option") == 0) { - char_name_option = atoi(w2); + charserv_config.char_config.char_name_option = atoi(w2); } else if (strcmpi(w1, "char_name_letters") == 0) { - safestrncpy(char_name_letters, w2, sizeof(char_name_letters)); + safestrncpy(charserv_config.char_config.char_name_letters, w2, sizeof(charserv_config.char_config.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); + charserv_config.char_config.char_del_level = atoi(w2); } else if (strcmpi(w1, "char_del_delay") == 0) { - char_del_delay = atoi(w2); + charserv_config.char_config.char_del_delay = atoi(w2); } else if (strcmpi(w1, "char_del_option") == 0) { - char_del_option = atoi(w2); + charserv_config.char_config.char_del_option = atoi(w2); } else if(strcmpi(w1,"db_path")==0) { - safestrncpy(db_path, w2, ARRAYLENGTH(db_path)); + safestrncpy(schema_config.db_path, w2, sizeof(schema_config.db_path)); } else if (strcmpi(w1, "console") == 0) { - console = config_switch(w2); + charserv_config.console = config_switch(w2); } else if (strcmpi(w1, "fame_list_alchemist") == 0) { fame_list_size_chemist = atoi(w2); if (fame_list_size_chemist > MAX_FAME_LIST) { @@ -5882,29 +5259,29 @@ int char_config_read(const char* cfgName) fame_list_size_taekwon = MAX_FAME_LIST; } } else if (strcmpi(w1, "guild_exp_rate") == 0) { - guild_exp_rate = atoi(w2); + charserv_config.guild_exp_rate = atoi(w2); } else if (strcmpi(w1, "pincode_enabled") == 0) { - pincode_enabled = config_switch(w2); + charserv_config.pincode_config.pincode_enabled = config_switch(w2); #if PACKETVER < 20110309 - if( pincode_enabled ) { + if( pincode_config.pincode_enabled ) { ShowWarning("pincode_enabled requires PACKETVER 20110309 or higher. Disabling...\n"); - pincode_enabled = false; + pincode_config.pincode_enabled = false; } #endif } else if (strcmpi(w1, "pincode_changetime") == 0) { - pincode_changetime = atoi(w2)*60*60*24; + charserv_config.pincode_config.pincode_changetime = atoi(w2)*60*60*24; } else if (strcmpi(w1, "pincode_maxtry") == 0) { - pincode_maxtry = atoi(w2); + charserv_config.pincode_config.pincode_maxtry = atoi(w2); } else if (strcmpi(w1, "pincode_force") == 0) { - pincode_force = config_switch(w2); + charserv_config.pincode_config.pincode_force = config_switch(w2); } else if (strcmpi(w1, "char_move_enabled") == 0) { - char_move_enabled = config_switch(w2); + charserv_config.charmove_config.char_move_enabled = config_switch(w2); } else if (strcmpi(w1, "char_movetoused") == 0) { - char_movetoused = config_switch(w2); + charserv_config.charmove_config.char_movetoused = config_switch(w2); } else if (strcmpi(w1, "char_moves_unlimited") == 0) { - char_moves_unlimited = config_switch(w2); + charserv_config.charmove_config.char_moves_unlimited = config_switch(w2); } else if (strcmpi(w1, "char_checkdb") == 0) { - char_check_db = config_switch(w2); + charserv_config.char_check_db = config_switch(w2); } else if (strcmpi(w1, "import") == 0) { char_config_read(w2); } @@ -5915,22 +5292,37 @@ int char_config_read(const char* cfgName) return 0; } + +/* + * Message conf function + */ +int char_msg_config_read(char *cfgName){ + return _msg_config_read(cfgName,CHAR_MAX_MSG,msg_table); +} +const char* char_msg_txt(int msg_number){ + return _msg_txt(msg_number,CHAR_MAX_MSG,msg_table); +} +void char_do_final_msg(void){ + _do_final_msg(CHAR_MAX_MSG,msg_table); +} + + void do_final(void) { ShowStatus("Terminating...\n"); - set_all_offline(-1); - set_all_offline_sql(); + char_set_all_offline(-1); + char_set_all_offline_sql(); inter_final(); flush_fifos(); do_final_msg(); - do_final_mapif(); - do_final_loginif(); + do_final_chmapif(); + do_final_chlogif(); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s`", ragsrvinfo_db) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s`", schema_config.ragsrvinfo_db) ) Sql_ShowDebug(sql_handle); char_db_->destroy(char_db_, NULL); @@ -5949,6 +5341,11 @@ void do_final(void) ShowStatus("Finished.\n"); } + +void set_server_type(void){ + SERVER_TYPE = ATHENA_SERVER_CHAR; +} + //------------------------------ // Function called when the server // has received a crash signal. @@ -5957,24 +5354,17 @@ void do_abort(void) { } -void set_server_type(void) -{ - SERVER_TYPE = ATHENA_SERVER_CHAR; -} - - /// Called when a terminate signal is received. -void do_shutdown(void) -{ +void do_shutdown(void) { if( runflag != CHARSERVER_ST_SHUTDOWN ) { int id; runflag = CHARSERVER_ST_SHUTDOWN; ShowStatus("Shutting down...\n"); // TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS] - for( id = 0; id < ARRAYLENGTH(server); ++id ) - mapif_server_reset(id); - loginif_check_shutdown(); + for( id = 0; id < ARRAYLENGTH(map_server); ++id ) + chmapif_server_reset(id); + chlogif_check_shutdown(); flush_fifos(); runflag = CORE_ST_STOP; } @@ -5986,7 +5376,6 @@ int do_init(int argc, char **argv) //Read map indexes runflag = CHARSERVER_ST_STARTING; mapindex_init(); - start_point.map = mapindex_name2id("new_zone01"); CHAR_CONF_NAME = "conf/char_athena.conf"; LAN_CONF_NAME = "conf/subnet_athena.conf"; @@ -5995,12 +5384,14 @@ int do_init(int argc, char **argv) cli_get_options(argc,argv); - msg_config_read(MSG_CONF_NAME_EN); + char_set_defaults(); char_config_read(CHAR_CONF_NAME); char_lan_config_read(LAN_CONF_NAME); - sql_config_read(SQL_CONF_NAME); + char_set_default_sql(); + char_sql_config_read(SQL_CONF_NAME); + msg_config_read(MSG_CONF_NAME_EN); - if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) { + if (strcmp(charserv_config.userid, "s1")==0 && strcmp(charserv_config.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_athena.conf (or conf/import/char_conf.txt)\n"); @@ -6010,10 +5401,10 @@ int do_init(int argc, char **argv) auth_db = idb_alloc(DB_OPT_RELEASE_DATA); online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); - mmo_char_sql_init(); + char_mmo_sql_init(); char_read_fame_list(); //Read fame lists. - if ((naddr_ != 0) && (!login_ip || !char_ip)) + if ((naddr_ != 0) && (!(charserv_config.login_ip) || !(charserv_config.char_ip) )) { char ip_str[16]; ip2str(addr_[0], ip_str); @@ -6022,96 +5413,64 @@ int do_init(int argc, char **argv) ShowStatus("Multiple interfaces detected.. using %s as our IP address\n", ip_str); else ShowStatus("Defaulting to %s as our IP address\n", ip_str); - if (!login_ip) { - safestrncpy(login_ip_str, ip_str, sizeof(login_ip_str)); - login_ip = str2ip(login_ip_str); + if (!(charserv_config.login_ip) ) { + safestrncpy(charserv_config.login_ip_str, ip_str, sizeof(charserv_config.login_ip_str)); + charserv_config.login_ip = str2ip(charserv_config.login_ip_str); } - if (!char_ip) { - safestrncpy(char_ip_str, ip_str, sizeof(char_ip_str)); - char_ip = str2ip(char_ip_str); + if (!(charserv_config.char_ip)) { + safestrncpy(charserv_config.char_ip_str, ip_str, sizeof(charserv_config.char_ip_str)); + charserv_config.char_ip = str2ip(charserv_config.char_ip_str); } } - do_init_loginif(); - do_init_mapif(); + do_init_chlogif(); + do_init_chmapif(); // periodically update the overall user count on all mapservers + login server - add_timer_func_list(broadcast_user_count, "broadcast_user_count"); - add_timer_interval(gettick() + 1000, broadcast_user_count, 0, 0, 5 * 1000); + add_timer_func_list(char_broadcast_user_count, "broadcast_user_count"); + add_timer_interval(gettick() + 1000, char_broadcast_user_count, 0, 0, 5 * 1000); // Timer to clear (online_char_db) - add_timer_func_list(chardb_waiting_disconnect, "chardb_waiting_disconnect"); + add_timer_func_list(char_chardb_waiting_disconnect, "chardb_waiting_disconnect"); // Online Data timers (checking if char still connected) - add_timer_func_list(online_data_cleanup, "online_data_cleanup"); - add_timer_interval(gettick() + 1000, online_data_cleanup, 0, 0, 600 * 1000); + add_timer_func_list(char_online_data_cleanup, "online_data_cleanup"); + add_timer_interval(gettick() + 1000, char_online_data_cleanup, 0, 0, 600 * 1000); //chek db tables - if(char_check_db && char_checkdb() == 0){ + if(charserv_config.char_check_db && char_checkdb() == 0){ ShowFatalError("char : A tables is missing in sql-server, please fix it, see (sql-files main.sql for structure) \n"); exit(EXIT_FAILURE); } //Cleaning the tables for NULL entrys @ startup [Sirius] //Chardb clean - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '0'", char_db) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '0'", schema_config.char_db) ) Sql_ShowDebug(sql_handle); //guilddb clean - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_lv` = '0' AND `max_member` = '0' AND `exp` = '0' AND `next_exp` = '0' AND `average_lv` = '0'", guild_db) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_lv` = '0' AND `max_member` = '0' AND `exp` = '0' AND `next_exp` = '0' AND `average_lv` = '0'", schema_config.guild_db) ) Sql_ShowDebug(sql_handle); //guildmemberdb clean - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '0' AND `account_id` = '0' AND `char_id` = '0'", guild_member_db) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '0' AND `account_id` = '0' AND `char_id` = '0'", schema_config.guild_member_db) ) Sql_ShowDebug(sql_handle); - set_defaultparse(parse_char); - + set_defaultparse(chclif_parse); - if( (char_fd = make_listen_bind(bind_ip,char_port)) == -1 ) { - ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",char_port); + if( (char_fd = make_listen_bind(charserv_config.bind_ip,charserv_config.char_port)) == -1 ) { + ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",charserv_config.char_port); exit(EXIT_FAILURE); } - ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); - if( runflag != CORE_ST_STOP ) { shutdown_callback = do_shutdown; runflag = CHARSERVER_ST_RUNNING; } - if( console ){ //start listening - add_timer_func_list(parse_console_timer, "parse_console_timer"); - add_timer_interval(gettick()+1000, parse_console_timer, 0, 0, 1000); //start in 1s each 1sec - } + do_init_chcnslif(); + + ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", charserv_config.char_port); + return 0; } - -int char_msg_config_read(char *cfgName){ - return _msg_config_read(cfgName,CHAR_MAX_MSG,msg_table); -} -const char* char_msg_txt(int msg_number){ - return _msg_txt(msg_number,CHAR_MAX_MSG,msg_table); -} -void char_do_final_msg(void){ - _do_final_msg(CHAR_MAX_MSG,msg_table); -} - -/*====================================================== - * Login-Server help option info - *------------------------------------------------------*/ -void display_helpscreen(bool do_exit) -{ - ShowInfo("Usage: %s [options]\n", SERVER_NAME); - ShowInfo("\n"); - ShowInfo("Options:\n"); - ShowInfo(" -?, -h [--help]\t\tDisplays this help screen.\n"); - ShowInfo(" -v [--version]\t\tDisplays the server's version.\n"); - ShowInfo(" --run-once\t\t\tCloses server after loading (testing).\n"); - ShowInfo(" --char-config \t\tAlternative char-server configuration.\n"); - ShowInfo(" --lan-config \t\tAlternative lag configuration.\n"); - ShowInfo(" --inter-config \t\tAlternative inter-server configuration.\n"); - ShowInfo(" --msg-config \t\tAlternative message configuration.\n"); - if( do_exit ) - exit(EXIT_SUCCESS); -} diff --git a/src/char/char.h b/src/char/char.h index 7d52271791..a4d03b0c80 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -4,31 +4,24 @@ #ifndef _CHAR_SQL_H_ #define _CHAR_SQL_H_ +#define DB_NAME_LEN 256 //max len of dbs + #include "../config/core.h" #include "../common/core.h" // CORE_ST_LAST #include "../common/msg_conf.h" +#include "../common/mmo.h" -enum E_CHARSERVER_ST -{ + +extern int login_fd; //login file descriptor +extern int char_fd; //char file descriptor + +enum E_CHARSERVER_ST { CHARSERVER_ST_RUNNING = CORE_ST_LAST, CHARSERVER_ST_STARTING, CHARSERVER_ST_SHUTDOWN, CHARSERVER_ST_LAST }; -struct mmo_charstatus; - -#define MAX_MAP_SERVERS 30 - -#define DEFAULT_AUTOSAVE_INTERVAL 300*1000 - -#define msg_config_read(cfgName) char_msg_config_read(cfgName) -#define msg_txt(msg_number) char_msg_txt(msg_number) -#define do_final_msg() char_do_final_msg() -int char_msg_config_read(char *cfgName); -const char* char_msg_txt(int msg_number); -void char_do_final_msg(void); - enum { TABLE_INVENTORY, TABLE_CART, @@ -36,11 +29,213 @@ enum { TABLE_GUILD_STORAGE, }; -int memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch); +struct Schema_Config { + int db_use_sqldbs; + char db_path[1024]; + char char_db[DB_NAME_LEN]; + char scdata_db[DB_NAME_LEN]; + char skillcooldown_db[DB_NAME_LEN]; + char cart_db[DB_NAME_LEN]; + char inventory_db[DB_NAME_LEN]; + char charlog_db[DB_NAME_LEN]; + char storage_db[DB_NAME_LEN]; + char interlog_db[DB_NAME_LEN]; + char reg_db[DB_NAME_LEN]; + char skill_db[DB_NAME_LEN]; + char memo_db[DB_NAME_LEN]; + char guild_db[DB_NAME_LEN]; + char guild_alliance_db[DB_NAME_LEN]; + char guild_castle_db[DB_NAME_LEN]; + char guild_expulsion_db[DB_NAME_LEN]; + char guild_member_db[DB_NAME_LEN]; + char guild_position_db[DB_NAME_LEN]; + char guild_skill_db[DB_NAME_LEN]; + char guild_storage_db[DB_NAME_LEN]; + char party_db[DB_NAME_LEN]; + char pet_db[DB_NAME_LEN]; + char mail_db[DB_NAME_LEN]; // MAIL SYSTEM + char auction_db[DB_NAME_LEN]; // Auctions System + char friend_db[DB_NAME_LEN]; + char hotkey_db[DB_NAME_LEN]; + char quest_db[DB_NAME_LEN]; + char homunculus_db[DB_NAME_LEN]; + char skill_homunculus_db[DB_NAME_LEN]; + char mercenary_db[DB_NAME_LEN]; + char mercenary_owner_db[DB_NAME_LEN]; + char ragsrvinfo_db[DB_NAME_LEN]; + char elemental_db[DB_NAME_LEN]; + char bonus_script_db[DB_NAME_LEN]; +}; +extern struct Schema_Config schema_config; -int mapif_sendall(unsigned char *buf,unsigned int len); -int mapif_sendallwos(int fd,unsigned char *buf,unsigned int len); -int mapif_send(int fd,unsigned char *buf,unsigned int len); +// Pincode system +enum pincode_state { + PINCODE_OK = 0, + PINCODE_ASK, + PINCODE_NOTSET, + PINCODE_EXPIRED, + PINCODE_NEW, + PINCODE_PASSED, + PINCODE_WRONG, + PINCODE_MAXSTATE +}; +struct Pincode_Config { + bool pincode_enabled; + int pincode_changetime; + int pincode_maxtry; + bool pincode_force; +}; +struct CharMove_Config { + bool char_move_enabled; + bool char_movetoused; + bool char_moves_unlimited; +}; +struct Char_Config { + int char_per_account; //Maximum chars per account (default unlimited) [Sirius] + int char_del_level; //From which level u can delete character [Lupus] + int char_del_delay; //minimum delay before effectly do the deletion + bool name_ignoring_case; // Allow or not identical name for characters but with a different case by [Yor] + char unknown_char_name[NAME_LENGTH]; // Name to use when the requested name cannot be determined + char char_name_letters[1024]; // list of letters/symbols allowed (or not) in a character name. by [Yor] + int char_name_option; // Option to know which letters/symbols are authorised 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] + int char_del_option; // Character deletion type, email = 1, birthdate = 2 (default) +}; + +#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] +struct CharServ_Config { + char userid[24]; + char passwd[24]; + char server_name[20]; + char wisp_server_name[NAME_LENGTH]; + char login_ip_str[128]; + uint32 login_ip; + uint16 login_port; + char char_ip_str[128]; + uint32 char_ip; + char bind_ip_str[128]; + uint32 bind_ip; + uint16 char_port; + int char_maintenance; + bool char_new; + int char_new_display; + + struct CharMove_Config charmove_config; + struct Char_Config char_config; + struct Pincode_Config pincode_config; + + int save_log; // show loading/saving messages + int log_char; // loggin char or not [devil] + int log_inter; // loggin inter or not [devil] + int char_check_db; ///cheking sql-table at begining ? + + struct point start_point; // Initial position the player will spawn on server + int console; + int max_connect_user; + int gm_allow_group; + int autosave_interval; + int start_zeny; + int guild_exp_rate; +}; +extern struct CharServ_Config charserv_config; + +#define MAX_MAP_SERVERS 30 //how many mapserver a char server can handle +struct mmo_map_server { + int fd; + uint32 ip; + uint16 port; + int users; + unsigned short map[MAX_MAP_PER_SERVER]; +}; +extern struct mmo_map_server map_server[MAX_MAP_SERVERS]; + +#define AUTH_TIMEOUT 30000 +struct auth_node { + int account_id; + int char_id; + uint32 login_id1; + uint32 login_id2; + uint32 ip; + int sex; + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + int group_id; + unsigned changing_mapservers : 1; + uint8 version; +}; +DBMap* char_get_authdb(); // int account_id -> struct auth_node* + +struct online_char_data { + int account_id; + int char_id; + int fd; + int waiting_disconnect; + short server; // -2: unknown server, -1: not connected, 0+: id of server + bool pincode_success; +}; +DBMap* char_get_onlinedb(); // int account_id -> struct online_char_data* + +struct char_session_data { + bool auth; // whether the session is authed or not + int account_id, login_id1, login_id2, sex; + int found_char[MAX_CHARS]; // ids of chars on this account + char email[40]; // e-mail (default: a@a.com) by [Yor] + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + int group_id; // permission + uint8 char_slots; // total number of characters that can be created + uint8 chars_vip; + uint8 chars_billing; + uint32 version; + uint8 clienttype; + char new_name[NAME_LENGTH]; + char birthdate[10+1]; // YYYY-MM-DD + // Pincode system + char pincode[PINCODE_LENGTH+1]; + uint32 pincode_seed; + time_t pincode_change; + uint16 pincode_try; + // Addon system + int bank_vault; + unsigned int char_moves[MAX_CHARS]; // character moves left + uint8 isvip; + time_t unban_time[MAX_CHARS]; + int charblock_timer; +}; + + +struct mmo_charstatus; +DBMap* char_get_chardb(); // int char_id -> struct mmo_charstatus* + +//Custom limits for the fame lists. [Skotlex] +extern int fame_list_size_chemist; +extern int fame_list_size_smith; +extern int fame_list_size_taekwon; +// Char-server-side stored fame lists [DracoRPG] +extern struct fame_list smith_fame_list[MAX_FAME_LIST]; +extern struct fame_list chemist_fame_list[MAX_FAME_LIST]; +extern struct fame_list taekwon_fame_list[MAX_FAME_LIST]; + +#define DEFAULT_AUTOSAVE_INTERVAL 300*1000 +#define MAX_CHAR_BUF 144 //Max size (for WFIFOHEAD calls) + +int char_search_mapserver(unsigned short map, uint32 ip, uint16 port); +int char_lan_subnetcheck(uint32 ip); + +int char_count_users(void); +DBData char_create_online_data(DBKey key, va_list args); +int char_db_setoffline(DBKey key, DBData *data, va_list ap); +void char_set_char_online(int map_id, int char_id, int account_id); +void char_set_char_offline(int char_id, int account_id); +void char_set_all_offline(int id); +void char_disconnect_player(int account_id); +int char_chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); + +int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p); +int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p); +int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything); +int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf); +int char_delete_char_sql(int char_id); +int char_rename_char_sql(struct char_session_data *sd, int char_id); +int char_divorce_char_sql(int partner_id1, int partner_id2); +int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch); int char_married(int pl1,int pl2); int char_child(int parent_id, int child_id); @@ -49,47 +244,35 @@ int char_family(int pl1,int pl2,int pl3); int request_accreg2(int account_id, int char_id); int save_accreg2(unsigned char* buf, int len); -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]; -extern char cart_db[256]; -extern char inventory_db[256]; -extern char charlog_db[256]; -extern char storage_db[256]; -extern char interlog_db[256]; -extern char reg_db[256]; -extern char skill_db[256]; -extern char memo_db[256]; -extern char guild_db[256]; -extern char guild_alliance_db[256]; -extern char guild_castle_db[256]; -extern char guild_expulsion_db[256]; -extern char guild_member_db[256]; -extern char guild_position_db[256]; -extern char guild_skill_db[256]; -extern char guild_storage_db[256]; -extern char party_db[256]; -extern char pet_db[256]; -extern char mail_db[256]; -extern char auction_db[256]; -extern char quest_db[256]; -extern char homunculus_db[256]; -extern char skill_homunculus_db[256]; -extern char mercenary_db[256]; -extern char mercenary_owner_db[256]; -extern char elemental_db[256]; -extern char ragsrvinfo_db[256]; -extern char bonus_script_db[256]; -extern char skillcooldown_db[256]; +//extern bool char_gm_read; +int char_loadName(int char_id, char* name); +int char_check_char_name(char * name, char * esc_name); -extern int db_use_sqldbs; // added for sql item_db read for char server [Valaris] +//Bonus Script +void bonus_script_get(int fd);///Get bonus_script data +void bonus_script_save(int fd); ///Save bonus_script data + +void char_pincode_decrypt( uint32 userSeed, char* pin ); +int char_pincode_compare( int fd, struct char_session_data* sd, char* pin ); +void char_auth_ok(int fd, struct char_session_data *sd); +void char_set_charselect(int account_id); +void char_read_fame_list(void); + +#if PACKETVER >= 20120307 +int char_make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int hair_color, int hair_style); +#else +int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style); +#endif + +//For use in packets that depend on an sd being present [Skotlex] +#define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } } + +#define msg_config_read(cfgName) char_msg_config_read(cfgName) +#define msg_txt(msg_number) char_msg_txt(msg_number) +#define do_final_msg() char_do_final_msg() +int char_msg_config_read(char *cfgName); +const char* char_msg_txt(int msg_number); +void char_do_final_msg(void); -extern int guild_exp_rate; -extern int log_inter; #endif /* _CHAR_SQL_H_ */ diff --git a/src/char/char_clif.c b/src/char/char_clif.c new file mode 100644 index 0000000000..29e18b71e9 --- /dev/null +++ b/src/char/char_clif.c @@ -0,0 +1,1116 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/mmo.h" +#include "../common/socket.h" +#include "../common/sql.h" +#include "../common/random.h" +#include "../common/showmsg.h" +#include "../common/mapindex.h" +#include "../common/malloc.h" +#include "../common/strlib.h" +#include "../common/utils.h" +#include "inter.h" +#include "char.h" +#include "char_logif.h" +#include "char_mapif.h" +#include "char_clif.h" + +#include +#include +#include + + +//------------------------------------------------ +//Add On system +//------------------------------------------------ +// reason +// 0: success +// 1: failed +void chclif_moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ){ + WFIFOHEAD(fd,8); + WFIFOW(fd,0) = 0x8d5; + WFIFOW(fd,2) = 8; + WFIFOW(fd,4) = reason; + WFIFOW(fd,6) = sd->char_moves[index]; + WFIFOSET(fd,8); +} + +/* + * Client is requesting to move a charslot + */ +int chclif_parse_moveCharSlot( int fd, struct char_session_data* sd){ + uint16 from, to; + + if( RFIFOREST(fd) < 8 ) + return 0; + from = RFIFOW(fd,2); + to = RFIFOW(fd,4); + //Cnt = RFIFOW(fd,6); //how many time we have left to change (client.. lol we don't trust him) + RFIFOSKIP(fd,8); + + // Have we changed to often or is it disabled? + if( (charserv_config.charmove_config.char_move_enabled)==0 + || ( (charserv_config.charmove_config.char_moves_unlimited)==0 && sd->char_moves[from] <= 0 ) ){ + chclif_moveCharSlotReply( fd, sd, from, 1 ); + return 0; + } + + // We dont even have a character on the chosen slot? + if( sd->found_char[from] <= 0 ){ + chclif_moveCharSlotReply( fd, sd, from, 1 ); + return 0; + } + + if( sd->found_char[to] > 0 ){ + // We want to move to a used position + if( charserv_config.charmove_config.char_movetoused ){ // TODO: check if the target is in deletion process + // Admin is friendly and uses triangle exchange + if( SQL_ERROR == Sql_QueryStr(sql_handle, "START TRANSACTION") + || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'",schema_config.char_db, to, sd->found_char[from] ) + || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, from, sd->found_char[to] ) + || SQL_ERROR == Sql_QueryStr(sql_handle, "COMMIT") + ){ + chclif_moveCharSlotReply( fd, sd, from, 1 ); + Sql_ShowDebug(sql_handle); + Sql_QueryStr(sql_handle,"ROLLBACK"); + return 0; + } + }else{ + // Admin doesnt allow us to + chclif_moveCharSlotReply( fd, sd, from, 1 ); + return 0; + } + }else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", schema_config.char_db, to, sd->found_char[from] ) ){ + Sql_ShowDebug(sql_handle); + chclif_moveCharSlotReply( fd, sd, from, 1 ); + return 0; + } + + if( (charserv_config.charmove_config.char_moves_unlimited)==0 ){ + sd->char_moves[from]--; + Sql_Query(sql_handle, "UPDATE `%s` SET `moves`='%d' WHERE `char_id`='%d'", schema_config.char_db, sd->char_moves[from], sd->found_char[from] ); + } + + // We successfully moved the char - time to notify the client + chclif_moveCharSlotReply( fd, sd, from, 0 ); + chclif_mmo_char_send(fd, sd); + return 1; +} + +/* pincode_sendstate transmist the pincode state to client + * S 08b9 .L .L .W (HC_SECOND_PASSWD_LOGIN) + * state : + * 0 = disabled / pin is correct + * 1 = ask for pin - client sends 0x8b8 + * 2 = create new pin - client sends 0x8ba + * 3 = pin must be changed - client 0x8be + * 4 = create new pin - client sends 0x8ba + * 5 = client shows msgstr(1896) + * 6 = client shows msgstr(1897) Unable to use your KSSN number + * 7 = char select window shows a button - client sends 0x8c5 + * 8 = pincode was incorrect +*/ +void chclif_pincode_sendstate( int fd, struct char_session_data* sd, enum pincode_state state ){ + WFIFOHEAD(fd, 12); + WFIFOW(fd, 0) = 0x8b9; + WFIFOL(fd, 2) = sd->pincode_seed = rnd() % 0xFFFF; + WFIFOL(fd, 6) = sd->account_id; + WFIFOW(fd,10) = state; + WFIFOSET(fd,12); +} + +/* + * Client just entering charserv from login, send him pincode confirmation + */ +int chclif_parse_reqpincode_window(int fd, struct char_session_data* sd){ + if( RFIFOREST(fd) < 6 ) + return 0; + if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ){ + if( strlen( sd->pincode ) <= 0 ){ + chclif_pincode_sendstate( fd, sd, PINCODE_NEW ); + }else{ + chclif_pincode_sendstate( fd, sd, PINCODE_ASK ); + } + } + RFIFOSKIP(fd,6); + return 1; +} + +/* + * Client as anwsered pincode questionning, checking if valid anwser + */ +int chclif_parse_pincode_check( int fd, struct char_session_data* sd ){ + char pin[PINCODE_LENGTH+1]; + + if( RFIFOREST(fd) < 10 ) + return 0; + if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) + return 0; + + memset(pin,0,PINCODE_LENGTH+1); + strncpy((char*)pin, (char*)RFIFOP(fd, 6), PINCODE_LENGTH); + RFIFOSKIP(fd,10); + + char_pincode_decrypt(sd->pincode_seed, pin ); + if( char_pincode_compare( fd, sd, pin ) ){ + chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + } + return 1; +} + +/* + * Client request to change pincode + */ +int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ + char oldpin[PINCODE_LENGTH+1]; + char newpin[PINCODE_LENGTH+1]; + + if( RFIFOREST(fd) < 14 ) + return 0; + if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) + return 0; + + memset(oldpin,0,PINCODE_LENGTH+1); + memset(newpin,0,PINCODE_LENGTH+1); + strncpy(oldpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH); + strncpy(newpin, (char*)RFIFOP(fd,10), PINCODE_LENGTH); + RFIFOSKIP(fd,14); + + char_pincode_decrypt(sd->pincode_seed,oldpin); + if( !char_pincode_compare( fd, sd, oldpin ) ) + return 0; + char_pincode_decrypt(sd->pincode_seed,newpin); + + chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); + strncpy(sd->pincode, newpin, sizeof(newpin)); + + chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + return 1; +} + +/* + * activate PIN system and set first PIN + */ +int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){ + char newpin[PINCODE_LENGTH+1]; + + memset(newpin,0,PINCODE_LENGTH+1); + + if( RFIFOREST(fd) < 10 ) + return 0; + + if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) + return 0; + strncpy( newpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH ); + RFIFOSKIP(fd,10); + + char_pincode_decrypt( sd->pincode_seed, newpin ); + + chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); + strncpy( sd->pincode, newpin, strlen( newpin ) ); + + chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + return 1; +} + + +//---------------------------------------- +// Tell client how many pages, kRO sends 17 (Yommy) +//---------------------------------------- +void chclif_charlist_notify( int fd, struct char_session_data* sd ){ + WFIFOHEAD(fd, 6); + WFIFOW(fd, 0) = 0x9a0; + // pages to req / send them all in 1 until mmo_chars_fromsql can split them up + WFIFOL(fd, 2) = (sd->char_slots>3)?sd->char_slots/3:1; //int TotalCnt (nb page to load) + WFIFOSET(fd,6); +} + +void chclif_block_character( int fd, struct char_session_data* sd ){ + WFIFOHEAD(fd, 4); + WFIFOW(fd, 0) = 0x20d; + WFIFOW(fd, 2) = 4; //packet len + WFIFOSET(fd,4); +} + +//---------------------------------------- +// Function to send characters to a player +//---------------------------------------- +int chclif_mmo_send006b(int fd, struct char_session_data* sd){ + int j, offset = 0; + bool newvers = (sd->version >= date2version(20100413) ); + if(newvers) //20100413 + offset += 3; + if (charserv_config.save_log) + ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); + + j = 24 + offset; // offset + WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF); + WFIFOW(fd,0) = 0x6b; + if(newvers){ //20100413 + WFIFOB(fd,4) = MAX_CHARS; // Max slots. + WFIFOB(fd,5) = sd->char_slots; // Available slots. (PremiumStartSlot) + WFIFOB(fd,6) = MAX_CHARS; // Premium slots. (Any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red) + } + memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes + j+=char_mmo_chars_fromsql(sd, WFIFOP(fd,j)); + WFIFOW(fd,2) = j; // packet len + WFIFOSET(fd,j); + + return 0; +} + +//---------------------------------------- +// Notify client about charselect window data [Ind] +//---------------------------------------- +void chclif_mmo_send082d(int fd, struct char_session_data* sd) { + if (charserv_config.save_log) + ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); + WFIFOHEAD(fd,29); + WFIFOW(fd,0) = 0x82d; + WFIFOW(fd,2) = 29; + WFIFOB(fd,4) = sd->char_slots; + WFIFOB(fd,5) = MAX_CHARS - sd->char_slots; + WFIFOB(fd,6) = MAX_CHARS - sd->char_slots; + WFIFOB(fd,7) = sd->char_slots; + WFIFOB(fd,8) = sd->char_slots; + memset(WFIFOP(fd,9), 0, 20); // unused bytes + WFIFOSET(fd,29); +} + +void chclif_mmo_send099d(int fd, struct char_session_data *sd) { + WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF)); + WFIFOW(fd,0) = 0x99d; + WFIFOW(fd,2) = char_mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4; + WFIFOSET(fd,WFIFOW(fd,2)); +} + + +/* + * Function to choose wich kind of charlist to send to client depending on his version + */ +void chclif_mmo_char_send(int fd, struct char_session_data* sd){ + ShowInfo("sd->version = %d\n",sd->version); + if(sd->version >= date2version(20130000) ){ + chclif_mmo_send082d(fd,sd); + chclif_charlist_notify(fd,sd); + chclif_block_character(fd,sd); + } + //@FIXME dump from kro doesn't show 6b transmission + chclif_mmo_send006b(fd,sd); +} + +/* + * Transmit auth result to client + * .B () + * result : + * 1 : Server closed + * 2 : Someone has already logged in with this id + * 8 : already online + */ +void chclif_send_auth_result(int fd,char result){ + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = result; + WFIFOSET(fd,3); +} + +/// @param result +/// 0 (0x718): An unknown error has occurred. +/// 1: none/success +/// 3 (0x719): A database error occurred. +/// 4 (0x71a): To delete a character you must withdraw from the guild. +/// 5 (0x71b): To delete a character you must withdraw from the party. +/// Any (0x718): An unknown error has occurred. +/// HC: <0828>.W .L .L .L +void chclif_char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date) { + WFIFOHEAD(fd,14); + WFIFOW(fd,0) = 0x828; + WFIFOL(fd,2) = char_id; + WFIFOL(fd,6) = result; + WFIFOL(fd,10) = TOL(delete_date); + WFIFOSET(fd,14); +} + +/// @param result +/// 0 (0x718): An unknown error has occurred. +/// 1: none/success +/// 2 (0x71c): Due to system settings can not be deleted. +/// 3 (0x719): A database error occurred. +/// 4 (0x71d): Deleting not yet possible time. +/// 5 (0x71e): Date of birth do not match. +/// Any (0x718): An unknown error has occurred. +/// HC: <082a>.W .L .L +void chclif_char_delete2_accept_ack(int fd, int char_id, uint32 result) { + WFIFOHEAD(fd,10); + WFIFOW(fd,0) = 0x82a; + WFIFOL(fd,2) = char_id; + WFIFOL(fd,6) = result; + WFIFOSET(fd,10); +} + +/// @param result +/// 1 (0x718): none/success, (if char id not in deletion process): An unknown error has occurred. +/// 2 (0x719): A database error occurred. +/// Any (0x718): An unknown error has occurred. +/// HC: <082c>.W .L .L +void chclif_char_delete2_cancel_ack(int fd, int char_id, uint32 result) { + WFIFOHEAD(fd,10); + WFIFOW(fd,0) = 0x82c; + WFIFOL(fd,2) = char_id; + WFIFOL(fd,6) = result; + WFIFOSET(fd,10); +} + +// CH: <0827>.W .L +int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { + int char_id, i; + char* data; + time_t delete_date; + + FIFOSD_CHECK(6) + + char_id = RFIFOL(fd,2); + RFIFOSKIP(fd,6); + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); + if( i == MAX_CHARS ) + {// character not found + chclif_char_delete2_ack(fd, char_id, 3, 0); + return 0; + } + + if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + { + Sql_ShowDebug(sql_handle); + chclif_char_delete2_ack(fd, char_id, 3, 0); + return 0; + } + + Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); + + if( delete_date ) {// character already queued for deletion + chclif_char_delete2_ack(fd, char_id, 0, 0); + return 0; + } + +/* + // Aegis imposes these checks probably to avoid dead member + // entries in guilds/parties, otherwise they are not required. + // TODO: Figure out how these are enforced during waiting. + if( guild_id ) + {// character in guild + char_delete2_ack(fd, char_id, 4, 0); + return; + } + + if( party_id ) + {// character in party + char_delete2_ack(fd, char_id, 5, 0); + return; + } +*/ + + // success + delete_date = time(NULL)+(charserv_config.char_config.char_del_delay); + + if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", schema_config.char_db, (unsigned long)delete_date, char_id) ) + { + Sql_ShowDebug(sql_handle); + chclif_char_delete2_ack(fd, char_id, 3, 0); + return 0; + } + + chclif_char_delete2_ack(fd, char_id, 1, delete_date); + return 1; +} + +// CH: <0829>.W .L .6B +int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) { + char birthdate[8+1]; + int char_id, i, k; + unsigned int base_level; + char* data; + time_t delete_date; + + FIFOSD_CHECK(12) + + char_id = RFIFOL(fd,2); + + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id); + + // construct "YY-MM-DD" + birthdate[0] = RFIFOB(fd,6); + birthdate[1] = RFIFOB(fd,7); + birthdate[2] = '-'; + birthdate[3] = RFIFOB(fd,8); + birthdate[4] = RFIFOB(fd,9); + birthdate[5] = '-'; + birthdate[6] = RFIFOB(fd,10); + birthdate[7] = RFIFOB(fd,11); + birthdate[8] = 0; + RFIFOSKIP(fd,12); + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); + if( i == MAX_CHARS ) + {// character not found + chclif_char_delete2_accept_ack(fd, char_id, 3); + return 0; + } + + if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + {// data error + Sql_ShowDebug(sql_handle); + chclif_char_delete2_accept_ack(fd, char_id, 3); + return 0; + } + + Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10); + + if( !delete_date || delete_date>time(NULL) ) + {// not queued or delay not yet passed + chclif_char_delete2_accept_ack(fd, char_id, 4); + return 0; + } + + if( strcmp(sd->birthdate+2, birthdate) ) // +2 to cut off the century + {// birth date is wrong + chclif_char_delete2_accept_ack(fd, char_id, 5); + return 0; + } + + if( ( charserv_config.char_config.char_del_level > 0 && base_level >= (unsigned int)charserv_config.char_config.char_del_level ) + || ( charserv_config.char_config.char_del_level < 0 && base_level <= (unsigned int)(-charserv_config.char_config.char_del_level) ) ) + {// character level config restriction + chclif_char_delete2_accept_ack(fd, char_id, 2); + return 0; + } + + // success + if( char_delete_char_sql(char_id) < 0 ) + { + chclif_char_delete2_accept_ack(fd, char_id, 3); + return 0; + } + + // refresh character list cache + for(k = i; k < MAX_CHARS-1; k++) + { + sd->found_char[k] = sd->found_char[k+1]; + } + sd->found_char[MAX_CHARS-1] = -1; + + chclif_char_delete2_accept_ack(fd, char_id, 1); + return 1; +} + +// CH: <082b>.W .L +int chclif_parse_char_delete2_cancel(int fd, struct char_session_data* sd) { + int char_id, i; + + FIFOSD_CHECK(6) + + char_id = RFIFOL(fd,2); + RFIFOSKIP(fd,6); + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); + if( i == MAX_CHARS ) + {// character not found + chclif_char_delete2_cancel_ack(fd, char_id, 2); + return 0; + } + + // there is no need to check, whether or not the character was + // queued for deletion, as the client prints an error message by + // itself, if it was not the case (@see char_delete2_cancel_ack) + if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", schema_config.char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); + chclif_char_delete2_cancel_ack(fd, char_id, 2); + return 0; + } + + chclif_char_delete2_cancel_ack(fd, char_id, 1); + return 1; +} + +/* + * Register a new mapserver into that char-serv + * charserv can handle a MAX_SERVERS mapservs + */ +int chclif_parse_maplogin(int fd){ + int i; + + if (RFIFOREST(fd) < 60) + return 0; + else { + char* l_user = (char*)RFIFOP(fd,2); + char* l_pass = (char*)RFIFOP(fd,26); + l_user[23] = '\0'; + l_pass[23] = '\0'; + ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd <= 0 ); + if( runflag != CHARSERVER_ST_RUNNING || + i == ARRAYLENGTH(map_server) || + strcmp(l_user, charserv_config.userid) != 0 || + strcmp(l_pass, charserv_config.passwd) != 0 ) + { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2af9; + WFIFOB(fd,2) = 3; + WFIFOSET(fd,3); + } else { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2af9; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + + map_server[i].fd = fd; + map_server[i].ip = ntohl(RFIFOL(fd,54)); + map_server[i].port = ntohs(RFIFOW(fd,58)); + map_server[i].users = 0; + memset(map_server[i].map, 0, sizeof(map_server[i].map)); + session[fd]->func_parse = chmapif_parse; + session[fd]->flag.server = 1; + realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + chmapif_init(fd); + } + RFIFOSKIP(fd,60); + } + return 1; +} + +// 0065 .L .L .L .W .B +int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){ + if( RFIFOREST(fd) < 17 ) // request to connect + return 0; + else { + struct auth_node* node; + DBMap *auth_db = char_get_authdb(); + + int account_id = RFIFOL(fd,2); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); + int sex = RFIFOB(fd,16); + RFIFOSKIP(fd,17); + + ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2); + + if (sd) { + //Received again auth packet for already authentified account?? Discard it. + //TODO: Perhaps log this as a hack attempt? + //TODO: and perhaps send back a reply? + ShowInfo("Already registered break\n"); + return 0; + } + + CREATE(session[fd]->session_data, struct char_session_data, 1); + sd = (struct char_session_data*)session[fd]->session_data; + sd->account_id = account_id; + sd->login_id1 = login_id1; + sd->login_id2 = login_id2; + sd->sex = sex; + sd->auth = false; // not authed yet + + // send back account_id + WFIFOHEAD(fd,4); + WFIFOL(fd,0) = account_id; + WFIFOSET(fd,4); + + if( runflag != CHARSERVER_ST_RUNNING ) + { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0;// rejected from server + WFIFOSET(fd,3); + return 0; + } + + // search authentification + node = (struct auth_node*)idb_get(auth_db, account_id); + if( node != NULL && + node->account_id == account_id && + node->login_id1 == login_id1 && + node->login_id2 == login_id2 /*&& + node->ip == ipl*/ ) + {// authentication found (coming from map server) + DBMap *online_char_db = char_get_onlinedb(); + struct online_char_data* ol_cd = (struct online_char_data*)idb_get(online_char_db, account_id); + if(ol_cd) sd->version = ol_cd->version; + ShowInfo("char_parse_reqtoconnect: authentication found (coming from map server), sd->v=%d online_chd=%d\n",sd->version,ol_cd); + idb_remove(auth_db, account_id); + char_auth_ok(fd, sd); + } + else + {// authentication not found (coming from login server) + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,23); + WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account + WFIFOL(login_fd,2) = sd->account_id; + WFIFOL(login_fd,6) = sd->login_id1; + WFIFOL(login_fd,10) = sd->login_id2; + WFIFOB(login_fd,14) = sd->sex; + WFIFOL(login_fd,15) = htonl(ipl); + WFIFOL(login_fd,19) = fd; + WFIFOSET(login_fd,23); + } else { // if no login-server, we must refuse connection + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + } + } + } + return 1; +} + +//struct PACKET_CH_CHARLIST_REQ { 0x0 short PacketType} +int chclif_parse_req_charlist(int fd, struct char_session_data* sd){ + if( RFIFOREST(fd) < 2 ) + return 0; + RFIFOSKIP(fd,2); + chclif_mmo_send099d(fd,sd); + return 1; +} + +int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ + FIFOSD_CHECK(3); + { + struct mmo_charstatus char_dat; + struct mmo_charstatus *cd; + char* data; + int char_id; + uint32 subnet_map_ip; + struct auth_node* node; + int i, map_fd; + DBMap *auth_db = char_get_authdb(); + DBMap *char_db_ = char_get_chardb(); + + int slot = RFIFOB(fd,2); + RFIFOSKIP(fd,3); + + if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", schema_config.char_db, sd->account_id, slot) + || SQL_SUCCESS != Sql_NextRow(sql_handle) + || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) ) + { //Not found?? May be forged packet. + Sql_ShowDebug(sql_handle); + Sql_FreeResult(sql_handle); + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; // rejected from server + WFIFOSET(fd,3); + return 0; + } + + char_id = atoi(data); + Sql_FreeResult(sql_handle); + + /* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */ + char_set_char_online(-2,char_id,sd->account_id); + if( !char_mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */ + char_set_char_offline(char_id, sd->account_id); + /* failed to load something. REJECT! */ + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + return 0;/* jump off this boat */ + } + + //Have to switch over to the DB instance otherwise data won't propagate [Kevin] + cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); + cd->sex = sd->sex; + + if (charserv_config.log_char) { + char esc_name[NAME_LENGTH*2+1]; + + Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", + schema_config.charlog_db, sd->account_id, slot, esc_name) ) + Sql_ShowDebug(sql_handle); + } + ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name); + + // searching map server + i = char_search_mapserver(cd->last_point.map, -1, -1); + + // if map is not found, we check major cities + if (i < 0 || !cd->last_point.map) { + unsigned short j; + //First check that there's actually a map server online. + ARR_FIND( 0, ARRAYLENGTH(map_server), j, map_server[j].fd >= 0 && map_server[j].map[0] ); + if (j == ARRAYLENGTH(map_server)) { + ShowInfo("Connection Closed. No map servers available.\n"); + chclif_send_auth_result(fd,1); // 01 = Server closed + return 0; + } + if ((i = char_search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) { + cd->last_point.x = 273; + cd->last_point.y = 354; + } else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) { + cd->last_point.x = 120; + cd->last_point.y = 100; + } else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) { + cd->last_point.x = 160; + cd->last_point.y = 94; + } else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) { + cd->last_point.x = 116; + cd->last_point.y = 57; + } else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) { + cd->last_point.x = 87; + cd->last_point.y = 117; + } else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) { + cd->last_point.x = 94; + cd->last_point.y = 103; + } else { + ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map)); + chclif_send_auth_result(fd,1); // 01 = Server closed + return 0; + } + ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j)); + cd->last_point.map = j; + } + + //Send NEW auth packet [Kevin] + //FIXME: is this case even possible? [ultramage] + if ((map_fd = map_server[i].fd) < 1 || session[map_fd] == NULL) + { + ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); + map_server[i].fd = -1; + memset(&map_server[i], 0, sizeof(struct mmo_map_server)); + chclif_send_auth_result(fd,1); //Send server closed. + return 0; + } + + //Send player to map + WFIFOHEAD(fd,28); + WFIFOW(fd,0) = 0x71; + WFIFOL(fd,2) = cd->char_id; + mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); + subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : map_server[i].ip); + WFIFOW(fd,26) = ntows(htons(map_server[i].port)); // [!] LE byte order here [!] + WFIFOSET(fd,28); + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = sd->account_id; + node->char_id = cd->char_id; + node->login_id1 = sd->login_id1; + node->login_id2 = sd->login_id2; + node->sex = sd->sex; + node->expiration_time = sd->expiration_time; + node->group_id = sd->group_id; + node->ip = ipl; + idb_put(auth_db, sd->account_id, node); + + } + return 1; +} + +// S 0970 .24B .B .W .W +// S 0067 .24B .B .B .B .B .B .B .B .W .W +int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd){ + int i=0, ch; + + if (cmd == 0x970) FIFOSD_CHECK(31) //>=20120307 + else if (cmd == 0x67) FIFOSD_CHECK(37) + else return 0; + + if( (charserv_config.char_new)==0 ) //turn character creation on/off [Kevin] + i = -2; + else { + if (cmd == 0x970){ + i = char_make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29)); + RFIFOSKIP(fd,31); + } + else if(cmd == 0x67){ +#if PACKETVER < 20120307 + i = char_make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35)); + RFIFOSKIP(fd,37); +#endif + } + } + + //'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3) + if (i < 0) { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6e; + /* Others I found [Ind] */ + /* 0x02 = Symbols in Character Names are forbidden */ + /* 0x03 = You are not elegible to open the Character Slot. */ + switch (i) { + case -1: WFIFOB(fd,2) = 0x00; break; + case -2: WFIFOB(fd,2) = 0xFF; break; + case -3: WFIFOB(fd,2) = 0x01; break; + case -4: WFIFOB(fd,2) = 0x03; break; + } + WFIFOSET(fd,3); + } else { + int len; + // retrieve data + struct mmo_charstatus char_dat; + char_mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed. + + // send to player + WFIFOHEAD(fd,2+MAX_CHAR_BUF); + WFIFOW(fd,0) = 0x6d; + len = 2 + char_mmo_char_tobuf(WFIFOP(fd,2), &char_dat); + WFIFOSET(fd,len); + + // add new entry to the chars list + ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 ); + if( ch < MAX_CHARS ) + sd->found_char[ch] = i; // the char_id of the new char + } + return 1; +} + +int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){ + char email[40]; + int i, ch; + + if (cmd == 0x68) FIFOSD_CHECK(46) + else if (cmd == 0x1fb) FIFOSD_CHECK(56) + else return 0; + + { + int cid = RFIFOL(fd,2); + + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); + memcpy(email, RFIFOP(fd,6), 40); + RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); + + // Check if e-mail is correct + if(strcmpi(email, sd->email) && //email does not matches and + ( + strcmp("a@a.com", sd->email) || //it is not default email, or + (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default + )) { //Fail + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; // 00 = Incorrect Email address + WFIFOSET(fd,3); + return 0; + } + + // check if this char exists + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + { // Such a character does not exist in the account + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + return 0; + } + + // remove char from list and compact it + for(ch = i; ch < MAX_CHARS-1; ch++) + sd->found_char[ch] = sd->found_char[ch+1]; + sd->found_char[MAX_CHARS-1] = -1; + + /* Delete character */ + if(char_delete_char_sql(cid)<0){ + //can't delete the char + //either SQL error or can't delete by some CONFIG conditions + //del fail + WFIFOHEAD(fd,3); + WFIFOW(fd, 0) = 0x70; + WFIFOB(fd, 2) = 0; + WFIFOSET(fd, 3); + return 0; + } + /* Char successfully deleted.*/ + WFIFOHEAD(fd,2); + WFIFOW(fd,0) = 0x6f; + WFIFOSET(fd,2); + } + return 1; +} + +// R 0187 .l +int chclif_parse_keepalive(int fd){ + if (RFIFOREST(fd) < 6) + return 0; + //int aid = RFIFOL(fd,2); + RFIFOSKIP(fd,6); + return 1; +} + +// R 08fc .l .24B +// R 028d .l .l .24B +int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd){ + if(cmd == 0x8fc) FIFOSD_CHECK(30) + if(cmd == 0x28d) FIFOSD_CHECK(34) + else return 0; + + { + int i, cid=0; + char name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1]; + safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH); + + if(cmd == 0x8fc){ + cid =RFIFOL(fd,2); + RFIFOSKIP(fd,30); + } + else if(cmd == 0x28d) { + int aid = RFIFOL(fd,2); + cid =RFIFOL(fd,6); + if( aid != sd->account_id ) + return 0; + RFIFOSKIP(fd,34); + } + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + return 0; + + normalize_name(name,TRIM_CHARS); + Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( !char_check_char_name(name,esc_name) ) + { + i = 1; + safestrncpy(sd->new_name, name, NAME_LENGTH); + } + else + i = 0; + + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x28e; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + } + return 1; +} + +// 0x28f .L +int chclif_parse_ackrename(int fd, struct char_session_data* sd){ + // 0: Successful + // 1: This character's name has already been changed. You cannot change a character's name more than once. + // 2: User information is not correct. + // 3: You have failed to change this character's name. + // 4: Another user is using this character name, so please select another one. + FIFOSD_CHECK(6) + + { + int i; + int cid = RFIFOL(fd,2); + RFIFOSKIP(fd,6); + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + return 0; + i = char_rename_char_sql(sd, cid); + + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x290; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + } + return 1; +} + +// R 07e5 .w .l +int chclif_parse_reqcaptcha(int fd){ + WFIFOHEAD(fd,5); + WFIFOW(fd,0) = 0x7e9; + WFIFOW(fd,2) = 5; + WFIFOB(fd,4) = 1; + WFIFOSET(fd,5); + RFIFOSKIP(fd,8); + return 1; +} + +// R 07e7 .w .l .b10 .b14 +int chclif_parse_chkcaptcha(int fd){ + WFIFOHEAD(fd,5); + WFIFOW(fd,0) = 0x7e9; + WFIFOW(fd,2) = 5; + WFIFOB(fd,4) = 1; + WFIFOSET(fd,5); + RFIFOSKIP(fd,32); + return 1; +} + +/** + * Entry point from client to char-serv + * function that check incoming command then split it to correct handler. + * @param fd: file descriptor to parse, (link to client) + */ +int chclif_parse(int fd) { + unsigned short cmd; + struct char_session_data* sd = (struct char_session_data*)session[fd]->session_data; + uint32 ipl = session[fd]->client_addr; + + // disconnect any player if no login-server. + if(login_fd < 0) + set_eof(fd); + + if(session[fd]->flag.eof) + { + if( sd != NULL && sd->auth ) + { // already authed client + DBMap *online_char_db = char_get_onlinedb(); + struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id); + if( data != NULL && data->fd == fd) + data->fd = -1; + if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex] + char_set_char_offline(-1,sd->account_id); + } + do_close(fd); + return 0; + } + + while( RFIFOREST(fd) >= 2 ) + { + cmd = RFIFOW(fd,0); + switch( cmd ) + { + + case 0x65: chclif_parse_reqtoconnect(fd,sd,ipl); break; + // char select + case 0x66: chclif_parse_charselect(fd,sd,ipl); break; + // createnewchar + case 0x970: chclif_parse_createnewchar(fd,sd,cmd); break; + case 0x67: chclif_parse_createnewchar(fd,sd,cmd); break; + // delete char + case 0x68: chclif_parse_delchar(fd,sd,cmd); break; // + case 0x1fb: chclif_parse_delchar(fd,sd,cmd); break; // 2004-04-19aSakexe+ langtype 12 char deletion packet + // client keep-alive packet (every 12 seconds) + case 0x187: chclif_parse_keepalive(fd); break; + // char rename + case 0x8fc: chclif_parse_reqrename(fd,sd,cmd); break; //request + case 0x28d: chclif_parse_reqrename(fd,sd,cmd); break; //request + case 0x28f: chclif_parse_ackrename(fd,sd); break; //Confirm change name. + // captcha + case 0x7e5: chclif_parse_reqcaptcha(fd); break; // captcha code request (not implemented) + case 0x7e7: chclif_parse_chkcaptcha(fd); break; // captcha code check (not implemented) + // deletion timer request + case 0x827: chclif_parse_char_delete2_req(fd, sd); break; + // deletion accept request + case 0x829: chclif_parse_char_delete2_accept(fd, sd); break; + // deletion cancel request + case 0x82b: chclif_parse_char_delete2_cancel(fd, sd); break; + // login as map-server + case 0x2af8: chclif_parse_maplogin(fd); return 0; // avoid processing of followup packets here + //pincode + case 0x8b8: chclif_parse_pincode_check( fd, sd ); break; // checks the entered pin + case 0x8c5: chclif_parse_reqpincode_window(fd,sd); break; // request for PIN window + case 0x8be: chclif_parse_pincode_change( fd, sd ); break; // pincode change request + case 0x8ba: chclif_parse_pincode_setnew( fd, sd ); break; // activate PIN system and set first PIN + // character movement request + case 0x8d4: chclif_parse_moveCharSlot(fd,sd); break; + case 0x9a1: chclif_parse_req_charlist(fd,sd); break; + // unknown packet received + default: + ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); + set_eof(fd); + return 0; + } + } + + RFIFOFLUSH(fd); + return 0; +} diff --git a/src/char/char_clif.h b/src/char/char_clif.h new file mode 100644 index 0000000000..76b37f2dca --- /dev/null +++ b/src/char/char_clif.h @@ -0,0 +1,65 @@ +/* + * File: char_clif.h + * Author: lighta + * + * Created on June 15, 2013, 12:06 PM + */ + +#ifndef CHAR_CLIF_H +#define CHAR_CLIF_H + +#include "char.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void chclif_moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ); +int chclif_parse_moveCharSlot( int fd, struct char_session_data* sd); +void chclif_pincode_sendstate( int fd, struct char_session_data* sd, enum pincode_state state ); +int chclif_parse_reqpincode_window(int fd, struct char_session_data* sd); +int chclif_parse_pincode_check( int fd, struct char_session_data* sd ); +int chclif_parse_pincode_change( int fd, struct char_session_data* sd ); +int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ); + +void chclif_charlist_notify( int fd, struct char_session_data* sd ); +void chclif_block_character( int fd, struct char_session_data* sd ); +int chclif_mmo_send006b(int fd, struct char_session_data* sd); +void chclif_mmo_send082d(int fd, struct char_session_data* sd); +void chclif_mmo_send099d(int fd, struct char_session_data *sd); +void chclif_mmo_char_send(int fd, struct char_session_data* sd); +void chclif_send_auth_result(int fd,char result); +void chclif_char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date); +void chclif_char_delete2_accept_ack(int fd, int char_id, uint32 result); +void chclif_char_delete2_cancel_ack(int fd, int char_id, uint32 result); + +int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd); +int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd); +int chclif_parse_char_delete2_cancel(int fd, struct char_session_data* sd); + +int chclif_parse_maplogin(int fd); +int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl); +int chclif_parse_req_charlist(int fd, struct char_session_data* sd); +int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl); +int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd); +int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd); +int chclif_parse_keepalive(int fd); +int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd); +int chclif_parse_ackrename(int fd, struct char_session_data* sd); +int chclif_parse_reqcaptcha(int fd); +int chclif_parse_chkcaptcha(int fd); + +int chclif_parse(int fd); + + + + + + + +#ifdef __cplusplus +} +#endif + +#endif /* CHAR_CLIF_H */ + diff --git a/src/char/char_cnslif.c b/src/char/char_cnslif.c new file mode 100644 index 0000000000..e374b98864 --- /dev/null +++ b/src/char/char_cnslif.c @@ -0,0 +1,77 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/socket.h" +#include "../common/showmsg.h" +#include "../common/timer.h" +#include "../common/ers.h" +#include "../common/cli.h" +#include "char.h" +#include "char_cnslif.h" + +#include +#include +#include + +/*====================================================== + * Login-Server help option info + *------------------------------------------------------*/ +void display_helpscreen(bool do_exit) +{ + ShowInfo("Usage: %s [options]\n", SERVER_NAME); + ShowInfo("\n"); + ShowInfo("Options:\n"); + ShowInfo(" -?, -h [--help]\t\tDisplays this help screen.\n"); + ShowInfo(" -v [--version]\t\tDisplays the server's version.\n"); + ShowInfo(" --run-once\t\t\tCloses server after loading (testing).\n"); + ShowInfo(" --char-config \t\tAlternative char-server configuration.\n"); + ShowInfo(" --lan-config \t\tAlternative lag configuration.\n"); + ShowInfo(" --inter-config \t\tAlternative inter-server configuration.\n"); + ShowInfo(" --msg-config \t\tAlternative message configuration.\n"); + if( do_exit ) + exit(EXIT_SUCCESS); +} + +// Console Command Parser [Wizputer] +int cnslif_parse(const char* buf) +{ + char type[64]; + char command[64]; + int n=0; + + if( ( n = sscanf(buf, "%63[^:]:%63[^\n]", type, command) ) < 2 ){ + if((n = sscanf(buf, "%63[^\n]", type))<1) return -1; //nothing to do no arg + } + if( n != 2 ){ //end string + ShowNotice("Type: '%s'\n",type); + command[0] = '\0'; + } + else + ShowNotice("Type of command: '%s' || Command: '%s'\n",type,command); + + if( n == 2 && strcmpi("server", type) == 0 ){ + if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){ + runflag = 0; + } + else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 ) + ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n"); + } + else if( strcmpi("ers_report", type) == 0 ){ + ers_report(); + } + else if( strcmpi("help", type) == 0 ){ + ShowInfo("Available commands:\n"); + ShowInfo("\t server:shutdown => Stops the server.\n"); + ShowInfo("\t server:alive => Checks if the server is running.\n"); + ShowInfo("\t ers_report => Displays database usage.\n"); + } + + return 0; +} + +void do_init_chcnslif(void){ + if( charserv_config.console ){ //start listening + add_timer_func_list(parse_console_timer, "parse_console_timer"); + add_timer_interval(gettick()+1000, parse_console_timer, 0, 0, 1000); //start in 1s each 1sec + } +} \ No newline at end of file diff --git a/src/char/char_cnslif.h b/src/char/char_cnslif.h new file mode 100644 index 0000000000..2eb58564a6 --- /dev/null +++ b/src/char/char_cnslif.h @@ -0,0 +1,25 @@ +/* + * File: char_cnslif.h + * Author: lighta + * + * Created on June 15, 2013, 12:07 PM + */ + +#ifndef CHAR_CNSLIF_H +#define CHAR_CNSLIF_H + +#ifdef __cplusplus +extern "C" { +#endif + +void display_helpscreen(bool do_exit); +int cnslif_parse(const char* buf); +void do_init_chcnslif(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* CHAR_CNSLIF_H */ + diff --git a/src/char/char_logif.c b/src/char/char_logif.c new file mode 100644 index 0000000000..0c9ac7d2e3 --- /dev/null +++ b/src/char/char_logif.c @@ -0,0 +1,653 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/showmsg.h" +#include "../common/sql.h" +#include "../common/utils.h" +#include "../common/strlib.h" +#include "inter.h" +#include "int_guild.h" +#include "char.h" +#include "char_clif.h" +#include "char_mapif.h" +#include "char_logif.h" + +#include +#include +#include + +//early declaration +void chlogif_on_ready(void); +void chlogif_on_disconnect(void); + + +int chlogif_pincode_notifyLoginPinError( int account_id ){ + if (login_fd > 0 && session[login_fd] && !session[login_fd]->flag.eof){ + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x2739; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); + return 1; + } + return 0; +} + +int chlogif_pincode_notifyLoginPinUpdate( int account_id, char* pin ){ + if (login_fd > 0 && session[login_fd] && !session[login_fd]->flag.eof){ + WFIFOHEAD(login_fd,11); + WFIFOW(login_fd,0) = 0x2738; + WFIFOL(login_fd,2) = account_id; + strncpy( (char*)WFIFOP(login_fd,6), pin, PINCODE_LENGTH+1 ); + WFIFOSET(login_fd,11); + return 1; + } + return 0; +} + +void chlogif_pincode_start(int fd, struct char_session_data* sd){ + if( charserv_config.pincode_config.pincode_enabled ){ + // PIN code system enabled + if( sd->pincode[0] == '\0' ){ + // No PIN code has been set yet + if( charserv_config.pincode_config.pincode_force ){ + chclif_pincode_sendstate( fd, sd, PINCODE_NEW ); + }else{ + chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + } + }else{ + if( !(charserv_config.pincode_config.pincode_changetime) + || ( sd->pincode_change + charserv_config.pincode_config.pincode_changetime ) > time(NULL) ){ + DBMap* online_char_db = char_get_onlinedb(); + struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id ); + + if( node != NULL && node->pincode_success ){ + // User has already passed the check + chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + }else{ + // Ask user for his PIN code + chclif_pincode_sendstate( fd, sd, PINCODE_ASK ); + } + }else{ + // User hasnt changed his PIN code too long + chclif_pincode_sendstate( fd, sd, PINCODE_EXPIRED ); + } + } + }else{ + // PIN code system disabled + chclif_pincode_sendstate( fd, sd, PINCODE_OK ); + } +} + +/** + * Load this character's account id into the 'online accounts' packet + * @see DBApply + */ +static int chlogif_send_acc_tologin_sub(DBKey key, DBData *data, va_list ap) { + struct online_char_data* character = db_data2ptr(data); + int* i = va_arg(ap, int*); + if(character->server > -1) { + WFIFOL(login_fd,8+(*i)*4) = character->account_id; + (*i)++; + return 1; + } + return 0; +} + +int chlogif_send_acc_tologin(int tid, unsigned int tick, int id, intptr_t data) { + if (login_fd > 0 && session[login_fd]){ + DBMap* online_char_db = char_get_onlinedb(); + // send account list to login server + int users = online_char_db->size(online_char_db); + int i = 0; + + WFIFOHEAD(login_fd,8+users*4); + WFIFOW(login_fd,0) = 0x272d; + online_char_db->foreach(online_char_db, chlogif_send_acc_tologin_sub, &i, users); + WFIFOW(login_fd,2) = 8+ i*4; + WFIFOL(login_fd,4) = i; + WFIFOSET(login_fd,WFIFOW(login_fd,2)); + return 1; + } + return 0; +} + +int chlogif_send_usercount(int users){ + if( login_fd > 0 && session[login_fd] ) + { + // send number of user to login server + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x2714; + WFIFOL(login_fd,2) = users; + WFIFOSET(login_fd,6); + return 1; + } + return 0; +} + +//Send packet forward to login-server for account saving +int chlogif_save_accreg2(unsigned char* buf, int len){ + if (login_fd > 0) { + WFIFOHEAD(login_fd,len+4); + memcpy(WFIFOP(login_fd,4), buf, len); + WFIFOW(login_fd,0) = 0x2728; + WFIFOW(login_fd,2) = len+4; + WFIFOSET(login_fd,len+4); + return 1; + } + return 0; +} + +int chlogif_request_accreg2(int account_id, int char_id){ + if (login_fd > 0) { + WFIFOHEAD(login_fd,10); + WFIFOW(login_fd,0) = 0x272e; + WFIFOL(login_fd,2) = account_id; + WFIFOL(login_fd,6) = char_id; + WFIFOSET(login_fd,10); + return 1; + } + return 0; +} + +int chlogif_send_reqaccdata(int fd, struct char_session_data *sd){ + //loginif_isconnected + if (login_fd > 0) { // request account data + // request account data + WFIFOHEAD(fd,6); + WFIFOW(fd,0) = 0x2716; + WFIFOL(fd,2) = sd->account_id; + WFIFOSET(fd,6); + return 1; + } + return 0; +} + +int chlogif_send_setacconline(int aid){ + //loginif_isconnected + if (login_fd > 0 && !session[login_fd]->flag.eof){ + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x272b; + WFIFOL(login_fd,2) = aid; + WFIFOSET(login_fd,6); + return 1; + } + return 0; +} + +void chlogif_send_setallaccoffline(int fd){ + WFIFOHEAD(fd,2); + WFIFOW(fd,0) = 0x2737; + WFIFOSET(fd,2); +} + +int chlogif_send_setaccoffline(int fd, int aid){ + if (loginif_isconnected()){ + WFIFOHEAD(fd,6); + WFIFOW(fd,0) = 0x272c; + WFIFOL(fd,2) = aid; + WFIFOSET(fd,6); + return 1; + } + return 0; +} + +int chlogif_parse_ackconnect(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 3) + return 0; + + if (RFIFOB(fd,2)) { + //printf("connect login server error : %d\n", RFIFOB(fd,2)); + 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 map_athena.conf and char_athena.conf\n"); + set_eof(fd); + return 0; + } else { + ShowStatus("Connected to login-server (connection #%d).\n", fd); + chlogif_on_ready(); + } + RFIFOSKIP(fd,3); + return 1; +} + +int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 25) + return 0; + { + int account_id = RFIFOL(fd,2); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); + uint8 sex = RFIFOB(fd,14); + uint8 result = RFIFOB(fd,15); + int request_id = RFIFOL(fd,16); + uint32 version = RFIFOL(fd,20); + uint8 clienttype = RFIFOB(fd,24); + RFIFOSKIP(fd,25); + + if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) && + !sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex ) + { + int client_fd = request_id; + sd->version = version; + sd->clienttype = clienttype; + if(sd->version != date2version(PACKETVER)) + ShowWarning("s aid=%d has an incorect version=%d in clientinfo. Server compiled for %d\n", + sd->account_id,sd->version,date2version(PACKETVER)); + + switch( result ) + { + case 0:// ok + char_auth_ok(client_fd, sd); + break; + case 1:// auth failed + WFIFOHEAD(client_fd,3); + WFIFOW(client_fd,0) = 0x6c; + WFIFOB(client_fd,2) = 0;// rejected from server + WFIFOSET(client_fd,3); + break; + } + } + } + return 1; +} + +int chlogif_parse_reqaccdata(int fd, struct char_session_data* sd){ + int u_fd; //user fd + if (RFIFOREST(fd) < 79) + return 0; + + // find the authenticated session with this account id + ARR_FIND( 0, fd_max, u_fd, session[u_fd] && (sd = (struct char_session_data*)session[u_fd]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) ); + if( u_fd < fd_max ) + { + int server_id; + memcpy(sd->email, RFIFOP(fd,6), 40); + sd->expiration_time = (time_t)RFIFOL(fd,46); + sd->group_id = RFIFOB(fd,50); + sd->char_slots = RFIFOB(fd,51); + if( sd->char_slots > MAX_CHARS ) { + ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots); + sd->char_slots = MAX_CHARS;/* cap to maximum */ + } else if ( !sd->char_slots )/* no value aka 0 in sql */ + sd->char_slots = MIN_CHARS;/* cap to minimum */ + safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate)); + safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode)); + sd->pincode_change = (time_t)RFIFOL(fd,68); + sd->bank_vault = RFIFOL(fd,72); + sd->isvip = RFIFOB(fd,76); + sd->chars_vip = RFIFOB(fd,77); + sd->chars_billing = RFIFOB(fd,78); + ARR_FIND( 0, ARRAYLENGTH(map_server), server_id, map_server[server_id].fd > 0 && map_server[server_id].map[0] ); + // continued from char_auth_ok... + if( server_id == ARRAYLENGTH(map_server) || //server not online, bugreport:2359 + (charserv_config.max_connect_user == 0 && sd->group_id != charserv_config.gm_allow_group) || + ( charserv_config.max_connect_user > 0 && char_count_users() >= charserv_config.max_connect_user && sd->group_id != charserv_config.gm_allow_group ) ) { + // refuse connection (over populated) + WFIFOHEAD(u_fd,3); + WFIFOW(u_fd,0) = 0x6c; + WFIFOW(u_fd,2) = 0; + WFIFOSET(u_fd,3); + } else { + // send characters to player + chclif_mmo_char_send(u_fd, sd); + if(sd->version >= date2version(20110309)){ + ShowInfo("Asking to start pincode\n"); + chlogif_pincode_start(u_fd,sd); + } + } + } + RFIFOSKIP(fd,79); + return 1; +} + +int chlogif_parse_keepalive(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 2) + return 0; + RFIFOSKIP(fd,2); + session[fd]->flag.ping = 0; + return 1; +} + +int chlogif_parse_ackchangesex(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 7) + return 0; + { + unsigned char buf[7]; + int i; + + int acc = RFIFOL(fd,2); + int sex = RFIFOB(fd,6); + RFIFOSKIP(fd,7); + + if( acc > 0 ) + {// TODO: Is this even possible? + int char_id[MAX_CHARS]; + int class_[MAX_CHARS]; + int guild_id[MAX_CHARS]; + int num; + char* data; + DBMap* auth_db = char_get_authdb(); + + struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc); + if( node != NULL ) + node->sex = sex; + + // get characters + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", schema_config.char_db, acc) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_CHARS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + Sql_GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data); + } + num = i; + for( i = 0; i < num; ++i ) + { + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || + class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || + class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER || + class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER || + class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T || + class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER || + class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) + { + // job modification + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) + class_[i] = (sex ? JOB_BARD : JOB_DANCER); + else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) + class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); + else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) + class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); + else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ) + class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER); + else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ) + class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T); + else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ) + class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); + else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) + class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); + } + + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", schema_config.char_db, class_[i], char_id[i]) ) + Sql_ShowDebug(sql_handle); + + if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] + inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); + } + Sql_FreeResult(sql_handle); + + // disconnect player if online on char-server + char_disconnect_player(acc); + } + + // notify all mapservers about this change + WBUFW(buf,0) = 0x2b0d; + WBUFL(buf,2) = acc; + WBUFB(buf,6) = sex; + chmapif_sendall(buf, 7); + } + return 1; +} + +int chlogif_parse_ackacc2req(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + + { //Receive account_reg2 registry, forward to map servers. + unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)]; + memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2)); + WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex] + chmapif_sendall(buf, WBUFW(buf,2)); + RFIFOSKIP(fd, RFIFOW(fd,2)); + } + return 1; +} + +int chlogif_parse_accbannotification(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 11) + return 0; + + { // send to all map-servers to disconnect the player + unsigned char buf[11]; + WBUFW(buf,0) = 0x2b14; + WBUFL(buf,2) = RFIFOL(fd,2); + WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban + WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment + chmapif_sendall(buf, 11); + } + // disconnect player if online on char-server + char_disconnect_player(RFIFOL(fd,2)); + RFIFOSKIP(fd,11); + return 1; +} + +int chlogif_parse_askkick(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 6) + return 0; + { + DBMap* online_char_db = char_get_onlinedb(); + DBMap* auth_db = char_get_authdb(); + int aid = RFIFOL(fd,2); + struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid); + RFIFOSKIP(fd,6); + if( character != NULL ) + {// account is already marked as online! + if( character->server > -1 ) + { //Kick it from the map server it is on. + mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); + if (character->waiting_disconnect == INVALID_TIMER) + character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, char_chardb_waiting_disconnect, character->account_id, 0); + } + else + {// Manual kick from char server. + struct char_session_data *tsd; + int i; + ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid ); + if( i < fd_max ) + { + chclif_send_auth_result(i,2); //Send "Someone has already logged in with this id" + set_eof(i); + } + else // still moving to the map-server + char_set_char_offline(-1, aid); + } + } + idb_remove(auth_db, aid);// reject auth attempts from map-server + } + return 1; +} + +int chlogif_parse_updip(int fd, struct char_session_data* sd){ + if (RFIFOREST(fd) < 2) + return 0; + { + unsigned char buf[2]; + uint32 new_ip = 0; + + WBUFW(buf,0) = 0x2b1e; + chmapif_sendall(buf, 2); + + new_ip = host2ip(charserv_config.login_ip_str); + if (new_ip && new_ip != charserv_config.login_ip) + charserv_config.login_ip = new_ip; //Update login ip, too. + + new_ip = host2ip(charserv_config.char_ip_str); + if (new_ip && new_ip != charserv_config.char_ip) + { //Update ip. + charserv_config.char_ip = new_ip; + ShowInfo("Updating IP for [%s].\n", charserv_config.char_ip_str); + // notify login server about the change + WFIFOHEAD(fd,6); + WFIFOW(fd,0) = 0x2736; + WFIFOL(fd,2) = htonl(charserv_config.char_ip); + WFIFOSET(fd,6); + } + + RFIFOSKIP(fd,2); + } + return 1; +} + +int chlogif_parse(int fd) { + struct char_session_data* sd = NULL; + + // only process data from the login-server + if( fd != login_fd ) { + ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd); + do_close(fd); + return 0; + } + + if( session[fd]->flag.eof ) { + do_close(fd); + login_fd = -1; + chlogif_on_disconnect(); + return 0; + } else if ( session[fd]->flag.ping ) {/* we've reached stall time */ + if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */ + set_eof(fd); + return 0; + } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */ + WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718) + WFIFOW(fd,0) = 0x2719; + WFIFOSET(fd,2); + + session[fd]->flag.ping = 2; + } + } + + sd = (struct char_session_data*)session[fd]->session_data; + + while(RFIFOREST(fd) >= 2) { + uint16 command = RFIFOW(fd,0); + + switch( command ) + { + case 0x2741: loginif_parse_BankingAck(fd); break; + case 0x2743: loginif_parse_vipack(fd); break; + + // acknowledgement of connect-to-loginserver request + case 0x2711: chlogif_parse_ackconnect(fd,sd); break; + // acknowledgement of account authentication request + case 0x2713: chlogif_parse_ackaccreq(fd, sd); break; + // account data + case 0x2717: chlogif_parse_reqaccdata(fd, sd); break; + // login-server alive packet + case 0x2718: chlogif_parse_keepalive(fd, sd); break; + // changesex reply + case 0x2723: chlogif_parse_ackchangesex(fd, sd); break; + // reply to an account_reg2 registry request + case 0x2729: chlogif_parse_ackacc2req(fd, sd); break; + // State change of account/ban notification (from login-server) + case 0x2731: chlogif_parse_accbannotification(fd, sd); break; + // Login server request to kick a character out. [Skotlex] + case 0x2734: chlogif_parse_askkick(fd,sd); break; + // ip address update signal from login server + case 0x2735: chlogif_parse_updip(fd,sd); break; + default: + ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command); + set_eof(fd); + return 0; + } + } + + RFIFOFLUSH(fd); + return 0; +} + +int chlogif_check_connect_logserver(int tid, unsigned int tick, int id, intptr_t data) { + if (login_fd > 0 && session[login_fd] != NULL) + return 0; + + ShowInfo("Attempt to connect to login-server...\n"); + login_fd = make_connection(charserv_config.login_ip, charserv_config.login_port, false,10); + if (login_fd == -1) + { //Try again later. [Skotlex] + login_fd = 0; + return 0; + } + session[login_fd]->func_parse = chlogif_parse; + session[login_fd]->flag.server = 1; + realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + + WFIFOHEAD(login_fd,86); + WFIFOW(login_fd,0) = 0x2710; + memcpy(WFIFOP(login_fd,2), charserv_config.userid, 24); + memcpy(WFIFOP(login_fd,26), charserv_config.passwd, 24); + WFIFOL(login_fd,50) = 0; + WFIFOL(login_fd,54) = htonl(charserv_config.char_ip); + WFIFOW(login_fd,58) = htons(charserv_config.char_port); + memcpy(WFIFOP(login_fd,60), charserv_config.server_name, 20); + WFIFOW(login_fd,80) = 0; + WFIFOW(login_fd,82) = charserv_config.char_maintenance; + WFIFOW(login_fd,84) = charserv_config.char_new_display; //only display (New) if they want to [Kevin] + WFIFOSET(login_fd,86); + + return 1; +} + + + +void do_init_chlogif(void) { + // establish char-login connection if not present + add_timer_func_list(chlogif_check_connect_logserver, "check_connect_login_server"); + add_timer_interval(gettick() + 1000, chlogif_check_connect_logserver, 0, 0, 10 * 1000); + + // send a list of all online account IDs to login server + add_timer_func_list(chlogif_send_acc_tologin, "send_accounts_tologin"); + add_timer_interval(gettick() + 1000, chlogif_send_acc_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour +} + +/// Resets all the data. +void chlogif_reset(void){ + int id; + // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS] + for( id = 0; id < ARRAYLENGTH(map_server); ++id ) + chmapif_server_reset(id); + flush_fifos(); + exit(EXIT_FAILURE); +} + +/// Checks the conditions for the server to stop. +/// Releases the cookie when all characters are saved. +/// If all the conditions are met, it stops the core loop. +void chlogif_check_shutdown(void) +{ + if( runflag != CHARSERVER_ST_SHUTDOWN ) + return; + runflag = CORE_ST_STOP; +} + +/// Called when the connection to Login Server is disconnected. +void chlogif_on_disconnect(void){ + ShowWarning("Connection to Login Server lost.\n\n"); +} + +/// Called when all the connection steps are completed. +void chlogif_on_ready(void) +{ + int i; + + chlogif_check_shutdown(); + + //Send online accounts to login server. + chlogif_send_acc_tologin(INVALID_TIMER, gettick(), 0, 0); + + // if no map-server already connected, display a message... + ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd > 0 && map_server[i].map[0] ); + if( i == ARRAYLENGTH(map_server) ) + ShowStatus("Awaiting maps from map-server.\n"); +} + +void do_final_chlogif(void) +{ + if( login_fd != -1 ) + { + do_close(login_fd); + login_fd = -1; + } +} \ No newline at end of file diff --git a/src/char/char_logif.h b/src/char/char_logif.h new file mode 100644 index 0000000000..47b6d7e84e --- /dev/null +++ b/src/char/char_logif.h @@ -0,0 +1,52 @@ +/* + * File: char_logif.h + * Author: lighta + * + * Created on June 15, 2013, 12:05 PM + */ + +#ifndef CHAR_LOGIF_H +#define CHAR_LOGIF_H + +#include "char.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int chlogif_pincode_notifyLoginPinError( int account_id ); +int chlogif_pincode_notifyLoginPinUpdate( int account_id, char* pin ); +void chlogif_pincode_start(int fd, struct char_session_data* sd); +int chlogif_send_acc_tologin(int tid, unsigned int tick, int id, intptr_t data); +int chlogif_send_usercount(int users); +int chlogif_save_accreg2(unsigned char* buf, int len); +int chlogif_request_accreg2(int account_id, int char_id); +int chlogif_send_reqaccdata(int fd, struct char_session_data *sd); +int chlogif_send_setacconline(int aid); +void chlogif_send_setallaccoffline(int fd); +int chlogif_send_setaccoffline(int fd, int aid); +int chlogif_parse_ackconnect(int fd, struct char_session_data* sd); +int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd); +int chlogif_parse_reqaccdata(int fd, struct char_session_data* sd); +int chlogif_parse_keepalive(int fd, struct char_session_data* sd); +int chlogif_parse_ackchangesex(int fd, struct char_session_data* sd); +int chlogif_parse_ackacc2req(int fd, struct char_session_data* sd); +int chlogif_parse_accbannotification(int fd, struct char_session_data* sd); +int chlogif_parse_askkick(int fd, struct char_session_data* sd); +int chlogif_parse_updip(int fd, struct char_session_data* sd); + +int chlogif_parse(int fd); +int chlogif_check_connect_logserver(int tid, unsigned int tick, int id, intptr_t data); +void do_init_chlogif(void); +void chlogif_reset(void); +void chlogif_check_shutdown(void); +void chlogif_on_disconnect(void); +void chlogif_on_ready(void); +void do_final_chlogif(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CHAR_LOGIF_H */ + diff --git a/src/char/char_mapif.c b/src/char/char_mapif.c new file mode 100644 index 0000000000..dc07031b6c --- /dev/null +++ b/src/char/char_mapif.c @@ -0,0 +1,1278 @@ +/** + * @file char_mapif.c + * Module purpose is to handle incoming and outgoing requests with map-server. + * Licensed under GNU GPL. + * For more information, see LICENCE in the main folder. + * @author Athena Dev Teams originally in login.c + * @author rAthena Dev Team + */ + +#include "../common/socket.h" +#include "../common/sql.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "inter.h" +#include "char.h" +#include "char_mapif.h" + +#include +#include +#include + +/** + * Packet send to all map-servers, attach to ourself + * @param buf: packet to send in form of an array buffer + * @param len: size of packet + * @return : the number of map-serv the packet was sent to + */ +int chmapif_sendall(unsigned char *buf, unsigned int len){ + int i, c; + + c = 0; + for(i = 0; i < ARRAYLENGTH(map_server); i++) { + int fd; + if ((fd = map_server[i].fd) > 0) { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + c++; + } + } + + return c; +} + +/** + * Packet send to all map-servers, except one. (wos: without our self) attach to ourself + * @param sfd: fd to discard sending to + * @param buf: packet to send in form of an array buffer + * @param len: size of packet + * @return : the number of map-serv the packet was sent to + */ +int chmapif_sendallwos(int sfd, unsigned char *buf, unsigned int len){ + int i, c; + + c = 0; + for(i = 0; i < ARRAYLENGTH(map_server); i++) { + int fd; + if ((fd = map_server[i].fd) > 0 && fd != sfd) { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + c++; + } + } + + return c; +} + +/** + * Packet send to all char-servers, except one. (wos: without our self) + * @param fd: fd to send packet too + * @param buf: packet to send in form of an array buffer + * @param len: size of packet + * @return : the number of map-serv the packet was sent to (O|1) + */ +int chmapif_send(int fd, unsigned char *buf, unsigned int len){ + if (fd >= 0) { + int i; + ARR_FIND( 0, ARRAYLENGTH(map_server), i, fd == map_server[i].fd ); + if( i < ARRAYLENGTH(map_server) ) + { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + return 1; + } + } + return 0; +} + + + +/** + * Send map-servers fames ranking lists + * Defaut fame list are 32B, (id+point+names) + * S .W .W .W ?B ?B ?B + * @param fd: fd to send packet too (map-serv) if -1 send to all + * @return : 0 success + */ +int chmapif_send_fame_list(int fd){ + int i, len = 8; + unsigned char buf[32000]; + + WBUFW(buf,0) = 0x2b1b; + + for(i = 0; i < fame_list_size_smith && smith_fame_list[i].id; i++) { + memcpy(WBUFP(buf, len), &smith_fame_list[i], sizeof(struct fame_list)); + len += sizeof(struct fame_list); + } + // add blacksmith's block length + WBUFW(buf, 6) = len; + + for(i = 0; i < fame_list_size_chemist && chemist_fame_list[i].id; i++) { + memcpy(WBUFP(buf, len), &chemist_fame_list[i], sizeof(struct fame_list)); + len += sizeof(struct fame_list); + } + // add alchemist's block length + WBUFW(buf, 4) = len; + + for(i = 0; i < fame_list_size_taekwon && taekwon_fame_list[i].id; i++) { + memcpy(WBUFP(buf, len), &taekwon_fame_list[i], sizeof(struct fame_list)); + len += sizeof(struct fame_list); + } + // add total packet length + WBUFW(buf, 2) = len; + + if (fd != -1) + chmapif_send(fd, buf, len); + else + chmapif_sendall(buf, len); + + return 0; +} + +/** + * Send to map-servers the updated fame ranking lists + * We actually just send this one when we only need to update rankpoint but pos didn't change + * @param type: ranking type + * @param index: position in the ranking + * @param fame: number of points + */ +void chmapif_update_fame_list(int type, int index, int fame) { + unsigned char buf[8]; + WBUFW(buf,0) = 0x2b22; + WBUFB(buf,2) = type; + WBUFB(buf,3) = index; + WBUFL(buf,4) = fame; + chmapif_sendall(buf, 8); +} + +/** + * Send to map-servers the users count on this char-serv, (meaning the total of all mapserv) + * @param users: number of players on this char-serv + */ +void chmapif_sendall_playercount(int users){ + uint8 buf[6]; + // send number of players to all map-servers + WBUFW(buf,0) = 0x2b00; + WBUFL(buf,2) = users; + chmapif_sendall(buf,6); +} + +/** + * This function is called when the map-serv initialise is chrif interface. + * Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary + * We reply by sending back the char_serv_wisp_name fame list and + * @param fd: wich fd to parse from + * @param id: wich map_serv id + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_getmapname(int fd, int id){ + int j = 0, i = 0; + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + + //Retain what map-index that map-serv contains + memset(map_server[id].map, 0, sizeof(map_server[id].map)); + for(i = 4; i < RFIFOW(fd,2); i += 4) { + map_server[id].map[j] = RFIFOW(fd,i); + j++; + } + + ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", + id, j, CONVIP(map_server[id].ip), map_server[id].port); + ShowStatus("Map-server %d loading complete.\n", id); + + // send name for wisp to player + WFIFOHEAD(fd, 3 + NAME_LENGTH); + WFIFOW(fd,0) = 0x2afb; + WFIFOB(fd,2) = 0; //0 succes, 1:failure + memcpy(WFIFOP(fd,3), charserv_config.wisp_server_name, NAME_LENGTH); + WFIFOSET(fd,3+NAME_LENGTH); + + chmapif_send_fame_list(fd); //Send fame list. + + { + unsigned char buf[16384]; + int x; + if (j == 0) { + ShowWarning("Map-server %d has NO maps.\n", id); + } else { + // Transmitting maps information to the other map-servers + WBUFW(buf,0) = 0x2b04; + WBUFW(buf,2) = j * 4 + 10; + WBUFL(buf,4) = htonl(map_server[id].ip); + WBUFW(buf,8) = htons(map_server[id].port); + memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4); + chmapif_sendallwos(fd, buf, WBUFW(buf,2)); + } + // Transmitting the maps of the other map-servers to the new map-server + for(x = 0; x < ARRAYLENGTH(map_server); x++) { + if (map_server[x].fd > 0 && x != id) { + WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map)); + WFIFOW(fd,0) = 0x2b04; + WFIFOL(fd,4) = htonl(map_server[x].ip); + WFIFOW(fd,8) = htons(map_server[x].port); + j = 0; + for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++) + if (map_server[x].map[i]) + WFIFOW(fd,10+(j++)*4) = map_server[x].map[i]; + if (j > 0) { + WFIFOW(fd,2) = j * 4 + 10; + WFIFOSET(fd,WFIFOW(fd,2)); + } + } + } + } + RFIFOSKIP(fd,RFIFOW(fd,2)); + return 1; +} + +/** + * Map-serv requesting to send the list of sc_data the player has saved + * @author [Skotlex] + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_askscdata(int fd){ + if (RFIFOREST(fd) < 10) + return 0; + { +#ifdef ENABLE_SC_SAVING + int aid, cid; + aid = RFIFOL(fd,2); + cid = RFIFOL(fd,6); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", + schema_config.scdata_db, aid, cid) ) + { + Sql_ShowDebug(sql_handle); + return 0; + } + if( Sql_NumRows(sql_handle) > 0 ) + { + struct status_change_data scdata; + int count; + char* data; + + WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); + WFIFOW(fd,0) = 0x2b1d; + WFIFOL(fd,4) = aid; + WFIFOL(fd,8) = cid; + for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) + { + Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); + memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); + } + if (count >= 50) + ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); + if (count > 0) + { + WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); + WFIFOW(fd,12) = count; + WFIFOSET(fd,WFIFOW(fd,2)); + + //Clear the data once loaded. + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, aid, cid) ) + Sql_ShowDebug(sql_handle); + } + } + Sql_FreeResult(sql_handle); +#endif + RFIFOSKIP(fd, 10); + } + return 1; +} + +/** + * Map-serv sent us his new users count, updating info + * @param fd: wich fd to parse from + * @param id: wich map_serv id + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_getusercount(int fd, int id){ + if (RFIFOREST(fd) < 4) + return 0; + if (RFIFOW(fd,2) != map_server[id].users) { + map_server[id].users = RFIFOW(fd,2); + ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id); + } + RFIFOSKIP(fd, 4); + return 1; +} + +/** + * Map-serv sent us all his users info, (aid and cid) so we can update online_char_db + * @param fd: wich fd to parse from + * @param id: wich map_serv id + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_regmapuser(int fd, int id){ + int i; + if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { + //TODO: When data mismatches memory, update guild/party online/offline states. + int aid, cid; + struct online_char_data* character; + DBMap* online_char_db = char_get_onlinedb(); + + map_server[id].users = RFIFOW(fd,4); + online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown' + for(i = 0; i < map_server[id].users; i++) { + aid = RFIFOL(fd,6+i*8); + cid = RFIFOL(fd,6+i*8+4); + character = idb_ensure(online_char_db, aid, char_create_online_data); + if( character->server > -1 && character->server != id ) + { + ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", + character->account_id, character->char_id, character->server, id, aid, cid); + mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); + } + character->server = id; + character->char_id = cid; + } + //If any chars remain in -2, they will be cleaned in the cleanup timer. + RFIFOSKIP(fd,RFIFOW(fd,2)); + } + return 1; +} + +/** + * Map-serv request to save mmo_char_status in sql + * Receive character data from map-server for saving + * @param fd: wich fd to parse from + * @param id: wich map_serv id + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_reqsavechar(int fd, int id){ + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { + int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2); + struct online_char_data* character; + DBMap* online_char_db = char_get_onlinedb(); + + if (size - 13 != sizeof(struct mmo_charstatus)) + { + ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus)); + RFIFOSKIP(fd,size); + return 0; + } + //Check account only if this ain't final save. Final-save goes through because of the char-map reconnect + if (RFIFOB(fd,12) || RFIFOB(fd,13) || ( + (character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL && + character->char_id == cid)) + { + struct mmo_charstatus char_dat; + memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus)); + char_mmo_char_tosql(cid, &char_dat); + } else { //This may be valid on char-server reconnection, when re-sending characters that already logged off. + ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid); + char_set_char_online(id, cid, aid); + } + + if (RFIFOB(fd,12)) + { //Flag, set character offline after saving. [Skotlex] + char_set_char_offline(cid, aid); + WFIFOHEAD(fd,10); + WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save. + WFIFOL(fd,2) = aid; + WFIFOL(fd,6) = cid; + WFIFOSET(fd,10); + } + RFIFOSKIP(fd,size); + } + return 1; +} + +/** + * Player Requesting char-select from map_serv + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_authok(int fd){ + if( RFIFOREST(fd) < 19 ) + return 0; + else{ + int account_id = RFIFOL(fd,2); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); + uint32 ip = RFIFOL(fd,14); + int version = RFIFOB(fd,18); + RFIFOSKIP(fd,19); + + if( runflag != CHARSERVER_ST_RUNNING ){ + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 0;// not ok + WFIFOSET(fd,7); + }else{ + struct auth_node* node; + DBMap* auth_db = char_get_authdb(); + DBMap* online_char_db = char_get_onlinedb(); + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = account_id; + node->char_id = 0; + node->login_id1 = login_id1; + node->login_id2 = login_id2; + //node->sex = 0; + node->ip = ntohl(ip); + //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) + //node->gmlevel = 0; + idb_put(auth_db, account_id, node); + + //Set char to "@ char select" in online db [Kevin] + char_set_charselect(account_id); + { + struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id); + if( character != NULL ){ + character->pincode_success = true; + character->version = version; + } + } + + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 1;// ok + WFIFOSET(fd,7); + } + } + return 1; +} + +//Request to save skill cooldown data +int chmapif_parse_req_saveskillcooldown(int fd){ + if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) + return 0; + else { + int count, aid, cid; + aid = RFIFOL(fd,4); + cid = RFIFOL(fd,8); + count = RFIFOW(fd,12); + if( count > 0 ) + { + struct skill_cooldown_data data; + StringBuf buf; + int i; + + StringBuf_Init(&buf); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", schema_config.skillcooldown_db); + for( i = 0; i < count; ++i ) + { + memcpy(&data,RFIFOP(fd,14+i*sizeof(struct skill_cooldown_data)),sizeof(struct skill_cooldown_data)); + if( i > 0 ) + StringBuf_AppendStr(&buf, ", "); + StringBuf_Printf(&buf, "('%d','%d','%d','%d')", aid, cid, data.skill_id, data.tick); + } + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + StringBuf_Destroy(&buf); + } + RFIFOSKIP(fd, RFIFOW(fd, 2)); + } + return 1; +} + +//Request skillcooldown data 0x2b0a +int chmapif_parse_req_skillcooldown(int fd){ + if (RFIFOREST(fd) < 10) + return 0; + else { + int aid, cid; + aid = RFIFOL(fd,2); + cid = RFIFOL(fd,6); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT skill, tick FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", + schema_config.skillcooldown_db, aid, cid) ) + { + Sql_ShowDebug(sql_handle); + return 0; + } + if( Sql_NumRows(sql_handle) > 0 ) + { + int count; + char* data; + struct skill_cooldown_data scd; + + WFIFOHEAD(fd,14 + MAX_SKILLCOOLDOWN * sizeof(struct skill_cooldown_data)); + WFIFOW(fd,0) = 0x2b0b; + WFIFOL(fd,4) = aid; + WFIFOL(fd,8) = cid; + for( count = 0; count < MAX_SKILLCOOLDOWN && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) + { + Sql_GetData(sql_handle, 0, &data, NULL); scd.skill_id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); scd.tick = atoi(data); + memcpy(WFIFOP(fd,14+count*sizeof(struct skill_cooldown_data)), &scd, sizeof(struct skill_cooldown_data)); + } + if( count >= MAX_SKILLCOOLDOWN ) + ShowWarning("Too many skillcooldowns for %d:%d, some of them were not loaded.\n", aid, cid); + if( count > 0 ) + { + WFIFOW(fd,2) = 14 + count * sizeof(struct skill_cooldown_data); + WFIFOW(fd,12) = count; + WFIFOSET(fd,WFIFOW(fd,2)); + //Clear the data once loaded. + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.skillcooldown_db, aid, cid) ) + Sql_ShowDebug(sql_handle); + } + } + Sql_FreeResult(sql_handle); + RFIFOSKIP(fd, 10); + } + return 1; +} + +/** + * Player requesting to change map-serv + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_reqchangemapserv(int fd){ + if (RFIFOREST(fd) < 39) + return 0; + { + int map_id, map_fd = -1; + struct mmo_charstatus* char_data; + struct mmo_charstatus char_dat; + DBMap* char_db_ = char_get_chardb(); + + map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. + if (map_id >= 0) + map_fd = map_server[map_id].fd; + //Char should just had been saved before this packet, so this should be safe. [Skotlex] + char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); + if (char_data == NULL) { //Really shouldn't happen. + char_mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); + char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); + } + + if( runflag == CHARSERVER_ST_RUNNING && + session_isActive(map_fd) && + char_data ) + { //Send the map server the auth of this player. + struct online_char_data* data; + struct auth_node* node; + DBMap* auth_db = char_get_authdb(); + DBMap* online_char_db = char_get_onlinedb(); + + int aid = RFIFOL(fd,2); + + //Update the "last map" as this is where the player must be spawned on the new map server. + char_data->last_point.map = RFIFOW(fd,18); + char_data->last_point.x = RFIFOW(fd,20); + char_data->last_point.y = RFIFOW(fd,22); + char_data->sex = RFIFOB(fd,30); + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = aid; + node->char_id = RFIFOL(fd,14); + node->login_id1 = RFIFOL(fd,6); + node->login_id2 = RFIFOL(fd,10); + node->sex = RFIFOB(fd,30); + node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing) + node->ip = ntohl(RFIFOL(fd,31)); + node->group_id = RFIFOL(fd,35); + node->changing_mapservers = 1; + idb_put(auth_db, aid, node); + + data = idb_ensure(online_char_db, aid, char_create_online_data); + data->char_id = char_data->char_id; + data->server = map_id; //Update server where char is. + + //Reply with an ack. + WFIFOHEAD(fd,30); + WFIFOW(fd,0) = 0x2b06; + memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); + WFIFOSET(fd,30); + } else { //Reply with nak + WFIFOHEAD(fd,30); + WFIFOW(fd,0) = 0x2b06; + memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); + WFIFOL(fd,6) = 0; //Set login1 to 0. + WFIFOSET(fd,30); + } + RFIFOSKIP(fd,39); + } + return 1; +} + +/** + * Player requesting to remove friend from list + * Remove RFIFOL(fd,6) (friend_id) from RFIFOL(fd,2) (char_id) friend list + * @author [Ind] + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_askrmfriend(int fd){ + if (RFIFOREST(fd) < 10) + return 0; + { + int char_id, friend_id; + char_id = RFIFOL(fd,2); + friend_id = RFIFOL(fd,6); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1", + schema_config.friend_db, char_id, friend_id) ) { + Sql_ShowDebug(sql_handle); + return 0; + } + RFIFOSKIP(fd,10); + } + return 1; +} + +/** + * Lookup to search if that char_id correspond to a name. + * Comming from map-serv to search on other map-serv + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_reqcharname(int fd){ + if (RFIFOREST(fd) < 6) + return 0; + + WFIFOHEAD(fd,30); + WFIFOW(fd,0) = 0x2b09; + WFIFOL(fd,2) = RFIFOL(fd,2); + char_loadName((int)RFIFOL(fd,2), (char*)WFIFOP(fd,6)); + WFIFOSET(fd,30); + + RFIFOSKIP(fd,6); + return 1; +} + +/** + * Forward an email update request to login-serv + * Map server send information to change an email of an account -> login-server + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_reqnewemail(int fd){ + if (RFIFOREST(fd) < 86) + return 0; + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,86); + memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 .L .40B .40B + WFIFOW(login_fd,0) = 0x2722; + WFIFOSET(login_fd,86); + } + RFIFOSKIP(fd, 86); + return 1; +} + +/** + * Forward a change of status for account to login-serv + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_fwlog_changestatus(int fd){ + if (RFIFOREST(fd) < 44) + return 0; + { + int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + char esc_name[NAME_LENGTH*2+1]; + + int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request) + const char* name = (char*)RFIFOP(fd,6); // name of the target character + int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban + short year = RFIFOW(fd,32); + short month = RFIFOW(fd,34); + short day = RFIFOW(fd,36); + short hour = RFIFOW(fd,38); + short minute = RFIFOW(fd,40); + short second = RFIFOW(fd,42); + RFIFOSKIP(fd,44); + + Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, esc_name) ) + Sql_ShowDebug(sql_handle); + else + if( Sql_NumRows(sql_handle) == 0 ) + { + result = 1; // 1-player not found + } + else + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + Sql_ShowDebug(sql_handle); + //FIXME: set proper result value? + else + { + char name[NAME_LENGTH]; + int account_id; + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); + + if( login_fd <= 0 ) + result = 3; // 3-login-server offline + //FIXME: need to move this check to login server [ultramage] +// else +// if( acc != -1 && isGM(acc) < isGM(account_id) ) +// result = 2; // 2-gm level too low + else + switch( type ) { + case 1: // block + WFIFOHEAD(login_fd,10); + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = account_id; + WFIFOL(login_fd,6) = 5; // new account status + WFIFOSET(login_fd,10); + break; + case 2: // ban + WFIFOHEAD(login_fd,18); + WFIFOW(login_fd, 0) = 0x2725; + WFIFOL(login_fd, 2) = account_id; + WFIFOW(login_fd, 6) = year; + WFIFOW(login_fd, 8) = month; + WFIFOW(login_fd,10) = day; + WFIFOW(login_fd,12) = hour; + WFIFOW(login_fd,14) = minute; + WFIFOW(login_fd,16) = second; + WFIFOSET(login_fd,18); + break; + case 3: // unblock + WFIFOHEAD(login_fd,10); + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = account_id; + WFIFOL(login_fd,6) = 0; // new account status + WFIFOSET(login_fd,10); + break; + case 4: // unban + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x272a; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); + break; + case 5: // changesex + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x2727; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); + break; + } + } + + Sql_FreeResult(sql_handle); + + // send answer if a player ask, not if the server ask + if( acc != -1 && type != 5) { // Don't send answer for changesex + WFIFOHEAD(fd,34); + WFIFOW(fd, 0) = 0x2b0f; + WFIFOL(fd, 2) = acc; + safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); + WFIFOW(fd,30) = type; + WFIFOW(fd,32) = result; + WFIFOSET(fd,34); + } + } + return 1; +} + +/** + * Received an update of fame point for char_id cid + * Update the list associated and transmit the new ranking + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_updfamelist(int fd){ + if (RFIFOREST(fd) < 11) + return 0; + { + int cid = RFIFOL(fd, 2); + int fame = RFIFOL(fd, 6); + char type = RFIFOB(fd, 10); + int size; + struct fame_list* list; + int player_pos; + int fame_pos; + + switch(type) + { + case 1: size = fame_list_size_smith; list = smith_fame_list; break; + case 2: size = fame_list_size_chemist; list = chemist_fame_list; break; + case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; + default: size = 0; list = NULL; break; + } + + ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player + ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be + + if( player_pos == size && fame_pos == size ) + ;// not on list and not enough fame to get on it + else if( fame_pos == player_pos ) + {// same position + list[player_pos].fame = fame; + chmapif_update_fame_list(type, player_pos, fame); + } + else + {// move in the list + if( player_pos == size ) + {// new ranker - not in the list + ARR_MOVE(size - 1, fame_pos, list, struct fame_list); + list[fame_pos].id = cid; + list[fame_pos].fame = fame; + char_loadName(cid, list[fame_pos].name); + } + else + {// already in the list + if( fame_pos == size ) + --fame_pos;// move to the end of the list + ARR_MOVE(player_pos, fame_pos, list, struct fame_list); + list[fame_pos].fame = fame; + } + chmapif_send_fame_list(-1); + } + + RFIFOSKIP(fd,11); + } + return 1; +} + +/** + * Transmit the acknolegement of divorce of partner_id1 and partner_id2 + * Update the list associated and transmit the new ranking + * @param partner_id1: char id1 divorced + * @param partner_id2: char id2 divorced + */ +void chmapif_send_ackdivorce(int partner_id1, int partner_id2){ + unsigned char buf[11]; + WBUFW(buf,0) = 0x2b12; + WBUFL(buf,2) = partner_id1; + WBUFL(buf,6) = partner_id2; + chmapif_sendall(buf,10); +} + +/** + * Received a divorce request + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_reqdivorce(int fd){ + if( RFIFOREST(fd) < 10 ) + return 0; + char_divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + return 1; +} + +/** + * Receive rates of this map index + * @author [Wizputer] + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_updmapinfo(int fd){ + if( RFIFOREST(fd) < 14 ) + return 0; + { + char esc_server_name[sizeof(charserv_config.server_name)*2+1]; + Sql_EscapeString(sql_handle, esc_server_name, charserv_config.server_name); + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d'", + schema_config.ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) ) + Sql_ShowDebug(sql_handle); + RFIFOSKIP(fd,14); + } + return 1; +} + +/** + * Character disconnected set online 0 + * @author [Wizputer] + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_setcharoffline(int fd){ + if (RFIFOREST(fd) < 6) + return 0; + char_set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + return 1; +} + + +/** + * Reset all chars to offline + * @author [Wizputer] + * @param fd: wich fd to parse from + * @param id: wich map_serv id + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_setalloffline(int fd, int id){ + char_set_all_offline(id); + RFIFOSKIP(fd,2); + return 1; +} + +/** + * Character set online + * @author [Wizputer] + * @param fd: wich fd to parse from + * @param id: wich map_serv id + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_setcharonline(int fd, int id){ + if (RFIFOREST(fd) < 10) + return 0; + char_set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + return 1; +} + +/** + * Build and send fame ranking lists + * @author [DracoRPG] + * @param fd: wich fd to parse from + * @param id: wich map_serv id + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_reqfamelist(int fd){ + if (RFIFOREST(fd) < 2) + return 0; + char_read_fame_list(); + chmapif_send_fame_list(-1); + RFIFOSKIP(fd,2); + return 1; +} + +/** + * Request to save status change data.s + * @author [Skotlex] + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_save_scdata(int fd){ + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { +#ifdef ENABLE_SC_SAVING + int count, aid, cid; + + aid = RFIFOL(fd, 4); + cid = RFIFOL(fd, 8); + count = RFIFOW(fd, 12); + + if( count > 0 ) + { + struct status_change_data data; + StringBuf buf; + int i; + + StringBuf_Init(&buf); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", schema_config.scdata_db); + for( i = 0; i < count; ++i ) + { + memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); + if( i > 0 ) + StringBuf_AppendStr(&buf, ", "); + StringBuf_Printf(&buf, "('%d','%d','%hu','%d','%d','%d','%d','%d')", aid, cid, + data.type, data.tick, data.val1, data.val2, data.val3, data.val4); + } + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + StringBuf_Destroy(&buf); + } +#endif + RFIFOSKIP(fd, RFIFOW(fd, 2)); + } + return 1; +} + +/** + * map-server keep alive packet, awnser back map that we alive as well + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_keepalive(int fd){ + WFIFOHEAD(fd,2); + WFIFOW(fd,0) = 0x2b24; + WFIFOSET(fd,2); + RFIFOSKIP(fd,2); + return 1; +} + +/** + * auth request from map-server + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_reqauth(int fd, int id){ + if (RFIFOREST(fd) < 19) + return 0; + + { + int account_id; + int char_id; + int login_id1; + char sex; + uint32 ip; + struct auth_node* node; + struct mmo_charstatus* cd; + struct mmo_charstatus char_dat; + DBMap* auth_db = char_get_authdb(); + DBMap* char_db_ = char_get_chardb(); + + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + login_id1 = RFIFOL(fd,10); + sex = RFIFOB(fd,14); + ip = ntohl(RFIFOL(fd,15)); + RFIFOSKIP(fd,19); + + node = (struct auth_node*)idb_get(auth_db, account_id); + cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); + if( cd == NULL ) + { //Really shouldn't happen. + char_mmo_char_fromsql(char_id, &char_dat, true); + cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); + } + if( runflag == CHARSERVER_ST_RUNNING && + cd != NULL && + node != NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 && + node->sex == sex /*&& + node->ip == ip*/ ) + {// auth ok + cd->sex = sex; + + WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus)); + WFIFOW(fd,0) = 0x2afd; + WFIFOW(fd,2) = 25 + sizeof(struct mmo_charstatus); + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = node->login_id1; + WFIFOL(fd,12) = node->login_id2; + WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" + WFIFOL(fd,20) = node->group_id; + WFIFOB(fd,24) = node->changing_mapservers; + memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); + WFIFOSET(fd, WFIFOW(fd,2)); + + // only use the auth once and mark user online + idb_remove(auth_db, account_id); + char_set_char_online(id, char_id, account_id); + } + else + {// auth failed + WFIFOHEAD(fd,19); + WFIFOW(fd,0) = 0x2b27; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = char_id; + WFIFOL(fd,10) = login_id1; + WFIFOB(fd,14) = sex; + WFIFOL(fd,15) = htonl(ip); + WFIFOSET(fd,19); + } + } + return 1; +} + +/** + * ip address update + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_updmapip(int fd, int id){ + if (RFIFOREST(fd) < 6) return 0; + map_server[id].ip = ntohl(RFIFOL(fd, 2)); + ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(map_server[id].ip)); + RFIFOSKIP(fd,6); + return 1; +} + +/** + * transmit emu usage for anom stats + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ +int chmapif_parse_fw_configstats(int fd){ + if( RFIFOREST(fd) < RFIFOW(fd,4) ) + return 0;/* packet wasn't fully received yet (still fragmented) */ + else { + int sfd;/* stat server fd */ + RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */ + + if( (sfd = make_connection(host2ip("stats.rathena.org"),(uint16)25421,true,10) ) == -1 ) { + RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ + return 0;/* connection not possible, we drop the report */ + } + + session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */ + WFIFOHEAD(sfd, RFIFOW(fd,2) ); + memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2)); + WFIFOSET(sfd, RFIFOW(fd,2) ); + flush_fifo(sfd); + do_close(sfd); + RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ + } + return 1; +} + + + +/** + * Entry point from map-server to char-server. + * Function that checks incoming command, then splits it to the correct handler. + * If not found any hander here transmis packet to inter + * @param fd: file descriptor to parse, (link to map-serv) + * @return 0=invalid server,marked for disconnection,unknow packet; 1=success + */ +int chmapif_parse(int fd){ + int id; //mapserv id + ARR_FIND( 0, ARRAYLENGTH(map_server), id, map_server[id].fd == fd ); + if( id == ARRAYLENGTH(map_server) ) + {// not a map server + ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd); + do_close(fd); + return 0; + } + if( session[fd]->flag.eof ) + { + do_close(fd); + map_server[id].fd = -1; + chmapif_on_disconnect(id); + return 0; + } + + while(RFIFOREST(fd) >= 2){ + switch(RFIFOW(fd,0)){ + case 0x2afa: chmapif_parse_getmapname(fd,id); break; + case 0x2afc: chmapif_parse_askscdata(fd); break; + case 0x2afe: chmapif_parse_getusercount(fd,id); break; //get nb user + case 0x2aff: chmapif_parse_regmapuser(fd,id); break; //register users + case 0x2b01: chmapif_parse_reqsavechar(fd,id); break; + case 0x2b02: chmapif_parse_authok(fd); break; + case 0x2b05: chmapif_parse_reqchangemapserv(fd); break; + case 0x2b07: chmapif_parse_askrmfriend(fd); break; + case 0x2b08: chmapif_parse_reqcharname(fd); break; + case 0x2b0a: chmapif_parse_req_skillcooldown(fd); break; + case 0x2b0c: chmapif_parse_reqnewemail(fd); break; + case 0x2b0e: chmapif_parse_fwlog_changestatus(fd); break; + case 0x2b10: chmapif_parse_updfamelist(fd); break; + case 0x2b11: chmapif_parse_reqdivorce(fd); break; + case 0x2b15: chmapif_parse_req_saveskillcooldown(fd); break; + case 0x2b16: chmapif_parse_updmapinfo(fd); break; + case 0x2b17: chmapif_parse_setcharoffline(fd); break; + case 0x2b18: chmapif_parse_setalloffline(fd,id); break; + case 0x2b19: chmapif_parse_setcharonline(fd,id); break; + case 0x2b1a: chmapif_parse_reqfamelist(fd); break; + case 0x2b1c: chmapif_parse_save_scdata(fd); break; + case 0x2b23: chmapif_parse_keepalive(fd); break; + case 0x2b26: chmapif_parse_reqauth(fd,id); break; + case 0x2736: chmapif_parse_updmapip(fd,id); break; + case 0x3008: chmapif_parse_fw_configstats(fd); break; + + default: + { + // inter server - packet + int r = inter_parse_frommap(fd); + if (r == 1) break; // processed + if (r == 2) return 0; // need more packet + // no inter server packet. no char server packet -> disconnect + ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0)); + set_eof(fd); + return 0; + } + } // switch + } // while + + return 1; +} + + +// Initialization process (currently only initialization inter_mapif) +int chmapif_init(int fd){ + return inter_mapif_init(fd); +} + +/** + * Initializes a server structure. + * @param id: id of map-serv (should be >0, FIXME) + */ +void chmapif_server_init(int id) { + memset(&map_server[id], 0, sizeof(map_server[id])); + map_server[id].fd = -1; +} + +/** + * Destroys a server structure. + * @param id: id of map-serv (should be >0, FIXME) + */ +void chmapif_server_destroy(int id){ + if( map_server[id].fd == -1 ){ + do_close(map_server[id].fd); + map_server[id].fd = -1; + } +} + +/** + * chmapif constructor + * Initialisation, function called at start of the char-serv. + */ +void do_init_chmapif(void){ + int i; + for( i = 0; i < ARRAYLENGTH(map_server); ++i ) + chmapif_server_init(i); +} + +/** + * Resets all the data related to a server. + * Actually destroys then recreates the struct. + * @param id: id of map-serv (should be >0, FIXME) + */ +void chmapif_server_reset(int id){ + int i,j; + unsigned char buf[16384]; + int fd = map_server[id].fd; + DBMap* online_char_db = char_get_onlinedb(); + + //Notify other map servers that this one is gone. [Skotlex] + WBUFW(buf,0) = 0x2b20; + WBUFL(buf,4) = htonl(map_server[id].ip); + WBUFW(buf,8) = htons(map_server[id].port); + j = 0; + for(i = 0; i < MAX_MAP_PER_SERVER; i++) + if (map_server[id].map[i]) + WBUFW(buf,10+(j++)*4) = map_server[id].map[i]; + if (j > 0) { + WBUFW(buf,2) = j * 4 + 10; + chmapif_sendallwos(fd, buf, WBUFW(buf,2)); + } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", schema_config.ragsrvinfo_db, map_server[id].fd) ) + Sql_ShowDebug(sql_handle); + online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. + chmapif_server_destroy(id); + chmapif_server_init(id); +} + + +/** + * Called when the connection to Map Server is disconnected. + * @param id: id of map-serv (should be >0, FIXME) + */ +void chmapif_on_disconnect(int id){ + ShowStatus("Map-server #%d has disconnected.\n", id); + chmapif_server_reset(id); +} + + +/** + * chmapif destructor + * dealloc..., function called at exit of the char-serv + */ +void do_final_chmapif(void){ + int i; + for( i = 0; i < ARRAYLENGTH(map_server); ++i ) + chmapif_server_destroy(i); +} diff --git a/src/char/char_mapif.h b/src/char/char_mapif.h new file mode 100644 index 0000000000..04ede959dc --- /dev/null +++ b/src/char/char_mapif.h @@ -0,0 +1,66 @@ +/** + * @file char_mapif.h + * Module purpose is to handle incoming and outgoing requests with map-server. + * Licensed under GNU GPL. + * For more information, see LICENCE in the main folder. + * @author Athena Dev Teams originally in login.c + * @author rAthena Dev Team + */ + + +#ifndef CHAR_MAPIF_H +#define CHAR_MAPIF_H + +#ifdef __cplusplus +extern "C" { +#endif + +int chmapif_sendall(unsigned char *buf, unsigned int len); +int chmapif_sendallwos(int sfd, unsigned char *buf, unsigned int len); +int chmapif_send(int fd, unsigned char *buf, unsigned int len); +int chmapif_send_fame_list(int fd); +void chmapif_update_fame_list(int type, int index, int fame); +void chmapif_sendall_playercount(int users); +int chmapif_parse_getmapname(int fd, int id); +int chmapif_parse_askscdata(int fd); +int chmapif_parse_getusercount(int fd, int id); +int chmapif_parse_regmapuser(int fd, int id); +int chmapif_parse_reqsavechar(int fd, int id); +int chmapif_parse_authok(int fd); +int chmapif_parse_req_saveskillcooldown(int fd); +int chmapif_parse_req_skillcooldown(int fd); +int chmapif_parse_reqchangemapserv(int fd); +int chmapif_parse_askrmfriend(int fd); +int chmapif_parse_reqcharname(int fd); +int chmapif_parse_reqnewemail(int fd); +int chmapif_parse_fwlog_changestatus(int fd); +int chmapif_parse_updfamelist(int fd); +void chmapif_send_ackdivorce(int partner_id1, int partner_id2); +int chmapif_parse_reqdivorce(int fd); +int chmapif_parse_updmapinfo(int fd); +int chmapif_parse_setcharoffline(int fd); +int chmapif_parse_setalloffline(int fd, int id); +int chmapif_parse_setcharonline(int fd, int id); +int chmapif_parse_reqfamelist(int fd); +int chmapif_parse_save_scdata(int fd); +int chmapif_parse_keepalive(int fd); +int chmapif_parse_reqauth(int fd, int id); +int chmapif_parse_updmapip(int fd, int id); +int chmapif_parse_fw_configstats(int fd); + +int chmapif_parse(int fd); +int chmapif_init(int fd); +void chmapif_server_init(int id); +void chmapif_server_destroy(int id); +void do_init_chmapif(void); +void chmapif_server_reset(int id); +void chmapif_on_disconnect(int id); +void do_final_chmapif(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* CHAR_MAPIF_H */ + diff --git a/src/char/int_auction.c b/src/char/int_auction.c index b795a07cf9..8396b78967 100644 --- a/src/char/int_auction.c +++ b/src/char/int_auction.c @@ -10,6 +10,7 @@ #include "../common/sql.h" #include "../common/timer.h" #include "char.h" +#include "char_mapif.h" #include "inter.h" #include "int_mail.h" #include "int_auction.h" @@ -50,7 +51,7 @@ void auction_save(struct auction_data *auction) StringBuf_Init(&buf); StringBuf_Printf(&buf, "UPDATE `%s` SET `seller_id` = '%d', `seller_name` = ?, `buyer_id` = '%d', `buyer_name` = ?, `price` = '%d', `buynow` = '%d', `hours` = '%d', `timestamp` = '%lu', `nameid` = '%d', `item_name` = ?, `type` = '%d', `refine` = '%d', `attribute` = '%d'", - auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute); + schema_config.auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute); for( j = 0; j < MAX_SLOTS; j++ ) StringBuf_Printf(&buf, ", `card%d` = '%d'", j, auction->item.card[j]); StringBuf_Printf(&buf, " WHERE `auction_id` = '%d'", auction->auction_id); @@ -81,7 +82,7 @@ unsigned int auction_create(struct auction_data *auction) auction->timestamp = time(NULL) + (auction->hours * 3600); StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", auction_db); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", schema_config.auction_db); for( j = 0; j < MAX_SLOTS; j++ ) StringBuf_Printf(&buf, ",`card%d`", j); StringBuf_Printf(&buf, ") VALUES ('%d',?,'%d',?,'%d','%d','%d','%lu','%d',?,'%d','%d','%d','%"PRIu64"'", @@ -135,7 +136,7 @@ static void mapif_Auction_message(int char_id, unsigned char result) WBUFW(buf,0) = 0x3854; WBUFL(buf,2) = char_id; WBUFL(buf,6) = result; - mapif_sendall(buf,7); + chmapif_sendall(buf,7); } static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data) @@ -165,7 +166,7 @@ void auction_delete(struct auction_data *auction) { unsigned int auction_id = auction->auction_id; - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", auction_db, auction_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", schema_config.auction_db, auction_id) ) Sql_ShowDebug(sql_handle); if( auction->auction_end_timer != INVALID_TIMER ) @@ -187,7 +188,7 @@ void inter_auctions_fromsql(void) "`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`"); for( i = 0; i < MAX_SLOTS; i++ ) StringBuf_Printf(&buf, ",`card%d`", i); - StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db); + StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", schema_config.auction_db); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); diff --git a/src/char/int_elemental.c b/src/char/int_elemental.c index ad622c6ce4..1729e9654b 100644 --- a/src/char/int_elemental.c +++ b/src/char/int_elemental.c @@ -17,12 +17,12 @@ bool mapif_elemental_save(struct s_elemental* ele) { bool flag = true; - + if( ele->elemental_id == 0 ) { // Create new DB entry if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`class`,`mode`,`hp`,`sp`,`max_hp`,`max_sp`,`atk1`,`atk2`,`matk`,`aspd`,`def`,`mdef`,`flee`,`hit`,`life_time`)" "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%u')", - elemental_db, ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->atk, ele->atk2, ele->matk, ele->amotion, ele->def, ele->mdef, ele->flee, ele->hit, ele->life_time) ) + schema_config.elemental_db, ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->atk, ele->atk2, ele->matk, ele->amotion, ele->def, ele->mdef, ele->flee, ele->hit, ele->life_time) ) { Sql_ShowDebug(sql_handle); flag = false; @@ -32,7 +32,7 @@ bool mapif_elemental_save(struct s_elemental* ele) { } else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_id` = '%d', `class` = '%d', `mode` = '%d', `hp` = '%d', `sp` = '%d'," "`max_hp` = '%d', `max_sp` = '%d', `atk1` = '%d', `atk2` = '%d', `matk` = '%d', `aspd` = '%d', `def` = '%d'," - "`mdef` = '%d', `flee` = '%d', `hit` = '%d', `life_time` = '%u' WHERE `ele_id` = '%d'",elemental_db, + "`mdef` = '%d', `flee` = '%d', `hit` = '%d', `life_time` = '%u' WHERE `ele_id` = '%d'", schema_config.elemental_db, ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->atk, ele->atk2, ele->matk, ele->amotion, ele->def, ele->mdef, ele->flee, ele->hit, ele->life_time, ele->elemental_id) ) { // Update DB entry @@ -44,23 +44,23 @@ bool mapif_elemental_save(struct s_elemental* ele) { bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) { char* data; - + memset(ele, 0, sizeof(struct s_elemental)); ele->elemental_id = ele_id; ele->char_id = char_id; - + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `mode`, `hp`, `sp`, `max_hp`, `max_sp`, `atk1`, `atk2`, `matk`, `aspd`," "`def`, `mdef`, `flee`, `hit`, `life_time` FROM `%s` WHERE `ele_id` = '%d' AND `char_id` = '%d'", - elemental_db, ele_id, char_id) ) { + schema_config.elemental_db, ele_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; } - + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { Sql_FreeResult(sql_handle); return false; } - + Sql_GetData(sql_handle, 0, &data, NULL); ele->class_ = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); ele->mode = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); ele->hp = atoi(data); @@ -77,24 +77,24 @@ bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) { Sql_GetData(sql_handle, 13, &data, NULL); ele->hit = atoi(data); Sql_GetData(sql_handle, 14, &data, NULL); ele->life_time = atoi(data); Sql_FreeResult(sql_handle); - if( save_log ) + if( charserv_config.save_log ) ShowInfo("Elemental loaded (%d - %d).\n", ele->elemental_id, ele->char_id); - + return true; } bool mapif_elemental_delete(int ele_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `ele_id` = '%d'", elemental_db, ele_id) ) { + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `ele_id` = '%d'", schema_config.elemental_db, ele_id) ) { Sql_ShowDebug(sql_handle); return false; } - + return true; } static void mapif_elemental_send(int fd, struct s_elemental *ele, unsigned char flag) { int size = sizeof(struct s_elemental) + 5; - + WFIFOHEAD(fd,size); WFIFOW(fd,0) = 0x387c; WFIFOW(fd,2) = size; @@ -150,7 +150,7 @@ void inter_elemental_sql_final(void) { *------------------------------------------*/ int inter_elemental_parse_frommap(int fd) { unsigned short cmd = RFIFOW(fd,0); - + switch( cmd ) { case 0x307c: mapif_parse_elemental_create(fd, (struct s_elemental*)RFIFOP(fd,4)); break; case 0x307d: mapif_parse_elemental_load(fd, (int)RFIFOL(fd,2), (int)RFIFOL(fd,6)); break; diff --git a/src/char/int_guild.c b/src/char/int_guild.c index 831231c923..82dadf9bc7 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -10,6 +10,7 @@ #include "../common/strlib.h" #include "../common/timer.h" #include "char.h" +#include "char_mapif.h" #include "inter.h" #include "int_guild.h" @@ -72,7 +73,7 @@ static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data) if( g->save_flag == GS_REMOVE ) {// Nothing to save, guild is ready for removal. - if (save_log) + if (charserv_config.save_log) ShowInfo("Guild Unloaded (%d - %s)\n", g->guild_id, g->name); db_remove(guild_db_, key); } @@ -84,15 +85,15 @@ static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data) state = guild_db_->size(guild_db_); if( state < 1 ) state = 1; //Calculate the time slot for the next save. - add_timer(tick + autosave_interval/state, guild_save_timer, 0, 0); + add_timer(tick + (charserv_config.autosave_interval)/state, guild_save_timer, 0, 0); return 0; } int inter_guild_removemember_tosql(int account_id, int char_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", guild_member_db, account_id, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", schema_config.guild_member_db, account_id, char_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '0' WHERE `char_id` = '%d'", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '0' WHERE `char_id` = '%d'", schema_config.char_db, char_id) ) Sql_ShowDebug(sql_handle); return 0; } @@ -140,7 +141,7 @@ int inter_guild_tosql(struct guild *g,int flag) if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`name`,`master`,`guild_lv`,`max_member`,`average_lv`,`char_id`) " "VALUES ('%s', '%s', '%d', '%d', '%d', '%d')", - guild_db, esc_name, esc_master, g->guild_lv, g->max_member, g->average_lv, g->member[0].char_id) ) + schema_config.guild_db, esc_name, esc_master, g->guild_lv, g->max_member, g->average_lv, g->member[0].char_id) ) { Sql_ShowDebug(sql_handle); if (g->guild_id == -1) @@ -160,7 +161,7 @@ int inter_guild_tosql(struct guild *g,int flag) bool add_comma = false; StringBuf_Init(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET ", guild_db); + StringBuf_Printf(&buf, "UPDATE `%s` SET ", schema_config.guild_db); if (flag & GS_EMBLEM) { @@ -238,14 +239,14 @@ int inter_guild_tosql(struct guild *g,int flag) Sql_EscapeStringLen(sql_handle, esc_name, m->name, strnlen(m->name, NAME_LENGTH)); if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`) " "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%"PRIu64"','%d','%d','%d','%s')", - guild_member_db, g->guild_id, m->account_id, m->char_id, + schema_config.guild_member_db, g->guild_id, m->account_id, m->char_id, m->hair, m->hair_color, m->gender, m->class_, m->lv, m->exp, m->exp_payper, m->online, m->position, esc_name) ) Sql_ShowDebug(sql_handle); if (m->modified&GS_MEMBER_NEW || new_guild == 1) { if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '%d' WHERE `char_id` = '%d'", - char_db, g->guild_id, m->char_id) ) + schema_config.char_db, g->guild_id, m->char_id) ) Sql_ShowDebug(sql_handle); } m->modified = GS_MEMBER_UNMODIFIED; @@ -262,7 +263,7 @@ int inter_guild_tosql(struct guild *g,int flag) continue; Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ('%d','%d','%s','%d','%d')", - guild_position_db, g->guild_id, i, esc_name, p->mode, p->exp_mode) ) + schema_config.guild_position_db, g->guild_id, i, esc_name, p->mode, p->exp_mode) ) Sql_ShowDebug(sql_handle); p->modified = GS_POSITION_UNMODIFIED; } @@ -275,7 +276,7 @@ int inter_guild_tosql(struct guild *g,int flag) // their info changed, not to mention this would also mess up oppositions! // [Skotlex] //if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d'", guild_alliance_db, g->guild_id, g->guild_id) ) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, g->guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_alliance_db, g->guild_id) ) { Sql_ShowDebug(sql_handle); } @@ -290,7 +291,7 @@ int inter_guild_tosql(struct guild *g,int flag) Sql_EscapeStringLen(sql_handle, esc_name, a->name, strnlen(a->name, NAME_LENGTH)); if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) " "VALUES ('%d','%d','%d','%s')", - guild_alliance_db, g->guild_id, a->opposition, a->guild_id, esc_name) ) + schema_config.guild_alliance_db, g->guild_id, a->opposition, a->guild_id, esc_name) ) Sql_ShowDebug(sql_handle); } } @@ -308,7 +309,7 @@ int inter_guild_tosql(struct guild *g,int flag) Sql_EscapeStringLen(sql_handle, esc_name, e->name, strnlen(e->name, NAME_LENGTH)); Sql_EscapeStringLen(sql_handle, esc_mes, e->mes, strnlen(e->mes, sizeof(e->mes))); if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`name`,`mes`) " - "VALUES ('%d','%d','%s','%s')", guild_expulsion_db, g->guild_id, e->account_id, esc_name, esc_mes) ) + "VALUES ('%d','%d','%s','%s')", schema_config.guild_expulsion_db, g->guild_id, e->account_id, esc_name, esc_mes) ) Sql_ShowDebug(sql_handle); } } @@ -320,13 +321,13 @@ int inter_guild_tosql(struct guild *g,int flag) for(i=0;iskill[i].id>0 && g->skill[i].lv>0){ if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`id`,`lv`) VALUES ('%d','%d','%d')", - guild_skill_db, g->guild_id, g->skill[i].id, g->skill[i].lv) ) + schema_config.guild_skill_db, g->guild_id, g->skill[i].id, g->skill[i].lv) ) Sql_ShowDebug(sql_handle); } } } - if (save_log) + if (charserv_config.save_log) ShowInfo("Saved guild (%d - %s):%s\n",g->guild_id,g->name,t_info); return 1; } @@ -352,7 +353,7 @@ struct guild * inter_guild_fromsql(int guild_id) #endif if( SQL_ERROR == Sql_Query(sql_handle, "SELECT g.`name`,c.`name`,g.`guild_lv`,g.`connect_member`,g.`max_member`,g.`average_lv`,g.`exp`,g.`next_exp`,g.`skill_point`,g.`mes1`,g.`mes2`,g.`emblem_len`,g.`emblem_id`,g.`emblem_data` " - "FROM `%s` g LEFT JOIN `%s` c ON c.`char_id` = g.`char_id` WHERE g.`guild_id`='%d'", guild_db, char_db, guild_id) ) + "FROM `%s` g LEFT JOIN `%s` c ON c.`char_id` = g.`char_id` WHERE g.`guild_id`='%d'", schema_config.guild_db, schema_config.char_db, guild_id) ) { Sql_ShowDebug(sql_handle); return NULL; @@ -407,7 +408,7 @@ struct guild * inter_guild_fromsql(int guild_id) // load guild member info if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` " - "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) ) + "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", schema_config.guild_member_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -435,7 +436,7 @@ struct guild * inter_guild_fromsql(int guild_id) } //printf("- Read guild_position %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_position_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -457,7 +458,7 @@ struct guild * inter_guild_fromsql(int guild_id) } //printf("- Read guild_alliance %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_alliance_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -473,7 +474,7 @@ struct guild * inter_guild_fromsql(int guild_id) } //printf("- Read guild_expulsion %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_expulsion_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -489,7 +490,7 @@ struct guild * inter_guild_fromsql(int guild_id) } //printf("- Read guild_skill %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", schema_config.guild_skill_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -514,7 +515,7 @@ struct guild * inter_guild_fromsql(int guild_id) idb_put(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 (charserv_config.save_log) ShowInfo("Guild loaded (%d - %s)\n", guild_id, g->name); return g; @@ -528,15 +529,15 @@ int inter_guildcastle_tosql(struct guild_castle *gc) StringBuf_Init(&buf); StringBuf_Printf(&buf, "REPLACE INTO `%s` SET `castle_id`='%d', `guild_id`='%d', `economy`='%d', `defense`='%d', " - "`triggerE`='%d', `triggerD`='%d', `nextTime`='%d', `payTime`='%d', `createTime`='%d', `visibleC`='%d'", - guild_castle_db, gc->castle_id, gc->guild_id, gc->economy, gc->defense, - gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime, gc->createTime, gc->visibleC); + "`triggerE`='%d', `triggerD`='%d', `nextTime`='%d', `payTime`='%d', `createTime`='%d', `visibleC`='%d'", + schema_config.guild_castle_db, gc->castle_id, gc->guild_id, gc->economy, gc->defense, + gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime, gc->createTime, gc->visibleC); for (i = 0; i < MAX_GUARDIANS; ++i) StringBuf_Printf(&buf, ", `visibleG%d`='%d'", i, gc->guardian[i].visible); if (SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf))) Sql_ShowDebug(sql_handle); - else if(save_log) + else if(charserv_config.save_log) ShowInfo("Saved guild castle (%d)\n", gc->castle_id); StringBuf_Destroy(&buf); @@ -559,7 +560,7 @@ static struct guild_castle* inter_guildcastle_fromsql(int castle_id) "`triggerD`, `nextTime`, `payTime`, `createTime`, `visibleC`"); for (i = 0; i < MAX_GUARDIANS; ++i) StringBuf_Printf(&buf, ", `visibleG%d`", i); - StringBuf_Printf(&buf, " FROM `%s` WHERE `castle_id`='%d'", guild_castle_db, castle_id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `castle_id`='%d'", schema_config.guild_castle_db, castle_id); if (SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf))) { Sql_ShowDebug(sql_handle); StringBuf_Destroy(&buf); @@ -588,7 +589,7 @@ static struct guild_castle* inter_guildcastle_fromsql(int castle_id) idb_put(castle_db, castle_id, gc); - if (save_log) + if (charserv_config.save_log) ShowInfo("Loaded guild castle (%d - guild %d)\n", castle_id, gc->guild_id); return gc; @@ -617,7 +618,7 @@ int inter_guild_CharOnline(int char_id, int guild_id) if (guild_id == -1) { //Get guild_id from the database - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", schema_config.char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; @@ -668,7 +669,7 @@ int inter_guild_CharOffline(int char_id, int guild_id) if (guild_id == -1) { //Get guild_id from the database - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", schema_config.char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; @@ -762,7 +763,7 @@ int search_guildname(char *str) Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH)); //Lookup guilds with the same name - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE name='%s'", guild_db, esc_name) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE name='%s'", schema_config.guild_db, esc_name) ) { Sql_ShowDebug(sql_handle); return -1; @@ -908,9 +909,9 @@ int mapif_guild_noinfo(int fd,int guild_id) WBUFL(buf,4)=guild_id; ShowWarning("int_guild: info not found %d\n",guild_id); if(fd<0) - mapif_sendall(buf,8); + chmapif_sendall(buf,8); else - mapif_send(fd,buf,8); + chmapif_send(fd,buf,8); return 0; } @@ -922,9 +923,9 @@ int mapif_guild_info(int fd,struct guild *g) WBUFW(buf,2)=4+sizeof(struct guild); memcpy(buf+4,g,sizeof(struct guild)); if(fd<0) - mapif_sendall(buf,WBUFW(buf,2)); + chmapif_sendall(buf,WBUFW(buf,2)); else - mapif_send(fd,buf,WBUFW(buf,2)); + chmapif_send(fd,buf,WBUFW(buf,2)); return 0; } @@ -952,7 +953,7 @@ int mapif_guild_withdraw(int guild_id,int account_id,int char_id,int flag, const WBUFB(buf,14)=flag; memcpy(WBUFP(buf,15),mes,40); memcpy(WBUFP(buf,55),name,NAME_LENGTH); - mapif_sendall(buf,55+NAME_LENGTH); + chmapif_sendall(buf,55+NAME_LENGTH); ShowInfo("int_guild: guild withdraw (%d - %d: %s - %s)\n",guild_id,account_id,name,mes); return 0; } @@ -968,7 +969,7 @@ int mapif_guild_memberinfoshort(struct guild *g,int idx) WBUFB(buf,14)=(unsigned char)g->member[idx].online; WBUFW(buf,15)=g->member[idx].lv; WBUFW(buf,17)=g->member[idx].class_; - mapif_sendall(buf,19); + chmapif_sendall(buf,19); return 0; } @@ -979,7 +980,7 @@ int mapif_guild_broken(int guild_id,int flag) WBUFW(buf,0)=0x3836; WBUFL(buf,2)=guild_id; WBUFB(buf,6)=flag; - mapif_sendall(buf,7); + chmapif_sendall(buf,7); ShowInfo("int_guild: Guild broken (%d)\n",guild_id); return 0; } @@ -995,7 +996,7 @@ int mapif_guild_message(int guild_id,int account_id,char *mes,int len, int sfd) WBUFL(buf,4)=guild_id; WBUFL(buf,8)=account_id; memcpy(WBUFP(buf,12),mes,len); - mapif_sendallwos(sfd, buf,len+12); + chmapif_sendallwos(sfd, buf,len+12); return 0; } @@ -1010,7 +1011,7 @@ int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len) WBUFL(buf, 4)=guild_id; WBUFW(buf, 8)=type; memcpy(WBUFP(buf,10),data,len); - mapif_sendall(buf,len+10); + chmapif_sendall(buf,len+10); return 0; } @@ -1027,7 +1028,7 @@ int mapif_guild_memberinfochanged(int guild_id,int account_id,int char_id, int t WBUFL(buf,12)=char_id; WBUFW(buf,16)=type; memcpy(WBUFP(buf,18),data,len); - mapif_sendall(buf,len+18); + chmapif_sendall(buf,len+18); return 0; } @@ -1039,7 +1040,7 @@ int mapif_guild_skillupack(int guild_id,uint16 skill_id,int account_id) WBUFL(buf, 2)=guild_id; WBUFL(buf, 6)=skill_id; WBUFL(buf,10)=account_id; - mapif_sendall(buf,14); + chmapif_sendall(buf,14); return 0; } @@ -1055,7 +1056,7 @@ int mapif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account WBUFB(buf,18)=flag; memcpy(WBUFP(buf,19),name1,NAME_LENGTH); memcpy(WBUFP(buf,19+NAME_LENGTH),name2,NAME_LENGTH); - mapif_sendall(buf,19+2*NAME_LENGTH); + chmapif_sendall(buf,19+2*NAME_LENGTH); return 0; } @@ -1068,7 +1069,7 @@ int mapif_guild_position(struct guild *g,int idx) WBUFL(buf,4)=g->guild_id; WBUFL(buf,8)=idx; memcpy(WBUFP(buf,12),&g->position[idx],sizeof(struct guild_position)); - mapif_sendall(buf,WBUFW(buf,2)); + chmapif_sendall(buf,WBUFW(buf,2)); return 0; } @@ -1080,7 +1081,7 @@ int mapif_guild_notice(struct guild *g) WBUFL(buf,2)=g->guild_id; memcpy(WBUFP(buf,6),g->mes1,MAX_GUILDMES1); memcpy(WBUFP(buf,66),g->mes2,MAX_GUILDMES2); - mapif_sendall(buf,186); + chmapif_sendall(buf,186); return 0; } @@ -1093,7 +1094,7 @@ int mapif_guild_emblem(struct guild *g) WBUFL(buf,4)=g->guild_id; WBUFL(buf,8)=g->emblem_id; memcpy(WBUFP(buf,12),g->emblem_data,g->emblem_len); - mapif_sendall(buf,WBUFW(buf,2)); + chmapif_sendall(buf,WBUFW(buf,2)); return 0; } @@ -1104,7 +1105,7 @@ int mapif_guild_master_changed(struct guild *g, int aid, int cid) WBUFL(buf,2)=g->guild_id; WBUFL(buf,6)=aid; WBUFL(buf,10)=cid; - mapif_sendall(buf,14); + chmapif_sendall(buf,14); return 0; } @@ -1144,15 +1145,15 @@ int mapif_parse_CreateGuild(int fd,int account_id,char *name,struct guild_member return 0; } // Check Authorised letters/symbols in the name of the character - if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised + if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised for (i = 0; i < NAME_LENGTH && name[i]; i++) - if (strchr(char_name_letters, name[i]) == NULL) { + if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) { mapif_guild_created(fd,account_id,NULL); return 0; } - } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden + } else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden for (i = 0; i < NAME_LENGTH && name[i]; i++) - if (strchr(char_name_letters, name[i]) != NULL) { + if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) { mapif_guild_created(fd,account_id,NULL); return 0; } @@ -1202,7 +1203,7 @@ int mapif_parse_CreateGuild(int fd,int account_id,char *name,struct guild_member mapif_guild_created(fd,account_id,g); mapif_guild_info(fd,g); - if(log_inter) + if(charserv_config.log_inter) inter_log("guild %s (id=%d) created by master %s (id=%d)\n", name, g->guild_id, master->name, master->account_id ); @@ -1268,7 +1269,7 @@ int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, in if( g == NULL ) { // Unknown guild, just update the player - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", schema_config.char_db, account_id, char_id) ) Sql_ShowDebug(sql_handle); // mapif_guild_withdraw(guild_id,account_id,char_id,flag,g->member[i].name,mes); return 0; @@ -1381,37 +1382,37 @@ int mapif_parse_BreakGuild(int fd,int guild_id) // Delete guild from sql //printf("- Delete guild %d from guild\n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", schema_config.guild_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", schema_config.guild_member_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", schema_config.guild_castle_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", schema_config.guild_storage_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", schema_config.guild_alliance_db, guild_id, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", schema_config.guild_position_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", schema_config.guild_skill_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", schema_config.guild_expulsion_db, guild_id) ) Sql_ShowDebug(sql_handle); //printf("- Update guild %d of char\n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", char_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", schema_config.char_db, guild_id) ) Sql_ShowDebug(sql_handle); mapif_guild_broken(guild_id,0); - if(log_inter) + if(charserv_config.log_inter) inter_log("guild %s (id=%d) broken\n",g->name,guild_id); //Remove the guild from memory. [Skotlex] @@ -1499,8 +1500,8 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha exp = g->member[i].exp - old_exp; // Compute gained exp - if (guild_exp_rate != 100) - exp = exp*guild_exp_rate/100; + if (charserv_config.guild_exp_rate != 100) + exp = exp*(charserv_config.guild_exp_rate)/100; // Update guild exp if (exp > UINT64_MAX - g->exp) @@ -1761,7 +1762,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 (charserv_config.log_inter && gc->guild_id != value) { int gid = (value) ? value : gc->guild_id; struct guild *g = idb_get(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 f6bfd422b9..af0e1d010f 100644 --- a/src/char/int_homun.c +++ b/src/char/int_homun.c @@ -95,7 +95,7 @@ bool mapif_homunculus_save(struct s_homunculus* hd) if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`char_id`, `class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) " "VALUES ('%d', '%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, + schema_config.homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize) ) { Sql_ShowDebug(sql_handle); @@ -109,7 +109,7 @@ bool mapif_homunculus_save(struct s_homunculus* hd) else { if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'", - homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, + schema_config.homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) ) { Sql_ShowDebug(sql_handle); @@ -121,7 +121,7 @@ bool mapif_homunculus_save(struct s_homunculus* hd) int i; stmt = SqlStmt_Malloc(sql_handle); - if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", skill_homunculus_db, hd->hom_id) ) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", schema_config.skill_homunculus_db, hd->hom_id) ) SqlStmt_ShowDebug(stmt); for( i = 0; i < MAX_HOMUNSKILL; ++i ) { @@ -155,7 +155,8 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) memset(hd, 0, sizeof(*hd)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'", homunculus_db, homun_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'", + schema_config.homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -201,7 +202,7 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) hd->hunger = cap_value(hd->hunger, 0, 100); // Load Homunculus Skill - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", skill_homunculus_db, homun_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", schema_config.skill_homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -223,7 +224,7 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) } Sql_FreeResult(sql_handle); - if( save_log ) + if( charserv_config.save_log ) ShowInfo("Homunculus loaded (%d - %s).\n", hd->hom_id, hd->name); return true; @@ -231,8 +232,8 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) bool mapif_homunculus_delete(int homun_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", homunculus_db, homun_id) - || SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", skill_homunculus_db, homun_id) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", schema_config.homunculus_db, homun_id) + || SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", schema_config.skill_homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -245,16 +246,16 @@ bool mapif_homunculus_rename(char *name) int i; // Check Authorised letters/symbols in the name of the homun - if( char_name_option == 1 ) + if( charserv_config.char_config.char_name_option == 1 ) {// only letters/symbols in char_name_letters are authorised for( i = 0; i < NAME_LENGTH && name[i]; i++ ) - if( strchr(char_name_letters, name[i]) == NULL ) + if( strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL ) return false; } else - if( char_name_option == 2 ) + if( charserv_config.char_config.char_name_option == 2 ) {// letters/symbols in char_name_letters are forbidden for( i = 0; i < NAME_LENGTH && name[i]; i++ ) - if( strchr(char_name_letters, name[i]) != NULL ) + if( strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL ) return false; } diff --git a/src/char/int_mail.c b/src/char/int_mail.c index 28f46c4b82..8cf84db66c 100644 --- a/src/char/int_mail.c +++ b/src/char/int_mail.c @@ -9,6 +9,7 @@ #include "../common/sql.h" #include "../common/timer.h" #include "char.h" +#include "char_mapif.h" #include "inter.h" #include @@ -35,7 +36,7 @@ static int mail_fromsql(int char_id, struct mail_data* md) // I keep the `status` < 3 just in case someone forget to apply the sqlfix StringBuf_Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' AND `status` < 3 ORDER BY `id` LIMIT %d", - mail_db, char_id, MAIL_MAX_INBOX + 1); + schema_config.mail_db, char_id, MAIL_MAX_INBOX + 1); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); @@ -84,7 +85,7 @@ static int mail_fromsql(int char_id, struct mail_data* md) msg = &md->msg[i]; if( msg->status == MAIL_NEW ) { - if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_UNREAD, msg->id) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", schema_config.mail_db, MAIL_UNREAD, msg->id) ) Sql_ShowDebug(sql_handle); msg->status = MAIL_UNREAD; @@ -108,7 +109,7 @@ int mail_savemessage(struct mail_message* msg) // build message save query StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `status`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`, `unique_id`", mail_db); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `status`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`, `unique_id`", schema_config.mail_db); for (j = 0; j < MAX_SLOTS; j++) StringBuf_Printf(&buf, ", `card%d`", j); StringBuf_Printf(&buf, ") VALUES (?, '%d', ?, '%d', ?, ?, '%lu', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%"PRIu64"'", @@ -116,7 +117,7 @@ int mail_savemessage(struct mail_message* msg) for (j = 0; j < MAX_SLOTS; j++) StringBuf_Printf(&buf, ", '%d'", msg->item.card[j]); StringBuf_AppendStr(&buf, ")"); - + //Unique Non Stackable Item ID updateLastUid(msg->item.unique_id); dbUpdateUid(sql_handle); @@ -153,7 +154,7 @@ static bool mail_loadmessage(int mail_id, struct mail_message* msg) "`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`,`unique_id`"); for( j = 0; j < MAX_SLOTS; j++ ) StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `id` = '%d'", mail_db, mail_id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `id` = '%d'", schema_config.mail_db, mail_id); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) @@ -228,7 +229,7 @@ static void mapif_parse_Mail_requestinbox(int fd) static void mapif_parse_Mail_read(int fd) { int mail_id = RFIFOL(fd,2); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_READ, mail_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", schema_config.mail_db, MAIL_READ, mail_id) ) Sql_ShowDebug(sql_handle); } @@ -241,7 +242,7 @@ static bool mail_DeleteAttach(int mail_id) int i; StringBuf_Init(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `zeny` = '0', `nameid` = '0', `amount` = '0', `refine` = '0', `attribute` = '0', `identify` = '0'", mail_db); + StringBuf_Printf(&buf, "UPDATE `%s` SET `zeny` = '0', `nameid` = '0', `amount` = '0', `refine` = '0', `attribute` = '0', `identify` = '0'", schema_config.mail_db); for (i = 0; i < MAX_SLOTS; i++) StringBuf_Printf(&buf, ", `card%d` = '0'", i); StringBuf_Printf(&buf, " WHERE `id` = '%d'", mail_id); @@ -297,7 +298,7 @@ static void mapif_parse_Mail_getattach(int fd) static void mapif_Mail_delete(int fd, int char_id, int mail_id) { bool failed = false; - if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", schema_config.mail_db, mail_id) ) { Sql_ShowDebug(sql_handle); failed = true; @@ -322,7 +323,7 @@ static void mapif_parse_Mail_delete(int fd) void mapif_Mail_new(struct mail_message *msg) { unsigned char buf[74]; - + if( !msg || !msg->id ) return; @@ -331,7 +332,7 @@ void mapif_Mail_new(struct mail_message *msg) WBUFL(buf,6) = msg->id; memcpy(WBUFP(buf,10), msg->send_name, NAME_LENGTH); memcpy(WBUFP(buf,34), msg->title, MAIL_TITLE_LENGTH); - mapif_sendall(buf, 74); + chmapif_sendall(buf, 74); } /*========================================== @@ -346,7 +347,7 @@ static void mapif_Mail_return(int fd, int char_id, int mail_id) { if( msg.dest_id != char_id) return; - else if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) + else if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", schema_config.mail_db, mail_id) ) Sql_ShowDebug(sql_handle); else { @@ -389,7 +390,7 @@ static void mapif_parse_Mail_return(int fd) static void mapif_Mail_send(int fd, struct mail_message* msg) { int len = sizeof(struct mail_message) + 4; - + WFIFOHEAD(fd,len); WFIFOW(fd,0) = 0x384d; WFIFOW(fd,2) = len; @@ -411,7 +412,7 @@ static void mapif_parse_Mail_send(int fd) // Try to find the Dest Char by Name Sql_EscapeStringLen(sql_handle, esc_name, msg.dest_name, strnlen(msg.dest_name, NAME_LENGTH)); - if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, esc_name) ) Sql_ShowDebug(sql_handle); else if ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) diff --git a/src/char/int_mercenary.c b/src/char/int_mercenary.c index 3b37144163..88d001c72a 100644 --- a/src/char/int_mercenary.c +++ b/src/char/int_mercenary.c @@ -19,7 +19,7 @@ bool mercenary_owner_fromsql(int char_id, struct mmo_charstatus *status) { char* data; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith` FROM `%s` WHERE `char_id` = '%d'", mercenary_owner_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith` FROM `%s` WHERE `char_id` = '%d'", schema_config.mercenary_owner_db, char_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -46,7 +46,7 @@ bool mercenary_owner_fromsql(int char_id, struct mmo_charstatus *status) bool mercenary_owner_tosql(int char_id, struct mmo_charstatus *status) { if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`, `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith`) VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - mercenary_owner_db, char_id, status->mer_id, status->arch_calls, status->arch_faith, status->spear_calls, status->spear_faith, status->sword_calls, status->sword_faith) ) + schema_config.mercenary_owner_db, char_id, status->mer_id, status->arch_calls, status->arch_faith, status->spear_calls, status->spear_faith, status->sword_calls, status->sword_faith) ) { Sql_ShowDebug(sql_handle); return false; @@ -57,10 +57,10 @@ bool mercenary_owner_tosql(int char_id, struct mmo_charstatus *status) bool mercenary_owner_delete(int char_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", mercenary_owner_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.mercenary_owner_db, char_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", mercenary_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", schema_config.mercenary_db, char_id) ) Sql_ShowDebug(sql_handle); return true; @@ -74,7 +74,7 @@ bool mapif_mercenary_save(struct s_mercenary* merc) { // Create new DB entry if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`class`,`hp`,`sp`,`kill_counter`,`life_time`) VALUES ('%d','%d','%d','%d','%u','%u')", - mercenary_db, merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->life_time) ) + schema_config.mercenary_db, merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->life_time) ) { Sql_ShowDebug(sql_handle); flag = false; @@ -84,7 +84,7 @@ bool mapif_mercenary_save(struct s_mercenary* merc) } else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_id` = '%d', `class` = '%d', `hp` = '%d', `sp` = '%d', `kill_counter` = '%u', `life_time` = '%u' WHERE `mer_id` = '%d'", - mercenary_db, merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->life_time, merc->mercenary_id) ) + schema_config.mercenary_db, merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->life_time, merc->mercenary_id) ) { // Update DB entry Sql_ShowDebug(sql_handle); flag = false; @@ -101,7 +101,7 @@ bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc) merc->mercenary_id = merc_id; merc->char_id = char_id; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `hp`, `sp`, `kill_counter`, `life_time` FROM `%s` WHERE `mer_id` = '%d' AND `char_id` = '%d'", mercenary_db, merc_id, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `hp`, `sp`, `kill_counter`, `life_time` FROM `%s` WHERE `mer_id` = '%d' AND `char_id` = '%d'", schema_config.mercenary_db, merc_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -119,15 +119,15 @@ bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc) Sql_GetData(sql_handle, 3, &data, NULL); merc->kill_count = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); merc->life_time = atoi(data); Sql_FreeResult(sql_handle); - if( save_log ) + if( charserv_config.save_log ) ShowInfo("Mercenary loaded (%d - %d).\n", merc->mercenary_id, merc->char_id); - + return true; } bool mapif_mercenary_delete(int merc_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `mer_id` = '%d'", mercenary_db, merc_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `mer_id` = '%d'", schema_config.mercenary_db, merc_id) ) { Sql_ShowDebug(sql_handle); return false; diff --git a/src/char/int_party.c b/src/char/int_party.c index ed8e645cc3..32936819f1 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -11,6 +11,7 @@ #include "../common/mapindex.h" #include "../common/sql.h" #include "char.h" +#include "char_mapif.h" #include "inter.h" #include "int_party.h" @@ -129,9 +130,9 @@ int inter_party_tosql(struct party *p, int flag, int index) if( flag & PS_BREAK ) {// Break the party // we'll skip name-checking and just reset everyone with the same party id [celest] - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", schema_config.char_db, party_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", schema_config.party_db, party_id) ) Sql_ShowDebug(sql_handle); //Remove from memory idb_remove(party_db_, party_id); @@ -143,7 +144,7 @@ int inter_party_tosql(struct party *p, int flag, int index) if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`name`, `exp`, `item`, `leader_id`, `leader_char`) " "VALUES ('%s', '%d', '%d', '%d', '%d')", - party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) + schema_config.party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) { Sql_ShowDebug(sql_handle); return 0; @@ -154,32 +155,32 @@ int inter_party_tosql(struct party *p, int flag, int index) if( flag & PS_BASIC ) {// Update party info. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'", - party_db, esc_name, p->exp, p->item, party_id) ) + schema_config.party_db, esc_name, p->exp, p->item, party_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_LEADER ) {// Update leader if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'", - party_db, p->member[index].account_id, p->member[index].char_id, party_id) ) + schema_config.party_db, p->member[index].account_id, p->member[index].char_id, party_id) ) Sql_ShowDebug(sql_handle); } - + if( flag & PS_ADDMEMBER ) {// Add one party member. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'", - char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) + schema_config.char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_DELMEMBER ) {// Remove one party member. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'", - char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) + schema_config.char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) Sql_ShowDebug(sql_handle); } - if( save_log ) + if( charserv_config.save_log ) ShowInfo("Party Saved (%d - %s)\n", party_id, p->name); return 1; } @@ -200,7 +201,7 @@ struct party_data *inter_party_fromsql(int party_id) #endif if( party_id <= 0 ) return NULL; - + //Load from memory p = (struct party_data*)idb_get(party_db_, party_id); if( p != NULL ) @@ -209,7 +210,7 @@ struct party_data *inter_party_fromsql(int party_id) p = party_pt; memset(p, 0, sizeof(struct party_data)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", schema_config.party_db, party_id) ) { Sql_ShowDebug(sql_handle); return NULL; @@ -227,7 +228,7 @@ struct party_data *inter_party_fromsql(int party_id) Sql_FreeResult(sql_handle); // Load members - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", schema_config.char_db, party_id) ) { Sql_ShowDebug(sql_handle); return NULL; @@ -246,7 +247,7 @@ struct party_data *inter_party_fromsql(int party_id) } Sql_FreeResult(sql_handle); - if( save_log ) + if( charserv_config.save_log ) ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name); //Add party to memory. CREATE(p, struct party_data, 1); @@ -291,7 +292,7 @@ struct party_data* search_partyname(char* str) struct party_data* p = NULL; Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", schema_config.party_db, esc_name) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { @@ -370,9 +371,9 @@ static void mapif_party_info(int fd, struct party* p, int char_id) memcpy(WBUFP(buf,8), p, sizeof(struct party)); if(fd<0) - mapif_sendall(buf,WBUFW(buf,2)); + chmapif_sendall(buf,WBUFW(buf,2)); else - mapif_send(fd,buf,WBUFW(buf,2)); + chmapif_send(fd,buf,WBUFW(buf,2)); } //Whether or not additional party members @@ -399,9 +400,9 @@ int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag) WBUFW(buf,12)=p->item; WBUFB(buf,14)=flag; if(flag==0) - mapif_sendall(buf,15); + chmapif_sendall(buf,15); else - mapif_send(fd,buf,15); + chmapif_send(fd,buf,15); return 0; } @@ -413,7 +414,7 @@ int mapif_party_withdraw(int party_id,int account_id, int char_id) { WBUFL(buf,2) = party_id; WBUFL(buf,6) = account_id; WBUFL(buf,10) = char_id; - mapif_sendall(buf, 14); + chmapif_sendall(buf, 14); return 0; } @@ -429,7 +430,7 @@ int mapif_party_membermoved(struct party *p,int idx) WBUFW(buf,14) = p->member[idx].map; WBUFB(buf,16) = p->member[idx].online; WBUFW(buf,17) = p->member[idx].lv; - mapif_sendall(buf, 19); + chmapif_sendall(buf, 19); return 0; } @@ -440,7 +441,7 @@ int mapif_party_broken(int party_id,int flag) WBUFW(buf,0)=0x3826; WBUFL(buf,2)=party_id; WBUFB(buf,6)=flag; - mapif_sendall(buf,7); + chmapif_sendall(buf,7); //printf("int_party: broken %d\n",party_id); return 0; } @@ -454,7 +455,7 @@ int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd) WBUFL(buf,4)=party_id; WBUFL(buf,8)=account_id; memcpy(WBUFP(buf,12),mes,len); - mapif_sendallwos(sfd, buf,len+12); + chmapif_sendallwos(sfd, buf,len+12); return 0; } @@ -472,9 +473,9 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part return 0; } // Check Authorised letters/symbols in the name of the character - if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised + if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised for (i = 0; i < NAME_LENGTH && name[i]; i++) - if (strchr(char_name_letters, name[i]) == NULL) { + if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) { if( name[i] == '"' ) { /* client-special-char */ normalize_name(name,"\""); mapif_parse_CreateParty(fd,name,item,item2,leader); @@ -483,16 +484,16 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part mapif_party_created(fd,leader->account_id,leader->char_id,NULL); return 0; } - } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden + } else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden for (i = 0; i < NAME_LENGTH && name[i]; i++) - if (strchr(char_name_letters, name[i]) != NULL) { + if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) { mapif_party_created(fd,leader->account_id,leader->char_id,NULL); return 0; } } p = (struct party_data*)aCalloc(1, sizeof(struct party_data)); - + memcpy(p->party.name,name,NAME_LENGTH); p->party.exp=0; p->party.item=(item?1:0)|(item2?2:0); @@ -596,7 +597,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id) p = inter_party_fromsql(party_id); if( p == NULL ) {// Party does not exists? - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", schema_config.char_db, party_id) ) Sql_ShowDebug(sql_handle); return 0; } @@ -633,7 +634,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id) int_party_check_lv(p); } } - + if (party_check_empty(p) == 0) mapif_party_info(-1, &p->party, 0); return 0; @@ -648,7 +649,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id if (p == NULL) return 0; - for(i = 0; i < MAX_PARTY && + for(i = 0; i < MAX_PARTY && (p->party.member[i].account_id != account_id || p->party.member[i].char_id != char_id); i++); @@ -662,7 +663,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id else p->party.count--; // Even share check situations: Family state (always breaks) - // character logging on/off is max/min level (update level range) + // character logging on/off is max/min level (update level range) // or character logging on/off has a different level (update level range using new level) if (p->family || (p->party.member[i].lv <= p->min_lv || p->party.member[i].lv >= p->max_lv) || @@ -727,7 +728,7 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id for (i = 0; i < MAX_PARTY; i++) { - if(p->party.member[i].leader) + if(p->party.member[i].leader) p->party.member[i].leader = 0; if(p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id) @@ -799,7 +800,7 @@ int inter_party_CharOnline(int char_id, int party_id) {// Get party_id from the database char* data; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", schema_config.char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; @@ -814,7 +815,7 @@ int inter_party_CharOnline(int char_id, int party_id) } if (party_id == 0) return 0; //No party... - + p = inter_party_fromsql(party_id); if(!p) { ShowError("Character %d's party %d not found!\n", char_id, party_id); @@ -845,7 +846,7 @@ int inter_party_CharOffline(int char_id, int party_id) { {// Get guild_id from the database char* data; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", schema_config.char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; @@ -860,7 +861,7 @@ int inter_party_CharOffline(int char_id, int party_id) { } if (party_id == 0) return 0; //No party... - + //Character has a party, set character offline and check if they were the only member online if ((p = inter_party_fromsql(party_id)) == NULL) return 0; diff --git a/src/char/int_pet.c b/src/char/int_pet.c index f01eaa9bf8..049bd27bc9 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -32,7 +32,7 @@ int inter_pet_tosql(int pet_id, struct s_pet* p) if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) " "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, + schema_config.pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate) ) { Sql_ShowDebug(sql_handle); @@ -43,7 +43,7 @@ int inter_pet_tosql(int pet_id, struct s_pet* p) else {// Update pet. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", - pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, + schema_config.pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id) ) { Sql_ShowDebug(sql_handle); @@ -51,7 +51,7 @@ int inter_pet_tosql(int pet_id, struct s_pet* p) } } - if (save_log) + if (charserv_config.save_log) ShowInfo("Pet saved %d - %s.\n", pet_id, p->name); return 1; } @@ -68,7 +68,7 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p) //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", schema_config.pet_db, pet_id) ) { Sql_ShowDebug(sql_handle); return 0; @@ -94,7 +94,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( charserv_config.save_log ) ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name); } return 0; @@ -114,7 +114,7 @@ void inter_pet_sql_final(void){ int inter_pet_delete(int pet_id){ ShowInfo("delete pet request: %d...\n",pet_id); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", schema_config.pet_db, pet_id) ) Sql_ShowDebug(sql_handle); return 0; } diff --git a/src/char/int_quest.c b/src/char/int_quest.c index 224205412f..1480b3e0df 100644 --- a/src/char/int_quest.c +++ b/src/char/int_quest.c @@ -34,7 +34,7 @@ int mapif_quests_fromsql(int char_id, struct quest questlog[]) memset(&tmp_quest, 0, sizeof(struct quest)); - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state`, `time`, `count1`, `count2`, `count3` FROM `%s` WHERE `char_id`=? LIMIT %d", quest_db, MAX_QUEST_DB) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state`, `time`, `count1`, `count2`, `count3` FROM `%s` WHERE `char_id`=? LIMIT %d", schema_config.quest_db, MAX_QUEST_DB) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_quest.quest_id, 0, NULL, NULL) @@ -55,7 +55,7 @@ int mapif_quests_fromsql(int char_id, struct quest questlog[]) //Delete a quest bool mapif_quest_delete(int char_id, int quest_id) { - if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", schema_config.quest_db, quest_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -67,7 +67,7 @@ bool mapif_quest_delete(int char_id, int quest_id) //Add a quest to a questlog bool mapif_quest_add(int char_id, struct quest qd) { - if ( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", schema_config.quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) ) { Sql_ShowDebug(sql_handle); return false; @@ -79,7 +79,7 @@ bool mapif_quest_add(int char_id, struct quest qd) //Update a questlog bool mapif_quest_update(int char_id, struct quest qd) { - if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", schema_config.quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; diff --git a/src/char/int_storage.c b/src/char/int_storage.c index a19420ac27..d00a999b3b 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -20,7 +20,7 @@ /// Save storage data to sql int storage_tosql(int account_id, struct storage_data* p) { - memitemdata_to_sql(p->items, MAX_STORAGE, account_id, TABLE_STORAGE); + char_memitemdata_to_sql(p->items, MAX_STORAGE, account_id, TABLE_STORAGE); return 0; } @@ -38,7 +38,7 @@ int storage_fromsql(int account_id, struct storage_data* p) StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", schema_config.storage_db, account_id); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); @@ -74,7 +74,7 @@ int storage_fromsql(int account_id, struct storage_data* p) /// Save guild_storage data to sql int guild_storage_tosql(int guild_id, struct guild_storage* p) { - memitemdata_to_sql(p->items, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE); + char_memitemdata_to_sql(p->items, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE); ShowInfo ("guild storage save to DB - guild: %d\n", guild_id); return 0; } @@ -94,7 +94,7 @@ int guild_storage_fromsql(int guild_id, struct guild_storage* p) StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`bound`,`unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", schema_config.guild_storage_db, guild_id); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); @@ -142,13 +142,13 @@ void inter_storage_sql_final(void) // Delete char storage int inter_storage_delete(int account_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", schema_config.storage_db, account_id) ) Sql_ShowDebug(sql_handle); return 0; } int inter_guild_storage_delete(int guild_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_storage_db, guild_id) ) Sql_ShowDebug(sql_handle); return 0; } @@ -158,7 +158,7 @@ int inter_guild_storage_delete(int guild_id) int mapif_load_guild_storage(int fd,int account_id,int guild_id, char flag) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) > 0 ) {// guild exists @@ -218,7 +218,7 @@ int mapif_parse_SaveGuildStorage(int fd) } else { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) > 0 ) {// guild exists @@ -262,7 +262,7 @@ int mapif_parse_itembound_retrieve(int fd) StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",inventory_db,char_id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'",schema_config.inventory_db,char_id); stmt = SqlStmt_Malloc(sql_handle); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) @@ -304,7 +304,7 @@ int mapif_parse_itembound_retrieve(int fd) //First we delete the character's items StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE",inventory_db); + StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE",schema_config.inventory_db); for(j=0; jreg_num; ++i ) { r = ®->reg[i]; @@ -590,11 +592,11 @@ int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int typ switch( type ) { case 3: //char reg - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'", schema_config.reg_db, char_id) ) Sql_ShowDebug(sql_handle); break; case 2: //account reg - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'", schema_config.reg_db, account_id) ) Sql_ShowDebug(sql_handle); break; case 1: //account2 reg @@ -669,7 +671,7 @@ static int inter_config_read(const char* cfgName) else if(!strcmpi(w1,"party_share_level")) party_share_level = (unsigned int)atof(w2); else if(!strcmpi(w1,"log_inter")) - log_inter = atoi(w2); + charserv_config.log_inter = atoi(w2); else if(!strcmpi(w1,"import")) inter_config_read(w2); } @@ -692,7 +694,7 @@ int inter_log(char* fmt, ...) va_end(ap); Sql_EscapeStringLen(sql_handle, esc_str, str, strnlen(str, sizeof(str))); - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')", interlog_db, esc_str) ) + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')", schema_config.interlog_db, esc_str) ) Sql_ShowDebug(sql_handle); return 0; @@ -769,8 +771,7 @@ int inter_mapif_init(int fd) int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd) { unsigned char *buf = (unsigned char*)aMalloc((len)*sizeof(unsigned char)); - if (buf == NULL) return 1; - + WBUFW(buf,0) = 0x3800; WBUFW(buf,2) = len; WBUFL(buf,4) = fontColor; @@ -779,7 +780,7 @@ int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short WBUFW(buf,12) = fontAlign; WBUFW(buf,14) = fontY; memcpy(WBUFP(buf,16), mes, len - 16); - mapif_sendallwos(sfd, buf, len); + chmapif_sendallwos(sfd, buf, len); aFree(buf); return 0; @@ -797,7 +798,7 @@ int mapif_wis_message(struct WisData *wd) memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH); memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH); memcpy(WBUFP(buf,56), wd->msg, wd->len); - wd->count = mapif_sendall(buf,WBUFW(buf,2)); + wd->count = chmapif_sendall(buf,WBUFW(buf,2)); return 0; } @@ -810,7 +811,7 @@ int mapif_wis_end(struct WisData *wd, int flag) WBUFW(buf, 0)=0x3802; memcpy(WBUFP(buf, 2),wd->src,24); WBUFB(buf,26)=flag; - mapif_send(wd->fd,buf,27); + chmapif_send(wd->fd,buf,27); return 0; } @@ -818,7 +819,7 @@ int mapif_wis_end(struct WisData *wd, int flag) static void mapif_account_reg(int fd, unsigned char *src) { WBUFW(src,0)=0x3804; //NOTE: writing to RFIFO - mapif_sendallwos(fd, src, WBUFW(src,2)); + chmapif_sendallwos(fd, src, WBUFW(src,2)); } // Send the requested account_reg @@ -935,7 +936,7 @@ int mapif_parse_WisRequest(int fd) safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", schema_config.char_db, esc_name) ) Sql_ShowDebug(sql_handle); // search if character exists before to ask all map-servers @@ -945,7 +946,7 @@ int mapif_parse_WisRequest(int fd) WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - mapif_send(fd, buf, 27); + chmapif_send(fd, buf, 27); } else {// Character exists. So, ask all map-servers @@ -960,7 +961,7 @@ int mapif_parse_WisRequest(int fd) WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - mapif_send(fd, buf, 27); + chmapif_send(fd, buf, 27); } else { @@ -1014,7 +1015,7 @@ int mapif_parse_WisToGM(int fd) memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); WBUFW(buf, 0) = 0x3803; - mapif_sendall(buf, RFIFOW(fd,2)); + chmapif_sendall(buf, RFIFOW(fd,2)); return 0; } @@ -1034,7 +1035,7 @@ int mapif_parse_Registry(int fd) max = ACCOUNT_REG_NUM; break; case 1: //Account2 registry, must be sent over to login server. - return save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4); + return chlogif_save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4); default: return 1; } @@ -1061,7 +1062,7 @@ int mapif_parse_RegistryRequest(int fd) //Load Account Registry if (RFIFOB(fd,11)) mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2); //Ask Login Server for Account2 values. - if (RFIFOB(fd,10)) request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6)); + if (RFIFOB(fd,10)) chlogif_request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6)); return 1; } @@ -1089,15 +1090,15 @@ int mapif_parse_NameChangeRequest(int fd) name = (char*)RFIFOP(fd,11); // Check Authorised letters/symbols in the name - if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised + if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised for (i = 0; i < NAME_LENGTH && name[i]; i++) - if (strchr(char_name_letters, name[i]) == NULL) { + if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) { mapif_namechange_ack(fd, account_id, char_id, type, 0, name); return 0; } - } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden + } else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden for (i = 0; i < NAME_LENGTH && name[i]; i++) - if (strchr(char_name_letters, name[i]) != NULL) { + if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) { mapif_namechange_ack(fd, account_id, char_id, type, 0, name); return 0; } diff --git a/src/common/cli.c b/src/common/cli.c index 66dc71a9bb..76049e7f3d 100644 --- a/src/common/cli.c +++ b/src/common/cli.c @@ -1,3 +1,12 @@ +/** + * @file cli.c + * Module purpose is to handle the console (cli=console line input) while the servers launch and run. + * This contains functions common to all servers, but then dispatches them to a specific parser on each server. + * Licensed under GNU GPL. + * For more information, see LICENCE in the main folder. + * @author rAthena Dev Team + */ + #include #include #include @@ -29,14 +38,16 @@ char* LOGIN_CONF_NAME; char* LAN_CONF_NAME; //char-login char* MSG_CONF_NAME_EN; //all -/* - * Function to check if specified option have an argument follow it - * return +/** + * Function to check if the specified option has an argument following it. + * @param option: actual args string + * @param i: index of current args + * @param argc: arguments count + * @return * false : no other args found, and throw a warning * true : something following us */ -bool opt_has_next_value(const char* option, int i, int argc) -{ +bool opt_has_next_value(const char* option, int i, int argc){ if (i >= argc - 1) { ShowWarning("Missing value for option '%s'.\n", option); return false; @@ -45,11 +56,12 @@ bool opt_has_next_value(const char* option, int i, int argc) return true; } -/* - * Display some info about emulator such as +/** + * Display some information about the emulator, such as: * svn version - * website/forum adresse + * website/forum address * irc hangout + * @param do_exit: terminate execution ? */ void display_versionscreen(bool do_exit) { @@ -68,16 +80,18 @@ void display_versionscreen(bool do_exit) exit(EXIT_SUCCESS); } -/* - * Read the option specify in command line - * and assign the confs used by the different server - * exit on failure or return true +/** + * Read the option specified in the command line + * and assign the confs used by the different servers. + * @TODO remove and place into csnlif of different serv + * @param argc: arguments count (from main) + * @param argv: arguments values (from main) + * @return true or exit on failure */ -int cli_get_options(int argc, char ** argv) -{ - int i = 0; - for (i = 1; i < argc; i++) { - const char* arg = argv[i]; +int cli_get_options(int argc, char ** argv) { + int i = 0; + for (i = 1; i < argc; i++) { + const char* arg = argv[i]; if (arg[0] != '-' && (arg[0] != '/' || arg[1] == '-')) {// -, -- and / ShowError("Unknown option '%s'.\n", argv[i]); @@ -163,17 +177,29 @@ int cli_get_options(int argc, char ** argv) return 1; } -int cli_hasevent(){ +/** + * Detect if the console has some input to be read. + * @return true if event, else false + */ +bool cli_hasevent(){ #ifdef WIN32 - return _kbhit(); + return (_kbhit()!=0); #else struct pollfd fds; fds.fd = 0; /* this is STDIN */ fds.events = POLLIN; - return poll(&fds, 1, 0); + return (poll(&fds, 1, 0)>0); #endif } +/** + * Timered function to check if the console has a new event to be read. + * @param tid: timer id + * @param tick: tick of execution + * @param id: user account id + * @param data: unused + * @return 0 + */ int parse_console_timer(int tid, unsigned int tick, int id, intptr_t data) { char buf[MAX_CONSOLE_IN]; //max cmd atm is 63+63+63+3+3 diff --git a/src/common/cli.h b/src/common/cli.h index c4cca4ae41..d3f48683bc 100644 --- a/src/common/cli.h +++ b/src/common/cli.h @@ -1,8 +1,10 @@ -/* - * File: cli.h - * Author: lighta - * - * Created on February 21, 2013, 6:15 PM +/** + * @file cli.h + * Module purpose is to handle the console (cli=console line input) while the servers launch and run. + * This contains functions common to all servers, but then dispatches them to a specific parser on each server. + * Licensed under GNU GPL. + * For more information, see LICENCE in the main folder. + * @author rAthena Dev Team */ #ifndef CLI_H @@ -32,6 +34,8 @@ extern "C" { extern char* MSG_CONF_NAME_EN; //all extern void display_helpscreen(bool exit); +void display_versionscreen(bool do_exit); +bool opt_has_next_value(const char* option, int i, int argc); int cli_get_options(int argc, char ** argv); int parse_console_timer(int tid, unsigned int tick, int id, intptr_t data); extern int parse_console(const char* buf); //particular for each serv diff --git a/src/common/evdp.h b/src/common/evdp.h index bc34546868..ff64d4d6b2 100644 --- a/src/common/evdp.h +++ b/src/common/evdp.h @@ -136,7 +136,7 @@ bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep); * the connection must be already added (as client or listener) * * - * @return sucess indicator + * @return success indicator */ bool evdp_writable_add(int32 fd, EVDP_DATA *ep); diff --git a/src/common/malloc.c b/src/common/malloc.c index 23580e9316..4d75e34528 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -115,6 +115,8 @@ void aFree_(void *p, const char *file, int line, const char *func) // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p); if (p) FREE(p, file, line, func); + + p = NULL; } diff --git a/src/common/mmo.h b/src/common/mmo.h index ef81c40a8e..560b41f65f 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -90,6 +90,7 @@ //For character names, title names, guilds, maps, etc. //Includes null-terminator as it is the length of the array. #define NAME_LENGTH (23 + 1) +#define PASSWD_LENGTH (32+1) //For item names, which tend to have much longer names. #define ITEM_NAME_LENGTH 50 //For Map Names, which the client considers to be 16 in length including the .gat extension diff --git a/src/common/mutex.c b/src/common/mutex.c index 251c727c60..6b4f551197 100644 --- a/src/common/mutex.c +++ b/src/common/mutex.c @@ -90,7 +90,7 @@ void ramutex_lock( ramutex m ){ bool ramutex_trylock( ramutex m ){ #ifdef WIN32 - if(TryEnterCriticalSection(&m->hMutex) != FALSE) + if(TryEnterCriticalSection(&m->hMutex) == TRUE) return true; return false; diff --git a/src/common/timer.h b/src/common/timer.h index 3708558345..c29e7b10b3 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -51,6 +51,7 @@ int add_timer_func_list(TimerFunc func, char* name); unsigned long get_uptime(void); +//transform a timestamp to string const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format); void split_time(int time, int* year, int* month, int* day, int* hour, int* minute, int* second); double solve_time(char* modif_p); From 06f8917d750e99fff6d28d340c4b64184f1c4eee Mon Sep 17 00:00:00 2001 From: lighta Date: Mon, 28 Apr 2014 20:52:30 -0400 Subject: [PATCH 2/7] Cleaning few thing while bored in class... -TODO harmonize while(next) packet parsing --- src/char/Makefile.in | 2 +- src/char/char.c | 2016 +---------------------------------------- src/char/char.h | 8 +- src/char/char_clif.c | 391 ++++---- src/char/char_clif.h | 1 + src/char/char_logif.c | 118 ++- src/char/char_logif.h | 10 + src/char/char_mapif.c | 644 +++++++++---- src/char/char_mapif.h | 7 + 9 files changed, 789 insertions(+), 2408 deletions(-) diff --git a/src/char/Makefile.in b/src/char/Makefile.in index b180880274..44e4812209 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -15,7 +15,7 @@ LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_H = ../common/sql.h -CHAR_OBJ = $(shell ls *.c | sed -e "s/.c/.o/g") +CHAR_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g") #CHAR_OBJ = char.o char_clif.o char_logif.o char_mapif.o char_cnslif.o \ inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o int_mail.o int_auction.o int_quest.o int_mercenary.o int_elemental.o CHAR_SQL_OBJ = $(CHAR_OBJ:%=obj_sql/%) diff --git a/src/char/char.c b/src/char/char.c index f158adaeb0..1acade574e 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -80,8 +80,6 @@ int loginif_reqvipdata(uint32 aid, uint8 type, int add_vip_time, int mapfd); int loginif_parse_vipack(int fd); // Addon system - -void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to ); void moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ); int loginif_BankingReq(int32 account_id, int8 type, int32 data); @@ -104,9 +102,6 @@ DBMap* char_get_authdb() { return auth_db; } DBMap* char_get_onlinedb() { return online_char_db; } DBMap* char_get_chardb() { return char_db_; } -int loginif_isconnected(); -#define loginif_check(a) { if(!loginif_isconnected()) return a; } - /** * @see DBCreateData */ @@ -273,7 +268,7 @@ void char_set_all_offline(int id){ ShowNotice("Sending users of map-server %d offline.\n",id); online_char_db->foreach(online_char_db,char_db_kickoffline,id); - if (id >= 0 || !loginif_isconnected()) + if (id >= 0 || !chlogif_isconnected()) return; //Tell login-server to also mark all our characters as offline. chlogif_send_setallaccoffline(login_fd); @@ -1846,10 +1841,6 @@ void mmo_char_send099d(int fd, struct char_session_data *sd) { WFIFOSET(fd,WFIFOW(fd,2)); } -//struct PACKET_CH_CHARLIST_REQ { 0x0 short PacketType} -void char_parse_req_charlist(int fd, struct char_session_data* sd){ - mmo_char_send099d(fd,sd); -} //---------------------------------------- // Function to send characters to a player @@ -2030,122 +2021,7 @@ void char_auth_ok(int fd, struct char_session_data *sd) { int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); void mapif_server_reset(int id); -/** - * Send to login-serv the request of banking operation from map - * HA 0x2740L B L - * @param account_id - * @param type : 0 = select, 1 = update - * @param data - * @return - */ -int loginif_BankingReq(int32 account_id, int8 type, int32 data){ - loginif_check(-1); - WFIFOHEAD(login_fd,11); - WFIFOW(login_fd,0) = 0x2740; - WFIFOL(login_fd,2) = account_id; - WFIFOB(login_fd,6) = type; - WFIFOL(login_fd,7) = data; - WFIFOSET(login_fd,11); - return 0; -} - -/* - * Received the banking data from login and transmit it to all map-serv - * AH 0x2741L L B - * HZ 0x2b29 L L - */ -int loginif_parse_BankingAck(int fd){ - if (RFIFOREST(fd) < 11) - return 0; - else { - uint32 aid = RFIFOL(fd,2); - int32 bank_vault = RFIFOL(fd,6); - char not_fw = RFIFOB(fd,10); - RFIFOSKIP(fd,11); - - if(not_fw==0) mapif_BankingAck(aid, bank_vault); - } - return 1; -} - -//HZ 0x2b29 L L -int mapif_BankingAck(int32 account_id, int32 bank_vault){ - unsigned char buf[11]; - WBUFW(buf,0) = 0x2b29; - WBUFL(buf,2) = account_id; - WBUFL(buf,6) = bank_vault; - chmapif_sendall(buf, 10); //inform all maps-attached - return 1; -} - -/* - * HZ 0x2b2b - * Transmist vip data to mapserv - */ -int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid) { -#ifdef VIP_ENABLE - uint8 buf[16]; - WBUFW(buf,0) = 0x2b2b; - WBUFL(buf,2) = aid; - WBUFL(buf,6) = vip_time; - WBUFB(buf,10) = isvip; - WBUFB(buf,11) = isgm; - WBUFL(buf,12) = groupid; - chmapif_send(mapfd,buf,16); // inform the mapserv back -#endif - return 0; -} - -/** - * HZ 0x2b2b - * Request vip data from loginserv - * @param aid : account_id to request the vip data - * @param type : &2 define new duration, &1 load info - * @param add_vip_time : tick to add to vip timestamp - * @param mapfd: link to mapserv for ack - * @return 0 if success - */ -int loginif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd) { - loginif_check(-1); -#ifdef VIP_ENABLE - WFIFOHEAD(login_fd,15); - WFIFOW(login_fd,0) = 0x2742; - WFIFOL(login_fd,2) = aid; //aid - WFIFOB(login_fd,6) = type; //type - WFIFOL(login_fd,7) = timediff; //req_inc_duration - WFIFOL(login_fd,11) = mapfd; //req_inc_duration - WFIFOSET(login_fd,15); -#endif - return 0; -} - -/* - * AH 0x2743 - * We received the info from login-serv, transmit it to map - */ -int loginif_parse_vipack(int fd) { -#ifdef VIP_ENABLE - if (RFIFOREST(fd) < 20) - return 0; - else { - uint32 aid = RFIFOL(fd,2); //aid - uint32 vip_time = RFIFOL(fd,6); //vip_time - uint8 isvip = RFIFOB(fd,10); //isvip - uint32 groupid = RFIFOL(fd,11); //new group id - uint8 isgm = RFIFOB(fd,15); //isgm - int mapfd = RFIFOL(fd,16); //link to mapserv for ack - RFIFOSKIP(fd,20); - mapif_vipack(mapfd,aid,vip_time,isvip,isgm,groupid); - } -#endif - return 1; -} - - -int loginif_isconnected(){ - return (login_fd > 0 && session[login_fd] && !session[login_fd]->flag.eof); -} /// Resets all the data. void loginif_reset(void) @@ -2217,7 +2093,7 @@ void do_final_loginif(void) } } -int request_accreg2(int account_id, int char_id) +int char_request_accreg2(int account_id, int char_id) { loginif_check(0); @@ -2230,7 +2106,7 @@ int request_accreg2(int account_id, int char_id) } //Send packet forward to login-server for account saving -int save_accreg2(unsigned char* buf, int len) +int char_save_accreg2(unsigned char* buf, int len) { loginif_check(0); @@ -2337,16 +2213,6 @@ int char_send_fame_list(int fd) return 0; } -void char_update_fame_list(int type, int index, int fame) -{ - unsigned char buf[8]; - WBUFW(buf,0) = 0x2b22; - WBUFB(buf,2) = type; - WBUFB(buf,3) = index; - WBUFL(buf,4) = fame; - chmapif_sendall(buf, 8); -} - //Loads a character's name and stores it in the buffer given (must be NAME_LENGTH in size) //Returns 1 on found, 0 on not found (buffer is filled with Unknown char name) int char_loadName(int char_id, char* name){ @@ -2423,926 +2289,7 @@ void mapif_on_disconnect(int id) mapif_server_reset(id); } -int mapif_parse_reqcharban(int fd){ - if (RFIFOREST(fd) < 10+NAME_LENGTH) - return 0; - else { - //int aid = RFIFOL(fd,2); aid of player who as requested the ban - int timediff = RFIFOL(fd,6); - const char* name = (char*)RFIFOP(fd,10); // name of the target character - RFIFOSKIP(fd,10+NAME_LENGTH); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, name) ) - Sql_ShowDebug(sql_handle); - else if( Sql_NumRows(sql_handle) == 0 ){ - return -1; // 1-player not found - } - else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){ - Sql_ShowDebug(sql_handle); - Sql_FreeResult(sql_handle); - return -1; - } else { - int t_cid=0,t_aid=0; - char* data; - time_t unban_time; - time_t now = time(NULL); - SqlStmt* stmt = SqlStmt_Malloc(sql_handle); - - Sql_GetData(sql_handle, 0, &data, NULL); t_aid = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); t_cid = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); unban_time = atol(data); - Sql_FreeResult(sql_handle); - - if(timediff<0 && unban_time==0) return 0; //attemp to reduce time of a non banned account ?!? - else if(unban_time now ) { - unsigned char buf[11]; - WBUFW(buf,0) = 0x2b14; - WBUFL(buf,2) = t_cid; - WBUFB(buf,6) = 2; - WBUFL(buf,7) = (unsigned int)unban_time; - chmapif_sendall(buf, 11); - // disconnect player if online on char-server - disconnect_player(t_aid); - } - } - } - return 0; -} - -int mapif_parse_reqcharunban(int fd){ - if (RFIFOREST(fd) < 6) - return 0; - else { - int cid = RFIFOL(fd,2); - RFIFOSKIP(fd,6); - - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time` = '0' WHERE `char_id` = '%d' LIMIT 1", schema_config.char_db, cid) ) { - Sql_ShowDebug(sql_handle); - return -1; - } - } - return 0; -} - -/** - * Request from map-server to change an account's status (will just be forwarded to login server) - * ZH 2b0e L 24B W L - * @param fd: link to mapserv - */ -int mapif_parse_req_alter_acc(int fd) { - if (RFIFOREST(fd) < 44) - return 0; - else { - int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline, 4-current group level > VIP group level - char esc_name[NAME_LENGTH*2+1]; - char answer = true; - - int aid = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request) - const char* name = (char*)RFIFOP(fd,6); // name of the target character - int operation = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5-changesex, 6-vip, 7-bank - int32 timediff = RFIFOL(fd,32); - int val1 = RFIFOL(fd,36); - int val2 = RFIFOL(fd,40); - RFIFOSKIP(fd,44); - - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, esc_name) ) - Sql_ShowDebug(sql_handle); - else if( Sql_NumRows(sql_handle) == 0 ) { - result = 1; // 1-player not found - } - else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { - Sql_ShowDebug(sql_handle); - result = 1; - } else { - char name[NAME_LENGTH]; - int account_id; - char* data; - - Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); - Sql_FreeResult(sql_handle); - - if(!loginif_isconnected()) - result = 3; // 3-login-server offline - //FIXME: need to move this check to login server [ultramage] - // if( acc != -1 && isGM(acc) < isGM(account_id) ) - // result = 2; // 2-gm level too low - else { - switch( operation ) { - case 1: // block - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = account_id; - WFIFOL(login_fd,6) = 5; // new account status - WFIFOSET(login_fd,10); - break; - case 2: // ban - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd, 0) = 0x2725; - WFIFOL(login_fd, 2) = account_id; - WFIFOL(login_fd, 6) = timediff; - WFIFOSET(login_fd,10); - break; - case 3: // unblock - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = account_id; - WFIFOL(login_fd,6) = 0; // new account status - WFIFOSET(login_fd,10); - break; - case 4: // unban - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x272a; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); - break; - case 5: // changesex - answer = false; - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x2727; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); - break; - case 6: - answer = (val1&4); // vip_req val1=type, &1 login send return, &2 update timestamp, &4 map send answer - loginif_reqvipdata(account_id, val1, timediff, fd); - break; - case 7: - answer = (val1&1); //val&1 request answer, val1&2 save data - loginif_BankingReq(aid, val1, val2); - break; - } //end switch operation - } //login is connected - } - - // send answer if a player asks, not if the server asks - if( aid != -1 && answer) { // Don't send answer for changesex - WFIFOHEAD(fd,34); - WFIFOW(fd, 0) = 0x2b0f; - WFIFOL(fd, 2) = aid; - safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); - WFIFOW(fd,30) = operation; - WFIFOW(fd,32) = result; - WFIFOSET(fd,34); - } - } - return 1; -} - -int parse_frommap(int fd) -{ - int i, j; - int id; - - ARR_FIND( 0, ARRAYLENGTH(map_server), id, map_server[id].fd == fd ); - if( id == ARRAYLENGTH(map_server) ) - {// not a map server - ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd); - do_close(fd); - return 0; - } - if( session[fd]->flag.eof ) - { - do_close(fd); - map_server[id].fd = -1; - mapif_on_disconnect(id); - return 0; - } - - while(RFIFOREST(fd) >= 2){ - switch(RFIFOW(fd,0)){ - - case 0x2afa: // Receiving map names list from the map-server - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - - memset(map_server[id].map, 0, sizeof(map_server[id].map)); - j = 0; - for(i = 4; i < RFIFOW(fd,2); i += 4) { - map_server[id].map[j] = RFIFOW(fd,i); - j++; - } - - ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", - id, j, CONVIP(map_server[id].ip), map_server[id].port); - ShowStatus("Map-server %d loading complete.\n", id); - - // send name for wisp to player - WFIFOHEAD(fd, 3 + NAME_LENGTH); - WFIFOW(fd,0) = 0x2afb; - WFIFOB(fd,2) = 0; - memcpy(WFIFOP(fd,3), charserv_config.wisp_server_name, NAME_LENGTH); - WFIFOSET(fd,3+NAME_LENGTH); - - char_send_fame_list(fd); //Send fame list. - - { - int x; - if (j == 0) { - ShowWarning("Map-server %d has NO maps.\n", id); - } else { - unsigned char buf[16384]; - - // Transmitting maps information to the other map-servers - WBUFW(buf,0) = 0x2b04; - WBUFW(buf,2) = j * 4 + 10; - WBUFL(buf,4) = htonl(map_server[id].ip); - WBUFW(buf,8) = htons(map_server[id].port); - memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4); - chmapif_sendallwos(fd, buf, WBUFW(buf,2)); - } - // Transmitting the maps of the other map-servers to the new map-server - for(x = 0; x < ARRAYLENGTH(map_server); x++) { - if (map_server[x].fd > 0 && x != id) { - WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map)); - WFIFOW(fd,0) = 0x2b04; - WFIFOL(fd,4) = htonl(map_server[x].ip); - WFIFOW(fd,8) = htons(map_server[x].port); - j = 0; - for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++) - if (map_server[x].map[i]) - WFIFOW(fd,10+(j++)*4) = map_server[x].map[i]; - if (j > 0) { - WFIFOW(fd,2) = j * 4 + 10; - WFIFOSET(fd,WFIFOW(fd,2)); - } - } - } - } - RFIFOSKIP(fd,RFIFOW(fd,2)); - break; - - case 0x2afc: //Packet command is now used for sc_data request. [Skotlex] - if (RFIFOREST(fd) < 10) - return 0; - { -#ifdef ENABLE_SC_SAVING - int aid, cid; - aid = RFIFOL(fd,2); - cid = RFIFOL(fd,6); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", - schema_config.scdata_db, aid, cid) ) - { - Sql_ShowDebug(sql_handle); - break; - } - if( Sql_NumRows(sql_handle) > 0 ) - { - struct status_change_data scdata; - int count; - char* data; - - WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); - WFIFOW(fd,0) = 0x2b1d; - WFIFOL(fd,4) = aid; - WFIFOL(fd,8) = cid; - for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) - { - Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); - memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); - } - if (count >= 50) - ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); - if (count > 0) - { - WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); - WFIFOW(fd,12) = count; - WFIFOSET(fd,WFIFOW(fd,2)); - } - } - Sql_FreeResult(sql_handle); -#endif - RFIFOSKIP(fd, 10); - } - break; - - case 0x2b0a: //Request skillcooldown data - if (RFIFOREST(fd) < 10) - return 0; - { - int aid, cid; - aid = RFIFOL(fd,2); - cid = RFIFOL(fd,6); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT skill, tick FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", - schema_config.skillcooldown_db, aid, cid) ) - { - Sql_ShowDebug(sql_handle); - break; - } - if( Sql_NumRows(sql_handle) > 0 ) - { - int count; - char* data; - struct skill_cooldown_data scd; - - WFIFOHEAD(fd,14 + MAX_SKILLCOOLDOWN * sizeof(struct skill_cooldown_data)); - WFIFOW(fd,0) = 0x2b0b; - WFIFOL(fd,4) = aid; - WFIFOL(fd,8) = cid; - for( count = 0; count < MAX_SKILLCOOLDOWN && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) - { - Sql_GetData(sql_handle, 0, &data, NULL); scd.skill_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); scd.tick = atoi(data); - memcpy(WFIFOP(fd,14+count*sizeof(struct skill_cooldown_data)), &scd, sizeof(struct skill_cooldown_data)); - } - if( count >= MAX_SKILLCOOLDOWN ) - ShowWarning("Too many skillcooldowns for %d:%d, some of them were not loaded.\n", aid, cid); - if( count > 0 ) - { - WFIFOW(fd,2) = 14 + count * sizeof(struct skill_cooldown_data); - WFIFOW(fd,12) = count; - WFIFOSET(fd,WFIFOW(fd,2)); - //Clear the data once loaded. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.skillcooldown_db, aid, cid) ) - Sql_ShowDebug(sql_handle); - } - } - Sql_FreeResult(sql_handle); - RFIFOSKIP(fd, 10); - } - break; - case 0x2afe: //set MAP user count - if (RFIFOREST(fd) < 4) - return 0; - if (RFIFOW(fd,2) != map_server[id].users) { - map_server[id].users = RFIFOW(fd,2); - ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id); - } - RFIFOSKIP(fd, 4); - break; - - case 0x2aff: //set MAP users - if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - { - //TODO: When data mismatches memory, update guild/party online/offline states. - int aid, cid; - struct online_char_data* character; - - map_server[id].users = RFIFOW(fd,4); - online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown' - for(i = 0; i < map_server[id].users; i++) { - aid = RFIFOL(fd,6+i*8); - cid = RFIFOL(fd,6+i*8+4); - character = idb_ensure(online_char_db, aid, char_create_online_data); - if( character->server > -1 && character->server != id ) - { - ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", - character->account_id, character->char_id, character->server, id, aid, cid); - mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); - } - character->server = id; - character->char_id = cid; - } - //If any chars remain in -2, they will be cleaned in the cleanup timer. - RFIFOSKIP(fd,RFIFOW(fd,2)); - } - break; - - case 0x2b01: // Receive character data from map-server for saving - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - { - int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2); - struct online_char_data* character; - - if (size - 13 != sizeof(struct mmo_charstatus)) - { - ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus)); - RFIFOSKIP(fd,size); - break; - } - //Check account only if this ain't final save. Final-save goes through because of the char-map reconnect - if (RFIFOB(fd,12) || RFIFOB(fd,13) || ( - (character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL && - character->char_id == cid)) - { - struct mmo_charstatus char_dat; - memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus)); - mmo_char_tosql(cid, &char_dat); - } else { //This may be valid on char-server reconnection, when re-sending characters that already logged off. - ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid); - set_char_online(id, cid, aid); - } - - if (RFIFOB(fd,12)) - { //Flag, set character offline after saving. [Skotlex] - set_char_offline(cid, aid); - WFIFOHEAD(fd,10); - WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save. - WFIFOL(fd,2) = aid; - WFIFOL(fd,6) = cid; - WFIFOSET(fd,10); - } - RFIFOSKIP(fd,size); - } - break; - - case 0x2b02: // req char selection - if( RFIFOREST(fd) < 19 ) - return 0; - else{ - int account_id = RFIFOL(fd,2); - uint32 login_id1 = RFIFOL(fd,6); - uint32 login_id2 = RFIFOL(fd,10); - uint32 ip = RFIFOL(fd,14); - uint8 version = RFIFOB(fd,18); - RFIFOSKIP(fd,19); - - if( runflag != CHARSERVER_ST_RUNNING ){ - WFIFOHEAD(fd,7); - WFIFOW(fd,0) = 0x2b03; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 0;// not ok - WFIFOSET(fd,7); - }else{ - struct auth_node* node; - - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = account_id; - node->char_id = 0; - node->login_id1 = login_id1; - node->login_id2 = login_id2; - //node->sex = 0; - node->ip = ntohl(ip); - node->version = version; //upd version for mapserv - //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) - //node->gmlevel = 0; - idb_put(auth_db, account_id, node); - - //Set char to "@ char select" in online db [Kevin] - set_char_charselect(account_id); - { - struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id); - - if( character != NULL ){ - character->pincode_success = true; - } - } - - WFIFOHEAD(fd,7); - WFIFOW(fd,0) = 0x2b03; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 1;// ok - WFIFOSET(fd,7); - } - } - break; - - case 0x2b05: // request "change map server" - if (RFIFOREST(fd) < 39) - return 0; - { - int map_id, map_fd = -1; - struct mmo_charstatus* char_data; - struct mmo_charstatus char_dat; - - map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. - if (map_id >= 0) - map_fd = map_server[map_id].fd; - //Char should just had been saved before this packet, so this should be safe. [Skotlex] - char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); - if (char_data == NULL) { //Really shouldn't happen. - mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); - char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); - } - - if( runflag == CHARSERVER_ST_RUNNING && - session_isActive(map_fd) && - char_data ) - { //Send the map server the auth of this player. - struct online_char_data* data; - struct auth_node* node; - - //Update the "last map" as this is where the player must be spawned on the new map server. - char_data->last_point.map = RFIFOW(fd,18); - char_data->last_point.x = RFIFOW(fd,20); - char_data->last_point.y = RFIFOW(fd,22); - char_data->sex = RFIFOB(fd,30); - - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = RFIFOL(fd,2); - node->char_id = RFIFOL(fd,14); - node->login_id1 = RFIFOL(fd,6); - node->login_id2 = RFIFOL(fd,10); - node->sex = RFIFOB(fd,30); - node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing) - node->ip = ntohl(RFIFOL(fd,31)); - node->group_id = RFIFOL(fd,35); - node->changing_mapservers = 1; - idb_put(auth_db, RFIFOL(fd,2), node); - - data = idb_ensure(online_char_db, RFIFOL(fd,2), char_create_online_data); - data->char_id = char_data->char_id; - data->server = map_id; //Update server where char is. - - //Reply with an ack. - WFIFOHEAD(fd,30); - WFIFOW(fd,0) = 0x2b06; - memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); - WFIFOSET(fd,30); - } else { //Reply with nak - WFIFOHEAD(fd,30); - WFIFOW(fd,0) = 0x2b06; - memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); - WFIFOL(fd,6) = 0; //Set login1 to 0. - WFIFOSET(fd,30); - } - RFIFOSKIP(fd,39); - } - break; - - case 0x2b07: // Remove RFIFOL(fd,6) (friend_id) from RFIFOL(fd,2) (char_id) friend list [Ind] - if (RFIFOREST(fd) < 10) - return 0; - { - int char_id, friend_id; - char_id = RFIFOL(fd,2); - friend_id = RFIFOL(fd,6); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1", - schema_config.friend_db, char_id, friend_id) ) { - Sql_ShowDebug(sql_handle); - break; - } - RFIFOSKIP(fd,10); - } - break; - - case 0x2b08: // char name request - if (RFIFOREST(fd) < 6) - return 0; - - WFIFOHEAD(fd,30); - WFIFOW(fd,0) = 0x2b09; - WFIFOL(fd,2) = RFIFOL(fd,2); - char_loadName((int)RFIFOL(fd,2), (char*)WFIFOP(fd,6)); - WFIFOSET(fd,30); - - RFIFOSKIP(fd,6); - break; - - case 0x2b0c: // Map server send information to change an email of an account -> login-server - if (RFIFOREST(fd) < 86) - return 0; - if (!loginif_isconnected()) { // don't send request if no login-server or eof - WFIFOHEAD(login_fd,86); - memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 .L .40B .40B - WFIFOW(login_fd,0) = 0x2722; - WFIFOSET(login_fd,86); - } - RFIFOSKIP(fd, 86); - break; - - case 0x2b0e: mapif_parse_req_alter_acc(fd); break; - - case 0x2b10: // Update and send fame ranking list - if (RFIFOREST(fd) < 11) - return 0; - { - int cid = RFIFOL(fd, 2); - int fame = RFIFOL(fd, 6); - char type = RFIFOB(fd, 10); - int size; - struct fame_list* list; - int player_pos; - int fame_pos; - - switch(type) - { - case 1: size = fame_list_size_smith; list = smith_fame_list; break; - case 2: size = fame_list_size_chemist; list = chemist_fame_list; break; - case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; - default: size = 0; list = NULL; break; - } - - ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player - ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be - - if( player_pos == size && fame_pos == size ) - ;// not on list and not enough fame to get on it - else if( fame_pos == player_pos ) - {// same position - list[player_pos].fame = fame; - char_update_fame_list(type, player_pos, fame); - } - else - {// move in the list - if( player_pos == size ) - {// new ranker - not in the list - ARR_MOVE(size - 1, fame_pos, list, struct fame_list); - list[fame_pos].id = cid; - list[fame_pos].fame = fame; - char_loadName(cid, list[fame_pos].name); - } - else - {// already in the list - if( fame_pos == size ) - --fame_pos;// move to the end of the list - ARR_MOVE(player_pos, fame_pos, list, struct fame_list); - list[fame_pos].fame = fame; - } - char_send_fame_list(-1); - } - - RFIFOSKIP(fd,11); - } - break; - - // Divorce chars - case 0x2b11: - if( RFIFOREST(fd) < 10 ) - return 0; - divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6)); - RFIFOSKIP(fd,10); - break; - - case 0x2b16: // Receive rates [Wizputer] - if( RFIFOREST(fd) < 14 ) - return 0; - { - char esc_server_name[sizeof(charserv_config.server_name)*2+1]; - - Sql_EscapeString(sql_handle, esc_server_name, charserv_config.server_name); - - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d'", - schema_config.ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) ) - Sql_ShowDebug(sql_handle); - RFIFOSKIP(fd,14); - } - break; - - case 0x2b17: // Character disconnected set online 0 [Wizputer] - if (RFIFOREST(fd) < 6) - return 0; - set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); - RFIFOSKIP(fd,10); - break; - - case 0x2b18: // Reset all chars to offline [Wizputer] - set_all_offline(id); - RFIFOSKIP(fd,2); - break; - - case 0x2b19: // Character set online [Wizputer] - if (RFIFOREST(fd) < 10) - return 0; - set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6)); - RFIFOSKIP(fd,10); - break; - - case 0x2b1a: // Build and send fame ranking lists [DracoRPG] - if (RFIFOREST(fd) < 2) - return 0; - char_read_fame_list(); - char_send_fame_list(-1); - RFIFOSKIP(fd,2); - break; - - case 0x2b1c: //Request to save status change data. [Skotlex] - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - { -#ifdef ENABLE_SC_SAVING - int count, aid, cid; - - aid = RFIFOL(fd, 4); - cid = RFIFOL(fd, 8); - count = RFIFOW(fd, 12); - - // Whatever comes from the mapserver, now is the time to drop previous entries - if( Sql_Query( sql_handle, "DELETE FROM `%s` where `account_id` = %d and `char_id` = %d;", schema_config.scdata_db, aid, cid ) != SQL_SUCCESS ){ - Sql_ShowDebug( sql_handle ); - }else if( count > 0 ){ - struct status_change_data data; - StringBuf buf; - int i; - - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", schema_config.scdata_db); - for( i = 0; i < count; ++i ) - { - memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); - if( i > 0 ) - StringBuf_AppendStr(&buf, ", "); - StringBuf_Printf(&buf, "('%d','%d','%hu','%d','%d','%d','%d','%d')", aid, cid, - data.type, data.tick, data.val1, data.val2, data.val3, data.val4); - } - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) - Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); - } -#endif - RFIFOSKIP(fd, RFIFOW(fd, 2)); - } - break; - - case 0x2b15: //Request to save skill cooldown data - if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) - return 0; - { - int count, aid, cid; - aid = RFIFOL(fd,4); - cid = RFIFOL(fd,8); - count = RFIFOW(fd,12); - if( count > 0 ) - { - struct skill_cooldown_data data; - StringBuf buf; - int i; - - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", schema_config.skillcooldown_db); - for( i = 0; i < count; ++i ) - { - memcpy(&data,RFIFOP(fd,14+i*sizeof(struct skill_cooldown_data)),sizeof(struct skill_cooldown_data)); - if( i > 0 ) - StringBuf_AppendStr(&buf, ", "); - StringBuf_Printf(&buf, "('%d','%d','%d','%d')", aid, cid, data.skill_id, data.tick); - } - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) - Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); - } - RFIFOSKIP(fd, RFIFOW(fd, 2)); - } - break; - - case 0x2b23: // map-server alive packet - WFIFOHEAD(fd,2); - WFIFOW(fd,0) = 0x2b24; - WFIFOSET(fd,2); - RFIFOSKIP(fd,2); - break; - - case 0x2b26: // auth request from map-server - if (RFIFOREST(fd) < 20) - return 0; - - { - int account_id; - int char_id; - int login_id1; - char sex; - uint32 ip; - struct auth_node* node; - struct mmo_charstatus* cd; - struct mmo_charstatus char_dat; - bool autotrade; - - account_id = RFIFOL(fd,2); - char_id = RFIFOL(fd,6); - login_id1 = RFIFOL(fd,10); - sex = RFIFOB(fd,14); - ip = ntohl(RFIFOL(fd,15)); - autotrade = RFIFOB(fd,19); - RFIFOSKIP(fd,20); - - node = (struct auth_node*)idb_get(auth_db, account_id); - cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); - if( cd == NULL ) - { //Really shouldn't happen. - mmo_char_fromsql(char_id, &char_dat, true); - cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); - } - - if( runflag == CHARSERVER_ST_RUNNING && autotrade && cd ){ - uint32 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; - cd->sex = sex; - - WFIFOHEAD(fd,mmo_charstatus_len); - WFIFOW(fd,0) = 0x2afd; - WFIFOW(fd,2) = mmo_charstatus_len; - WFIFOL(fd,4) = account_id; - WFIFOL(fd,8) = 0; - WFIFOL(fd,12) = 0; - WFIFOL(fd,16) = 0; - WFIFOL(fd,20) = 0; - WFIFOB(fd,24) = 0; - memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); - WFIFOSET(fd, WFIFOW(fd,2)); - - set_char_online(id, char_id, account_id); - }else if( runflag == CHARSERVER_ST_RUNNING && - cd != NULL && - node != NULL && - node->account_id == account_id && - node->char_id == char_id && - node->login_id1 == login_id1 && - node->sex == sex /*&& - node->ip == ip*/ ) - {// auth ok - uint32 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; - cd->sex = sex; - - WFIFOHEAD(fd,mmo_charstatus_len); - WFIFOW(fd,0) = 0x2afd; - WFIFOW(fd,2) = mmo_charstatus_len; - WFIFOL(fd,4) = account_id; - WFIFOL(fd,8) = node->login_id1; - WFIFOL(fd,12) = node->login_id2; - WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" - WFIFOL(fd,20) = node->group_id; - WFIFOB(fd,24) = node->changing_mapservers; - memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); - WFIFOSET(fd, WFIFOW(fd,2)); - - // only use the auth once and mark user online - idb_remove(auth_db, account_id); - set_char_online(id, char_id, account_id); - } - else - {// auth failed - WFIFOHEAD(fd,19); - WFIFOW(fd,0) = 0x2b27; - WFIFOL(fd,2) = account_id; - WFIFOL(fd,6) = char_id; - WFIFOL(fd,10) = login_id1; - WFIFOB(fd,14) = sex; - WFIFOL(fd,15) = htonl(ip); - WFIFOSET(fd,19); - } - } - break; - - case 0x2736: // ip address update - if (RFIFOREST(fd) < 6) return 0; - map_server[id].ip = ntohl(RFIFOL(fd, 2)); - ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(map_server[id].ip)); - RFIFOSKIP(fd,6); - break; - - case 0x3008: - if( RFIFOREST(fd) < RFIFOW(fd,4) ) - return 0;/* packet wasn't fully received yet (still fragmented) */ - else { - int sfd;/* stat server fd */ - RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */ - - if( (sfd = make_connection(host2ip("stats.rathena.org"),(uint16)25421,true,10) ) == -1 ) { - RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ - break;/* connection not possible, we drop the report */ - } - - session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */ - WFIFOHEAD(sfd, RFIFOW(fd,2) ); - memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2)); - WFIFOSET(sfd, RFIFOW(fd,2) ); - flush_fifo(sfd); - do_close(sfd); - RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ - } - break; - - case 0x2b28: mapif_parse_reqcharban(fd); break; //charban - case 0x2b2a: mapif_parse_reqcharunban(fd); break; //charunban - //case 0x2b2c: /*free*/; break; - case 0x2b2d: bonus_script_get(fd); break; //Load data - case 0x2b2e: bonus_script_save(fd); break;//Save data - - default: - { - // inter server - packet - int r = inter_parse_frommap(fd); - if (r == 1) break; // processed - if (r == 2) return 0; // need more packet - - // no inter server packet. no char server packet -> disconnect - ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0)); - set_eof(fd); - return 0; - } - } // switch - } // while - - return 0; -} void do_init_mapif(void) { @@ -3378,12 +2325,6 @@ int char_search_mapserver(unsigned short map, uint32 ip, uint16 port){ return -1; } -// Initialization process (currently only initialization inter_mapif) -static int char_mapif_init(int fd) -{ - return inter_mapif_init(fd); -} - /** * Test to know if an IP come from LAN or WAN. * @param ip: ip to check if in auth network @@ -3465,808 +2406,6 @@ void char_delete2_cancel_ack(int fd, int char_id, uint32 result) } -static void char_delete2_req(int fd, struct char_session_data* sd) -{// CH: <0827>.W .L - int char_id, i; - char* data; - time_t delete_date; - - char_id = RFIFOL(fd,2); - - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); - if( i == MAX_CHARS ) - {// character not found - char_delete2_ack(fd, char_id, 3, 0); - return; - } - - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) - { - Sql_ShowDebug(sql_handle); - char_delete2_ack(fd, char_id, 3, 0); - return; - } - - Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); - - if( delete_date ) {// character already queued for deletion - char_delete2_ack(fd, char_id, 0, 0); - return; - } - -/* - // Aegis imposes these checks probably to avoid dead member - // entries in guilds/parties, otherwise they are not required. - // TODO: Figure out how these are enforced during waiting. - if( guild_id ) - {// character in guild - char_delete2_ack(fd, char_id, 4, 0); - return; - } - - if( party_id ) - {// character in party - char_delete2_ack(fd, char_id, 5, 0); - return; - } -*/ - - // success - delete_date = time(NULL)+charserv_config.char_config.char_del_delay; - - if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", schema_config.char_db, (unsigned long)delete_date, char_id) ) - { - Sql_ShowDebug(sql_handle); - char_delete2_ack(fd, char_id, 3, 0); - return; - } - - char_delete2_ack(fd, char_id, 1, delete_date); -} - - -static void char_delete2_accept(int fd, struct char_session_data* sd) -{// CH: <0829>.W .L .6B - char birthdate[8+1]; - int char_id, i, k; - unsigned int base_level; - char* data; - time_t delete_date; - - char_id = RFIFOL(fd,2); - - ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id); - - // construct "YY-MM-DD" - birthdate[0] = RFIFOB(fd,6); - birthdate[1] = RFIFOB(fd,7); - birthdate[2] = '-'; - birthdate[3] = RFIFOB(fd,8); - birthdate[4] = RFIFOB(fd,9); - birthdate[5] = '-'; - birthdate[6] = RFIFOB(fd,10); - birthdate[7] = RFIFOB(fd,11); - birthdate[8] = 0; - - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); - if( i == MAX_CHARS ) - {// character not found - char_delete2_accept_ack(fd, char_id, 3); - return; - } - - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) - {// data error - Sql_ShowDebug(sql_handle); - char_delete2_accept_ack(fd, char_id, 3); - return; - } - - Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10); - - if( !delete_date || delete_date>time(NULL) ) - {// not queued or delay not yet passed - char_delete2_accept_ack(fd, char_id, 4); - return; - } - - if( strcmp(sd->birthdate+2, birthdate) ) // +2 to cut off the century - {// birth date is wrong - char_delete2_accept_ack(fd, char_id, 5); - return; - } - - if( ( charserv_config.char_config.char_del_level > 0 && base_level >= (unsigned int)charserv_config.char_config.char_del_level ) - || ( charserv_config.char_config.char_del_level < 0 && base_level <= (unsigned int)(-charserv_config.char_config.char_del_level) ) - || !(charserv_config.char_config.char_del_option&2) ) - {// character level config restriction - char_delete2_accept_ack(fd, char_id, 2); - return; - } - - // success - if( delete_char_sql(char_id) < 0 ) - { - char_delete2_accept_ack(fd, char_id, 3); - return; - } - - // refresh character list cache - for(k = i; k < MAX_CHARS-1; k++) { - sd->found_char[k] = sd->found_char[k+1]; - } - sd->found_char[MAX_CHARS-1] = -1; - - char_delete2_accept_ack(fd, char_id, 1); -} - - -static void char_delete2_cancel(int fd, struct char_session_data* sd) -{// CH: <082b>.W .L - int char_id, i; - - char_id = RFIFOL(fd,2); - - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); - if( i == MAX_CHARS ) - {// character not found - char_delete2_cancel_ack(fd, char_id, 2); - return; - } - - // there is no need to check, whether or not the character was - // queued for deletion, as the client prints an error message by - // itself, if it was not the case (@see char_delete2_cancel_ack) - if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", schema_config.char_db, char_id) ) - { - Sql_ShowDebug(sql_handle); - char_delete2_cancel_ack(fd, char_id, 2); - return; - } - - char_delete2_cancel_ack(fd, char_id, 1); -} - - -int parse_char(int fd) -{ - int i, ch; - char email[40]; - unsigned short cmd; - int map_fd; - struct char_session_data* sd; - uint32 ipl = session[fd]->client_addr; - - sd = (struct char_session_data*)session[fd]->session_data; - - // disconnect any player if no login-server. - if(login_fd < 0) - set_eof(fd); - - if(session[fd]->flag.eof) - { - if( sd != NULL && sd->auth ) - { // already authed client - struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id); - if( data != NULL && data->fd == fd) - data->fd = -1; - if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex] - set_char_offline(-1,sd->account_id); - } - do_close(fd); - return 0; - } - - while( RFIFOREST(fd) >= 2 ) - { - //For use in packets that depend on an sd being present [Skotlex] - #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } } - - cmd = RFIFOW(fd,0); - switch( cmd ) - { - - // request to connect - // 0065 .L .L .L .W .B - case 0x65: - if( RFIFOREST(fd) < 17 ) - return 0; - { - struct auth_node* node; - - int account_id = RFIFOL(fd,2); - uint32 login_id1 = RFIFOL(fd,6); - uint32 login_id2 = RFIFOL(fd,10); - int sex = RFIFOB(fd,16); - RFIFOSKIP(fd,17); - - ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2); - - if (sd) { - //Received again auth packet for already authentified account?? Discard it. - //TODO: Perhaps log this as a hack attempt? - //TODO: and perhaps send back a reply? - break; - } - - CREATE(session[fd]->session_data, struct char_session_data, 1); - sd = (struct char_session_data*)session[fd]->session_data; - sd->account_id = account_id; - sd->login_id1 = login_id1; - sd->login_id2 = login_id2; - sd->sex = sex; - sd->auth = false; // not authed yet - - // send back account_id - WFIFOHEAD(fd,4); - WFIFOL(fd,0) = account_id; - WFIFOSET(fd,4); - - if( runflag != CHARSERVER_ST_RUNNING ) - { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0;// rejected from server - WFIFOSET(fd,3); - break; - } - - // search authentification - node = (struct auth_node*)idb_get(auth_db, account_id); - if( node != NULL && - node->account_id == account_id && - node->login_id1 == login_id1 && - node->login_id2 == login_id2 /*&& - node->ip == ipl*/ ) - {// authentication found (coming from map server) - sd->version = node->version; - idb_remove(auth_db, account_id); - char_auth_ok(fd, sd); - } - else - {// authentication not found (coming from login server) - if (loginif_isconnected()) { // don't send request if no login-server - WFIFOHEAD(login_fd,23); - WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account - WFIFOL(login_fd,2) = sd->account_id; - WFIFOL(login_fd,6) = sd->login_id1; - WFIFOL(login_fd,10) = sd->login_id2; - WFIFOB(login_fd,14) = sd->sex; - WFIFOL(login_fd,15) = htonl(ipl); - WFIFOL(login_fd,19) = fd; - WFIFOSET(login_fd,23); - } else { // if no login-server, we must refuse connection - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - } - } - } - break; - - // char select - case 0x66: - FIFOSD_CHECK(3); - { - struct mmo_charstatus char_dat; - struct mmo_charstatus *cd; - char* data; - int char_id; - uint32 subnet_map_ip; - struct auth_node* node; - - int slot = RFIFOB(fd,2); - RFIFOSKIP(fd,3); - - if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", schema_config.char_db, sd->account_id, slot) - || SQL_SUCCESS != Sql_NextRow(sql_handle) - || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) ) - { //Not found?? May be forged packet. - Sql_ShowDebug(sql_handle); - Sql_FreeResult(sql_handle); - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0; // rejected from server - WFIFOSET(fd,3); - break; - } - - char_id = atoi(data); - Sql_FreeResult(sql_handle); - - /* client doesn't let it get to this point if you're banned, so its a forged packet */ - if( sd->found_char[slot] == char_id && sd->unban_time[slot] > time(NULL) ) { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0; // rejected from server - WFIFOSET(fd,3); - break; - } - - /* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */ - set_char_online(-2,char_id,sd->account_id); - if( !mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */ - set_char_offline(char_id, sd->account_id); - /* failed to load something. REJECT! */ - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - break;/* jump off this boat */ - } - - //Have to switch over to the DB instance otherwise data won't propagate [Kevin] - cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); - cd->sex = sd->sex; - - if (charserv_config.log_char) { - char esc_name[NAME_LENGTH*2+1]; - - Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", - schema_config.charlog_db, sd->account_id, slot, esc_name) ) - Sql_ShowDebug(sql_handle); - } - ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name); - - // searching map server - i = search_mapserver(cd->last_point.map, -1, -1); - - // if map is not found, we check major cities - if (i < 0 || !cd->last_point.map) { - unsigned short j; - //First check that there's actually a map server online. - ARR_FIND( 0, ARRAYLENGTH(map_server), j, map_server[j].fd >= 0 && map_server[j].map[0] ); - if (j == ARRAYLENGTH(map_server)) { - ShowInfo("Connection Closed. No map servers available.\n"); - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 1; // 01 = Server closed - WFIFOSET(fd,3); - break; - } - if ((i = search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) { - cd->last_point.x = 273; - cd->last_point.y = 354; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) { - cd->last_point.x = 120; - cd->last_point.y = 100; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) { - cd->last_point.x = 160; - cd->last_point.y = 94; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) { - cd->last_point.x = 116; - cd->last_point.y = 57; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) { - cd->last_point.x = 87; - cd->last_point.y = 117; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) { - cd->last_point.x = 94; - cd->last_point.y = 103; - } else { - ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map)); - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 1; // 01 = Server closed - WFIFOSET(fd,3); - break; - } - ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j)); - cd->last_point.map = j; - } - - //Send NEW auth packet [Kevin] - //FIXME: is this case even possible? [ultramage] - if ((map_fd = map_server[i].fd) < 1 || session[map_fd] == NULL) - { - ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); - map_server[i].fd = -1; - memset(&map_server[i], 0, sizeof(struct mmo_map_server)); - //Send server closed. - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 1; // 01 = Server closed - WFIFOSET(fd,3); - break; - } - - //Send player to map - WFIFOHEAD(fd,28); - WFIFOW(fd,0) = 0x71; - WFIFOL(fd,2) = cd->char_id; - mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); - subnet_map_ip = char_lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] - WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : map_server[i].ip); - WFIFOW(fd,26) = ntows(htons(map_server[i].port)); // [!] LE byte order here [!] - WFIFOSET(fd,28); - - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = sd->account_id; - node->char_id = cd->char_id; - node->login_id1 = sd->login_id1; - node->login_id2 = sd->login_id2; - node->sex = sd->sex; - node->expiration_time = sd->expiration_time; - node->group_id = sd->group_id; - node->ip = ipl; - idb_put(auth_db, sd->account_id, node); - - } - break; - - // create new char -#if PACKETVER >= 20120307 - // S 0970 .24B .B .W .W - case 0x970: - FIFOSD_CHECK(31); -#else - // S 0067 .24B .B .B .B .B .B .B .B .W .W - case 0x67: - FIFOSD_CHECK(37); -#endif - - if( !charserv_config.char_new ) //turn character creation on/off [Kevin] - i = -2; - else -#if PACKETVER >= 20120307 - i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29)); -#else - i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35)); -#endif - - //'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3) - if (i < 0) { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6e; - /* Others I found [Ind] */ - /* 0x02 = Symbols in Character Names are forbidden */ - /* 0x03 = You are not elegible to open the Character Slot. */ - switch (i) { - case -1: WFIFOB(fd,2) = 0x00; break; - case -2: WFIFOB(fd,2) = 0xFF; break; - case -3: WFIFOB(fd,2) = 0x01; break; - case -4: WFIFOB(fd,2) = 0x03; break; - } - WFIFOSET(fd,3); - } else { - int len; - // retrieve data - struct mmo_charstatus char_dat; - mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed. - - // send to player - WFIFOHEAD(fd,2+MAX_CHAR_BUF); - WFIFOW(fd,0) = 0x6d; - len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat); - WFIFOSET(fd,len); - - // add new entry to the chars list - ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 ); - if( ch < MAX_CHARS ) - sd->found_char[ch] = i; // the char_id of the new char - } -#if PACKETVER >= 20120307 - RFIFOSKIP(fd,31); -#else - RFIFOSKIP(fd,37); -#endif - break; - - // delete char - case 0x68: - // 2004-04-19aSakexe+ langtype 12 char deletion packet - case 0x1fb: - if (cmd == 0x68) FIFOSD_CHECK(46); - if (cmd == 0x1fb) FIFOSD_CHECK(56); - { - int cid = RFIFOL(fd,2); - - ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); - memcpy(email, RFIFOP(fd,6), 40); - RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); - - // Check if e-mail is correct - if((strcmpi(email, sd->email) && //email does not matches and - ( - strcmp("a@a.com", sd->email) || //it is not default email, or - (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default - )) - || !(charserv_config.char_config.char_del_option&1) - ) { //Fail - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x70; - WFIFOB(fd,2) = 0; // 00 = Incorrect Email address - WFIFOSET(fd,3); - break; - } - - // check if this char exists - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - { // Such a character does not exist in the account - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x70; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - break; - } - - // remove char from list and compact it - for(ch = i; ch < MAX_CHARS-1; ch++) - sd->found_char[ch] = sd->found_char[ch+1]; - sd->found_char[MAX_CHARS-1] = -1; - - /* Delete character */ - if(delete_char_sql(cid)<0){ - //can't delete the char - //either SQL error or can't delete by some CONFIG conditions - //del fail - WFIFOHEAD(fd,3); - WFIFOW(fd, 0) = 0x70; - WFIFOB(fd, 2) = 0; - WFIFOSET(fd, 3); - break; - } - /* Char successfully deleted.*/ - WFIFOHEAD(fd,2); - WFIFOW(fd,0) = 0x6f; - WFIFOSET(fd,2); - } - break; - - // client keep-alive packet (every 12 seconds) - // R 0187 .l - case 0x187: - if (RFIFOREST(fd) < 6) - return 0; - RFIFOSKIP(fd,6); - break; - // char rename request - // R 08fc .l .24B - case 0x8fc: - FIFOSD_CHECK(30); - { - int i, cid =RFIFOL(fd,2); - char name[NAME_LENGTH]; - char esc_name[NAME_LENGTH*2+1]; - safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH); - RFIFOSKIP(fd,30); - - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - break; - - normalize_name(name,TRIM_CHARS); - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( !check_char_name(name,esc_name) ) { - i = 1; - safestrncpy(sd->new_name, name, NAME_LENGTH); - } else - i = 0; - - WFIFOHEAD(fd, 4); - WFIFOW(fd,0) = 0x28e; - WFIFOW(fd,2) = i; - WFIFOSET(fd,4); - } - break; - - // char rename request - // R 028d .l .l .24B - case 0x28d: - FIFOSD_CHECK(34); - { - int i, aid = RFIFOL(fd,2), cid =RFIFOL(fd,6); - char name[NAME_LENGTH]; - char esc_name[NAME_LENGTH*2+1]; - safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH); - RFIFOSKIP(fd,34); - - if( aid != sd->account_id ) - break; - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - break; - - normalize_name(name,TRIM_CHARS); - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( !check_char_name(name,esc_name) ) - { - i = 1; - safestrncpy(sd->new_name, name, NAME_LENGTH); - } - else - i = 0; - - WFIFOHEAD(fd, 4); - WFIFOW(fd,0) = 0x28e; - WFIFOW(fd,2) = i; - WFIFOSET(fd,4); - } - break; - //Confirm change name. - // 0x28f .L - case 0x28f: - // 0: Sucessfull - // 1: This character's name has already been changed. You cannot change a character's name more than once. - // 2: User information is not correct. - // 3: You have failed to change this character's name. - // 4: Another user is using this character name, so please select another one. - FIFOSD_CHECK(6); - { - int i; - int cid = RFIFOL(fd,2); - RFIFOSKIP(fd,6); - - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - break; - i = rename_char_sql(sd, cid); - - WFIFOHEAD(fd, 4); - WFIFOW(fd,0) = 0x290; - WFIFOW(fd,2) = i; - WFIFOSET(fd,4); - } - break; - - // captcha code request (not implemented) - // R 07e5 .w .l - case 0x7e5: - WFIFOHEAD(fd,5); - WFIFOW(fd,0) = 0x7e9; - WFIFOW(fd,2) = 5; - WFIFOB(fd,4) = 1; - WFIFOSET(fd,5); - RFIFOSKIP(fd,8); - break; - - // captcha code check (not implemented) - // R 07e7 .w .l .b10 .b14 - case 0x7e7: - WFIFOHEAD(fd,5); - WFIFOW(fd,0) = 0x7e9; - WFIFOW(fd,2) = 5; - WFIFOB(fd,4) = 1; - WFIFOSET(fd,5); - RFIFOSKIP(fd,32); - break; - - // deletion timer request - case 0x827: - FIFOSD_CHECK(6); - char_delete2_req(fd, sd); - RFIFOSKIP(fd,6); - break; - - // deletion accept request - case 0x829: - FIFOSD_CHECK(12); - char_delete2_accept(fd, sd); - RFIFOSKIP(fd,12); - break; - - // deletion cancel request - case 0x82b: - FIFOSD_CHECK(6); - char_delete2_cancel(fd, sd); - RFIFOSKIP(fd,6); - break; - - // login as map-server - case 0x2af8: - if (RFIFOREST(fd) < 60) - return 0; - else { - char* l_user = (char*)RFIFOP(fd,2); - char* l_pass = (char*)RFIFOP(fd,26); - l_user[23] = '\0'; - l_pass[23] = '\0'; - ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd <= 0 ); - if( runflag != CHARSERVER_ST_RUNNING || - i == ARRAYLENGTH(map_server) || - strcmp(l_user, charserv_config.userid) != 0 || - strcmp(l_pass, charserv_config.passwd) != 0 ) - { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x2af9; - WFIFOB(fd,2) = 3; - WFIFOSET(fd,3); - } else { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x2af9; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - - map_server[i].fd = fd; - map_server[i].ip = ntohl(RFIFOL(fd,54)); - map_server[i].port = ntohs(RFIFOW(fd,58)); - map_server[i].users = 0; - memset(map_server[i].map, 0, sizeof(map_server[i].map)); - session[fd]->func_parse = parse_frommap; - session[fd]->flag.server = 1; - realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - char_mapif_init(fd); - } - RFIFOSKIP(fd,60); - } - return 0; // avoid processing of followup packets here - - // checks the entered pin - case 0x8b8: - if( RFIFOREST(fd) < 10 ) - return 0; - if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ) - chclif_parse_pincode_check( fd, sd ); - RFIFOSKIP(fd,10); - break; - - // request for PIN window - case 0x8c5: - if( RFIFOREST(fd) < 6 ) - return 0; - if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ){ - if( sd->pincode[0] == '\0' ){ - pincode_sendstate( fd, sd, PINCODE_NEW ); - }else{ - pincode_sendstate( fd, sd, PINCODE_ASK ); - } - } - RFIFOSKIP(fd,6); - break; - - // pincode change request - case 0x8be: - if( RFIFOREST(fd) < 14 ) - return 0; - - if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ) - pincode_change( fd, sd ); - - RFIFOSKIP(fd,14); - break; - - // activate PIN system and set first PIN - case 0x8ba: - if( RFIFOREST(fd) < 10 ) - return 0; - if( charserv_config.pincode_config.pincode_enabled && RFIFOL(fd,2) == sd->account_id ) - pincode_setnew( fd, sd ); - RFIFOSKIP(fd,10); - break; - - // character movement request - case 0x8d4: - if( RFIFOREST(fd) < 8 ) - return 0; - - moveCharSlot( fd, sd, RFIFOW(fd, 2), RFIFOW(fd, 4) ); - mmo_char_send(fd, sd); - RFIFOSKIP(fd,8); - break; - - case 0x9a1: - if( RFIFOREST(fd) < 2 ) - return 0; - char_parse_req_charlist(fd,sd); - RFIFOSKIP(fd,2); - break; - - // unknown packet received - default: - ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); - set_eof(fd); - return 0; - } - } - - RFIFOFLUSH(fd); - return 0; -} - // Console Command Parser [Wizputer] int parse_console(const char* buf) { @@ -4317,7 +2456,7 @@ int char_broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) return 0; prev_users = users; - if( loginif_isconnected() ) + if( chlogif_isconnected() ) { // send number of user to login server WFIFOHEAD(login_fd,6); @@ -4362,7 +2501,7 @@ static int send_accounts_tologin_sub(DBKey key, DBData *data, va_list ap) */ int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data) { - if (loginif_isconnected()) + if (chlogif_isconnected()) { // send account list to login server int users = online_char_db->size(online_char_db); @@ -4413,12 +2552,12 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data //------------------------------------------------ //Pincode system //------------------------------------------------ -int pincode_compare( int fd, struct char_session_data* sd, char* pin ){ +int char_pincode_compare( int fd, struct char_session_data* sd, char* pin ){ if( strcmp( sd->pincode, pin ) == 0 ){ sd->pincode_try = 0; return 1; }else{ - pincode_sendstate( fd, sd, PINCODE_WRONG ); + chclif_pincode_sendstate( fd, sd, PINCODE_WRONG ); if( charserv_config.pincode_config.pincode_maxtry && ++sd->pincode_try >= charserv_config.pincode_config.pincode_maxtry ){ chlogif_pincode_notifyLoginPinError( sd->account_id ); @@ -4454,147 +2593,6 @@ void char_pincode_decrypt( uint32 userSeed, char* pin ){ aFree( buf ); } -//------------------------------------------------ -//Add On system -//------------------------------------------------ -void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to ){ - // Have we changed to often or is it disabled? - if( !charserv_config.charmove_config.char_move_enabled || ( !charserv_config.charmove_config.char_moves_unlimited && sd->char_moves[from] <= 0 ) ){ - moveCharSlotReply( fd, sd, from, 1 ); - return; - } - - // We dont even have a character on the chosen slot? - if( sd->found_char[from] <= 0 ){ - moveCharSlotReply( fd, sd, from, 1 ); - return; - } - - if( sd->found_char[to] > 0 ){ - // We want to move to a used position - if( charserv_config.charmove_config.char_movetoused ){ // TODO: check if the target is in deletion process - // Admin is friendly and uses triangle exchange - if( SQL_ERROR == Sql_QueryStr(sql_handle, "START TRANSACTION") - || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, to, sd->found_char[from] ) - || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, from, sd->found_char[to] ) - || SQL_ERROR == Sql_QueryStr(sql_handle, "COMMIT") - ){ - moveCharSlotReply( fd, sd, from, 1 ); - Sql_ShowDebug(sql_handle); - Sql_QueryStr(sql_handle,"ROLLBACK"); - return; - } - }else{ - // Admin doesnt allow us to - moveCharSlotReply( fd, sd, from, 1 ); - return; - } - }else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", schema_config.char_db, to, sd->found_char[from] ) ){ - Sql_ShowDebug(sql_handle); - moveCharSlotReply( fd, sd, from, 1 ); - return; - } - - if( ! charserv_config.charmove_config.char_moves_unlimited ){ - sd->char_moves[from]--; - Sql_Query(sql_handle, "UPDATE `%s` SET `moves`='%d' WHERE `char_id`='%d'", schema_config.char_db, sd->char_moves[from], sd->found_char[from] ); - } - - // We successfully moved the char - time to notify the client - moveCharSlotReply( fd, sd, from, 0 ); - mmo_char_send(fd, sd); -} - - -/** [Cydh] -* Get bonus_script data(s) from table to load -* @param fd -*/ -void bonus_script_get(int fd) { - if (RFIFOREST(fd) < 6) - return; - else { - int cid; - cid = RFIFOL(fd,2); - RFIFOSKIP(fd,6); - - if (SQL_ERROR == Sql_Query(sql_handle,"SELECT `script`, `tick`, `flag`, `type`, `icon` FROM `%s` WHERE `char_id`='%d'", - schema_config.bonus_script_db,cid)) - { - Sql_ShowDebug(sql_handle); - return; - } - if (Sql_NumRows(sql_handle) > 0) { - struct bonus_script_data bsdata; - int count; - char *data; - - WFIFOHEAD(fd,10+50*sizeof(struct bonus_script_data)); - WFIFOW(fd,0) = 0x2b2f; - WFIFOL(fd,4) = cid; - for (count = 0; count < 20 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count) { - Sql_GetData(sql_handle,0,&data,NULL); memcpy(bsdata.script,data,strlen(data)+1); - Sql_GetData(sql_handle,1,&data,NULL); bsdata.tick = atoi(data); - Sql_GetData(sql_handle,2,&data,NULL); bsdata.flag = atoi(data); - Sql_GetData(sql_handle,3,&data,NULL); bsdata.type = atoi(data); - Sql_GetData(sql_handle,4,&data,NULL); bsdata.icon = atoi(data); - memcpy(WFIFOP(fd,10+count*sizeof(struct bonus_script_data)),&bsdata,sizeof(struct bonus_script_data)); - } - if (count >= 20) - ShowWarning("Too many bonus_script for %d, some of them were not loaded.\n",cid); - if (count > 0) { - WFIFOW(fd,2) = 10 + count*sizeof(struct bonus_script_data); - WFIFOW(fd,8) = count; - WFIFOSET(fd,WFIFOW(fd,2)); - - //Clear the data once loaded. - if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id`='%d'",schema_config.bonus_script_db,cid)) - Sql_ShowDebug(sql_handle); - ShowInfo("Loaded %d bonus_script for char_id: %d\n",count,cid); - } - } - Sql_FreeResult(sql_handle); - } -} - -/** [Cydh] -* Save bonus_script data(s) to the table -* @param fd -*/ -void bonus_script_save(int fd) { - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return; - else { - int count, cid; - - cid = RFIFOL(fd,4); - count = RFIFOW(fd,8); - - if (count > 0) { - struct bonus_script_data bs; - StringBuf buf; - int i; - char esc_script[MAX_BONUS_SCRIPT_LENGTH] = ""; - - StringBuf_Init(&buf); - StringBuf_Printf(&buf,"INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ",schema_config.bonus_script_db); - for (i = 0; i < count; ++i) { - memcpy(&bs,RFIFOP(fd,10+i*sizeof(struct bonus_script_data)),sizeof(struct bonus_script_data)); - Sql_EscapeString(sql_handle,esc_script,bs.script); - if (i > 0) - StringBuf_AppendStr(&buf,", "); - StringBuf_Printf(&buf,"('%d','%s','%d','%d','%d','%d')",cid,esc_script,bs.tick,bs.flag,bs.type,bs.icon); - } - if (SQL_ERROR == Sql_QueryStr(sql_handle,StringBuf_Value(&buf))) - Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); - ShowInfo("Saved %d bonus_script for char_id: %d\n",count,cid); - } - RFIFOSKIP(fd,RFIFOW(fd,2)); - } -} - - //------------------------------------------------ //Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't //replies/disconnect the player we tried to kick. [Skotlex] diff --git a/src/char/char.h b/src/char/char.h index a4d03b0c80..0cb83379b1 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -241,17 +241,13 @@ int char_married(int pl1,int pl2); int char_child(int parent_id, int child_id); int char_family(int pl1,int pl2,int pl3); -int request_accreg2(int account_id, int char_id); -int save_accreg2(unsigned char* buf, int len); +int char_request_accreg2(int account_id, int char_id); +int char_save_accreg2(unsigned char* buf, int len); //extern bool char_gm_read; int char_loadName(int char_id, char* name); int char_check_char_name(char * name, char * esc_name); -//Bonus Script -void bonus_script_get(int fd);///Get bonus_script data -void bonus_script_save(int fd); ///Save bonus_script data - void char_pincode_decrypt( uint32 userSeed, char* pin ); int char_pincode_compare( int fd, struct char_session_data* sd, char* pin ); void char_auth_ok(int fd, struct char_session_data *sd); diff --git a/src/char/char_clif.c b/src/char/char_clif.c index 29e18b71e9..7957e6b20c 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -163,29 +163,30 @@ int chclif_parse_pincode_check( int fd, struct char_session_data* sd ){ * Client request to change pincode */ int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ - char oldpin[PINCODE_LENGTH+1]; - char newpin[PINCODE_LENGTH+1]; - if( RFIFOREST(fd) < 14 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 0; + else { + char oldpin[PINCODE_LENGTH+1]; + char newpin[PINCODE_LENGTH+1]; + + memset(oldpin,0,PINCODE_LENGTH+1); + memset(newpin,0,PINCODE_LENGTH+1); + strncpy(oldpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH); + strncpy(newpin, (char*)RFIFOP(fd,10), PINCODE_LENGTH); + RFIFOSKIP(fd,14); - memset(oldpin,0,PINCODE_LENGTH+1); - memset(newpin,0,PINCODE_LENGTH+1); - strncpy(oldpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH); - strncpy(newpin, (char*)RFIFOP(fd,10), PINCODE_LENGTH); - RFIFOSKIP(fd,14); + char_pincode_decrypt(sd->pincode_seed,oldpin); + if( !char_pincode_compare( fd, sd, oldpin ) ) + return 0; + char_pincode_decrypt(sd->pincode_seed,newpin); - char_pincode_decrypt(sd->pincode_seed,oldpin); - if( !char_pincode_compare( fd, sd, oldpin ) ) - return 0; - char_pincode_decrypt(sd->pincode_seed,newpin); + chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); + strncpy(sd->pincode, newpin, sizeof(newpin)); - chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); - strncpy(sd->pincode, newpin, sizeof(newpin)); - - chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + } return 1; } @@ -193,24 +194,24 @@ int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ * activate PIN system and set first PIN */ int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){ - char newpin[PINCODE_LENGTH+1]; - - memset(newpin,0,PINCODE_LENGTH+1); - if( RFIFOREST(fd) < 10 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 0; - strncpy( newpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH ); - RFIFOSKIP(fd,10); + else { + char newpin[PINCODE_LENGTH+1]; + memset(newpin,0,PINCODE_LENGTH+1); + strncpy( newpin, (char*)RFIFOP(fd,6), PINCODE_LENGTH ); + RFIFOSKIP(fd,10); - char_pincode_decrypt( sd->pincode_seed, newpin ); + char_pincode_decrypt( sd->pincode_seed, newpin ); - chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); - strncpy( sd->pincode, newpin, strlen( newpin ) ); + chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); + strncpy( sd->pincode, newpin, strlen( newpin ) ); - chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); + } return 1; } @@ -364,12 +365,12 @@ void chclif_char_delete2_cancel_ack(int fd, int char_id, uint32 result) { // CH: <0827>.W .L int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { - int char_id, i; + FIFOSD_CHECK(6) + { + int char_id, i; char* data; time_t delete_date; - - FIFOSD_CHECK(6) - + char_id = RFIFOL(fd,2); RFIFOSKIP(fd,6); @@ -410,7 +411,6 @@ int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { return; } */ - // success delete_date = time(NULL)+(charserv_config.char_config.char_del_delay); @@ -422,19 +422,19 @@ int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { } chclif_char_delete2_ack(fd, char_id, 1, delete_date); - return 1; + } + return 1; } // CH: <0829>.W .L .6B int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) { - char birthdate[8+1]; + FIFOSD_CHECK(12) + { + char birthdate[8+1]; int char_id, i, k; unsigned int base_level; char* data; time_t delete_date; - - FIFOSD_CHECK(12) - char_id = RFIFOL(fd,2); ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id); @@ -502,7 +502,8 @@ int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) { sd->found_char[MAX_CHARS-1] = -1; chclif_char_delete2_accept_ack(fd, char_id, 1); - return 1; + } + return 1; } // CH: <082b>.W .L @@ -601,7 +602,7 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){ //TODO: Perhaps log this as a hack attempt? //TODO: and perhaps send back a reply? ShowInfo("Already registered break\n"); - return 0; + return 0; // @CHEKME this was break } CREATE(session[fd]->session_data, struct char_session_data, 1); @@ -634,11 +635,8 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){ node->login_id2 == login_id2 /*&& node->ip == ipl*/ ) {// authentication found (coming from map server) - DBMap *online_char_db = char_get_onlinedb(); - struct online_char_data* ol_cd = (struct online_char_data*)idb_get(online_char_db, account_id); - if(ol_cd) sd->version = ol_cd->version; - ShowInfo("char_parse_reqtoconnect: authentication found (coming from map server), sd->v=%d online_chd=%d\n",sd->version,ol_cd); - idb_remove(auth_db, account_id); + sd->version = node->version; + idb_remove(auth_db, account_id); char_auth_ok(fd, sd); } else @@ -705,6 +703,15 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ char_id = atoi(data); Sql_FreeResult(sql_handle); + /* client doesn't let it get to this point if you're banned, so its a forged packet */ + if( sd->found_char[slot] == char_id && sd->unban_time[slot] > time(NULL) ) { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; // rejected from server + WFIFOSET(fd,3); + return 0; + } + /* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */ char_set_char_online(-2,char_id,sd->account_id); if( !char_mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */ @@ -787,7 +794,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ WFIFOW(fd,0) = 0x71; WFIFOL(fd,2) = cd->char_id; mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); - subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + subnet_map_ip = char_lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : map_server[i].ip); WFIFOW(fd,26) = ntows(htons(map_server[i].port)); // [!] LE byte order here [!] WFIFOSET(fd,28); @@ -867,66 +874,64 @@ int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd){ } int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){ - char email[40]; - int i, ch; + if (cmd == 0x68) FIFOSD_CHECK(46) + else if (cmd == 0x1fb) FIFOSD_CHECK(56) + else return 0; + { + char email[40]; + int i, ch; + int cid = RFIFOL(fd,2); - if (cmd == 0x68) FIFOSD_CHECK(46) - else if (cmd == 0x1fb) FIFOSD_CHECK(56) - else return 0; + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); + memcpy(email, RFIFOP(fd,6), 40); + RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); - { - int cid = RFIFOL(fd,2); + // Check if e-mail is correct + if(strcmpi(email, sd->email) && //email does not matches and + ( + strcmp("a@a.com", sd->email) || //it is not default email, or + (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default + )) { //Fail + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; // 00 = Incorrect Email address + WFIFOSET(fd,3); + return 0; + } - ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); - memcpy(email, RFIFOP(fd,6), 40); - RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); + // check if this char exists + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + { // Such a character does not exist in the account + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + return 0; + } - // Check if e-mail is correct - if(strcmpi(email, sd->email) && //email does not matches and - ( - strcmp("a@a.com", sd->email) || //it is not default email, or - (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default - )) { //Fail - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x70; - WFIFOB(fd,2) = 0; // 00 = Incorrect Email address - WFIFOSET(fd,3); - return 0; - } + // remove char from list and compact it + for(ch = i; ch < MAX_CHARS-1; ch++) + sd->found_char[ch] = sd->found_char[ch+1]; + sd->found_char[MAX_CHARS-1] = -1; - // check if this char exists - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - { // Such a character does not exist in the account - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x70; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - return 0; - } - - // remove char from list and compact it - for(ch = i; ch < MAX_CHARS-1; ch++) - sd->found_char[ch] = sd->found_char[ch+1]; - sd->found_char[MAX_CHARS-1] = -1; - - /* Delete character */ - if(char_delete_char_sql(cid)<0){ - //can't delete the char - //either SQL error or can't delete by some CONFIG conditions - //del fail - WFIFOHEAD(fd,3); - WFIFOW(fd, 0) = 0x70; - WFIFOB(fd, 2) = 0; - WFIFOSET(fd, 3); - return 0; - } - /* Char successfully deleted.*/ - WFIFOHEAD(fd,2); - WFIFOW(fd,0) = 0x6f; - WFIFOSET(fd,2); - } - return 1; + /* Delete character */ + if(char_delete_char_sql(cid)<0){ + //can't delete the char + //either SQL error or can't delete by some CONFIG conditions + //del fail + WFIFOHEAD(fd,3); + WFIFOW(fd, 0) = 0x70; + WFIFOB(fd, 2) = 0; + WFIFOSET(fd, 3); + return 0; + } + /* Char successfully deleted.*/ + WFIFOHEAD(fd,2); + WFIFOW(fd,0) = 0x6f; + WFIFOSET(fd,2); + } + return 1; } // R 0187 .l @@ -941,97 +946,96 @@ int chclif_parse_keepalive(int fd){ // R 08fc .l .24B // R 028d .l .l .24B int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd){ - if(cmd == 0x8fc) FIFOSD_CHECK(30) - if(cmd == 0x28d) FIFOSD_CHECK(34) - else return 0; + int i, cid=0; + char name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1]; - { - int i, cid=0; - char name[NAME_LENGTH]; - char esc_name[NAME_LENGTH*2+1]; - safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH); + if(cmd == 0x8fc){ + FIFOSD_CHECK(30) + cid =RFIFOL(fd,2); + safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH); + RFIFOSKIP(fd,30); + } + else if(cmd == 0x28d) { + FIFOSD_CHECK(34) + int aid = RFIFOL(fd,2); + cid =RFIFOL(fd,6); + safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH); + RFIFOSKIP(fd,34); + if( aid != sd->account_id ) + return 0; + } - if(cmd == 0x8fc){ - cid =RFIFOL(fd,2); - RFIFOSKIP(fd,30); - } - else if(cmd == 0x28d) { - int aid = RFIFOL(fd,2); - cid =RFIFOL(fd,6); - if( aid != sd->account_id ) - return 0; - RFIFOSKIP(fd,34); - } + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + return 0; - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - return 0; + normalize_name(name,TRIM_CHARS); + Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( !char_check_char_name(name,esc_name) ) + { + i = 1; + safestrncpy(sd->new_name, name, NAME_LENGTH); + } + else + i = 0; - normalize_name(name,TRIM_CHARS); - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( !char_check_char_name(name,esc_name) ) - { - i = 1; - safestrncpy(sd->new_name, name, NAME_LENGTH); - } - else - i = 0; - - WFIFOHEAD(fd, 4); - WFIFOW(fd,0) = 0x28e; - WFIFOW(fd,2) = i; - WFIFOSET(fd,4); - } - return 1; + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x28e; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + return 1; } // 0x28f .L int chclif_parse_ackrename(int fd, struct char_session_data* sd){ - // 0: Successful - // 1: This character's name has already been changed. You cannot change a character's name more than once. - // 2: User information is not correct. - // 3: You have failed to change this character's name. - // 4: Another user is using this character name, so please select another one. - FIFOSD_CHECK(6) + // 0: Successful + // 1: This character's name has already been changed. You cannot change a character's name more than once. + // 2: User information is not correct. + // 3: You have failed to change this character's name. + // 4: Another user is using this character name, so please select another one. + FIFOSD_CHECK(6) + { + int i; + int cid = RFIFOL(fd,2); + RFIFOSKIP(fd,6); - { - int i; - int cid = RFIFOL(fd,2); - RFIFOSKIP(fd,6); + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + return 0; + i = char_rename_char_sql(sd, cid); - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - return 0; - i = char_rename_char_sql(sd, cid); + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x290; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + } + return 1; +} - WFIFOHEAD(fd, 4); - WFIFOW(fd,0) = 0x290; - WFIFOW(fd,2) = i; - WFIFOSET(fd,4); - } - return 1; +int chclif_ack_captcha(int fd){ + WFIFOHEAD(fd,5); + WFIFOW(fd,0) = 0x7e9; + WFIFOW(fd,2) = 5; + WFIFOB(fd,4) = 1; + WFIFOSET(fd,5); + return 1; } // R 07e5 .w .l int chclif_parse_reqcaptcha(int fd){ - WFIFOHEAD(fd,5); - WFIFOW(fd,0) = 0x7e9; - WFIFOW(fd,2) = 5; - WFIFOB(fd,4) = 1; - WFIFOSET(fd,5); - RFIFOSKIP(fd,8); - return 1; + //FIFOSD_CHECK(8) + RFIFOSKIP(fd,8); + chclif_ack_captcha(fd); + return 1; } // R 07e7 .w .l .b10 .b14 int chclif_parse_chkcaptcha(int fd){ - WFIFOHEAD(fd,5); - WFIFOW(fd,0) = 0x7e9; - WFIFOW(fd,2) = 5; - WFIFOB(fd,4) = 1; - WFIFOSET(fd,5); - RFIFOSKIP(fd,32); - return 1; + //FIFOSD_CHECK(32) + RFIFOSKIP(fd,32); + chclif_ack_captcha(fd); + return 1; } /** @@ -1043,6 +1047,7 @@ int chclif_parse(int fd) { unsigned short cmd; struct char_session_data* sd = (struct char_session_data*)session[fd]->session_data; uint32 ipl = session[fd]->client_addr; + int next=0; // disconnect any player if no login-server. if(login_fd < 0) @@ -1066,43 +1071,43 @@ int chclif_parse(int fd) { while( RFIFOREST(fd) >= 2 ) { cmd = RFIFOW(fd,0); + if(next==-1) return 0; // avoid processing of followup packets (prev was probably incomplete) switch( cmd ) { - - case 0x65: chclif_parse_reqtoconnect(fd,sd,ipl); break; + case 0x65: next=chclif_parse_reqtoconnect(fd,sd,ipl); break; // char select - case 0x66: chclif_parse_charselect(fd,sd,ipl); break; + case 0x66: next=chclif_parse_charselect(fd,sd,ipl); break; // createnewchar - case 0x970: chclif_parse_createnewchar(fd,sd,cmd); break; - case 0x67: chclif_parse_createnewchar(fd,sd,cmd); break; + case 0x970: next=chclif_parse_createnewchar(fd,sd,cmd); break; + case 0x67: next=chclif_parse_createnewchar(fd,sd,cmd); break; // delete char - case 0x68: chclif_parse_delchar(fd,sd,cmd); break; // - case 0x1fb: chclif_parse_delchar(fd,sd,cmd); break; // 2004-04-19aSakexe+ langtype 12 char deletion packet + case 0x68: next=chclif_parse_delchar(fd,sd,cmd); break; // + case 0x1fb: next=chclif_parse_delchar(fd,sd,cmd); break; // 2004-04-19aSakexe+ langtype 12 char deletion packet // client keep-alive packet (every 12 seconds) - case 0x187: chclif_parse_keepalive(fd); break; + case 0x187: next=chclif_parse_keepalive(fd); break; // char rename - case 0x8fc: chclif_parse_reqrename(fd,sd,cmd); break; //request - case 0x28d: chclif_parse_reqrename(fd,sd,cmd); break; //request - case 0x28f: chclif_parse_ackrename(fd,sd); break; //Confirm change name. + case 0x8fc: next=chclif_parse_reqrename(fd,sd,cmd); break; //request + case 0x28d: next=chclif_parse_reqrename(fd,sd,cmd); break; //request + case 0x28f: next=chclif_parse_ackrename(fd,sd); break; //Confirm change name. // captcha - case 0x7e5: chclif_parse_reqcaptcha(fd); break; // captcha code request (not implemented) - case 0x7e7: chclif_parse_chkcaptcha(fd); break; // captcha code check (not implemented) + case 0x7e5: next=chclif_parse_reqcaptcha(fd); break; // captcha code request (not implemented) + case 0x7e7: next=chclif_parse_chkcaptcha(fd); break; // captcha code check (not implemented) // deletion timer request - case 0x827: chclif_parse_char_delete2_req(fd, sd); break; + case 0x827: next=chclif_parse_char_delete2_req(fd, sd); break; // deletion accept request - case 0x829: chclif_parse_char_delete2_accept(fd, sd); break; + case 0x829: next=chclif_parse_char_delete2_accept(fd, sd); break; // deletion cancel request - case 0x82b: chclif_parse_char_delete2_cancel(fd, sd); break; + case 0x82b: next=chclif_parse_char_delete2_cancel(fd, sd); break; // login as map-server case 0x2af8: chclif_parse_maplogin(fd); return 0; // avoid processing of followup packets here //pincode - case 0x8b8: chclif_parse_pincode_check( fd, sd ); break; // checks the entered pin - case 0x8c5: chclif_parse_reqpincode_window(fd,sd); break; // request for PIN window - case 0x8be: chclif_parse_pincode_change( fd, sd ); break; // pincode change request - case 0x8ba: chclif_parse_pincode_setnew( fd, sd ); break; // activate PIN system and set first PIN + case 0x8b8: next=chclif_parse_pincode_check( fd, sd ); break; // checks the entered pin + case 0x8c5: next=chclif_parse_reqpincode_window(fd,sd); break; // request for PIN window + case 0x8be: next=chclif_parse_pincode_change( fd, sd ); break; // pincode change request + case 0x8ba: next=chclif_parse_pincode_setnew( fd, sd ); break; // activate PIN system and set first PIN // character movement request - case 0x8d4: chclif_parse_moveCharSlot(fd,sd); break; - case 0x9a1: chclif_parse_req_charlist(fd,sd); break; + case 0x8d4: next=chclif_parse_moveCharSlot(fd,sd); break; + case 0x9a1: next=chclif_parse_req_charlist(fd,sd); break; // unknown packet received default: ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); diff --git a/src/char/char_clif.h b/src/char/char_clif.h index 76b37f2dca..143ef783d7 100644 --- a/src/char/char_clif.h +++ b/src/char/char_clif.h @@ -46,6 +46,7 @@ int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd); int chclif_parse_keepalive(int fd); int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd); int chclif_parse_ackrename(int fd, struct char_session_data* sd); +int chclif_ack_captcha(int fd); int chclif_parse_reqcaptcha(int fd); int chclif_parse_chkcaptcha(int fd); diff --git a/src/char/char_logif.c b/src/char/char_logif.c index 0c9ac7d2e3..6149d5cab9 100644 --- a/src/char/char_logif.c +++ b/src/char/char_logif.c @@ -22,7 +22,6 @@ void chlogif_on_ready(void); void chlogif_on_disconnect(void); - int chlogif_pincode_notifyLoginPinError( int account_id ){ if (login_fd > 0 && session[login_fd] && !session[login_fd]->flag.eof){ WFIFOHEAD(login_fd,6); @@ -183,7 +182,7 @@ void chlogif_send_setallaccoffline(int fd){ } int chlogif_send_setaccoffline(int fd, int aid){ - if (loginif_isconnected()){ + if (chlogif_isconnected()){ WFIFOHEAD(fd,6); WFIFOW(fd,0) = 0x272c; WFIFOL(fd,2) = aid; @@ -492,9 +491,94 @@ int chlogif_parse_updip(int fd, struct char_session_data* sd){ return 1; } +/** + * Send to login-serv the request of banking operation from map + * HA 0x2740L B L + * @param account_id + * @param type : 0 = select, 1 = update + * @param data + * @return + */ +int chlogif_BankingReq(int32 account_id, int8 type, int32 data){ + loginif_check(-1); + + WFIFOHEAD(login_fd,11); + WFIFOW(login_fd,0) = 0x2740; + WFIFOL(login_fd,2) = account_id; + WFIFOB(login_fd,6) = type; + WFIFOL(login_fd,7) = data; + WFIFOSET(login_fd,11); + return 0; +} + +/* + * Received the banking data from login and transmit it to all map-serv + * AH 0x2741L L B + * HZ 0x2b29 L L + */ +int chlogif_parse_BankingAck(int fd){ + if (RFIFOREST(fd) < 11) + return -1; + else { + uint32 aid = RFIFOL(fd,2); + int32 bank_vault = RFIFOL(fd,6); + char not_fw = RFIFOB(fd,10); + RFIFOSKIP(fd,11); + + if(not_fw==0) chmapif_BankingAck(aid, bank_vault); + } + return 1; +} + +/* + * AH 0x2743 + * We received the info from login-serv, transmit it to map + */ +int chlogif_parse_vipack(int fd) { +#ifdef VIP_ENABLE + if (RFIFOREST(fd) < 20) + return -1; + else { + uint32 aid = RFIFOL(fd,2); //aid + uint32 vip_time = RFIFOL(fd,6); //vip_time + uint8 isvip = RFIFOB(fd,10); //isvip + uint32 groupid = RFIFOL(fd,11); //new group id + uint8 isgm = RFIFOB(fd,15); //isgm + int mapfd = RFIFOL(fd,16); //link to mapserv for ack + RFIFOSKIP(fd,20); + mapif_vipack(mapfd,aid,vip_time,isvip,isgm,groupid); + } +#endif + return 1; +} + +/** + * HZ 0x2b2b + * Request vip data from loginserv + * @param aid : account_id to request the vip data + * @param type : &2 define new duration, &1 load info + * @param add_vip_time : tick to add to vip timestamp + * @param mapfd: link to mapserv for ack + * @return 0 if success + */ +int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd) { + loginif_check(-1); +#ifdef VIP_ENABLE + WFIFOHEAD(login_fd,15); + WFIFOW(login_fd,0) = 0x2742; + WFIFOL(login_fd,2) = aid; //aid + WFIFOB(login_fd,6) = type; //type + WFIFOL(login_fd,7) = timediff; //req_inc_duration + WFIFOL(login_fd,11) = mapfd; //req_inc_duration + WFIFOSET(login_fd,15); +#endif + return 0; +} + + int chlogif_parse(int fd) { struct char_session_data* sd = NULL; - + int next=0; // only process data from the login-server if( fd != login_fd ) { ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd); @@ -524,30 +608,30 @@ int chlogif_parse(int fd) { while(RFIFOREST(fd) >= 2) { uint16 command = RFIFOW(fd,0); + if(next==-1) return 0; //do not parse next data switch( command ) { - case 0x2741: loginif_parse_BankingAck(fd); break; - case 0x2743: loginif_parse_vipack(fd); break; - + case 0x2741: next=chlogif_parse_BankingAck(fd); break; + case 0x2743: next=chlogif_parse_vipack(fd); break; // acknowledgement of connect-to-loginserver request - case 0x2711: chlogif_parse_ackconnect(fd,sd); break; + case 0x2711: next=chlogif_parse_ackconnect(fd,sd); break; // acknowledgement of account authentication request - case 0x2713: chlogif_parse_ackaccreq(fd, sd); break; + case 0x2713: next=chlogif_parse_ackaccreq(fd, sd); break; // account data - case 0x2717: chlogif_parse_reqaccdata(fd, sd); break; + case 0x2717: next=chlogif_parse_reqaccdata(fd, sd); break; // login-server alive packet - case 0x2718: chlogif_parse_keepalive(fd, sd); break; + case 0x2718: next=chlogif_parse_keepalive(fd, sd); break; // changesex reply - case 0x2723: chlogif_parse_ackchangesex(fd, sd); break; + case 0x2723: next=chlogif_parse_ackchangesex(fd, sd); break; // reply to an account_reg2 registry request - case 0x2729: chlogif_parse_ackacc2req(fd, sd); break; + case 0x2729: next=chlogif_parse_ackacc2req(fd, sd); break; // State change of account/ban notification (from login-server) - case 0x2731: chlogif_parse_accbannotification(fd, sd); break; + case 0x2731: next=chlogif_parse_accbannotification(fd, sd); break; // Login server request to kick a character out. [Skotlex] - case 0x2734: chlogif_parse_askkick(fd,sd); break; + case 0x2734: next=chlogif_parse_askkick(fd,sd); break; // ip address update signal from login server - case 0x2735: chlogif_parse_updip(fd,sd); break; + case 0x2735: next=chlogif_parse_updip(fd,sd); break; default: ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command); set_eof(fd); @@ -592,6 +676,10 @@ int chlogif_check_connect_logserver(int tid, unsigned int tick, int id, intptr_t +int chlogif_isconnected(){ + return (login_fd > 0 && session[login_fd] && !session[login_fd]->flag.eof); +} + void do_init_chlogif(void) { // establish char-login connection if not present add_timer_func_list(chlogif_check_connect_logserver, "check_connect_login_server"); diff --git a/src/char/char_logif.h b/src/char/char_logif.h index 47b6d7e84e..4812393460 100644 --- a/src/char/char_logif.h +++ b/src/char/char_logif.h @@ -35,7 +35,14 @@ int chlogif_parse_accbannotification(int fd, struct char_session_data* sd); int chlogif_parse_askkick(int fd, struct char_session_data* sd); int chlogif_parse_updip(int fd, struct char_session_data* sd); +int chlogif_BankingReq(int32 account_id, int8 type, int32 data); +int chlogif_parse_BankingAck(int fd); +int chlogif_parse_vipack(int fd); +int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd); + int chlogif_parse(int fd); + +int chlogif_isconnected(); int chlogif_check_connect_logserver(int tid, unsigned int tick, int id, intptr_t data); void do_init_chlogif(void); void chlogif_reset(void); @@ -44,6 +51,9 @@ void chlogif_on_disconnect(void); void chlogif_on_ready(void); void do_final_chlogif(void); + +#define loginif_check(a) { if(!chlogif_isconnected()) return a; } + #ifdef __cplusplus } #endif diff --git a/src/char/char_mapif.c b/src/char/char_mapif.c index dc07031b6c..a84b2cc8d7 100644 --- a/src/char/char_mapif.c +++ b/src/char/char_mapif.c @@ -14,6 +14,7 @@ #include "../common/strlib.h" #include "inter.h" #include "char.h" +#include "char_logif.h" #include "char_mapif.h" #include @@ -172,7 +173,7 @@ void chmapif_sendall_playercount(int users){ int chmapif_parse_getmapname(int fd, int id){ int j = 0, i = 0; if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; + return -1; //Retain what map-index that map-serv contains memset(map_server[id].map, 0, sizeof(map_server[id].map)); @@ -195,11 +196,11 @@ int chmapif_parse_getmapname(int fd, int id){ chmapif_send_fame_list(fd); //Send fame list. { - unsigned char buf[16384]; int x; if (j == 0) { ShowWarning("Map-server %d has NO maps.\n", id); } else { + unsigned char buf[16384]; // Transmitting maps information to the other map-servers WBUFW(buf,0) = 0x2b04; WBUFW(buf,2) = j * 4 + 10; @@ -238,7 +239,7 @@ int chmapif_parse_getmapname(int fd, int id){ */ int chmapif_parse_askscdata(int fd){ if (RFIFOREST(fd) < 10) - return 0; + return -1; { #ifdef ENABLE_SC_SAVING int aid, cid; @@ -277,10 +278,6 @@ int chmapif_parse_askscdata(int fd){ WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); WFIFOW(fd,12) = count; WFIFOSET(fd,WFIFOW(fd,2)); - - //Clear the data once loaded. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, aid, cid) ) - Sql_ShowDebug(sql_handle); } } Sql_FreeResult(sql_handle); @@ -298,7 +295,7 @@ int chmapif_parse_askscdata(int fd){ */ int chmapif_parse_getusercount(int fd, int id){ if (RFIFOREST(fd) < 4) - return 0; + return -1; if (RFIFOW(fd,2) != map_server[id].users) { map_server[id].users = RFIFOW(fd,2); ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id); @@ -316,7 +313,7 @@ int chmapif_parse_getusercount(int fd, int id){ int chmapif_parse_regmapuser(int fd, int id){ int i; if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; + return -1; { //TODO: When data mismatches memory, update guild/party online/offline states. int aid, cid; @@ -353,7 +350,7 @@ int chmapif_parse_regmapuser(int fd, int id){ */ int chmapif_parse_reqsavechar(int fd, int id){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; + return -1; { int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2); struct online_char_data* character; @@ -399,7 +396,7 @@ int chmapif_parse_reqsavechar(int fd, int id){ */ int chmapif_parse_authok(int fd){ if( RFIFOREST(fd) < 19 ) - return 0; + return -1; else{ int account_id = RFIFOL(fd,2); uint32 login_id1 = RFIFOL(fd,6); @@ -427,6 +424,7 @@ int chmapif_parse_authok(int fd){ node->login_id2 = login_id2; //node->sex = 0; node->ip = ntohl(ip); + node->version = version; //upd version for mapserv //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) //node->gmlevel = 0; idb_put(auth_db, account_id, node); @@ -437,7 +435,6 @@ int chmapif_parse_authok(int fd){ struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id); if( character != NULL ){ character->pincode_success = true; - character->version = version; } } @@ -454,7 +451,7 @@ int chmapif_parse_authok(int fd){ //Request to save skill cooldown data int chmapif_parse_req_saveskillcooldown(int fd){ if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) - return 0; + return -1; else { int count, aid, cid; aid = RFIFOL(fd,4); @@ -487,7 +484,7 @@ int chmapif_parse_req_saveskillcooldown(int fd){ //Request skillcooldown data 0x2b0a int chmapif_parse_req_skillcooldown(int fd){ if (RFIFOREST(fd) < 10) - return 0; + return -1; else { int aid, cid; aid = RFIFOL(fd,2); @@ -539,7 +536,7 @@ int chmapif_parse_req_skillcooldown(int fd){ */ int chmapif_parse_reqchangemapserv(int fd){ if (RFIFOREST(fd) < 39) - return 0; + return -1; { int map_id, map_fd = -1; struct mmo_charstatus* char_data; @@ -616,7 +613,7 @@ int chmapif_parse_reqchangemapserv(int fd){ */ int chmapif_parse_askrmfriend(int fd){ if (RFIFOREST(fd) < 10) - return 0; + return -1; { int char_id, friend_id; char_id = RFIFOL(fd,2); @@ -639,7 +636,7 @@ int chmapif_parse_askrmfriend(int fd){ */ int chmapif_parse_reqcharname(int fd){ if (RFIFOREST(fd) < 6) - return 0; + return -1; WFIFOHEAD(fd,30); WFIFOW(fd,0) = 0x2b09; @@ -659,8 +656,8 @@ int chmapif_parse_reqcharname(int fd){ */ int chmapif_parse_reqnewemail(int fd){ if (RFIFOREST(fd) < 86) - return 0; - if (login_fd > 0) { // don't send request if no login-server + return -1; + if (chlogif_isconnected()) { // don't send request if no login-server WFIFOHEAD(login_fd,86); memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 .L .40B .40B WFIFOW(login_fd,0) = 0x2722; @@ -677,101 +674,98 @@ int chmapif_parse_reqnewemail(int fd){ */ int chmapif_parse_fwlog_changestatus(int fd){ if (RFIFOREST(fd) < 44) - return 0; - { - int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + return -1; + else { + int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline, 4-current group level > VIP group level char esc_name[NAME_LENGTH*2+1]; + char answer = true; - int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request) + int aid = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request) const char* name = (char*)RFIFOP(fd,6); // name of the target character - int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban - short year = RFIFOW(fd,32); - short month = RFIFOW(fd,34); - short day = RFIFOW(fd,36); - short hour = RFIFOW(fd,38); - short minute = RFIFOW(fd,40); - short second = RFIFOW(fd,42); + int operation = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5-changesex, 6-vip, 7-bank + int32 timediff = RFIFOL(fd,32); + int val1 = RFIFOL(fd,36); + int val2 = RFIFOL(fd,40); RFIFOSKIP(fd,44); Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, esc_name) ) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, esc_name) ) Sql_ShowDebug(sql_handle); - else - if( Sql_NumRows(sql_handle) == 0 ) - { + else if( Sql_NumRows(sql_handle) == 0 ) { result = 1; // 1-player not found } - else - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); - //FIXME: set proper result value? - else - { + result = 1; + } else { char name[NAME_LENGTH]; int account_id; char* data; Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); + Sql_FreeResult(sql_handle); - if( login_fd <= 0 ) + if(!chlogif_isconnected()) result = 3; // 3-login-server offline //FIXME: need to move this check to login server [ultramage] -// else -// if( acc != -1 && isGM(acc) < isGM(account_id) ) -// result = 2; // 2-gm level too low - else - switch( type ) { - case 1: // block + // if( acc != -1 && isGM(acc) < isGM(account_id) ) + // result = 2; // 2-gm level too low + else { + switch( operation ) { + case 1: // block WFIFOHEAD(login_fd,10); WFIFOW(login_fd,0) = 0x2724; WFIFOL(login_fd,2) = account_id; WFIFOL(login_fd,6) = 5; // new account status WFIFOSET(login_fd,10); - break; - case 2: // ban - WFIFOHEAD(login_fd,18); + break; + case 2: // ban + WFIFOHEAD(login_fd,10); WFIFOW(login_fd, 0) = 0x2725; WFIFOL(login_fd, 2) = account_id; - WFIFOW(login_fd, 6) = year; - WFIFOW(login_fd, 8) = month; - WFIFOW(login_fd,10) = day; - WFIFOW(login_fd,12) = hour; - WFIFOW(login_fd,14) = minute; - WFIFOW(login_fd,16) = second; - WFIFOSET(login_fd,18); - break; - case 3: // unblock + WFIFOL(login_fd, 6) = timediff; + WFIFOSET(login_fd,10); + break; + case 3: // unblock WFIFOHEAD(login_fd,10); WFIFOW(login_fd,0) = 0x2724; WFIFOL(login_fd,2) = account_id; WFIFOL(login_fd,6) = 0; // new account status WFIFOSET(login_fd,10); - break; - case 4: // unban + break; + case 4: // unban WFIFOHEAD(login_fd,6); WFIFOW(login_fd,0) = 0x272a; WFIFOL(login_fd,2) = account_id; WFIFOSET(login_fd,6); - break; - case 5: // changesex + break; + case 5: // changesex + answer = false; WFIFOHEAD(login_fd,6); WFIFOW(login_fd,0) = 0x2727; WFIFOL(login_fd,2) = account_id; WFIFOSET(login_fd,6); - break; - } + break; + case 6: + answer = (val1&4); // vip_req val1=type, &1 login send return, &2 update timestamp, &4 map send answer + chlogif_reqvipdata(account_id, val1, timediff, fd); + break; + case 7: + answer = (val1&1); //val&1 request answer, val1&2 save data + chlogif_BankingReq(aid, val1, val2); + break; + } //end switch operation + } //login is connected } - Sql_FreeResult(sql_handle); - - // send answer if a player ask, not if the server ask - if( acc != -1 && type != 5) { // Don't send answer for changesex + // send answer if a player asks, not if the server asks + if( aid != -1 && answer) { // Don't send answer for changesex WFIFOHEAD(fd,34); WFIFOW(fd, 0) = 0x2b0f; - WFIFOL(fd, 2) = acc; + WFIFOL(fd, 2) = aid; safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); - WFIFOW(fd,30) = type; + WFIFOW(fd,30) = operation; WFIFOW(fd,32) = result; WFIFOSET(fd,34); } @@ -785,9 +779,9 @@ int chmapif_parse_fwlog_changestatus(int fd){ * @param fd: wich fd to parse from * @return : 0 not enough data received, 1 success */ -int chmapif_parse_updfamelist(int fd){ +int chmapif_parse_req_alter_acc(int fd){ if (RFIFOREST(fd) < 11) - return 0; + return -1; { int cid = RFIFOL(fd, 2); int fame = RFIFOL(fd, 6); @@ -860,7 +854,7 @@ void chmapif_send_ackdivorce(int partner_id1, int partner_id2){ */ int chmapif_parse_reqdivorce(int fd){ if( RFIFOREST(fd) < 10 ) - return 0; + return -1; char_divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6)); RFIFOSKIP(fd,10); return 1; @@ -874,7 +868,7 @@ int chmapif_parse_reqdivorce(int fd){ */ int chmapif_parse_updmapinfo(int fd){ if( RFIFOREST(fd) < 14 ) - return 0; + return -1; { char esc_server_name[sizeof(charserv_config.server_name)*2+1]; Sql_EscapeString(sql_handle, esc_server_name, charserv_config.server_name); @@ -894,7 +888,7 @@ int chmapif_parse_updmapinfo(int fd){ */ int chmapif_parse_setcharoffline(int fd){ if (RFIFOREST(fd) < 6) - return 0; + return -1; char_set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); RFIFOSKIP(fd,10); return 1; @@ -923,7 +917,7 @@ int chmapif_parse_setalloffline(int fd, int id){ */ int chmapif_parse_setcharonline(int fd, int id){ if (RFIFOREST(fd) < 10) - return 0; + return -1; char_set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6)); RFIFOSKIP(fd,10); return 1; @@ -938,7 +932,7 @@ int chmapif_parse_setcharonline(int fd, int id){ */ int chmapif_parse_reqfamelist(int fd){ if (RFIFOREST(fd) < 2) - return 0; + return -1; char_read_fame_list(); chmapif_send_fame_list(-1); RFIFOSKIP(fd,2); @@ -953,7 +947,7 @@ int chmapif_parse_reqfamelist(int fd){ */ int chmapif_parse_save_scdata(int fd){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; + return -1; { #ifdef ENABLE_SC_SAVING int count, aid, cid; @@ -962,7 +956,11 @@ int chmapif_parse_save_scdata(int fd){ cid = RFIFOL(fd, 8); count = RFIFOW(fd, 12); - if( count > 0 ) + // Whatever comes from the mapserver, now is the time to drop previous entries + if( Sql_Query( sql_handle, "DELETE FROM `%s` where `account_id` = %d and `char_id` = %d;", schema_config.scdata_db, aid, cid ) != SQL_SUCCESS ){ + Sql_ShowDebug( sql_handle ); + } + else if( count > 0 ) { struct status_change_data data; StringBuf buf; @@ -1007,75 +1005,94 @@ int chmapif_parse_keepalive(int fd){ * @return : 0 not enough data received, 1 success */ int chmapif_parse_reqauth(int fd, int id){ - if (RFIFOREST(fd) < 19) - return 0; + if (RFIFOREST(fd) < 20) + return -1; - { - int account_id; - int char_id; - int login_id1; - char sex; - uint32 ip; - struct auth_node* node; - struct mmo_charstatus* cd; - struct mmo_charstatus char_dat; - DBMap* auth_db = char_get_authdb(); - DBMap* char_db_ = char_get_chardb(); + { + int account_id; + int char_id; + int login_id1; + char sex; + uint32 ip; + struct auth_node* node; + struct mmo_charstatus* cd; + struct mmo_charstatus char_dat; + bool autotrade; - account_id = RFIFOL(fd,2); - char_id = RFIFOL(fd,6); - login_id1 = RFIFOL(fd,10); - sex = RFIFOB(fd,14); - ip = ntohl(RFIFOL(fd,15)); - RFIFOSKIP(fd,19); + DBMap* auth_db = char_get_authdb(); + DBMap* char_db_ = char_get_chardb(); - node = (struct auth_node*)idb_get(auth_db, account_id); - cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); - if( cd == NULL ) - { //Really shouldn't happen. - char_mmo_char_fromsql(char_id, &char_dat, true); - cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); - } - if( runflag == CHARSERVER_ST_RUNNING && - cd != NULL && - node != NULL && - node->account_id == account_id && - node->char_id == char_id && - node->login_id1 == login_id1 && - node->sex == sex /*&& - node->ip == ip*/ ) - {// auth ok - cd->sex = sex; + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + login_id1 = RFIFOL(fd,10); + sex = RFIFOB(fd,14); + ip = ntohl(RFIFOL(fd,15)); + autotrade = RFIFOB(fd,19); + RFIFOSKIP(fd,20); - WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus)); - WFIFOW(fd,0) = 0x2afd; - WFIFOW(fd,2) = 25 + sizeof(struct mmo_charstatus); - WFIFOL(fd,4) = account_id; - WFIFOL(fd,8) = node->login_id1; - WFIFOL(fd,12) = node->login_id2; - WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" - WFIFOL(fd,20) = node->group_id; - WFIFOB(fd,24) = node->changing_mapservers; - memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); - WFIFOSET(fd, WFIFOW(fd,2)); + node = (struct auth_node*)idb_get(auth_db, account_id); + cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); + if( cd == NULL ) + { //Really shouldn't happen. + char_mmo_char_fromsql(char_id, &char_dat, true); + cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); + } + if( runflag == CHARSERVER_ST_RUNNING && autotrade && cd ){ + uint32 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; + cd->sex = sex; - // only use the auth once and mark user online - idb_remove(auth_db, account_id); - char_set_char_online(id, char_id, account_id); - } - else - {// auth failed - WFIFOHEAD(fd,19); - WFIFOW(fd,0) = 0x2b27; - WFIFOL(fd,2) = account_id; - WFIFOL(fd,6) = char_id; - WFIFOL(fd,10) = login_id1; - WFIFOB(fd,14) = sex; - WFIFOL(fd,15) = htonl(ip); - WFIFOSET(fd,19); - } - } - return 1; + WFIFOHEAD(fd,mmo_charstatus_len); + WFIFOW(fd,0) = 0x2afd; + WFIFOW(fd,2) = mmo_charstatus_len; + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = 0; + WFIFOL(fd,12) = 0; + WFIFOL(fd,16) = 0; + WFIFOL(fd,20) = 0; + WFIFOB(fd,24) = 0; + memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); + WFIFOSET(fd, WFIFOW(fd,2)); + + char_set_char_online(id, char_id, account_id); + } else if( runflag == CHARSERVER_ST_RUNNING && + cd != NULL && + node != NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 && + node->sex == sex /*&& + node->ip == ip*/ ) + {// auth ok + uint32 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; + cd->sex = sex; + + WFIFOHEAD(fd,mmo_charstatus_len); + WFIFOW(fd,0) = 0x2afd; + WFIFOW(fd,2) = mmo_charstatus_len; + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = node->login_id1; + WFIFOL(fd,12) = node->login_id2; + WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" + WFIFOL(fd,20) = node->group_id; + WFIFOB(fd,24) = node->changing_mapservers; + memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); + WFIFOSET(fd, WFIFOW(fd,2)); + + // only use the auth once and mark user online + idb_remove(auth_db, account_id); + char_set_char_online(id, char_id, account_id); + } else {// auth failed + WFIFOHEAD(fd,19); + WFIFOW(fd,0) = 0x2b27; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = char_id; + WFIFOL(fd,10) = login_id1; + WFIFOB(fd,14) = sex; + WFIFOL(fd,15) = htonl(ip); + WFIFOSET(fd,19); + } + } + return 1; } /** @@ -1084,7 +1101,8 @@ int chmapif_parse_reqauth(int fd, int id){ * @return : 0 not enough data received, 1 success */ int chmapif_parse_updmapip(int fd, int id){ - if (RFIFOREST(fd) < 6) return 0; + if (RFIFOREST(fd) < 6) + return -1; map_server[id].ip = ntohl(RFIFOL(fd, 2)); ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(map_server[id].ip)); RFIFOSKIP(fd,6); @@ -1098,7 +1116,7 @@ int chmapif_parse_updmapip(int fd, int id){ */ int chmapif_parse_fw_configstats(int fd){ if( RFIFOREST(fd) < RFIFOW(fd,4) ) - return 0;/* packet wasn't fully received yet (still fragmented) */ + return -1;/* packet wasn't fully received yet (still fragmented) */ else { int sfd;/* stat server fd */ RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */ @@ -1119,7 +1137,258 @@ int chmapif_parse_fw_configstats(int fd){ return 1; } +int chmapif_parse_updfamelist(int fd){ + if (RFIFOREST(fd) < 11) + return -1; + { + int cid = RFIFOL(fd, 2); + int fame = RFIFOL(fd, 6); + char type = RFIFOB(fd, 10); + int size; + struct fame_list* list; + int player_pos; + int fame_pos; + switch(type) + { + case 1: size = fame_list_size_smith; list = smith_fame_list; break; + case 2: size = fame_list_size_chemist; list = chemist_fame_list; break; + case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; + default: size = 0; list = NULL; break; + } + + ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player + ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be + + if( player_pos == size && fame_pos == size ) + ;// not on list and not enough fame to get on it + else if( fame_pos == player_pos ) + {// same position + list[player_pos].fame = fame; + chmapif_update_fame_list(type, player_pos, fame); + } + else + {// move in the list + if( player_pos == size ) + {// new ranker - not in the list + ARR_MOVE(size - 1, fame_pos, list, struct fame_list); + list[fame_pos].id = cid; + list[fame_pos].fame = fame; + char_loadName(cid, list[fame_pos].name); + } + else + {// already in the list + if( fame_pos == size ) + --fame_pos;// move to the end of the list + ARR_MOVE(player_pos, fame_pos, list, struct fame_list); + list[fame_pos].fame = fame; + } + chmapif_send_fame_list(-1); + } + + RFIFOSKIP(fd,11); + } + return 1; +} + +//HZ 0x2b29 L L +int chmapif_BankingAck(int32 account_id, int32 bank_vault){ + unsigned char buf[11]; + WBUFW(buf,0) = 0x2b29; + WBUFL(buf,2) = account_id; + WBUFL(buf,6) = bank_vault; + chmapif_sendall(buf, 10); //inform all maps-attached + return 1; +} + + +/* + * HZ 0x2b2b + * Transmist vip data to mapserv + */ +int chmapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid) { +#ifdef VIP_ENABLE + uint8 buf[16]; + WBUFW(buf,0) = 0x2b2b; + WBUFL(buf,2) = aid; + WBUFL(buf,6) = vip_time; + WBUFB(buf,10) = isvip; + WBUFB(buf,11) = isgm; + WBUFL(buf,12) = groupid; + chmapif_send(mapfd,buf,16); // inform the mapserv back +#endif + return 0; +} + +int chmapif_parse_reqcharban(int fd){ + if (RFIFOREST(fd) < 10+NAME_LENGTH) + return -1; + else { + //int aid = RFIFOL(fd,2); aid of player who as requested the ban + int timediff = RFIFOL(fd,6); + const char* name = (char*)RFIFOP(fd,10); // name of the target character + RFIFOSKIP(fd,10+NAME_LENGTH); + + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, name) ) + Sql_ShowDebug(sql_handle); + else if( Sql_NumRows(sql_handle) == 0 ){ + return -1; // 1-player not found + } + else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){ + Sql_ShowDebug(sql_handle); + Sql_FreeResult(sql_handle); + return -1; + } else { + int t_cid=0,t_aid=0; + char* data; + time_t unban_time; + time_t now = time(NULL); + SqlStmt* stmt = SqlStmt_Malloc(sql_handle); + + Sql_GetData(sql_handle, 0, &data, NULL); t_aid = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); t_cid = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); unban_time = atol(data); + Sql_FreeResult(sql_handle); + + if(timediff<0 && unban_time==0) return 0; //attemp to reduce time of a non banned account ?!? + else if(unban_time now ) { + unsigned char buf[11]; + WBUFW(buf,0) = 0x2b14; + WBUFL(buf,2) = t_cid; + WBUFB(buf,6) = 2; + WBUFL(buf,7) = (unsigned int)unban_time; + chmapif_sendall(buf, 11); + // disconnect player if online on char-server + char_disconnect_player(t_aid); + } + } + } + return 0; +} + +int chmapif_parse_reqcharunban(int fd){ + if (RFIFOREST(fd) < 6) + return -1; + else { + int cid = RFIFOL(fd,2); + RFIFOSKIP(fd,6); + + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time` = '0' WHERE `char_id` = '%d' LIMIT 1", schema_config.char_db, cid) ) { + Sql_ShowDebug(sql_handle); + return -1; + } + } + return 0; +} + +/** [Cydh] +* Get bonus_script data(s) from table to load +* @param fd +*/ +int chmapif_bonus_script_get(int fd) { + if (RFIFOREST(fd) < 6) + return -1; + else { + int cid; + cid = RFIFOL(fd,2); + RFIFOSKIP(fd,6); + + if (SQL_ERROR == Sql_Query(sql_handle,"SELECT `script`, `tick`, `flag`, `type`, `icon` FROM `%s` WHERE `char_id`='%d'", + schema_config.bonus_script_db,cid)) + { + Sql_ShowDebug(sql_handle); + return 0; + } + if (Sql_NumRows(sql_handle) > 0) { + struct bonus_script_data bsdata; + int count; + char *data; + + WFIFOHEAD(fd,10+50*sizeof(struct bonus_script_data)); + WFIFOW(fd,0) = 0x2b2f; + WFIFOL(fd,4) = cid; + for (count = 0; count < 20 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count) { + Sql_GetData(sql_handle,0,&data,NULL); memcpy(bsdata.script,data,strlen(data)+1); + Sql_GetData(sql_handle,1,&data,NULL); bsdata.tick = atoi(data); + Sql_GetData(sql_handle,2,&data,NULL); bsdata.flag = atoi(data); + Sql_GetData(sql_handle,3,&data,NULL); bsdata.type = atoi(data); + Sql_GetData(sql_handle,4,&data,NULL); bsdata.icon = atoi(data); + memcpy(WFIFOP(fd,10+count*sizeof(struct bonus_script_data)),&bsdata,sizeof(struct bonus_script_data)); + } + if (count >= 20) + ShowWarning("Too many bonus_script for %d, some of them were not loaded.\n",cid); + if (count > 0) { + WFIFOW(fd,2) = 10 + count*sizeof(struct bonus_script_data); + WFIFOW(fd,8) = count; + WFIFOSET(fd,WFIFOW(fd,2)); + + //Clear the data once loaded. + if (SQL_ERROR == Sql_Query(sql_handle,"DELETE FROM `%s` WHERE `char_id`='%d'",schema_config.bonus_script_db,cid)) + Sql_ShowDebug(sql_handle); + ShowInfo("Loaded %d bonus_script for char_id: %d\n",count,cid); + } + } + Sql_FreeResult(sql_handle); + } + return 1; +} + +/** [Cydh] +* Save bonus_script data(s) to the table +* @param fd +*/ +int chmapif_bonus_script_save(int fd) { + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return -1; + else { + int count, cid; + + cid = RFIFOL(fd,4); + count = RFIFOW(fd,8); + + if (count > 0) { + struct bonus_script_data bs; + StringBuf buf; + int i; + char esc_script[MAX_BONUS_SCRIPT_LENGTH] = ""; + + StringBuf_Init(&buf); + StringBuf_Printf(&buf,"INSERT INTO `%s` (`char_id`, `script`, `tick`, `flag`, `type`, `icon`) VALUES ",schema_config.bonus_script_db); + for (i = 0; i < count; ++i) { + memcpy(&bs,RFIFOP(fd,10+i*sizeof(struct bonus_script_data)),sizeof(struct bonus_script_data)); + Sql_EscapeString(sql_handle,esc_script,bs.script); + if (i > 0) + StringBuf_AppendStr(&buf,", "); + StringBuf_Printf(&buf,"('%d','%s','%d','%d','%d','%d')",cid,esc_script,bs.tick,bs.flag,bs.type,bs.icon); + } + if (SQL_ERROR == Sql_QueryStr(sql_handle,StringBuf_Value(&buf))) + Sql_ShowDebug(sql_handle); + StringBuf_Destroy(&buf); + ShowInfo("Saved %d bonus_script for char_id: %d\n",count,cid); + } + RFIFOSKIP(fd,RFIFOW(fd,2)); + } + return 1; +} /** * Entry point from map-server to char-server. @@ -1130,6 +1399,7 @@ int chmapif_parse_fw_configstats(int fd){ */ int chmapif_parse(int fd){ int id; //mapserv id + int next=0; ARR_FIND( 0, ARRAYLENGTH(map_server), id, map_server[id].fd == fd ); if( id == ARRAYLENGTH(map_server) ) {// not a map server @@ -1146,45 +1416,51 @@ int chmapif_parse(int fd){ } while(RFIFOREST(fd) >= 2){ - switch(RFIFOW(fd,0)){ - case 0x2afa: chmapif_parse_getmapname(fd,id); break; - case 0x2afc: chmapif_parse_askscdata(fd); break; - case 0x2afe: chmapif_parse_getusercount(fd,id); break; //get nb user - case 0x2aff: chmapif_parse_regmapuser(fd,id); break; //register users - case 0x2b01: chmapif_parse_reqsavechar(fd,id); break; - case 0x2b02: chmapif_parse_authok(fd); break; - case 0x2b05: chmapif_parse_reqchangemapserv(fd); break; - case 0x2b07: chmapif_parse_askrmfriend(fd); break; - case 0x2b08: chmapif_parse_reqcharname(fd); break; - case 0x2b0a: chmapif_parse_req_skillcooldown(fd); break; - case 0x2b0c: chmapif_parse_reqnewemail(fd); break; - case 0x2b0e: chmapif_parse_fwlog_changestatus(fd); break; - case 0x2b10: chmapif_parse_updfamelist(fd); break; - case 0x2b11: chmapif_parse_reqdivorce(fd); break; - case 0x2b15: chmapif_parse_req_saveskillcooldown(fd); break; - case 0x2b16: chmapif_parse_updmapinfo(fd); break; - case 0x2b17: chmapif_parse_setcharoffline(fd); break; - case 0x2b18: chmapif_parse_setalloffline(fd,id); break; - case 0x2b19: chmapif_parse_setcharonline(fd,id); break; - case 0x2b1a: chmapif_parse_reqfamelist(fd); break; - case 0x2b1c: chmapif_parse_save_scdata(fd); break; - case 0x2b23: chmapif_parse_keepalive(fd); break; - case 0x2b26: chmapif_parse_reqauth(fd,id); break; - case 0x2736: chmapif_parse_updmapip(fd,id); break; - case 0x3008: chmapif_parse_fw_configstats(fd); break; - - default: - { - // inter server - packet - int r = inter_parse_frommap(fd); - if (r == 1) break; // processed - if (r == 2) return 0; // need more packet - // no inter server packet. no char server packet -> disconnect - ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0)); - set_eof(fd); - return 0; - } - } // switch + if(next==-1) return 0; //avoid processing rest of packet + + switch(RFIFOW(fd,0)){ + case 0x2736: next=chmapif_parse_updmapip(fd,id); break; + case 0x2afa: next=chmapif_parse_getmapname(fd,id); break; + case 0x2afc: next=chmapif_parse_askscdata(fd); break; + case 0x2afe: next=chmapif_parse_getusercount(fd,id); break; //get nb user + case 0x2aff: next=chmapif_parse_regmapuser(fd,id); break; //register users + case 0x2b01: next=chmapif_parse_reqsavechar(fd,id); break; + case 0x2b02: next=chmapif_parse_authok(fd); break; + case 0x2b05: next=chmapif_parse_reqchangemapserv(fd); break; + case 0x2b07: next=chmapif_parse_askrmfriend(fd); break; + case 0x2b08: next=chmapif_parse_reqcharname(fd); break; + case 0x2b0a: next=chmapif_parse_req_skillcooldown(fd); break; + case 0x2b0c: next=chmapif_parse_reqnewemail(fd); break; + case 0x2b0e: next=chmapif_parse_req_alter_acc(fd); break; + case 0x2b10: next=chmapif_parse_updfamelist(fd); break; + case 0x2b11: next=chmapif_parse_reqdivorce(fd); break; + case 0x2b15: next=chmapif_parse_req_saveskillcooldown(fd); break; + case 0x2b16: next=chmapif_parse_updmapinfo(fd); break; + case 0x2b17: next=chmapif_parse_setcharoffline(fd); break; + case 0x2b18: next=chmapif_parse_setalloffline(fd,id); break; + case 0x2b19: next=chmapif_parse_setcharonline(fd,id); break; + case 0x2b1a: next=chmapif_parse_reqfamelist(fd); break; + case 0x2b1c: next=chmapif_parse_save_scdata(fd); break; + case 0x2b23: next=chmapif_parse_keepalive(fd); break; + case 0x2b26: next=chmapif_parse_reqauth(fd,id); break; + case 0x2b28: chmapif_parse_reqcharban(fd); break; //charban + case 0x2b2a: chmapif_parse_reqcharunban(fd); break; //charunban + //case 0x2b2c: /*free*/; break; + case 0x2b2d: chmapif_bonus_script_get(fd); break; //Load data + case 0x2b2e: chmapif_bonus_script_save(fd); break;//Save data + case 0x3008: next=chmapif_parse_fw_configstats(fd); break; + default: + { + // inter server - packet + int r = inter_parse_frommap(fd); + if (r == 1) break; // processed + if (r == 2) return 0; // need more packet + // no inter server packet. no char server packet -> disconnect + ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0)); + set_eof(fd); + return 0; + } + } // switch } // while return 1; diff --git a/src/char/char_mapif.h b/src/char/char_mapif.h index 04ede959dc..0341d37dff 100644 --- a/src/char/char_mapif.h +++ b/src/char/char_mapif.h @@ -48,6 +48,13 @@ int chmapif_parse_reqauth(int fd, int id); int chmapif_parse_updmapip(int fd, int id); int chmapif_parse_fw_configstats(int fd); +int chmapif_BankingAck(int32 account_id, int32 bank_vault); +int chmapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid); +int chmapif_parse_reqcharban(int fd); +int chmapif_parse_reqcharunban(int fd); +int chmapif_bonus_script_get(int fd); +int chmapif_bonus_script_save(int fd); + int chmapif_parse(int fd); int chmapif_init(int fd); void chmapif_server_init(int id); From 06286ebe7c67dc33ecc989d4fef09ee8babf0deb Mon Sep 17 00:00:00 2001 From: lighta Date: Wed, 30 Apr 2014 00:23:28 -0400 Subject: [PATCH 3/7] Move and clean few more thing around Testing refact, looking good for now. --- src/char/char.c | 551 +---------------------------------------- src/char/char_clif.c | 67 ++++- src/char/char_clif.h | 1 + src/char/char_cnslif.c | 26 +- src/char/char_logif.c | 39 ++- src/char/char_logif.h | 1 + src/char/char_mapif.c | 2 + src/common/cli.h | 1 + 8 files changed, 129 insertions(+), 559 deletions(-) diff --git a/src/char/char.c b/src/char/char.c index 1acade574e..63d6a193e7 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -75,25 +75,7 @@ struct s_subnet { } subnet[16]; int subnet_count = 0; -int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid); -int loginif_reqvipdata(uint32 aid, uint8 type, int add_vip_time, int mapfd); -int loginif_parse_vipack(int fd); - -// Addon system -void moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ); - -int loginif_BankingReq(int32 account_id, int8 type, int32 data); -int loginif_parse_BankingAck(int fd); -int mapif_BankingAck(int32 account_id, int32 bank_vault); - - -//Bonus Script -void bonus_script_get(int fd);///Get bonus_script data -void bonus_script_save(int fd); ///Save bonus_script data - - int char_chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); -int delete_char_sql(int char_id); DBMap* auth_db; // int account_id -> struct auth_node* DBMap* online_char_db; // int account_id -> struct online_char_data* @@ -1753,158 +1735,6 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) } - -//---------------------------------------- -// Tell client how many pages, kRO sends 17 (Yommy) -//---------------------------------------- -void char_charlist_notify( int fd, struct char_session_data* sd ){ - int found=0, count=0, i=0; - for(i=0; ifound_char[i] != -1){ - found=1; - } - if(i%3 && found){ //each page contains 3char max - count++; - found=0; - } - } - - WFIFOHEAD(fd, 6); - WFIFOW(fd, 0) = 0x9a0; - // pages to req / send them all in 1 until mmo_chars_fromsql can split them up - WFIFOL(fd, 2) = count?count:1; - WFIFOSET(fd,6); -} - -void char_block_character( int fd, struct char_session_data* sd ); -int charblock_timer(int tid, unsigned int tick, int id, intptr_t data) -{ - struct char_session_data* sd=NULL; - int i=0; - ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == id); - - if(sd == NULL || sd->charblock_timer==INVALID_TIMER) //has disconected or was required to stop - return 0; - if (sd->charblock_timer != tid){ - sd->charblock_timer = INVALID_TIMER; - return 0; - } - char_block_character(i,sd); - return 0; -} -/* - * 0x20d .W 24B (HC_BLOCK_CHARACTER) - * L 20B (TAG_CHARACTER_BLOCK_INFO) - */ -void char_block_character( int fd, struct char_session_data* sd){ - int i=0, j=0, len=4; - time_t now = time(NULL); - - WFIFOHEAD(fd, 4+MAX_CHARS*24); - WFIFOW(fd, 0) = 0x20d; - - for(i=0; ifound_char[i] == -1) - continue; - if(sd->unban_time[i]){ - if( sd->unban_time[i] > now ) { - char szExpireDate[21]; - WFIFOL(fd, 4+j*24) = sd->found_char[i]; - timestamp2string(szExpireDate, 20, sd->unban_time[i], "%Y-%m-%d %H:%M:%S"); - memcpy(WFIFOP(fd,8+j*24),szExpireDate,20); - } - else { - WFIFOL(fd, 4+j*24) = 0; - sd->unban_time[i] = 0; - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time`='0' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, sd->found_char[i]) ) - Sql_ShowDebug(sql_handle); - } - len+=24; - j++; //pkt list idx - } - } - WFIFOW(fd, 2) = len; //packet len - WFIFOSET(fd,len); - - ARR_FIND(0, MAX_CHARS, i, sd->unban_time[i] > now); //sd->charslot only have productible char - if(i < MAX_CHARS ){ - sd->charblock_timer = add_timer( - gettick() + 10000, // each 10s resend that list - charblock_timer, sd->account_id, 0); - } -} - -void mmo_char_send099d(int fd, struct char_session_data *sd) { - WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF)); - WFIFOW(fd,0) = 0x99d; - WFIFOW(fd,2) = char_mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4; - WFIFOSET(fd,WFIFOW(fd,2)); -} - - -//---------------------------------------- -// Function to send characters to a player -//---------------------------------------- -int mmo_char_send006b(int fd, struct char_session_data* sd){ - int j, offset = 0; - bool newvers = (sd->version >= date2version(20100413)); - if(newvers) //20100413 - offset += 3; - if ( charserv_config.save_log ) - ShowInfo("Loading Char Data 6b ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); - - j = 24 + offset; // offset - WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF); - WFIFOW(fd,0) = 0x6b; - if(newvers){ //20100413 - WFIFOB(fd,4) = MAX_CHARS; // Max slots - WFIFOB(fd,5) = MAX_CHARS - sd->chars_billing - sd->chars_vip; // PremiumStartSlot - WFIFOB(fd,6) = MAX_CHARS - sd->chars_billing; // PremiumEndSlot - /* this+0x7 char dummy1_beginbilling */ - /* this+0x8 unsigned long code */ - /* this+0xc unsigned long time1 */ - /* this+0x10 unsigned long time2 */ - /* this+0x14 char dummy2_endbilling[7] */ - } - memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes 4-24 7-27 - j+=char_mmo_chars_fromsql(sd, WFIFOP(fd,j)); - WFIFOW(fd,2) = j; // packet len - WFIFOSET(fd,j); - - return 0; -} - -//---------------------------------------- -// Notify client about charselect window data [Ind] -//---------------------------------------- -void mmo_char_send082d(int fd, struct char_session_data* sd) { - if (charserv_config.save_log) - ShowInfo("Loading Char Data 82d ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); - WFIFOHEAD(fd,29); - WFIFOW(fd,0) = 0x82d; - WFIFOW(fd,2) = 29; - WFIFOB(fd,4) = MAX_CHARS - sd->chars_billing - sd->chars_vip; //NormalSlotNum - WFIFOB(fd,5) = sd->chars_vip; //PremiumSlotNum - WFIFOB(fd,6) = sd->chars_billing; //BillingSlotNum - WFIFOB(fd,7) = sd->char_slots; //ProducibleSlotNum - WFIFOB(fd,8) = sd->char_slots; //ValidSlotNum - memset(WFIFOP(fd,9), 0, 20); // unused bytes - WFIFOSET(fd,29); -} - -void mmo_char_send(int fd, struct char_session_data* sd){ - //ShowInfo("sd->version = %d\n",sd->version); - if(sd->version > date2version(20130000) ){ - mmo_char_send082d(fd,sd); - char_charlist_notify(fd,sd); - } - //else - //@FIXME dump from kro doesn't show 6b transmission - mmo_char_send006b(fd,sd); - if(sd->version > date2version(20060819) ) - char_block_character(fd,sd); -} - int char_married(int pl1, int pl2) { if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", schema_config.char_db, pl1) ) @@ -2018,106 +1848,6 @@ void char_auth_ok(int fd, struct char_session_data *sd) { // continues when account data is received... } -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); -void mapif_server_reset(int id); - - - -/// Resets all the data. -void loginif_reset(void) -{ - int id; - // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS] - for( id = 0; id < ARRAYLENGTH(map_server); ++id ) - mapif_server_reset(id); - flush_fifos(); - exit(EXIT_FAILURE); -} - - -/// Checks the conditions for the server to stop. -/// Releases the cookie when all characters are saved. -/// If all the conditions are met, it stops the core loop. -void loginif_check_shutdown(void) -{ - if( runflag != CHARSERVER_ST_SHUTDOWN ) - return; - runflag = CORE_ST_STOP; -} - - -/// Called when the connection to Login Server is disconnected. -void loginif_on_disconnect(void) -{ - ShowWarning("Connection to Login Server lost.\n\n"); -} - - -/// Called when all the connection steps are completed. -void loginif_on_ready(void) -{ - int i; - - loginif_check_shutdown(); - - //Send online accounts to login server. - send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0); - - // if no map-server already connected, display a message... - ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd > 0 && map_server[i].map[0] ); - if( i == ARRAYLENGTH(map_server) ) - ShowStatus("Awaiting maps from map-server.\n"); -} - - -int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data); -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); - -void do_init_loginif(void) -{ - // establish char-login connection if not present - add_timer_func_list(check_connect_login_server, "check_connect_login_server"); - add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000); - - // send a list of all online account IDs to login server - add_timer_func_list(send_accounts_tologin, "send_accounts_tologin"); - add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour -} - -void do_final_loginif(void) -{ - if( login_fd != -1 ) - { - do_close(login_fd); - login_fd = -1; - } -} - -int char_request_accreg2(int account_id, int char_id) -{ - loginif_check(0); - - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd,0) = 0x272e; - WFIFOL(login_fd,2) = account_id; - WFIFOL(login_fd,6) = char_id; - WFIFOSET(login_fd,10); - return 1; -} - -//Send packet forward to login-server for account saving -int char_save_accreg2(unsigned char* buf, int len) -{ - loginif_check(0); - - WFIFOHEAD(login_fd,len+4); - memcpy(WFIFOP(login_fd,4), buf, len); - WFIFOW(login_fd,0) = 0x2728; - WFIFOW(login_fd,2) = len+4; - WFIFOSET(login_fd,len+4); - return 1; -} - void char_read_fame_list(void) { int i; @@ -2176,43 +1906,6 @@ void char_read_fame_list(void) Sql_FreeResult(sql_handle); } -// Send map-servers the fame ranking lists -int char_send_fame_list(int fd) -{ - int i, len = 8; - unsigned char buf[32000]; - - WBUFW(buf,0) = 0x2b1b; - - for(i = 0; i < fame_list_size_smith && smith_fame_list[i].id; i++) { - memcpy(WBUFP(buf, len), &smith_fame_list[i], sizeof(struct fame_list)); - len += sizeof(struct fame_list); - } - // add blacksmith's block length - WBUFW(buf, 6) = len; - - for(i = 0; i < fame_list_size_chemist && chemist_fame_list[i].id; i++) { - memcpy(WBUFP(buf, len), &chemist_fame_list[i], sizeof(struct fame_list)); - len += sizeof(struct fame_list); - } - // add alchemist's block length - WBUFW(buf, 4) = len; - - for(i = 0; i < fame_list_size_taekwon && taekwon_fame_list[i].id; i++) { - memcpy(WBUFP(buf, len), &taekwon_fame_list[i], sizeof(struct fame_list)); - len += sizeof(struct fame_list); - } - // add total packet length - WBUFW(buf, 2) = len; - - if (fd != -1) - chmapif_send(fd, buf, len); - else - chmapif_sendall(buf, len); - - return 0; -} - //Loads a character's name and stores it in the buffer given (must be NAME_LENGTH in size) //Returns 1 on found, 0 on not found (buffer is filled with Unknown char name) int char_loadName(int char_id, char* name){ @@ -2234,77 +1927,6 @@ int char_loadName(int char_id, char* name){ return 0; } -int search_mapserver(unsigned short map, uint32 ip, uint16 port); - - -/// Initializes a server structure. -void mapif_server_init(int id) -{ - memset(&map_server[id], 0, sizeof(map_server[id])); - map_server[id].fd = -1; -} - - -/// Destroys a server structure. -void mapif_server_destroy(int id) -{ - if( map_server[id].fd == -1 ) - { - do_close(map_server[id].fd); - map_server[id].fd = -1; - } -} - - -/// Resets all the data related to a server. -void mapif_server_reset(int id) -{ - int i,j; - unsigned char buf[16384]; - int fd = map_server[id].fd; - //Notify other map servers that this one is gone. [Skotlex] - WBUFW(buf,0) = 0x2b20; - WBUFL(buf,4) = htonl(map_server[id].ip); - WBUFW(buf,8) = htons(map_server[id].port); - j = 0; - for(i = 0; i < MAX_MAP_PER_SERVER; i++) - if (map_server[id].map[i]) - WBUFW(buf,10+(j++)*4) = map_server[id].map[i]; - if (j > 0) { - WBUFW(buf,2) = j * 4 + 10; - chmapif_sendallwos(fd, buf, WBUFW(buf,2)); - } - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", schema_config.ragsrvinfo_db, map_server[id].fd) ) - Sql_ShowDebug(sql_handle); - online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. - mapif_server_destroy(id); - mapif_server_init(id); -} - - -/// Called when the connection to a Map Server is disconnected. -void mapif_on_disconnect(int id) -{ - ShowStatus("Map-server #%d has disconnected.\n", id); - mapif_server_reset(id); -} - - - -void do_init_mapif(void) -{ - int i; - for( i = 0; i < ARRAYLENGTH(map_server); ++i ) - mapif_server_init(i); -} - -void do_final_mapif(void) -{ - int i; - for( i = 0; i < ARRAYLENGTH(map_server); ++i ) - mapif_server_destroy(i); -} - // Searches for the mapserver that has a given map (and optionally ip/port, if not -1). // If found, returns the server's index in the 'server' array (otherwise returns -1). int char_search_mapserver(unsigned short map, uint32 ip, uint16 port){ @@ -2342,70 +1964,6 @@ int char_lan_subnetcheck(uint32 ip){ } } - -/// @param result -/// 0 (0x718): An unknown error has occurred. -/// 1: none/success -/// 3 (0x719): A database error occurred. -/// 4 (0x71a): To delete a character you must withdraw from the guild. -/// 5 (0x71b): To delete a character you must withdraw from the party. -/// Any (0x718): An unknown error has occurred. -void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date) -{// HC: <0828>.W .L .L .L - WFIFOHEAD(fd,14); - WFIFOW(fd,0) = 0x828; - WFIFOL(fd,2) = char_id; - WFIFOL(fd,6) = result; -#if PACKETVER > 20130000 - WFIFOL(fd,10) = TOL(delete_date - time(NULL)); -#else - WFIFOL(fd,10) = TOL(delete_date); -#endif - WFIFOSET(fd,14); -} - - -/// @param result -/// 0 (0x718): An unknown error has occurred. -/// 1: none/success -/// 2 (0x71c): Due to system settings can not be deleted. -/// 3 (0x719): A database error occurred. -/// 4 (0x71d): Deleting not yet possible time. -/// 5 (0x71e): Date of birth do not match. -/// Any (0x718): An unknown error has occurred. -void char_delete2_accept_ack(int fd, int char_id, uint32 result) -{// HC: <082a>.W .L .L - if(result == 1 ){ - struct char_session_data* sd; - sd = (struct char_session_data*)session[fd]->session_data; - - if( sd->version >= date2version(20130000) ){ - mmo_char_send(fd, sd); - } - } - - WFIFOHEAD(fd,10); - WFIFOW(fd,0) = 0x82a; - WFIFOL(fd,2) = char_id; - WFIFOL(fd,6) = result; - WFIFOSET(fd,10); -} - - -/// @param result -/// 1 (0x718): none/success, (if char id not in deletion process): An unknown error has occurred. -/// 2 (0x719): A database error occurred. -/// Any (0x718): An unknown error has occurred. -void char_delete2_cancel_ack(int fd, int char_id, uint32 result) -{// HC: <082c>.W .L .L - WFIFOHEAD(fd,10); - WFIFOW(fd,0) = 0x82c; - WFIFOL(fd,2) = char_id; - WFIFOL(fd,6) = result; - WFIFOSET(fd,10); -} - - // Console Command Parser [Wizputer] int parse_console(const char* buf) { @@ -2444,111 +2002,6 @@ int parse_console(const char* buf) } - -int char_broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) -{ - uint8 buf[6]; - int users = char_count_users(); - - // only send an update when needed - static int prev_users = 0; - if( prev_users == users ) - return 0; - prev_users = users; - - if( chlogif_isconnected() ) - { - // send number of user to login server - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x2714; - WFIFOL(login_fd,2) = users; - WFIFOSET(login_fd,6); - } - - // send number of players to all map-servers - WBUFW(buf,0) = 0x2b00; - WBUFL(buf,2) = users; - chmapif_sendall(buf,6); - - return 0; -} - -/** - * Load this character's account id into the 'online accounts' packet - * @see DBApply - */ -static int send_accounts_tologin_sub(DBKey key, DBData *data, va_list ap) -{ - struct online_char_data* character = db_data2ptr(data); - int* i = va_arg(ap, int*); - - if(character->server > -1) - { - WFIFOL(login_fd,8+(*i)*4) = character->account_id; - (*i)++; - return 1; - } - return 0; -} - -/** - * Timered function to send all account_id connected to login-serv - * @param tid : Timer id - * @param tick : Scheduled tick - * @param id : GID linked to that timered call - * @param data : data transmited for delayed function - * @return - */ -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data) -{ - if (chlogif_isconnected()) - { - // send account list to login server - int users = online_char_db->size(online_char_db); - int i = 0; - - WFIFOHEAD(login_fd,8+users*4); - WFIFOW(login_fd,0) = 0x272d; - online_char_db->foreach(online_char_db, send_accounts_tologin_sub, &i, users); - WFIFOW(login_fd,2) = 8+ i*4; - WFIFOL(login_fd,4) = i; - WFIFOSET(login_fd,WFIFOW(login_fd,2)); - } - return 0; -} - -int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data) -{ - if (login_fd > 0 && session[login_fd] != NULL) - return 0; - - ShowInfo("Attempt to connect to login-server...\n"); - login_fd = make_connection(charserv_config.login_ip, charserv_config.login_port, false,10); - if (login_fd == -1) - { //Try again later. [Skotlex] - login_fd = 0; - return 0; - } - session[login_fd]->func_parse = chlogif_parse; - session[login_fd]->flag.server = 1; - realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - - WFIFOHEAD(login_fd,86); - WFIFOW(login_fd,0) = 0x2710; - memcpy(WFIFOP(login_fd,2), charserv_config.userid, 24); - memcpy(WFIFOP(login_fd,26), charserv_config.passwd, 24); - WFIFOL(login_fd,50) = 0; - WFIFOL(login_fd,54) = htonl(charserv_config.char_ip); - WFIFOW(login_fd,58) = htons(charserv_config.char_port); - memcpy(WFIFOP(login_fd,60), charserv_config.server_name, 20); - WFIFOW(login_fd,80) = 0; - WFIFOW(login_fd,82) = charserv_config.char_maintenance; - WFIFOW(login_fd,84) = charserv_config.char_new_display; //only display (New) if they want to [Kevin] - WFIFOSET(login_fd,86); - - return 1; -} - //------------------------------------------------ //Pincode system //------------------------------------------------ @@ -3426,8 +2879,8 @@ int do_init(int argc, char **argv) do_init_chmapif(); // periodically update the overall user count on all mapservers + login server - add_timer_func_list(char_broadcast_user_count, "broadcast_user_count"); - add_timer_interval(gettick() + 1000, char_broadcast_user_count, 0, 0, 5 * 1000); + add_timer_func_list(chlogif_broadcast_user_count, "broadcast_user_count"); + add_timer_interval(gettick() + 1000, chlogif_broadcast_user_count, 0, 0, 5 * 1000); // Timer to clear (online_char_db) add_timer_func_list(char_chardb_waiting_disconnect, "chardb_waiting_disconnect"); diff --git a/src/char/char_clif.c b/src/char/char_clif.c index 7957e6b20c..d568be8d45 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -10,6 +10,7 @@ #include "../common/malloc.h" #include "../common/strlib.h" #include "../common/utils.h" +#include "../common/timer.h" #include "inter.h" #include "char.h" #include "char_logif.h" @@ -227,13 +228,6 @@ void chclif_charlist_notify( int fd, struct char_session_data* sd ){ WFIFOSET(fd,6); } -void chclif_block_character( int fd, struct char_session_data* sd ){ - WFIFOHEAD(fd, 4); - WFIFOW(fd, 0) = 0x20d; - WFIFOW(fd, 2) = 4; //packet len - WFIFOSET(fd,4); -} - //---------------------------------------- // Function to send characters to a player //---------------------------------------- @@ -987,6 +981,65 @@ int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd){ return 1; } + +int charblock_timer(int tid, unsigned int tick, int id, intptr_t data) +{ + struct char_session_data* sd=NULL; + int i=0; + ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == id); + + if(sd == NULL || sd->charblock_timer==INVALID_TIMER) //has disconected or was required to stop + return 0; + if (sd->charblock_timer != tid){ + sd->charblock_timer = INVALID_TIMER; + return 0; + } + chclif_block_character(i,sd); + return 0; +} + +/* + * 0x20d .W 24B (HC_BLOCK_CHARACTER) + * L 20B (TAG_CHARACTER_BLOCK_INFO) + */ +void chclif_block_character( int fd, struct char_session_data* sd){ + int i=0, j=0, len=4; + time_t now = time(NULL); + + WFIFOHEAD(fd, 4+MAX_CHARS*24); + WFIFOW(fd, 0) = 0x20d; + + for(i=0; ifound_char[i] == -1) + continue; + if(sd->unban_time[i]){ + if( sd->unban_time[i] > now ) { + char szExpireDate[21]; + WFIFOL(fd, 4+j*24) = sd->found_char[i]; + timestamp2string(szExpireDate, 20, sd->unban_time[i], "%Y-%m-%d %H:%M:%S"); + memcpy(WFIFOP(fd,8+j*24),szExpireDate,20); + } + else { + WFIFOL(fd, 4+j*24) = 0; + sd->unban_time[i] = 0; + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `unban_time`='0' WHERE `char_id`='%d' LIMIT 1", schema_config.char_db, sd->found_char[i]) ) + Sql_ShowDebug(sql_handle); + } + len+=24; + j++; //pkt list idx + } + } + WFIFOW(fd, 2) = len; //packet len + WFIFOSET(fd,len); + + ARR_FIND(0, MAX_CHARS, i, sd->unban_time[i] > now); //sd->charslot only have productible char + if(i < MAX_CHARS ){ + sd->charblock_timer = add_timer( + gettick() + 10000, // each 10s resend that list + charblock_timer, sd->account_id, 0); + } +} + // 0x28f .L int chclif_parse_ackrename(int fd, struct char_session_data* sd){ // 0: Successful diff --git a/src/char/char_clif.h b/src/char/char_clif.h index 143ef783d7..3d44fac3c2 100644 --- a/src/char/char_clif.h +++ b/src/char/char_clif.h @@ -49,6 +49,7 @@ int chclif_parse_ackrename(int fd, struct char_session_data* sd); int chclif_ack_captcha(int fd); int chclif_parse_reqcaptcha(int fd); int chclif_parse_chkcaptcha(int fd); +void chclif_block_character( int fd, struct char_session_data* sd); int chclif_parse(int fd); diff --git a/src/char/char_cnslif.c b/src/char/char_cnslif.c index e374b98864..768c4403e1 100644 --- a/src/char/char_cnslif.c +++ b/src/char/char_cnslif.c @@ -32,6 +32,28 @@ void display_helpscreen(bool do_exit) exit(EXIT_SUCCESS); } +/** + * Timered function to check if the console has a new event to be read. + * @param tid: timer id + * @param tick: tick of execution + * @param id: user account id + * @param data: unused + * @return 0 + */ +int cnslif_console_timer(int tid, unsigned int tick, int id, intptr_t data) { + char buf[MAX_CONSOLE_IN]; //max cmd atm is 63+63+63+3+3 + + memset(buf,0,MAX_CONSOLE_IN); //clear out buf + + if(cli_hasevent()){ + if(fgets(buf, MAX_CONSOLE_IN, stdin)==NULL) + return -1; + else if(strlen(buf)>MIN_CONSOLE_IN) + cnslif_parse(buf); + } + return 0; +} + // Console Command Parser [Wizputer] int cnslif_parse(const char* buf) { @@ -71,7 +93,7 @@ int cnslif_parse(const char* buf) void do_init_chcnslif(void){ if( charserv_config.console ){ //start listening - add_timer_func_list(parse_console_timer, "parse_console_timer"); - add_timer_interval(gettick()+1000, parse_console_timer, 0, 0, 1000); //start in 1s each 1sec + add_timer_func_list(cnslif_console_timer, "cnslif_console_timer"); + add_timer_interval(gettick()+1000, cnslif_console_timer, 0, 0, 1000); //start in 1s each 1sec } } \ No newline at end of file diff --git a/src/char/char_logif.c b/src/char/char_logif.c index 6149d5cab9..be47c747fe 100644 --- a/src/char/char_logif.c +++ b/src/char/char_logif.c @@ -94,8 +94,16 @@ static int chlogif_send_acc_tologin_sub(DBKey key, DBData *data, va_list ap) { return 0; } +/** + * Timered function to send all account_id connected to login-serv + * @param tid : Timer id + * @param tick : Scheduled tick + * @param id : GID linked to that timered call + * @param data : data transmited for delayed function + * @return + */ int chlogif_send_acc_tologin(int tid, unsigned int tick, int id, intptr_t data) { - if (login_fd > 0 && session[login_fd]){ + if ( chlogif_isconnected() ){ DBMap* online_char_db = char_get_onlinedb(); // send account list to login server int users = online_char_db->size(online_char_db); @@ -125,6 +133,35 @@ int chlogif_send_usercount(int users){ return 0; } + +int chlogif_broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) +{ + uint8 buf[6]; + int users = char_count_users(); + + // only send an update when needed + static int prev_users = 0; + if( prev_users == users ) + return 0; + prev_users = users; + + if( chlogif_isconnected() ) + { + // send number of user to login server + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x2714; + WFIFOL(login_fd,2) = users; + WFIFOSET(login_fd,6); + } + + // send number of players to all map-servers + WBUFW(buf,0) = 0x2b00; + WBUFL(buf,2) = users; + chmapif_sendall(buf,6); + + return 0; +} + //Send packet forward to login-server for account saving int chlogif_save_accreg2(unsigned char* buf, int len){ if (login_fd > 0) { diff --git a/src/char/char_logif.h b/src/char/char_logif.h index 4812393460..b6d364c932 100644 --- a/src/char/char_logif.h +++ b/src/char/char_logif.h @@ -18,6 +18,7 @@ int chlogif_pincode_notifyLoginPinError( int account_id ); int chlogif_pincode_notifyLoginPinUpdate( int account_id, char* pin ); void chlogif_pincode_start(int fd, struct char_session_data* sd); int chlogif_send_acc_tologin(int tid, unsigned int tick, int id, intptr_t data); +int chlogif_broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data); int chlogif_send_usercount(int users); int chlogif_save_accreg2(unsigned char* buf, int len); int chlogif_request_accreg2(int account_id, int char_id); diff --git a/src/char/char_mapif.c b/src/char/char_mapif.c index a84b2cc8d7..4c1ce560b1 100644 --- a/src/char/char_mapif.c +++ b/src/char/char_mapif.c @@ -1,3 +1,5 @@ + + /** * @file char_mapif.c * Module purpose is to handle incoming and outgoing requests with map-server. diff --git a/src/common/cli.h b/src/common/cli.h index d3f48683bc..4819dfa494 100644 --- a/src/common/cli.h +++ b/src/common/cli.h @@ -34,6 +34,7 @@ extern "C" { extern char* MSG_CONF_NAME_EN; //all extern void display_helpscreen(bool exit); +bool cli_hasevent(); void display_versionscreen(bool do_exit); bool opt_has_next_value(const char* option, int i, int argc); int cli_get_options(int argc, char ** argv); From bf5d94b3e985c8c12772ee2fb3800a438e65a92a Mon Sep 17 00:00:00 2001 From: lighta Date: Fri, 2 May 2014 12:05:18 -0400 Subject: [PATCH 4/7] Updating Makefile Cleaning out ligconfig creation rules, use of archive and use of variable to avoid duplicate. --- .gitignore | 2 ++ 3rdparty/libconfig/Makefile.in | 24 ++++++++++++++------- src/char/Makefile.in | 26 +++++++++++------------ src/common/Makefile.in | 38 +++++++++++++++------------------- src/login/Makefile.in | 28 ++++++++++++------------- src/map/Makefile.in | 31 ++++++++++++--------------- src/test/Makefile.in | 11 ++++------ src/tool/Makefile.in | 32 +++++++++++----------------- 8 files changed, 91 insertions(+), 101 deletions(-) diff --git a/.gitignore b/.gitignore index 4c2548685b..f60782fecd 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ Thumbs.db # /3rdparty/libconfig/ /3rdparty/libconfig/Makefile /3rdparty/libconfig/*.o +/3rdparty/libconfig/obj # /3rdparty/mt19937ar/ /3rdparty/mt19937ar/Makefile @@ -123,3 +124,4 @@ Thumbs.db /vcproj-9/login-server_sql /vcproj-9/map-server_sql /vcproj-9/mapcache +/conf/.tmp-desd_conf.yml diff --git a/3rdparty/libconfig/Makefile.in b/3rdparty/libconfig/Makefile.in index ee17298b4d..c35b452f7a 100644 --- a/3rdparty/libconfig/Makefile.in +++ b/3rdparty/libconfig/Makefile.in @@ -1,26 +1,36 @@ -LIBCONFIG_OBJ = libconfig.o grammar.o scanctx.o scanner.o strbuf.o -LIBCONFIG_H = libconfig.h grammar.h parsectx.h scanctx.h scanner.h strbuf.h wincompat.h +LIBCONFIG_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g") +LIBCONFIG_DIR_OBJ = $(LIBCONFIG_OBJ:%=obj/%) +LIBCONFIG_H = $(shell ls *.h) +LIBCONFIG_AR = obj/libconfig.a @SET_MAKE@ ##################################################################### .PHONY : all clean help -all: $(LIBCONFIG_OBJ) +all: $(LIBCONFIG_AR) clean: @echo " CLEAN libconfig" - @rm -rf *.o + @rm -rf obj *.o help: @echo "possible targets are 'all' 'clean' 'help'" - @echo "'all' - builds $(LIBCONFIG_OBJ)" - @echo "'clean' - deletes $(LIBCONFIG_OBJ)" + @echo "'all' - builds $(LIBCONFIG_DIR_OBJ)" + @echo "'clean' - deletes $(LIBCONFIG_DIR_OBJ)" @echo "'help' - outputs this message" ##################################################################### -%.o: %.c $(LIBCONFIG_H) +obj_dir: + @echo " MKDIR obj" + @-mkdir obj + +obj/%.o: %.c $(LIBCONFIG_H) @echo " CC $<" @@CC@ @CFLAGS@ @DEFS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + +$(LIBCONFIG_AR): obj_dir $(LIBCONFIG_DIR_OBJ) + @echo " AR $@" + @@AR@ rcs obj/libconfig.a $(LIBCONFIG_DIR_OBJ) diff --git a/src/char/Makefile.in b/src/char/Makefile.in index 44e4812209..4866464104 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -1,23 +1,21 @@ COMMON_H = $(shell ls ../common/*.h) +COMMON_AR = ../common/obj_all/common.a +COMMON_SQL_AR = ../common/obj_sql/common_sql.a +COMMON_INCLUDE = -I../common/ MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar -LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ - ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o -LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ - ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ - ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h) +LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_H = ../common/sql.h CHAR_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g") -#CHAR_OBJ = char.o char_clif.o char_logif.o char_mapif.o char_cnslif.o \ - inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o int_mail.o int_auction.o int_quest.o int_mercenary.o int_elemental.o CHAR_SQL_OBJ = $(CHAR_OBJ:%=obj_sql/%) CHAR_H = $(shell ls ../char/*.h) @@ -52,9 +50,9 @@ help: ##################################################################### -char-server: obj_sql $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a +char-server: obj_sql $(CHAR_SQL_OBJ) $(LIBCONFIG_AR) $(COMMON_SQL_AR) $(COMMON_AR) @echo " LD @OCHR@@EXEEXT@" - @@CC@ @LDFLAGS@ -o ../../@OCHR@@EXEEXT@ $(CHAR_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ + @@CC@ @LDFLAGS@ -o ../../@OCHR@@EXEEXT@ $(CHAR_SQL_OBJ) $(LIBCONFIG_AR) $(COMMON_SQL_AR) $(COMMON_AR) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ needs_mysql: @echo "MySQL not found or disabled by the configure script" @@ -66,17 +64,17 @@ obj_sql: obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) $(LIBCONFIG_H) @echo " CC $<" - @@CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @@CC@ @CFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files -../common/obj_all/common.a: +$(COMMON_AR): @$(MAKE) -C ../common sql -../common/obj_sql/common_sql.a: +$(COMMON_SQL_AR): @$(MAKE) -C ../common sql -MT19937AR_OBJ: +$(MT19937AR_OBJ): @$(MAKE) -C ../../3rdparty/mt19937ar -LIBCONFIG_OBJ: +$(LIBCONFIG_AR): @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/common/Makefile.in b/src/common/Makefile.in index 90ea2c74d2..f11fb915ae 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -1,25 +1,21 @@ -COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o \ - obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \ - obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \ - obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \ - obj_all/conf.o obj_all/thread.o obj_all/mutex.o obj_all/raconf.o obj_all/mempool.o \ - obj_all/msg_conf.o obj_all/cli.o - +#COMMON_OBJ = $(ls *.c | grep -viw sql.c | sed -e "s/\.c/\.o/g") +COMMON_OBJ = core.o socket.o timer.o db.o nullpo.o malloc.o showmsg.o strlib.o utils.o \ + grfio.o mapindex.o ers.o md5calc.o minicore.o minisocket.o minimalloc.o random.o des.o \ + conf.o thread.o mutex.o raconf.o mempool.o msg_conf.o cli.o +COMMON_DIR_OBJ = $(COMMON_OBJ:%=obj_all/%) COMMON_H = $(shell ls ../common/*.h) - COMMON_SQL_OBJ = obj_sql/sql.o COMMON_SQL_H = sql.h +COMMON_AR = obj_all/common.a +COMMON_SQL_AR = obj_sql/common_sql.a MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar -LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ - ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o -LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ - ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ - ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h) +LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig HAVE_MYSQL=@HAVE_MYSQL@ @@ -64,18 +60,18 @@ obj_sql: @echo " MKDIR obj_sql" @-mkdir obj_sql -obj_all/common.a: $(COMMON_OBJ) +$(COMMON_AR): $(COMMON_DIR_OBJ) @echo " AR $@" - @@AR@ rcs obj_all/common.a $(COMMON_OBJ) + @@AR@ rcs $(COMMON_AR) $(COMMON_DIR_OBJ) -obj_sql/common_sql.a: $(COMMON_SQL_OBJ) +$(COMMON_SQL_AR): $(COMMON_SQL_OBJ) @echo " AR $@" - @@AR@ rcs obj_sql/common_sql.a $(COMMON_SQL_OBJ) + @@AR@ rcs $(COMMON_SQL_AR) $(COMMON_SQL_OBJ) -common: obj_all $(COMMON_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) obj_all/common.a +common: obj_all $(COMMON_DIR_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_AR) $(COMMON_AR) -common_sql: obj_sql $(COMMON_SQL_OBJ) obj_sql/common_sql.a +common_sql: obj_sql $(COMMON_SQL_OBJ) $(COMMON_SQL_AR) obj_all/%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) @echo " CC $<" @@ -91,8 +87,8 @@ obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) $(LIBCONFIG_H) # missing object files -MT19937AR_OBJ: +$(MT19937AR_OBJ): @$(MAKE) -C ../../3rdparty/mt19937ar -LIBCONFIG_OBJ: +$(LIBCONFIG_AR): @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/login/Makefile.in b/src/login/Makefile.in index d6110ae53b..0422202db8 100644 --- a/src/login/Makefile.in +++ b/src/login/Makefile.in @@ -1,20 +1,20 @@ COMMON_H = $(shell ls ../common/*.h) +COMMON_AR = ../common/obj_all/common.a +COMMON_SQL_AR = ../common/obj_sql/common_sql.a +COMMON_INCLUDE = -I../common MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar -LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ - ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o -LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ - ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ - ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h) +LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig -LOGIN_OBJ = login.o account_sql.o ipban_sql.o loginlog_sql.o +LOGIN_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g") LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%) -LOGIN_H = login.h account.h ipban.h loginlog.h +LOGIN_H = $(shell ls *.h) HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) @@ -58,26 +58,26 @@ obj_sql: #executables -login-server: obj_sql $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) +login-server: obj_sql $(LOGIN_SQL_OBJ) $(COMMON_SQL_AR) $(COMMON_AR) $(MT19937AR_OBJ) @echo " LD @OLOG@@EXEEXT@" - @@CC@ @LDFLAGS@ -o ../../@OLOG@@EXEEXT@ $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ + @@CC@ @LDFLAGS@ -o ../../@OLOG@@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_SQL_AR) $(COMMON_AR) $(MT19937AR_OBJ) $(LIBCONFIG_AR) @LIBS@ @MYSQL_LIBS@ # login object files obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) @echo " CC $<" - @@CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @@CC@ @CFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files -../common/obj_all/common.a: +$(COMMON_AR): @$(MAKE) -C ../common sql -../common/obj_sql/common_sql.a: +$(COMMON_SQL_AR): @$(MAKE) -C ../common sql -MT19937AR_OBJ: +$(MT19937AR_OBJ): @$(MAKE) -C ../../3rdparty/mt19937ar -LIBCONFIG_OBJ: +$(LIBCONFIG_AR): @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/map/Makefile.in b/src/map/Makefile.in index bd2db827ba..6cfda3baaf 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -1,23 +1,18 @@ COMMON_H = $(shell ls ../common/*.h) +COMMON_AR = ../common/obj_all/common.a +COMMON_SQL_AR = ../common/obj_sql/common_sql.a +COMMON_INCLUDE = -I../common/ MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar -LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ - ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o -LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ - ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ - ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h) +LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig -MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \ - npc_chat.o chat.o path.o itemdb.o mob.o script.o \ - storage.o skill.o atcommand.o battle.o battleground.o \ - intif.o trade.o party.o vending.o guild.o pet.o \ - log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \ - buyingstore.o searchstore.o duel.o pc_groups.o elemental.o cashshop.o channel.o mapreg_sql.o +MAP_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g") MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) MAP_H = $(shell ls ../map/*.h) \ $(shell ls ../config/*.h) @@ -71,26 +66,26 @@ obj_sql: # executables -map-server: obj_sql $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a +map-server: obj_sql $(MAP_SQL_OBJ) $(COMMON_SQL_AR) $(COMMON_AR) $(LIBCONFIG_AR) @echo " LD @OMAP@@EXEEXT@" - @@CC@ @LDFLAGS@ -o ../../@OMAP@@EXEEXT@ $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ + @@CC@ @LDFLAGS@ -o ../../@OMAP@@EXEEXT@ $(MAP_SQL_OBJ) $(COMMON_SQL_AR) $(COMMON_AR) $(MT19937AR_OBJ) $(LIBCONFIG_AR) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ # map object files obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) @echo " CC $<" - @@CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @@CC@ @CFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files -../common/obj_all/common.a: +$(COMMON_AR): @$(MAKE) -C ../common sql -../common/obj_sql/common_sql.a: +$(COMMON_SQL_AR): @$(MAKE) -C ../common sql -MT19937AR_OBJ: +$(MT19937AR_OBJ): @$(MAKE) -C ../../3rdparty/mt19937ar -LIBCONFIG_OBJ: +$(LIBCONFIG_AR): @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/test/Makefile.in b/src/test/Makefile.in index e3a763789d..66369788d7 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -5,11 +5,8 @@ MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar -LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ - ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o -LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ - ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ - ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h) +LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig TEST_SPINLOCK_OBJ=obj/test_spinlock.o @@ -40,7 +37,7 @@ help: test_spinlock: $(TEST_SPINLOCK_DEPENDS) @echo " LD $@" - @@CC@ @LDFLAGS@ -o ../../test_spinlock@EXEEXT@ $(TEST_SPINLOCK_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ + @@CC@ @LDFLAGS@ -o ../../test_spinlock@EXEEXT@ $(TEST_SPINLOCK_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_AR) @LIBS@ @MYSQL_LIBS@ # object directories @@ -64,5 +61,5 @@ obj/%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) MT19937AR_OBJ: @$(MAKE) -C ../../3rdparty/mt19937ar -LIBCONFIG_OBJ: +LIBCONFIG_AR: @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/tool/Makefile.in b/src/tool/Makefile.in index d72ef5405a..dcf49bc937 100644 --- a/src/tool/Makefile.in +++ b/src/tool/Makefile.in @@ -1,16 +1,11 @@ -COMMON_OBJ = ../common/obj_all/minicore.o ../common/obj_all/malloc.o \ - ../common/obj_all/showmsg.o ../common/obj_all/strlib.o \ - ../common/obj_all/utils.o ../common/obj_all/des.o ../common/obj_all/grfio.o -COMMON_H = ../common/core.h ../common/mmo.h \ - ../common/malloc.h ../common/showmsg.h ../common/strlib.h \ - ../common/utils.h ../common/cbasetypes.h ../common/des.h ../common/grfio.h ../config/renewal.h +COMMON_OBJ = minicore.o malloc.o showmsg.o strlib.o utils.o des.o grfio.o +COMMON_DIR_OBJ = $(COMMON_OBJ:%=../common/obj_all/%) +COMMON_H = $(shell ls ../common/*.h) +COMMON_INCLUDE = -I../common/ -LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ - ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o -LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ - ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ - ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_H = $(shell ls ../../3rdparty/libconfig/*.h) +LIBCONFIG_AR = ../../3rdparty/libconfig/obj/libconfig.a LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig OTHER_H = ../config/renewal.h @@ -24,9 +19,9 @@ MAPCACHE_OBJ = obj_all/mapcache.o all: mapcache -mapcache: obj_all $(MAPCACHE_OBJ) $(COMMON_OBJ) $(LIBCONFIG_OBJ) +mapcache: obj_all $(MAPCACHE_OBJ) $(COMMON_DIR_OBJ) $(LIBCONFIG_OBJ) @echo " LD $@" - @@CC@ @LDFLAGS@ $(LIBCONFIG_INCLUDE) -o ../../mapcache@EXEEXT@ $(MAPCACHE_OBJ) $(COMMON_OBJ) $(LIBCONFIG_OBJ) @LIBS@ + @@CC@ @LDFLAGS@ -o ../../mapcache@EXEEXT@ $(MAPCACHE_OBJ) $(COMMON_DIR_OBJ) $(LIBCONFIG_AR) @LIBS@ clean: @echo " CLEAN tool" @@ -46,14 +41,11 @@ obj_all: obj_all/%.o: %.c $(COMMON_H) $(OTHER_H) $(LIBCONFIG_H) @echo " CC $<" - @@CC@ @CFLAGS@ $(LIBCONFIG_INCLUDE) @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @@CC@ @CFLAGS@ $(COMMON_INCLUDE) $(LIBCONFIG_INCLUDE) @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing common object files -../common/obj_all/%.o: - @$(MAKE) -C ../common txt +$(COMMON_DIR_OBJ): + @$(MAKE) -C ../common sql -../common/obj_all/mini%.o: - @$(MAKE) -C ../common txt - -LIBCONFIG_OBJ: +$(LIBCONFIG_AR): @$(MAKE) -C ../../3rdparty/libconfig From af737790d2b221089ad389a90cfefc5a11dfde7d Mon Sep 17 00:00:00 2001 From: lighta Date: Sat, 3 May 2014 01:17:12 -0400 Subject: [PATCH 5/7] Fixed some return value for next parsing next==-1 to avoid parsing was mistmatchingFIFOSD_CHECK that was using 0 for same purpose. To avoid all confusion 0 is now used to said to not continue parsing. Fix 0x2b0e pointing to wrong parser. --- src/char/char_clif.c | 282 +++++++++++++++++++++--------------------- src/char/char_logif.c | 106 ++++++++-------- src/char/char_mapif.c | 117 +++++++++--------- 3 files changed, 249 insertions(+), 256 deletions(-) diff --git a/src/char/char_clif.c b/src/char/char_clif.c index d568be8d45..5d6fd750ca 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -54,13 +54,13 @@ int chclif_parse_moveCharSlot( int fd, struct char_session_data* sd){ if( (charserv_config.charmove_config.char_move_enabled)==0 || ( (charserv_config.charmove_config.char_moves_unlimited)==0 && sd->char_moves[from] <= 0 ) ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); - return 0; + return 1; } // We dont even have a character on the chosen slot? if( sd->found_char[from] <= 0 ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); - return 0; + return 1; } if( sd->found_char[to] > 0 ){ @@ -75,17 +75,17 @@ int chclif_parse_moveCharSlot( int fd, struct char_session_data* sd){ chclif_moveCharSlotReply( fd, sd, from, 1 ); Sql_ShowDebug(sql_handle); Sql_QueryStr(sql_handle,"ROLLBACK"); - return 0; + return 1; } }else{ // Admin doesnt allow us to chclif_moveCharSlotReply( fd, sd, from, 1 ); - return 0; + return 1; } }else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", schema_config.char_db, to, sd->found_char[from] ) ){ Sql_ShowDebug(sql_handle); chclif_moveCharSlotReply( fd, sd, from, 1 ); - return 0; + return 1; } if( (charserv_config.charmove_config.char_moves_unlimited)==0 ){ @@ -147,7 +147,7 @@ int chclif_parse_pincode_check( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 10 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) - return 0; + return 1; memset(pin,0,PINCODE_LENGTH+1); strncpy((char*)pin, (char*)RFIFOP(fd, 6), PINCODE_LENGTH); @@ -167,7 +167,7 @@ int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 14 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) - return 0; + return 1; else { char oldpin[PINCODE_LENGTH+1]; char newpin[PINCODE_LENGTH+1]; @@ -180,7 +180,7 @@ int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ char_pincode_decrypt(sd->pincode_seed,oldpin); if( !char_pincode_compare( fd, sd, oldpin ) ) - return 0; + return 1; char_pincode_decrypt(sd->pincode_seed,newpin); chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); @@ -199,7 +199,7 @@ int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){ return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) - return 0; + return 1; else { char newpin[PINCODE_LENGTH+1]; memset(newpin,0,PINCODE_LENGTH+1); @@ -362,60 +362,60 @@ int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { FIFOSD_CHECK(6) { int char_id, i; - char* data; - time_t delete_date; - - char_id = RFIFOL(fd,2); - RFIFOSKIP(fd,6); + char* data; + time_t delete_date; - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); - if( i == MAX_CHARS ) - {// character not found - chclif_char_delete2_ack(fd, char_id, 3, 0); - return 0; - } + char_id = RFIFOL(fd,2); + RFIFOSKIP(fd,6); - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) - { - Sql_ShowDebug(sql_handle); - chclif_char_delete2_ack(fd, char_id, 3, 0); - return 0; - } + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); + if( i == MAX_CHARS ) + {// character not found + chclif_char_delete2_ack(fd, char_id, 3, 0); + return 1; + } - Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); + if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + { + Sql_ShowDebug(sql_handle); + chclif_char_delete2_ack(fd, char_id, 3, 0); + return 1; + } - if( delete_date ) {// character already queued for deletion - chclif_char_delete2_ack(fd, char_id, 0, 0); - return 0; - } + Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); -/* - // Aegis imposes these checks probably to avoid dead member - // entries in guilds/parties, otherwise they are not required. - // TODO: Figure out how these are enforced during waiting. - if( guild_id ) - {// character in guild - char_delete2_ack(fd, char_id, 4, 0); - return; - } + if( delete_date ) {// character already queued for deletion + chclif_char_delete2_ack(fd, char_id, 0, 0); + return 1; + } - if( party_id ) - {// character in party - char_delete2_ack(fd, char_id, 5, 0); - return; - } -*/ - // success - delete_date = time(NULL)+(charserv_config.char_config.char_del_delay); + /* + // Aegis imposes these checks probably to avoid dead member + // entries in guilds/parties, otherwise they are not required. + // TODO: Figure out how these are enforced during waiting. + if( guild_id ) + {// character in guild + chclif_char_delete2_ack(fd, char_id, 4, 0); + return 1; + } - if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", schema_config.char_db, (unsigned long)delete_date, char_id) ) - { - Sql_ShowDebug(sql_handle); - chclif_char_delete2_ack(fd, char_id, 3, 0); - return 0; - } + if( party_id ) + {// character in party + chclif_char_delete2_ack(fd, char_id, 5, 0); + return 1; + } + */ + // success + delete_date = time(NULL)+(charserv_config.char_config.char_del_delay); - chclif_char_delete2_ack(fd, char_id, 1, delete_date); + if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", schema_config.char_db, (unsigned long)delete_date, char_id) ) + { + Sql_ShowDebug(sql_handle); + chclif_char_delete2_ack(fd, char_id, 3, 0); + return 1; + } + + chclif_char_delete2_ack(fd, char_id, 1, delete_date); } return 1; } @@ -425,77 +425,75 @@ int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) { FIFOSD_CHECK(12) { char birthdate[8+1]; - int char_id, i, k; - unsigned int base_level; - char* data; - time_t delete_date; - char_id = RFIFOL(fd,2); + int char_id, i, k; + unsigned int base_level; + char* data; + time_t delete_date; + char_id = RFIFOL(fd,2); - ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id); + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id); - // construct "YY-MM-DD" - birthdate[0] = RFIFOB(fd,6); - birthdate[1] = RFIFOB(fd,7); - birthdate[2] = '-'; - birthdate[3] = RFIFOB(fd,8); - birthdate[4] = RFIFOB(fd,9); - birthdate[5] = '-'; - birthdate[6] = RFIFOB(fd,10); - birthdate[7] = RFIFOB(fd,11); - birthdate[8] = 0; - RFIFOSKIP(fd,12); + // construct "YY-MM-DD" + birthdate[0] = RFIFOB(fd,6); + birthdate[1] = RFIFOB(fd,7); + birthdate[2] = '-'; + birthdate[3] = RFIFOB(fd,8); + birthdate[4] = RFIFOB(fd,9); + birthdate[5] = '-'; + birthdate[6] = RFIFOB(fd,10); + birthdate[7] = RFIFOB(fd,11); + birthdate[8] = 0; + RFIFOSKIP(fd,12); - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); - if( i == MAX_CHARS ) - {// character not found - chclif_char_delete2_accept_ack(fd, char_id, 3); - return 0; - } + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id ); + if( i == MAX_CHARS ) + {// character not found + chclif_char_delete2_accept_ack(fd, char_id, 3); + return 1; + } - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) - {// data error - Sql_ShowDebug(sql_handle); - chclif_char_delete2_accept_ack(fd, char_id, 3); - return 0; - } + if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + {// data error + Sql_ShowDebug(sql_handle); + chclif_char_delete2_accept_ack(fd, char_id, 3); + return 1; + } - Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10); - if( !delete_date || delete_date>time(NULL) ) - {// not queued or delay not yet passed - chclif_char_delete2_accept_ack(fd, char_id, 4); - return 0; - } + if( !delete_date || delete_date>time(NULL) ) + {// not queued or delay not yet passed + chclif_char_delete2_accept_ack(fd, char_id, 4); + return 1; + } - if( strcmp(sd->birthdate+2, birthdate) ) // +2 to cut off the century - {// birth date is wrong - chclif_char_delete2_accept_ack(fd, char_id, 5); - return 0; - } + if( strcmp(sd->birthdate+2, birthdate) ) // +2 to cut off the century + {// birth date is wrong + chclif_char_delete2_accept_ack(fd, char_id, 5); + return 1; + } - if( ( charserv_config.char_config.char_del_level > 0 && base_level >= (unsigned int)charserv_config.char_config.char_del_level ) - || ( charserv_config.char_config.char_del_level < 0 && base_level <= (unsigned int)(-charserv_config.char_config.char_del_level) ) ) - {// character level config restriction - chclif_char_delete2_accept_ack(fd, char_id, 2); - return 0; - } + if( ( charserv_config.char_config.char_del_level > 0 && base_level >= (unsigned int)charserv_config.char_config.char_del_level ) + || ( charserv_config.char_config.char_del_level < 0 && base_level <= (unsigned int)(-charserv_config.char_config.char_del_level) ) ) + {// character level config restriction + chclif_char_delete2_accept_ack(fd, char_id, 2); + return 1; + } - // success - if( char_delete_char_sql(char_id) < 0 ) - { - chclif_char_delete2_accept_ack(fd, char_id, 3); - return 0; - } + // success + if( char_delete_char_sql(char_id) < 0 ){ + chclif_char_delete2_accept_ack(fd, char_id, 3); + return 1; + } - // refresh character list cache - for(k = i; k < MAX_CHARS-1; k++) - { - sd->found_char[k] = sd->found_char[k+1]; - } - sd->found_char[MAX_CHARS-1] = -1; + // refresh character list cache + for(k = i; k < MAX_CHARS-1; k++){ + sd->found_char[k] = sd->found_char[k+1]; + } + sd->found_char[MAX_CHARS-1] = -1; - chclif_char_delete2_accept_ack(fd, char_id, 1); + chclif_char_delete2_accept_ack(fd, char_id, 1); } return 1; } @@ -513,7 +511,7 @@ int chclif_parse_char_delete2_cancel(int fd, struct char_session_data* sd) { if( i == MAX_CHARS ) {// character not found chclif_char_delete2_cancel_ack(fd, char_id, 2); - return 0; + return 1; } // there is no need to check, whether or not the character was @@ -523,7 +521,7 @@ int chclif_parse_char_delete2_cancel(int fd, struct char_session_data* sd) { { Sql_ShowDebug(sql_handle); chclif_char_delete2_cancel_ack(fd, char_id, 2); - return 0; + return 1; } chclif_char_delete2_cancel_ack(fd, char_id, 1); @@ -572,7 +570,7 @@ int chclif_parse_maplogin(int fd){ } RFIFOSKIP(fd,60); } - return 1; + return 0; } // 0065 .L .L .L .W .B @@ -596,7 +594,7 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){ //TODO: Perhaps log this as a hack attempt? //TODO: and perhaps send back a reply? ShowInfo("Already registered break\n"); - return 0; // @CHEKME this was break + return 1; } CREATE(session[fd]->session_data, struct char_session_data, 1); @@ -618,7 +616,7 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){ WFIFOW(fd,0) = 0x6c; WFIFOB(fd,2) = 0;// rejected from server WFIFOSET(fd,3); - return 0; + return 1; } // search authentification @@ -691,20 +689,20 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ WFIFOW(fd,0) = 0x6c; WFIFOB(fd,2) = 0; // rejected from server WFIFOSET(fd,3); - return 0; + return 1; } char_id = atoi(data); Sql_FreeResult(sql_handle); - /* client doesn't let it get to this point if you're banned, so its a forged packet */ - if( sd->found_char[slot] == char_id && sd->unban_time[slot] > time(NULL) ) { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0; // rejected from server - WFIFOSET(fd,3); - return 0; - } + /* client doesn't let it get to this point if you're banned, so its a forged packet */ + if( sd->found_char[slot] == char_id && sd->unban_time[slot] > time(NULL) ) { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; // rejected from server + WFIFOSET(fd,3); + return 1; + } /* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */ char_set_char_online(-2,char_id,sd->account_id); @@ -715,7 +713,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ WFIFOW(fd,0) = 0x6c; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - return 0;/* jump off this boat */ + return 1;/* jump off this boat */ } //Have to switch over to the DB instance otherwise data won't propagate [Kevin] @@ -743,7 +741,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ if (j == ARRAYLENGTH(map_server)) { ShowInfo("Connection Closed. No map servers available.\n"); chclif_send_auth_result(fd,1); // 01 = Server closed - return 0; + return 1; } if ((i = char_search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) { cd->last_point.x = 273; @@ -766,7 +764,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ } else { ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map)); chclif_send_auth_result(fd,1); // 01 = Server closed - return 0; + return 1; } ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j)); cd->last_point.map = j; @@ -780,7 +778,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ map_server[i].fd = -1; memset(&map_server[i], 0, sizeof(struct mmo_map_server)); chclif_send_auth_result(fd,1); //Send server closed. - return 0; + return 1; } //Send player to map @@ -890,7 +888,7 @@ int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){ WFIFOW(fd,0) = 0x70; WFIFOB(fd,2) = 0; // 00 = Incorrect Email address WFIFOSET(fd,3); - return 0; + return 1; } // check if this char exists @@ -901,7 +899,7 @@ int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){ WFIFOW(fd,0) = 0x70; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - return 0; + return 1; } // remove char from list and compact it @@ -918,7 +916,7 @@ int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){ WFIFOW(fd, 0) = 0x70; WFIFOB(fd, 2) = 0; WFIFOSET(fd, 3); - return 0; + return 1; } /* Char successfully deleted.*/ WFIFOHEAD(fd,2); @@ -957,12 +955,12 @@ int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd){ safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH); RFIFOSKIP(fd,34); if( aid != sd->account_id ) - return 0; + return 1; } ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); if( i == MAX_CHARS ) - return 0; + return 1; normalize_name(name,TRIM_CHARS); Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); @@ -1055,7 +1053,7 @@ int chclif_parse_ackrename(int fd, struct char_session_data* sd){ ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); if( i == MAX_CHARS ) - return 0; + return 1; i = char_rename_char_sql(sd, cid); WFIFOHEAD(fd, 4); @@ -1100,8 +1098,7 @@ int chclif_parse(int fd) { unsigned short cmd; struct char_session_data* sd = (struct char_session_data*)session[fd]->session_data; uint32 ipl = session[fd]->client_addr; - int next=0; - + // disconnect any player if no login-server. if(login_fd < 0) set_eof(fd); @@ -1123,8 +1120,8 @@ int chclif_parse(int fd) { while( RFIFOREST(fd) >= 2 ) { + int next=1; cmd = RFIFOW(fd,0); - if(next==-1) return 0; // avoid processing of followup packets (prev was probably incomplete) switch( cmd ) { case 0x65: next=chclif_parse_reqtoconnect(fd,sd,ipl); break; @@ -1167,6 +1164,7 @@ int chclif_parse(int fd) { set_eof(fd); return 0; } + if(next==0) return 0; // avoid processing of followup packets (prev was probably incomplete) } RFIFOFLUSH(fd); diff --git a/src/char/char_logif.c b/src/char/char_logif.c index be47c747fe..b255ab6032 100644 --- a/src/char/char_logif.c +++ b/src/char/char_logif.c @@ -269,9 +269,9 @@ int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){ int client_fd = request_id; sd->version = version; sd->clienttype = clienttype; - if(sd->version != date2version(PACKETVER)) - ShowWarning("s aid=%d has an incorect version=%d in clientinfo. Server compiled for %d\n", - sd->account_id,sd->version,date2version(PACKETVER)); + if(sd->version != date2version(PACKETVER)) + ShowWarning("s aid=%d has an incorect version=%d in clientinfo. Server compiled for %d\n", + sd->account_id,sd->version,date2version(PACKETVER)); switch( result ) { @@ -498,33 +498,29 @@ int chlogif_parse_askkick(int fd, struct char_session_data* sd){ } int chlogif_parse_updip(int fd, struct char_session_data* sd){ - if (RFIFOREST(fd) < 2) - return 0; - { - unsigned char buf[2]; - uint32 new_ip = 0; + unsigned char buf[2]; + uint32 new_ip = 0; - WBUFW(buf,0) = 0x2b1e; - chmapif_sendall(buf, 2); + WBUFW(buf,0) = 0x2b1e; + chmapif_sendall(buf, 2); - new_ip = host2ip(charserv_config.login_ip_str); - if (new_ip && new_ip != charserv_config.login_ip) - charserv_config.login_ip = new_ip; //Update login ip, too. + new_ip = host2ip(charserv_config.login_ip_str); + if (new_ip && new_ip != charserv_config.login_ip) + charserv_config.login_ip = new_ip; //Update login ip, too. - new_ip = host2ip(charserv_config.char_ip_str); - if (new_ip && new_ip != charserv_config.char_ip) - { //Update ip. - charserv_config.char_ip = new_ip; - ShowInfo("Updating IP for [%s].\n", charserv_config.char_ip_str); - // notify login server about the change - WFIFOHEAD(fd,6); - WFIFOW(fd,0) = 0x2736; - WFIFOL(fd,2) = htonl(charserv_config.char_ip); - WFIFOSET(fd,6); - } - - RFIFOSKIP(fd,2); + new_ip = host2ip(charserv_config.char_ip_str); + if (new_ip && new_ip != charserv_config.char_ip) + { //Update ip. + charserv_config.char_ip = new_ip; + ShowInfo("Updating IP for [%s].\n", charserv_config.char_ip_str); + // notify login server about the change + WFIFOHEAD(fd,6); + WFIFOW(fd,0) = 0x2736; + WFIFOL(fd,2) = htonl(charserv_config.char_ip); + WFIFOSET(fd,6); } + + RFIFOSKIP(fd,2); return 1; } @@ -555,7 +551,7 @@ int chlogif_BankingReq(int32 account_id, int8 type, int32 data){ */ int chlogif_parse_BankingAck(int fd){ if (RFIFOREST(fd) < 11) - return -1; + return 0; else { uint32 aid = RFIFOL(fd,2); int32 bank_vault = RFIFOL(fd,6); @@ -574,7 +570,7 @@ int chlogif_parse_BankingAck(int fd){ int chlogif_parse_vipack(int fd) { #ifdef VIP_ENABLE if (RFIFOREST(fd) < 20) - return -1; + return 0; else { uint32 aid = RFIFOL(fd,2); //aid uint32 vip_time = RFIFOL(fd,6); //vip_time @@ -615,7 +611,7 @@ int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd) { int chlogif_parse(int fd) { struct char_session_data* sd = NULL; - int next=0; + // only process data from the login-server if( fd != login_fd ) { ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd); @@ -644,36 +640,36 @@ int chlogif_parse(int fd) { sd = (struct char_session_data*)session[fd]->session_data; while(RFIFOREST(fd) >= 2) { + int next=1; uint16 command = RFIFOW(fd,0); - if(next==-1) return 0; //do not parse next data - switch( command ) { - case 0x2741: next=chlogif_parse_BankingAck(fd); break; - case 0x2743: next=chlogif_parse_vipack(fd); break; - // acknowledgement of connect-to-loginserver request - case 0x2711: next=chlogif_parse_ackconnect(fd,sd); break; - // acknowledgement of account authentication request - case 0x2713: next=chlogif_parse_ackaccreq(fd, sd); break; - // account data - case 0x2717: next=chlogif_parse_reqaccdata(fd, sd); break; - // login-server alive packet - case 0x2718: next=chlogif_parse_keepalive(fd, sd); break; - // changesex reply - case 0x2723: next=chlogif_parse_ackchangesex(fd, sd); break; - // reply to an account_reg2 registry request - case 0x2729: next=chlogif_parse_ackacc2req(fd, sd); break; - // State change of account/ban notification (from login-server) - case 0x2731: next=chlogif_parse_accbannotification(fd, sd); break; - // Login server request to kick a character out. [Skotlex] - case 0x2734: next=chlogif_parse_askkick(fd,sd); break; - // ip address update signal from login server - case 0x2735: next=chlogif_parse_updip(fd,sd); break; - default: - ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command); - set_eof(fd); - return 0; + case 0x2741: next=chlogif_parse_BankingAck(fd); break; + case 0x2743: next=chlogif_parse_vipack(fd); break; + // acknowledgement of connect-to-loginserver request + case 0x2711: next=chlogif_parse_ackconnect(fd,sd); break; + // acknowledgement of account authentication request + case 0x2713: next=chlogif_parse_ackaccreq(fd, sd); break; + // account data + case 0x2717: next=chlogif_parse_reqaccdata(fd, sd); break; + // login-server alive packet + case 0x2718: next=chlogif_parse_keepalive(fd, sd); break; + // changesex reply + case 0x2723: next=chlogif_parse_ackchangesex(fd, sd); break; + // reply to an account_reg2 registry request + case 0x2729: next=chlogif_parse_ackacc2req(fd, sd); break; + // State change of account/ban notification (from login-server) + case 0x2731: next=chlogif_parse_accbannotification(fd, sd); break; + // Login server request to kick a character out. [Skotlex] + case 0x2734: next=chlogif_parse_askkick(fd,sd); break; + // ip address update signal from login server + case 0x2735: next=chlogif_parse_updip(fd,sd); break; + default: + ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command); + set_eof(fd); + return 0; } + if(next==0) return 0; //do not parse next data } RFIFOFLUSH(fd); diff --git a/src/char/char_mapif.c b/src/char/char_mapif.c index 4c1ce560b1..09485e3c6b 100644 --- a/src/char/char_mapif.c +++ b/src/char/char_mapif.c @@ -175,7 +175,7 @@ void chmapif_sendall_playercount(int users){ int chmapif_parse_getmapname(int fd, int id){ int j = 0, i = 0; if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return -1; + return 0; //Retain what map-index that map-serv contains memset(map_server[id].map, 0, sizeof(map_server[id].map)); @@ -202,7 +202,7 @@ int chmapif_parse_getmapname(int fd, int id){ if (j == 0) { ShowWarning("Map-server %d has NO maps.\n", id); } else { - unsigned char buf[16384]; + unsigned char buf[16384]; // Transmitting maps information to the other map-servers WBUFW(buf,0) = 0x2b04; WBUFW(buf,2) = j * 4 + 10; @@ -241,7 +241,7 @@ int chmapif_parse_getmapname(int fd, int id){ */ int chmapif_parse_askscdata(int fd){ if (RFIFOREST(fd) < 10) - return -1; + return 0; { #ifdef ENABLE_SC_SAVING int aid, cid; @@ -251,7 +251,7 @@ int chmapif_parse_askscdata(int fd){ schema_config.scdata_db, aid, cid) ) { Sql_ShowDebug(sql_handle); - return 0; + return 1; } if( Sql_NumRows(sql_handle) > 0 ) { @@ -297,7 +297,7 @@ int chmapif_parse_askscdata(int fd){ */ int chmapif_parse_getusercount(int fd, int id){ if (RFIFOREST(fd) < 4) - return -1; + return 0; if (RFIFOW(fd,2) != map_server[id].users) { map_server[id].users = RFIFOW(fd,2); ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id); @@ -313,12 +313,11 @@ int chmapif_parse_getusercount(int fd, int id){ * @return : 0 not enough data received, 1 success */ int chmapif_parse_regmapuser(int fd, int id){ - int i; if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) - return -1; + return 0; { //TODO: When data mismatches memory, update guild/party online/offline states. - int aid, cid; + int aid, cid, i; struct online_char_data* character; DBMap* online_char_db = char_get_onlinedb(); @@ -352,7 +351,7 @@ int chmapif_parse_regmapuser(int fd, int id){ */ int chmapif_parse_reqsavechar(int fd, int id){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return -1; + return 0; { int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2); struct online_char_data* character; @@ -362,7 +361,7 @@ int chmapif_parse_reqsavechar(int fd, int id){ { ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus)); RFIFOSKIP(fd,size); - return 0; + return 1; } //Check account only if this ain't final save. Final-save goes through because of the char-map reconnect if (RFIFOB(fd,12) || RFIFOB(fd,13) || ( @@ -398,7 +397,7 @@ int chmapif_parse_reqsavechar(int fd, int id){ */ int chmapif_parse_authok(int fd){ if( RFIFOREST(fd) < 19 ) - return -1; + return 0; else{ int account_id = RFIFOL(fd,2); uint32 login_id1 = RFIFOL(fd,6); @@ -426,7 +425,7 @@ int chmapif_parse_authok(int fd){ node->login_id2 = login_id2; //node->sex = 0; node->ip = ntohl(ip); - node->version = version; //upd version for mapserv + node->version = version; //upd version for mapserv //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) //node->gmlevel = 0; idb_put(auth_db, account_id, node); @@ -453,7 +452,7 @@ int chmapif_parse_authok(int fd){ //Request to save skill cooldown data int chmapif_parse_req_saveskillcooldown(int fd){ if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) - return -1; + return 0; else { int count, aid, cid; aid = RFIFOL(fd,4); @@ -486,16 +485,17 @@ int chmapif_parse_req_saveskillcooldown(int fd){ //Request skillcooldown data 0x2b0a int chmapif_parse_req_skillcooldown(int fd){ if (RFIFOREST(fd) < 10) - return -1; + return 0; else { int aid, cid; aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); + RFIFOSKIP(fd, 10); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT skill, tick FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.skillcooldown_db, aid, cid) ) { Sql_ShowDebug(sql_handle); - return 0; + return 1; } if( Sql_NumRows(sql_handle) > 0 ) { @@ -526,7 +526,6 @@ int chmapif_parse_req_skillcooldown(int fd){ } } Sql_FreeResult(sql_handle); - RFIFOSKIP(fd, 10); } return 1; } @@ -538,7 +537,7 @@ int chmapif_parse_req_skillcooldown(int fd){ */ int chmapif_parse_reqchangemapserv(int fd){ if (RFIFOREST(fd) < 39) - return -1; + return 0; { int map_id, map_fd = -1; struct mmo_charstatus* char_data; @@ -615,7 +614,7 @@ int chmapif_parse_reqchangemapserv(int fd){ */ int chmapif_parse_askrmfriend(int fd){ if (RFIFOREST(fd) < 10) - return -1; + return 0; { int char_id, friend_id; char_id = RFIFOL(fd,2); @@ -623,7 +622,7 @@ int chmapif_parse_askrmfriend(int fd){ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1", schema_config.friend_db, char_id, friend_id) ) { Sql_ShowDebug(sql_handle); - return 0; + return 1; } RFIFOSKIP(fd,10); } @@ -638,7 +637,7 @@ int chmapif_parse_askrmfriend(int fd){ */ int chmapif_parse_reqcharname(int fd){ if (RFIFOREST(fd) < 6) - return -1; + return 0; WFIFOHEAD(fd,30); WFIFOW(fd,0) = 0x2b09; @@ -658,7 +657,7 @@ int chmapif_parse_reqcharname(int fd){ */ int chmapif_parse_reqnewemail(int fd){ if (RFIFOREST(fd) < 86) - return -1; + return 0; if (chlogif_isconnected()) { // don't send request if no login-server WFIFOHEAD(login_fd,86); memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 .L .40B .40B @@ -676,7 +675,7 @@ int chmapif_parse_reqnewemail(int fd){ */ int chmapif_parse_fwlog_changestatus(int fd){ if (RFIFOREST(fd) < 44) - return -1; + return 0; else { int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline, 4-current group level > VIP group level char esc_name[NAME_LENGTH*2+1]; @@ -783,7 +782,7 @@ int chmapif_parse_fwlog_changestatus(int fd){ */ int chmapif_parse_req_alter_acc(int fd){ if (RFIFOREST(fd) < 11) - return -1; + return 0; { int cid = RFIFOL(fd, 2); int fame = RFIFOL(fd, 6); @@ -856,7 +855,7 @@ void chmapif_send_ackdivorce(int partner_id1, int partner_id2){ */ int chmapif_parse_reqdivorce(int fd){ if( RFIFOREST(fd) < 10 ) - return -1; + return 0; char_divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6)); RFIFOSKIP(fd,10); return 1; @@ -870,7 +869,7 @@ int chmapif_parse_reqdivorce(int fd){ */ int chmapif_parse_updmapinfo(int fd){ if( RFIFOREST(fd) < 14 ) - return -1; + return 0; { char esc_server_name[sizeof(charserv_config.server_name)*2+1]; Sql_EscapeString(sql_handle, esc_server_name, charserv_config.server_name); @@ -890,7 +889,7 @@ int chmapif_parse_updmapinfo(int fd){ */ int chmapif_parse_setcharoffline(int fd){ if (RFIFOREST(fd) < 6) - return -1; + return 0; char_set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); RFIFOSKIP(fd,10); return 1; @@ -919,7 +918,7 @@ int chmapif_parse_setalloffline(int fd, int id){ */ int chmapif_parse_setcharonline(int fd, int id){ if (RFIFOREST(fd) < 10) - return -1; + return 0; char_set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6)); RFIFOSKIP(fd,10); return 1; @@ -934,7 +933,7 @@ int chmapif_parse_setcharonline(int fd, int id){ */ int chmapif_parse_reqfamelist(int fd){ if (RFIFOREST(fd) < 2) - return -1; + return 0; char_read_fame_list(); chmapif_send_fame_list(-1); RFIFOSKIP(fd,2); @@ -949,7 +948,7 @@ int chmapif_parse_reqfamelist(int fd){ */ int chmapif_parse_save_scdata(int fd){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return -1; + return 0; { #ifdef ENABLE_SC_SAVING int count, aid, cid; @@ -958,10 +957,10 @@ int chmapif_parse_save_scdata(int fd){ cid = RFIFOL(fd, 8); count = RFIFOW(fd, 12); - // Whatever comes from the mapserver, now is the time to drop previous entries - if( Sql_Query( sql_handle, "DELETE FROM `%s` where `account_id` = %d and `char_id` = %d;", schema_config.scdata_db, aid, cid ) != SQL_SUCCESS ){ - Sql_ShowDebug( sql_handle ); - } + // Whatever comes from the mapserver, now is the time to drop previous entries + if( Sql_Query( sql_handle, "DELETE FROM `%s` where `account_id` = %d and `char_id` = %d;", schema_config.scdata_db, aid, cid ) != SQL_SUCCESS ){ + Sql_ShowDebug( sql_handle ); + } else if( count > 0 ) { struct status_change_data data; @@ -1008,7 +1007,7 @@ int chmapif_parse_keepalive(int fd){ */ int chmapif_parse_reqauth(int fd, int id){ if (RFIFOREST(fd) < 20) - return -1; + return 0; { int account_id; @@ -1019,7 +1018,7 @@ int chmapif_parse_reqauth(int fd, int id){ struct auth_node* node; struct mmo_charstatus* cd; struct mmo_charstatus char_dat; - bool autotrade; + bool autotrade = false; DBMap* auth_db = char_get_authdb(); DBMap* char_db_ = char_get_chardb(); @@ -1104,7 +1103,7 @@ int chmapif_parse_reqauth(int fd, int id){ */ int chmapif_parse_updmapip(int fd, int id){ if (RFIFOREST(fd) < 6) - return -1; + return 0; map_server[id].ip = ntohl(RFIFOL(fd, 2)); ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(map_server[id].ip)); RFIFOSKIP(fd,6); @@ -1118,7 +1117,7 @@ int chmapif_parse_updmapip(int fd, int id){ */ int chmapif_parse_fw_configstats(int fd){ if( RFIFOREST(fd) < RFIFOW(fd,4) ) - return -1;/* packet wasn't fully received yet (still fragmented) */ + return 0;/* packet wasn't fully received yet (still fragmented) */ else { int sfd;/* stat server fd */ RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */ @@ -1141,7 +1140,7 @@ int chmapif_parse_fw_configstats(int fd){ int chmapif_parse_updfamelist(int fd){ if (RFIFOREST(fd) < 11) - return -1; + return 0; { int cid = RFIFOL(fd, 2); int fame = RFIFOL(fd, 6); @@ -1224,7 +1223,7 @@ int chmapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 is int chmapif_parse_reqcharban(int fd){ if (RFIFOREST(fd) < 10+NAME_LENGTH) - return -1; + return 0; else { //int aid = RFIFOL(fd,2); aid of player who as requested the ban int timediff = RFIFOL(fd,6); @@ -1234,12 +1233,12 @@ int chmapif_parse_reqcharban(int fd){ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", schema_config.char_db, name) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) == 0 ){ - return -1; // 1-player not found + return 1; // 1-player not found } else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){ Sql_ShowDebug(sql_handle); Sql_FreeResult(sql_handle); - return -1; + return 1; } else { int t_cid=0,t_aid=0; char* data; @@ -1252,7 +1251,8 @@ int chmapif_parse_reqcharban(int fd){ Sql_GetData(sql_handle, 2, &data, NULL); unban_time = atol(data); Sql_FreeResult(sql_handle); - if(timediff<0 && unban_time==0) return 0; //attemp to reduce time of a non banned account ?!? + if(timediff<0 && unban_time==0) + return 1; //attemp to reduce time of a non banned account ?!? else if(unban_time 0) { struct bonus_script_data bsdata; @@ -1351,7 +1351,7 @@ int chmapif_bonus_script_get(int fd) { } Sql_FreeResult(sql_handle); } - return 1; + return 1; } /** [Cydh] @@ -1360,7 +1360,7 @@ int chmapif_bonus_script_get(int fd) { */ int chmapif_bonus_script_save(int fd) { if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return -1; + return 0; else { int count, cid; @@ -1389,7 +1389,7 @@ int chmapif_bonus_script_save(int fd) { } RFIFOSKIP(fd,RFIFOW(fd,2)); } - return 1; + return 1; } /** @@ -1401,7 +1401,7 @@ int chmapif_bonus_script_save(int fd) { */ int chmapif_parse(int fd){ int id; //mapserv id - int next=0; + ARR_FIND( 0, ARRAYLENGTH(map_server), id, map_server[id].fd == fd ); if( id == ARRAYLENGTH(map_server) ) {// not a map server @@ -1418,9 +1418,8 @@ int chmapif_parse(int fd){ } while(RFIFOREST(fd) >= 2){ - if(next==-1) return 0; //avoid processing rest of packet - - switch(RFIFOW(fd,0)){ + int next=1; + switch(RFIFOW(fd,0)){ case 0x2736: next=chmapif_parse_updmapip(fd,id); break; case 0x2afa: next=chmapif_parse_getmapname(fd,id); break; case 0x2afc: next=chmapif_parse_askscdata(fd); break; @@ -1433,7 +1432,7 @@ int chmapif_parse(int fd){ case 0x2b08: next=chmapif_parse_reqcharname(fd); break; case 0x2b0a: next=chmapif_parse_req_skillcooldown(fd); break; case 0x2b0c: next=chmapif_parse_reqnewemail(fd); break; - case 0x2b0e: next=chmapif_parse_req_alter_acc(fd); break; + case 0x2b0e: next=chmapif_parse_fwlog_changestatus(fd); break; case 0x2b10: next=chmapif_parse_updfamelist(fd); break; case 0x2b11: next=chmapif_parse_reqdivorce(fd); break; case 0x2b15: next=chmapif_parse_req_saveskillcooldown(fd); break; @@ -1462,9 +1461,9 @@ int chmapif_parse(int fd){ set_eof(fd); return 0; } - } // switch + } // switch + if(next==0) return 0; //avoid processing rest of packet } // while - return 1; } From 348e01b673ad720ee081b9a38541efc54ad3fcb2 Mon Sep 17 00:00:00 2001 From: lighta Date: Sat, 3 May 2014 01:19:34 -0400 Subject: [PATCH 6/7] Cleanup unused function --- src/char/char_mapif.c | 66 ++++--------------------------------------- 1 file changed, 6 insertions(+), 60 deletions(-) diff --git a/src/char/char_mapif.c b/src/char/char_mapif.c index 09485e3c6b..778063e528 100644 --- a/src/char/char_mapif.c +++ b/src/char/char_mapif.c @@ -774,66 +774,6 @@ int chmapif_parse_fwlog_changestatus(int fd){ return 1; } -/** - * Received an update of fame point for char_id cid - * Update the list associated and transmit the new ranking - * @param fd: wich fd to parse from - * @return : 0 not enough data received, 1 success - */ -int chmapif_parse_req_alter_acc(int fd){ - if (RFIFOREST(fd) < 11) - return 0; - { - int cid = RFIFOL(fd, 2); - int fame = RFIFOL(fd, 6); - char type = RFIFOB(fd, 10); - int size; - struct fame_list* list; - int player_pos; - int fame_pos; - - switch(type) - { - case 1: size = fame_list_size_smith; list = smith_fame_list; break; - case 2: size = fame_list_size_chemist; list = chemist_fame_list; break; - case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; - default: size = 0; list = NULL; break; - } - - ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player - ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be - - if( player_pos == size && fame_pos == size ) - ;// not on list and not enough fame to get on it - else if( fame_pos == player_pos ) - {// same position - list[player_pos].fame = fame; - chmapif_update_fame_list(type, player_pos, fame); - } - else - {// move in the list - if( player_pos == size ) - {// new ranker - not in the list - ARR_MOVE(size - 1, fame_pos, list, struct fame_list); - list[fame_pos].id = cid; - list[fame_pos].fame = fame; - char_loadName(cid, list[fame_pos].name); - } - else - {// already in the list - if( fame_pos == size ) - --fame_pos;// move to the end of the list - ARR_MOVE(player_pos, fame_pos, list, struct fame_list); - list[fame_pos].fame = fame; - } - chmapif_send_fame_list(-1); - } - - RFIFOSKIP(fd,11); - } - return 1; -} - /** * Transmit the acknolegement of divorce of partner_id1 and partner_id2 * Update the list associated and transmit the new ranking @@ -1138,6 +1078,12 @@ int chmapif_parse_fw_configstats(int fd){ return 1; } +/** + * Received an update of fame point for char_id cid + * Update the list associated and transmit the new ranking + * @param fd: wich fd to parse from + * @return : 0 not enough data received, 1 success + */ int chmapif_parse_updfamelist(int fd){ if (RFIFOREST(fd) < 11) return 0; From 3585e700f2dd9d2531b1a1bf8a821788ddbd7fa9 Mon Sep 17 00:00:00 2001 From: lighta Date: Thu, 5 Jun 2014 02:51:13 -0400 Subject: [PATCH 7/7] Merge remote-tracking branch 'upstream/master' Conflicts: src/char/char.c src/char/int_storage.c --- src/char/char.c | 4 ++-- src/char/int_storage.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/char/char.c b/src/char/char.c index d53e1a9e96..902a3e0cf3 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -347,7 +347,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p){ "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," "`delete_date`='%lu',`robe`='%d',`moves`='%d',`font`='%u'" " WHERE `account_id`='%d' AND `char_id` = '%d'", - char_db, p->base_level, p->job_level, + schema_config.char_db, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, @@ -990,7 +990,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`," "`unban_time`,`font`" - " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db) + " FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p->char_id, 0, NULL, NULL) diff --git a/src/char/int_storage.c b/src/char/int_storage.c index c28afb68e7..a2f1d9ffa7 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -422,8 +422,14 @@ int mapif_parse_itembound_retrieve(int fd) //Finally reload storage and tell map we're done mapif_load_guild_storage(fd,aid,guild_id,0); - //If character is logged in char, disconnect - disconnect_player(aid); + //If character is logged in char, disconnect, + /* @CHECKME [lighta] + * I suppose this was an attempt to avoid item duplication if the expelled user reconnect during the operation. + * well it's kinda ugly to expel someone like this, so I consider this as a hack. + * we better flag them so that they not allowed to reconnect during operation or flag it so we will flush those item on ram with the map ack. + * both way seem nicer for player. + */ + char_disconnect_player(aid); //Tell map-server the operation is over and it can unlock the storage mapif_itembound_ack(fd,aid,guild_id);