Support itemids up to ~2 billion (#5141)

Co-authored-by: aleos89 <aleos89@users.noreply.github.com>
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
Vincent Stumpf
2020-08-08 03:06:07 -07:00
committed by GitHub
parent fd148a6783
commit 3776bfbaa3
71 changed files with 1012 additions and 777 deletions

View File

@@ -1606,7 +1606,7 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
int delete_amount = price, i;
if (!id) { // Item Data is checked at script parsing but in case of item_db reload, check again.
ShowWarning("Failed to find sellitem %hu for itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y);
ShowWarning("Failed to find sellitem %u for itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y);
return ERROR_TYPE_PURCHASE_FAIL;
}
if (cost[1] < points || cost[0] < (price - points)) {
@@ -1614,7 +1614,7 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
memset(output, '\0', sizeof(output));
sprintf(output, msg_txt(sd, 712), id->jname, id->nameid); // You do not have enough %s (%hu).
sprintf(output, msg_txt(sd, 712), id->jname, id->nameid); // You do not have enough %s (%u).
clif_messagecolor(&sd->bl, color_table[COLOR_RED], output, false, SELF);
return ERROR_TYPE_PURCHASE_FAIL;
}
@@ -1633,13 +1633,13 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
amount = delete_amount;
if (pc_delitem(sd, i, amount, 0, 0, LOG_TYPE_NPC)) {
ShowWarning("Failed to delete item %hu from '%s' at itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, sd->status.name, nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y);
ShowWarning("Failed to delete item %u from '%s' at itemshop NPC '%s' (%s, %d, %d)!\n", nd->u.shop.itemshop_nameid, sd->status.name, nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y);
return ERROR_TYPE_PURCHASE_FAIL;
}
delete_amount -= amount;
}
if (delete_amount > 0) {
ShowError("Item %hu is not enough as payment at itemshop NPC '%s' (%s, %d, %d, AID=%d, CID=%d)!\n", nd->u.shop.itemshop_nameid, nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y, sd->status.account_id, sd->status.char_id);
ShowError("Item %u is not enough as payment at itemshop NPC '%s' (%s, %d, %d, AID=%d, CID=%d)!\n", nd->u.shop.itemshop_nameid, nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y, sd->status.account_id, sd->status.char_id);
return ERROR_TYPE_PURCHASE_FAIL;
}
}
@@ -1675,7 +1675,7 @@ static enum e_CASHSHOP_ACK npc_cashshop_process_payment(struct npc_data *nd, int
int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM_sub* item_list)
{
int i, j, amount, new_, w, vt;
unsigned short nameid;
t_itemid nameid;
struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
enum e_CASHSHOP_ACK res;
item_data *id;
@@ -1707,7 +1707,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, str
if( !itemdb_isstackable2(id) && amount > 1 )
{
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %u!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = item_list[i].amount = 1;
}
@@ -1797,7 +1797,7 @@ void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, in
memset(output, '\0', sizeof(output));
sprintf(output, msg_txt(sd, 714), id->jname, id->nameid); // Item Shop List: %s (%hu)
sprintf(output, msg_txt(sd, 714), id->jname, id->nameid); // Item Shop List: %s (%u)
clif_broadcast(&sd->bl, output, strlen(output) + 1, BC_BLUE,SELF);
}
@@ -1833,7 +1833,7 @@ void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, in
* @param points: Cost of total items
* @return clif_cashshop_ack value to display
*/
int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amount, int points)
int npc_cashshop_buy(struct map_session_data *sd, t_itemid nameid, int amount, int points)
{
struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
struct item_data *item;
@@ -1865,7 +1865,7 @@ int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amo
if(!itemdb_isstackable2(item) && amount > 1)
{
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n",
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %u!\n",
sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = 1;
}
@@ -1886,7 +1886,7 @@ int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amo
if( (double)nd->u.shop.shop_item[i].value * amount > INT_MAX )
{
ShowWarning("npc_cashshop_buy: Item '%s' (%hu) price overflow attempt!\n", item->name, nameid);
ShowWarning("npc_cashshop_buy: Item '%s' (%u) price overflow attempt!\n", item->name, nameid);
ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n",
nd->exname, map_mapid2mapname(nd->bl.m), nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, nd->u.shop.shop_item[i].value, amount);
return ERROR_TYPE_ITEM_ID;
@@ -1979,7 +1979,8 @@ uint8 npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *
memset(market_index, 0, sizeof(market_index));
// process entries in buy list, one by one
for( i = 0; i < n; ++i ) {
unsigned short nameid, amount;
t_itemid nameid;
unsigned short amount;
int value;
item_data *id;
@@ -2009,7 +2010,7 @@ uint8 npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *
return 3; // item no longer in itemdb
if( !itemdb_isstackable2(id) && 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 nonstackable item %hu!\n",
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %u!\n",
sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = item_list[i].qty = 1;
}
@@ -2051,7 +2052,7 @@ uint8 npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *
pc_payzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
for( i = 0; i < n; ++i ) {
unsigned short nameid = item_list[i].nameid;
t_itemid nameid = item_list[i].nameid;
unsigned short amount = item_list[i].qty;
#if PACKETVER >= 20131223
@@ -2201,7 +2202,7 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list
// verify the sell list
for( i = 0; i < n; i++ )
{
unsigned short nameid;
t_itemid nameid;
int amount, idx, value;
idx = item_list[i*2]-2;
@@ -2860,7 +2861,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
int m, is_discount = 0;
uint16 dir;
short x, y;
unsigned short nameid = 0;
t_itemid nameid = 0;
struct npc_data *nd;
enum npc_subtype type;
@@ -2904,12 +2905,12 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
switch(type) {
case NPCTYPE_ITEMSHOP: {
if (sscanf(p,",%5hu:%11d,",&nameid,&is_discount) < 1) {
if (sscanf(p,",%u:%11d,",&nameid,&is_discount) < 1) {
ShowError("npc_parse_shop: Invalid item cost definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
return strchr(start,'\n'); // skip and continue
}
if (itemdb_exists(nameid) == NULL) {
ShowWarning("npc_parse_shop: Invalid item ID cost in file '%s', line '%d' (id '%hu').\n", filepath, strline(buffer,start-buffer), nameid);
ShowWarning("npc_parse_shop: Invalid item ID cost in file '%s', line '%d' (id '%u').\n", filepath, strline(buffer,start-buffer), nameid);
return strchr(start,'\n'); // skip and continue
}
p = strchr(p+1,',');
@@ -2964,7 +2965,8 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
nd = npc_create_npc(m, x, y);
nd->u.shop.count = 0;
while ( p ) {
unsigned short nameid2, qty = 0;
t_itemid nameid2;
unsigned short qty = 0;
int value;
struct item_data* id;
bool skip = false;
@@ -2974,14 +2976,14 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
switch(type) {
case NPCTYPE_MARKETSHOP:
#if PACKETVER >= 20131223
if (sscanf(p, ",%6hu:%11d:%6hu", &nameid2, &value, &qty) != 3) {
if (sscanf(p, ",%u:%11d:%6hu", &nameid2, &value, &qty) != 3) {
ShowError("npc_parse_shop: (MARKETSHOP) Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer, start - buffer), w1, w2, w3, w4);
skip = true;
}
#endif
break;
default:
if (sscanf(p, ",%6hu:%11d", &nameid2, &value) != 2) {
if (sscanf(p, ",%u:%11d", &nameid2, &value) != 2) {
ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer, start - buffer), w1, w2, w3, w4);
skip = true;
}
@@ -2992,7 +2994,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
break;
if( (id = itemdb_exists(nameid2)) == NULL ) {
ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%hu').\n", filepath, strline(buffer,start-buffer), nameid2);
ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%u').\n", filepath, strline(buffer,start-buffer), nameid2);
p = strchr(p+1,',');
continue;
}
@@ -3001,15 +3003,15 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
else value = 0; // Cashshop doesn't have a "buy price" in the item_db
}
if (value == 0 && (type == NPCTYPE_SHOP || type == NPCTYPE_MARKETSHOP)) { // NPC selling items for free!
ShowWarning("npc_parse_shop: Item %s [%hu] is being sold for FREE in file '%s', line '%d'.\n",
ShowWarning("npc_parse_shop: Item %s [%u] is being sold for FREE in file '%s', line '%d'.\n",
id->name, nameid2, filepath, strline(buffer,start-buffer));
}
if( type == NPCTYPE_SHOP && value*0.75 < id->value_sell*1.24 ) { // Exploit possible: you can buy and sell back with profit
ShowWarning("npc_parse_shop: Item %s [%hu] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n",
ShowWarning("npc_parse_shop: Item %s [%u] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n",
id->name, nameid2, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer));
}
if (type == NPCTYPE_MARKETSHOP && (!qty || qty > UINT16_MAX)) {
ShowWarning("npc_parse_shop: Item %s [%hu] is stocked with invalid value %d, changed to 1. File '%s', line '%d'.\n",
ShowWarning("npc_parse_shop: Item %s [%u] is stocked with invalid value %d, changed to 1. File '%s', line '%d'.\n",
id->name, nameid2, qty, filepath, strline(buffer,start-buffer));
qty = 1;
}
@@ -3625,7 +3627,7 @@ int npc_instancedestroy(struct npc_data* nd)
**/
void npc_market_tosql(const char *exname, struct npc_item_list *list) {
SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle);
if (SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`name`,`nameid`,`price`,`amount`,`flag`) VALUES ('%s','%hu','%d','%hu','%" PRIu8 "')",
if (SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `%s` (`name`,`nameid`,`price`,`amount`,`flag`) VALUES ('%s','%u','%d','%hu','%" PRIu8 "')",
market_table, exname, list->nameid, list->value, list->qty, list->flag) ||
SQL_ERROR == SqlStmt_Execute(stmt))
SqlStmt_ShowDebug(stmt);
@@ -3638,14 +3640,14 @@ void npc_market_tosql(const char *exname, struct npc_item_list *list) {
* @param nameid Item ID
* @param clear True: will removes all records related with the NPC
**/
void npc_market_delfromsql_(const char *exname, unsigned short nameid, bool clear) {
void npc_market_delfromsql_(const char *exname, t_itemid nameid, bool clear) {
SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle);
if (clear) {
if( SQL_ERROR == SqlStmt_Prepare(stmt, "DELETE FROM `%s` WHERE `name`='%s'", market_table, exname) ||
SQL_ERROR == SqlStmt_Execute(stmt))
SqlStmt_ShowDebug(stmt);
} else {
if (SQL_ERROR == SqlStmt_Prepare(stmt, "DELETE FROM `%s` WHERE `name`='%s' AND `nameid`='%d' LIMIT 1", market_table, exname, nameid) ||
if (SQL_ERROR == SqlStmt_Prepare(stmt, "DELETE FROM `%s` WHERE `name`='%s' AND `nameid`='%u' LIMIT 1", market_table, exname, nameid) ||
SQL_ERROR == SqlStmt_Execute(stmt))
SqlStmt_ShowDebug(stmt);
}
@@ -3683,7 +3685,7 @@ static int npc_market_checkall_sub(DBKey key, DBData *data, va_list ap) {
uint16 j;
if (!list->nameid || !itemdb_exists(list->nameid)) {
ShowError("npc_market_checkall_sub: NPC '%s' sells invalid item '%hu', deleting...\n", nd->exname, list->nameid);
ShowError("npc_market_checkall_sub: NPC '%s' sells invalid item '%u', deleting...\n", nd->exname, list->nameid);
npc_market_delfromsql(nd->exname, list->nameid);
continue;
}
@@ -3708,7 +3710,7 @@ static int npc_market_checkall_sub(DBKey key, DBData *data, va_list ap) {
npc_market_tosql(nd->exname, &nd->u.shop.shop_item[j]);
}
else { // Removing "out-of-date" entry
ShowError("npc_market_checkall_sub: NPC '%s' does not sell item %hu (qty %hu), deleting...\n", nd->exname, list->nameid, list->qty);
ShowError("npc_market_checkall_sub: NPC '%s' does not sell item %u (qty %hu), deleting...\n", nd->exname, list->nameid, list->qty);
npc_market_delfromsql(nd->exname, list->nameid);
}
}
@@ -3771,7 +3773,7 @@ static void npc_market_fromsql(void) {
strdb_put(NPCMarketDB, market->exname, market);
}
Sql_GetData(mmysql_handle, 1, &data, NULL); list.nameid = atoi(data);
Sql_GetData(mmysql_handle, 1, &data, NULL); list.nameid = strtoul(data, nullptr, 10);
Sql_GetData(mmysql_handle, 2, &data, NULL); list.value = atoi(data);
Sql_GetData(mmysql_handle, 3, &data, NULL); list.qty = atoi(data);
Sql_GetData(mmysql_handle, 4, &data, NULL); list.flag = atoi(data);
@@ -4250,7 +4252,7 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
if (!strcmpi(drop_arg1, "random"))
args.nightmaredrop.drop_id = -1;
else if (itemdb_exists((args.nightmaredrop.drop_id = atoi(drop_arg1))) == NULL) {
else if (itemdb_exists((args.nightmaredrop.drop_id = strtol(drop_arg1, nullptr, 10))) == NULL) {
args.nightmaredrop.drop_id = 0;
ShowWarning("npc_parse_mapflag: Invalid item ID '%d' supplied for mapflag 'pvp_nightmaredrop' (file '%s', line '%d'), removing.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", args.nightmaredrop.drop_id, filepath, strline(buffer, start - buffer), w1, w2, w3, w4);
break;