From 2110a6ead859d91f4c86db947c16f35bf973c1f9 Mon Sep 17 00:00:00 2001
From: Lemongrass3110 <lemongrass@kstp.at>
Date: Thu, 1 Jul 2021 09:09:45 +0200
Subject: [PATCH] Turned storage_db into an unordered_map (#6038)

Fixed some inconsistent behaviors between normal and premium storages.

Thanks to @limitro
---
 src/map/intif.cpp   | 30 ++++++++------
 src/map/storage.cpp | 96 +++++++++++----------------------------------
 src/map/storage.hpp |  6 +--
 3 files changed, 43 insertions(+), 89 deletions(-)

diff --git a/src/map/intif.cpp b/src/map/intif.cpp
index fcb9ca06d1..6d2135dac7 100644
--- a/src/map/intif.cpp
+++ b/src/map/intif.cpp
@@ -3540,9 +3540,10 @@ static void intif_parse_StorageSaved(int fd)
 				//ShowInfo("Inventory has been saved (AID: %d).\n", RFIFOL(fd, 2));
 				break;
 			case TABLE_STORAGE: //storage
-				//ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2));
-				if (RFIFOB(fd, 8))
-					storage_premiumStorage_saved(map_id2sd(RFIFOL(fd, 2)));
+				//if (RFIFOB(fd, 8))
+				//	ShowInfo("Storage %d has been saved (AID: %d).\n", RFIFOL(fd, 2), RFIFOB(fd, 8) );
+				//else
+				//	ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2));
 				break;
 			case TABLE_CART: // cart
 				//ShowInfo("Cart has been saved (AID: %d).\n", RFIFOL(fd, 2));
@@ -3566,21 +3567,24 @@ static void intif_parse_StorageSaved(int fd)
  * Receive storage information
  **/
 void intif_parse_StorageInfo_recv(int fd) {
-	int i, size = sizeof(struct s_storage_table), count = (RFIFOW(fd, 2) - 4) / size;
+	int size = sizeof(struct s_storage_table), count = (RFIFOW(fd, 2) - 4) / size;
 
-	storage_count = 0;
-	if (storage_db)
-		aFree(storage_db);
-	storage_db = NULL;
+	storage_db.clear();
 
-	for (i = 0; i < count; i++) {
-		RECREATE(storage_db, struct s_storage_table, storage_count+1);
-		memcpy(&storage_db[storage_count], RFIFOP(fd, 4 + size * i), size);
-		storage_count++;
+	for( int i = 0; i < count; i++ ){
+		struct s_storage_table* ptr = (struct s_storage_table*)RFIFOP( fd, 4 + size * i );
+		std::shared_ptr<struct s_storage_table> storage = std::make_shared<struct s_storage_table>();
+
+		safestrncpy( storage->name, ptr->name, sizeof( storage->name ) );
+		safestrncpy( storage->table, ptr->table, sizeof( storage->table ) );
+		storage->max_num = ptr->max_num;
+		storage->id = ptr->id;
+
+		storage_db[storage->id] = storage;
 	}
 
 	if (battle_config.etc_log)
-		ShowInfo("Received '" CL_WHITE "%d" CL_RESET "' storage info from inter-server.\n", storage_count);
+		ShowInfo("Received '" CL_WHITE PRIdPTR CL_RESET "' storage info from inter-server.\n", storage_db.size());
 }
 
 /**
diff --git a/src/map/storage.cpp b/src/map/storage.cpp
index 1322221964..7ad997efec 100644
--- a/src/map/storage.cpp
+++ b/src/map/storage.cpp
@@ -9,7 +9,6 @@
 #include <string.h>
 
 #include "../common/cbasetypes.hpp"
-#include "../common/malloc.hpp"
 #include "../common/nullpo.hpp"
 #include "../common/showmsg.hpp"
 #include "../common/utilities.hpp"
@@ -28,26 +27,23 @@
 
 using namespace rathena;
 
+std::unordered_map<uint16, std::shared_ptr<struct s_storage_table>> storage_db;
+
 ///Databases of guild_storage : int guild_id -> struct guild_storage
 std::map<int, struct s_storage> guild_storage_db;
 
-struct s_storage_table *storage_db;
-int storage_count;
-
 /**
  * Get storage name
  * @param id Storage ID
  * @return Storage name or "Storage" if not found
- * @author [Cydh]
  **/
 const char *storage_getName(uint8 id) {
-	if (storage_db && storage_count) {
-		int i;
-		for (i = 0; i < storage_count; i++) {
-			if (&storage_db[i] && storage_db[i].id == id && storage_db[i].name[0])
-				return storage_db[i].name;
-		}
+	std::shared_ptr<struct s_storage_table> storage = util::umap_find( storage_db, (uint16)id );
+
+	if( storage ){
+		return storage->name;
 	}
+
 	return "Storage";
 }
 
@@ -57,14 +53,7 @@ const char *storage_getName(uint8 id) {
  * @return True:Valid, False:Invalid
  **/
 bool storage_exists(uint8 id) {
-	if (storage_db && storage_count) {
-		int i;
-		for (i = 0; i < storage_count; i++) {
-			if (storage_db[i].id == id)
-				return true;
-		}
-	}
-	return false;
+	return util::umap_find( storage_db, (uint16)id ) != nullptr;
 }
 
 /**
@@ -109,8 +98,6 @@ void storage_sortitem(struct item* items, unsigned int size)
  */
 void do_init_storage(void)
 {
-	storage_db = NULL;
-	storage_count = 0;
 }
 
 /**
@@ -121,10 +108,7 @@ void do_init_storage(void)
 void do_final_storage(void)
 {
 	guild_storage_db.clear();
-	if (storage_db)
-		aFree(storage_db);
-	storage_db = NULL;
-	storage_count = 0;
+	storage_db.clear();
 }
 
 /**
@@ -132,7 +116,7 @@ void do_final_storage(void)
  * @author [Skotlex]
  */
 void do_reconnect_storage(void){
-	for( auto entry : guild_storage_db ){
+	for( const auto& entry : guild_storage_db ){
 		struct s_storage stor = entry.second;
 
 		// Save closed storages.
@@ -479,23 +463,6 @@ void storage_storagesave(struct map_session_data *sd)
 	intif_storage_save(sd, &sd->storage);
 }
 
-/**
- * Ack of storage has been saved
- * @param sd: Player who has the storage
- */
-void storage_storagesaved(struct map_session_data *sd)
-{
-	if (!sd)
-		return;
-
-	sd->storage.dirty = false;
-
-	if (sd->state.storage_flag == 1) {
-		sd->state.storage_flag = 0;
-		clif_storageclose(sd);
-	}
-}
-
 /**
  * Make player close his storage
  * @param sd: Player who has the storage
@@ -510,12 +477,12 @@ void storage_storageclose(struct map_session_data *sd)
 			chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART);
 		else
 			storage_storagesave(sd);
-		if (sd->state.storage_flag == 1) {
-			sd->state.storage_flag = 0;
-			clif_storageclose(sd);
-		}
-	} else
-		storage_storagesaved(sd);
+	}
+	
+	if( sd->state.storage_flag == 1 ){
+		sd->state.storage_flag = 0;
+		clif_storageclose( sd );
+	}
 }
 
 /**
@@ -1200,22 +1167,6 @@ void storage_premiumStorage_save(struct map_session_data *sd) {
 	intif_storage_save(sd, &sd->premiumStorage);
 }
 
-/**
- * Ack of secondary premium has been saved
- * @param sd Player who has the storage
- **/
-void storage_premiumStorage_saved(struct map_session_data *sd) {
-	if (!sd)
-		return;
-
-	sd->premiumStorage.dirty = 0;
-
-	if (sd->state.storage_flag == 3) {
-		sd->state.storage_flag = 0;
-		clif_storageclose(sd);
-	}
-}
-
 /**
  * Request to close premium storage
  * @param sd Player who has the storage
@@ -1228,18 +1179,17 @@ void storage_premiumStorage_close(struct map_session_data *sd) {
 		if (save_settings&CHARSAVE_STORAGE)
 			chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART);
 		else
-			storage_premiumStorage_save(sd);
-		if (sd->state.storage_flag == 3) {
-			sd->state.storage_flag = 0;
-			clif_storageclose(sd);
-		}
+			storage_premiumStorage_save(sd);	
+	}
+
+	if( sd->state.storage_flag == 3 ){
+		sd->state.storage_flag = 0;
+		clif_storageclose( sd );
 	}
-	else 
-		storage_premiumStorage_saved(sd);
 }
 
 /**
- * Force save then close the premium storage
+ * Force save the premium storage
  * @param sd Player who has the storage
  * @author [Cydh]
  **/
diff --git a/src/map/storage.hpp b/src/map/storage.hpp
index f762ea6fb0..a24ec8b7b5 100644
--- a/src/map/storage.hpp
+++ b/src/map/storage.hpp
@@ -4,6 +4,8 @@
 #ifndef STORAGE_HPP
 #define STORAGE_HPP
 
+#include <memory>
+#include <unordered_map>
 #include <vector>
 
 #include "../common/cbasetypes.hpp"
@@ -13,8 +15,7 @@ struct s_storage;
 struct item;
 struct map_session_data;
 
-extern struct s_storage_table *storage_db;
-extern int storage_count;
+extern std::unordered_map<uint16, std::shared_ptr<struct s_storage_table>> storage_db;
 
 enum e_storage_add {
 	STORAGE_ADD_OK,
@@ -86,7 +87,6 @@ void storage_guild_storagesaved(int guild_id); //Ack from char server that guild
 void storage_premiumStorage_open(struct map_session_data *sd);
 bool storage_premiumStorage_load(struct map_session_data *sd, uint8 num, uint8 mode);
 void storage_premiumStorage_save(struct map_session_data *sd);
-void storage_premiumStorage_saved(struct map_session_data *sd);
 void storage_premiumStorage_close(struct map_session_data *sd);
 void storage_premiumStorage_quit(struct map_session_data *sd);