Some major changes to @reloaditemdb to allow unloading of any item while map server is running.

- Delete any item from inventory/cart/open storages that went missing during the reload.
- Delete item from any shop that has this item.
- Refresh item screen for anyone who has a shop open.
- Delete mob db drop table references.
- Delete item from storage during load if it isn't in the item db.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12661 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
Kevin 2008-04-27 07:18:21 +00:00
parent 2eabb3d1f7
commit 26a70ed737
9 changed files with 201 additions and 32 deletions

View File

@ -3,6 +3,15 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2008/04/27
* Some major changes to @reloaditemdb to allow unloading of any item
while map server is running.
- Delete any item from inventory/cart/open storages that went missing
during the reload.
- Delete item from any shop that has this item.
- Refresh item screen for anyone who has a shop open.
- Delete mob db drop table references.
- Delete item from storage during load if it isn't in the item db. [Kevin]
2008/04/26 2008/04/26
* Added script function hasquest. [Kevin] * Added script function hasquest. [Kevin]
* Fixed OnGuildBreak. [Kevin] * Fixed OnGuildBreak. [Kevin]

View File

@ -1894,20 +1894,27 @@ void clif_storagelist(struct map_session_data *sd,struct storage *stor)
if(stor->storage_[i].nameid<=0) if(stor->storage_[i].nameid<=0)
continue; continue;
id = itemdb_search(stor->storage_[i].nameid); id = itemdb_search(stor->storage_[i].nameid);
if(!itemdb_isstackable2(id)) if(!id)
{ //Equippable {
WBUFW(bufe,ne*20+4)=i+1; //Item not found, was probably deleted and then map server reloaded/item db reloaded
clif_item_sub(bufe, ne*20+6, &stor->storage_[i], id, id->equip); storage_delitem(sd, stor, i, stor->storage_[i].amount);
clif_addcards(WBUFP(bufe, ne*20+16), &stor->storage_[i]); return;
ne++;
} else { //Stackable
WBUFW(buf,n*s+4)=i+1;
clif_item_sub(buf, n*s+6, &stor->storage_[i], id,-1);
#if PACKETVER >= 5
clif_addcards(WBUFP(buf,n*s+14), &stor->storage_[i]);
#endif
n++;
} }
else
if(!itemdb_isstackable2(id))
{ //Equippable
WBUFW(bufe,ne*20+4)=i+1;
clif_item_sub(bufe, ne*20+6, &stor->storage_[i], id, id->equip);
clif_addcards(WBUFP(bufe, ne*20+16), &stor->storage_[i]);
ne++;
} else { //Stackable
WBUFW(buf,n*s+4)=i+1;
clif_item_sub(buf, n*s+6, &stor->storage_[i], id,-1);
#if PACKETVER >= 5
clif_addcards(WBUFP(buf,n*s+14), &stor->storage_[i]);
#endif
n++;
}
} }
if(n){ if(n){
#if PACKETVER < 5 #if PACKETVER < 5

View File

@ -10,6 +10,10 @@
#include "battle.h" // struct battle_config #include "battle.h" // struct battle_config
#include "script.h" // item script processing #include "script.h" // item script processing
#include "pc.h" // W_MUSICAL, W_WHIP #include "pc.h" // W_MUSICAL, W_WHIP
#include "storage.h"
#include "npc.h"
#include "clif.h"
#include "mob.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -1008,6 +1012,22 @@ static void destroy_item_data(struct item_data* self, int free_self)
aFree(self); aFree(self);
} }
/*==========================================
* Looks for an item, returns NULL if not found
*------------------------------------------*/
struct item_data* itemdb_search2(int nameid)
{
if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
{
DBKey key;
if( itemdb_array[nameid] )
return itemdb_array[nameid];
key.i = nameid;
return NULL;
}
return (struct item_data*)idb_get(itemdb_other,nameid);
}
static int itemdb_final_sub(DBKey key,void *data,va_list ap) static int itemdb_final_sub(DBKey key,void *data,va_list ap)
{ {
struct item_data *id = (struct item_data *)data; struct item_data *id = (struct item_data *)data;
@ -1018,32 +1038,142 @@ static int itemdb_final_sub(DBKey key,void *data,va_list ap)
return 0; return 0;
} }
static int itemdb_reload_sub(DBKey key,void *data,va_list ap) int itemdb_reload_check_npc(DBKey key,void * data,va_list ap)
{ {
struct item_data *id = (struct item_data *)data; struct npc_data * nd = (struct npc_data *)data;
int offset = 0, i = 0;
if( id != &dummy_item && id->flag.db2) if(nd->subtype != SHOP && nd->subtype != CASHSHOP)
destroy_item_data(id, 1); return 0;
while(i < nd->u.shop.count)
{
if(itemdb_search2(nd->u.shop.shop_item[i].nameid) == NULL)
{
nd->u.shop.count--;
//Shift array to left, overwriting old data
for(offset = i; offset+1 < nd->u.shop.count; offset++);
{
nd->u.shop.shop_item[offset].nameid = nd->u.shop.shop_item[offset+1].nameid;
nd->u.shop.shop_item[offset].value = nd->u.shop.shop_item[offset+1].value;
}
}
//increment counter if we didn't delete something
else
i++;
}
//Resize array
RECREATE(nd->u.shop.shop_item, struct npc_item_list, nd->u.shop.count);
return 0; return 0;
} }
static int itemdb_reload_check(DBKey key,void *data,va_list ap)
{
int i;
struct map_session_data *sd = (struct map_session_data *)data;
struct storage * stor;
struct item_data * id;
struct npc_data * nd;
if(sd->npc_shopid)
{
nd = (struct npc_data*)map_id2bl(sd->npc_shopid);
clif_buylist(sd, nd);
}
//First, handle all items in inventories/equiped, cart, and storage
for(i = 0; i < MAX_INVENTORY; i++)
{
if(!sd->status.inventory[i].nameid)
continue;
id = itemdb_search2(sd->status.inventory[i].nameid);
if(id == NULL)
{
sd->inventory_data[i] = NULL;
pc_delitem(sd, i, sd->status.inventory[i].amount, 4);
}
else
{
sd->inventory_data[i] = id;
}
}
//Delete nonexistant items from cart
for(i = 0; i < MAX_CART; i++)
{
if(!sd->status.cart[i].nameid)
continue;
id = itemdb_search2(sd->status.cart[i].nameid);
if(id == NULL)
{
sd->inventory_data[i] = NULL;
pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0);
}
}
//Delete storage
if(stor = account2storage2(sd->status.account_id))
{
//If storage isn't found, it will be deleted whenever storage is loaded again
if(stor)
{
for(i = 0; i < MAX_STORAGE; i++)
{
if(!sd->status.inventory[i].nameid)
continue;
if(itemdb_search2(sd->status.inventory[i].nameid) == NULL)
storage_delitem(sd, stor, i, stor->storage_[i].amount);
}
}
}
return 0;
}
//Cleanup mob db drop tables
void itemdb_foreach_mobdb(void)
{
int i = 0, j = 0;
struct item_data * id;
s_mob_db * mdb;
for(i=0; i < MAX_MOB_DB; i++)
{
mdb = mob_db(i);
if(mdb == mob_dummy)
continue;
for(j=0; j < MAX_MOB_DROP; j++)
{
id = itemdb_search2(mdb->dropitem[j].nameid);
if(id == NULL)
{
mdb->dropitem[j].nameid = 0;
mdb->dropitem[j].p = 0;
}
}
}
}
void itemdb_reload(void) void itemdb_reload(void)
{ {
int i; do_final_itemdb();
do_init_itemdb();
for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) //Update ALL items on the server
if( itemdb_array[i] ) map_foreachpc(itemdb_reload_check);
if( itemdb_array[i]->flag.db2 ) npc_foreach(itemdb_reload_check_npc);
{ itemdb_foreach_mobdb();
destroy_item_data(itemdb_array[i], 1);
memset(itemdb_array[i], 0, sizeof(struct item_data));
}
itemdb_other->clear(itemdb_other, itemdb_reload_sub);
itemdb_read();
} }
void do_final_itemdb(void) void do_final_itemdb(void)

