From 4fb6740ebf921141687a50a07e516d9ec11babb0 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Fri, 6 Jan 2023 20:29:01 +0100 Subject: [PATCH] Replaced DBMap usage in char-server (#7514) Co-authored-by: Aleos --- src/char/char.cpp | 218 +++++++++++++-------------- src/char/char.hpp | 18 ++- src/char/char_clif.cpp | 41 ++--- src/char/char_logif.cpp | 60 ++++---- src/char/char_mapif.cpp | 145 ++++++++++-------- src/char/int_auction.cpp | 97 ++++++------ src/char/int_clan.cpp | 90 +++++------ src/char/int_guild.cpp | 318 ++++++++++++++++++--------------------- src/char/int_mail.cpp | 13 +- src/char/int_party.cpp | 185 +++++++++++------------ src/char/inter.cpp | 93 +++++------- 11 files changed, 630 insertions(+), 648 deletions(-) diff --git a/src/char/char.cpp b/src/char/char.cpp index 6fb4dd5425..85635c54aa 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -4,6 +4,9 @@ #pragma warning(disable:4800) #include "char.hpp" +#include +#include + #include #include #include @@ -22,6 +25,7 @@ #include "../common/socket.hpp" #include "../common/strlib.hpp" #include "../common/timer.hpp" +#include "../common/utilities.hpp" #include "char_clif.hpp" #include "char_cnslif.hpp" @@ -37,6 +41,7 @@ #include "int_storage.hpp" #include "packets.hpp" +using namespace rathena; using namespace rathena::server_character; //definition of exported var declared in header @@ -70,31 +75,30 @@ struct s_subnet { } subnet[16]; int subnet_count = 0; -DBMap* auth_db; // uint32 account_id -> struct auth_node* -DBMap* online_char_db; // uint32 account_id -> struct online_char_data* -DBMap* char_db_; // uint32 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_; } +// uint32 account_id -> struct auth_node* +std::unordered_map> auth_db; +// uint32 account_id -> struct online_char_data* +std::unordered_map> online_char_db; +// uint32 char_id -> struct mmo_charstatus* +std::unordered_map> char_db; +std::unordered_map>& char_get_authdb() { return auth_db; } +std::unordered_map>& char_get_onlinedb() { return online_char_db; } +std::unordered_map>& char_get_chardb() { return char_db; } -/** - * @see DBCreateData - */ -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; - character->char_id = -1; - character->server = -1; - character->fd = -1; - character->waiting_disconnect = INVALID_TIMER; - return db_ptr2data(character); +online_char_data::online_char_data( uint32 account_id ){ + this->account_id = account_id; + this->char_id = -1; + this->server = -1; + this->fd = -1; + this->waiting_disconnect = INVALID_TIMER; } void char_set_charselect(uint32 account_id) { - struct online_char_data* character; + std::shared_ptr character = util::umap_find( char_get_onlinedb(), account_id ); - character = (struct online_char_data*)idb_ensure(online_char_db, account_id, char_create_online_data); + if( character == nullptr ){ + character = std::make_shared( account_id ); + } if( character->server > -1 ) if( map_server[character->server].users > 0 ) // Prevent this value from going negative. @@ -113,20 +117,27 @@ void char_set_charselect(uint32 account_id) { } void char_set_char_online(int map_id, uint32 char_id, uint32 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', `last_login`=NOW() 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, 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(map_server[character->server].fd, character->account_id, character->char_id, 2); + std::shared_ptr character = util::umap_find( char_get_onlinedb(), account_id ); + + if( character != nullptr ){ + 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(map_server[character->server].fd, character->account_id, character->char_id, 2); + } + + // Get rid of disconnect timer + if( character->waiting_disconnect != INVALID_TIMER ){ + delete_timer( character->waiting_disconnect, char_chardb_waiting_disconnect ); + character->waiting_disconnect = INVALID_TIMER; + } + }else{ + character = std::make_shared( account_id ); } //Update state data @@ -136,14 +147,9 @@ void char_set_char_online(int map_id, uint32 char_id, uint32 account_id) { if( character->server > -1 ) map_server[character->server].users++; - //Get rid of disconnect timer - if(character->waiting_disconnect != INVALID_TIMER) { - delete_timer(character->waiting_disconnect, char_chardb_waiting_disconnect); - character->waiting_disconnect = INVALID_TIMER; - } - //Set char online in guild cache. If char is in memory, use the guild id on it, otherwise seek it. - cp = (struct mmo_charstatus*)idb_get(char_db_,char_id); + std::shared_ptr cp = util::umap_find( char_get_chardb(), char_id ); + inter_guild_CharOnline(char_id, cp?cp->guild_id:-1); //Notify login server @@ -151,8 +157,6 @@ void char_set_char_online(int map_id, uint32 char_id, uint32 account_id) { } void char_set_char_offline(uint32 char_id, uint32 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'", schema_config.char_db, account_id) ) @@ -160,17 +164,20 @@ void char_set_char_offline(uint32 char_id, uint32 account_id){ } else { - struct mmo_charstatus* cp = (struct mmo_charstatus*)idb_get(char_db_,char_id); + std::shared_ptr cp = util::umap_find( char_get_chardb(), char_id ); + inter_guild_CharOffline(char_id, cp?cp->guild_id:-1); if (cp) - idb_remove(char_db_,char_id); + char_get_chardb().erase( 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] + std::shared_ptr character = util::umap_find( char_get_onlinedb(), account_id ); + + // We don't free yet to avoid aCalloc/aFree spamming during char change. [Skotlex] + if( character != nullptr ){ if( character->server > -1 ) if( map_server[character->server].users > 0 ) // Prevent this value from going negative. map_server[character->server].users--; @@ -197,12 +204,7 @@ void char_set_char_offline(uint32 char_id, uint32 account_id){ } } -/** - * @see DBApply - */ -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); +void char_db_setoffline( std::shared_ptr character, int server ){ if (server == -1) { character->char_id = -1; character->server = -1; @@ -212,28 +214,17 @@ int char_db_setoffline(DBKey key, DBData *data, va_list ap) { } } else if (character->server == server) character->server = -2; //In some map server that we aren't connected to. - return 0; } -/** - * @see DBApply - */ -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); - +void char_db_kickoffline( std::shared_ptr character, int server_id ){ if (server_id > -1 && character->server != server_id) - return 0; + return; //Kick out any connected characters, and set them offline as appropriate. if (character->server > -1) mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 1); else if (character->waiting_disconnect == INVALID_TIMER) char_set_char_offline(character->char_id, character->account_id); - else - return 0; // fail - - return 1; } void char_set_all_offline(int id){ @@ -241,7 +232,10 @@ void char_set_all_offline(int id){ ShowNotice("Sending all users offline.\n"); else ShowNotice("Sending users of map-server %d offline.\n",id); - online_char_db->foreach(online_char_db,char_db_kickoffline,id); + + for( const auto& pair : char_get_onlinedb() ){ + char_db_kickoffline( pair.second, id ); + } if (id >= 0 || !chlogif_isconnected()) return; @@ -257,28 +251,23 @@ void char_set_all_offline_sql(void){ Sql_ShowDebug(sql_handle); } -/** - * @see DBCreateData - */ -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 char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ int i = 0; int count = 0; int diff = 0; char save_status[128]; //For displaying save information. [Skotlex] - struct mmo_charstatus *cp; int errors = 0; //If there are any errors while saving, "cp" will not be updated at the end. StringBuf buf; if (char_id!=p->char_id) return 0; - cp = (struct mmo_charstatus *)idb_ensure(char_db_, char_id, char_create_charstatus); + std::shared_ptr cp = util::umap_find( char_get_chardb(), char_id ); + + if( cp == nullptr ){ + cp = std::make_shared(); + cp->char_id = char_id; + char_get_chardb()[cp->char_id] = cp; + } StringBuf_Init(&buf); memset(save_status, 0, sizeof(save_status)); @@ -526,8 +515,11 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ StringBuf_Destroy(&buf); 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)); + + if( !errors ){ + memcpy( cp.get(), p, sizeof( struct mmo_charstatus ) ); + } + return 0; } @@ -1035,7 +1027,6 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf, uint8* coun //===================================================================================================== int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything) { int i; - struct mmo_charstatus* cp; SqlStmt* stmt; char last_map[MAP_NAME_LENGTH_EXT]; char save_map[MAP_NAME_LENGTH_EXT]; @@ -1273,16 +1264,22 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, StringBuf_Value(&msg_buf)); //ok. all data load successfully! SqlStmt_Free(stmt); - cp = (struct mmo_charstatus *)idb_ensure(char_db_, char_id, char_create_charstatus); - memcpy(cp, p, sizeof(struct mmo_charstatus)); + std::shared_ptr cp = util::umap_find( char_get_chardb(), char_id ); + + if( cp == nullptr ){ + cp = std::make_shared(); + cp->char_id = char_id; + char_get_chardb()[cp->char_id] = cp; + } + + memcpy( cp.get(), p, sizeof( struct mmo_charstatus ) ); + StringBuf_Destroy(&msg_buf); return 1; } //========================================================================================================== 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 ... @@ -2000,10 +1997,10 @@ void char_set_session_flag_(int account_id, int val, bool set) { } void char_auth_ok(int fd, struct char_session_data *sd) { - struct online_char_data* character; + std::shared_ptr character = util::umap_find( char_get_onlinedb(), sd->account_id ); - if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) != NULL ) - { // check if character is not online already. [Skotlex] + // Check if character is not online already. [Skotlex] + if( character != nullptr ){ if (character->server > -1) { //Character already online. KICK KICK KICK mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); @@ -2208,33 +2205,38 @@ void char_pincode_decrypt( uint32 userSeed, char* pin ){ //replies/disconnect the player we tried to kick. [Skotlex] //------------------------------------------------ TIMER_FUNC(char_chardb_waiting_disconnect){ - 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. + std::shared_ptr character = util::umap_find( char_get_onlinedb(), static_cast( id ) ); + + // Mark it offline due to timeout. + if( character != nullptr && character->waiting_disconnect == tid ){ character->waiting_disconnect = INVALID_TIMER; char_set_char_offline(character->char_id, character->account_id); } return 0; } -/** - * @see DBApply - */ -int char_online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) -{ - struct online_char_data *character= (struct online_char_data *)db_data2ptr(data); - if (character->fd != -1) - return 0; //Character still connected - if (character->server == -2) //Unknown server.. set them offline - 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; -} - TIMER_FUNC(char_online_data_cleanup){ - online_char_db->foreach(online_char_db, char_online_data_cleanup_sub); + for( auto it = char_get_onlinedb().begin(); it != char_get_onlinedb().end(); ){ + std::shared_ptr character = it->second; + + // Character still connected + if( character->fd != -1 ){ + return 0; + } + + // Unknown server - set them offline + if( character->server == -2 ){ + char_set_char_offline( character->char_id, character->account_id ); + } + + // Free data from players that have not been online for a while. + if( character->server < 0 ){ + it = char_get_onlinedb().erase( it ); + }else{ + it++; + } + } + return 0; } @@ -3162,9 +3164,9 @@ void CharacterServer::finalize(){ do_final_chmapif(); do_final_chlogif(); - char_db_->destroy(char_db_, NULL); - online_char_db->destroy(online_char_db, NULL); - auth_db->destroy(auth_db, NULL); + char_get_chardb().clear(); + char_get_onlinedb().clear(); + char_get_authdb().clear(); if( char_fd != -1 ) { @@ -3218,8 +3220,6 @@ bool CharacterServer::initialize( int argc, char *argv[] ){ inter_init_sql((argc > 2) ? argv[2] : SQL_CONF_NAME); // inter server configuration - auth_db = idb_alloc(DB_OPT_RELEASE_DATA); - online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); char_mmo_sql_init(); char_read_fame_list(); //Read fame lists. diff --git a/src/char/char.hpp b/src/char/char.hpp index 7b4813a658..b9febad347 100644 --- a/src/char/char.hpp +++ b/src/char/char.hpp @@ -4,6 +4,8 @@ #ifndef CHAR_HPP #define CHAR_HPP +#include +#include #include #include "../common/core.hpp" // CORE_ST_LAST @@ -233,7 +235,8 @@ struct auth_node { unsigned changing_mapservers : 1; uint8 version; }; -DBMap* char_get_authdb(); // uint32 account_id -> struct auth_node* + +std::unordered_map>& char_get_authdb(); struct online_char_data { uint32 account_id; @@ -242,8 +245,12 @@ struct online_char_data { int waiting_disconnect; short server; // -2: unknown server, -1: not connected, 0+: id of server bool pincode_success; + +public: + online_char_data( uint32 account_id ); }; -DBMap* char_get_onlinedb(); // uint32 account_id -> struct online_char_data* + +std::unordered_map>& char_get_onlinedb(); struct char_session_data { bool auth; // whether the session is authed or not @@ -271,9 +278,7 @@ struct char_session_data { uint8 flag; // &1 - Retrieving guild bound items }; - -struct mmo_charstatus; -DBMap* char_get_chardb(); // uint32 char_id -> struct mmo_charstatus* +std::unordered_map>& char_get_chardb(); //Custom limits for the fame lists. [Skotlex] extern int fame_list_size_chemist; @@ -291,8 +296,7 @@ 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_db_setoffline( std::shared_ptr character, int server ); void char_set_char_online(int map_id, uint32 char_id, uint32 account_id); void char_set_char_offline(uint32 char_id, uint32 account_id); void char_set_all_offline(int id); diff --git a/src/char/char_clif.cpp b/src/char/char_clif.cpp index f2332a8771..552ee7e113 100644 --- a/src/char/char_clif.cpp +++ b/src/char/char_clif.cpp @@ -3,6 +3,9 @@ #include "char_clif.hpp" +#include +#include + #include #include @@ -15,6 +18,7 @@ #include "../common/sql.hpp" #include "../common/strlib.hpp" #include "../common/timer.hpp" +#include "../common/utilities.hpp" #include "../common/utils.hpp" #include "char.hpp" @@ -23,6 +27,8 @@ #include "inter.hpp" #include "packets.hpp" +using namespace rathena; + #if PACKETVER_SUPPORTS_PINCODE bool pincode_allowed( char* pincode ); #endif @@ -703,9 +709,6 @@ 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(); - uint32 account_id = RFIFOL(fd,2); uint32 login_id1 = RFIFOL(fd,6); uint32 login_id2 = RFIFOL(fd,10); @@ -741,14 +744,15 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){ } // search authentification - node = (struct auth_node*)idb_get(auth_db, account_id); - if( node != NULL && + std::shared_ptr node = util::umap_find( char_get_authdb(), account_id); + + if( node != nullptr && node->account_id == account_id && node->login_id1 == login_id1 && node->login_id2 == login_id2 /*&& node->ip == ipl*/ ) {// authentication found (coming from map server) - idb_remove(auth_db, account_id); + char_get_authdb().erase(account_id); char_auth_ok(fd, sd); } else @@ -780,7 +784,7 @@ int chclif_parse_req_charlist(int fd, struct char_session_data* sd){ } //Send player to map -void chclif_send_map_data( int fd, struct mmo_charstatus *cd, uint32 ipl, int map_server_index ){ +void chclif_send_map_data( int fd, std::shared_ptr cd, uint32 ipl, int map_server_index ){ #if PACKETVER >= 20170315 int cmd = 0xAC5; int size = 156; @@ -806,13 +810,9 @@ 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; uint32 char_id; - struct auth_node* node; int i, map_fd, server_id; - DBMap *auth_db = char_get_authdb(); - DBMap *char_db_ = char_get_chardb(); int slot = RFIFOB(fd,2); RFIFOSKIP(fd,3); @@ -864,7 +864,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ } //Have to switch over to the DB instance otherwise data won't propagate [Kevin] - cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); + std::shared_ptr cd = util::umap_find( char_get_chardb(), char_id ); if (charserv_config.log_char) { char esc_name[NAME_LENGTH*2+1]; @@ -930,7 +930,8 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ chclif_send_map_data( fd, cd, ipl, i ); // create temporary auth entry - CREATE(node, struct auth_node, 1); + std::shared_ptr node = std::make_shared(); + node->account_id = sd->account_id; node->char_id = cd->char_id; node->login_id1 = sd->login_id1; @@ -939,8 +940,8 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ node->expiration_time = sd->expiration_time; node->group_id = sd->group_id; node->ip = ipl; - idb_put(auth_db, sd->account_id, node); + char_get_authdb()[node->account_id] = node; } return 1; } @@ -1363,12 +1364,16 @@ int chclif_parse(int 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) + std::shared_ptr data = util::umap_find( char_get_onlinedb(), sd->account_id ); + + if( data != nullptr && data->fd == fd ){ data->fd = -1; - if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex] + } + + // If it is not in any server, send it offline. [Skotlex] + if( data == nullptr || data->server == -1 ){ char_set_char_offline(-1,sd->account_id); + } } do_close(fd); return 0; diff --git a/src/char/char_logif.cpp b/src/char/char_logif.cpp index aa1f3eead8..5fb9bf0321 100644 --- a/src/char/char_logif.cpp +++ b/src/char/char_logif.cpp @@ -3,6 +3,8 @@ #include "char_logif.hpp" +#include + #include #include @@ -11,6 +13,7 @@ #include "../common/sql.hpp" #include "../common/strlib.hpp" #include "../common/timer.hpp" +#include "../common/utilities.hpp" #include "../common/utils.hpp" #include "char.hpp" @@ -19,6 +22,8 @@ #include "inter.hpp" #include "int_guild.hpp" +using namespace rathena; + //early declaration void chlogif_on_ready(void); void chlogif_on_disconnect(void); @@ -59,10 +64,9 @@ void chlogif_pincode_start(int fd, struct char_session_data* sd){ }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 ); + std::shared_ptr node = util::umap_find( char_get_onlinedb(), sd->account_id ); - if( node != NULL && node->pincode_success ){ + if( node != nullptr && node->pincode_success ){ // User has already passed the check chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); }else{ @@ -82,21 +86,6 @@ void chlogif_pincode_start(int fd, struct char_session_data* sd){ } #endif -/** - * Load this character's account id into the 'online accounts' packet - * @see DBApply - */ -int chlogif_send_acc_tologin_sub(DBKey key, DBData *data, va_list ap) { - struct online_char_data* character = (struct online_char_data*)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 @@ -107,14 +96,20 @@ int chlogif_send_acc_tologin_sub(DBKey key, DBData *data, va_list ap) { */ TIMER_FUNC(chlogif_send_acc_tologin){ 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); + int users = char_get_onlinedb().size(); 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); + for( const auto& pair : char_get_onlinedb() ){ + std::shared_ptr character = pair.second; + + if( character->server > -1 ){ + WFIFOL( login_fd, 8 + i * 4 ) = character->account_id; + i++; + } + } WFIFOW(login_fd,2) = 8+ i*4; WFIFOL(login_fd,4) = i; WFIFOSET(login_fd,WFIFOW(login_fd,2)); @@ -434,18 +429,17 @@ int chlogif_parse_ackchangesex(int fd) return 0; else { unsigned char buf[7]; - int acc = RFIFOL(fd,2); + uint32 acc = RFIFOL(fd,2); int sex = RFIFOB(fd,6); RFIFOSKIP(fd,7); if (acc > 0) { // TODO: Is this even possible? unsigned char i; int char_id = 0, class_ = 0, guild_id = 0; - DBMap* auth_db = char_get_authdb(); - struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc); + std::shared_ptr node = util::umap_find( char_get_authdb(), acc ); SqlStmt *stmt; - if (node != NULL) + if (node != nullptr) node->sex = sex; // get characters @@ -550,13 +544,13 @@ int chlogif_parse_askkick(int fd){ if (RFIFOREST(fd) < 6) return 0; else { - 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); + uint32 aid = RFIFOL(fd,2); RFIFOSKIP(fd,6); - if( character != NULL ) - {// account is already marked as online! + + std::shared_ptr character = util::umap_find( char_get_onlinedb(), aid ); + + // account is already marked as online! + if( character != nullptr ){ 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); @@ -577,7 +571,9 @@ int chlogif_parse_askkick(int fd){ char_set_char_offline(-1, aid); } } - idb_remove(auth_db, aid);// reject auth attempts from map-server + + // reject auth attempts from map-server + char_get_authdb().erase( aid ); } return 1; } diff --git a/src/char/char_mapif.cpp b/src/char/char_mapif.cpp index a75c8f1852..a4fe7109eb 100644 --- a/src/char/char_mapif.cpp +++ b/src/char/char_mapif.cpp @@ -3,6 +3,8 @@ #include "char_mapif.hpp" +#include + #include #include //memcpy @@ -12,11 +14,14 @@ #include "../common/sql.hpp" #include "../common/strlib.hpp" #include "../common/timer.hpp" +#include "../common/utilities.hpp" #include "char.hpp" #include "char_logif.hpp" #include "inter.hpp" +using namespace rathena; + /** * Packet send to all map-servers, attach to ourself * @param buf: packet to send in form of an array buffer @@ -357,21 +362,29 @@ int chmapif_parse_regmapuser(int fd, int id){ return 0; else { //TODO: When data mismatches memory, update guild/party online/offline states. - DBMap* online_char_db = char_get_onlinedb(); - int i; - 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++) { - int aid = RFIFOL(fd,6+i*8); - int cid = RFIFOL(fd,6+i*8+4); - struct online_char_data* character = (struct online_char_data*)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); + + // Set all chars from this server as 'unknown' + for( const auto& pair : char_get_onlinedb() ){ + char_db_setoffline( pair.second, id ); + } + + for( int i = 0; i < map_server[id].users; i++ ){ + uint32 aid = RFIFOL(fd,6+i*8); + uint32 cid = RFIFOL(fd,6+i*8+4); + + std::shared_ptr character = util::umap_find( char_get_onlinedb(), aid ); + + if( character != nullptr ){ + 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); + } + }else{ + character = std::make_shared( aid ); } + character->server = id; character->char_id = cid; } @@ -392,9 +405,8 @@ int chmapif_parse_reqsavechar(int fd, int id){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; else { - 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(); + uint32 aid = RFIFOL( fd, 4 ), cid = RFIFOL( fd, 8 ); + uint16 size = RFIFOW( fd, 2 ); if (size - 13 != sizeof(struct mmo_charstatus)) { @@ -402,11 +414,11 @@ int chmapif_parse_reqsavechar(int fd, int id){ RFIFOSKIP(fd,size); return 1; } + + std::shared_ptr character = util::umap_find( char_get_onlinedb(), aid ); + //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)) - { + if( RFIFOB( fd, 12 ) || RFIFOB( fd, 13 ) || ( character != nullptr && 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); @@ -461,12 +473,9 @@ int chmapif_parse_authok(int fd){ if( !global_core->is_running() ){ chmapif_charselres(fd,account_id,0); }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); + std::shared_ptr node = std::make_shared(); + node->account_id = account_id; node->char_id = 0; node->login_id1 = login_id1; @@ -475,16 +484,18 @@ int chmapif_parse_authok(int fd){ 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); + + char_get_authdb()[node->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; - } + + std::shared_ptr character = util::umap_find( char_get_onlinedb(), account_id ); + + if( character != nullptr ){ + character->pincode_success = true; } + chmapif_charselres(fd,account_id,1); } } @@ -596,30 +607,28 @@ int chmapif_parse_reqchangemapserv(int fd){ return 0; else { 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)); + + uint32 char_id = RFIFOL( fd, 14 ); + + // Char should just had been saved before this packet, so this should be safe. [Skotlex] + std::shared_ptr char_data = util::umap_find( char_get_chardb(), char_id ); + + // Really shouldn't happen. + if( char_data == nullptr ){ + char_mmo_char_fromsql( char_id, &char_dat, true ); + char_data = util::umap_find( char_get_chardb(), char_id ); } if( global_core->is_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); + uint32 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); @@ -628,9 +637,10 @@ int chmapif_parse_reqchangemapserv(int fd){ char_data->sex = RFIFOB(fd,30); // create temporary auth entry - CREATE(node, struct auth_node, 1); + std::shared_ptr node = std::make_shared(); + node->account_id = aid; - node->char_id = RFIFOL(fd,14); + node->char_id = char_id; node->login_id1 = RFIFOL(fd,6); node->login_id2 = RFIFOL(fd,10); node->sex = RFIFOB(fd,30); @@ -638,9 +648,15 @@ int chmapif_parse_reqchangemapserv(int fd){ node->ip = ntohl(RFIFOL(fd,31)); node->group_id = RFIFOL(fd,35); node->changing_mapservers = 1; - idb_put(auth_db, aid, node); - data = (struct online_char_data*)idb_ensure(online_char_db, aid, char_create_online_data); + char_get_authdb()[node->account_id] = node; + + std::shared_ptr data = util::umap_find( char_get_onlinedb(), aid ); + + if( data == nullptr ){ + data = std::make_shared( aid ); + } + data->char_id = char_data->char_id; data->server = map_id; //Update server where char is. @@ -988,14 +1004,9 @@ int chmapif_parse_reqauth(int fd, int id){ uint32 login_id1; unsigned char sex; uint32 ip; - struct auth_node* node; - struct mmo_charstatus* cd; struct mmo_charstatus char_dat; bool autotrade; - 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); @@ -1004,13 +1015,15 @@ int chmapif_parse_reqauth(int fd, int id){ autotrade = RFIFOB(fd,19) != 0; 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. (or autotrade) - char_mmo_char_fromsql(char_id, &char_dat, true); - cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); + std::shared_ptr node = util::umap_find( char_get_authdb(), account_id ); + std::shared_ptr cd = util::umap_find( char_get_chardb(), char_id ); + + if( cd == nullptr ){ + // Really shouldn't happen. (or autotrade) + char_mmo_char_fromsql( char_id, &char_dat, true ); + cd = util::umap_find( char_get_chardb(), char_id ); } + if( global_core->is_running() && autotrade && cd ){ uint16 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; @@ -1023,7 +1036,7 @@ int chmapif_parse_reqauth(int fd, int id){ WFIFOL(fd,16) = 0; WFIFOL(fd,20) = 0; WFIFOB(fd,24) = 0; - memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); + memcpy( WFIFOP( fd, 25 ), cd.get(), sizeof(struct mmo_charstatus)); WFIFOSET(fd, WFIFOW(fd,2)); char_set_char_online(id, char_id, account_id); @@ -1050,11 +1063,11 @@ int chmapif_parse_reqauth(int fd, int id){ 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)); + memcpy( WFIFOP( fd, 25 ), cd.get(), 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_get_authdb().erase( account_id ); char_set_char_online(id, char_id, account_id); } else {// auth failed WFIFOHEAD(fd,19); @@ -1492,7 +1505,6 @@ void chmapif_server_reset(int id){ int j = 0; 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; @@ -1505,7 +1517,12 @@ void chmapif_server_reset(int id){ WBUFW(buf,2) = j * 4 + 10; chmapif_sendallwos(fd, buf, WBUFW(buf,2)); } - online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. + + // Tag relevant chars as 'in disconnected' server. + for( const auto& pair : char_get_onlinedb() ){ + char_db_setoffline( pair.second, id ); + } + chmapif_server_destroy(id); chmapif_server_init(id); } diff --git a/src/char/int_auction.cpp b/src/char/int_auction.cpp index 620ad7b9a0..2959b9e52f 100644 --- a/src/char/int_auction.cpp +++ b/src/char/int_auction.cpp @@ -3,6 +3,9 @@ #include "int_auction.hpp" +#include +#include + #include #include #include @@ -14,35 +17,37 @@ #include "../common/sql.hpp" #include "../common/strlib.hpp" #include "../common/timer.hpp" +#include "../common/utilities.hpp" #include "char.hpp" #include "char_mapif.hpp" #include "inter.hpp" #include "int_mail.hpp" -static DBMap* auction_db_ = NULL; // int auction_id -> struct auction_data* +using namespace rathena; -void auction_delete(struct auction_data *auction); +// int auction_id -> struct auction_data* +static std::unordered_map> auction_db; + +void auction_delete( std::shared_ptr auction ); TIMER_FUNC(auction_end_timer); int auction_count(uint32 char_id, bool buy) { int i = 0; - struct auction_data *auction; - DBIterator *iter = db_iterator(auction_db_); - for( auction = (struct auction_data *)dbi_first(iter); dbi_exists(iter); auction = (struct auction_data *)dbi_next(iter) ) - { - if( (buy && auction->buyer_id == char_id) || (!buy && auction->seller_id == char_id) ) + for( const auto& pair : auction_db ){ + std::shared_ptr auction = pair.second; + + if( ( buy && auction->buyer_id == char_id ) || ( !buy && auction->seller_id == char_id ) ){ i++; + } } - dbi_destroy(iter); return i; } -void auction_save(struct auction_data *auction) -{ +void auction_save( std::shared_ptr auction ){ int j; StringBuf buf; SqlStmt* stmt; @@ -76,8 +81,7 @@ void auction_save(struct auction_data *auction) StringBuf_Destroy(&buf); } -unsigned int auction_create(struct auction_data *auction) -{ +uint32 auction_create( std::shared_ptr auction ){ int j; StringBuf buf; SqlStmt* stmt; @@ -119,7 +123,6 @@ unsigned int auction_create(struct auction_data *auction) } else { - struct auction_data *auction_; t_tick tick = auction->hours * 3600000; auction->item.amount = 1; @@ -130,9 +133,7 @@ unsigned int auction_create(struct auction_data *auction) auction->auction_end_timer = add_timer( gettick() + tick , auction_end_timer, auction->auction_id, 0); ShowInfo("New Auction %u | time left %" PRtf " ms | By %s.\n", auction->auction_id, tick, auction->seller_name); - CREATE(auction_, struct auction_data, 1); - memcpy(auction_, auction, sizeof(struct auction_data)); - idb_put(auction_db_, auction_->auction_id, auction_); + auction_db[auction->auction_id] = auction; } SqlStmt_Free(stmt); @@ -152,9 +153,9 @@ void mapif_Auction_message(uint32 char_id, unsigned char result) } TIMER_FUNC(auction_end_timer){ - struct auction_data *auction; - if( (auction = (struct auction_data *)idb_get(auction_db_, id)) != NULL ) - { + std::shared_ptr auction = util::umap_find( auction_db, static_cast( id ) ); + + if( auction != nullptr ){ if( auction->buyer_id ) { mail_sendmail(0, msg_txt(200), auction->buyer_id, auction->buyer_name, msg_txt(201), msg_txt(202), 0, &auction->item, 1); @@ -173,8 +174,7 @@ TIMER_FUNC(auction_end_timer){ return 0; } -void auction_delete(struct auction_data *auction) -{ +void auction_delete( std::shared_ptr auction ){ unsigned int auction_id = auction->auction_id; if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", schema_config.auction_db, auction_id) ) @@ -183,7 +183,7 @@ void auction_delete(struct auction_data *auction) if( auction->auction_end_timer != INVALID_TIMER ) delete_timer(auction->auction_end_timer, auction_end_timer); - idb_remove(auction_db_, auction_id); + auction_db.erase( auction_id ); } void inter_auctions_fromsql(void) @@ -214,8 +214,8 @@ void inter_auctions_fromsql(void) while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { struct item *item; - struct auction_data *auction; - CREATE(auction, struct auction_data, 1); + std::shared_ptr auction = std::make_shared(); + Sql_GetData(sql_handle, 0, &data, NULL); auction->auction_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); auction->seller_id = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(auction->seller_name, data, NAME_LENGTH); @@ -261,7 +261,8 @@ void inter_auctions_fromsql(void) endtick = tick + 10000; // 10 Second's to process ended auctions auction->auction_end_timer = add_timer(endtick, auction_end_timer, auction->auction_id, 0); - idb_put(auction_db_, auction->auction_id, auction); + + auction_db[auction->auction_id] = auction; } Sql_FreeResult(sql_handle); @@ -288,14 +289,13 @@ void mapif_parse_Auction_requestlist(int fd) int price = RFIFOL(fd,10); short type = RFIFOW(fd,8), page = max(1,RFIFOW(fd,14)); unsigned char buf[5 * sizeof(struct auction_data)]; - DBIterator *iter = db_iterator(auction_db_); - struct auction_data *auction; short i = 0, j = 0, pages = 1; memcpy(searchtext, RFIFOP(fd,16), NAME_LENGTH); - for( auction = static_cast(dbi_first(iter)); dbi_exists(iter); auction = static_cast(dbi_next(iter)) ) - { + for( const auto& pair : auction_db ){ + std::shared_ptr auction = pair.second; + if( (type == 0 && auction->type != IT_ARMOR && auction->type != IT_PETARMOR) || (type == 1 && auction->type != IT_WEAPON) || (type == 2 && auction->type != IT_CARD) || @@ -316,10 +316,9 @@ void mapif_parse_Auction_requestlist(int fd) if( page != pages ) continue; // This is not the requested Page - memcpy(WBUFP(buf, j * len), auction, len); + memcpy( WBUFP( buf, j * len ), auction.get(), len ); j++; // Found Results } - dbi_destroy(iter); mapif_Auction_sendlist(fd, char_id, j, pages, buf); } @@ -337,15 +336,22 @@ void mapif_Auction_register(int fd, struct auction_data *auction) void mapif_parse_Auction_register(int fd) { - struct auction_data auction; if( RFIFOW(fd,2) != sizeof(struct auction_data) + 4 ) return; - memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data)); - if( auction_count(auction.seller_id, false) < 5 ) - auction.auction_id = auction_create(&auction); + struct auction_data* auction = reinterpret_cast( RFIFOP( fd, 4 ) ); - mapif_Auction_register(fd, &auction); + if( auction_count( auction->seller_id, false ) < 5 ){ + std::shared_ptr auction2 = std::make_shared(); + + memcpy( auction2.get(), auction, sizeof( struct auction_data ) ); + + auction2->auction_id = auction_create( auction2 ); + + auction = auction2.get(); + } + + mapif_Auction_register( fd, auction ); } void mapif_Auction_cancel(int fd, uint32 char_id, unsigned char result) @@ -360,10 +366,10 @@ void mapif_Auction_cancel(int fd, uint32 char_id, unsigned char result) void mapif_parse_Auction_cancel(int fd) { uint32 char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6); - struct auction_data *auction; - if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL ) - { + std::shared_ptr auction = util::umap_find( auction_db, auction_id ); + + if( auction == nullptr ){ mapif_Auction_cancel(fd, char_id, 1); // Bid Number is Incorrect return; } @@ -398,10 +404,9 @@ void mapif_Auction_close(int fd, uint32 char_id, unsigned char result) void mapif_parse_Auction_close(int fd) { uint32 char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6); - struct auction_data *auction; + std::shared_ptr auction = util::umap_find( auction_db, auction_id ); - if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL ) - { + if( auction == nullptr ){ mapif_Auction_close(fd, char_id, 2); // Bid Number is Incorrect return; } @@ -442,10 +447,9 @@ void mapif_parse_Auction_bid(int fd) { uint32 char_id = RFIFOL(fd,4), auction_id = RFIFOL(fd,8); int bid = RFIFOL(fd,12); - struct auction_data *auction; + std::shared_ptr auction = util::umap_find( auction_db, auction_id ); - if( (auction = (struct auction_data *)idb_get(auction_db_, auction_id)) == NULL || auction->price >= bid || auction->seller_id == char_id ) - { + if( auction == nullptr || auction->price >= bid || auction->seller_id == char_id ){ mapif_Auction_bid(fd, char_id, bid, 0); // You have failed to bid in the auction return; } @@ -508,7 +512,6 @@ int inter_auction_parse_frommap(int fd) int inter_auction_sql_init(void) { - auction_db_ = idb_alloc(DB_OPT_RELEASE_DATA); inter_auctions_fromsql(); return 0; @@ -516,7 +519,7 @@ int inter_auction_sql_init(void) void inter_auction_sql_final(void) { - auction_db_->destroy(auction_db_,NULL); + auction_db.clear(); return; } diff --git a/src/char/int_clan.cpp b/src/char/int_clan.cpp index c882047c35..5ea0e9b510 100644 --- a/src/char/int_clan.cpp +++ b/src/char/int_clan.cpp @@ -3,6 +3,10 @@ #include "int_clan.hpp" +#include +#include +#include + #include #include //memset @@ -17,8 +21,10 @@ #include "char_mapif.hpp" #include "inter.hpp" -//clan cache -static DBMap* clan_db; // int clan_id -> struct clan* +// int clan_id -> struct clan* +static std::unordered_map> clan_db; + +using namespace rathena; int inter_clan_removemember_tosql(uint32 account_id, uint32 char_id){ if( SQL_ERROR == Sql_Query( sql_handle, "UPDATE `%s` SET `clan_id` = '0' WHERE `char_id` = '%d'", schema_config.char_db, char_id ) ){ @@ -29,16 +35,15 @@ int inter_clan_removemember_tosql(uint32 account_id, uint32 char_id){ } } -struct clan* inter_clan_fromsql(int clan_id){ - struct clan* clan; +std::shared_ptr inter_clan_fromsql(int clan_id){ char* data; size_t len; int i; if( clan_id <= 0 ) - return NULL; + return nullptr; - clan = (struct clan*)idb_get(clan_db, clan_id); + std::shared_ptr clan = util::umap_find( clan_db, clan_id ); if( clan ){ return clan; @@ -46,15 +51,14 @@ struct clan* inter_clan_fromsql(int clan_id){ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`, `master`, `mapname`, `max_member` FROM `%s` WHERE `clan_id`='%d'", schema_config.clan_table, clan_id) ){ Sql_ShowDebug(sql_handle); - return NULL; + return nullptr; } if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){ - return NULL;// Clan does not exists. + return nullptr; // Clan does not exists. } - CREATE(clan, struct clan, 1); - memset(clan, 0, sizeof(struct clan)); + clan = std::make_shared(); clan->id = clan_id; Sql_GetData(sql_handle, 0, &data, &len); memcpy(clan->name, data, min(len, NAME_LENGTH)); @@ -73,8 +77,7 @@ struct clan* inter_clan_fromsql(int clan_id){ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `clan_id`='%d'", schema_config.clan_alliance_table, clan_id) ){ Sql_ShowDebug(sql_handle); - aFree(clan); - return NULL; + return nullptr; } for( i = 0; i < MAX_CLANALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); i++ ){ @@ -85,7 +88,7 @@ struct clan* inter_clan_fromsql(int clan_id){ Sql_GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, zmin(len, NAME_LENGTH)); } - idb_put( clan_db, clan_id, clan); + clan_db[clan->id] = clan; if (charserv_config.save_log) ShowInfo("Clan loaded (%d - %s)\n", clan_id, clan->name); @@ -94,24 +97,22 @@ struct clan* inter_clan_fromsql(int clan_id){ } int mapif_clan_info( int fd ){ - DBIterator *iter; int offset; - struct clan* clan; int length; - length = 4 + db_size(clan_db) * sizeof( struct clan ); + length = 4 + clan_db.size() * sizeof( struct clan ); WFIFOHEAD( fd, length ); WFIFOW( fd, 0 ) = 0x38A0; WFIFOW( fd, 2 ) = length; offset = 4; - iter = db_iterator(clan_db); - for( clan = (struct clan*)dbi_first(iter); dbi_exists(iter); clan = (struct clan*)dbi_next(iter) ){ - memcpy( WFIFOP( fd, offset ), clan, sizeof( struct clan ) ); + for( const auto& pair : clan_db ){ + std::shared_ptr clan = pair.second; + + memcpy( WFIFOP( fd, offset ), clan.get(), sizeof( struct clan ) ); offset += sizeof( struct clan ); } - dbi_destroy(iter); WFIFOSET( fd, length ); @@ -138,7 +139,7 @@ static int mapif_parse_clan_message( int fd ){ return 0; } -static void mapif_clan_refresh_onlinecount( int fd, struct clan* clan ){ +static void mapif_clan_refresh_onlinecount( int fd, std::shared_ptr clan ){ unsigned char buf[8]; WBUFW(buf,0) = 0x38A2; @@ -149,9 +150,10 @@ static void mapif_clan_refresh_onlinecount( int fd, struct clan* clan ){ } static void mapif_parse_clan_member_left( int fd ){ - struct clan* clan = (struct clan*)idb_get(clan_db, RFIFOL(fd,2) ); + std::shared_ptr clan = util::umap_find( clan_db, static_cast( RFIFOL( fd, 2 ) ) ); - if( clan == NULL ){ // Unknown clan + // Unknown clan + if( clan == nullptr ){ return; } @@ -163,9 +165,10 @@ static void mapif_parse_clan_member_left( int fd ){ } static void mapif_parse_clan_member_joined( int fd ){ - struct clan* clan = (struct clan*)idb_get(clan_db, RFIFOL(fd,2) ); + std::shared_ptr clan = util::umap_find( clan_db, static_cast( RFIFOL( fd, 2 ) ) ); - if( clan == NULL ){ // Unknown clan + // Unknown clan + if( clan == nullptr ){ return; } @@ -203,45 +206,28 @@ int inter_clan_parse_frommap( int fd ){ // Initialize clan sql int inter_clan_init(void){ - char* data; - int* clan_ids; - int amount; - - clan_db = idb_alloc(DB_OPT_RELEASE_DATA); - if( SQL_ERROR == Sql_Query( sql_handle, "SELECT `clan_id` FROM `%s`", schema_config.clan_table ) ){ Sql_ShowDebug(sql_handle); return 1; } - amount = (int)Sql_NumRows( sql_handle ); + std::vector clan_ids; - if( amount > 0 ){ - int i; + while( SQL_SUCCESS == Sql_NextRow( sql_handle ) ){ + char* data; + Sql_GetData( sql_handle, 0, &data, nullptr ); + clan_ids.push_back( atoi( data ) ); + } - CREATE( clan_ids, int, amount ); - i = 0; + Sql_FreeResult( sql_handle ); - while( SQL_SUCCESS == Sql_NextRow(sql_handle) ){ - Sql_GetData(sql_handle, 0, &data, NULL); - clan_ids[i++] = atoi(data); - } - - Sql_FreeResult( sql_handle ); - - // If we didnt load a row as expected - amount = i; - - for( i = 0; i < amount; i++ ){ - inter_clan_fromsql( clan_ids[i] ); - } - - aFree(clan_ids); + for( int32 clan_id : clan_ids ){ + inter_clan_fromsql( clan_id ); } return 0; } void inter_clan_final(){ - db_destroy(clan_db); + clan_db.clear(); } diff --git a/src/char/int_guild.cpp b/src/char/int_guild.cpp index 95cccdadd4..f328bed205 100644 --- a/src/char/int_guild.cpp +++ b/src/char/int_guild.cpp @@ -3,6 +3,9 @@ #include "int_guild.hpp" +#include +#include + #include #define __STDC_WANT_LIB_EXT1__ 1 #include @@ -34,32 +37,29 @@ using namespace rathena; static const char dataToHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; -//Guild cache -static DBMap* guild_db_; // int guild_id -> struct guild* -static DBMap *castle_db; +// int guild_id -> struct guild* +static std::unordered_map> guild_db; +static std::unordered_map> castle_db; int mapif_parse_GuildLeave(int fd,int guild_id,uint32 account_id,uint32 char_id,int flag,const char *mes); int mapif_guild_broken(int guild_id,int flag); -bool guild_check_empty(struct guild *g); -int guild_calcinfo(struct guild *g); +bool guild_check_empty( std::shared_ptr g ); +int guild_calcinfo( std::shared_ptr g ); int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len); -int mapif_guild_info(int fd,struct guild *g); -int guild_break_sub(int key,void *data,va_list ap); -int inter_guild_tosql(struct guild *g,int flag); -int guild_checkskill(struct guild *g, int id); +int mapif_guild_info( int fd, std::shared_ptr g ); +int inter_guild_tosql( std::shared_ptr g, int flag ); +int guild_checkskill( std::shared_ptr g, int id ); TIMER_FUNC(guild_save_timer){ static int last_id = 0; //To know in which guild we were. int state = 0; //0: Have not reached last guild. 1: Reached last guild, ready for save. 2: Some guild saved, don't do further saving. - DBIterator *iter = db_iterator(guild_db_); - DBKey key; - struct guild* g; if( last_id == 0 ) //Save the first guild in the list. state = 1; - for( g = (struct guild*)db_data2ptr(iter->first(iter, &key)); dbi_exists(iter); g = (struct guild*)db_data2ptr(iter->next(iter, &key)) ) - { + for( auto it = guild_db.begin(); it != guild_db.end(); ){ + std::shared_ptr g = it->second; + if( state == 0 && g->guild_id == last_id ) state++; //Save next guild in the list. else if( state == 1 && g->save_flag&GS_MASK ) @@ -72,19 +72,20 @@ TIMER_FUNC(guild_save_timer){ state++; } - if( g->save_flag == GS_REMOVE ) - {// Nothing to save, guild is ready for removal. + // Nothing to save, guild is ready for removal. + if( g->save_flag == GS_REMOVE ){ if (charserv_config.save_log) ShowInfo("Guild Unloaded (%d - %s)\n", g->guild_id, g->name); - db_remove(guild_db_, key); + it = guild_db.erase( it ); + }else{ + it++; } } - dbi_destroy(iter); if( state != 2 ) //Reached the end of the guild db without saving. last_id = 0; //Reset guild saved, return to beginning. - state = guild_db_->size(guild_db_); + state = guild_db.size(); if( state < 1 ) state = 1; //Calculate the time slot for the next save. add_timer(tick + (charserv_config.autosave_interval)/state, guild_save_timer, 0, 0); return 0; @@ -100,8 +101,7 @@ int inter_guild_removemember_tosql(uint32 char_id) } // Save guild into sql -int inter_guild_tosql(struct guild *g,int flag) -{ +int inter_guild_tosql( std::shared_ptr g, int flag ){ // Table guild (GS_BASIC_MASK) // GS_EMBLEM `emblem_len`,`emblem_id`,`emblem_data` // GS_CONNECT `connect_member`,`average_lv` @@ -333,20 +333,21 @@ int inter_guild_tosql(struct guild *g,int flag) } // Read guild from sql -struct guild * inter_guild_fromsql(int guild_id) -{ - struct guild *g; +std::shared_ptr inter_guild_fromsql( int32 guild_id ){ char* data; size_t len; char* p; int i; - if( guild_id <= 0 ) - return NULL; + if( guild_id <= 0 ){ + return nullptr; + } - g = (struct guild*)idb_get(guild_db_, guild_id); - if( g ) + std::shared_ptr g = util::umap_find( guild_db, guild_id ); + + if( g != nullptr ){ return g; + } #ifdef NOISY ShowInfo("Guild load request (%d)...\n", guild_id); @@ -356,13 +357,15 @@ struct guild * inter_guild_fromsql(int 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; + return nullptr; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) - return NULL;// Guild does not exists. + // Guild does not exists. + if( SQL_SUCCESS != Sql_NextRow( sql_handle ) ){ + return nullptr; + } - CREATE(g, struct guild, 1); + g = std::make_shared(); g->guild_id = guild_id; Sql_GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, zmin(len, NAME_LENGTH)); @@ -412,8 +415,7 @@ struct guild * inter_guild_fromsql(int guild_id) "FROM `%s` `m` INNER JOIN `%s` `c` on `c`.`char_id`=`m`.`char_id` WHERE `m`.`guild_id`='%d' ORDER BY `position`", schema_config.guild_member_db, schema_config.char_db, guild_id) ) { Sql_ShowDebug(sql_handle); - aFree(g); - return NULL; + return nullptr; } for( i = 0; i < g->max_member && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { @@ -452,8 +454,7 @@ struct guild * inter_guild_fromsql(int 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); - return NULL; + return nullptr; } while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { @@ -474,8 +475,7 @@ struct guild * inter_guild_fromsql(int 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); - return NULL; + return nullptr; } for( i = 0; i < MAX_GUILDALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { @@ -490,8 +490,7 @@ struct guild * inter_guild_fromsql(int 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); - return NULL; + return nullptr; } for( i = 0; i < MAX_GUILDEXPULSION && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { @@ -506,8 +505,7 @@ struct guild * inter_guild_fromsql(int 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); - return NULL; + return nullptr; } for(i = 0; i < MAX_GUILDSKILL; i++) @@ -525,8 +523,11 @@ struct guild * inter_guild_fromsql(int guild_id) } Sql_FreeResult(sql_handle); - 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. + // Add to cache + guild_db[g->guild_id] = g; + + // But set it to be removed, in case it is not needed for long. + g->save_flag |= GS_REMOVE; if (charserv_config.save_log) ShowInfo("Guild loaded (%d - %s)\n", guild_id, g->name); @@ -542,10 +543,10 @@ struct guild * inter_guild_fromsql(int guild_id) uint16 inter_guild_storagemax(int guild_id) { #ifdef OFFICIAL_GUILD_STORAGE - struct guild *g = inter_guild_fromsql(guild_id); + std::shared_ptr g = inter_guild_fromsql( guild_id ); uint16 max = 0; - if (!g) { + if( g == nullptr ){ ShowError("Guild %d not found!\n", guild_id); return 0; } @@ -561,8 +562,7 @@ uint16 inter_guild_storagemax(int guild_id) } // `guild_castle` (`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, `visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`) -int inter_guildcastle_tosql(struct guild_castle *gc) -{ +int inter_guildcastle_tosql( std::shared_ptr gc ){ StringBuf buf; int i; @@ -584,15 +584,16 @@ int inter_guildcastle_tosql(struct guild_castle *gc) } // Read guild_castle from SQL -struct guild_castle* inter_guildcastle_fromsql(int castle_id) -{ +std::shared_ptr inter_guildcastle_fromsql( int castle_id ){ char *data; int i; StringBuf buf; - struct guild_castle *gc = (struct guild_castle *)idb_get(castle_db, castle_id); - if (gc != NULL) + std::shared_ptr gc = util::umap_find( castle_db, castle_id ); + + if( gc != nullptr ){ return gc; + } StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, " @@ -607,7 +608,8 @@ struct guild_castle* inter_guildcastle_fromsql(int castle_id) } StringBuf_Destroy(&buf); - CREATE(gc, struct guild_castle, 1); + gc = std::make_shared(); + gc->castle_id = castle_id; if (SQL_SUCCESS == Sql_NextRow(sql_handle)) { @@ -626,7 +628,7 @@ struct guild_castle* inter_guildcastle_fromsql(int castle_id) } Sql_FreeResult(sql_handle); - idb_put(castle_db, castle_id, gc); + castle_db[gc->castle_id] = gc; if (charserv_config.save_log) ShowInfo("Loaded guild castle (%d - guild %d)\n", castle_id, gc->guild_id); @@ -637,7 +639,6 @@ struct guild_castle* inter_guildcastle_fromsql(int castle_id) int inter_guild_CharOnline(uint32 char_id, int guild_id) { - struct guild *g; int i; if (guild_id == -1) { @@ -664,8 +665,9 @@ int inter_guild_CharOnline(uint32 char_id, int guild_id) if (guild_id == 0) return 0; //No guild... - g = inter_guild_fromsql(guild_id); - if(!g) { + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + if( g == nullptr ){ ShowError("Character %d's guild %d not found!\n", char_id, guild_id); return 0; } @@ -687,7 +689,6 @@ int inter_guild_CharOnline(uint32 char_id, int guild_id) int inter_guild_CharOffline(uint32 char_id, int guild_id) { - struct guild *g=NULL; int online_count, i; if (guild_id == -1) @@ -716,9 +717,12 @@ int inter_guild_CharOffline(uint32 char_id, int guild_id) return 0; //No guild... //Character has a guild, set character offline and check if they were the only member online - g = inter_guild_fromsql(guild_id); - if (g == NULL) //Guild not found? + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + // Guild not found? + if( g == nullptr ){ return 0; + } //Set member offline ARR_FIND( 0, g->max_member, i, g->member[i].char_id == char_id ); @@ -800,33 +804,22 @@ void GuildExpDatabase::loadingFinished() { // Initialize guild sql and read exp_guild.yml void inter_guild_sql_init(void) { - //Initialize the guild cache - guild_db_= idb_alloc(DB_OPT_RELEASE_DATA); - castle_db = idb_alloc(DB_OPT_RELEASE_DATA); - guild_exp_db.load(); add_timer_func_list(guild_save_timer, "guild_save_timer"); add_timer(gettick() + 10000, guild_save_timer, 0, 0); } -/** - * @see DBApply - */ -int guild_db_final(DBKey key, DBData *data, va_list ap) -{ - struct guild *g = (struct guild*)db_data2ptr(data); - if (g->save_flag&GS_MASK) { - inter_guild_tosql(g, g->save_flag&GS_MASK); - return 1; - } - return 0; -} - void inter_guild_sql_final(void) { - guild_db_->destroy(guild_db_, guild_db_final); - db_destroy(castle_db); - return; + for( const auto& pair : guild_db ){ + std::shared_ptr guild = pair.second; + + if( guild->save_flag&GS_MASK ){ + inter_guild_tosql( guild, guild->save_flag&GS_MASK ); + } + } + guild_db.clear(); + castle_db.clear(); } // Get guild_id by its name. Returns 0 if not found, -1 on error. @@ -859,8 +852,7 @@ int search_guildname(char *str) } // Check if guild is empty -bool guild_check_empty(struct guild *g) -{ +bool guild_check_empty( std::shared_ptr g ){ int i; ARR_FIND( 0, g->max_member, i, g->member[i].account_id > 0 ); //Let the calling function handle the guild removal in case they need @@ -874,14 +866,12 @@ t_exp GuildExpDatabase::get_nextexp(uint16 level) { return ((guild_exp == nullptr) ? 0 : guild_exp->exp); } -int guild_checkskill(struct guild *g,int id) -{ +int guild_checkskill( std::shared_ptr g, int id ){ int idx = id - GD_SKILLBASE; return idx < 0 || idx >= MAX_GUILDSKILL ? 0 : g->skill[idx].lv; } -int guild_calcinfo(struct guild *g) -{ +int guild_calcinfo( std::shared_ptr g ){ int i,c; struct guild before = *g; // Save guild current values @@ -943,8 +933,7 @@ int guild_calcinfo(struct guild *g) //------------------------------------------------------------------- // Packet sent to map server -int mapif_guild_created(int fd,uint32 account_id,struct guild *g) -{ +int mapif_guild_created( int fd, uint32 account_id, std::shared_ptr g ){ WFIFOHEAD(fd, 10); WFIFOW(fd,0)=0x3830; WFIFOL(fd,2)=account_id; @@ -975,12 +964,11 @@ int mapif_guild_noinfo(int fd,int guild_id) } // Send guild info -int mapif_guild_info(int fd,struct guild *g) -{ +int mapif_guild_info( int fd, std::shared_ptr g ){ unsigned char buf[8+sizeof(struct guild)]; WBUFW(buf,0)=0x3831; WBUFW(buf,2)=4+sizeof(struct guild); - memcpy(buf+4,g,sizeof(struct guild)); + memcpy( buf + 4, g.get(), sizeof( struct guild ) ); if(fd<0) chmapif_sendall(buf,WBUFW(buf,2)); else @@ -1018,8 +1006,7 @@ int mapif_guild_withdraw(int guild_id,uint32 account_id,uint32 char_id,int flag, } // Send short member's info -int mapif_guild_memberinfoshort(struct guild *g,int idx) -{ +int mapif_guild_memberinfoshort( std::shared_ptr g, int idx ){ unsigned char buf[19]; WBUFW(buf, 0)=0x3835; WBUFL(buf, 2)=g->guild_id; @@ -1120,8 +1107,7 @@ int mapif_guild_alliance(int guild_id1,int guild_id2,uint32 account_id1,uint32 a } // Send a guild position desc -int mapif_guild_position(struct guild *g,int idx) -{ +int mapif_guild_position( std::shared_ptr g, int idx ){ unsigned char buf[12 + sizeof(struct guild_position)]; WBUFW(buf,0)=0x383b; WBUFW(buf,2)=sizeof(struct guild_position)+12; @@ -1133,8 +1119,7 @@ int mapif_guild_position(struct guild *g,int idx) } // Send the guild notice -int mapif_guild_notice(struct guild *g) -{ +int mapif_guild_notice( std::shared_ptr g ){ unsigned char buf[256]; WBUFW(buf,0)=0x383e; WBUFL(buf,2)=g->guild_id; @@ -1145,8 +1130,7 @@ int mapif_guild_notice(struct guild *g) } // Send emblem data -int mapif_guild_emblem(struct guild *g) -{ +int mapif_guild_emblem( std::shared_ptr g ){ unsigned char buf[12 + sizeof(g->emblem_data)]; WBUFW(buf,0)=0x383f; WBUFW(buf,2)=g->emblem_len+12; @@ -1158,8 +1142,7 @@ int mapif_guild_emblem(struct guild *g) } // Send the guild emblem_id (version) -int mapif_guild_emblem_version(guild* g) -{ +int mapif_guild_emblem_version( std::shared_ptr g ){ unsigned char buf[10]; WBUFW(buf, 0) = 0x3841; WBUFL(buf, 2) = g->guild_id; @@ -1169,8 +1152,7 @@ int mapif_guild_emblem_version(guild* g) return 0; } -int mapif_guild_master_changed(struct guild *g, int aid, int cid, time_t time) -{ +int mapif_guild_master_changed( std::shared_ptr g, int aid, int cid, time_t time ){ unsigned char buf[18]; WBUFW(buf,0)=0x3843; WBUFL(buf,2)=g->guild_id; @@ -1183,17 +1165,16 @@ int mapif_guild_master_changed(struct guild *g, int aid, int cid, time_t time) int mapif_guild_castle_dataload(int fd, int sz, int *castle_ids) { - struct guild_castle *gc = NULL; int num = (sz - 4) / sizeof(int); - int len = 4 + num * sizeof(*gc); + int len = 4 + num * sizeof( struct guild_castle ); int i; WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x3840; WFIFOW(fd, 2) = len; for (i = 0; i < num; i++) { - gc = inter_guildcastle_fromsql(*(castle_ids++)); - memcpy(WFIFOP(fd, 4 + i * sizeof(*gc)), gc, sizeof(*gc)); + std::shared_ptr gc = inter_guildcastle_fromsql( *(castle_ids++) ); + memcpy( WFIFOP( fd, 4 + i * sizeof( struct guild_castle ) ), gc.get(), sizeof( struct guild_castle ) ); } WFIFOSET(fd, len); return 0; @@ -1206,7 +1187,6 @@ int mapif_guild_castle_dataload(int fd, int sz, int *castle_ids) // Guild creation request int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_member *master) { - struct guild *g; int i=0; #ifdef NOISY ShowInfo("Creating Guild (%s)\n", name); @@ -1231,8 +1211,9 @@ int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_mem } } - g = (struct guild *)aMalloc(sizeof(struct guild)); - memset(g,0,sizeof(struct guild)); + std::shared_ptr g = std::make_shared(); + + memset( g.get(), 0, sizeof( struct guild ) ); memcpy(g->name,name,NAME_LENGTH); memcpy(g->master,master->name,NAME_LENGTH); @@ -1263,13 +1244,12 @@ int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_mem //Failed to Create guild.... ShowError("Failed to create Guild %s (Guild Master: %s)\n", g->name, g->master); mapif_guild_created(fd,account_id,NULL); - aFree(g); return 0; } ShowInfo("Created Guild %d - %s (Guild Master: %s)\n", g->guild_id, g->name, g->master); - //Add to cache - idb_put(guild_db_, g->guild_id, g); + // Add to cache + guild_db[g->guild_id] = g; // Report to client mapif_guild_created(fd,account_id,g); @@ -1285,13 +1265,12 @@ int mapif_parse_CreateGuild(int fd,uint32 account_id,char *name,struct guild_mem // Return guild info to client int mapif_parse_GuildInfo(int fd,int guild_id) { - struct guild * g = inter_guild_fromsql(guild_id); //We use this because on start-up the info of castle-owned guilds is requied. [Skotlex] - if(g) - { + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + if( g != nullptr ){ if (!guild_calcinfo(g)) mapif_guild_info(fd,g); - } - else + }else mapif_guild_noinfo(fd,guild_id); // Failed to load info return 0; } @@ -1299,19 +1278,16 @@ int mapif_parse_GuildInfo(int fd,int guild_id) // Add member to guild int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m) { - struct guild * g; - int i; + std::shared_ptr g = inter_guild_fromsql( guild_id ); - g = inter_guild_fromsql(guild_id); - if(g==NULL){ + if( g == nullptr ){ // Failed to add mapif_guild_memberadded(fd,guild_id,m->account_id,m->char_id,1); return 0; } // Find an empty slot - for(i=0;imax_member;i++) - { + for( int i = 0; i < g->max_member; i++ ){ if(g->member[i].account_id==0) { memcpy(&g->member[i],m,sizeof(struct guild_member)); @@ -1337,9 +1313,9 @@ int mapif_parse_GuildLeave(int fd, int guild_id, uint32 account_id, uint32 char_ { int i; - struct guild* g = inter_guild_fromsql(guild_id); - if( g == NULL ) - { + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + if( g == nullptr ){ // 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'", schema_config.char_db, account_id, char_id) ) Sql_ShowDebug(sql_handle); @@ -1394,13 +1370,14 @@ int mapif_parse_GuildLeave(int fd, int guild_id, uint32 account_id, uint32 char_ int mapif_parse_GuildChangeMemberInfoShort(int fd,int guild_id,uint32 account_id,uint32 char_id,int online,int lv,int class_) { // Could speed up by manipulating only guild_member - struct guild * g; int i,sum,c; int prev_count, prev_alv; - g = inter_guild_fromsql(guild_id); - if(g==NULL) + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + if( g == nullptr ){ return 0; + } ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id ); if( i < g->max_member ) @@ -1446,11 +1423,11 @@ int mapif_parse_GuildChangeMemberInfoShort(int fd,int guild_id,uint32 account_id // BreakGuild int mapif_parse_BreakGuild(int fd,int guild_id) { - struct guild * g; + std::shared_ptr g = inter_guild_fromsql( guild_id ); - g = inter_guild_fromsql(guild_id); - if(g==NULL) + if( g == nullptr ){ return 0; + } // Delete guild from sql //printf("- Delete guild %d from guild\n",guild_id); @@ -1487,8 +1464,9 @@ int mapif_parse_BreakGuild(int fd,int guild_id) if(charserv_config.log_inter) inter_log("guild %s (id=%d) broken\n",g->name,guild_id); - //Remove the guild from memory. [Skotlex] - idb_remove(guild_db_, guild_id); + // Remove the guild from memory. [Skotlex] + guild_db.erase( guild_id ); + return 0; } @@ -1501,10 +1479,11 @@ int mapif_parse_GuildMessage(int fd,int guild_id,uint32 account_id,char *mes,int // Modification of the guild int mapif_parse_GuildBasicInfoChange(int fd,int guild_id,int type,const char *data,int len) { - struct guild *g = inter_guild_fromsql(guild_id); + std::shared_ptr g = inter_guild_fromsql( guild_id ); - if (!g) + if( g == nullptr ){ return 0; + } short data_value = *((short *)data); @@ -1542,11 +1521,12 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,uint32 account_id,uint { // Could make some improvement in speed, because only change guild_member int i; - struct guild * g; - g = inter_guild_fromsql(guild_id); - if(g==NULL) + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + if( g == nullptr ){ return 0; + } // Search the member for(i=0;imax_member;i++) @@ -1649,12 +1629,11 @@ int inter_guild_sex_changed(int guild_id,uint32 account_id,uint32 char_id, short int inter_guild_charname_changed(int guild_id,uint32 account_id, uint32 char_id, char *name) { - struct guild *g; int i, flag = 0; - g = inter_guild_fromsql(guild_id); - if( g == NULL ) - { + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + if( g == nullptr ){ ShowError("inter_guild_charrenamed: Can't find guild %d.\n", guild_id); return 0; } @@ -1687,11 +1666,11 @@ int inter_guild_charname_changed(int guild_id,uint32 account_id, uint32 char_id, int mapif_parse_GuildPosition(int fd,int guild_id,int idx,struct guild_position *p) { // Could make some improvement in speed, because only change guild_position - struct guild * g; + std::shared_ptr g = inter_guild_fromsql( guild_id ); - g = inter_guild_fromsql(guild_id); - if(g==NULL || idx<0 || idx>=MAX_GUILDPOSITION) + if( g == nullptr || idx < 0 || idx >= MAX_GUILDPOSITION ){ return 0; + } memcpy(&g->position[idx],p,sizeof(struct guild_position)); mapif_guild_position(g,idx); @@ -1703,12 +1682,13 @@ int mapif_parse_GuildPosition(int fd,int guild_id,int idx,struct guild_position // Guild Skill UP int mapif_parse_GuildSkillUp(int fd,int guild_id,uint16 skill_id,uint32 account_id,int max) { - struct guild * g; int idx = skill_id - GD_SKILLBASE; - g = inter_guild_fromsql(guild_id); - if(g == NULL || idx < 0 || idx >= MAX_GUILDSKILL) + std::shared_ptr g = inter_guild_fromsql( guild_id ); + + if( g == nullptr || idx < 0 || idx >= MAX_GUILDSKILL ){ return 0; + } if(g->skill_point>0 && g->skill[idx].id>0 && g->skill[idx].lv g, int guild_id, uint32 account_id1, uint32 account_id2, int flag ){ int i; char name[NAME_LENGTH]; @@ -1755,16 +1734,19 @@ int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, uint32 accoun int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2,uint32 account_id1,uint32 account_id2,int flag) { // Could speed up - struct guild *g[2]; + std::shared_ptr g[2]; int j,i; g[0] = inter_guild_fromsql(guild_id1); g[1] = inter_guild_fromsql(guild_id2); - if(g[0] && g[1]==NULL && (flag & GUILD_ALLIANCE_REMOVE)) //Requested to remove an alliance with a not found guild. + // Requested to remove an alliance with a not found guild. + if( g[0] != nullptr && g[1] == nullptr && ( flag & GUILD_ALLIANCE_REMOVE ) ){ return mapif_parse_GuildDeleteAlliance(g[0], guild_id2, account_id1, account_id2, flag); //Try to do a manual removal of said guild. + } - if(g[0]==NULL || g[1]==NULL) + if( g[0] == nullptr || g[1] == nullptr ){ return 0; + } if(flag&GUILD_ALLIANCE_REMOVE) { @@ -1805,11 +1787,11 @@ int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2,uint32 account_ // Change guild message int mapif_parse_GuildNotice(int fd,int guild_id,const char *mes1,const char *mes2) { - struct guild *g; + std::shared_ptr g = inter_guild_fromsql( guild_id ); - g = inter_guild_fromsql(guild_id); - if(g==NULL) + if( g == nullptr ){ return 0; + } memcpy(g->mes1,mes1,MAX_GUILDMES1); memcpy(g->mes2,mes2,MAX_GUILDMES2); @@ -1820,11 +1802,11 @@ int mapif_parse_GuildNotice(int fd,int guild_id,const char *mes1,const char *mes int mapif_parse_GuildEmblem(int fd,int len,int guild_id,int dummy,const char *data) { - struct guild * g; + std::shared_ptr g = inter_guild_fromsql( guild_id ); - g = inter_guild_fromsql(guild_id); - if(g==NULL) + if( g == nullptr ){ return 0; + } if (len > sizeof(g->emblem_data)) len = sizeof(g->emblem_data); @@ -1843,9 +1825,9 @@ int mapif_parse_GuildCastleDataLoad(int fd, int len, int *castle_ids) int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) { - struct guild_castle *gc = inter_guildcastle_fromsql(castle_id); + std::shared_ptr gc = inter_guildcastle_fromsql( castle_id ); - if (gc == NULL) { + if( gc == nullptr ){ ShowError("mapif_parse_GuildCastleDataSave: castle id=%d not found\n", castle_id); return 0; } @@ -1854,7 +1836,7 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) case CD_GUILD_ID: if (charserv_config.log_inter && gc->guild_id != value) { int gid = (value) ? value : gc->guild_id; - struct guild *g = (struct guild*)idb_get(guild_db_, gid); + std::shared_ptr g = util::umap_find( guild_db, gid ); inter_log("guild %s (id=%d) %s castle id=%d\n", (g) ? g->name : "??", gid, (value) ? "occupy" : "abandon", castle_id); } @@ -1882,14 +1864,14 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int len) { - struct guild * g; struct guild_member gm; int pos; - g = inter_guild_fromsql(guild_id); + std::shared_ptr g = inter_guild_fromsql( guild_id ); - if(g==NULL || len > NAME_LENGTH) + if( g == nullptr || len > NAME_LENGTH ){ return 0; + } // Find member (name) for (pos = 0; pos < g->max_member && strncmp(g->member[pos].name, name, len); pos++); @@ -1922,7 +1904,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le int mapif_parse_GuildEmblemVersion(int fd, int guild_id, int version) { - guild* g = inter_guild_fromsql(guild_id); + std::shared_ptr g = inter_guild_fromsql( guild_id ); if (g == nullptr) return 0; diff --git a/src/char/int_mail.cpp b/src/char/int_mail.cpp index caf28edc62..ad6534b3d2 100644 --- a/src/char/int_mail.cpp +++ b/src/char/int_mail.cpp @@ -3,6 +3,8 @@ #include "int_mail.hpp" +#include + #include #include @@ -11,11 +13,14 @@ #include "../common/socket.hpp" #include "../common/sql.hpp" #include "../common/strlib.hpp" +#include "../common/utilities.hpp" #include "char.hpp" #include "char_mapif.hpp" #include "inter.hpp" +using namespace rathena; + bool mail_loadmessage(int mail_id, struct mail_message* msg); void mapif_Mail_return( int fd, uint32 char_id, int mail_id, uint32 account_id_receiver = 0, uint32 account_id_sender = 0 ); bool mapif_Mail_delete( int fd, uint32 char_id, int mail_id, uint32 account_id = 0 ); @@ -460,10 +465,10 @@ bool mapif_Mail_delete( int fd, uint32 char_id, int mail_id, uint32 account_id ) // If the char server triggered this, check if we have to notify a map server if( fd <= 0 ){ - struct online_char_data* character; + std::shared_ptr character = util::umap_find( char_get_onlinedb(), account_id ); // Check for online players - if( ( character = (struct online_char_data*)idb_get( char_get_onlinedb(), account_id ) ) != nullptr && character->server >= 0 ){ + if( character != nullptr && character->server >= 0 ){ fd = map_server[character->server].fd; }else{ // The request was triggered inside the character server or the player is offline now @@ -561,10 +566,10 @@ void mapif_Mail_return( int fd, uint32 char_id, int mail_id, uint32 account_id_r // If the char server triggered this, check if we have to notify a map server if( fd <= 0 ){ - struct online_char_data* character; + std::shared_ptr character = util::umap_find( char_get_onlinedb(), account_id_sender ); // Check for online players - if( ( character = (struct online_char_data*)idb_get( char_get_onlinedb(), account_id_sender ) ) != nullptr && character->server >= 0 ){ + if( character != nullptr && character->server >= 0 ){ fd = map_server[character->server].fd; }else{ // The request was triggered inside the character server or the player is offline now diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp index 433c72ceab..9d56baca5b 100644 --- a/src/char/int_party.cpp +++ b/src/char/int_party.cpp @@ -3,6 +3,9 @@ #include "int_party.hpp" +#include +#include + #include #include @@ -14,11 +17,14 @@ #include "../common/socket.hpp" #include "../common/sql.hpp" #include "../common/strlib.hpp" +#include "../common/utilities.hpp" #include "char.hpp" #include "char_mapif.hpp" #include "inter.hpp" +using namespace rathena; + struct party_data { struct party party; unsigned int min_lv, max_lv; @@ -26,18 +32,18 @@ struct party_data { unsigned char size; //Total size of party. }; -static struct party_data *party_pt; -static DBMap* party_db_; // int party_id -> struct party_data* +// int party_id -> struct party_data* +static std::unordered_map> party_db; int mapif_party_broken(int party_id,int flag); -int party_check_empty(struct party_data *p); +int party_check_empty( std::shared_ptr p ); int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type); -int party_check_exp_share(struct party_data *p); +int party_check_exp_share( std::shared_ptr p ); int mapif_party_optionchanged(int fd,struct party *p, uint32 account_id, int flag); -int party_check_family_share(struct party_data *p); +int party_check_family_share( std::shared_ptr p ); //Updates party's level range and unsets even share if broken. -static int int_party_check_lv(struct party_data *p) { +static int int_party_check_lv( std::shared_ptr p ){ int i; unsigned int lv; p->min_lv = UINT_MAX; @@ -62,8 +68,7 @@ static int int_party_check_lv(struct party_data *p) { return 1; } //Calculates the state of a party. -void int_party_calc_state(struct party_data *p) -{ +void int_party_calc_state( std::shared_ptr p ){ int i; p->min_lv = UINT_MAX; p->max_lv = 0; @@ -116,7 +121,7 @@ int inter_party_tosql(struct party *p, int flag, int index) { // 'party' ('party_id','name','exp','item','leader_id','leader_char') char esc_name[NAME_LENGTH*2+1];// escaped party name - int party_id; + int32 party_id; if( p == NULL || p->party_id == 0 ) return 0; @@ -135,7 +140,7 @@ int inter_party_tosql(struct party *p, int flag, int index) 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); + party_db.erase( party_id ); return 1; } @@ -186,11 +191,9 @@ int inter_party_tosql(struct party *p, int flag, int index) } // Read party from mysql -struct party_data *inter_party_fromsql(int party_id) -{ +std::shared_ptr inter_party_fromsql( int party_id ){ int leader_id = 0; int leader_char = 0; - struct party_data* p; struct party_member* m; char* data; size_t len; @@ -203,12 +206,11 @@ struct party_data *inter_party_fromsql(int party_id) return NULL; //Load from memory - p = (struct party_data*)idb_get(party_db_, party_id); - if( p != NULL ) - return p; + std::shared_ptr p = util::umap_find( party_db, party_id ); - p = party_pt; - memset(p, 0, sizeof(struct party_data)); + if( p != nullptr ){ + return p; + } 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) ) { @@ -219,6 +221,8 @@ struct party_data *inter_party_fromsql(int party_id) if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) return NULL; + p = std::make_shared(); + p->party.party_id = party_id; Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, zmin(len, NAME_LENGTH)); Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0); @@ -249,25 +253,17 @@ struct party_data *inter_party_fromsql(int party_id) 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); - memcpy(p, party_pt, sizeof(struct party_data)); + //init state int_party_calc_state(p); - idb_put(party_db_, party_id, p); + + party_db[p->party.party_id] = p; + return p; } int inter_party_sql_init(void) { - //memory alloc - party_db_ = idb_alloc(DB_OPT_RELEASE_DATA); - party_pt = (struct party_data*)aCalloc(sizeof(struct party_data), 1); - if (!party_pt) { - ShowFatalError("inter_party_sql_init: Out of Memory!\n"); - exit(EXIT_FAILURE); - } - // Remove parties with no members on startup from party_db. [Skotlex] if (charserv_config.clear_parties) { ShowStatus("Cleaning party table...\n"); @@ -281,17 +277,14 @@ int inter_party_sql_init(void) void inter_party_sql_final(void) { - party_db_->destroy(party_db_, NULL); - aFree(party_pt); - return; + party_db.clear(); } // Search for the party according to its name -struct party_data* search_partyname(char* str) -{ +std::shared_ptr search_partyname( char* str ){ char esc_name[NAME_LENGTH*2+1]; char* data; - struct party_data* p = NULL; + std::shared_ptr p = nullptr; 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'", schema_config.party_db, esc_name) ) @@ -306,7 +299,7 @@ struct party_data* search_partyname(char* str) return p; } -int party_check_family_share(struct party_data *p) { +int party_check_family_share( std::shared_ptr p ){ int i; unsigned short map = 0; if (!p->family) @@ -342,16 +335,18 @@ int party_check_family_share(struct party_data *p) { } // Returns whether this party can keep having exp share or not. -int party_check_exp_share(struct party_data *p) -{ +int party_check_exp_share( std::shared_ptr p ){ return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level || party_check_family_share(p)); } // Is there any member in the party? -int party_check_empty(struct party_data *p) -{ +int party_check_empty( std::shared_ptr p ){ int i; - if (p==NULL||p->party.party_id==0) return 1; + + if( p == nullptr || p->party.party_id == 0 ){ + return 1; + } + for(i=0;iparty.member[i].account_id;i++); if (i < MAX_PARTY) return 0; // If there is no member, then break the party @@ -505,15 +500,16 @@ int mapif_party_message(int party_id,uint32 account_id,char *mes,int len, int sf // Create Party int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader) { - struct party_data *p; - int i; - if( (p=search_partyname(name))!=NULL){ + std::shared_ptr p = search_partyname( name ); + + if( p != nullptr ){ mapif_party_created(fd,leader->account_id,leader->char_id,NULL); return 0; } + // Check Authorised letters/symbols in the name of the character 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++) + for( int i = 0; i < NAME_LENGTH && name[i]; i++ ){ if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) { if( name[i] == '"' ) { /* client-special-char */ normalize_name(name,"\""); @@ -523,15 +519,17 @@ 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 (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++) + for( int i = 0; i < NAME_LENGTH && name[i]; i++ ){ 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)); + p = std::make_shared(); memcpy(p->party.name,name,NAME_LENGTH); p->party.exp=0; @@ -545,11 +543,11 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part if (inter_party_tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) { //Add party to db int_party_calc_state(p); - idb_put(party_db_, p->party.party_id, p); + party_db[p->party.party_id] = p; mapif_party_info(fd, &p->party, 0); mapif_party_created(fd,leader->account_id,leader->char_id,&p->party); - } else { //Failed to create party. - aFree(p); + }else{ + // Failed to create party. mapif_party_created(fd,leader->account_id,leader->char_id,NULL); } @@ -559,22 +557,23 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part // Party information request void mapif_parse_PartyInfo(int fd, int party_id, uint32 char_id) { - struct party_data *p; - p = inter_party_fromsql(party_id); - if (p) + std::shared_ptr p = inter_party_fromsql( party_id ); + + if( p != nullptr ){ mapif_party_info(fd, &p->party, char_id); - else + }else{ mapif_party_noinfo(fd, party_id, char_id); + } } // Add a player to party request int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member) { - struct party_data *p; int i; - p = inter_party_fromsql(party_id); - if( p == NULL || p->size == MAX_PARTY ) { + std::shared_ptr p = inter_party_fromsql( party_id ); + + if( p == nullptr || p->size == MAX_PARTY ){ mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1); return 0; } @@ -608,9 +607,9 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member //Party setting change request int mapif_parse_PartyChangeOption(int fd,int party_id,uint32 account_id,int exp,int item) { - struct party_data *p; int flag = 0; - p = inter_party_fromsql(party_id); + + std::shared_ptr p = inter_party_fromsql( party_id ); if(!p) return 0; @@ -630,12 +629,12 @@ int mapif_parse_PartyChangeOption(int fd,int party_id,uint32 account_id,int exp, //Request leave party int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type) { - struct party_data *p; int i,j=-1; - p = inter_party_fromsql(party_id); - if( p == NULL ) - {// Party does not exists? + std::shared_ptr p = inter_party_fromsql( party_id ); + + // Party does not exists? + if( p == nullptr ){ 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; @@ -682,12 +681,13 @@ int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_ // When member goes to other map or levels up. int mapif_parse_PartyChangeMap(int fd, int party_id, uint32 account_id, uint32 char_id, unsigned short map, int online, unsigned int lv) { - struct party_data *p; int i; - p = inter_party_fromsql(party_id); - if (p == NULL) + std::shared_ptr p = inter_party_fromsql( party_id ); + + if( p == nullptr ){ return 0; + } for(i = 0; i < MAX_PARTY && (p->party.member[i].account_id != account_id || @@ -740,9 +740,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, uint32 account_id, uint32 c //Request party dissolution int mapif_parse_BreakParty(int fd,int party_id) { - struct party_data *p; - - p = inter_party_fromsql(party_id); + std::shared_ptr p = inter_party_fromsql( party_id ); if(!p) return 0; @@ -759,16 +757,12 @@ int mapif_parse_PartyMessage(int fd,int party_id,uint32 account_id,char *mes,int int mapif_parse_PartyLeaderChange(int fd,int party_id,uint32 account_id,uint32 char_id) { - struct party_data *p; - int i; - - p = inter_party_fromsql(party_id); + std::shared_ptr p = inter_party_fromsql( party_id ); if(!p) return 0; - for (i = 0; i < MAX_PARTY; i++) - { + for( int i = 0; i < MAX_PARTY; i++ ){ if(p->party.member[i].leader) p->party.member[i].leader = 0; if(p->party.member[i].account_id == account_id && @@ -789,16 +783,16 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,uint32 account_id,uint32 c */ int mapif_parse_PartyShareLevel(int fd,unsigned int share_lvl) { - struct party_data *p; - DBIterator* iter = db_iterator(party_db_); - party_share_level = share_lvl; - for(p = (struct party_data *)dbi_first(iter); dbi_exists(iter); p = (struct party_data *)dbi_next(iter)) { //Update online parties - if(p->party.count > 1) - int_party_calc_state(p); + // Update online parties + for( const auto& pair : party_db ){ + std::shared_ptr p = pair.second; + + if( p->party.count > 1 ){ + int_party_calc_state( p ); + } } - dbi_destroy(iter); return 1; } @@ -839,7 +833,6 @@ int inter_party_leave(int party_id,uint32 account_id, uint32 char_id, char *name int inter_party_CharOnline(uint32 char_id, int party_id) { - struct party_data* p; int i; if( party_id == -1 ) @@ -862,7 +855,8 @@ int inter_party_CharOnline(uint32 char_id, int party_id) if (party_id == 0) return 0; //No party... - p = inter_party_fromsql(party_id); + std::shared_ptr p = inter_party_fromsql( party_id ); + if(!p) { ShowError("Character %d's party %d not found!\n", char_id, party_id); return 0; @@ -885,7 +879,6 @@ int inter_party_CharOnline(uint32 char_id, int party_id) } int inter_party_CharOffline(uint32 char_id, int party_id) { - struct party_data *p=NULL; int i; if( party_id == -1 ) @@ -909,8 +902,11 @@ int inter_party_CharOffline(uint32 char_id, int party_id) { 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) + std::shared_ptr p = inter_party_fromsql( party_id ); + + if( p == nullptr ){ return 0; + } //Set member offline for(i=0; i< MAX_PARTY; i++) { @@ -925,20 +921,21 @@ int inter_party_CharOffline(uint32 char_id, int party_id) { } } - if(!p->party.count) - //Parties don't have any data that needs be saved at this point... so just remove it from memory. - idb_remove(party_db_, party_id); + // Parties don't have any data that needs be saved at this point... so just remove it from memory. + if( p->party.count == 0 ){ + party_db.erase( party_id ); + } + return 1; } int inter_party_charname_changed(int party_id, uint32 char_id, char *name) { - struct party_data* p = NULL; int i; - p = inter_party_fromsql(party_id); - if( p == NULL || p->party.party_id == 0 ) - { + std::shared_ptr p = inter_party_fromsql( party_id ); + + if( p == nullptr || p->party.party_id == 0 ){ ShowError("inter_party_charname_changed: Can't find party %d.\n", party_id); return 0; } diff --git a/src/char/inter.cpp b/src/char/inter.cpp index 7d51b3068b..d321d36a2b 100644 --- a/src/char/inter.cpp +++ b/src/char/inter.cpp @@ -3,11 +3,14 @@ #include "inter.hpp" +#include +#include +#include + #include #include #include #include // for stat/lstat/fstat - [Dekamaster/Ultimate GM Tool] -#include #include "../common/cbasetypes.hpp" #include "../common/database.hpp" @@ -34,12 +37,12 @@ #include "int_quest.hpp" #include "int_storage.hpp" +using namespace rathena; + std::string cfgFile = "inter_athena.yml"; ///< Inter-Config file InterServerDatabase interServerDb; #define WISDATA_TTL (60*1000) //Wis data Time To Live (60 seconds) -#define WISDELLIST_MAX 256 // Number of elements in the list Delete data Wis - Sql* sql_handle = NULL; ///Link to mysql db, connection FD @@ -66,13 +69,18 @@ int inter_recv_packet_length[] = { 2,-1, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30A0- Clan packets }; +#ifndef WHISPER_MESSAGE_SIZE + #define WHISPER_MESSAGE_SIZE 512 +#endif + struct WisData { int id, fd, count, len, gmlvl; t_tick tick; - char src[NAME_LENGTH], dst[NAME_LENGTH], msg[512]; + char src[NAME_LENGTH], dst[NAME_LENGTH], msg[WHISPER_MESSAGE_SIZE]; }; -static DBMap* wis_db = NULL; // int wis_id -> struct WisData* -static int wis_dellist[WISDELLIST_MAX], wis_delnum; + +// int wis_id -> struct WisData* +static std::unordered_map> wis_db; /* from pc.cpp due to @accinfo. any ideas to replace this crap are more than welcome. */ const char* job_name(int class_) { @@ -405,7 +413,7 @@ void geoip_readdb(void){ ShowStatus("Finished Reading " CL_GREEN "GeoIP" CL_RESET " Database.\n"); } /* [Dekamaster/Nightroad] */ -/* WHY NOT A DBMAP: There are millions of entries in GeoIP and it has its own algorithm to go quickly through them, a DBMap wouldn't be efficient */ +/* There are millions of entries in GeoIP and it has its own algorithm to go quickly through them */ const char* geoip_getcountry(uint32 ipnum){ int depth; unsigned int x; @@ -987,7 +995,6 @@ int inter_init_sql(const char *file) Sql_ShowDebug(sql_handle); } - wis_db = idb_alloc(DB_OPT_RELEASE_DATA); interServerDb.load(); inter_guild_sql_init(); inter_storage_sql_init(); @@ -1007,7 +1014,7 @@ int inter_init_sql(const char *file) // finalize void inter_final(void) { - wis_db->destroy(wis_db, NULL); + wis_db.clear(); inter_guild_sql_final(); inter_storage_sql_final(); @@ -1073,8 +1080,7 @@ int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short } // Wis sending -int mapif_wis_message(struct WisData *wd) -{ +int mapif_wis_message( std::shared_ptr wd ){ unsigned char buf[2048]; int headersize = 12 + 2 * NAME_LENGTH; @@ -1116,40 +1122,19 @@ int mapif_disconnectplayer(int fd, uint32 account_id, uint32 char_id, int reason //-------------------------------------------------------- -/** - * Existence check of WISP data - * @see DBApply - */ -int check_ttl_wisdata_sub(DBKey key, DBData *data, va_list ap) -{ - t_tick tick; - struct WisData *wd = (struct WisData *)db_data2ptr(data); - tick = va_arg(ap, t_tick); - - if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX) - wis_dellist[wis_delnum++] = wd->id; - - return 0; -} - -int check_ttl_wisdata(void) -{ +void check_ttl_wisdata(){ t_tick tick = gettick(); - int i; - do { - wis_delnum = 0; - wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick); - for(i = 0; i < wis_delnum; i++) { - struct WisData *wd = (struct WisData*)idb_get(wis_db, wis_dellist[i]); - ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst); - // removed. not send information after a timeout. Just no answer for the player - //mapif_wis_reply(wd->fd, wd->src, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - idb_remove(wis_db, wd->id); + for( auto it = wis_db.begin(); it != wis_db.end(); ){ + std::shared_ptr wd = it->second; + + if( DIFF_TICK( tick, wd->tick ) > WISDATA_TTL ){ + ShowWarning( "inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst ); + it = wis_db.erase( it ); + }else{ + it++; } - } while(wis_delnum >= WISDELLIST_MAX); - - return 0; + } } //-------------------------------------------------------- @@ -1193,7 +1178,6 @@ int mapif_wis_reply( int mapserver_fd, char* target, uint8 flag ){ // Wisp/page request to send int mapif_parse_WisRequest(int fd) { - struct WisData* wd; char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1];// escaped name char* data; @@ -1203,7 +1187,7 @@ int mapif_parse_WisRequest(int fd) if ( fd <= 0 ) {return 0;} // check if we have a valid fd - if (RFIFOW(fd,2)-headersize >= sizeof(wd->msg)) { + if( RFIFOW( fd, 2 ) - headersize >= WHISPER_MESSAGE_SIZE ){ ShowWarning("inter: Wis message size too long.\n"); return 0; } else if (RFIFOW(fd,2)-headersize <= 0) { // normaly, impossible, but who knows... @@ -1237,11 +1221,11 @@ int mapif_parse_WisRequest(int fd) { static int wisid = 0; - CREATE(wd, struct WisData, 1); - // Whether the failure of previous wisp/page transmission (timeout) check_ttl_wisdata(); + std::shared_ptr wd = std::make_shared(); + wd->id = ++wisid; wd->fd = fd; wd->len= RFIFOW(fd,2)-headersize; @@ -1250,8 +1234,10 @@ int mapif_parse_WisRequest(int fd) safestrncpy(wd->dst, RFIFOCP(fd,8+NAME_LENGTH), NAME_LENGTH); safestrncpy(wd->msg, RFIFOCP(fd,8+2*NAME_LENGTH), wd->len); wd->tick = gettick(); - idb_put(wis_db, wd->id, wd); - mapif_wis_message(wd); + + wis_db[wd->id] = wd; + + mapif_wis_message( wd ); } } @@ -1263,19 +1249,20 @@ int mapif_parse_WisRequest(int fd) // Wisp/page transmission result int mapif_parse_WisReply(int fd) { - int id; + int32 id; uint8 flag; - struct WisData *wd; id = RFIFOL(fd,2); flag = RFIFOB(fd,6); - wd = (struct WisData*)idb_get(wis_db, id); - if (wd == NULL) + std::shared_ptr wd = util::umap_find( wis_db, id ); + + if( wd == nullptr ){ return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server + } if ((--wd->count) <= 0 || flag != 1) { mapif_wis_reply(wd->fd, wd->src, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - idb_remove(wis_db, id); + wis_db.erase( id ); } return 0;