瀏覽代碼

Replaced DBMap usage in char-server (#7514)

Co-authored-by: Aleos <aleos89@users.noreply.github.com>
Lemongrass3110 2 年之前
父節點
當前提交
4fb6740ebf
共有 11 個文件被更改,包括 631 次插入649 次删除
  1. 110 110
      src/char/char.cpp
  2. 11 7
      src/char/char.hpp
  3. 23 18
      src/char/char_clif.cpp
  4. 28 32
      src/char/char_logif.cpp
  5. 81 64
      src/char/char_mapif.cpp
  6. 50 47
      src/char/int_auction.cpp
  7. 38 52
      src/char/int_clan.cpp
  8. 150 168
      src/char/int_guild.cpp
  9. 9 4
      src/char/int_mail.cpp
  10. 91 94
      src/char/int_party.cpp
  11. 40 53
      src/char/inter.cpp

+ 110 - 110
src/char/char.cpp

@@ -4,6 +4,9 @@
 #pragma warning(disable:4800)
 #include "char.hpp"
 
+#include <memory>
+#include <unordered_map>
+
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -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_; }
-
-/**
- * @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);
+// uint32 account_id -> struct auth_node*
+std::unordered_map<uint32, std::shared_ptr<struct auth_node>> auth_db;
+// uint32 account_id -> struct online_char_data*
+std::unordered_map<uint32, std::shared_ptr<struct online_char_data>> online_char_db;
+// uint32 char_id -> struct mmo_charstatus*
+std::unordered_map<uint32, std::shared_ptr<struct mmo_charstatus>> char_db;
+std::unordered_map<uint32, std::shared_ptr<struct auth_node>>& char_get_authdb() { return auth_db; }
+std::unordered_map<uint32, std::shared_ptr<struct online_char_data>>& char_get_onlinedb() { return online_char_db; }
+std::unordered_map<uint32, std::shared_ptr<struct mmo_charstatus>>& char_get_chardb() { return char_db; }
+
+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<struct online_char_data> 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<struct online_char_data>( 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<struct online_char_data> 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<struct online_char_data>( 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<struct mmo_charstatus> 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<struct mmo_charstatus> 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<struct online_char_data> 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<struct online_char_data> 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<struct online_char_data> 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<struct mmo_charstatus> cp = util::umap_find( char_get_chardb(), char_id );
+
+	if( cp == nullptr ){
+		cp = std::make_shared<struct mmo_charstatus>();
+		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<struct mmo_charstatus> cp = util::umap_find( char_get_chardb(), char_id );
+
+	if( cp == nullptr ){
+		cp = std::make_shared<struct mmo_charstatus>();
+		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<struct online_char_data> 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<struct online_char_data> character = util::umap_find( char_get_onlinedb(), static_cast<uint32>( 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<struct online_char_data> 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.
 

+ 11 - 7
src/char/char.hpp

@@ -4,6 +4,8 @@
 #ifndef CHAR_HPP
 #define CHAR_HPP
 
+#include <memory>
+#include <unordered_map>
 #include <vector>
 
 #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<uint32, std::shared_ptr<struct auth_node>>& 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<uint32, std::shared_ptr<struct online_char_data>>& 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<uint32, std::shared_ptr<struct mmo_charstatus>>& 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<struct online_char_data> 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);

+ 23 - 18
src/char/char_clif.cpp

@@ -3,6 +3,9 @@
 
 #include "char_clif.hpp"
 
+#include <memory>
+#include <unordered_map>
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -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<struct auth_node> 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<struct mmo_charstatus> 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<struct mmo_charstatus> 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<struct auth_node> node = std::make_shared<struct auth_node>();
+
 		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<struct online_char_data> 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;

+ 28 - 32
src/char/char_logif.cpp

@@ -3,6 +3,8 @@
 
 #include "char_logif.hpp"
 
+#include <memory>
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -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<struct online_char_data> 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<struct online_char_data> 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<struct auth_node> 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<struct online_char_data> 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;
 }

+ 81 - 64
src/char/char_mapif.cpp

@@ -3,6 +3,8 @@
 
 #include "char_mapif.hpp"
 
+#include <memory>
+
 #include <stdlib.h>
 #include <string.h> //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<struct online_char_data> 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<struct online_char_data>( 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<struct online_char_data> 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<struct auth_node> node = std::make_shared<struct auth_node>();
+
 			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<struct online_char_data> 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<struct mmo_charstatus> 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<struct auth_node> node = std::make_shared<struct auth_node>();
+
 			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<struct online_char_data> data = util::umap_find( char_get_onlinedb(), aid );
+
+			if( data == nullptr ){
+				data = std::make_shared<struct online_char_data>( 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<struct auth_node> node = util::umap_find( char_get_authdb(), account_id );
+		std::shared_ptr<struct mmo_charstatus> 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);
 }

+ 50 - 47
src/char/int_auction.cpp

@@ -3,6 +3,9 @@
 
 #include "int_auction.hpp"
 
+#include <memory>
+#include <unordered_map>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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;
+
+// int auction_id -> struct auction_data*
+static std::unordered_map<uint32, std::shared_ptr<struct auction_data>> auction_db;
 
-void auction_delete(struct auction_data *auction);
+void auction_delete( std::shared_ptr<struct auction_data> 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<struct auction_data> 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<struct auction_data> 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<struct auction_data> 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<struct auction_data> auction = util::umap_find( auction_db, static_cast<uint32>( 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<struct auction_data> auction ){
 	unsigned int auction_id = auction->auction_id;
 
 	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", 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<struct auction_data> auction = std::make_shared<struct auction_data>();
+
 		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<auction_data *>(dbi_first(iter)); dbi_exists(iter); auction = static_cast<auction_data *>(dbi_next(iter)) )
-	{
+	for( const auto& pair : auction_db ){
+		std::shared_ptr<struct auction_data> 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<struct auction_data*>( RFIFOP( fd, 4 ) );
+
+	if( auction_count( auction->seller_id, false ) < 5 ){
+		std::shared_ptr<struct auction_data> auction2 = std::make_shared<struct auction_data>();
 
-	mapif_Auction_register(fd, &auction);
+		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<struct auction_data> 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<struct auction_data> 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<struct auction_data> 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;
 }

+ 38 - 52
src/char/int_clan.cpp

@@ -3,6 +3,10 @@
 
 #include "int_clan.hpp"
 
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
 #include <stdlib.h>
 #include <string.h> //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<int32, std::shared_ptr<struct clan>> 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<struct clan> 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<struct clan> 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<struct clan>();
 
 	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<struct clan> 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<struct clan> 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<struct clan> clan = util::umap_find( clan_db, static_cast<int32>( 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<struct clan> clan = util::umap_find( clan_db, static_cast<int32>( 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<int32> clan_ids;
 
-	if( amount > 0 ){
-		int i;
-
-		CREATE( clan_ids, int, amount );
-		i = 0;
-
-		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;
+	while( SQL_SUCCESS == Sql_NextRow( sql_handle ) ){
+		char* data;
+		Sql_GetData( sql_handle,  0, &data, nullptr );
+		clan_ids.push_back( atoi( data ) );
+	}
 
-		for( i = 0; i < amount; i++ ){
-			inter_clan_fromsql( clan_ids[i] );
-		}
+	Sql_FreeResult( sql_handle );
 
-		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();
 }

+ 150 - 168
src/char/int_guild.cpp

@@ -3,6 +3,9 @@
 
 #include "int_guild.hpp"
 
+#include <memory>
+#include <unordered_map>
+
 #include <stdlib.h>
 #define __STDC_WANT_LIB_EXT1__ 1
 #include <string.h>
@@ -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<int32, std::shared_ptr<struct guild>> guild_db;
+static std::unordered_map<int32, std::shared_ptr<struct guild_castle>> 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<struct guild> g );
+int guild_calcinfo( std::shared_ptr<struct guild> 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<struct guild> g );
+int inter_guild_tosql( std::shared_ptr<struct guild> g, int flag );
+int guild_checkskill( std::shared_ptr<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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;
+	}
+
+	std::shared_ptr<struct guild> g = util::umap_find( guild_db, guild_id );
 
-	g = (struct guild*)idb_get(guild_db_, guild_id);
-	if( g )
+	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<struct guild>();
 
 	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<struct guild> 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<struct guild_castle> 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<struct guild_castle> 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<struct guild_castle> 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<struct guild_castle>();
+
 	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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild_castle> 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<struct guild> g = std::make_shared<struct guild>();
+
+	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<struct guild> 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<struct guild> 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;i<g->max_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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> g = inter_guild_fromsql( guild_id );
+
+	if( g == nullptr ){
 		return 0;
+	}
 
 	// Search the member
 	for(i=0;i<g->max_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<struct guild> 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<struct guild> 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<struct guild> 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<max )
 	{
@@ -1725,8 +1705,7 @@ int mapif_parse_GuildSkillUp(int fd,int guild_id,uint16 skill_id,uint32 account_
 }
 
 //Manual deletion of an alliance when partnering guild does not exists. [Skotlex]
-int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, uint32 account_id1, uint32 account_id2, int flag)
-{
+int mapif_parse_GuildDeleteAlliance( std::shared_ptr<struct guild> 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<struct guild> 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<struct guild> 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<struct guild> 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<struct guild_castle> 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<struct guild> 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<struct guild> 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<struct guild> g = inter_guild_fromsql( guild_id );
 
 	if (g == nullptr)
 		return 0;

+ 9 - 4
src/char/int_mail.cpp

@@ -3,6 +3,8 @@
 
 #include "int_mail.hpp"
 
+#include <memory>
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -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<struct online_char_data> 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<struct online_char_data> 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

+ 91 - 94
src/char/int_party.cpp

@@ -3,6 +3,9 @@
 
 #include "int_party.hpp"
 
+#include <memory>
+#include <unordered_map>
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -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<int32, std::shared_ptr<struct party_data>> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data>();
+
 	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<struct party_data> search_partyname( char* str ){
 	char esc_name[NAME_LENGTH*2+1];
 	char* data;
-	struct party_data* p = NULL;
+	std::shared_ptr<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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;i<MAX_PARTY && !p->party.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<struct party_data> 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<struct party_data>();
 
 	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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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<struct party_data> 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;
 	}

+ 40 - 53
src/char/inter.cpp

@@ -3,11 +3,14 @@
 
 #include "inter.hpp"
 
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
 #include <stdlib.h>
 #include <string.h>
 #include <string>
 #include <sys/stat.h> // for stat/lstat/fstat - [Dekamaster/Ultimate GM Tool]
-#include <vector>
 
 #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<int32, std::shared_ptr<struct WisData>> 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<struct WisData> 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);
-		}
-	} while(wis_delnum >= WISDELLIST_MAX);
+	for( auto it = wis_db.begin(); it != wis_db.end(); ){
+		std::shared_ptr<struct WisData> wd = it->second;
 
-	return 0;
+		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++;
+		}
+	}
 }
 
 //--------------------------------------------------------
@@ -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<struct WisData> wd = std::make_shared<struct WisData>();
+
 			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<struct WisData> 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;