Jelajahi Sumber

Cleaned up CZ_PC_SELL_ITEMLIST and its related functions
* Added a validation check for remaining item amount

Jittapan 2 tahun lalu
induk
melakukan
b28eac7b56
5 mengubah file dengan 34 tambahan dan 21 penghapusan
  1. 4 5
      src/map/clif.cpp
  2. 1 1
      src/map/clif_packetdb.hpp
  3. 16 14
      src/map/npc.cpp
  4. 1 1
      src/map/npc.hpp
  5. 12 0
      src/map/packets.hpp

+ 4 - 5
src/map/clif.cpp

@@ -12295,16 +12295,15 @@ void clif_npc_sell_result(struct map_session_data* sd, unsigned char result)
 void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
 {
 	int fail=0,n;
-	unsigned short *item_list;
 	struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
+	PACKET_CZ_PC_SELL_ITEMLIST* p = reinterpret_cast<PACKET_CZ_PC_SELL_ITEMLIST*>(RFIFOP(fd, 0));
 
-	n = (RFIFOW(fd,info->pos[0])-4) /4; // (pktlen-(cmd+len))/listsize
-	item_list = (unsigned short*)RFIFOP(fd,info->pos[1]);
-
+	n = (p->packetLength - 4) / sizeof(PACKET_CZ_PC_SELL_ITEMLIST_sub); // (pktlen-(cmd+len))/listsize
+	
 	if (sd->state.trading || !sd->npc_shopid)
 		fail = 1;
 	else
-		fail = npc_selllist(sd,n,item_list);
+		fail = npc_selllist(sd, n, p->sellList);
 
 	sd->npc_shopid = 0; //Clear shop data.
 	clif_npc_sell_result(sd, fail);

+ 1 - 1
src/map/clif_packetdb.hpp

@@ -107,7 +107,7 @@
 	packet(0x00c6,-1);
 	packet(0x00c7,-1);
 	parseable_packet(0x00c8,-1,clif_parse_NpcBuyListSend,2,4);
-	parseable_packet(0x00c9,-1,clif_parse_NpcSellListSend,2,4);
+	parseable_packet(HEADER_CZ_PC_SELL_ITEMLIST,-1,clif_parse_NpcSellListSend,2,4);
 	packet(0x00ca,3);
 	packet(0x00cb,3);
 	parseable_packet(0x00cc,6,clif_parse_GMKick,2);

+ 16 - 14
src/map/npc.cpp

@@ -2849,7 +2849,7 @@ e_purchase_result npc_buylist( struct map_session_data* sd, std::vector<s_npc_bu
 }
 
 /// npc_selllist for script-controlled shops
-static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd)
+static int npc_selllist_sub(struct map_session_data* sd, int list_length, PACKET_CZ_PC_SELL_ITEMLIST_sub* item_list, struct npc_data* nd)
 {
 	char npc_ev[EVENT_NAME_LENGTH];
 	char card_slot[NAME_LENGTH];
@@ -2891,12 +2891,12 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
 	}
 
 	// save list of to be sold items
