diff --git a/Hercules.xcodeproj/project.pbxproj b/Hercules.xcodeproj/project.pbxproj index fc7aa8dc4d4..3d1424a6ff3 100644 --- a/Hercules.xcodeproj/project.pbxproj +++ b/Hercules.xcodeproj/project.pbxproj @@ -1075,7 +1075,7 @@ A56CC652185642B4009EB79C /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0830; ORGANIZATIONNAME = herc.ws; }; buildConfigurationList = A56CC655185642B4009EB79C /* Build configuration list for PBXProject "Hercules" */; @@ -1506,6 +1506,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)"; COPY_PHASE_STRIP = NO; @@ -1597,6 +1598,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)"; COPY_PHASE_STRIP = YES; diff --git a/Hercules.xcodeproj/xcshareddata/xcschemes/HPMHooking_char.xcscheme b/Hercules.xcodeproj/xcshareddata/xcschemes/HPMHooking_char.xcscheme index 5aa51934972..8bfd2fe6d11 100644 --- a/Hercules.xcodeproj/xcshareddata/xcschemes/HPMHooking_char.xcscheme +++ b/Hercules.xcodeproj/xcshareddata/xcschemes/HPMHooking_char.xcscheme @@ -1,6 +1,6 @@ . +//============================================================================== +//= Storage Configuration +//============================================================================== +//= @Format Notes: +//= - There can be an unlimited amount of storages and limits. +//= - All setting names are case-sensitive and must be keyed accurately. +//= - It is not recommended to set the maximum storage capacity over 1000 items. + +storage_conf: ( +/****************************************************************************** +********************************* Entry structure ***************************** +******************************************************************************* +{ + Id: (int) (required|unique) Unique Identifier + Name: (string) (required) Name of the storage sent to the client. + Capacity: (int) (required) Maximum capacity of the storage. +} +*******************************************************************************/ +{ + // DO NOT EDIT THIS ENTRY! + // This is the default (official) storage for an account. + Id: 1 + Name: "Storage" + Capacity: 600 +}, +) diff --git a/conf/messages.conf b/conf/messages.conf index 78f0c6aa9d0..b5e1a492a62 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -52,7 +52,7 @@ 24: Job level raised. 25: Job level lowered. 26: [%d] seconds left until you can use -27: Storage has been not loaded yet. +27: Storage '%s' has not been loaded yet. 28: No player found. 29: 1 player found. 30: %d players found. @@ -74,7 +74,10 @@ 46: %s recalled! 47: Base level can't go any higher. 48: Any work in progress (NPC dialog, manufacturing ...) quit and try again. -//49-52 FREE +49: Please specify a storage name. (usage: @storeall ). +50: Please specify a storage name. (usage: @clearstorage ). +51: Invalid storage name or ID +52: Please specify a storage name. (usage: @storage ). 53: '%s' stats: 54: No player found in map '%s'. 55: 1 player found in map '%s'. @@ -684,7 +687,7 @@ 918: Please enter a speed value (usage: @speed <%d-%d>). // @storage -919: Storage opened. +919: Storage #%d opened. // @guildstorage 920: Guild storage opened. diff --git a/db/constants.conf b/db/constants.conf index eda877671f0..05598be6fdd 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -3872,4 +3872,13 @@ constants_db: { UDT_STATADD: 54 UDT_ROBE: 55 UDT_BODY2: 56 + + comment__: "Storage Types" + STORAGE_TYPE_MAIN: 1 + + comment__: "Storage Access Types" + STORAGE_ACCESS_VIEW: 0x0 + STORAGE_ACCESS_GET: 0x1 + STORAGE_ACCESS_PUT: 0x2 + STORAGE_ACCESS_ALL: 0x3 } diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 46580406135..d5665c94f06 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5625,7 +5625,9 @@ has no gear, script will be terminated with an error. //===================================== --------------------------------------- -*openstorage() +*openstorage({, }) + +Default Storage Access Mode: STORAGE_ACCESS_ALL This will open character's Kafra storage window on the client connected to the invoking character. It can be used from any kind of NPC or item @@ -5637,9 +5639,15 @@ storage window, to avoid any disruption when both windows overlap. mes("I will now open your stash for you"); close2(); - openstorage(); + openstorage(1); end; +Storage Modes: + STORAGE_ACCESS_VIEW // View storage only + STORAGE_ACCESS_GET // Allow getting items from storage. + STORAGE_ACCESS_PUT // Allow putting items to storage. + STORAGE_ACCESS_ALL // Allow all actions. + --------------------------------------- *openmail() diff --git a/npc/custom/etc/quest_warper.txt b/npc/custom/etc/quest_warper.txt index 35b863e9d8c..e4db7cedf39 100644 --- a/npc/custom/etc/quest_warper.txt +++ b/npc/custom/etc/quest_warper.txt @@ -474,7 +474,7 @@ L_Storage: } mes "Close this window and I will open your storage."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; L_StorageJBlow: diff --git a/npc/kafras/functions_kafras.txt b/npc/kafras/functions_kafras.txt index 90334cc6e74..2781b23c91b 100644 --- a/npc/kafras/functions_kafras.txt +++ b/npc/kafras/functions_kafras.txt @@ -293,7 +293,7 @@ function script F_KafStor { } callfunc("F_CheckKafCode"); //check your storage password, if set close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); cutin "", 255; end; } diff --git a/npc/kafras/kafras.txt b/npc/kafras/kafras.txt index 29b1b02da16..d0d5aaf07ec 100644 --- a/npc/kafras/kafras.txt +++ b/npc/kafras/kafras.txt @@ -92,7 +92,7 @@ aldeba_in,96,181,4 script Kafra Service 4_F_KAFRA5,{ mes "Thank you for your patronage."; callfunc("F_CheckKafCode"); //check your storage password, if set close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); break; case 3: mes "[Kafra Leilah]"; diff --git a/npc/other/CashShop_Functions.txt b/npc/other/CashShop_Functions.txt index 92fe841e17c..d60af59efdc 100644 --- a/npc/other/CashShop_Functions.txt +++ b/npc/other/CashShop_Functions.txt @@ -46,7 +46,7 @@ function script F_CashStore { mes "Welcome to the Kafra Corporation."; mes "Here, let me open your Storage for you."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); cutin "",255; return; } diff --git a/npc/quests/quests_13_1.txt b/npc/quests/quests_13_1.txt index 17cacaff66d..0011e583889 100644 --- a/npc/quests/quests_13_1.txt +++ b/npc/quests/quests_13_1.txt @@ -7678,7 +7678,7 @@ function Catwarp; mes "Your storage will"; mes "be opened shortly."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } else { @@ -7725,7 +7725,7 @@ function Catwarp; mes "Your storage will"; mes "be opened shortly."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } else { @@ -7847,7 +7847,7 @@ function Catwarp; mes "Your storage will"; mes "be opened shortly."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } else { diff --git a/npc/quests/quests_13_2.txt b/npc/quests/quests_13_2.txt index e64e1c84a86..a60f31b10f6 100644 --- a/npc/quests/quests_13_2.txt +++ b/npc/quests/quests_13_2.txt @@ -109,7 +109,7 @@ spl_fild02,25,211,4 script Cat Hand Agent#spl 4_M_BOSSCAT,{ mes "Thank you."; mes "Your storage will be opened shortly."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } else { @@ -156,7 +156,7 @@ spl_fild02,25,211,4 script Cat Hand Agent#spl 4_M_BOSSCAT,{ mes "Thank you."; mes "Your storage will be opened shortly."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } else { @@ -277,7 +277,7 @@ spl_fild02,25,211,4 script Cat Hand Agent#spl 4_M_BOSSCAT,{ mes "Thank you."; mes "Your storage will be opened shortly."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } else { diff --git a/npc/re/cities/mora.txt b/npc/re/cities/mora.txt index a58ee44634c..314e8846551 100644 --- a/npc/re/cities/mora.txt +++ b/npc/re/cities/mora.txt @@ -1192,7 +1192,7 @@ mora,48,128,0 script Drawer#mora_warehouse HIDDEN_NPC,{ close; } Zeny -= 100; - openstorage; + openstorage(STORAGE_TYPE_MAIN); close; case 2: mes "- You gave up using the warehouse. -"; diff --git a/npc/re/jobs/novice/academy.txt b/npc/re/jobs/novice/academy.txt index 1b657673723..7e8db3232b5 100644 --- a/npc/re/jobs/novice/academy.txt +++ b/npc/re/jobs/novice/academy.txt @@ -5393,7 +5393,7 @@ iz_ac01,95,46,5 script Kafra Guide Trainer#ac 4_F_KAFRA1,{ mes("Thanks for using~!"); close2(); cutin("", 255); - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } else { mes("[Kafra Guide Trainer]"); diff --git a/npc/re/other/dimensional_gap.txt b/npc/re/other/dimensional_gap.txt index b303f14b727..cf66afaa183 100644 --- a/npc/re/other/dimensional_gap.txt +++ b/npc/re/other/dimensional_gap.txt @@ -137,7 +137,7 @@ dali,112,95,4 script Logistics Manager 4_M_MERCAT2,{ mes("You need at least 200 zeny to use the Storage."); } else { Zeny -= 200; - openstorage(); + openstorage(STORAGE_TYPE_MAIN); } close(); } diff --git a/npc/re/quests/eden/eden_service.txt b/npc/re/quests/eden/eden_service.txt index ce6efaa67a6..e8bbbe95402 100644 --- a/npc/re/quests/eden/eden_service.txt +++ b/npc/re/quests/eden/eden_service.txt @@ -65,7 +65,7 @@ } Zeny -= 500; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } mes "I don't have enough zeny."; diff --git a/npc/re/quests/quests_dicastes.txt b/npc/re/quests/quests_dicastes.txt index 817b4780dff..3d60156f8c1 100644 --- a/npc/re/quests/quests_dicastes.txt +++ b/npc/re/quests/quests_dicastes.txt @@ -445,7 +445,7 @@ dic_in01,254,119,0 script Item Storage#01 CLEAR_NPC,{ } Zeny -= 500; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } diff --git a/npc/re/quests/quests_malangdo.txt b/npc/re/quests/quests_malangdo.txt index 786aeccb1dc..8ad5d983cdd 100644 --- a/npc/re/quests/quests_malangdo.txt +++ b/npc/re/quests/quests_malangdo.txt @@ -370,7 +370,7 @@ malangdo,184,139,4 script Storekeeper#mal 4_CAT_ADV2,{ mes "[Storekeeper]"; mes "Thank you."; close2; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; } diff --git a/npc/woe-fe/agit_main.txt b/npc/woe-fe/agit_main.txt index 5ac5b8e9af5..2d97ddf14ec 100644 --- a/npc/woe-fe/agit_main.txt +++ b/npc/woe-fe/agit_main.txt @@ -366,7 +366,7 @@ OnRecvCastle: mes "the Kafra Service."; close2; cutin "",255; - openstorage; + openstorage(STORAGE_TYPE_MAIN); end; case 2: mes "[Kafra Employee]"; diff --git a/npc/woe-se/agit_main_se.txt b/npc/woe-se/agit_main_se.txt index 6fc3193774e..10c279fde6a 100644 --- a/npc/woe-se/agit_main_se.txt +++ b/npc/woe-se/agit_main_se.txt @@ -869,7 +869,7 @@ OnInit: mes "have at least Novice Skill"; mes "Lv.6 to use the Storage."; } - else openstorage; + else openstorage(STORAGE_TYPE_MAIN); break; case 2: mes "[Kafra Employee]"; diff --git a/sql-files/main.sql b/sql-files/main.sql index feda8a4cdbd..e9dabb3b4d3 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -884,6 +884,7 @@ INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1477434595); -- 2016-10-2 INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1488454834); -- 2017-03-02--11-40.sql INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1488744559); -- 2017-03-05--08-09.sql INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1489588190); -- 2017-03-15--14-29.sql +INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1496487154); -- 2017-06-03--10-52.sql INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1509835214); -- 2017-11-04--10-39.sql -- -- Table structure for table `storage` @@ -892,6 +893,7 @@ INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1509835214); -- 2017-11-0 CREATE TABLE IF NOT EXISTS `storage` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `account_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `storage_id` INT(11) UNSIGNED NOT NULL DEFAULT '1', `nameid` INT(11) UNSIGNED NOT NULL DEFAULT '0', `amount` SMALLINT(11) UNSIGNED NOT NULL DEFAULT '0', `equip` INT(11) UNSIGNED NOT NULL DEFAULT '0', diff --git a/sql-files/upgrades/2017-06-03--10-52.sql b/sql-files/upgrades/2017-06-03--10-52.sql new file mode 100644 index 00000000000..8190eba693f --- /dev/null +++ b/sql-files/upgrades/2017-06-03--10-52.sql @@ -0,0 +1,23 @@ +#1496487154 + +-- This file is part of Hercules. +-- http://herc.ws - http://github.com/HerculesWS/Hercules +-- +-- Copyright (C) 2013-2015 Hercules Dev Team +-- +-- Hercules is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +ALTER TABLE `storage` ADD `storage_id` INT(11) UNSIGNED NOT NULL DEFAULT '1' AFTER `account_id`; + +INSERT INTO `sql_updates` (`timestamp`) VALUES (1496487154); diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt index 11cb36a7920..9d7fa69a3d7 100644 --- a/sql-files/upgrades/index.txt +++ b/sql-files/upgrades/index.txt @@ -40,4 +40,5 @@ 2017-03-02--11-40.sql 2017-03-05--08-09.sql 2017-03-15--14-29.sql +2017-06-03--10-52.sql 2017-11-04--10-39.sql diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 70cdc5f1984..50feb83634e 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -41,24 +41,30 @@ struct inter_storage_interface inter_storage_s; struct inter_storage_interface *inter_storage; /// Save storage data to sql -int inter_storage_tosql(int account_id, const struct storage_data *p) +int inter_storage_tosql(int account_id, int storage_id, const struct storage_data *p) { int i = 0, j = 0; - bool matched_p[MAX_STORAGE] = { false }; - int delete[MAX_STORAGE] = { 0 }; + bool *matched_p = NULL; + int *delete = NULL; int total_deletes = 0, total_updates = 0, total_inserts = 0; - int total_changes = 0; + int cp_size = 0; struct storage_data cp = { 0 }; StringBuf buf; nullpo_ret(p); VECTOR_INIT(cp.item); - inter_storage->fromsql(account_id, &cp); + + cp_size = inter_storage->fromsql(account_id, storage_id, &cp, 0); + + matched_p = aCalloc(VECTOR_LENGTH(p->item), sizeof(bool)); StrBuf->Init(&buf); if (VECTOR_LENGTH(cp.item) > 0) { + + delete = aCalloc(cp_size, sizeof(int)); + /** * Compare and update items, if any. */ @@ -78,7 +84,7 @@ int inter_storage_tosql(int account_id, const struct storage_data *p) int k = 0; if (memcmp(cp_it, p_it, sizeof(struct item)) != 0) { if (total_updates == 0) { - StrBuf->Printf(&buf, "REPLACE INTO `%s` (`id`, `account_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", storage_db); + StrBuf->Printf(&buf, "REPLACE INTO `%s` (`id`, `account_id`, `storage_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", storage_db); for (k = 0; k < MAX_SLOTS; k++) StrBuf->Printf(&buf, ", `card%d`", k); for (k = 0; k < MAX_ITEM_OPTIONS; k++) @@ -86,8 +92,8 @@ int inter_storage_tosql(int account_id, const struct storage_data *p) StrBuf->AppendStr(&buf, ", `expire_time`, `bound`, `unique_id`) VALUES"); } - StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%d', '%u', '%d', '%d', '%d'", - total_updates > 0 ? ", " : "", cp_it->id, account_id, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine, p_it->attribute); + StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%d', '%d', '%u', '%d', '%d', '%d'", + total_updates > 0 ? ", " : "", cp_it->id, account_id, storage_id, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine, p_it->attribute); for (k = 0; k < MAX_SLOTS; k++) StrBuf->Printf(&buf, ", '%d'", p_it->card[k]); for (k = 0; k < MAX_ITEM_OPTIONS; ++k) @@ -119,6 +125,8 @@ int inter_storage_tosql(int account_id, const struct storage_data *p) if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) Sql_ShowDebug(inter->sql_handle); } + + aFree(delete); } /** @@ -133,7 +141,7 @@ int inter_storage_tosql(int account_id, const struct storage_data *p) // Store the remaining items. if (total_inserts == 0) { StrBuf->Clear(&buf); - StrBuf->Printf(&buf, "INSERT INTO `%s` (`account_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", storage_db); + StrBuf->Printf(&buf, "INSERT INTO `%s` (`account_id`, `storage_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", storage_db); for (j = 0; j < MAX_SLOTS; ++j) StrBuf->Printf(&buf, ", `card%d`", j); for (j = 0; j < MAX_ITEM_OPTIONS; ++j) @@ -141,8 +149,8 @@ int inter_storage_tosql(int account_id, const struct storage_data *p) StrBuf->AppendStr(&buf, ") VALUES "); } - StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'", - total_inserts > 0 ? ", " : "", account_id, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine, + StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'", + total_inserts > 0 ? ", " : "", account_id, storage_id, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine, p_it->attribute, p_it->expire_time, p_it->bound, p_it->unique_id); for (j = 0; j < MAX_SLOTS; ++j) StrBuf->Printf(&buf, ", '%d'", p_it->card[j]); @@ -159,13 +167,14 @@ int inter_storage_tosql(int account_id, const struct storage_data *p) StrBuf->Destroy(&buf); VECTOR_CLEAR(cp.item); - total_changes = total_inserts + total_updates + total_deletes; - ShowInfo("storage save complete - id: %d (total: %d)\n", account_id, total_changes); - return total_changes; + aFree(matched_p); + + ShowInfo("Storage #%d save complete - id: %d (replace: %d, insert: %d, delete: %d)\n", storage_id, account_id, total_updates, total_inserts, total_deletes); + + return total_inserts + total_updates + total_deletes; } -/// Load storage data to mem -int inter_storage_fromsql(int account_id, struct storage_data *p) +int inter_storage_fromsql(int account_id, int storage_id, struct storage_data *p, int storage_size) { StringBuf buf; char* data; @@ -174,6 +183,7 @@ int inter_storage_fromsql(int account_id, struct storage_data *p) int num_rows = 0; nullpo_ret(p); + Assert_ret(storage_size >= 0); if (VECTOR_LENGTH(p->item) > 0) VECTOR_CLEAR(p->item); @@ -185,7 +195,7 @@ int inter_storage_fromsql(int account_id, struct storage_data *p) StrBuf->Printf(&buf, ",`card%d`", j); for (j = 0; j < MAX_ITEM_OPTIONS; ++j) StrBuf->Printf(&buf, ",`opt_idx%d`,`opt_val%d`", j, j); - StrBuf->Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id); + StrBuf->Printf(&buf, " FROM `%s` WHERE `account_id`='%d' AND `storage_id`='%d' ORDER BY `nameid`", storage_db, account_id, storage_id); if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) Sql_ShowDebug(inter->sql_handle); @@ -194,10 +204,14 @@ int inter_storage_fromsql(int account_id, struct storage_data *p) if ((num_rows = (int)SQL->NumRows(inter->sql_handle)) != 0) { - VECTOR_ENSURE(p->item, num_rows > MAX_STORAGE ? MAX_STORAGE : num_rows, 1); + VECTOR_ENSURE(p->item, storage_size > 0 ? min(num_rows, storage_size) : num_rows, 1); - for (i = 0; i < MAX_STORAGE && SQL_SUCCESS == SQL->NextRow(inter->sql_handle); ++i) { + for (i = 0; SQL_SUCCESS == SQL->NextRow(inter->sql_handle); ++i) { struct item item = { 0 }; + + if (storage_size > 0 && i > storage_size) + break; + SQL->GetData(inter->sql_handle, 0, &data, NULL); item.id = atoi(data); SQL->GetData(inter->sql_handle, 1, &data, NULL); item.nameid = atoi(data); SQL->GetData(inter->sql_handle, 2, &data, NULL); item.amount = atoi(data); @@ -229,7 +243,7 @@ int inter_storage_fromsql(int account_id, struct storage_data *p) SQL->FreeResult(inter->sql_handle); - ShowInfo("storage load complete from DB - id: %d (total: %d)\n", account_id, VECTOR_LENGTH(p->item)); + ShowInfo("Storage #%d load complete from DB - id: %d (total: %d)\n", storage_id, account_id, VECTOR_LENGTH(p->item)); return VECTOR_LENGTH(p->item); } @@ -373,30 +387,33 @@ int mapif_save_guild_storage_ack(int fd, int account_id, int guild_id, int fail) //--------------------------------------------------------- /** * Parses account storage load request from map server. - * @packet 0x3010 [in] .L + * @packet 0x3010 [in] .L .W .W * @param fd [in] file/socket descriptor * @return 1 on success, 0 on failure. */ int mapif_parse_AccountStorageLoad(int fd) { - int account_id = RFIFOL(fd, 2); + int account_id = RFIFOL(fd, 2), storage_id = RFIFOW(fd, 6); + int storage_size = RFIFOW(fd, 8); Assert_ret(fd > 0); Assert_ret(account_id > 0); + Assert_ret(storage_id >= 0); + Assert_ret(storage_size > 0); - mapif->account_storage_load(fd, account_id); + mapif->account_storage_load(fd, account_id, storage_id, storage_size); return 1; } /** - * Loads the account storage and send to the map server. - * @packet 0x3805 [out] .L .P + * Loads the account storage and sends to the map server. + * @packet 0x3805 [out] .W .L .W .P * @param fd [in] file/socket descriptor. * @param account_id [in] account id of the session. * @return 1 on success, 0 on failure. */ -int mapif_account_storage_load(int fd, int account_id) +int mapif_account_storage_load(int fd, int account_id, int storage_id, int storage_size) { struct storage_data stor = { 0 }; int count = 0, i = 0, len = 0; @@ -404,16 +421,18 @@ int mapif_account_storage_load(int fd, int account_id) Assert_ret(account_id > 0); VECTOR_INIT(stor.item); - count = inter_storage->fromsql(account_id, &stor); - len = 8 + count * sizeof(struct item); + count = inter_storage->fromsql(account_id, storage_id, &stor, storage_size); + + len = 10 + count * sizeof(struct item); WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x3805; WFIFOW(fd, 2) = (uint16) len; WFIFOL(fd, 4) = account_id; + WFIFOW(fd, 8) = storage_id; for (i = 0; i < count; i++) - memcpy(WFIFOP(fd, 8 + i * sizeof(struct item)), &VECTOR_INDEX(stor.item, i), sizeof(struct item)); + memcpy(WFIFOP(fd, 10 + i * sizeof(struct item)), &VECTOR_INDEX(stor.item, i), sizeof(struct item)); WFIFOSET(fd, len); VECTOR_CLEAR(stor.item); @@ -423,20 +442,21 @@ int mapif_account_storage_load(int fd, int account_id) /** * Parses an account storage save request from the map server. - * @packet 0x3011 [in] .W .L .P + * @packet 0x3011 [in] .W .L .L .P * @param fd [in] file/socket descriptor. * @return 1 on success, 0 on failure. */ int mapif_parse_AccountStorageSave(int fd) { - int payload_size = RFIFOW(fd, 2) - 8, account_id = RFIFOL(fd, 4); + int payload_size = RFIFOW(fd, 2) - 10, account_id = RFIFOL(fd, 4); + short storage_id = RFIFOW(fd, 8); int i = 0, count = 0; struct storage_data p_stor = { 0 }; Assert_ret(fd > 0); Assert_ret(account_id > 0); - count = payload_size/sizeof(struct item); + count = payload_size / sizeof(struct item); VECTOR_INIT(p_stor.item); @@ -444,7 +464,7 @@ int mapif_parse_AccountStorageSave(int fd) VECTOR_ENSURE(p_stor.item, count, 1); for (i = 0; i < count; i++) { - const struct item *it = RFIFOP(fd, 8 + i * sizeof(struct item)); + const struct item *it = RFIFOP(fd, 10 + i * sizeof(struct item)); VECTOR_PUSH(p_stor.item, *it); } @@ -452,11 +472,11 @@ int mapif_parse_AccountStorageSave(int fd) p_stor.aggregate = count; } - inter_storage->tosql(account_id, &p_stor); + inter_storage->tosql(account_id, storage_id, &p_stor); VECTOR_CLEAR(p_stor.item); - mapif->sAccountStorageSaveAck(fd, account_id, true); + mapif->sAccountStorageSaveAck(fd, account_id, storage_id, true); return 1; } @@ -464,18 +484,19 @@ int mapif_parse_AccountStorageSave(int fd) /** * Sends an acknowledgement for the save * status of the account storage. - * @packet 0x3808 [out] .L .B + * @packet 0x3808 [out] .L .W .B * @param fd [in] File/Socket Descriptor. * @param account_id [in] Account ID of the storage in question. * @param flag [in] Save flag, true for success and false for failure. */ -void mapif_send_AccountStorageSaveAck(int fd, int account_id, bool flag) +void mapif_send_AccountStorageSaveAck(int fd, int account_id, int storage_id, bool flag) { - WFIFOHEAD(fd, 7); + WFIFOHEAD(fd, 9); WFIFOW(fd, 0) = 0x3808; WFIFOL(fd, 2) = account_id; - WFIFOB(fd, 6) = flag ? 1 : 0; - WFIFOSET(fd, 7); + WFIFOW(fd, 6) = storage_id; + WFIFOB(fd, 8) = flag ? 1 : 0; + WFIFOSET(fd, 9); } //========================================================= diff --git a/src/char/int_storage.h b/src/char/int_storage.h index 46bb6910fb2..1a359b3d577 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -31,8 +31,8 @@ struct guild_storage; * inter_storage interface **/ struct inter_storage_interface { - int (*tosql) (int account_id, const struct storage_data *p); - int (*fromsql) (int account_id, struct storage_data *p); + int (*tosql) (int account_id, int storage_id, const struct storage_data *p); + int (*fromsql) (int account_id, int storage_id, struct storage_data *p, int storage_size); int (*guild_storage_tosql) (int guild_id, const struct guild_storage *p); int (*guild_storage_fromsql) (int guild_id, struct guild_storage* p); int (*sql_init) (void); diff --git a/src/char/inter.c b/src/char/inter.c index 557ee53139f..82523c8adec 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -69,7 +69,7 @@ int party_share_level = 10; // recv. packet list int inter_recv_packet_length[] = { -1,-1, 7,-1, -1,13,36, (2 + 4 + 4 + 4 + NAME_LENGTH), 0, 0, 0, 0, 0, 0, 0, 0, // 3000- - 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010- Account Storage [Smokexyz] + 10,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010- Account Storage [Smokexyz] -1,10,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, // 3020- Party -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030- -1, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040- diff --git a/src/char/mapif.c b/src/char/mapif.c index 9fccd691b4d..2dd674e0d46 100644 --- a/src/char/mapif.c +++ b/src/char/mapif.c @@ -197,10 +197,10 @@ int mapif_load_guild_storage(int fd,int account_id,int guild_id, char flag); int mapif_save_guild_storage_ack(int fd, int account_id, int guild_id, int fail); int mapif_parse_LoadGuildStorage(int fd); int mapif_parse_SaveGuildStorage(int fd); -int mapif_account_storage_load(int fd, int account_id); +int mapif_account_storage_load(int fd, int account_id, int storage_id, int storage_size); int mapif_parse_AccountStorageLoad(int fd); int mapif_parse_AccountStorageSave(int fd); -void mapif_send_AccountStorageSaveAck(int fd, int account_id, bool save); +void mapif_send_AccountStorageSaveAck(int fd, int account_id, int storage_id, bool save); int mapif_itembound_ack(int fd, int aid, int guild_id); int mapif_parse_ItemBoundRetrieve_sub(int fd); void mapif_parse_ItemBoundRetrieve(int fd); diff --git a/src/char/mapif.h b/src/char/mapif.h index a78940ba2c1..770cd0f8de6 100644 --- a/src/char/mapif.h +++ b/src/char/mapif.h @@ -189,10 +189,10 @@ struct mapif_interface { int (*save_guild_storage_ack) (int fd, int account_id, int guild_id, int fail); int (*parse_LoadGuildStorage) (int fd); int (*parse_SaveGuildStorage) (int fd); - int (*account_storage_load) (int fd, int account_id); + int (*account_storage_load) (int fd, int account_id, int storage_id, int storage_size); int (*pAccountStorageLoad) (int fd); int (*pAccountStorageSave) (int fd); - void (*sAccountStorageSaveAck) (int fd, int account_id, bool save); + void (*sAccountStorageSaveAck) (int fd, int account_id, int storage_id, bool save); int (*itembound_ack) (int fd, int aid, int guild_id); int (*parse_ItemBoundRetrieve_sub) (int fd); void (*parse_ItemBoundRetrieve) (int fd); diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h index a8524bddadd..d998ebdd269 100644 --- a/src/common/HPMDataCheck.h +++ b/src/common/HPMDataCheck.h @@ -225,6 +225,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { { "script_reg_str", sizeof(struct script_reg_str), SERVER_TYPE_ALL }, { "status_change_data", sizeof(struct status_change_data), SERVER_TYPE_ALL }, { "storage_data", sizeof(struct storage_data), SERVER_TYPE_ALL }, + { "storage_settings", sizeof(struct storage_settings), SERVER_TYPE_ALL }, #else #define COMMON_MMO_H #endif // COMMON_MMO_H diff --git a/src/common/mmo.h b/src/common/mmo.h index 7fd4ca6ea82..8ad3c8db88f 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -64,7 +64,7 @@ // 20120307 - 2012-03-07aRagexeRE+ - 0x970 #ifndef PACKETVER - #define PACKETVER 20141022 + #define PACKETVER 20150513 #endif // PACKETVER //Uncomment the following line if your client is ragexeRE instead of ragexe (required because of conflicting packets in ragexe vs ragexeRE). @@ -498,7 +498,15 @@ struct status_change_data { int tick; ///< Remaining duration. }; +/* Hercules Ultimate Storage System [Smokexyz/Hercules] */ +struct storage_settings { + int uid; ///< Storage Identifier. + char name[NAME_LENGTH]; ///< Storage Name + int capacity; ///< Item Capacity. +}; + struct storage_data { + int uid; ///< Storage Identifier. bool save; ///< save flag. bool received; ///< received flag. int aggregate; ///< total item count. diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 1590c3f0cd3..eeb171e204b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -850,15 +850,52 @@ ACMD(speed) *------------------------------------------*/ ACMD(storage) { + char storage_name[NAME_LENGTH] = ""; + int storage_id = 0, intval = 0; + struct storage_data *stor = NULL; + + if (*message && sscanf(message, "%12d", &intval) == 1) { + if (storage->get_settings(intval) == NULL) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 51), storage_name); + clif->message(fd, atcmd_output); // Invalid storage name or ID. + return false; + } + storage_id = intval; + } else if (*message && sscanf(message, "%23s", storage_name) == 1) { + if ((storage_id = storage->get_id_by_name(storage_name)) == -1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 51), storage_name); + clif->message(fd, atcmd_output); // Invalid storage name or ID. + return false; + } + } else { + clif->message(fd, msg_fd(fd, 52)); // Please specify a storage name (usage: @storage ). + return false; + } + + sd->storage.access = STORAGE_ACCESS_ALL; // Default storage access for atcommands. + + if ((stor = storage->ensure(sd, storage_id)) == NULL) { + ShowError("atcommand_storage: Error ensuring storage for player %d, storage_id %d\n", sd->bl.id, storage_id); + return false; + } + + if (stor->received == false) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 27), storage_name); + clif->message(fd, atcmd_output); // -- Storage '%s' has not been loaded yet. + return false; + } + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag) return false; - if (storage->open(sd) == 1) { //Already open. - clif->message(fd, msg_fd(fd,250)); // You have already opened your storage. Close it first. + if (storage->open(sd, stor) == 1) { // Already open. + clif->message(fd, msg_fd(fd, 250)); // You have already opened your storage. Close it first. return false; } - clif->message(fd, msg_fd(fd,919)); // Storage opened. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 919), storage_id); + + clif->message(fd, atcmd_output); // Storage #%d opened. return true; } @@ -5151,18 +5188,47 @@ ACMD(dropall) *------------------------------------------*/ ACMD(storeall) { - int i; + int i = 0; + char storage_name[NAME_LENGTH] = ""; + int storage_id = 0, intval = 0; + struct storage_data *stor = NULL; + + if (*message && sscanf(message, "%12d", &intval) == 1) { + if (storage->get_settings(intval) == NULL) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 51), storage_name); + clif->message(fd, atcmd_output); // Invalid storage name or ID. + return false; + } + storage_id = intval; + } else if (*message && sscanf(message, "%23s", storage_name) == 1) { + if ((storage_id = storage->get_id_by_name(storage_name)) == -1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 51), storage_name); + clif->message(fd, atcmd_output); // Invalid storage name or ID. + return false; + } + } else { + clif->message(fd, msg_fd(fd, 52)); // Please specify a storage name (usage: @clearstorage ). + return false; + } + + sd->storage.access = STORAGE_ACCESS_ALL; // Default storage access for atcommands. + + if ((stor = storage->ensure(sd, storage_id)) == NULL) { + ShowError("atcommand_storeall: Error ensuring storage for player %d, storage_id %d\n", sd->bl.id, storage_id); + return false; + } if (sd->state.storage_flag != STORAGE_FLAG_NORMAL) { //Open storage. - if (storage->open(sd) == 1) { - clif->message(fd, msg_fd(fd,1161)); // You currently cannot open your storage. + if (storage->open(sd, stor) == 1) { + clif->message(fd, msg_fd(fd, 1161)); // You currently cannot open your storage. return false; } } - if (sd->storage.received == false) { - clif->message(fd, msg_fd(fd, 27)); // "Storage has not been loaded yet" + if (stor->received == false) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 27), storage_name); + clif->message(fd, atcmd_output); // -- Storage '%s' has not been loaded yet. return false; } @@ -5170,39 +5236,70 @@ ACMD(storeall) if (sd->status.inventory[i].amount) { if(sd->status.inventory[i].equip != 0) pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); - storage->add(sd, i, sd->status.inventory[i].amount); + storage->add(sd, stor, i, sd->status.inventory[i].amount); } } + storage->close(sd); clif->message(fd, msg_fd(fd,1162)); // All items stored. + return true; } ACMD(clearstorage) { - int i; + int i = 0; + char storage_name[NAME_LENGTH] = ""; + int storage_id = 0, intval = 0; + struct storage_data *stor = NULL; + + if (*message && sscanf(message, "%12d", &intval) == 1) { + if (storage->get_settings(intval) == NULL) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 51), storage_name); + clif->message(fd, atcmd_output); // Invalid storage name or ID. + return false; + } + storage_id = intval; + } else if (*message && sscanf(message, "%23s", storage_name) == 1) { + if ((storage_id = storage->get_id_by_name(storage_name)) == -1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 51), storage_name); + clif->message(fd, atcmd_output); // Invalid storage name or ID. + return false; + } + } else { + clif->message(fd, msg_fd(fd, 52)); // Please specify a storage name (usage: @clearstorage ). + return false; + } if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { - clif->message(fd, msg_fd(fd,250)); + clif->message(fd, msg_fd(fd, 250)); // You have already opened your storage. Close it first. + return false; + } + + sd->storage.access = STORAGE_ACCESS_ALL; // Default storage access for atcommands. + + if ((stor = storage->ensure(sd, storage_id)) == NULL) { + ShowError("atcommand_clearstorage: Error ensuring storage for player %d, storage_id %d\n", sd->bl.id, storage_id); return false; } - if (sd->storage.received == false) { + if (stor->received == false) { clif->message(fd, msg_fd(fd, 27)); // "Storage has not been loaded yet" return false; } - for (i = 0; i < VECTOR_LENGTH(sd->storage.item); ++i) { - if (VECTOR_INDEX(sd->storage.item, i).nameid == 0) + for (i = 0; i < VECTOR_LENGTH(stor->item); ++i) { + if (VECTOR_INDEX(stor->item, i).nameid == 0) continue; // we skip the already deleted items. - storage->delitem(sd, i, VECTOR_INDEX(sd->storage.item, i).amount); + storage->delitem(sd, stor, i, VECTOR_INDEX(stor->item, i).amount); } storage->close(sd); clif->message(fd, msg_fd(fd,1394)); // Your storage was cleaned. + return true; } @@ -8043,7 +8140,6 @@ ACMD(resetskill) } /*========================================== - * #storagelist: Displays the items list of a player's storage. * #cartlist: Displays contents of target's cart. * #itemlist: Displays contents of target's inventory. *------------------------------------------*/ @@ -8055,11 +8151,7 @@ ACMD(itemlist) int size; StringBuf buf; - if( strcmpi(info->command, "storagelist") == 0 ) { - location = "storage"; - items = VECTOR_DATA(sd->storage.item); - size = VECTOR_LENGTH(sd->storage.item); - } else if( strcmpi(info->command, "cartlist") == 0 ) { + if( strcmpi(info->command, "cartlist") == 0 ) { location = "cart"; items = sd->status.cart; size = MAX_CART; @@ -9695,7 +9787,6 @@ void atcommand_basecommands(void) { ACMD_DEF(agitend2), ACMD_DEF2("skreset", resetskill), ACMD_DEF2("streset", resetstat), - ACMD_DEF2("storagelist", itemlist), ACMD_DEF2("cartlist", itemlist), ACMD_DEF2("itemlist", itemlist), ACMD_DEF(stats), diff --git a/src/map/chrif.c b/src/map/chrif.c index 96f1445230b..2b0e6244146 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -278,7 +278,10 @@ int chrif_isconnected(void) { * Flag = 2: Character is changing map-servers *------------------------------------------*/ // TODO: Flag enum -bool chrif_save(struct map_session_data *sd, int flag) { +bool chrif_save(struct map_session_data *sd, int flag) +{ + int i = 0; + nullpo_ret(sd); pc->makesavestatus(sd); @@ -297,8 +300,13 @@ bool chrif_save(struct map_session_data *sd, int flag) { if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->save(sd->status.account_id, sd->status.guild_id, flag); - if (flag) - sd->state.storage_flag = STORAGE_FLAG_CLOSED; //Force close it. + if (flag && sd->state.storage_flag != STORAGE_FLAG_CLOSED) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { + storage->close(sd); + } else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { + gstorage->close(sd); + } + } //Saving of registry values. if (sd->vars_dirty) @@ -324,8 +332,9 @@ bool chrif_save(struct map_session_data *sd, int flag) { if( sd->save_quest ) intif->quest_save(sd); - if (sd->storage.received == true && sd->storage.save == true) - intif->send_account_storage(sd); + for (i = 0; i < VECTOR_LENGTH(sd->storage.list); i++) + if (VECTOR_INDEX(sd->storage.list, i).received == true && VECTOR_INDEX(sd->storage.list, i).save == true) + intif->send_account_storage(sd, VECTOR_INDEX(sd->storage.list, i).uid); return true; } diff --git a/src/map/clif.c b/src/map/clif.c index 7edc1ec5a7d..c43e268a0f1 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2737,18 +2737,22 @@ void clif_equiplist(struct map_session_data *sd) { #endif } -void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) { +void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) +{ int i = 0; struct item_data *id; + const struct storage_settings *stst = storage->get_settings(sd->storage.current); nullpo_retv(sd); nullpo_retv(items); + nullpo_retv(stst); + do { int normal = 0, equip = 0, k = 0; for( ; i < items_length && k < 500; i++, k++ ) { - if( items[i].nameid <= 0 ) + if (items[i].nameid <= 0) continue; id = itemdb->search(items[i].nameid); @@ -2759,23 +2763,23 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items clif->item_normal(i+1,&storelist_normal.list[normal++],&items[i],id); } - if( normal ) { + if (normal) { storelist_normal.PacketType = storagelistnormalType; storelist_normal.PacketLength = ( sizeof( storelist_normal ) - sizeof( storelist_normal.list ) ) + (sizeof(struct NORMALITEM_INFO) * normal); #if PACKETVER >= 20120925 - safestrncpy(storelist_normal.name, "Storage", NAME_LENGTH); + safestrncpy(storelist_normal.name, stst->name, NAME_LENGTH); #endif clif->send(&storelist_normal, storelist_normal.PacketLength, &sd->bl, SELF); } - if( equip ) { + if (equip) { storelist_equip.PacketType = storagelistequipType; storelist_equip.PacketLength = ( sizeof( storelist_equip ) - sizeof( storelist_equip.list ) ) + (sizeof(struct EQUIPITEM_INFO) * equip); #if PACKETVER >= 20120925 - safestrncpy(storelist_equip.name, "Storage", NAME_LENGTH); + safestrncpy(storelist_equip.name, stst->name, NAME_LENGTH); #endif clif->send(&storelist_equip, storelist_equip.PacketLength, &sd->bl, SELF); @@ -8582,14 +8586,26 @@ void clif_messagecolor(struct block_list *bl, uint32 color, const char *msg) void clif_refresh_storagewindow(struct map_session_data *sd) { nullpo_retv(sd); + // Notify the client that the storage is open if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { - if (sd->storage.aggregate > 0) { - storage->sortitem(VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item)); - clif->storagelist(sd, VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item)); + const struct storage_settings *stst = storage->get_settings(sd->storage.current); + struct storage_data *stor = NULL; + + if (stst == NULL) return; + + if ((stor = storage->ensure(sd, sd->storage.current)) == NULL) { + return; + } + + if (stor->aggregate > 0) { + storage->sortitem(VECTOR_DATA(stor->item), VECTOR_LENGTH(stor->item)); + clif->storagelist(sd, VECTOR_DATA(stor->item), VECTOR_LENGTH(stor->item)); } - clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE); + + clif->updatestorageamount(sd, stor->aggregate, stst->capacity); } + // Notify the client that the gstorage is open otherwise it will // remain locked forever and nobody will be able to access it if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { @@ -8665,7 +8681,12 @@ void clif_refresh(struct map_session_data *sd) pc->disguise(sd, disguise); } - clif->refresh_storagewindow(sd); + // Close storage when refreshing the client + // to avoid an unnecessary complication of things. + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) + storage->close(sd); + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) + gstorage->close(sd); } /// Updates the object's (bl) name on client. @@ -11990,6 +12011,7 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) { int item_index, item_amount; + if (pc_istrading(sd)) return; @@ -11998,10 +12020,13 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1) return; - if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) - storage->add(sd, item_index, item_amount); - else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { + struct storage_data *stor = storage->ensure(sd, sd->storage.current); + if (stor != NULL) + storage->add(sd, stor, item_index, item_amount); + } else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { gstorage->add(sd, item_index, item_amount); + } } void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -12013,13 +12038,17 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) { int item_index, item_amount; + item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-1; item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]); - if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) - storage->get(sd, item_index, item_amount); - else if(sd->state.storage_flag == STORAGE_FLAG_GUILD) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { + struct storage_data *stor = storage->ensure(sd, sd->storage.current); + if (stor != NULL) + storage->get(sd, stor, item_index, item_amount); + } else if(sd->state.storage_flag == STORAGE_FLAG_GUILD) { gstorage->get(sd, item_index, item_amount); + } } void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -12027,15 +12056,19 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) __attri /// 0129 .W .L void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) { + if( sd->state.vending ) return; if (!pc_iscarton(sd)) return; - if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) - storage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); - else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { + struct storage_data *stor = storage->ensure(sd, sd->storage.current); + if (stor != NULL) + storage->addfromcart(sd, stor, RFIFOW(fd, 2) - 2, RFIFOL(fd, 4)); + } else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { gstorage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); + } } void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -12043,15 +12076,19 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) __attri /// 0128 .W .L void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) { + if( sd->state.vending ) return; if (!pc_iscarton(sd)) return; - if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) - storage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); - else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { + struct storage_data *stor = storage->ensure(sd, sd->storage.current); + if (stor != NULL) + storage->gettocart(sd, stor, RFIFOW(fd,2) - 1, RFIFOL(fd, 4)); + } else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { gstorage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); + } } void clif_parse_CloseKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); diff --git a/src/map/intif.c b/src/map/intif.c index 60edc8d8b6f..d30f7af26d2 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -446,26 +446,31 @@ int intif_request_registry(struct map_session_data *sd, int flag) /** * Request the inter-server for a character's storage data. - * @packet 0x3010 [out] .L + * @packet 0x3010 [out] .L .W .W * @param sd [in] pointer to session data. */ -void intif_request_account_storage(const struct map_session_data *sd) +void intif_request_account_storage(const struct map_session_data *sd, int storage_id) { + const struct storage_settings *stst = storage->get_settings(storage_id); + nullpo_retv(sd); + nullpo_retv(stst); /* Check for character server availability */ if (intif->CheckForCharServer()) return; - WFIFOHEAD(inter_fd, 6); + WFIFOHEAD(inter_fd, 10); WFIFOW(inter_fd, 0) = 0x3010; WFIFOL(inter_fd, 2) = sd->status.account_id; - WFIFOSET(inter_fd, 6); + WFIFOW(inter_fd, 6) = storage_id; + WFIFOW(inter_fd, 8) = stst->capacity; + WFIFOSET(inter_fd, 10); } /** * Parse the reception of account storage from the inter-server. - * @packet 0x3805 [in] .W .L .P + * @packet 0x3805 [in] .W .L .W .P * @param fd [in] file/socket descriptor. */ void intif_parse_account_storage(int fd) @@ -473,67 +478,77 @@ void intif_parse_account_storage(int fd) int account_id = 0, payload_size = 0, storage_count = 0; int i = 0; struct map_session_data *sd = NULL; + struct storage_data *stor = NULL; Assert_retv(fd > 0); - payload_size = RFIFOW(fd, 2) - 8; + payload_size = RFIFOW(fd, 2) - 10; if ((account_id = RFIFOL(fd, 4)) == 0 || (sd = map->id2sd(account_id)) == NULL) { ShowError("intif_parse_account_storage: Session pointer was null for account id %d!\n", account_id); return; } - if (sd->storage.received == true) { + if ((stor = storage->ensure(sd, RFIFOW(fd, 8))) == NULL) + return; + + if (stor->received == true) { ShowError("intif_parse_account_storage: Multiple calls from the inter-server received.\n"); return; } storage_count = (payload_size/sizeof(struct item)); - VECTOR_ENSURE(sd->storage.item, storage_count, 1); + VECTOR_ENSURE(stor->item, storage_count, 1); - sd->storage.aggregate = storage_count; // Total items in storage. + stor->aggregate = storage_count; // Total items in storage. for (i = 0; i < storage_count; i++) { - const struct item *it = RFIFOP(fd, 8 + i * sizeof(struct item)); - VECTOR_PUSH(sd->storage.item, *it); + const struct item *it = RFIFOP(fd, 10 + i * sizeof(struct item)); + VECTOR_PUSH(stor->item, *it); } - sd->storage.received = true; // Mark the storage state as received. - sd->storage.save = false; // Initialize the save flag as false. + stor->received = true; // Mark the storage state as received. + stor->save = false; // Initialize the save flag as false. pc->checkitem(sd); // re-check remaining items. } /** * Send account storage information for saving. - * @packet 0x3011 [out] .W .L .P + * @packet 0x3011 [out] .W .L .W .P * @param sd [in] pointer to session data. */ -void intif_send_account_storage(const struct map_session_data *sd) +void intif_send_account_storage(struct map_session_data *sd, int storage_id) { int len = 0, i = 0, c = 0; + struct storage_data *stor = NULL; nullpo_retv(sd); + if ((stor = storage->ensure(sd, storage_id)) == NULL) + return; + // Assert that at this point in the code, both flags are true. - Assert_retv(sd->storage.save == true); - Assert_retv(sd->storage.received == true); + Assert_retv(stor->save == true); + Assert_retv(stor->received == true); if (intif->CheckForCharServer()) return; - len = 8 + sd->storage.aggregate * sizeof(struct item); + len = 10 + stor->aggregate * sizeof(struct item); WFIFOHEAD(inter_fd, len); WFIFOW(inter_fd, 0) = 0x3011; WFIFOW(inter_fd, 2) = (uint16) len; WFIFOL(inter_fd, 4) = sd->status.account_id; - for (i = 0, c = 0; i < VECTOR_LENGTH(sd->storage.item); i++) { - if (VECTOR_INDEX(sd->storage.item, i).nameid == 0) + WFIFOW(inter_fd, 8) = storage_id; + + for (i = 0, c = 0; i < VECTOR_LENGTH(stor->item); i++) { + if (VECTOR_INDEX(stor->item, i).nameid == 0) continue; - memcpy(WFIFOP(inter_fd, 8 + c * sizeof(struct item)), &VECTOR_INDEX(sd->storage.item, i), sizeof(struct item)); + memcpy(WFIFOP(inter_fd, 10 + c * sizeof(struct item)), &VECTOR_INDEX(stor->item, i), sizeof(struct item)); c++; } @@ -542,27 +557,33 @@ void intif_send_account_storage(const struct map_session_data *sd) /** * Parse acknowledgement packet for the saving of an account's storage. - * @packet 0x3808 [in] .L .B + * @packet 0x3808 [in] .L .W .B * @param fd [in] file/socket descriptor. */ void intif_parse_account_storage_save_ack(int fd) { int account_id = RFIFOL(fd, 2); - uint8 saved = RFIFOB(fd, 6); + int storage_id = RFIFOW(fd, 6); + char saved = RFIFOB(fd, 8); struct map_session_data *sd = NULL; + struct storage_data *stor = NULL; Assert_retv(account_id > 0); Assert_retv(fd > 0); - + Assert_retv(storage_id >= 0); + if ((sd = map->id2sd(account_id)) == NULL) return; // character is most probably offline. if (saved == 0) { - ShowError("intif_parse_account_storage_save_ack: Storage has not been saved! (AID: %d)\n", account_id); + ShowError("intif_parse_account_storage_save_ack: Storage id %d has not been saved! (AID: %d)\n", storage_id, account_id); return; } - sd->storage.save = false; // Storage has been saved. + if ((stor = storage->ensure(sd, storage_id)) == NULL) + return; + + stor->save = false; // Storage has been saved. } //================================================================= @@ -2750,7 +2771,7 @@ int intif_parse(int fd) *-------------------------------------*/ void intif_defaults(void) { const int packet_len_table [INTIF_PACKET_LEN_TABLE_SIZE] = { - -1,-1,27,-1, -1,-1,37,-1, 7, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f + -1,-1,27,-1, -1,-1,37,-1, 9, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 diff --git a/src/map/intif.h b/src/map/intif.h index 4bca5f16788..7fd1e61acd1 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -67,8 +67,8 @@ struct intif_interface { int (*wis_message_to_gm) (char *Wisp_name, int permission, char *mes); int (*saveregistry) (struct map_session_data *sd); int (*request_registry) (struct map_session_data *sd, int flag); - void (*request_account_storage) (const struct map_session_data *sd); - void (*send_account_storage) (const struct map_session_data *sd); + void (*request_account_storage) (const struct map_session_data *sd, int storage_id); + void (*send_account_storage) (struct map_session_data *sd, int storage_id); int (*request_guild_storage) (int account_id, int guild_id); int (*send_guild_storage) (int account_id, struct guild_storage *gstor); int (*create_party) (struct party_member *member, const char *name, int item, int item2); diff --git a/src/map/map.c b/src/map/map.c index 5a647625f07..ed31d9ca476 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -6003,6 +6003,7 @@ int do_final(void) { script->final(); itemdb->final(); instance->final(); + storage->final(); gstorage->final(); guild->final(); party->final(); @@ -6060,6 +6061,7 @@ int do_final(void) { aFree(map->GRF_PATH_FILENAME); aFree(map->INTER_CONF_NAME); aFree(map->LOG_CONF_NAME); + aFree(map->STORAGE_CONF_FILENAME); HPM->event(HPET_POST_FINAL); @@ -6301,6 +6303,19 @@ static CMDLINEARG(grfpath) map->GRF_PATH_FILENAME = aStrdup(params); return true; } +/** + * --storage-path handler + * + * Overrides the default grf configuration filename. + * @see cmdline->exec + */ +static CMDLINEARG(storagepath) +{ + aFree(map->STORAGE_CONF_FILENAME); + map->STORAGE_CONF_FILENAME = aStrdup(params); + return true; +} + /** * --inter-config handler * @@ -6363,6 +6378,7 @@ void cmdline_args_init_local(void) CMDLINEARG_DEF2(script-config, scriptconfig, "Alternative script configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); CMDLINEARG_DEF2(msg-config, msgconfig, "Alternative message configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); CMDLINEARG_DEF2(grf-path, grfpath, "Alternative GRF path configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); + CMDLINEARG_DEF2(storage-path, storagepath, "Alternative Storage configuration path.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); CMDLINEARG_DEF2(inter-config, interconfig, "Alternative inter-server configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); CMDLINEARG_DEF2(log-config, logconfig, "Alternative logging configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM); CMDLINEARG_DEF2(script-check, scriptcheck, "Doesn't run the server, only tests the scripts passed through --load-script.", CMDLINE_OPT_SILENT); @@ -6388,6 +6404,7 @@ int do_init(int argc, char *argv[]) map->SCRIPT_CONF_NAME = aStrdup("conf/map/script.conf"); map->MSG_CONF_NAME = aStrdup("conf/messages.conf"); map->GRF_PATH_FILENAME = aStrdup("conf/grf-files.txt"); + map->STORAGE_CONF_FILENAME = aStrdup("conf/map/storage.conf"); HPM_map_do_init(); cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); @@ -6453,6 +6470,7 @@ int do_init(int argc, char *argv[]) atcommand->msg_read(map->MSG_CONF_NAME, false); map->inter_config_read(map->INTER_CONF_NAME, false); logs->config_read(map->LOG_CONF_NAME, false); + storage->config_read(map->STORAGE_CONF_FILENAME, false); } script->config_read(map->SCRIPT_CONF_NAME, false); @@ -6523,6 +6541,7 @@ int do_init(int argc, char *argv[]) status->init(minimal); party->init(minimal); guild->init(minimal); + storage->init(minimal); gstorage->init(minimal); pet->init(minimal); homun->init(minimal); @@ -6619,6 +6638,7 @@ void map_defaults(void) { map->SCRIPT_CONF_NAME = "conf/map/script.conf"; map->MSG_CONF_NAME = "conf/messages.conf"; map->GRF_PATH_FILENAME = "conf/grf-files.txt"; + map->STORAGE_CONF_FILENAME = "conf/map/storage.conf"; map->default_codepage[0] = '\0'; map->server_port = 3306; diff --git a/src/map/map.h b/src/map/map.h index 5835b5abcfc..d5b2daaf532 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1115,6 +1115,7 @@ struct map_interface { char *SCRIPT_CONF_NAME; char *MSG_CONF_NAME; char *GRF_PATH_FILENAME; + char *STORAGE_CONF_FILENAME; char autotrade_merchants_db[32]; char autotrade_data_db[32]; diff --git a/src/map/pc.c b/src/map/pc.c index d5d3595575b..cfbc30aa266 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1291,7 +1291,9 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->bg_queue.type = 0; VECTOR_INIT(sd->script_queues); - VECTOR_INIT(sd->storage.item); // initialize storage item vector. + + // Storage + VECTOR_INIT(sd->storage.list); sd->state.dialog = 0; @@ -1525,7 +1527,8 @@ int pc_reg_received(struct map_session_data *sd) chrif->scdata_request(sd->status.account_id, sd->status.char_id); // Storage Request - intif->request_account_storage(sd); + for (i = 0; i < VECTOR_LENGTH(storage->configuration); i++) + intif->request_account_storage(sd, VECTOR_INDEX(storage->configuration, i).uid); intif->Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox intif->request_questlog(sd); @@ -10272,21 +10275,27 @@ int pc_checkitem(struct map_session_data *sd) sd->itemcheck &= ~PCCHECKITEM_CART; } - if (sd->itemcheck & PCCHECKITEM_STORAGE && sd->storage.received == true) { - for (i = 0; i < VECTOR_LENGTH(sd->storage.item); i++) { - struct item *it = &VECTOR_INDEX(sd->storage.item, i); + if (sd->itemcheck & PCCHECKITEM_STORAGE) { + for (i = 0; i < VECTOR_LENGTH(sd->storage.list); i++) { + int j = 0; + struct storage_data *stor = &VECTOR_INDEX(sd->storage.list, i); - if ((id = it->nameid) == 0) - continue; + for (j = 0; j < VECTOR_LENGTH(sd->storage.list); j++) { + struct item *it = &VECTOR_INDEX(stor->item, j); - if (!itemdb_available(id)) { - ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", id, it->amount, sd->status.char_id); - storage->delitem(sd, i, it->amount); - continue; + if ((id = it->nameid) == 0) + continue; + + if (!itemdb_available(id)) { + ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from storage %d (amount=%d, char_id=%d).\n", id, stor->uid, it->amount, sd->status.char_id); + storage->delitem(sd, stor, i, it->amount); + continue; + } + + if (it->unique_id == 0 && itemdb->isstackable(id) == 0) + it->unique_id = itemdb->unique_id(sd); } - if (it->unique_id == 0 && itemdb->isstackable(id) == 0) - it->unique_id = itemdb->unique_id(sd); } storage->close(sd); diff --git a/src/map/pc.h b/src/map/pc.h index df0df979d8e..38cd4017338 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -32,6 +32,7 @@ #include "map/script.h" // struct reg_db #include "map/searchstore.h" // struct s_search_store_info #include "map/status.h" // enum sc_type, OPTION_* +#include "map/storage.h" #include "map/unit.h" // struct unit_data, struct view_data #include "map/vending.h" // struct s_vending #include "common/db.h" @@ -39,6 +40,7 @@ #include "common/hercules.h" #include "common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS + /** * Defines **/ @@ -260,7 +262,11 @@ struct map_session_data { struct mmo_charstatus status; struct item_data *inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups) - struct storage_data storage; ///< Account Storage + struct { + int current; ///< Marker for the current storage ID in use. + enum storage_access_modes access; ///< Access level for the user. + VECTOR_DECL(struct storage_data) list; ///< Account Storage + } storage; enum pc_checkitem_types itemcheck; short equip_index[EQI_MAX]; unsigned int weight,max_weight; diff --git a/src/map/script.c b/src/map/script.c index 7f7aba18323..dee0170da22 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10477,16 +10477,34 @@ BUILDIN(gettimestr) BUILDIN(openstorage) { struct map_session_data *sd = script->rid2sd(st); - if (sd == NULL) + int storage_id = script_getnum(st, 2); + int storage_access = script_hasdata(st, 3) ? script_getnum(st, 3) : STORAGE_ACCESS_ALL; + struct storage_data *stor = NULL; + const struct storage_settings *stst = NULL; + + nullpo_retr(false, sd); + + if ((stor = storage->ensure(sd, storage_id)) == NULL) { + script_pushint(st, 0); + ShowError("buildin_openstorage: Error ensuring storage for player aid %d, storage id %d.\n", sd->bl.id, storage_id); return false; + } - if (sd->storage.received == false) { + if ((stst = storage->get_settings(storage_id)) == NULL) { + script_pushint(st, 0); + ShowWarning("buildin_openstorage: Storage with ID %d was not found!\n", storage_id); + return false; + } + + if (stor->received == false) { script_pushint(st, 0); ShowWarning("buildin_openstorage: Storage data for AID %d has not been loaded.\n", sd->bl.id); return false; } - storage->open(sd); + sd->storage.access = storage_access; // Set storage access level. [Smokexyz/Hercules] + + storage->open(sd, stor); // Open storage! script_pushint(st, 1); // success flag. return true; @@ -24112,7 +24130,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(gettimetick,"i"), BUILDIN_DEF(gettime,"i"), BUILDIN_DEF(gettimestr,"si"), - BUILDIN_DEF(openstorage,""), + BUILDIN_DEF(openstorage,"i?"), BUILDIN_DEF(guildopenstorage,""), BUILDIN_DEF(itemskill,"vi?"), BUILDIN_DEF(produce,"i"), diff --git a/src/map/skill.c b/src/map/skill.c index 88a29b9a88a..6179063a938 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -44,6 +44,7 @@ #include "map/pet.h" #include "map/script.h" #include "map/status.h" +#include "map/storage.h" #include "map/unit.h" #include "common/cbasetypes.h" #include "common/ers.h" @@ -10864,15 +10865,18 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char switch(skill_id) { case AL_TELEPORT: - // The storage window is closed automatically by the client when there's - // any kind of map change, so we need to restore it automatically - // issue: 8027 if(strcmp(mapname,"Random")==0) pc->randomwarp(sd,CLR_TELEPORT); else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - clif->refresh_storagewindow(sd); + // Close storage when teleporting. + // Issue: https://github.com/HerculesWS/Hercules/issues/1762 + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) + storage->close(sd); + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) + gstorage->close(sd); + break; case AL_WARP: diff --git a/src/map/storage.c b/src/map/storage.c index 716abd62396..bb8bc8e4ee5 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -33,9 +33,11 @@ #include "map/map.h" // struct map_session_data #include "map/pc.h" #include "common/cbasetypes.h" -#include "common/db.h" +#include "common/conf.h" #include "common/memmgr.h" +#include "common/mmo.h" #include "common/nullpo.h" +#include "common/showmsg.h" #include #include @@ -95,37 +97,104 @@ void do_reconnect_storage(void) gstorage->db->foreach(gstorage->db, storage->reconnect_sub); } +/** + * Get a storage id by its name (through @commands etc...) + * @param[in] storage_name pointer to the storage name char array. + * @return id of the storage or -1 if not found. + */ +int storage_get_id_by_name(const char *storage_name) +{ + int i = 0; + + ARR_FIND(0, VECTOR_LENGTH(storage->configuration), i, strcmp(VECTOR_INDEX(storage->configuration, i).name, storage_name) == 0); + + if (i == VECTOR_LENGTH(storage->configuration)) + return -1; + + return VECTOR_INDEX(storage->configuration, i).uid; +} + +/** + * Get storage with a particular ID from a player. + * @param[in] sd pointer to map session data. + * @param[in] storage_id ID of the storage to receive. + * @return pointer to player's storage data structure or null if not found. + */ +struct storage_data *storage_ensure(struct map_session_data *sd, int storage_id) +{ + int i = 0; + struct storage_data *stor = NULL; + + nullpo_retr(NULL, sd); + + ARR_FIND(0, VECTOR_LENGTH(sd->storage.list), i, (stor = &VECTOR_INDEX(sd->storage.list, i)) != NULL && stor->uid == storage_id); + + if (i == VECTOR_LENGTH(sd->storage.list)) { + struct storage_data t_stor = { 0 }; + + t_stor.uid = storage_id; + VECTOR_INIT(t_stor.item); + VECTOR_ENSURE(sd->storage.list, 1, 1); + VECTOR_PUSH(sd->storage.list, t_stor); + stor = &VECTOR_LAST(sd->storage.list); + } + + return stor; +} + +/** + * Get a storage's settings through its ID. + * @param[in] storage_id the ID of the storage to find. + * @return storage settings of the storage in question. + */ +const struct storage_settings *storage_get_settings(int storage_id) +{ + int i = 0; + struct storage_settings *tmp_stor = NULL; + + ARR_FIND(0, VECTOR_LENGTH(storage->configuration), i, VECTOR_INDEX(storage->configuration, i).uid == storage_id); + + if (i < VECTOR_LENGTH(storage->configuration)) + tmp_stor = &VECTOR_INDEX(storage->configuration, i); + + return tmp_stor; +} + /*========================================== * Opens a storage. Returns: * 0 - success * 1 - fail *------------------------------------------*/ -int storage_storageopen(struct map_session_data *sd) +int storage_storageopen(struct map_session_data *sd, struct storage_data *stor) { + const struct storage_settings *stst = NULL; + nullpo_ret(sd); + nullpo_ret(stor); + Assert_ret(stor->received == true); // Assert the availability of data. + nullpo_ret(stst = storage->get_settings(stor->uid)); if (sd->state.storage_flag != STORAGE_FLAG_CLOSED) - return 1; //Already open? - - if (sd->storage.received == false) { - clif->message(sd->fd, msg_sd(sd, 27)); // Storage has not been loaded yet. - return 1; - } + return 1; // Storage is already open. - if( !pc_can_give_items(sd) ) { - //check is this GM level is allowed to put items to storage + // GM Permission check. + if (!pc_can_give_items(sd)) { clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action. return 1; } - sd->state.storage_flag = STORAGE_FLAG_NORMAL; + sd->state.storage_flag = STORAGE_FLAG_NORMAL; // Set the storage use state. + sd->storage.current = stor->uid; // Set current storage ID used. - if (sd->storage.aggregate > 0) { - storage->sortitem(VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item)); - clif->storagelist(sd, VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item)); + /* Send item list to client if available. */ + if (stor->aggregate > 0) { + storage->sortitem(VECTOR_DATA(stor->item), VECTOR_LENGTH(stor->item)); + clif->storagelist(sd, VECTOR_DATA(stor->item), VECTOR_LENGTH(stor->item)); } - clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE); + /* Send storage total items and max amount update. */ + clif->updatestorageamount(sd, stor->aggregate, stst->capacity); + return 0; } @@ -155,19 +224,21 @@ int compare_item(struct item *a, struct item *b) /*========================================== * Internal add-item function. *------------------------------------------*/ -int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) +int storage_additem(struct map_session_data* sd, struct storage_data *stor, struct item* item_data, int amount) { struct item_data *data = NULL; struct item *it = NULL; + const struct storage_settings *stst = NULL; int i; nullpo_retr(1, sd); - Assert_retr(1, sd->storage.received == true); - - nullpo_retr(1, item_data); - Assert_retr(1, item_data->nameid > 0); + nullpo_retr(1, stor); + Assert_retr(1, stor->received == true); // Assert the availability of the storage. + Assert_ret(stst = storage->get_settings(stor->uid)); // Assert existence of storage configuration. + nullpo_retr(1, item_data); // Assert availability of item data. + Assert_retr(1, item_data->nameid > 0); // Assert existence of item in the database. - Assert_retr(1, amount > 0); + Assert_retr(1, amount > 0); // Assert quantity of item. data = itemdb->search(item_data->nameid); @@ -186,8 +257,8 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo } if (itemdb->isstackable2(data)) {//Stackable - for (i = 0; i < VECTOR_LENGTH(sd->storage.item); i++) { - it = &VECTOR_INDEX(sd->storage.item, i); + for (i = 0; i < VECTOR_LENGTH(stor->item); i++) { + it = &VECTOR_INDEX(stor->item, i); if (it->nameid == 0) continue; @@ -199,38 +270,37 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo it->amount += amount; clif->storageitemadded(sd, it, i, amount); - - sd->storage.save = true; // set a save flag. - + stor->save = true; // set a save flag. + return 0; } } } // Check if storage exceeds limit. - if (sd->storage.aggregate >= MAX_STORAGE) + if (stor->aggregate >= stst->capacity) return 1; - ARR_FIND(0, VECTOR_LENGTH(sd->storage.item), i, VECTOR_INDEX(sd->storage.item, i).nameid == 0); + ARR_FIND(0, VECTOR_LENGTH(stor->item), i, VECTOR_INDEX(stor->item, i).nameid == 0); - if (i == VECTOR_LENGTH(sd->storage.item)) { - VECTOR_ENSURE(sd->storage.item, 1, 1); - VECTOR_PUSH(sd->storage.item, *item_data); - it = &VECTOR_LAST(sd->storage.item); + if (i == VECTOR_LENGTH(stor->item)) { + VECTOR_ENSURE(stor->item, 1, 1); + VECTOR_PUSH(stor->item, *item_data); + it = &VECTOR_LAST(stor->item); } else { - it = &VECTOR_INDEX(sd->storage.item, i); + it = &VECTOR_INDEX(stor->item, i); *it = *item_data; } it->amount = amount; - sd->storage.aggregate++; + stor->aggregate++; clif->storageitemadded(sd, it, i, amount); - clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE); + clif->updatestorageamount(sd, stor->aggregate, stst->capacity); - sd->storage.save = true; // set a save flag. + stor->save = true; // set a save flag. return 0; } @@ -238,30 +308,30 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo /*========================================== * Internal del-item function *------------------------------------------*/ -int storage_delitem(struct map_session_data* sd, int n, int amount) +int storage_delitem(struct map_session_data* sd, struct storage_data *stor, int n, int amount) { struct item *it = NULL; + const struct storage_settings *stst = NULL; nullpo_retr(1, sd); + nullpo_retr(1, stor); + Assert_retr(1, stor->received == true); + nullpo_retr(1, stst = storage->get_settings(stor->uid)); + Assert_retr(1, n >= 0 && n < VECTOR_LENGTH(stor->item)); - Assert_retr(1, sd->storage.received == true); - - Assert_retr(1, n >= 0 && n < VECTOR_LENGTH(sd->storage.item)); - - it = &VECTOR_INDEX(sd->storage.item, n); - + it = &VECTOR_INDEX(stor->item, n); + Assert_retr(1, amount <= it->amount); - Assert_retr(1, it->nameid > 0); it->amount -= amount; if (it->amount == 0) { memset(it, 0, sizeof(struct item)); - clif->updatestorageamount(sd, --sd->storage.aggregate, MAX_STORAGE); + clif->updatestorageamount(sd, --stor->aggregate, stst->capacity); } - sd->storage.save = true; + stor->save = true; if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) clif->storageitemremoved(sd, n, amount); @@ -276,13 +346,22 @@ int storage_delitem(struct map_session_data* sd, int n, int amount) * 0 : fail * 1 : success *------------------------------------------*/ -int storage_add_from_inventory(struct map_session_data* sd, int index, int amount) +int storage_add_from_inventory(struct map_session_data* sd, struct storage_data *stor, int index, int amount) { + const struct storage_settings *stst = NULL; + nullpo_ret(sd); + nullpo_ret(stor); + Assert_ret(stor->received == true); + nullpo_ret(stst = storage->get_settings(stor->uid)); - Assert_ret(sd->storage.received == true); + if ((sd->storage.access & STORAGE_ACCESS_PUT) == 0) { + clif->delitem(sd, index, amount, DELITEM_NORMAL); + clif->additem(sd, index, amount, 0); + return 0; + } - if (sd->storage.aggregate > MAX_STORAGE) + if (stor->aggregate >= stst->capacity) return 0; // storage full if (index < 0 || index >= MAX_INVENTORY) @@ -294,7 +373,7 @@ int storage_add_from_inventory(struct map_session_data* sd, int index, int amoun if (amount < 1 || amount > sd->status.inventory[index].amount) return 0; - if (storage->additem(sd, &sd->status.inventory[index], amount) == 0) + if (storage->additem(sd, stor, &sd->status.inventory[index], amount) == 0) pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_STORAGE); else clif->dropitem(sd, index, 0); @@ -309,19 +388,23 @@ int storage_add_from_inventory(struct map_session_data* sd, int index, int amoun * 0 : fail * 1 : success *------------------------------------------*/ -int storage_add_to_inventory(struct map_session_data* sd, int index, int amount) +int storage_add_to_inventory(struct map_session_data* sd, struct storage_data *stor, int index, int amount) { int flag; struct item *it = NULL; nullpo_ret(sd); + nullpo_ret(stor); + + Assert_ret(stor->received == true); - Assert_ret(sd->storage.received == true); + if ((sd->storage.access & STORAGE_ACCESS_GET) == 0) + return 0; - if (index < 0 || index >= VECTOR_LENGTH(sd->storage.item)) + if (index < 0 || index >= VECTOR_LENGTH(stor->item)) return 0; - it = &VECTOR_INDEX(sd->storage.item, index); + it = &VECTOR_INDEX(stor->item, index); if (it->nameid <= 0) return 0; //Nothing there @@ -330,7 +413,7 @@ int storage_add_to_inventory(struct map_session_data* sd, int index, int amount) return 0; if ((flag = pc->additem(sd, it, amount, LOG_TYPE_STORAGE)) == 0) - storage->delitem(sd, index, amount); + storage->delitem(sd, stor, index, amount); else clif->additem(sd, 0, 0, flag); @@ -344,26 +427,36 @@ int storage_add_to_inventory(struct map_session_data* sd, int index, int amount) * 0 : fail * 1 : success *------------------------------------------*/ -int storage_storageaddfromcart(struct map_session_data* sd, int index, int amount) +int storage_storageaddfromcart(struct map_session_data* sd, struct storage_data *stor, int index, int amount) { + const struct storage_settings *stst = NULL; + nullpo_ret(sd); + nullpo_ret(stor); + Assert_ret(stor->received == true); + nullpo_ret(stst = storage->get_settings(stor->uid)); - Assert_ret(sd->storage.received == true); - if (sd->storage.aggregate > MAX_STORAGE) + if ((sd->storage.access & STORAGE_ACCESS_PUT) == 0) { + clif->delitem(sd, index, amount, DELITEM_NORMAL); + clif->additem(sd, index, amount, 0); + return 0; + } + + if (stor->aggregate >= stst->capacity) return 0; // storage full / storage closed if (index < 0 || index >= MAX_CART) return 0; - if( sd->status.cart[index].nameid <= 0 ) + if (sd->status.cart[index].nameid <= 0) return 0; //No item there. if (amount < 1 || amount > sd->status.cart[index].amount) return 0; - if (storage->additem(sd,&sd->status.cart[index],amount) == 0) - pc->cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE); + if (storage->additem(sd, stor, &sd->status.cart[index], amount) == 0) + pc->cart_delitem(sd, index, amount, 0, LOG_TYPE_STORAGE); return 1; } @@ -375,19 +468,22 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun * 0 : fail * 1 : success *------------------------------------------*/ -int storage_storagegettocart(struct map_session_data* sd, int index, int amount) +int storage_storagegettocart(struct map_session_data* sd, struct storage_data *stor, int index, int amount) { int flag = 0; struct item *it = NULL; nullpo_ret(sd); + nullpo_ret(stor); + Assert_ret(stor->received == true); - Assert_ret(sd->storage.received == true); + if ((sd->storage.access & STORAGE_ACCESS_GET) == 0) + return 0; - if (index < 0 || index >= VECTOR_LENGTH(sd->storage.item)) + if (index < 0 || index >= VECTOR_LENGTH(stor->item)) return 0; - it = &VECTOR_INDEX(sd->storage.item, index); + it = &VECTOR_INDEX(stor->item, index); if (it->nameid <= 0) return 0; //Nothing there. @@ -396,7 +492,7 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount) return 0; if ((flag = pc->cart_additem(sd, it, amount, LOG_TYPE_STORAGE)) == 0) - storage->delitem(sd, index, amount); + storage->delitem(sd, stor, index, amount); else { clif->dropitem(sd, index,0); clif->cart_additem_ack(sd, flag == 1?0x0:0x1); @@ -412,10 +508,12 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount) void storage_storageclose(struct map_session_data* sd) { int i = 0; + struct storage_data *curr_stor = NULL; nullpo_retv(sd); - Assert_retv(sd->storage.received == true); + if ((curr_stor = storage->ensure(sd, sd->storage.current)) == NULL) + return; clif->storageclose(sd); @@ -424,15 +522,18 @@ void storage_storageclose(struct map_session_data* sd) /* Erase deleted account storage items from memory * and resize the vector. */ - while (i < VECTOR_LENGTH(sd->storage.item)) { - if (VECTOR_INDEX(sd->storage.item, i).nameid == 0) { - VECTOR_ERASE(sd->storage.item, i); + + while (i < VECTOR_LENGTH(curr_stor->item)) { + if (VECTOR_INDEX(curr_stor->item, i).nameid == 0) { + VECTOR_ERASE(curr_stor->item, i); } else { i++; } } sd->state.storage_flag = STORAGE_FLAG_CLOSED; + sd->storage.current = 0; // Reset current storage identifier. + sd->storage.access = STORAGE_ACCESS_ALL; // Reset access level to all levels. } /*========================================== @@ -839,10 +940,131 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) return 0; } +/** + * Read additional storage configuration fields for plugins. + * @param t [in] pointer to the config element being parsed. + * @param s_conf [in] pointer to the config struct being written to. + * @param filename [in] pointer to the filename string. + */ +void storage_config_read_additional_fields(struct config_setting_t *t, struct storage_settings *s_conf, const char *filename) +{ + // plugins do their own thing. +} + +/** + * Dynamically reads storage configuration and initializes required variables. + * + * @param filename Path to configuration file. + * @param imported Whether the current config is imported from another file. + * @retval false in case of error. + */ +bool storage_config_read(const char *filename, bool imported) +{ + struct config_t stor_libconf; + const struct config_setting_t *setting = NULL, *t = NULL; + int i = 0; + const char *import = NULL; + + nullpo_retr(false, filename); + + if (!imported) + VECTOR_INIT(storage->configuration); + + if (libconfig->load_file(&stor_libconf, filename) == 0) + return false; // Error message is already shown by libconfig->load_file() + + if ((setting = libconfig->setting_get_member(stor_libconf.root, "storage_conf")) == NULL && !imported) { + ShowError("storage_config_read: Error in reading file '%s'\n", filename); + libconfig->destroy(&stor_libconf); + return false; + } + + while ((t = libconfig->setting_get_elem(setting, i++)) != NULL) { + struct config_setting_t *tt = NULL; + struct storage_settings s_conf = { 0 }; + int d = 0; + + /* Id */ + if (libconfig->setting_lookup_int(t, "Id", &s_conf.uid) == 0) { + ShowError("storage_config_read: Id field not found for storage configuration in '%s'. Skipping...\n", filename); + continue; + } + + // Duplicate ID search and report... + ARR_FIND(0, VECTOR_LENGTH(storage->configuration), d, VECTOR_INDEX(storage->configuration, d).uid == s_conf.uid); + if (d < VECTOR_LENGTH(storage->configuration)) { + ShowError("storage_config_read: Duplicate ID %d for storage. Skipping...\n", s_conf.uid); + continue; + } + + // Check for an invalid ID... + if (s_conf.uid <= 0) { + ShowError("storage_config_read: ID for storage cannot be less than or equal to zero. Skipping...\n"); + continue; + } + + /* Name */ + if (libconfig->setting_lookup_mutable_string(t, "Name", s_conf.name, NAME_LENGTH) == 0) { + ShowError("storage_config_read: Name field not found for storage configuration (Id: %d) in '%s'. Skipping...\n", s_conf.uid, filename); + continue; + } + + /* Capacity */ + if (libconfig->setting_lookup_int(t, "Capacity", &s_conf.capacity) == 0) { + ShowError("storage_config_read: Capacity field not found for storage configuration (Id: %d) in '%s'. Skipping...\n", s_conf.uid, filename); + continue; + } + + /* Additional Fields */ + storage->config_read_additional_fields(tt, &s_conf, filename); + + if (imported) { + ARR_FIND(0, VECTOR_LENGTH(storage->configuration), i, VECTOR_INDEX(storage->configuration, i).uid == s_conf.uid); + if (i < VECTOR_LENGTH(storage->configuration)) + VECTOR_ERASE(storage->configuration, i); + } + + VECTOR_ENSURE(storage->configuration, 1, 1); + VECTOR_PUSH(storage->configuration, s_conf); + } + + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&stor_libconf, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, map->STORAGE_CONF_FILENAME) == 0) { + ShowWarning("battle_config_read: Loop detected! Skipping 'import'...\n"); + libconfig->destroy(&stor_libconf); + return false; + } else if (storage->config_read(import, true) == false) { + libconfig->destroy(&stor_libconf); + return false; + } + } + + libconfig->destroy(&stor_libconf); + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", VECTOR_LENGTH(storage->configuration), map->STORAGE_CONF_FILENAME); + + return true; +} + +void do_init_storage(bool minimal) +{ + if (minimal) + return; +} + +void do_final_storage(void) +{ + // Clear storage configuration vector. + if (VECTOR_LENGTH(storage->configuration) > 0) + VECTOR_CLEAR(storage->configuration); +} + void do_init_gstorage(bool minimal) { if (minimal) return; + gstorage->db = idb_alloc(DB_OPT_RELEASE_DATA); } @@ -855,9 +1077,16 @@ void storage_defaults(void) { storage = &storage_s; + storage->init = do_init_storage; + storage->final = do_final_storage; /* */ storage->reconnect = do_reconnect_storage; + storage->config_read = storage_config_read; + storage->config_read_additional_fields = storage_config_read_additional_fields; /* */ + storage->get_id_by_name = storage_get_id_by_name; + storage->ensure = storage_ensure; + storage->get_settings = storage_get_settings; storage->delitem = storage_delitem; storage->open = storage_storageopen; storage->add = storage_add_from_inventory; diff --git a/src/map/storage.h b/src/map/storage.h index 509862db725..a0a84285e84 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -24,9 +24,12 @@ #include "common/hercules.h" #include "common/db.h" +struct config_setting_t; struct guild_storage; struct item; struct map_session_data; +struct storage_settings; +struct storage_data; /** * Acceptable values for map_session_data.state.storage_flag @@ -37,17 +40,33 @@ enum storage_flag { STORAGE_FLAG_GUILD = 2, // Guild Storage open }; +// Storage Access Modes [Smokexyz/Hercules] +enum storage_access_modes { + STORAGE_ACCESS_VIEW = 0x0, + STORAGE_ACCESS_GET = 0x1, + STORAGE_ACCESS_PUT = 0x2, + STORAGE_ACCESS_ALL = STORAGE_ACCESS_VIEW | STORAGE_ACCESS_GET | STORAGE_ACCESS_PUT +}; + struct storage_interface { + VECTOR_DECL(struct storage_settings) configuration; + void (*init) (bool minimal); + void (*final) (void); /* */ void (*reconnect) (void); + bool (*config_read) (const char *filename, bool imported); + void (*config_read_additional_fields) (struct config_setting_t *t, struct storage_settings *s_conf, const char *filename); /* */ - int (*delitem) (struct map_session_data* sd, int n, int amount); - int (*open) (struct map_session_data *sd); - int (*add) (struct map_session_data *sd,int index,int amount); - int (*get) (struct map_session_data *sd,int index,int amount); - int (*additem) (struct map_session_data* sd, struct item* item_data, int amount); - int (*addfromcart) (struct map_session_data *sd,int index,int amount); - int (*gettocart) (struct map_session_data *sd,int index,int amount); + int (*get_id_by_name) (const char *storage_name); + struct storage_data *(*ensure) (struct map_session_data *sd, int storage_id); + const struct storage_settings *(*get_settings) (int storage_id); + int (*delitem) (struct map_session_data* sd, struct storage_data *stor, int n, int amount); + int (*open) (struct map_session_data *sd, struct storage_data *stor); + int (*add) (struct map_session_data *sd, struct storage_data *stor, int index, int amount); + int (*get) (struct map_session_data *sd, struct storage_data *stor, int index, int amount); + int (*additem) (struct map_session_data* sd, struct storage_data *stor, struct item* item_data, int amount); + int (*addfromcart) (struct map_session_data *sd, struct storage_data *stor, int index,int amount); + int (*gettocart) (struct map_session_data *sd, struct storage_data *stor, int index,int amount); void (*close) (struct map_session_data *sd); void (*pc_quit) (struct map_session_data *sd, int flag); int (*comp_item) (const void *i1_, const void *i2_); diff --git a/src/map/unit.c b/src/map/unit.c index 0b5b21caf27..732a4fe61bc 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2704,6 +2704,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) case BL_PC: { struct map_session_data *sd = BL_UCAST(BL_PC, bl); + int i = 0; sd->state.loggingout = 1; @@ -2742,7 +2743,6 @@ int unit_free(struct block_list *bl, clr_type clrtype) sd->combo_count = 0; /* [Ind/Hercules] */ if( sd->sc_display_count ) { - int i; for(i = 0; i < sd->sc_display_count; i++) { ers_free(pc->sc_display_ers, sd->sc_display[i]); } @@ -2757,8 +2757,12 @@ int unit_free(struct block_list *bl, clr_type clrtype) sd->instance = NULL; } VECTOR_CLEAR(sd->script_queues); - VECTOR_CLEAR(sd->storage.item); - sd->storage.received = false; + /* Storages */ + for (i = 0; i < VECTOR_LENGTH(sd->storage.list); i++) { + VECTOR_CLEAR(VECTOR_INDEX(sd->storage.list, i).item); + VECTOR_INDEX(sd->storage.list, i).received = false; + } + VECTOR_CLEAR(sd->storage.list); if( sd->quest_log != NULL ) { aFree(sd->quest_log); sd->quest_log = NULL; diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index b0c2d5fbcc0..0e76bb59956 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -3038,10 +3038,10 @@ typedef int64 (*HPMHOOK_pre_inter_rodex_savemessage) (struct rodex_message **msg typedef int64 (*HPMHOOK_post_inter_rodex_savemessage) (int64 retVal___, struct rodex_message *msg); #endif // CHAR_INT_RODEX_H #ifdef CHAR_INT_STORAGE_H /* inter_storage */ -typedef int (*HPMHOOK_pre_inter_storage_tosql) (int *account_id, const struct storage_data **p); -typedef int (*HPMHOOK_post_inter_storage_tosql) (int retVal___, int account_id, const struct storage_data *p); -typedef int (*HPMHOOK_pre_inter_storage_fromsql) (int *account_id, struct storage_data **p); -typedef int (*HPMHOOK_post_inter_storage_fromsql) (int retVal___, int account_id, struct storage_data *p); +typedef int (*HPMHOOK_pre_inter_storage_tosql) (int *account_id, int *storage_id, const struct storage_data **p); +typedef int (*HPMHOOK_post_inter_storage_tosql) (int retVal___, int account_id, int storage_id, const struct storage_data *p); +typedef int (*HPMHOOK_pre_inter_storage_fromsql) (int *account_id, int *storage_id, struct storage_data **p, int *storage_size); +typedef int (*HPMHOOK_post_inter_storage_fromsql) (int retVal___, int account_id, int storage_id, struct storage_data *p, int storage_size); typedef int (*HPMHOOK_pre_inter_storage_guild_storage_tosql) (int *guild_id, const struct guild_storage **p); typedef int (*HPMHOOK_post_inter_storage_guild_storage_tosql) (int retVal___, int guild_id, const struct guild_storage *p); typedef int (*HPMHOOK_pre_inter_storage_guild_storage_fromsql) (int *guild_id, struct guild_storage **p); @@ -3076,10 +3076,10 @@ typedef int (*HPMHOOK_pre_intif_saveregistry) (struct map_session_data **sd); typedef int (*HPMHOOK_post_intif_saveregistry) (int retVal___, struct map_session_data *sd); typedef int (*HPMHOOK_pre_intif_request_registry) (struct map_session_data **sd, int *flag); typedef int (*HPMHOOK_post_intif_request_registry) (int retVal___, struct map_session_data *sd, int flag); -typedef void (*HPMHOOK_pre_intif_request_account_storage) (const struct map_session_data **sd); -typedef void (*HPMHOOK_post_intif_request_account_storage) (const struct map_session_data *sd); -typedef void (*HPMHOOK_pre_intif_send_account_storage) (const struct map_session_data **sd); -typedef void (*HPMHOOK_post_intif_send_account_storage) (const struct map_session_data *sd); +typedef void (*HPMHOOK_pre_intif_request_account_storage) (const struct map_session_data **sd, int *storage_id); +typedef void (*HPMHOOK_post_intif_request_account_storage) (const struct map_session_data *sd, int storage_id); +typedef void (*HPMHOOK_pre_intif_send_account_storage) (struct map_session_data **sd, int *storage_id); +typedef void (*HPMHOOK_post_intif_send_account_storage) (struct map_session_data *sd, int storage_id); typedef int (*HPMHOOK_pre_intif_request_guild_storage) (int *account_id, int *guild_id); typedef int (*HPMHOOK_post_intif_request_guild_storage) (int retVal___, int account_id, int guild_id); typedef int (*HPMHOOK_pre_intif_send_guild_storage) (int *account_id, struct guild_storage **gstor); @@ -4518,14 +4518,14 @@ typedef int (*HPMHOOK_pre_mapif_parse_LoadGuildStorage) (int *fd); typedef int (*HPMHOOK_post_mapif_parse_LoadGuildStorage) (int retVal___, int fd); typedef int (*HPMHOOK_pre_mapif_parse_SaveGuildStorage) (int *fd); typedef int (*HPMHOOK_post_mapif_parse_SaveGuildStorage) (int retVal___, int fd); -typedef int (*HPMHOOK_pre_mapif_account_storage_load) (int *fd, int *account_id); -typedef int (*HPMHOOK_post_mapif_account_storage_load) (int retVal___, int fd, int account_id); +typedef int (*HPMHOOK_pre_mapif_account_storage_load) (int *fd, int *account_id, int *storage_id, int *storage_size); +typedef int (*HPMHOOK_post_mapif_account_storage_load) (int retVal___, int fd, int account_id, int storage_id, int storage_size); typedef int (*HPMHOOK_pre_mapif_pAccountStorageLoad) (int *fd); typedef int (*HPMHOOK_post_mapif_pAccountStorageLoad) (int retVal___, int fd); typedef int (*HPMHOOK_pre_mapif_pAccountStorageSave) (int *fd); typedef int (*HPMHOOK_post_mapif_pAccountStorageSave) (int retVal___, int fd); -typedef void (*HPMHOOK_pre_mapif_sAccountStorageSaveAck) (int *fd, int *account_id, bool *save); -typedef void (*HPMHOOK_post_mapif_sAccountStorageSaveAck) (int fd, int account_id, bool save); +typedef void (*HPMHOOK_pre_mapif_sAccountStorageSaveAck) (int *fd, int *account_id, int *storage_id, bool *save); +typedef void (*HPMHOOK_post_mapif_sAccountStorageSaveAck) (int fd, int account_id, int storage_id, bool save); typedef int (*HPMHOOK_pre_mapif_itembound_ack) (int *fd, int *aid, int *guild_id); typedef int (*HPMHOOK_post_mapif_itembound_ack) (int retVal___, int fd, int aid, int guild_id); typedef int (*HPMHOOK_pre_mapif_parse_ItemBoundRetrieve_sub) (int *fd); @@ -7220,22 +7220,36 @@ typedef unsigned short (*HPMHOOK_pre_status_base_matk_max) (const struct status_ typedef unsigned short (*HPMHOOK_post_status_base_matk_max) (unsigned short retVal___, const struct status_data *st); #endif // MAP_STATUS_H #ifdef MAP_STORAGE_H /* storage */ +typedef void (*HPMHOOK_pre_storage_init) (bool *minimal); +typedef void (*HPMHOOK_post_storage_init) (bool minimal); +typedef void (*HPMHOOK_pre_storage_final) (void); +typedef void (*HPMHOOK_post_storage_final) (void); typedef void (*HPMHOOK_pre_storage_reconnect) (void); typedef void (*HPMHOOK_post_storage_reconnect) (void); -typedef int (*HPMHOOK_pre_storage_delitem) (struct map_session_data **sd, int *n, int *amount); -typedef int (*HPMHOOK_post_storage_delitem) (int retVal___, struct map_session_data *sd, int n, int amount); -typedef int (*HPMHOOK_pre_storage_open) (struct map_session_data **sd); -typedef int (*HPMHOOK_post_storage_open) (int retVal___, struct map_session_data *sd); -typedef int (*HPMHOOK_pre_storage_add) (struct map_session_data **sd, int *index, int *amount); -typedef int (*HPMHOOK_post_storage_add) (int retVal___, struct map_session_data *sd, int index, int amount); -typedef int (*HPMHOOK_pre_storage_get) (struct map_session_data **sd, int *index, int *amount); -typedef int (*HPMHOOK_post_storage_get) (int retVal___, struct map_session_data *sd, int index, int amount); -typedef int (*HPMHOOK_pre_storage_additem) (struct map_session_data **sd, struct item **item_data, int *amount); -typedef int (*HPMHOOK_post_storage_additem) (int retVal___, struct map_session_data *sd, struct item *item_data, int amount); -typedef int (*HPMHOOK_pre_storage_addfromcart) (struct map_session_data **sd, int *index, int *amount); -typedef int (*HPMHOOK_post_storage_addfromcart) (int retVal___, struct map_session_data *sd, int index, int amount); -typedef int (*HPMHOOK_pre_storage_gettocart) (struct map_session_data **sd, int *index, int *amount); -typedef int (*HPMHOOK_post_storage_gettocart) (int retVal___, struct map_session_data *sd, int index, int amount); +typedef bool (*HPMHOOK_pre_storage_config_read) (const char **filename, bool *imported); +typedef bool (*HPMHOOK_post_storage_config_read) (bool retVal___, const char *filename, bool imported); +typedef void (*HPMHOOK_pre_storage_config_read_additional_fields) (struct config_setting_t **t, struct storage_settings **s_conf, const char **filename); +typedef void (*HPMHOOK_post_storage_config_read_additional_fields) (struct config_setting_t *t, struct storage_settings *s_conf, const char *filename); +typedef int (*HPMHOOK_pre_storage_get_id_by_name) (const char **storage_name); +typedef int (*HPMHOOK_post_storage_get_id_by_name) (int retVal___, const char *storage_name); +typedef struct storage_data* (*HPMHOOK_pre_storage_ensure) (struct map_session_data **sd, int *storage_id); +typedef struct storage_data* (*HPMHOOK_post_storage_ensure) (struct storage_data* retVal___, struct map_session_data *sd, int storage_id); +typedef const struct storage_settings* (*HPMHOOK_pre_storage_get_settings) (int *storage_id); +typedef const struct storage_settings* (*HPMHOOK_post_storage_get_settings) (const struct storage_settings* retVal___, int storage_id); +typedef int (*HPMHOOK_pre_storage_delitem) (struct map_session_data **sd, struct storage_data **stor, int *n, int *amount); +typedef int (*HPMHOOK_post_storage_delitem) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int n, int amount); +typedef int (*HPMHOOK_pre_storage_open) (struct map_session_data **sd, struct storage_data **stor); +typedef int (*HPMHOOK_post_storage_open) (int retVal___, struct map_session_data *sd, struct storage_data *stor); +typedef int (*HPMHOOK_pre_storage_add) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); +typedef int (*HPMHOOK_post_storage_add) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); +typedef int (*HPMHOOK_pre_storage_get) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); +typedef int (*HPMHOOK_post_storage_get) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); +typedef int (*HPMHOOK_pre_storage_additem) (struct map_session_data **sd, struct storage_data **stor, struct item **item_data, int *amount); +typedef int (*HPMHOOK_post_storage_additem) (int retVal___, struct map_session_data *sd, struct storage_data *stor, struct item *item_data, int amount); +typedef int (*HPMHOOK_pre_storage_addfromcart) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); +typedef int (*HPMHOOK_post_storage_addfromcart) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); +typedef int (*HPMHOOK_pre_storage_gettocart) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); +typedef int (*HPMHOOK_post_storage_gettocart) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); typedef void (*HPMHOOK_pre_storage_close) (struct map_session_data **sd); typedef void (*HPMHOOK_post_storage_close) (struct map_session_data *sd); typedef void (*HPMHOOK_pre_storage_pc_quit) (struct map_session_data **sd, int *flag); diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc index a372f83b393..f0bac2c01c8 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc @@ -8248,15 +8248,15 @@ int64 HP_inter_rodex_savemessage(struct rodex_message *msg) { return retVal___; } /* inter_storage_interface */ -int HP_inter_storage_tosql(int account_id, const struct storage_data *p) { +int HP_inter_storage_tosql(int account_id, int storage_id, const struct storage_data *p) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_inter_storage_tosql_pre > 0) { - int (*preHookFunc) (int *account_id, const struct storage_data **p); + int (*preHookFunc) (int *account_id, int *storage_id, const struct storage_data **p); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_inter_storage_tosql_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_inter_storage_tosql_pre[hIndex].func; - retVal___ = preHookFunc(&account_id, &p); + retVal___ = preHookFunc(&account_id, &storage_id, &p); } if (*HPMforce_return) { *HPMforce_return = false; @@ -8264,26 +8264,26 @@ int HP_inter_storage_tosql(int account_id, const struct storage_data *p) { } } { - retVal___ = HPMHooks.source.inter_storage.tosql(account_id, p); + retVal___ = HPMHooks.source.inter_storage.tosql(account_id, storage_id, p); } if (HPMHooks.count.HP_inter_storage_tosql_post > 0) { - int (*postHookFunc) (int retVal___, int account_id, const struct storage_data *p); + int (*postHookFunc) (int retVal___, int account_id, int storage_id, const struct storage_data *p); for (hIndex = 0; hIndex < HPMHooks.count.HP_inter_storage_tosql_post; hIndex++) { postHookFunc = HPMHooks.list.HP_inter_storage_tosql_post[hIndex].func; - retVal___ = postHookFunc(retVal___, account_id, p); + retVal___ = postHookFunc(retVal___, account_id, storage_id, p); } } return retVal___; } -int HP_inter_storage_fromsql(int account_id, struct storage_data *p) { +int HP_inter_storage_fromsql(int account_id, int storage_id, struct storage_data *p, int storage_size) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_inter_storage_fromsql_pre > 0) { - int (*preHookFunc) (int *account_id, struct storage_data **p); + int (*preHookFunc) (int *account_id, int *storage_id, struct storage_data **p, int *storage_size); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_inter_storage_fromsql_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_inter_storage_fromsql_pre[hIndex].func; - retVal___ = preHookFunc(&account_id, &p); + retVal___ = preHookFunc(&account_id, &storage_id, &p, &storage_size); } if (*HPMforce_return) { *HPMforce_return = false; @@ -8291,13 +8291,13 @@ int HP_inter_storage_fromsql(int account_id, struct storage_data *p) { } } { - retVal___ = HPMHooks.source.inter_storage.fromsql(account_id, p); + retVal___ = HPMHooks.source.inter_storage.fromsql(account_id, storage_id, p, storage_size); } if (HPMHooks.count.HP_inter_storage_fromsql_post > 0) { - int (*postHookFunc) (int retVal___, int account_id, struct storage_data *p); + int (*postHookFunc) (int retVal___, int account_id, int storage_id, struct storage_data *p, int storage_size); for (hIndex = 0; hIndex < HPMHooks.count.HP_inter_storage_fromsql_post; hIndex++) { postHookFunc = HPMHooks.list.HP_inter_storage_fromsql_post[hIndex].func; - retVal___ = postHookFunc(retVal___, account_id, p); + retVal___ = postHookFunc(retVal___, account_id, storage_id, p, storage_size); } } return retVal___; @@ -14885,15 +14885,15 @@ int HP_mapif_parse_SaveGuildStorage(int fd) { } return retVal___; } -int HP_mapif_account_storage_load(int fd, int account_id) { +int HP_mapif_account_storage_load(int fd, int account_id, int storage_id, int storage_size) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_mapif_account_storage_load_pre > 0) { - int (*preHookFunc) (int *fd, int *account_id); + int (*preHookFunc) (int *fd, int *account_id, int *storage_id, int *storage_size); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_mapif_account_storage_load_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_mapif_account_storage_load_pre[hIndex].func; - retVal___ = preHookFunc(&fd, &account_id); + retVal___ = preHookFunc(&fd, &account_id, &storage_id, &storage_size); } if (*HPMforce_return) { *HPMforce_return = false; @@ -14901,13 +14901,13 @@ int HP_mapif_account_storage_load(int fd, int account_id) { } } { - retVal___ = HPMHooks.source.mapif.account_storage_load(fd, account_id); + retVal___ = HPMHooks.source.mapif.account_storage_load(fd, account_id, storage_id, storage_size); } if (HPMHooks.count.HP_mapif_account_storage_load_post > 0) { - int (*postHookFunc) (int retVal___, int fd, int account_id); + int (*postHookFunc) (int retVal___, int fd, int account_id, int storage_id, int storage_size); for (hIndex = 0; hIndex < HPMHooks.count.HP_mapif_account_storage_load_post; hIndex++) { postHookFunc = HPMHooks.list.HP_mapif_account_storage_load_post[hIndex].func; - retVal___ = postHookFunc(retVal___, fd, account_id); + retVal___ = postHookFunc(retVal___, fd, account_id, storage_id, storage_size); } } return retVal___; @@ -14966,14 +14966,14 @@ int HP_mapif_pAccountStorageSave(int fd) { } return retVal___; } -void HP_mapif_sAccountStorageSaveAck(int fd, int account_id, bool save) { +void HP_mapif_sAccountStorageSaveAck(int fd, int account_id, int storage_id, bool save) { int hIndex = 0; if (HPMHooks.count.HP_mapif_sAccountStorageSaveAck_pre > 0) { - void (*preHookFunc) (int *fd, int *account_id, bool *save); + void (*preHookFunc) (int *fd, int *account_id, int *storage_id, bool *save); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_mapif_sAccountStorageSaveAck_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_mapif_sAccountStorageSaveAck_pre[hIndex].func; - preHookFunc(&fd, &account_id, &save); + preHookFunc(&fd, &account_id, &storage_id, &save); } if (*HPMforce_return) { *HPMforce_return = false; @@ -14981,13 +14981,13 @@ void HP_mapif_sAccountStorageSaveAck(int fd, int account_id, bool save) { } } { - HPMHooks.source.mapif.sAccountStorageSaveAck(fd, account_id, save); + HPMHooks.source.mapif.sAccountStorageSaveAck(fd, account_id, storage_id, save); } if (HPMHooks.count.HP_mapif_sAccountStorageSaveAck_post > 0) { - void (*postHookFunc) (int fd, int account_id, bool save); + void (*postHookFunc) (int fd, int account_id, int storage_id, bool save); for (hIndex = 0; hIndex < HPMHooks.count.HP_mapif_sAccountStorageSaveAck_post; hIndex++) { postHookFunc = HPMHooks.list.HP_mapif_sAccountStorageSaveAck_post[hIndex].func; - postHookFunc(fd, account_id, save); + postHookFunc(fd, account_id, storage_id, save); } } return; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index cc097aeae40..d711de42bba 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -5926,8 +5926,22 @@ struct { struct HPMHookPoint *HP_status_base_matk_min_post; struct HPMHookPoint *HP_status_base_matk_max_pre; struct HPMHookPoint *HP_status_base_matk_max_post; + struct HPMHookPoint *HP_storage_init_pre; + struct HPMHookPoint *HP_storage_init_post; + struct HPMHookPoint *HP_storage_final_pre; + struct HPMHookPoint *HP_storage_final_post; struct HPMHookPoint *HP_storage_reconnect_pre; struct HPMHookPoint *HP_storage_reconnect_post; + struct HPMHookPoint *HP_storage_config_read_pre; + struct HPMHookPoint *HP_storage_config_read_post; + struct HPMHookPoint *HP_storage_config_read_additional_fields_pre; + struct HPMHookPoint *HP_storage_config_read_additional_fields_post; + struct HPMHookPoint *HP_storage_get_id_by_name_pre; + struct HPMHookPoint *HP_storage_get_id_by_name_post; + struct HPMHookPoint *HP_storage_ensure_pre; + struct HPMHookPoint *HP_storage_ensure_post; + struct HPMHookPoint *HP_storage_get_settings_pre; + struct HPMHookPoint *HP_storage_get_settings_post; struct HPMHookPoint *HP_storage_delitem_pre; struct HPMHookPoint *HP_storage_delitem_post; struct HPMHookPoint *HP_storage_open_pre; @@ -12135,8 +12149,22 @@ struct { int HP_status_base_matk_min_post; int HP_status_base_matk_max_pre; int HP_status_base_matk_max_post; + int HP_storage_init_pre; + int HP_storage_init_post; + int HP_storage_final_pre; + int HP_storage_final_post; int HP_storage_reconnect_pre; int HP_storage_reconnect_post; + int HP_storage_config_read_pre; + int HP_storage_config_read_post; + int HP_storage_config_read_additional_fields_pre; + int HP_storage_config_read_additional_fields_post; + int HP_storage_get_id_by_name_pre; + int HP_storage_get_id_by_name_post; + int HP_storage_ensure_pre; + int HP_storage_ensure_post; + int HP_storage_get_settings_pre; + int HP_storage_get_settings_post; int HP_storage_delitem_pre; int HP_storage_delitem_post; int HP_storage_open_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index 7caf25de669..8885729eb93 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -3031,7 +3031,14 @@ struct HookingPointData HookingPoints[] = { { HP_POP(status->base_matk_min, HP_status_base_matk_min) }, { HP_POP(status->base_matk_max, HP_status_base_matk_max) }, /* storage_interface */ + { HP_POP(storage->init, HP_storage_init) }, + { HP_POP(storage->final, HP_storage_final) }, { HP_POP(storage->reconnect, HP_storage_reconnect) }, + { HP_POP(storage->config_read, HP_storage_config_read) }, + { HP_POP(storage->config_read_additional_fields, HP_storage_config_read_additional_fields) }, + { HP_POP(storage->get_id_by_name, HP_storage_get_id_by_name) }, + { HP_POP(storage->ensure, HP_storage_ensure) }, + { HP_POP(storage->get_settings, HP_storage_get_settings) }, { HP_POP(storage->delitem, HP_storage_delitem) }, { HP_POP(storage->open, HP_storage_open) }, { HP_POP(storage->add, HP_storage_add) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 4340f8dbd27..aad8a629502 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -32077,14 +32077,14 @@ int HP_intif_request_registry(struct map_session_data *sd, int flag) { } return retVal___; } -void HP_intif_request_account_storage(const struct map_session_data *sd) { +void HP_intif_request_account_storage(const struct map_session_data *sd, int storage_id) { int hIndex = 0; if (HPMHooks.count.HP_intif_request_account_storage_pre > 0) { - void (*preHookFunc) (const struct map_session_data **sd); + void (*preHookFunc) (const struct map_session_data **sd, int *storage_id); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_intif_request_account_storage_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_intif_request_account_storage_pre[hIndex].func; - preHookFunc(&sd); + preHookFunc(&sd, &storage_id); } if (*HPMforce_return) { *HPMforce_return = false; @@ -32092,25 +32092,25 @@ void HP_intif_request_account_storage(const struct map_session_data *sd) { } } { - HPMHooks.source.intif.request_account_storage(sd); + HPMHooks.source.intif.request_account_storage(sd, storage_id); } if (HPMHooks.count.HP_intif_request_account_storage_post > 0) { - void (*postHookFunc) (const struct map_session_data *sd); + void (*postHookFunc) (const struct map_session_data *sd, int storage_id); for (hIndex = 0; hIndex < HPMHooks.count.HP_intif_request_account_storage_post; hIndex++) { postHookFunc = HPMHooks.list.HP_intif_request_account_storage_post[hIndex].func; - postHookFunc(sd); + postHookFunc(sd, storage_id); } } return; } -void HP_intif_send_account_storage(const struct map_session_data *sd) { +void HP_intif_send_account_storage(struct map_session_data *sd, int storage_id) { int hIndex = 0; if (HPMHooks.count.HP_intif_send_account_storage_pre > 0) { - void (*preHookFunc) (const struct map_session_data **sd); + void (*preHookFunc) (struct map_session_data **sd, int *storage_id); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_intif_send_account_storage_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_intif_send_account_storage_pre[hIndex].func; - preHookFunc(&sd); + preHookFunc(&sd, &storage_id); } if (*HPMforce_return) { *HPMforce_return = false; @@ -32118,13 +32118,13 @@ void HP_intif_send_account_storage(const struct map_session_data *sd) { } } { - HPMHooks.source.intif.send_account_storage(sd); + HPMHooks.source.intif.send_account_storage(sd, storage_id); } if (HPMHooks.count.HP_intif_send_account_storage_post > 0) { - void (*postHookFunc) (const struct map_session_data *sd); + void (*postHookFunc) (struct map_session_data *sd, int storage_id); for (hIndex = 0; hIndex < HPMHooks.count.HP_intif_send_account_storage_post; hIndex++) { postHookFunc = HPMHooks.list.HP_intif_send_account_storage_post[hIndex].func; - postHookFunc(sd); + postHookFunc(sd, storage_id); } } return; @@ -79368,6 +79368,58 @@ unsigned short HP_status_base_matk_max(const struct status_data *st) { return retVal___; } /* storage_interface */ +void HP_storage_init(bool minimal) { + int hIndex = 0; + if (HPMHooks.count.HP_storage_init_pre > 0) { + void (*preHookFunc) (bool *minimal); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_init_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_storage_init_pre[hIndex].func; + preHookFunc(&minimal); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.storage.init(minimal); + } + if (HPMHooks.count.HP_storage_init_post > 0) { + void (*postHookFunc) (bool minimal); + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_init_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_storage_init_post[hIndex].func; + postHookFunc(minimal); + } + } + return; +} +void HP_storage_final(void) { + int hIndex = 0; + if (HPMHooks.count.HP_storage_final_pre > 0) { + void (*preHookFunc) (void); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_final_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_storage_final_pre[hIndex].func; + preHookFunc(); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.storage.final(); + } + if (HPMHooks.count.HP_storage_final_post > 0) { + void (*postHookFunc) (void); + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_final_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_storage_final_post[hIndex].func; + postHookFunc(); + } + } + return; +} void HP_storage_reconnect(void) { int hIndex = 0; if (HPMHooks.count.HP_storage_reconnect_pre > 0) { @@ -79394,15 +79446,149 @@ void HP_storage_reconnect(void) { } return; } -int HP_storage_delitem(struct map_session_data *sd, int n, int amount) { +bool HP_storage_config_read(const char *filename, bool imported) { + int hIndex = 0; + bool retVal___ = false; + if (HPMHooks.count.HP_storage_config_read_pre > 0) { + bool (*preHookFunc) (const char **filename, bool *imported); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_config_read_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_storage_config_read_pre[hIndex].func; + retVal___ = preHookFunc(&filename, &imported); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.storage.config_read(filename, imported); + } + if (HPMHooks.count.HP_storage_config_read_post > 0) { + bool (*postHookFunc) (bool retVal___, const char *filename, bool imported); + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_config_read_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_storage_config_read_post[hIndex].func; + retVal___ = postHookFunc(retVal___, filename, imported); + } + } + return retVal___; +} +void HP_storage_config_read_additional_fields(struct config_setting_t *t, struct storage_settings *s_conf, const char *filename) { + int hIndex = 0; + if (HPMHooks.count.HP_storage_config_read_additional_fields_pre > 0) { + void (*preHookFunc) (struct config_setting_t **t, struct storage_settings **s_conf, const char **filename); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_config_read_additional_fields_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_storage_config_read_additional_fields_pre[hIndex].func; + preHookFunc(&t, &s_conf, &filename); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.storage.config_read_additional_fields(t, s_conf, filename); + } + if (HPMHooks.count.HP_storage_config_read_additional_fields_post > 0) { + void (*postHookFunc) (struct config_setting_t *t, struct storage_settings *s_conf, const char *filename); + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_config_read_additional_fields_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_storage_config_read_additional_fields_post[hIndex].func; + postHookFunc(t, s_conf, filename); + } + } + return; +} +int HP_storage_get_id_by_name(const char *storage_name) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_storage_get_id_by_name_pre > 0) { + int (*preHookFunc) (const char **storage_name); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_get_id_by_name_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_storage_get_id_by_name_pre[hIndex].func; + retVal___ = preHookFunc(&storage_name); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.storage.get_id_by_name(storage_name); + } + if (HPMHooks.count.HP_storage_get_id_by_name_post > 0) { + int (*postHookFunc) (int retVal___, const char *storage_name); + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_get_id_by_name_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_storage_get_id_by_name_post[hIndex].func; + retVal___ = postHookFunc(retVal___, storage_name); + } + } + return retVal___; +} +struct storage_data* HP_storage_ensure(struct map_session_data *sd, int storage_id) { + int hIndex = 0; + struct storage_data* retVal___ = NULL; + if (HPMHooks.count.HP_storage_ensure_pre > 0) { + struct storage_data* (*preHookFunc) (struct map_session_data **sd, int *storage_id); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_ensure_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_storage_ensure_pre[hIndex].func; + retVal___ = preHookFunc(&sd, &storage_id); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.storage.ensure(sd, storage_id); + } + if (HPMHooks.count.HP_storage_ensure_post > 0) { + struct storage_data* (*postHookFunc) (struct storage_data* retVal___, struct map_session_data *sd, int storage_id); + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_ensure_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_storage_ensure_post[hIndex].func; + retVal___ = postHookFunc(retVal___, sd, storage_id); + } + } + return retVal___; +} +const struct storage_settings* HP_storage_get_settings(int storage_id) { + int hIndex = 0; + const struct storage_settings* retVal___ = NULL; + if (HPMHooks.count.HP_storage_get_settings_pre > 0) { + const struct storage_settings* (*preHookFunc) (int *storage_id); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_get_settings_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_storage_get_settings_pre[hIndex].func; + retVal___ = preHookFunc(&storage_id); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.storage.get_settings(storage_id); + } + if (HPMHooks.count.HP_storage_get_settings_post > 0) { + const struct storage_settings* (*postHookFunc) (const struct storage_settings* retVal___, int storage_id); + for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_get_settings_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_storage_get_settings_post[hIndex].func; + retVal___ = postHookFunc(retVal___, storage_id); + } + } + return retVal___; +} +int HP_storage_delitem(struct map_session_data *sd, struct storage_data *stor, int n, int amount) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_storage_delitem_pre > 0) { - int (*preHookFunc) (struct map_session_data **sd, int *n, int *amount); + int (*preHookFunc) (struct map_session_data **sd, struct storage_data **stor, int *n, int *amount); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_delitem_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_storage_delitem_pre[hIndex].func; - retVal___ = preHookFunc(&sd, &n, &amount); + retVal___ = preHookFunc(&sd, &stor, &n, &amount); } if (*HPMforce_return) { *HPMforce_return = false; @@ -79410,26 +79596,26 @@ int HP_storage_delitem(struct map_session_data *sd, int n, int amount) { } } { - retVal___ = HPMHooks.source.storage.delitem(sd, n, amount); + retVal___ = HPMHooks.source.storage.delitem(sd, stor, n, amount); } if (HPMHooks.count.HP_storage_delitem_post > 0) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd, int n, int amount); + int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int n, int amount); for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_delitem_post; hIndex++) { postHookFunc = HPMHooks.list.HP_storage_delitem_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd, n, amount); + retVal___ = postHookFunc(retVal___, sd, stor, n, amount); } } return retVal___; } -int HP_storage_open(struct map_session_data *sd) { +int HP_storage_open(struct map_session_data *sd, struct storage_data *stor) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_storage_open_pre > 0) { - int (*preHookFunc) (struct map_session_data **sd); + int (*preHookFunc) (struct map_session_data **sd, struct storage_data **stor); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_open_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_storage_open_pre[hIndex].func; - retVal___ = preHookFunc(&sd); + retVal___ = preHookFunc(&sd, &stor); } if (*HPMforce_return) { *HPMforce_return = false; @@ -79437,26 +79623,26 @@ int HP_storage_open(struct map_session_data *sd) { } } { - retVal___ = HPMHooks.source.storage.open(sd); + retVal___ = HPMHooks.source.storage.open(sd, stor); } if (HPMHooks.count.HP_storage_open_post > 0) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd); + int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct storage_data *stor); for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_open_post; hIndex++) { postHookFunc = HPMHooks.list.HP_storage_open_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd); + retVal___ = postHookFunc(retVal___, sd, stor); } } return retVal___; } -int HP_storage_add(struct map_session_data *sd, int index, int amount) { +int HP_storage_add(struct map_session_data *sd, struct storage_data *stor, int index, int amount) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_storage_add_pre > 0) { - int (*preHookFunc) (struct map_session_data **sd, int *index, int *amount); + int (*preHookFunc) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_add_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_storage_add_pre[hIndex].func; - retVal___ = preHookFunc(&sd, &index, &amount); + retVal___ = preHookFunc(&sd, &stor, &index, &amount); } if (*HPMforce_return) { *HPMforce_return = false; @@ -79464,26 +79650,26 @@ int HP_storage_add(struct map_session_data *sd, int index, int amount) { } } { - retVal___ = HPMHooks.source.storage.add(sd, index, amount); + retVal___ = HPMHooks.source.storage.add(sd, stor, index, amount); } if (HPMHooks.count.HP_storage_add_post > 0) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd, int index, int amount); + int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_add_post; hIndex++) { postHookFunc = HPMHooks.list.HP_storage_add_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd, index, amount); + retVal___ = postHookFunc(retVal___, sd, stor, index, amount); } } return retVal___; } -int HP_storage_get(struct map_session_data *sd, int index, int amount) { +int HP_storage_get(struct map_session_data *sd, struct storage_data *stor, int index, int amount) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_storage_get_pre > 0) { - int (*preHookFunc) (struct map_session_data **sd, int *index, int *amount); + int (*preHookFunc) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_get_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_storage_get_pre[hIndex].func; - retVal___ = preHookFunc(&sd, &index, &amount); + retVal___ = preHookFunc(&sd, &stor, &index, &amount); } if (*HPMforce_return) { *HPMforce_return = false; @@ -79491,26 +79677,26 @@ int HP_storage_get(struct map_session_data *sd, int index, int amount) { } } { - retVal___ = HPMHooks.source.storage.get(sd, index, amount); + retVal___ = HPMHooks.source.storage.get(sd, stor, index, amount); } if (HPMHooks.count.HP_storage_get_post > 0) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd, int index, int amount); + int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_get_post; hIndex++) { postHookFunc = HPMHooks.list.HP_storage_get_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd, index, amount); + retVal___ = postHookFunc(retVal___, sd, stor, index, amount); } } return retVal___; } -int HP_storage_additem(struct map_session_data *sd, struct item *item_data, int amount) { +int HP_storage_additem(struct map_session_data *sd, struct storage_data *stor, struct item *item_data, int amount) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_storage_additem_pre > 0) { - int (*preHookFunc) (struct map_session_data **sd, struct item **item_data, int *amount); + int (*preHookFunc) (struct map_session_data **sd, struct storage_data **stor, struct item **item_data, int *amount); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_additem_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_storage_additem_pre[hIndex].func; - retVal___ = preHookFunc(&sd, &item_data, &amount); + retVal___ = preHookFunc(&sd, &stor, &item_data, &amount); } if (*HPMforce_return) { *HPMforce_return = false; @@ -79518,26 +79704,26 @@ int HP_storage_additem(struct map_session_data *sd, struct item *item_data, int } } { - retVal___ = HPMHooks.source.storage.additem(sd, item_data, amount); + retVal___ = HPMHooks.source.storage.additem(sd, stor, item_data, amount); } if (HPMHooks.count.HP_storage_additem_post > 0) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct item *item_data, int amount); + int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct storage_data *stor, struct item *item_data, int amount); for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_additem_post; hIndex++) { postHookFunc = HPMHooks.list.HP_storage_additem_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd, item_data, amount); + retVal___ = postHookFunc(retVal___, sd, stor, item_data, amount); } } return retVal___; } -int HP_storage_addfromcart(struct map_session_data *sd, int index, int amount) { +int HP_storage_addfromcart(struct map_session_data *sd, struct storage_data *stor, int index, int amount) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_storage_addfromcart_pre > 0) { - int (*preHookFunc) (struct map_session_data **sd, int *index, int *amount); + int (*preHookFunc) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_addfromcart_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_storage_addfromcart_pre[hIndex].func; - retVal___ = preHookFunc(&sd, &index, &amount); + retVal___ = preHookFunc(&sd, &stor, &index, &amount); } if (*HPMforce_return) { *HPMforce_return = false; @@ -79545,26 +79731,26 @@ int HP_storage_addfromcart(struct map_session_data *sd, int index, int amount) { } } { - retVal___ = HPMHooks.source.storage.addfromcart(sd, index, amount); + retVal___ = HPMHooks.source.storage.addfromcart(sd, stor, index, amount); } if (HPMHooks.count.HP_storage_addfromcart_post > 0) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd, int index, int amount); + int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_addfromcart_post; hIndex++) { postHookFunc = HPMHooks.list.HP_storage_addfromcart_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd, index, amount); + retVal___ = postHookFunc(retVal___, sd, stor, index, amount); } } return retVal___; } -int HP_storage_gettocart(struct map_session_data *sd, int index, int amount) { +int HP_storage_gettocart(struct map_session_data *sd, struct storage_data *stor, int index, int amount) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_storage_gettocart_pre > 0) { - int (*preHookFunc) (struct map_session_data **sd, int *index, int *amount); + int (*preHookFunc) (struct map_session_data **sd, struct storage_data **stor, int *index, int *amount); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_gettocart_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_storage_gettocart_pre[hIndex].func; - retVal___ = preHookFunc(&sd, &index, &amount); + retVal___ = preHookFunc(&sd, &stor, &index, &amount); } if (*HPMforce_return) { *HPMforce_return = false; @@ -79572,13 +79758,13 @@ int HP_storage_gettocart(struct map_session_data *sd, int index, int amount) { } } { - retVal___ = HPMHooks.source.storage.gettocart(sd, index, amount); + retVal___ = HPMHooks.source.storage.gettocart(sd, stor, index, amount); } if (HPMHooks.count.HP_storage_gettocart_post > 0) { - int (*postHookFunc) (int retVal___, struct map_session_data *sd, int index, int amount); + int (*postHookFunc) (int retVal___, struct map_session_data *sd, struct storage_data *stor, int index, int amount); for (hIndex = 0; hIndex < HPMHooks.count.HP_storage_gettocart_post; hIndex++) { postHookFunc = HPMHooks.list.HP_storage_gettocart_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd, index, amount); + retVal___ = postHookFunc(retVal___, sd, stor, index, amount); } } return retVal___;