Cleaned up CZ_PC_SELL_ITEMLIST and its related functions

* Added a validation check for remaining item amount
This commit is contained in:
Jittapan
2022-10-28 14:57:33 +07:00
parent 88d6d798c7
commit b28eac7b56
5 changed files with 34 additions and 21 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 )

View File

@@ -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);

View File

@@ -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 ) );