From 8a75e79e2ff4ce907195417a3dd6ba90d570f4c1 Mon Sep 17 00:00:00 2001 From: smokexyz Date: Sun, 4 Jun 2017 21:57:08 +0800 Subject: [PATCH 01/12] Add SQL Files for HUSS. --- sql-files/main.sql | 2 ++ sql-files/upgrades/2017-06-03--10-52.sql | 23 +++++++++++++++++++++++ sql-files/upgrades/index.txt | 1 + 3 files changed, 26 insertions(+) create mode 100644 sql-files/upgrades/2017-06-03--10-52.sql 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 From cffd471ebb2df43769ee9d6c84eb4790fe49fa17 Mon Sep 17 00:00:00 2001 From: smokexyz Date: Sun, 4 Jun 2017 23:15:21 +0800 Subject: [PATCH 02/12] Update messages.conf with relevant messages to HUSS. --- conf/messages.conf | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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. From a3e731db0e4999dfeb8a9c566377f3bb237a357d Mon Sep 17 00:00:00 2001 From: smokexyz Date: Sun, 4 Jun 2017 23:17:26 +0800 Subject: [PATCH 03/12] Add storage.conf --- conf/map/storage.conf | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 conf/map/storage.conf diff --git a/conf/map/storage.conf b/conf/map/storage.conf new file mode 100644 index 00000000000..087e0649f33 --- /dev/null +++ b/conf/map/storage.conf @@ -0,0 +1,52 @@ +//================= Hercules Database ========================================== +//= _ _ _ +//= | | | | | | +//= | |_| | ___ _ __ ___ _ _| | ___ ___ +//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __| +//= | | | | __/ | | (__| |_| | | __/\__ \ +//= \_| |_/\___|_| \___|\__,_|_|\___||___/ +//================= License ==================================================== +//= This file is part of Hercules. +//= http://herc.ws - http://github.com/HerculesWS/Hercules +//= +//= Copyright (C) 2014-2017 Hercules Dev Team +//= Copyright (C) 2017 Smokexyz +//= +//= 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 . +//============================================================================== +//= 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 +}, +) From 3e4cf637dfc590742e18afd3380143646580abb5 Mon Sep 17 00:00:00 2001 From: smokexyz Date: Sun, 4 Jun 2017 23:19:30 +0800 Subject: [PATCH 04/12] Add main storage type to constants.md --- db/constants.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/db/constants.conf b/db/constants.conf index eda877671f0..545bd7c0707 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -3872,4 +3872,7 @@ constants_db: { UDT_STATADD: 54 UDT_ROBE: 55 UDT_BODY2: 56 + + comment__: "Storage Types" + STORAGE_TYPE_MAIN: 1 } From 4fc182d27c85b9df6cb055bd9dd9fa122ca1cabf Mon Sep 17 00:00:00 2001 From: smokexyz Date: Sun, 4 Jun 2017 23:41:22 +0800 Subject: [PATCH 05/12] Implementation of the Hercules Ultimate Storage System Storages can now be created through a configuration file that describes their attributes. Example storage configuration: ``` { 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. } ``` Additional storages are handled with dynamic arrays that will save a tonne of memory when created. They are saved in the same storage database (SQL) as the original. An infinite number of storages can be created, there are no limits. The current design implementation only allow saving/loading of approximately 1600 items per storage due to packet size limits. PS. Make sure you apply SQL upgrades for this patch! --- src/char/int_storage.c | 101 +++++++----- src/char/int_storage.h | 4 +- src/char/inter.c | 2 +- src/char/mapif.c | 4 +- src/char/mapif.h | 4 +- src/common/mmo.h | 8 + src/map/atcommand.c | 123 ++++++++++++--- src/map/chrif.c | 19 ++- src/map/clif.c | 77 ++++++--- src/map/intif.c | 72 +++++---- src/map/intif.h | 4 +- src/map/map.c | 20 +++ src/map/map.h | 1 + src/map/pc.c | 35 +++-- src/map/pc.h | 8 +- src/map/script.c | 21 ++- src/map/skill.c | 12 +- src/map/storage.c | 350 ++++++++++++++++++++++++++++++++--------- src/map/storage.h | 33 +++- src/map/unit.c | 10 +- 20 files changed, 680 insertions(+), 228 deletions(-) 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/mmo.h b/src/common/mmo.h index 7fd4ca6ea82..99a95c8637a 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -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..f5cd5a5ffef 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -850,15 +850,48 @@ 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. + stor = storage->ensure(sd, storage_id); + + 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 +5184,43 @@ 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. + stor = storage->ensure(sd, storage_id); 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 +5228,66 @@ 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; } - if (sd->storage.received == false) { + sd->storage.access = STORAGE_ACCESS_ALL; // Default storage access for atcommands. + stor = storage->ensure(sd, storage_id); + + 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 +8128,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 +8139,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 +9775,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..60cb3a68640 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,24 @@ 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; + + stor = storage->ensure(sd, sd->storage.current); + + 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 +8679,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 +12009,7 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) { int item_index, item_amount; + if (pc_istrading(sd)) return; @@ -11998,10 +12018,12 @@ 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); + 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 +12035,16 @@ 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); + 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 +12052,18 @@ 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); + 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 +12071,18 @@ 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); + 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..8266fb617cb 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,75 @@ 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) { + stor = storage->ensure(sd, RFIFOW(fd, 8)); + + 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); + stor = storage->ensure(sd, storage_id); + // 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 +555,32 @@ 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. + stor = storage->ensure(sd, storage_id); + + stor->save = false; // Storage has been saved. } //================================================================= @@ -2750,7 +2768,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..f1c78e45818 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10477,16 +10477,31 @@ BUILDIN(gettimestr) BUILDIN(openstorage) { struct map_session_data *sd = script->rid2sd(st); + 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; + if (sd == NULL) 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; + } + + stor = storage->ensure(sd, storage_id); + + 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 +24127,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..1d0e988d0d2 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 = storage->get_settings(stor->uid); + nullpo_ret(sd); + nullpo_ret(stst); - if (sd->state.storage_flag != STORAGE_FLAG_CLOSED) - return 1; //Already open? + Assert_ret(stor->received == true); // Assert the availability of data. - if (sd->storage.received == false) { - clif->message(sd->fd, msg_sd(sd, 27)); // Storage has not been loaded yet. - return 1; - } + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED) + 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,19 @@ 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 = storage->get_settings(stor->uid); 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); - - Assert_retr(1, amount > 0); + nullpo_retr(1, stst); // Assert existence of storage configuration. + Assert_retr(1, stor->received == true); // Assert the availability of the storage. + 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 quantity of item. data = itemdb->search(item_data->nameid); @@ -186,8 +255,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 +268,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 +306,29 @@ 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) { + const struct storage_settings *stst = storage->get_settings(stor->uid); struct item *it = NULL; nullpo_retr(1, sd); + Assert_retr(1, stst); + Assert_retr(1, stor->received == true); + 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 +343,17 @@ 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 = storage->get_settings(stor->uid); + nullpo_ret(sd); + nullpo_ret(stst); + nullpo_ret(stor); - Assert_ret(sd->storage.received == true); + Assert_ret(stor->received == true); - if (sd->storage.aggregate > MAX_STORAGE) + if (stor->aggregate >= stst->capacity) return 0; // storage full if (index < 0 || index >= MAX_INVENTORY) @@ -294,7 +365,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 +380,20 @@ 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(sd->storage.received == true); + Assert_ret(stor->received == true); - 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 +402,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 +416,30 @@ 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 = storage->get_settings(stor->uid); + nullpo_ret(sd); + nullpo_ret(stst); + nullpo_ret(stor); - Assert_ret(sd->storage.received == true); + Assert_ret(stor->received == true); - if (sd->storage.aggregate > MAX_STORAGE) + 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 +451,19 @@ 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); - Assert_ret(sd->storage.received == true); + Assert_ret(stor->received == true); - 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 +472,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 +488,11 @@ 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); + curr_stor = storage->ensure(sd, sd->storage.current); clif->storageclose(sd); @@ -424,15 +501,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 +919,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 +1056,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; From 0892d558a94fdd165ed1f9667e612fcc769d2bfe Mon Sep 17 00:00:00 2001 From: smokexyz Date: Sun, 4 Jun 2017 23:58:18 +0800 Subject: [PATCH 06/12] Add storage access modes. Added support for storage modes: STORAGE_ACCESS_VIEW STORAGE_ACCESS_GET STORAGE_ACCESS_PUT STORAGE_ACCESS_ALL --- src/map/storage.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/map/storage.c b/src/map/storage.c index 1d0e988d0d2..9bbd4bbf69b 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -353,6 +353,12 @@ int storage_add_from_inventory(struct map_session_data* sd, struct storage_data Assert_ret(stor->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 (stor->aggregate >= stst->capacity) return 0; // storage full @@ -390,6 +396,9 @@ int storage_add_to_inventory(struct map_session_data* sd, struct storage_data *s Assert_ret(stor->received == true); + if ((sd->storage.access & STORAGE_ACCESS_GET) == 0) + return 0; + if (index < 0 || index >= VECTOR_LENGTH(stor->item)) return 0; @@ -426,6 +435,13 @@ int storage_storageaddfromcart(struct map_session_data* sd, struct storage_data Assert_ret(stor->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 (stor->aggregate >= stst->capacity) return 0; // storage full / storage closed @@ -460,6 +476,9 @@ int storage_storagegettocart(struct map_session_data* sd, struct storage_data *s Assert_ret(stor->received == true); + if ((sd->storage.access & STORAGE_ACCESS_GET) == 0) + return 0; + if (index < 0 || index >= VECTOR_LENGTH(stor->item)) return 0; From 191acf31ecb65880d9fae4b3f0b8f8adcd62c3d3 Mon Sep 17 00:00:00 2001 From: smokexyz Date: Mon, 5 Jun 2017 00:01:33 +0800 Subject: [PATCH 07/12] Added Storage modes to constants.conf --- db/constants.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/db/constants.conf b/db/constants.conf index 545bd7c0707..05598be6fdd 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -3875,4 +3875,10 @@ constants_db: { 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 } From 47630a87caac4b3b66915bb52ec28e0a1fd717a1 Mon Sep 17 00:00:00 2001 From: smokexyz Date: Sun, 4 Jun 2017 23:42:54 +0800 Subject: [PATCH 08/12] HPM Hook Update & Hercules.xcodeproj update --- Hercules.xcodeproj/project.pbxproj | 4 +- .../xcschemes/HPMHooking_char.xcscheme | 2 +- .../xcschemes/HPMHooking_login.xcscheme | 2 +- .../xcschemes/HPMHooking_map.xcscheme | 2 +- .../xcschemes/char-server.xcscheme | 2 +- .../xcshareddata/xcschemes/db2sql.xcscheme | 2 +- .../xcschemes/login-server.xcscheme | 2 +- .../xcschemes/map-server.xcscheme | 2 +- .../xcshareddata/xcschemes/mapcache.xcscheme | 2 +- .../xcshareddata/xcschemes/sample.xcscheme | 2 +- src/common/HPMDataCheck.h | 1 + src/common/mmo.h | 2 +- src/plugins/HPMHooking/HPMHooking.Defs.inc | 66 ++-- .../HPMHooking/HPMHooking_char.Hooks.inc | 48 +-- .../HPMHooking_map.HPMHooksCore.inc | 28 ++ .../HPMHooking_map.HookingPoints.inc | 7 + .../HPMHooking/HPMHooking_map.Hooks.inc | 294 ++++++++++++++---- 17 files changed, 353 insertions(+), 115 deletions(-) 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 @@ 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___; From 0c2f8d811f01b3d7c06cb85136a3c174445d7bdb Mon Sep 17 00:00:00 2001 From: smokexyz Date: Mon, 5 Jun 2017 00:13:09 +0800 Subject: [PATCH 09/12] Updated doc/script_commands.txt --- doc/script_commands.txt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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() From 10b882d9aa89d1710a7a01a51359f88d71b2ae57 Mon Sep 17 00:00:00 2001 From: smokexyz Date: Mon, 5 Jun 2017 00:36:26 +0800 Subject: [PATCH 10/12] Removed storagelist command from groups.conf TODO List :) --- conf/groups.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/conf/groups.conf b/conf/groups.conf index 3f0c34ffba9..12d39ed4a65 100644 --- a/conf/groups.conf +++ b/conf/groups.conf @@ -234,7 +234,6 @@ groups: ( jail: true jailfor: true mute: true - storagelist: true cartlist: true itemlist: true stats: true From 30359079640b0e7060f7f6221c82277925f9f3f4 Mon Sep 17 00:00:00 2001 From: smokexyz Date: Mon, 5 Jun 2017 22:09:35 +0800 Subject: [PATCH 11/12] Updated scripts to comply with HUSS. --- npc/custom/etc/quest_warper.txt | 2 +- npc/kafras/functions_kafras.txt | 2 +- npc/kafras/kafras.txt | 2 +- npc/other/CashShop_Functions.txt | 2 +- npc/quests/quests_13_1.txt | 6 +++--- npc/quests/quests_13_2.txt | 6 +++--- npc/re/cities/mora.txt | 2 +- npc/re/jobs/novice/academy.txt | 2 +- npc/re/other/dimensional_gap.txt | 2 +- npc/re/quests/eden/eden_service.txt | 2 +- npc/re/quests/quests_dicastes.txt | 2 +- npc/re/quests/quests_malangdo.txt | 2 +- npc/woe-fe/agit_main.txt | 2 +- npc/woe-se/agit_main_se.txt | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) 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]"; From e82ebd0e40bbe1aa285f9e30411ca1ae1431d860 Mon Sep 17 00:00:00 2001 From: Smokexyz Date: Tue, 26 Dec 2017 13:55:51 +0800 Subject: [PATCH 12/12] Followup with review edits. --- src/map/atcommand.c | 18 +++++++++++++++--- src/map/clif.c | 16 +++++++++++----- src/map/intif.c | 9 ++++++--- src/map/script.c | 9 ++++++--- src/map/storage.c | 32 +++++++++++++++++--------------- 5 files changed, 55 insertions(+), 29 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index f5cd5a5ffef..eeb171e204b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -873,7 +873,11 @@ ACMD(storage) } sd->storage.access = STORAGE_ACCESS_ALL; // Default storage access for atcommands. - stor = storage->ensure(sd, storage_id); + + 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); @@ -5208,7 +5212,11 @@ ACMD(storeall) } sd->storage.access = STORAGE_ACCESS_ALL; // Default storage access for atcommands. - stor = storage->ensure(sd, storage_id); + + 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. @@ -5270,7 +5278,11 @@ ACMD(clearstorage) } sd->storage.access = STORAGE_ACCESS_ALL; // Default storage access for atcommands. - stor = storage->ensure(sd, storage_id); + + 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 (stor->received == false) { clif->message(fd, msg_fd(fd, 27)); // "Storage has not been loaded yet" diff --git a/src/map/clif.c b/src/map/clif.c index 60cb3a68640..c43e268a0f1 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -8594,7 +8594,9 @@ void clif_refresh_storagewindow(struct map_session_data *sd) if (stst == NULL) return; - stor = storage->ensure(sd, sd->storage.current); + if ((stor = storage->ensure(sd, sd->storage.current)) == NULL) { + return; + } if (stor->aggregate > 0) { storage->sortitem(VECTOR_DATA(stor->item), VECTOR_LENGTH(stor->item)); @@ -12020,7 +12022,8 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { struct storage_data *stor = storage->ensure(sd, sd->storage.current); - storage->add(sd, stor, item_index, item_amount); + 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); } @@ -12041,7 +12044,8 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { struct storage_data *stor = storage->ensure(sd, sd->storage.current); - storage->get(sd, stor, item_index, item_amount); + 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); } @@ -12060,7 +12064,8 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { struct storage_data *stor = storage->ensure(sd, sd->storage.current); - storage->addfromcart(sd, stor, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); + 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)); } @@ -12079,7 +12084,8 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { struct storage_data *stor = storage->ensure(sd, sd->storage.current); - storage->gettocart(sd, stor, RFIFOW(fd,2)-1, RFIFOL(fd,4)); + 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)); } diff --git a/src/map/intif.c b/src/map/intif.c index 8266fb617cb..d30f7af26d2 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -489,7 +489,8 @@ void intif_parse_account_storage(int fd) return; } - stor = storage->ensure(sd, RFIFOW(fd, 8)); + 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"); @@ -525,7 +526,8 @@ void intif_send_account_storage(struct map_session_data *sd, int storage_id) nullpo_retv(sd); - stor = storage->ensure(sd, storage_id); + if ((stor = storage->ensure(sd, storage_id)) == NULL) + return; // Assert that at this point in the code, both flags are true. Assert_retv(stor->save == true); @@ -578,7 +580,8 @@ void intif_parse_account_storage_save_ack(int fd) return; } - stor = storage->ensure(sd, storage_id); + if ((stor = storage->ensure(sd, storage_id)) == NULL) + return; stor->save = false; // Storage has been saved. } diff --git a/src/map/script.c b/src/map/script.c index f1c78e45818..dee0170da22 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10482,16 +10482,19 @@ BUILDIN(openstorage) struct storage_data *stor = NULL; const struct storage_settings *stst = NULL; - if (sd == 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 ((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; } - - stor = storage->ensure(sd, storage_id); if (stor->received == false) { script_pushint(st, 0); diff --git a/src/map/storage.c b/src/map/storage.c index 9bbd4bbf69b..bb8bc8e4ee5 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -167,12 +167,12 @@ const struct storage_settings *storage_get_settings(int storage_id) *------------------------------------------*/ int storage_storageopen(struct map_session_data *sd, struct storage_data *stor) { - const struct storage_settings *stst = storage->get_settings(stor->uid); + const struct storage_settings *stst = NULL; nullpo_ret(sd); - nullpo_ret(stst); - + 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; // Storage is already open. @@ -228,14 +228,16 @@ int storage_additem(struct map_session_data* sd, struct storage_data *stor, stru { struct item_data *data = NULL; struct item *it = NULL; - const struct storage_settings *stst = storage->get_settings(stor->uid); + const struct storage_settings *stst = NULL; int i; nullpo_retr(1, sd); - nullpo_retr(1, stst); // Assert existence of storage configuration. + 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 quantity of item. data = itemdb->search(item_data->nameid); @@ -308,12 +310,13 @@ int storage_additem(struct map_session_data* sd, struct storage_data *stor, stru *------------------------------------------*/ int storage_delitem(struct map_session_data* sd, struct storage_data *stor, int n, int amount) { - const struct storage_settings *stst = storage->get_settings(stor->uid); struct item *it = NULL; + const struct storage_settings *stst = NULL; nullpo_retr(1, sd); - Assert_retr(1, stst); + 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)); it = &VECTOR_INDEX(stor->item, n); @@ -345,13 +348,12 @@ int storage_delitem(struct map_session_data* sd, struct storage_data *stor, int *------------------------------------------*/ int storage_add_from_inventory(struct map_session_data* sd, struct storage_data *stor, int index, int amount) { - const struct storage_settings *stst = storage->get_settings(stor->uid); + const struct storage_settings *stst = NULL; nullpo_ret(sd); - nullpo_ret(stst); nullpo_ret(stor); - Assert_ret(stor->received == true); + nullpo_ret(stst = storage->get_settings(stor->uid)); if ((sd->storage.access & STORAGE_ACCESS_PUT) == 0) { clif->delitem(sd, index, amount, DELITEM_NORMAL); @@ -427,13 +429,12 @@ int storage_add_to_inventory(struct map_session_data* sd, struct storage_data *s *------------------------------------------*/ int storage_storageaddfromcart(struct map_session_data* sd, struct storage_data *stor, int index, int amount) { - const struct storage_settings *stst = storage->get_settings(stor->uid); + const struct storage_settings *stst = NULL; nullpo_ret(sd); - nullpo_ret(stst); nullpo_ret(stor); - Assert_ret(stor->received == true); + nullpo_ret(stst = storage->get_settings(stor->uid)); if ((sd->storage.access & STORAGE_ACCESS_PUT) == 0) { @@ -473,7 +474,7 @@ int storage_storagegettocart(struct map_session_data* sd, struct storage_data *s struct item *it = NULL; nullpo_ret(sd); - + nullpo_ret(stor); Assert_ret(stor->received == true); if ((sd->storage.access & STORAGE_ACCESS_GET) == 0) @@ -511,7 +512,8 @@ void storage_storageclose(struct map_session_data* sd) nullpo_retv(sd); - curr_stor = storage->ensure(sd, sd->storage.current); + if ((curr_stor = storage->ensure(sd, sd->storage.current)) == NULL) + return; clif->storageclose(sd);