summaryrefslogtreecommitdiff
path: root/src/map/storage.c
diff options
context:
space:
mode:
authorSmokexyz <sagunkho@hotmail.com>2017-04-28 05:57:39 +0800
committerSmokexyz <sagunkho@hotmail.com>2017-05-22 17:55:49 +0800
commite8affc41f106503b530abaa7faa20d6e63b727b8 (patch)
tree4e4418da2e850e9ae89f357d8b396da5ec739ac4 /src/map/storage.c
parent109661e3d5fb4cc6ddde9b32f8c99012c8d17bce (diff)
downloadhercules-e8affc41f106503b530abaa7faa20d6e63b727b8.tar.gz
hercules-e8affc41f106503b530abaa7faa20d6e63b727b8.tar.bz2
hercules-e8affc41f106503b530abaa7faa20d6e63b727b8.tar.xz
hercules-e8affc41f106503b530abaa7faa20d6e63b727b8.zip
Add storage_data reception, parsing and sending to/from the map-server.
Remove loading and saving of storage_data through char.c Re-declaration of structure storage_data as a vector. Re-code of portions in the map-server using storage_data. A new approach is taken by saving the loaded storage data from sql into memory for the duration of the session, thereby removing the need of querying the database to re-load all items everytime a storage save routine is issued from the map-server. Saving of storage items is done through a new function that significantly reduces the number of queries compared to char_memitemdata_tosql(), and therefore run-time speed. This method potentially reduces the number of update and delete queries from MAX_STORAGE (which could be >= 600) times to literally 1. Storage items are stored in a dynamically allocated array and handled accordingly. struct mmo_charstatus size reduces by 34,800 bytes. Update pc_checkitem() with masks for item checks. `sd->state.itemcheck` has been changed to `sd->itemcheck` of type `enum pc_checkitem_types` `battle/items.conf` has been updated to reflect configuration changes. Further updates to assert a successful reception of storage data in related functions.
Diffstat (limited to 'src/map/storage.c')
-rw-r--r--src/map/storage.c207
1 files changed, 136 insertions, 71 deletions
diff --git a/src/map/storage.c b/src/map/storage.c
index aacc7c053..4aefaae96 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -107,6 +107,11 @@ int storage_storageopen(struct map_session_data *sd)
if (sd->state.storage_flag != STORAGE_FLAG_CLOSED)
return 1; //Already open?
+ if (sd->storage.received == false) {
+ clif->message(sd->fd, msg_sd(sd, 27)); // Storage has not been loaded yet.
+ return 1;
+ }
+
if( !pc_can_give_items(sd) ) {
//check is this GM level is allowed to put items to storage
clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
@@ -114,9 +119,13 @@ int storage_storageopen(struct map_session_data *sd)
}
sd->state.storage_flag = STORAGE_FLAG_NORMAL;
- storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
- clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
- clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
+
+ 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));
+ }
+
+ clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE);
return 0;
}
@@ -148,61 +157,76 @@ int compare_item(struct item *a, struct item *b)
*------------------------------------------*/
int storage_additem(struct map_session_data* sd, struct item* item_data, int amount)
{
- struct storage_data* stor;
- struct item_data *data;
+ struct item_data *data = NULL;
+ struct item *it = NULL;
int i;
nullpo_retr(1, sd);
+ Assert_retr(1, sd->storage.received == true);
+
nullpo_retr(1, item_data);
- stor = &sd->status.storage;
- if( item_data->nameid <= 0 || amount <= 0 )
- return 1;
+ Assert_retr(1, item_data->nameid > 0);
+
+ Assert_retr(1, amount > 0);
data = itemdb->search(item_data->nameid);
- if( data->stack.storage && amount > data->stack.amount )
- {// item stack limitation
+ if (data->stack.storage && amount > data->stack.amount) // item stack limitation
return 1;
- }
if (!itemdb_canstore(item_data, pc_get_group_level(sd))) {
//Check if item is storable. [Skotlex]
- clif->message (sd->fd, msg_sd(sd,264)); // This item cannot be stored.
+ clif->message (sd->fd, msg_sd(sd, 264)); // This item cannot be stored.
return 1;
}
- if( item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd) ) {
- clif->message(sd->fd, msg_sd(sd,294)); // This bound item cannot be stored there.
+ if (item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd)) {
+ clif->message(sd->fd, msg_sd(sd, 294)); // This bound item cannot be stored there.
return 1;
}
- if( itemdb->isstackable2(data) )
- {//Stackable
- for( i = 0; i < MAX_STORAGE; i++ )
- {
- if( compare_item(&stor->items[i], item_data) )
- {// existing items found, stack them
- if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) )
+ if (itemdb->isstackable2(data)) {//Stackable
+ for (i = 0; i < VECTOR_LENGTH(sd->storage.item); i++) {
+ it = &VECTOR_INDEX(sd->storage.item, i);
+
+ if (it->nameid == 0)
+ continue;
+
+ if (compare_item(it, item_data)) { // existing items found, stack them
+ if (amount > MAX_AMOUNT - it->amount || (data->stack.storage && amount > data->stack.amount - it->amount))
return 1;
- stor->items[i].amount += amount;
- clif->storageitemadded(sd,&stor->items[i],i,amount);
+ it->amount += amount;
+
+ clif->storageitemadded(sd, it, i, amount);
+
return 0;
}
}
}
- // find free slot
- ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 );
- if( i >= MAX_STORAGE )
+ // Check if storage exceeds limit.
+ if (sd->storage.aggregate >= MAX_STORAGE)
return 1;
- // add item to slot
- memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
- stor->storage_amount++;
- stor->items[i].amount = amount;
- clif->storageitemadded(sd,&stor->items[i],i,amount);
- clif->updatestorageamount(sd, stor->storage_amount, MAX_STORAGE);
+ ARR_FIND(0, VECTOR_LENGTH(sd->storage.item), i, VECTOR_INDEX(sd->storage.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);
+ } else {
+ it = &VECTOR_INDEX(sd->storage.item, i);
+ *it = *item_data;
+ }
+
+ sd->storage.aggregate++;
+
+ clif->storageitemadded(sd, it, i, amount);
+
+ clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE);
+
+ sd->storage.save = true; // set a save flag.
return 0;
}
@@ -212,21 +236,32 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo
*------------------------------------------*/
int storage_delitem(struct map_session_data* sd, int n, int amount)
{
+ struct item *it = NULL;
+
nullpo_retr(1, sd);
- Assert_retr(1, n >= 0 && n < MAX_STORAGE);
- if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount )
- return 1;
- sd->status.storage.items[n].amount -= amount;
- if( sd->status.storage.items[n].amount == 0 )
- {
- memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0]));
- sd->status.storage.storage_amount--;
- if( sd->state.storage_flag == STORAGE_FLAG_NORMAL )
- clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
+ 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);
+
+ 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);
}
- if( sd->state.storage_flag == STORAGE_FLAG_NORMAL )
- clif->storageitemremoved(sd,n,amount);
+
+ sd->storage.save = true;
+
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
+ clif->storageitemremoved(sd, n, amount);
+
return 0;
}
@@ -237,23 +272,25 @@ int storage_delitem(struct map_session_data* sd, int n, int amount)
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storageadd(struct map_session_data* sd, int index, int amount)
+int storage_add_from_inventory(struct map_session_data* sd, int index, int amount)
{
nullpo_ret(sd);
- if( sd->status.storage.storage_amount > MAX_STORAGE )
+ Assert_ret(sd->storage.received == true);
+
+ if (sd->storage.aggregate > MAX_STORAGE)
return 0; // storage full
- if( index < 0 || index >= MAX_INVENTORY )
+ if (index < 0 || index >= MAX_INVENTORY)
return 0;
- if( sd->status.inventory[index].nameid <= 0 )
+ if (sd->status.inventory[index].nameid <= 0)
return 0; // No item on that spot
- if( amount < 1 || amount > sd->status.inventory[index].amount )
+ 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, &sd->status.inventory[index], amount) == 0)
pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_STORAGE);
else
clif->dropitem(sd, index, 0);
@@ -268,24 +305,30 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount)
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storageget(struct map_session_data* sd, int index, int amount)
+int storage_add_to_inventory(struct map_session_data* sd, int index, int amount)
{
int flag;
+ struct item *it = NULL;
nullpo_ret(sd);
- if( index < 0 || index >= MAX_STORAGE )
+
+ Assert_ret(sd->storage.received == true);
+
+ if (index < 0 || index >= VECTOR_LENGTH(sd->storage.item))
return 0;
- if( sd->status.storage.items[index].nameid <= 0 )
+ it = &VECTOR_INDEX(sd->storage.item, index);
+
+ if (it->nameid <= 0)
return 0; //Nothing there
- if( amount < 1 || amount > sd->status.storage.items[index].amount )
+ if (amount < 1 || amount > it->amount)
return 0;
- if( (flag = pc->additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 )
- storage->delitem(sd,index,amount);
+ if ((flag = pc->additem(sd, it, amount, LOG_TYPE_STORAGE)) == 0)
+ storage->delitem(sd, index, amount);
else
- clif->additem(sd,0,0,flag);
+ clif->additem(sd, 0, 0, flag);
return 1;
}
@@ -301,19 +344,21 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
{
nullpo_ret(sd);
- if( sd->status.storage.storage_amount > MAX_STORAGE )
+ Assert_ret(sd->storage.received == true);
+
+ if (sd->storage.aggregate > MAX_STORAGE)
return 0; // storage full / storage closed
- if( index < 0 || index >= MAX_CART )
+ if (index < 0 || index >= MAX_CART)
return 0;
if( sd->status.cart[index].nameid <= 0 )
return 0; //No item there.
- if( amount < 1 || amount > sd->status.cart[index].amount )
+ if (amount < 1 || amount > sd->status.cart[index].amount)
return 0;
- if( storage->additem(sd,&sd->status.cart[index],amount) == 0 )
+ if (storage->additem(sd,&sd->status.cart[index],amount) == 0)
pc->cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE);
return 1;
@@ -329,22 +374,28 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
{
int flag = 0;
+ struct item *it = NULL;
+
nullpo_ret(sd);
- if( index < 0 || index >= MAX_STORAGE )
+ Assert_ret(sd->storage.received == true);
+
+ if (index < 0 || index >= VECTOR_LENGTH(sd->storage.item))
return 0;
- if( sd->status.storage.items[index].nameid <= 0 )
+ it = &VECTOR_INDEX(sd->storage.item, index);
+
+ if (it->nameid <= 0)
return 0; //Nothing there.
- if( amount < 1 || amount > sd->status.storage.items[index].amount )
+ if (amount < 1 || amount > it->amount)
return 0;
- if( (flag = pc->cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 )
- storage->delitem(sd,index,amount);
+ if ((flag = pc->cart_additem(sd, it, amount, LOG_TYPE_STORAGE)) == 0)
+ storage->delitem(sd, index, amount);
else {
clif->dropitem(sd, index,0);
- clif->cart_additem_ack(sd,flag == 1?0x0:0x1);
+ clif->cart_additem_ack(sd, flag == 1?0x0:0x1);
}
return 1;
@@ -356,12 +407,26 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
*------------------------------------------*/
void storage_storageclose(struct map_session_data* sd)
{
+ int i = 0;
+
nullpo_retv(sd);
+ Assert_retv(sd->storage.received == true);
+
clif->storageclose(sd);
- if( map->save_settings&4 )
- chrif->save(sd,0); //Invokes the storage saving as well.
+ if (map->save_settings & 4)
+ chrif->save(sd, 0); //Invokes the storage saving as well.
+
+ /* 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);
+ } else {
+ i++;
+ }
+ }
sd->state.storage_flag = STORAGE_FLAG_CLOSED;
}
@@ -791,8 +856,8 @@ void storage_defaults(void)
/* */
storage->delitem = storage_delitem;
storage->open = storage_storageopen;
- storage->add = storage_storageadd;
- storage->get = storage_storageget;
+ storage->add = storage_add_from_inventory;
+ storage->get = storage_add_to_inventory;
storage->additem = storage_additem;
storage->addfromcart = storage_storageaddfromcart;
storage->gettocart = storage_storagegettocart;