From bf4abf934cb74f0e55a10cc9943d469072c2a8c9 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Fri, 9 Aug 2019 06:47:15 +0300 Subject: Add new version for packet ZC_NPC_MARKET_PURCHASE_RESULT Also add enum for result field in packet ZC_NPC_MARKET_PURCHASE_RESULT --- src/map/clif.c | 41 ++++++++++++++++++++--------------------- src/map/clif.h | 22 +++++++++++++++++++++- src/map/npc.c | 20 ++++++++++---------- src/map/npc.h | 4 +++- src/map/packets_struct.h | 45 ++++++++++++++++++++++++++++----------------- 5 files changed, 82 insertions(+), 50 deletions(-) (limited to 'src/map') diff --git a/src/map/clif.c b/src/map/clif.c index ff018c00a..9ae65a51f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -92,9 +92,6 @@ static struct packet_itemlist_equip itemlist_equip; static struct ZC_STORE_ITEMLIST_NORMAL storelist_normal; static struct ZC_STORE_ITEMLIST_EQUIP storelist_equip; static struct packet_viewequip_ack viewequip_list; -#if PACKETVER >= 20131223 -static struct packet_npc_market_result_ack npcmarket_result; -#endif // temporart buffer for send big packets char packet_buf[0xffff]; //#define DUMP_UNKNOWN_PACKET @@ -20337,40 +20334,43 @@ static void clif_parse_NPCBarterClosed(int fd, struct map_session_data *sd) sd->npc_shopid = 0; } -static void clif_npc_market_purchase_ack(struct map_session_data *sd, const struct itemlist *item_list, unsigned char response) +static void clif_npc_market_purchase_ack(struct map_session_data *sd, const struct itemlist *item_list, enum market_buy_result response) { -#if PACKETVER >= 20131223 - unsigned short c = 0; - +#if PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20130911 || defined(PACKETVER_ZERO) nullpo_retv(sd); nullpo_retv(item_list); - npcmarket_result.PacketType = npcmarketresultackType; - npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */ + struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *p = (struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *)packet_buf; + p->PacketType = HEADER_ZC_NPC_MARKET_PURCHASE_RESULT; + p->result = response; - if (npcmarket_result.result) { + unsigned short c = 0; + if (response == MARKET_BUY_RESULT_SUCCESS) { + int vectorLen = VECTOR_LENGTH(*item_list); + int maxCount = (sizeof(packet_buf) - sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT)) / sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub); + if (maxCount > vectorLen) + maxCount = vectorLen; struct npc_data *nd = map->id2nd(sd->npc_shopid); struct npc_item_list *shop = nd->u.scr.shop->item; unsigned short shop_size = nd->u.scr.shop->items; - int i; - for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + for (int i = 0; i < maxCount; i++) { const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); int j; - npcmarket_result.list[i].ITID = entry->id; - npcmarket_result.list[i].qty = entry->amount; + p->list[i].ITID = entry->id; + p->list[i].qty = entry->amount; - ARR_FIND( 0, shop_size, j, entry->id == shop[j].nameid); + ARR_FIND(0, shop_size, j, entry->id == shop[j].nameid); - npcmarket_result.list[i].price = (j != shop_size) ? shop[j].value : 0; + p->list[i].price = (j != shop_size) ? shop[j].value : 0; c++; } } - npcmarket_result.PacketLength = 5 + ( sizeof(npcmarket_result.list[0]) * c );; + p->PacketLength = sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT) + (sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub) * c); - clif->send(&npcmarket_result,npcmarket_result.PacketLength,&sd->bl,SELF); + clif->send(p, p->PacketLength, &sd->bl, SELF); #endif } @@ -20379,7 +20379,6 @@ static void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) { #if PACKETVER >= 20131223 const struct packet_npc_market_purchase *p = RP2PTR(fd); - int response = 0, i; int count = (p->PacketLength - 4) / sizeof p->list[0]; struct itemlist item_list; @@ -20388,7 +20387,7 @@ static void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) VECTOR_INIT(item_list); VECTOR_ENSURE(item_list, count, 1); - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { struct itemlist_entry entry = { 0 }; entry.id = p->list[i].ITID; @@ -20397,7 +20396,7 @@ static void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) VECTOR_PUSH(item_list, entry); } - response = npc->market_buylist(sd, &item_list); + enum market_buy_result response = npc->market_buylist(sd, &item_list); clif->npc_market_purchase_ack(sd, &item_list, response); VECTOR_CLEAR(item_list); diff --git a/src/map/clif.h b/src/map/clif.h index 103ca214f..86a31f2e5 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -699,6 +699,26 @@ enum expand_inventory_result { EXPAND_INVENTORY_RESULT_MAX_SIZE = 4 }; +#if PACKETVER_RE_NUM >= 20190807 +enum market_buy_result { + MARKET_BUY_RESULT_ERROR = 0xffff, // -1 + MARKET_BUY_RESULT_SUCCESS = 0, + MARKET_BUY_RESULT_NO_ZENY = 1, + MARKET_BUY_RESULT_OVER_WEIGHT = 2, + MARKET_BUY_RESULT_OUT_OF_SPACE = 3, + MARKET_BUY_RESULT_AMOUNT_TOO_BIG = 9 +}; +#else +enum market_buy_result { + MARKET_BUY_RESULT_ERROR = 0, + MARKET_BUY_RESULT_SUCCESS = 1, + MARKET_BUY_RESULT_NO_ZENY = 0, + MARKET_BUY_RESULT_OVER_WEIGHT = 0, + MARKET_BUY_RESULT_OUT_OF_SPACE = 0, + MARKET_BUY_RESULT_AMOUNT_TOO_BIG = 0 +}; +#endif + /** * Clif.c Interface **/ @@ -1266,7 +1286,7 @@ struct clif_interface { int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data); /* NPC Market */ void (*npc_market_open) (struct map_session_data *sd, struct npc_data *nd); - void (*npc_market_purchase_ack) (struct map_session_data *sd, const struct itemlist *item_list, unsigned char response); + void (*npc_market_purchase_ack) (struct map_session_data *sd, const struct itemlist *item_list, enum market_buy_result response); /* */ bool (*parse_roulette_db) (void); void (*roulette_generate_ack) (struct map_session_data *sd, enum GENERATE_ROULETTE_ACK result, short stage, short prizeIdx, int bonusItemID); diff --git a/src/map/npc.c b/src/map/npc.c index fea82c873..c3dff5870 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2115,7 +2115,7 @@ static int npc_buylist(struct map_session_data *sd, struct itemlist *item_list) /** * Processes incoming npc market purchase list **/ -static int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list) +static enum market_buy_result npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list) { struct npc_data* nd; struct npc_item_list *shop = NULL; @@ -2129,7 +2129,7 @@ static int npc_market_buylist(struct map_session_data *sd, struct itemlist *item nd = npc->checknear(sd,map->id2bl(sd->npc_shopid)); if (nd == NULL || nd->subtype != SCRIPT || VECTOR_LENGTH(*item_list) == 0 || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET) - return 1; + return MARKET_BUY_RESULT_ERROR; shop = nd->u.scr.shop->item; shop_size = nd->u.scr.shop->items; @@ -2149,18 +2149,18 @@ static int npc_market_buylist(struct map_session_data *sd, struct itemlist *item entry->id == itemdb_viewid(shop[j].nameid) //item_avail replacement ); if (j == shop_size) /* TODO find official response for this */ - return 1; // no such item in shop + return MARKET_BUY_RESULT_ERROR; // no such item in shop entry->id = shop[j].nameid; //item_avail replacement if (entry->amount > (int)shop[j].qty) - return 1; + return MARKET_BUY_RESULT_AMOUNT_TOO_BIG; value = shop[j].value; npc_market_qty[i] = j; if (!itemdb->exists(entry->id)) /* TODO find official response for this */ - return 1; // item no longer in itemdb + return MARKET_BUY_RESULT_ERROR; // item no longer in itemdb if (!itemdb->isstackable(entry->id) && entry->amount > 1) { //Exploit? You can't buy more than 1 of equipment types o.O @@ -2184,13 +2184,13 @@ static int npc_market_buylist(struct map_session_data *sd, struct itemlist *item } if (z > sd->status.zeny) /* TODO find official response for this */ - return 1; // Not enough Zeny + return MARKET_BUY_RESULT_NO_ZENY; // Not enough Zeny if( w + sd->weight > sd->max_weight ) /* TODO find official response for this */ - return 1; // Too heavy + return MARKET_BUY_RESULT_OVER_WEIGHT; // Too heavy if( pc->inventoryblank(sd) < new_ ) /* TODO find official response for this */ - return 1; // Not enough space to store items + return MARKET_BUY_RESULT_OUT_OF_SPACE; // Not enough space to store items pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); @@ -2200,7 +2200,7 @@ static int npc_market_buylist(struct map_session_data *sd, struct itemlist *item j = npc_market_qty[i]; if (entry->amount > (int)shop[j].qty) /* wohoo someone tampered with the packet. */ - return 1; + return MARKET_BUY_RESULT_AMOUNT_TOO_BIG; shop[j].qty -= entry->amount; @@ -2218,7 +2218,7 @@ static int npc_market_buylist(struct map_session_data *sd, struct itemlist *item } } - return 0; + return MARKET_BUY_RESULT_SUCCESS; } /** diff --git a/src/map/npc.h b/src/map/npc.h index 2819cbd87..507635a84 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -34,6 +34,8 @@ struct hplugin_data_store; struct itemlist; // map/itemdb.h struct view_data; +enum market_buy_result; + enum npc_parse_options { NPO_NONE = 0x0, NPO_ONINIT = 0x1, @@ -310,7 +312,7 @@ struct npc_interface { void (*trader_count_funds) (struct npc_data *nd, struct map_session_data *sd); bool (*trader_pay) (struct npc_data *nd, struct map_session_data *sd, int price, int points); void (*trader_update) (int master); - int (*market_buylist) (struct map_session_data *sd, struct itemlist *item_list); + enum market_buy_result (*market_buylist) (struct map_session_data *sd, struct itemlist *item_list); int (*barter_buylist) (struct map_session_data *sd, struct barteritemlist *item_list); bool (*trader_open) (struct map_session_data *sd, struct npc_data *nd); void (*market_fromsql) (void); diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index b40064abf..c1203b26d 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -300,7 +300,6 @@ enum packet_headers { notifybindonequip = 0x2d3, monsterhpType = 0x977, maptypeproperty2Type = 0x99b, - npcmarketresultackType = 0x9d7, #if PACKETVER >= 20131223 // version probably can be 20131030 [4144] wisendType = 0x9df, #else @@ -1362,22 +1361,6 @@ struct packet_npc_market_purchase { } list[]; // Note: We assume this should be <= MAX_INVENTORY (since you can't hold more than MAX_INVENTORY items thus cant buy that many at once). } __attribute__((packed)); -struct packet_npc_market_result_ack { - int16 PacketType; - int16 PacketLength; - uint8 result; - struct { -#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114 - uint32 ITID; -#else - uint16 ITID; -#endif - uint16 qty; - uint32 price; - // [4144] need remove MAX_INVENTORY from here - } list[MAX_INVENTORY];/* assuming MAX_INVENTORY is max since you can't hold more than MAX_INVENTORY items thus cant buy that many at once. */ -} __attribute__((packed)); - #if PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20131106 || defined(PACKETVER_ZERO) /* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */ struct PACKET_ZC_NPC_MARKET_OPEN_sub { @@ -3602,6 +3585,34 @@ struct PACKET_ZC_SKILLINFO_UPDATE2 { DEFINE_PACKET_HEADER(ZC_SKILLINFO_UPDATE2, 0x07e1); #endif +struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub { +#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114 + uint32 ITID; +#else + uint16 ITID; +#endif + uint16 qty; + uint32 price; +} __attribute__((packed)); + +#if PACKETVER_MAIN_NUM >= 20190807 || PACKETVER_RE_NUM >= 20190807 +struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT { + int16 PacketType; + int16 PacketLength; + uint16 result; + struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub list[]; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_NPC_MARKET_PURCHASE_RESULT, 0x0b4e); +#elif PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20130911 || defined(PACKETVER_ZERO) +struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT { + int16 PacketType; + int16 PacketLength; + uint8 result; + struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub list[]; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_NPC_MARKET_PURCHASE_RESULT, 0x09d7); +#endif + #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute #pragma pack(pop) #endif // not NetBSD < 6 / Solaris -- cgit v1.2.3-70-g09d2