소스 검색

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

Kevin 17 년 전
부모
커밋
26a70ed737
9개의 변경된 파일197개의 추가작업 그리고 28개의 파일을 삭제
  1. 9 0
      Changelog-Trunk.txt
  2. 19 12
      src/map/clif.c
  3. 143 13
      src/map/itemdb.c
  4. 5 0
      src/map/mob.h
  5. 13 0
      src/map/npc.c
  6. 2 0
      src/map/npc.h
  7. 3 2
      src/map/pc.c
  8. 1 1
      src/map/storage.c
  9. 2 0
      src/map/storage.h

+ 9 - 0
Changelog-Trunk.txt

@@ -3,6 +3,15 @@ Date	Added
 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.
 
+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
 	* Added script function hasquest. [Kevin]
 	* Fixed OnGuildBreak. [Kevin]

+ 19 - 12
src/map/clif.c

@@ -1894,20 +1894,27 @@ void clif_storagelist(struct map_session_data *sd,struct storage *stor)
 		if(stor->storage_[i].nameid<=0)
 			continue;
 		id = itemdb_search(stor->storage_[i].nameid);
-		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(!id)
+		{
+			//Item not found, was probably deleted and then map server reloaded/item db reloaded
+			storage_delitem(sd, stor, i, stor->storage_[i].amount);
+			return;
+		}
+		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]);
+				clif_addcards(WBUFP(buf,n*s+14), &stor->storage_[i]);
 #endif
-			n++;
-		}
+				n++;
+			}
 	}
 	if(n){
 #if PACKETVER < 5

+ 143 - 13
src/map/itemdb.c

@@ -10,6 +10,10 @@
 #include "battle.h" // struct battle_config
 #include "script.h" // item script processing
 #include "pc.h"     // W_MUSICAL, W_WHIP
+#include "storage.h"
+#include "npc.h"
+#include "clif.h"
+#include "mob.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -1008,6 +1012,22 @@ static void destroy_item_data(struct item_data* self, int free_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)
 {
 	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;
 }
 
-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)
-		destroy_item_data(id, 1);
+	if(nd->subtype != SHOP && nd->subtype != CASHSHOP)
+		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;
 }
 
-void itemdb_reload(void)
+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;
 
-	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
-		if( itemdb_array[i] )
-			if( itemdb_array[i]->flag.db2 )
+	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++)
 			{
-				destroy_item_data(itemdb_array[i], 1);
-				memset(itemdb_array[i], 0, sizeof(struct item_data));
+				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);
 			}
+		}
+	}
 
-	itemdb_other->clear(itemdb_other, itemdb_reload_sub);
+	return 0;
+}
 
-	itemdb_read();
+//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)
+{
+
+	do_final_itemdb();
+	do_init_itemdb();
+
+	//Update ALL items on the server
+	map_foreachpc(itemdb_reload_check);
+	npc_foreach(itemdb_reload_check_npc);
+	itemdb_foreach_mobdb();
 }
 
 void do_final_itemdb(void)

+ 5 - 0
src/map/mob.h

@@ -83,6 +83,11 @@ struct mob_db {
 	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 block_list bl;
 	struct unit_data  ud;

+ 13 - 0
src/map/npc.c

@@ -150,6 +150,19 @@ struct npc_data* npc_name2id(const char* 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);
+}
+
 /*==========================================
  * イベントキューのイベント処理
  *------------------------------------------*/

+ 2 - 0
src/map/npc.h

@@ -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);
 
+void npc_foreach(int (*func)(DBKey,void*,va_list), ...);
+
 extern struct npc_data* fake_nd;
 
 #endif /* _NPC_H_ */

+ 3 - 2
src/map/pc.c

@@ -2965,11 +2965,12 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type)
 {
 	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;
 
 	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].equip)
 			pc_unequipitem(sd,n,3);

+ 1 - 1
src/map/storage.c

@@ -224,7 +224,7 @@ static int storage_additem(struct map_session_data *sd,struct storage *stor,stru
 /*==========================================
  * 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)

+ 2 - 0
src/map/storage.h

@@ -11,9 +11,11 @@ struct item;
 //#include "map.h"
 struct map_session_data;
 
+struct storage *account2storage2(int account_id);
 int storage_storageopen(struct map_session_data *sd);
 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_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_storagegettocart(struct map_session_data *sd,int index,int amount);
 int storage_storageclose(struct map_session_data *sd);