-	for( i = 0; i < n; i++ )
+	for( i = 0; i < list_length; i++ )
 	{
-		int idx = item_list[i * 2] - 2;
+		int idx = item_list[i].index - 2;
 
 		script_setarray_pc( sd, "@sold_nameid", i, sd->inventory.u.items_inventory[idx].nameid, &key_nameid );
-		script_setarray_pc( sd, "@sold_quantity", i, item_list[i*2+1], &key_amount );
+		script_setarray_pc( sd, "@sold_quantity", i, item_list[i].amount, &key_amount );
 
 		if( itemdb_isequip(sd->inventory.u.items_inventory[idx].nameid) )
 		{// process equipment based information into the arrays
@@ -2933,7 +2933,7 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
 ///
 /// @param item_list 'n' pairs <index,amount>
 /// @return result code for clif_parse_NpcSellListSend
-uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list)
+uint8 npc_selllist(struct map_session_data* sd, int list_length, PACKET_CZ_PC_SELL_ITEMLIST_sub* item_list)
 {
 	double z;
 	int i,skill;
@@ -2950,13 +2950,13 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list
 	z = 0;
 
 	// verify the sell list
-	for( i = 0; i < n; i++ )
+	for( i = 0; i < list_length; i++ )
 	{
 		t_itemid nameid;
 		int amount, idx, value;
 
-		idx    = item_list[i*2]-2;
-		amount = item_list[i*2+1];
+		idx    = item_list[i].index - 2;
+		amount = item_list[i].amount;
 
 		if( idx >= MAX_INVENTORY || idx < 0 || amount < 0 )
 		{
@@ -2965,7 +2965,7 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list
 
 		nameid = sd->inventory.u.items_inventory[idx].nameid;
 
-		if( !nameid || !sd->inventory_data[idx] || sd->inventory.u.items_inventory[idx].amount < amount )
+		if( !nameid || !sd->inventory_data[idx] || sd->inventory.u.items_inventory[idx].amount < amount)
 		{
 			return 1;
 		}
@@ -2989,16 +2989,16 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list
 
 	if( nd->master_nd )
 	{// Script-controlled shops
-		return npc_selllist_sub(sd, n, item_list, nd->master_nd);
+		return npc_selllist_sub(sd, list_length, item_list, nd->master_nd);
 	}
 
 	// delete items
-	for( i = 0; i < n; i++ )
+	for( i = 0; i < list_length; i++ )
 	{
 		int amount, idx;
 
-		idx    = item_list[i*2]-2;
-		amount = item_list[i*2+1];
+		idx = item_list[i].index - 2;
+		amount = item_list[i].amount;
 
 		// Forged packet, we do not care if he loses items
 		if( sd->inventory_data[idx] == nullptr ){
@@ -3013,7 +3013,9 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list
 			}
 		}
 
-		pc_delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC);
+		if (pc_delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC)) {
+			return 1;
+		}
 	}
 
 	if( z > MAX_ZENY )

+ 1 - 1
src/map/npc.hpp

@@ -1488,7 +1488,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b
 int npc_buysellsel(struct map_session_data* sd, int id, int type);
 e_purchase_result npc_buylist(struct map_session_data* sd, std::vector<s_npc_buy_list>& item_list);
 static int npc_buylist_sub(struct map_session_data* sd, std::vector<s_npc_buy_list>& item_list, struct npc_data* nd);
-uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list);
+uint8 npc_selllist(struct map_session_data* sd, int list_length, PACKET_CZ_PC_SELL_ITEMLIST_sub* item_list);
 e_purchase_result npc_barter_purchase( struct map_session_data& sd, std::shared_ptr<s_npc_barter> barter, std::vector<s_barter_purchase>& purchases );
 void npc_parse_mob2(struct spawn_data* mob);
 struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);

+ 12 - 0
src/map/packets.hpp

@@ -344,6 +344,17 @@ struct PACKET_ZC_FRIENDS_LIST{
 	struct PACKET_ZC_FRIENDS_LIST_sub friends[];
 } __attribute__((packed));
 
+struct PACKET_CZ_PC_SELL_ITEMLIST_sub {
+	uint16 index;
+	uint16 amount;
+} __attribute__((packed));
+
+struct PACKET_CZ_PC_SELL_ITEMLIST {
+	int16 packetType;
+	int16 packetLength;
+	PACKET_CZ_PC_SELL_ITEMLIST_sub sellList[];
+} __attribute__((packed));
+
 // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
 #if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
 	#pragma pack( pop )
@@ -412,6 +423,7 @@ DEFINE_PACKET_HEADER(CZ_REQUEST_RESET_ENCHANT, 0x0b9e)
 DEFINE_PACKET_HEADER(ZC_RESPONSE_ENCHANT, 0x0b9f)
 DEFINE_PACKET_HEADER(CZ_CLOSE_UI_ENCHANT, 0x0ba0)
 DEFINE_PACKET_HEADER(CZ_USE_PACKAGEITEM, 0x0baf)
+DEFINE_PACKET_HEADER(CZ_PC_SELL_ITEMLIST, 0x00c9)
 
 const int16 MAX_INVENTORY_ITEM_PACKET_NORMAL = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_normal ) - ( sizeof( struct NORMALITEM_INFO ) * MAX_ITEMLIST) ) ) / sizeof( struct NORMALITEM_INFO ) );
 const int16 MAX_INVENTORY_ITEM_PACKET_EQUIP = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_equip ) - ( sizeof( struct EQUIPITEM_INFO ) * MAX_ITEMLIST ) ) ) / sizeof( struct EQUIPITEM_INFO ) );