summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/clif.c51
-rw-r--r--src/map/clif.h3
-rw-r--r--src/map/npc.c58
-rw-r--r--src/map/npc.h2
-rw-r--r--src/map/packets_struct.h3
5 files changed, 62 insertions, 55 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 9dc42bb07..eb67723e2 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -18193,33 +18193,30 @@ void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) {
sd->npc_shopid = 0;
}
-void clif_npc_market_purchase_ack(struct map_session_data *sd, const struct packet_npc_market_purchase *req, unsigned char response)
+void clif_npc_market_purchase_ack(struct map_session_data *sd, const struct itemlist *item_list, unsigned char response)
{
#if PACKETVER >= 20131223
unsigned short c = 0;
nullpo_retv(sd);
- nullpo_retv(req);
+ nullpo_retv(item_list);
npcmarket_result.PacketType = npcmarketresultackType;
npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */
- if( npcmarket_result.result ) {
- unsigned short i, list_size = (req->PacketLength - 4) / sizeof(req->list[0]), j;
- struct npc_data* nd;
- struct npc_item_list *shop = NULL;
- unsigned short shop_size = 0;
-
- nd = map->id2nd(sd->npc_shopid);
-
- shop = nd->u.scr.shop->item;
- shop_size = nd->u.scr.shop->items;
+ if (npcmarket_result.result) {
+ 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 < list_size; i++) {
+ for (i = 0; i < VECTOR_LENGTH(*item_list); i++) {
+ const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
+ int j;
- npcmarket_result.list[i].ITID = req->list[i].ITID;
- npcmarket_result.list[i].qty = req->list[i].qty;
+ npcmarket_result.list[i].ITID = entry->id;
+ npcmarket_result.list[i].qty = entry->amount;
- ARR_FIND( 0, shop_size, j, req->list[i].ITID == 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;
@@ -18238,16 +18235,28 @@ void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd)
{
#if PACKETVER >= 20131223
const struct packet_npc_market_purchase *p = RP2PTR(fd);
- struct packet_npc_market_purchase pcopy;
- int response = 0;
+ int response = 0, i;
int count = (p->PacketLength - 4) / sizeof p->list[0];
+ struct itemlist item_list;
Assert_retv(count >= 0 && count <= MAX_INVENTORY);
- memcpy(&pcopy, p, p->PacketLength); // FIXME: Temporary hack (until changed to a flexible array)
+ VECTOR_INIT(item_list);
+ VECTOR_ENSURE(item_list, count, 1);
+
+ for (i = 0; i < count; i++) {
+ struct itemlist_entry entry = { 0 };
+
+ entry.id = p->list[i].ITID;
+ entry.amount = p->list[i].qty;
- response = npc->market_buylist(sd, count, &pcopy);
- clif->npc_market_purchase_ack(sd, &pcopy, response);
+ VECTOR_PUSH(item_list, entry);
+ }
+
+ response = npc->market_buylist(sd, &item_list);
+ clif->npc_market_purchase_ack(sd, &item_list, response);
+
+ VECTOR_CLEAR(item_list);
#endif
}
diff --git a/src/map/clif.h b/src/map/clif.h
index 3b7e2e99f..ac0191210 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -40,6 +40,7 @@ struct guild;
struct homun_data;
struct item;
struct item_data;
+struct itemlist; // map/itemdb.h
struct map_session_data;
struct mercenary_data;
struct mob_data;
@@ -1080,7 +1081,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 packet_npc_market_purchase *req, unsigned char response);
+ void (*npc_market_purchase_ack) (struct map_session_data *sd, const struct itemlist *item_list, unsigned char response);
/* */
bool (*parse_roulette_db) (void);
void (*roulette_generate_ack) (struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID);
diff --git a/src/map/npc.c b/src/map/npc.c
index 793ca9a03..25a972299 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1930,10 +1930,9 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) {
}
/**
- * parses incoming npc market purchase list
+ * Processes incoming npc market purchase list
**/
-// FIXME[Haru]: This needs to be decoupled from the client. A packet struct should never make it into npc functions.
-int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, struct packet_npc_market_purchase *p)
+int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
{
struct npc_data* nd;
struct npc_item_list *shop = NULL;
@@ -1942,11 +1941,11 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st
unsigned short shop_size = 0;
nullpo_retr(1, sd);
- nullpo_retr(1, p);
+ nullpo_retr(1, item_list);
nd = npc->checknear(sd,map->id2bl(sd->npc_shopid));
- if( nd == NULL || nd->subtype != SCRIPT || !list_size || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET )
+ if (nd == NULL || nd->subtype != SCRIPT || VECTOR_LENGTH(*item_list) == 0 || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET)
return 1;
shop = nd->u.scr.shop->item;
@@ -1957,37 +1956,37 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st
new_ = 0;
// process entries in buy list, one by one
- for( i = 0; i < list_size; ++i ) {
- int nameid, amount, value;
+ for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
+ int value;
+ struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
// find this entry in the shop's sell list
ARR_FIND( 0, shop_size, j,
- p->list[i].ITID == shop[j].nameid || //Normal items
- p->list[i].ITID == itemdb_viewid(shop[j].nameid) //item_avail replacement
+ entry->id == shop[j].nameid || //Normal items
+ entry->id == itemdb_viewid(shop[j].nameid) //item_avail replacement
);
-
- if( j == shop_size ) /* TODO find official response for this */
+ if (j == shop_size) /* TODO find official response for this */
return 1; // no such item in shop
- if( p->list[i].qty > shop[j].qty )
+ entry->id = shop[j].nameid; //item_avail replacement
+
+ if (entry->amount > (int)shop[j].qty)
return 1;
- amount = p->list[i].qty;
- nameid = p->list[i].ITID = shop[j].nameid; //item_avail replacement
value = shop[j].value;
npc_market_qty[i] = j;
- if( !itemdb->exists(nameid) ) /* TODO find official response for this */
+ if (!itemdb->exists(entry->id)) /* TODO find official response for this */
return 1; // item no longer in itemdb
- if( !itemdb->isstackable(nameid) && amount > 1 ) {
+ if (!itemdb->isstackable(entry->id) && entry->amount > 1) {
//Exploit? You can't buy more than 1 of equipment types o.O
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
- sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
- amount = p->list[i].qty = 1;
+ sd->status.name, sd->status.account_id, sd->status.char_id, entry->amount, entry->id);
+ entry->amount = 1;
}
- switch( pc->checkadditem(sd,nameid,amount) ) {
+ switch (pc->checkadditem(sd, entry->id, entry->amount)) {
case ADDITEM_EXIST:
break;
case ADDITEM_NEW:
@@ -1997,8 +1996,8 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st
return 1;
}
- z += (int64)value * amount;
- w += itemdb_weight(nameid) * amount;
+ z += (int64)value * entry->amount;
+ w += itemdb_weight(entry->id) * entry->amount;
}
if (z > sd->status.zeny) /* TODO find official response for this */
@@ -2012,28 +2011,27 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st
pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
- for( i = 0; i < list_size; ++i ) {
- int nameid = p->list[i].ITID;
- int amount = p->list[i].qty;
+ for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
+ struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
j = npc_market_qty[i];
- if( p->list[i].qty > shop[j].qty ) /* wohoo someone tampered with the packet. */
+ if (entry->amount > (int)shop[j].qty) /* wohoo someone tampered with the packet. */
return 1;
- shop[j].qty -= amount;
+ shop[j].qty -= entry->amount;
npc->market_tosql(nd,j);
- if (itemdb_type(nameid) == IT_PETEGG) {
- pet->create_egg(sd, nameid);
+ if (itemdb_type(entry->id) == IT_PETEGG) {
+ pet->create_egg(sd, entry->id);
} else {
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = nameid;
+ item_tmp.nameid = entry->id;
item_tmp.identify = 1;
- pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC);
+ pc->additem(sd, &item_tmp, entry->amount, LOG_TYPE_NPC);
}
}
diff --git a/src/map/npc.h b/src/map/npc.h
index 2731d51db..1c7ad8398 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -293,7 +293,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, unsigned short list_size, struct packet_npc_market_purchase *p);
+ int (*market_buylist) (struct map_session_data *sd, struct itemlist *item_list);
bool (*trader_open) (struct map_session_data *sd, struct npc_data *nd);
void (*market_fromsql) (void);
void (*market_tosql) (struct npc_data *nd, unsigned short index);
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index 90ea85d4a..f23cefb26 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -1105,8 +1105,7 @@ struct packet_npc_market_purchase {
struct {
unsigned short ITID;
int qty;
- } 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. */
- // TODO[Haru]: Change to a flexible array
+ } 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 {