Additional fixes for cart exploit (#4148)

* Fixes #4146.
* Reverted some of 7f772c3 as this falls into a larger refactor scope.
* Resolved an issue where items could not be picked up from the cart when the overweight message was sent to the player.
* Added missing e_additem_result constants.
Thanks to @secretdataz, @Normynator, and @cydh!
This commit is contained in:
Jittapan Pluemsumran
2019-05-15 01:19:26 +07:00
committed by Aleos
parent 3ad276c9ef
commit 7ad1b32d7d
3 changed files with 56 additions and 49 deletions

View File

@@ -4806,13 +4806,13 @@ short pc_search_inventory(struct map_session_data *sd, unsigned short nameid) {
* 6 = ?
* 7 = stack limitation
*/
char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_pick_type log_type) {
enum e_additem_result pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_pick_type log_type) {
struct item_data *id;
int16 i;
unsigned int w;
nullpo_retr(1, sd);
nullpo_retr(1, item);
nullpo_retr(ADDITEM_INVALID, sd);
nullpo_retr(ADDITEM_INVALID, item);
if( item->nameid == 0 || amount <= 0 )
return ADDITEM_INVALID;
@@ -5342,33 +5342,33 @@ int pc_useitem(struct map_session_data *sd,int n)
* @param item
* @param amount
* @param log_type
* @return 0 = success; 1 = fail; 2 = no slot
* @return See pc.hpp::e_additem_result
*/
unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item,int amount,e_log_pick_type log_type)
enum e_additem_result pc_cart_additem(struct map_session_data *sd,struct item *item,int amount,e_log_pick_type log_type)
{
struct item_data *data;
int i,w;
nullpo_retr(1, sd);
nullpo_retr(1, item);
nullpo_retr(ADDITEM_INVALID, sd);
nullpo_retr(ADDITEM_INVALID, item);
if(item->nameid == 0 || amount <= 0)
return 1;
return ADDITEM_INVALID;
data = itemdb_search(item->nameid);
if( data->stack.cart && amount > data->stack.amount )
{// item stack limitation
return 1;
return ADDITEM_STACKLIMIT;
}
if( !itemdb_cancartstore(item, pc_get_group_level(sd)) || (item->bound > BOUND_ACCOUNT && !pc_can_give_bounded_items(sd)))
{ // Check item trade restrictions [Skotlex]
clif_displaymessage (sd->fd, msg_txt(sd,264));
return 1;
return ADDITEM_INVALID;
}
if( (w = data->weight*amount) + sd->cart_weight > sd->cart_weight_max )
return 1;
return ADDITEM_OVERWEIGHT;
i = MAX_CART;
if( itemdb_isstackable2(data) && !item->expire_time )
@@ -5386,7 +5386,7 @@ unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item,int
if( i < MAX_CART )
{// item already in cart, stack it
if( amount > MAX_AMOUNT - sd->cart.u.items_cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->cart.u.items_cart[i].amount ) )
return 2; // no slot
return ADDITEM_OVERAMOUNT; // no slot
sd->cart.u.items_cart[i].amount += amount;
clif_cart_additem(sd,i,amount,0);
@@ -5395,7 +5395,7 @@ unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item,int
{// item not stackable or not present, add it
ARR_FIND( 0, MAX_CART, i, sd->cart.u.items_cart[i].nameid == 0 );
if( i == MAX_CART )
return 2; // no slot
return ADDITEM_OVERAMOUNT; // no slot
memcpy(&sd->cart.u.items_cart[i],item,sizeof(sd->cart.u.items_cart[0]));
sd->cart.u.items_cart[i].id = 0;
@@ -5410,7 +5410,7 @@ unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item,int
sd->cart_weight += w;
clif_updatestatus(sd,SP_CARTINFO);
return 0;
return ADDITEM_SUCCESS;
}
/*==========================================
@@ -5443,15 +5443,12 @@ void pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log
*------------------------------------------*/
void pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
{
struct item *item_data;
char flag;
nullpo_retv(sd);
if (idx < 0 || idx >= MAX_INVENTORY) //Invalid index check [Skotlex]
return;
item_data = &sd->inventory.u.items_inventory[idx];
struct item *item_data = &sd->inventory.u.items_inventory[idx];
if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending || sd->state.prevend )
return;
@@ -5461,11 +5458,14 @@ void pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
return;
}
if( (flag = pc_cart_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0 )
enum e_additem_result flag = pc_cart_additem(sd,item_data,amount,LOG_TYPE_NONE);
if (flag == ADDITEM_SUCCESS)
pc_delitem(sd,idx,amount,0,5,LOG_TYPE_NONE);
else {
clif_dropitem(sd,idx,0);
clif_cart_additem_ack(sd,(flag==1)?ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT);
clif_delitem(sd, idx, amount, flag);
clif_cart_additem_ack(sd, (flag == ADDITEM_OVERAMOUNT) ? ADDITEM_TO_CART_FAIL_COUNT : ADDITEM_TO_CART_FAIL_WEIGHT);
clif_additem(sd, idx, amount, flag);
}
}
@@ -5498,22 +5498,19 @@ void pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
if (idx < 0 || idx >= MAX_CART) //Invalid index check [Skotlex]
return;
item* item_data=&sd->cart.u.items_cart[idx];
struct item *item_data=&sd->cart.u.items_cart[idx];
if (item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending || sd->state.prevend)
return;
if (pc_checkadditem(sd, item_data->nameid, amount) == CHKADDITEM_OVERAMOUNT) {
return;
}
enum e_additem_result flag = pc_additem(sd, item_data, amount, LOG_TYPE_NONE);
item item_copy = *item_data;
pc_cart_delitem(sd, idx, amount, 0, LOG_TYPE_NONE);
char flag = pc_additem(sd, &item_copy, amount, LOG_TYPE_NONE);
if(flag != ADDITEM_SUCCESS) {
clif_dropitem(sd,idx,0);
clif_additem(sd,0,0,flag);
if (flag == ADDITEM_SUCCESS)
pc_cart_delitem(sd, idx, amount, 0, LOG_TYPE_NONE);
else {
clif_cart_delitem(sd, idx, amount);
clif_additem(sd, idx, amount, flag);
clif_cart_additem(sd, idx, amount, 0);
}
}

View File

@@ -92,6 +92,23 @@ enum prevent_logout_trigger {
PLT_DAMAGE = 8
};
enum e_chkitem_result : uint8 {
CHKADDITEM_EXIST,
CHKADDITEM_NEW,
CHKADDITEM_OVERAMOUNT
};
enum e_additem_result : uint8 {
ADDITEM_SUCCESS,
ADDITEM_INVALID,
ADDITEM_OVERWEIGHT,
ADDITEM_ITEM,
ADDITEM_OVERITEM,
ADDITEM_OVERAMOUNT,
ADDITEM_REFUSED_TIME,
ADDITEM_STACKLIMIT
};
struct skill_cooldown_entry {
unsigned short skill_id;
int timer;
@@ -1049,7 +1066,7 @@ char pc_checkadditem(struct map_session_data *sd, unsigned short nameid, int amo
uint8 pc_inventoryblank(struct map_session_data *sd);
short pc_search_inventory(struct map_session_data *sd, unsigned short nameid);
char pc_payzeny(struct map_session_data *sd, int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
char pc_additem(struct map_session_data *sd, struct item *item, int amount, e_log_pick_type log_type);
enum e_additem_result pc_additem(struct map_session_data *sd, struct item *item, int amount, e_log_pick_type log_type);
char pc_getzeny(struct map_session_data *sd, int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
char pc_delitem(struct map_session_data *sd, int n, int amount, int type, short reason, e_log_pick_type log_type);
@@ -1062,7 +1079,7 @@ int pc_bound_chk(TBL_PC *sd,enum bound_type type,int *idxlist);
int pc_paycash( struct map_session_data *sd, int price, int points, e_log_pick_type type );
int pc_getcash( struct map_session_data *sd, int cash, int points, e_log_pick_type type );
unsigned char pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type);
enum e_additem_result pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type);
void pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type);
void pc_putitemtocart(struct map_session_data *sd,int idx,int amount);
void pc_getitemfromcart(struct map_session_data *sd,int idx,int amount);
@@ -1253,21 +1270,6 @@ void pc_readdb(void);
void do_init_pc(void);
void do_final_pc(void);
enum e_chkitem_result {
CHKADDITEM_EXIST,
CHKADDITEM_NEW,
CHKADDITEM_OVERAMOUNT
};
enum e_additem_result {
ADDITEM_SUCCESS,
ADDITEM_INVALID,
ADDITEM_OVERWEIGHT,
ADDITEM_OVERITEM = 4,
ADDITEM_OVERAMOUNT,
ADDITEM_STACKLIMIT = 7
};
// timer for night.day
extern int day_timer_tid;
extern int night_timer_tid;

View File

@@ -409,6 +409,10 @@ void storage_storageaddfromcart(struct map_session_data *sd, struct s_storage *s
enum e_storage_add result;
nullpo_retv(sd);
if (sd->state.prevend) {
return;
}
result = storage_canAddItem(stor, index, sd->cart.u.items_inventory, amount, MAX_CART);
if (result == STORAGE_ADD_INVALID)
return;
@@ -444,6 +448,10 @@ void storage_storagegettocart(struct map_session_data* sd, struct s_storage *sto
nullpo_retv(sd);
if (sd->state.prevend) {
return;
}
result = storage_canGetItem(stor, index, amount);
if (result != STORAGE_ADD_OK)
return;