View File

@ -83,6 +83,11 @@ struct mob_db {
struct spawn_info spawn[10]; struct spawn_info spawn[10];
}; };
typedef struct mob_db s_mob_db;
extern struct mob_db *mob_db_data[MAX_MOB_DB+1];
struct mob_db *mob_db(int index);
extern struct mob_db *mob_dummy;
struct mob_data { struct mob_data {
struct block_list bl; struct block_list bl;
struct unit_data ud; struct unit_data ud;

View File

@ -150,6 +150,19 @@ struct npc_data* npc_name2id(const char* name)
return (struct npc_data *) strdb_get(npcname_db, name); return (struct npc_data *) strdb_get(npcname_db, name);
} }
/*==========================================
* Run function for each npc
*------------------------------------------*/
void npc_foreach(int (*func)(DBKey, void*, va_list), ...)
{
va_list ap;
va_start(ap, func);
npcname_db->vforeach(npcname_db, func, ap);
va_end(ap);
}
/*========================================== /*==========================================
* *
*------------------------------------------*/ *------------------------------------------*/

View File

@ -146,6 +146,8 @@ int npc_script_event(struct map_session_data* sd, enum npce_event type);
int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points); int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points);
void npc_foreach(int (*func)(DBKey,void*,va_list), ...);
extern struct npc_data* fake_nd; extern struct npc_data* fake_nd;
#endif /* _NPC_H_ */ #endif /* _NPC_H_ */

View File

@ -2965,11 +2965,12 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type)
{ {
nullpo_retr(1, sd); nullpo_retr(1, sd);
if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL) if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || (sd->inventory_data[n] == NULL && ~type&4))
return 1; return 1;
sd->status.inventory[n].amount -= amount; sd->status.inventory[n].amount -= amount;
sd->weight -= sd->inventory_data[n]->weight*amount ; if(~type&4)
sd->weight -= sd->inventory_data[n]->weight*amount ;
if(sd->status.inventory[n].amount<=0){ if(sd->status.inventory[n].amount<=0){
if(sd->status.inventory[n].equip) if(sd->status.inventory[n].equip)
pc_unequipitem(sd,n,3); pc_unequipitem(sd,n,3);

View File

@ -224,7 +224,7 @@ static int storage_additem(struct map_session_data *sd,struct storage *stor,stru
/*========================================== /*==========================================
* Internal del-item function * Internal del-item function
*------------------------------------------*/ *------------------------------------------*/
static int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount) int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount)
{ {
if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount) if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount)

View File

@ -11,9 +11,11 @@ struct item;
//#include "map.h" //#include "map.h"
struct map_session_data; struct map_session_data;
struct storage *account2storage2(int account_id);
int storage_storageopen(struct map_session_data *sd); int storage_storageopen(struct map_session_data *sd);
int storage_storageadd(struct map_session_data *sd,int index,int amount); int storage_storageadd(struct map_session_data *sd,int index,int amount);
int storage_storageget(struct map_session_data *sd,int index,int amount); int storage_storageget(struct map_session_data *sd,int index,int amount);
int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount);
int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount); int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount);
int storage_storagegettocart(struct map_session_data *sd,int index,int amount); int storage_storagegettocart(struct map_session_data *sd,int index,int amount);
int storage_storageclose(struct map_session_data *sd); int storage_storageclose(struct map_session_data *sd);