diff --git a/common/bazaar.cpp b/common/bazaar.cpp index 8244d5c52..c3c828be6 100644 --- a/common/bazaar.cpp +++ b/common/bazaar.cpp @@ -307,7 +307,7 @@ Bazaar::GetSearchResults( r.trader_zone_id = t.trader.char_zone_id; r.trader_zone_instance_id = t.trader.char_zone_instance_id; r.trader_entity_id = t.trader.char_entity_id; - r.serial_number_RoF = fmt::format("{:016}\0", t.trader.item_sn); + r.serial_number_RoF = t.trader.item_sn; r.item_name = fmt::format("{:.63}\0", item_results.at(t.trader.item_id).name); r.trader_name = fmt::format("{:.63}\0", t.trader_name); r.item_stat = item_results.at(t.trader.item_id).stats; diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0a1349254..cb05be8b2 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -3093,7 +3093,7 @@ struct BazaarSearchCriteria_Struct { struct BazaarInspect_Struct { uint32 action; char player_name[64]; - uint32 serial_number; + char serial_number[16]; uint32 item_id; uint32 trader_id; }; @@ -3742,6 +3742,28 @@ struct GetItems_Struct{ int32 charges[EQ::invtype::BAZAAR_SIZE]; }; +struct Trader2_Struct { + uint32 action; + uint32 unknown_004; + uint64 items[EQ::invtype::BAZAAR_SIZE]; + uint32 item_cost[EQ::invtype::BAZAAR_SIZE]; + std::string serial_number[EQ::invtype::BAZAAR_SIZE]; +}; + +struct ClickTrader2_Struct { + uint32 action; + uint32 unknown_004; + uint64 items[EQ::invtype::BAZAAR_SIZE]; + uint32 item_cost[EQ::invtype::BAZAAR_SIZE]; + std::string serial_number[EQ::invtype::BAZAAR_SIZE]; +}; + +struct GetItems2_Struct { + uint64 items[EQ::invtype::BAZAAR_SIZE]; + std::string serial_number[EQ::invtype::BAZAAR_SIZE]; + uint32 charges[EQ::invtype::BAZAAR_SIZE]; +}; + struct BecomeTrader_Struct { uint32 action; uint16 zone_id; @@ -3795,7 +3817,7 @@ struct TraderItemUpdate_Struct{ struct TraderPriceUpdate_Struct { /*000*/ uint32 Action; /*004*/ uint32 SubAction; -/*008*/ int32 SerialNumber; +/*008*/ char serial_number[16]; /*012*/ uint32 Unknown012; /*016*/ uint32 NewPrice; /*020*/ uint32 Unknown016; @@ -6418,7 +6440,7 @@ struct BazaarSearchResultsFromDB_Struct { uint32 count; uint32 trader_id; uint32 item_id; - uint32 serial_number; + std::string serial_number; uint32 charges; uint32 cost; uint32 slot_id; diff --git a/common/item_instance.cpp b/common/item_instance.cpp index c9d48e75c..5aadebf63 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -158,7 +158,8 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy) m_custom_data = copy.m_custom_data; m_timers = copy.m_timers; - if (GetSerialNumber2().empty()) { + m_serial_number2 = copy.m_serial_number2; + if (copy.GetSerialNumber2().empty()) { CreateSerialNumber2(); } diff --git a/common/item_instance.h b/common/item_instance.h index 1f9b12ceb..25d977fd5 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -235,6 +235,7 @@ namespace EQ int32 GetSerialNumber() const { return m_SerialNumber; } void SetSerialNumber(int32 id) { m_SerialNumber = id; } const std::string &GetSerialNumber2() const { return m_serial_number2; } + //std::string &GetSerialNumber2() const { return m_serial_number2; } void SetSerialNumber2(std::string sn) { m_serial_number2 = std::move(sn); } void CreateSerialNumber2() diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index f0b7786f6..c8e8eb6d6 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4256,6 +4256,7 @@ namespace RoF2 OUT_str(seller_name); OUT_str(item_name); OUT_str(serial_number); + //strn0cpy(eq->serial_number, emu->serial_number.c_str(), sizeof(eq->serial_number)); FINISH_ENCODE(); } @@ -4321,6 +4322,7 @@ namespace RoF2 OUT_str(seller_name); OUT_str(item_name); OUT_str(serial_number); + //strn0cpy(eq->serial_number, emu->serial_number.c_str(), sizeof(eq->serial_number)); FINISH_ENCODE(); break; @@ -6152,19 +6154,20 @@ namespace RoF2 switch (action) { case structs::RoF2BazaarTraderBuyerActions::BeginTraderMode: { DECODE_LENGTH_EXACT(structs::BeginTrader_Struct); - SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::BeginTrader_Struct); + SETUP_DIRECT_DECODE(ClickTrader2_Struct, structs::BeginTrader_Struct); LogTrading("(RoF2) BeginTraderMode action [{}]", action); emu->action = TraderOn; std::copy_n(eq->item_cost, RoF2::invtype::BAZAAR_SIZE, emu->item_cost); - std::transform( - std::begin(eq->items), - std::end(eq->items), - std::begin(emu->serial_number), - [&](const structs::TraderItemSerial_Struct x) { - return Strings::ToUnsignedBigInt(x.serial_number,0); - } - ); + std::copy_n(eq->items->serial_number, RoF2::invtype::BAZAAR_SIZE, emu->serial_number); + // std::transform( + // std::begin(eq->items), + // std::end(eq->items), + // std::begin(emu->serial_number), + // [&](const structs::TraderItemSerial_Struct x) { + // return Strings::ToUnsignedBigInt(x.serial_number,0); + // } + // ); FINISH_DIRECT_DECODE(); break; @@ -6190,10 +6193,11 @@ namespace RoF2 LogTrading("(RoF2) PriceUpdate action [{}]", action); emu->Action = PriceUpdate; - emu->SerialNumber = Strings::ToUnsignedBigInt(eq->serial_number, 0); - if (emu->SerialNumber == 0) { - LogTrading("(RoF2) Price change with invalid serial number [{}]", eq->serial_number); - } + strn0cpy(emu->serial_number, eq->serial_number, sizeof(emu->serial_number)); + //FIXemu->serial_number = Strings::ToUnsignedBigInt(eq->serial_number, 0); + // if (emu->SerialNumber == 0) { + // LogTrading("(RoF2) Price change with invalid serial number [{}]", eq->serial_number); + // } emu->NewPrice = eq->new_price; FINISH_DIRECT_DECODE(); @@ -6284,22 +6288,23 @@ namespace RoF2 IN(item_id); IN(trader_id); emu->action = BazaarInspect; - emu->serial_number = Strings::ToUnsignedInt(eq->serial_number, 0); - if (emu->serial_number == 0) { - LogTrading( - "(RoF2) trader_id = [{}] requested a BazaarInspect with an invalid serial number of [{}]", - eq->trader_id, - eq->serial_number - ); - FINISH_DIRECT_DECODE(); - return; - } + strn0cpy(emu->serial_number, eq->serial_number, sizeof(emu->serial_number)); + //FIX emu->serial_number = Strings::ToUnsignedInt(eq->serial_number, 0); + // if (emu->serial_number == 0) { + // LogTrading( + // "(RoF2) trader_id = [{}] requested a BazaarInspect with an invalid serial number of [{}]", + // eq->trader_id, + // eq->serial_number + // ); + // FINISH_DIRECT_DECODE(); + // return; + // } - LogTrading("(RoF2) BazaarInspect action [{}] item_id [{}] serial_number [{}]", - action, - eq->item_id, - eq->serial_number - ); + // LogTrading("(RoF2) BazaarInspect action [{}] item_id [{}] serial_number [{}]", + // action, + // eq->item_id, + // eq->serial_number + // ); FINISH_DIRECT_DECODE(); break; } @@ -6335,7 +6340,9 @@ namespace RoF2 IN_str(buyer_name); IN_str(seller_name); IN_str(item_name); - IN_str(serial_number); + //IN_str(serial_number); + strn0cpy(emu->serial_number, eq->serial_number, sizeof(emu->serial_number)); +//FIX emu->serial_number = eq->serial_number; FINISH_DIRECT_DECODE(); break; @@ -6446,14 +6453,17 @@ namespace RoF2 RoF2::structs::ItemSerializationHeader hdr; //sprintf(hdr.unknown000, "06e0002Y1W00"); - // strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000)); - strn0cpy( - hdr.unknown000, - inst->GetSerialNumber2().empty() ? "0000000000000000" : inst->GetSerialNumber2().c_str(), - sizeof(hdr.unknown000) - ); + //strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000)); + strn0cpy(hdr.unknown000, inst->GetSerialNumber2().c_str(),sizeof(hdr.unknown000)); hdr.unknown000[16] = '\0'; + // strn0cpy( + // hdr.unknown000, + // inst->GetSerialNumber2().empty() ? "0000000000000000" : inst->GetSerialNumber2().c_str(), + // sizeof(hdr.unknown000) + // ); + //hdr.unknown000[16] = '\0'; + hdr.stacksize = 1; if (item->ID == PARCEL_MONEY_ITEM_ID) { diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index b6ad6bbf1..08e953e13 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -3554,8 +3554,8 @@ struct WhoAllPlayerPart4 { }; struct TraderItemSerial_Struct { - char serial_number[17]; - uint8 unknown_018; + char serial_number[16]; + uint8 unknown_018[2]; void operator=(uint32 a) { auto _tmp = fmt::format("{:016}", a); diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index c93b92581..1320e6a2e 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -228,7 +228,7 @@ namespace Titanium VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->trader_entity_id); bufptr += 4; VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->item_id); - VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number); + //FIX VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number); bufptr += 4; if (row->stackable) { strn0cpy( @@ -2529,7 +2529,7 @@ namespace Titanium IN(action); memcpy(emu->player_name, eq->player_name, sizeof(emu->player_name)); - IN(serial_number); + //FIXIN(serial_number); FINISH_DIRECT_DECODE(); break; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 6433621f5..90fecd6fd 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -338,7 +338,7 @@ namespace UF bufptr += 64; VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 1); VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->item_id); - VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number); + //FIX VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number); bufptr += 4; if (row->stackable) { strn0cpy( @@ -3618,7 +3618,7 @@ namespace UF IN(action); memcpy(emu->player_name, eq->player_name, sizeof(emu->player_name)); - IN(serial_number); + //FIXIN(serial_number); FINISH_DIRECT_DECODE(); break; diff --git a/common/repositories/base/base_trader_repository.h b/common/repositories/base/base_trader_repository.h index 99236fcac..a28ef2db5 100644 --- a/common/repositories/base/base_trader_repository.h +++ b/common/repositories/base/base_trader_repository.h @@ -19,24 +19,24 @@ class BaseTraderRepository { public: struct Trader { - uint64_t id; - uint32_t char_id; - uint32_t item_id; - uint32_t aug_slot_1; - uint32_t aug_slot_2; - uint32_t aug_slot_3; - uint32_t aug_slot_4; - uint32_t aug_slot_5; - uint32_t aug_slot_6; - uint32_t item_sn; - int32_t item_charges; - uint32_t item_cost; - uint8_t slot_id; - uint32_t char_entity_id; - uint32_t char_zone_id; - int32_t char_zone_instance_id; - uint8_t active_transaction; - time_t listing_date; + uint64_t id; + uint32_t char_id; + uint32_t item_id; + uint32_t aug_slot_1; + uint32_t aug_slot_2; + uint32_t aug_slot_3; + uint32_t aug_slot_4; + uint32_t aug_slot_5; + uint32_t aug_slot_6; + std::string item_sn; + int32_t item_charges; + uint32_t item_cost; + uint8_t slot_id; + uint32_t char_entity_id; + uint32_t char_zone_id; + int32_t char_zone_instance_id; + uint8_t active_transaction; + time_t listing_date; }; static std::string PrimaryKey() @@ -138,7 +138,7 @@ public: e.aug_slot_4 = 0; e.aug_slot_5 = 0; e.aug_slot_6 = 0; - e.item_sn = 0; + e.item_sn = ""; e.item_charges = 0; e.item_cost = 0; e.slot_id = 0; @@ -192,7 +192,7 @@ public: e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.item_sn = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.item_sn = row[9] ? row[9] : ""; e.item_charges = row[10] ? static_cast(atoi(row[10])) : 0; e.item_cost = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; @@ -242,7 +242,7 @@ public: v.push_back(columns[6] + " = " + std::to_string(e.aug_slot_4)); v.push_back(columns[7] + " = " + std::to_string(e.aug_slot_5)); v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_6)); - v.push_back(columns[9] + " = " + std::to_string(e.item_sn)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.item_sn) + "'"); v.push_back(columns[10] + " = " + std::to_string(e.item_charges)); v.push_back(columns[11] + " = " + std::to_string(e.item_cost)); v.push_back(columns[12] + " = " + std::to_string(e.slot_id)); @@ -281,7 +281,7 @@ public: v.push_back(std::to_string(e.aug_slot_4)); v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); - v.push_back(std::to_string(e.item_sn)); + v.push_back("'" + Strings::Escape(e.item_sn) + "'"); v.push_back(std::to_string(e.item_charges)); v.push_back(std::to_string(e.item_cost)); v.push_back(std::to_string(e.slot_id)); @@ -328,7 +328,7 @@ public: v.push_back(std::to_string(e.aug_slot_4)); v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); - v.push_back(std::to_string(e.item_sn)); + v.push_back("'" + Strings::Escape(e.item_sn) + "'"); v.push_back(std::to_string(e.item_charges)); v.push_back(std::to_string(e.item_cost)); v.push_back(std::to_string(e.slot_id)); @@ -379,7 +379,7 @@ public: e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.item_sn = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.item_sn = row[9] ? row[9] : ""; e.item_charges = row[10] ? static_cast(atoi(row[10])) : 0; e.item_cost = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; @@ -421,7 +421,7 @@ public: e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.item_sn = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.item_sn = row[9] ? row[9] : ""; e.item_charges = row[10] ? static_cast(atoi(row[10])) : 0; e.item_cost = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; e.slot_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; @@ -513,7 +513,7 @@ public: v.push_back(std::to_string(e.aug_slot_4)); v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); - v.push_back(std::to_string(e.item_sn)); + v.push_back("'" + Strings::Escape(e.item_sn) + "'"); v.push_back(std::to_string(e.item_charges)); v.push_back(std::to_string(e.item_cost)); v.push_back(std::to_string(e.slot_id)); @@ -553,7 +553,7 @@ public: v.push_back(std::to_string(e.aug_slot_4)); v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); - v.push_back(std::to_string(e.item_sn)); + v.push_back("'" + Strings::Escape(e.item_sn) + "'"); v.push_back(std::to_string(e.item_charges)); v.push_back(std::to_string(e.item_cost)); v.push_back(std::to_string(e.slot_id)); diff --git a/common/repositories/trader_repository.h b/common/repositories/trader_repository.h index 0354d6437..b5ac3810d 100644 --- a/common/repositories/trader_repository.h +++ b/common/repositories/trader_repository.h @@ -179,7 +179,7 @@ public: return item; } - static int UpdateQuantity(Database &db, uint32 char_id, uint32 serial_number, int16 quantity) + static int UpdateQuantity(Database &db, uint32 char_id, const std::string &serial_number, int16 quantity) { const auto trader_item = GetWhere( db, @@ -197,7 +197,7 @@ public: return UpdateOne(db, m); } - static Trader GetItemBySerialNumber(Database &db, uint32 serial_number, uint32 trader_id) + static Trader GetItemBySerialNumber(Database &db, std::string &serial_number, uint32 trader_id) { Trader e{}; const auto trader_item = GetWhere( @@ -212,22 +212,6 @@ public: return trader_item.at(0); } - static Trader GetItemBySerialNumber(Database &db, std::string serial_number, uint32 trader_id) - { - Trader e{}; - auto sn = Strings::ToUnsignedBigInt(serial_number); - const auto trader_item = GetWhere( - db, - fmt::format("`char_id` = '{}' AND `item_sn` = '{}' LIMIT 1", trader_id, sn) - ); - - if (trader_item.empty()) { - return e; - } - - return trader_item.at(0); - } - static int UpdateActiveTransaction(Database &db, uint32 id, bool status) { auto e = FindOne(db, id); @@ -259,7 +243,7 @@ public: static DistinctTraders_Struct GetTraderByInstanceAndSerialnumber( Database &db, uint32 instance_id, - const char *serial_number + std::string &serial_number ) { DistinctTraders_Struct trader{}; @@ -319,7 +303,7 @@ public: e.trader.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; e.trader.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; e.trader.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.trader.item_sn = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.trader.item_sn = row[9] ? row[9] : std::string(""); e.trader.item_charges = row[10] ? static_cast(atoi(row[10])) : 0; e.trader.item_cost = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; e.trader.slot_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; diff --git a/zone/client.cpp b/zone/client.cpp index 5ed9eddec..17f03587e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -12700,7 +12700,7 @@ uint16 Client::GetSkill(EQ::skills::SkillType skill_id) const return 0; } -void Client::RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity) +void Client::RemoveItemBySerialNumber(const std::string &serial_number, uint32 quantity) { EQ::ItemInstance *item = nullptr; @@ -12714,7 +12714,7 @@ void Client::RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity) } item = GetInv().GetItem(slot_id); - if (item && item->GetSerialNumber() == serial_number) { + if (item && item->GetSerialNumber2().compare(serial_number) == 0) { uint32 charges = item->IsStackable() ? item->GetCharges() : 0; uint32 stack_size = std::max(charges, static_cast(1)); if ((removed_count + stack_size) <= quantity) { diff --git a/zone/client.h b/zone/client.h index d5e8f3ef4..c7698252b 100644 --- a/zone/client.h +++ b/zone/client.h @@ -350,7 +350,7 @@ public: void SendTraderPacket(Client* trader, uint32 Unknown72 = 51); void SendBuyerPacket(Client* Buyer); void SendBuyerToBarterWindow(Client* buyer, uint32 action); - GetItems_Struct* GetTraderItems(); + GetItems2_Struct* GetTraderItems(); void SendBazaarWelcome(); void SendBarterWelcome(); void DyeArmor(EQ::TintProfile* dye); @@ -371,11 +371,11 @@ public: void SendColoredText(uint32 color, std::string message); void SendTraderItem(uint32 item_id,uint16 quantity, TraderRepository::Trader &trader); void DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria); - uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity); + uint16 FindTraderItem(std::string &SerialNumber,uint16 Quantity); uint32 FindTraderItemSerialNumber(int32 ItemID); - EQ::ItemInstance* FindTraderItemBySerialNumber(int32 SerialNumber); - void FindAndNukeTraderItem(int32 serial_number, int16 quantity, Client* customer, uint16 trader_slot); - void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 trader_slot, int32 serial_number, int32 item_id = 0); + EQ::ItemInstance* FindTraderItemBySerialNumber(std::string &serial_number); + void FindAndNukeTraderItem(std::string &serial_number, int16 quantity, Client* customer, uint16 trader_slot); + void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 trader_slot, const std::string &serial_number, int32 item_id = 0); void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0); void TradeRequestFailed(const EQApplicationPacket* app); void BuyTraderItem(TraderBuy_Struct* tbs, Client* trader, const EQApplicationPacket* app); @@ -587,7 +587,7 @@ public: void ServerFilter(SetServerFilter_Struct* filter); void BulkSendTraderInventory(uint32 char_id); - void SendSingleTraderItem(uint32 char_id, int serial_number); + void SendSingleTraderItem(uint32 char_id, const std::string &serial_number); void BulkSendMerchantInventory(int merchant_id, int npcid); inline uint8 GetLanguageSkill(uint8 language_id) const { return m_pp.languages[language_id]; } @@ -1150,7 +1150,7 @@ public: void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1); uint32 GetItemCooldown(uint32 item_id); void RemoveItem(uint32 item_id, uint32 quantity = 1); - void RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity = 1); + void RemoveItemBySerialNumber(const std::string &serial_number, uint32 quantity = 1); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, LootItem** bag_item_data = 0); diff --git a/zone/client_evolving_items.cpp b/zone/client_evolving_items.cpp index 77c29a45e..c8320e44a 100644 --- a/zone/client_evolving_items.cpp +++ b/zone/client_evolving_items.cpp @@ -386,7 +386,7 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst) PlayerEvent::EvolveItem e{}; - RemoveItemBySerialNumber(inst.GetSerialNumber()); + RemoveItemBySerialNumber(inst.GetSerialNumber2()); EvolvingItemsManager::Instance()->LoadPlayerEvent(inst, e); e.status = "Evolved Item due to obtaining progression - Old Evolve Item removed from inventory."; RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e); @@ -506,7 +506,7 @@ void Client::DoEvolveTransferXP(const EQApplicationPacket *app) PlayerEvent::EvolveItem e{}; - RemoveItemBySerialNumber(inst_from->GetSerialNumber()); + RemoveItemBySerialNumber(inst_from->GetSerialNumber2()); EvolvingItemsManager::Instance()->LoadPlayerEvent(*inst_from, e); e.status = "Transfer XP - Original FROM Evolve Item removed from inventory."; RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e); @@ -516,7 +516,7 @@ void Client::DoEvolveTransferXP(const EQApplicationPacket *app) e.status = "Transfer XP - Updated FROM item placed in inventory."; RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e); - RemoveItemBySerialNumber(inst_to->GetSerialNumber()); + RemoveItemBySerialNumber(inst_to->GetSerialNumber2()); EvolvingItemsManager::Instance()->LoadPlayerEvent(*inst_to, e); e.status = "Transfer XP - Original TO Evolve Item removed from inventory."; RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a059bef65..5b8fb836d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -15470,10 +15470,11 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app) auto in = (TraderBuy_Struct *) app->pBuffer; if (RuleB(Bazaar, UseAlternateBazaarSearch) && in->trader_id >= TraderRepository::TRADER_CONVERT_ID) { + auto sn = std::string(in->serial_number); auto trader = TraderRepository::GetTraderByInstanceAndSerialnumber( database, in->trader_id - TraderRepository::TRADER_CONVERT_ID, - in->serial_number + sn ); if (!trader.trader_id) { diff --git a/zone/parcels.cpp b/zone/parcels.cpp index f1dc874c1..08a2fd30c 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -455,7 +455,7 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) CharacterParcelsContainersRepository::InsertMany(database, all_entries); } - RemoveItemBySerialNumber(inst->GetSerialNumber(), parcel_out.quantity == 0 ? 1 : parcel_out.quantity); + RemoveItemBySerialNumber(inst->GetSerialNumber2(), parcel_out.quantity == 0 ? 1 : parcel_out.quantity); std::unique_ptr outapp(new EQApplicationPacket(OP_ShopSendParcel)); QueuePacket(outapp.get()); diff --git a/zone/trading.cpp b/zone/trading.cpp index 9415c9e01..4fc6c22b4 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -763,12 +763,12 @@ void Client::TraderShowItems() uint32 item_limit = trader_items.size() >= GetInv().GetLookup()->InventoryTypeSize.Bazaar ? GetInv().GetLookup()->InventoryTypeSize.Bazaar : trader_items.size(); - - for (int i = 0; i < item_limit; i++) { - data->item_cost[i] = trader_items.at(i).item_cost; - data->items[i] = ClientVersion() == EQ::versions::ClientVersion::RoF2 ? trader_items.at(i).item_sn - : trader_items.at(i).item_id; - } + //FIX + // for (int i = 0; i < item_limit; i++) { + // data->item_cost[i] = trader_items.at(i).item_cost; + // data->items[i] = ClientVersion() == EQ::versions::ClientVersion::RoF2 ? trader_items.at(i).item_sn + // : trader_items.at(i).item_id; + // } data->action = ListTraderItems; @@ -813,18 +813,45 @@ void Client::Trader_CustomerBrowsing(Client *Customer) void Client::TraderStartTrader(const EQApplicationPacket *app) { uint32 max_items = GetInv().GetLookup()->InventoryTypeSize.Bazaar; - auto in = (ClickTrader_Struct *) app->pBuffer; + auto in = (ClickTrader2_Struct *) app->pBuffer; auto inv = GetTraderItems(); bool trade_items_valid = true; std::vector trader_items{}; //Check inventory for no-trade items - for (auto i = 0; i < max_items; i++) { - if (inv->items[i] == 0 || inv->serial_number[i] == 0) { + // for (auto i = 0; i < max_items; i++) { + // if (inv->items[i] == 0 || inv->serial_number[i].empty()) { + // continue; + // } + // + // auto inst = FindTraderItemBySerialNumber(inv->serial_number[i]); + // if (inst) { + // if (inst->GetItem() && inst->GetItem()->NoDrop == 0) { + // Message( + // Chat::Red, + // fmt::format( + // "Item: {} is NODROP and found in a Trader's Satchel. Please remove and restart trader mode", + // inst->GetItem()->Name + // ).c_str() + // ); + // TraderEndTrader(); + // safe_delete(inv); + // return; + // } + // } + // } + + for (uint32 i = 0; i < max_items; i++) { + if (inv->items[i] == 0 || inv->serial_number[i].empty()) { continue; } - auto inst = FindTraderItemBySerialNumber(inv->serial_number[i]); + auto const inst = FindTraderItemBySerialNumber(inv->serial_number[i]); + if (!inst) { + trade_items_valid = false; + break; + } + if (inst) { if (inst->GetItem() && inst->GetItem()->NoDrop == 0) { Message( @@ -839,18 +866,6 @@ void Client::TraderStartTrader(const EQApplicationPacket *app) return; } } - } - - for (uint32 i = 0; i < max_items; i++) { - if (inv->serial_number[i] <= 0) { - continue; - } - - auto inst = FindTraderItemBySerialNumber(inv->serial_number[i]); - if (!inst) { - trade_items_valid = false; - break; - } auto it = std::find(std::begin(in->serial_number), std::end(in->serial_number), inv->serial_number[i]); if (inst && it != std::end(in->serial_number)) { @@ -980,7 +995,7 @@ void Client::SendTraderItem(uint32 ItemID, uint16 Quantity, TraderRepository::Tr } } -void Client::SendSingleTraderItem(uint32 char_id, int serial_number) +void Client::SendSingleTraderItem(uint32 char_id, const std::string &serial_number) { auto inst = database.LoadSingleTraderItem(char_id, serial_number); if (inst) { @@ -1019,14 +1034,14 @@ void Client::BulkSendTraderInventory(uint32 char_id) ) ); if (inst) { - inst->SetSerialNumber(trader_items.at(i).item_sn); + inst->SetSerialNumber2(trader_items.at(i).item_sn); if (trader_items.at(i).item_charges > 0) { inst->SetCharges(trader_items.at(i).item_charges); } if (inst->IsStackable()) { inst->SetMerchantCount(trader_items.at(i).item_charges); - inst->SetMerchantSlot(trader_items.at(i).item_sn); + //inst->SetMerchantSlot(trader_items.at(i).item_sn); } inst->SetPrice(trader_items.at(i).item_cost); @@ -1062,7 +1077,7 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { return 0; } -EQ::ItemInstance *Client::FindTraderItemBySerialNumber(int32 SerialNumber) +EQ::ItemInstance *Client::FindTraderItemBySerialNumber(std::string &serial_number) { EQ::ItemInstance *item = nullptr; int16 slot_id = 0; @@ -1075,7 +1090,7 @@ EQ::ItemInstance *Client::FindTraderItemBySerialNumber(int32 SerialNumber) slot_id = EQ::InventoryProfile::CalcSlotId(i, x); item = GetInv().GetItem(slot_id); if (item) { - if (item->GetSerialNumber() == SerialNumber) { + if (item->GetSerialNumber2().compare(serial_number) == 0) { return item; } } @@ -1083,17 +1098,17 @@ EQ::ItemInstance *Client::FindTraderItemBySerialNumber(int32 SerialNumber) } } - LogTrading("Couldn't find item! Serial No. was [{}]", SerialNumber); + LogTrading("Couldn't find item! Serial No. was [{}]", serial_number); return nullptr; } -GetItems_Struct *Client::GetTraderItems() +GetItems2_Struct *Client::GetTraderItems() { const EQ::ItemInstance *item = nullptr; int16 slot_id = INVALID_INDEX; - auto gis = new GetItems_Struct{0}; + auto gis = new GetItems2_Struct{0}; uint8 ndx = 0; for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) { @@ -1112,7 +1127,7 @@ GetItems_Struct *Client::GetTraderItems() if (item) { gis->items[ndx] = item->GetID(); - gis->serial_number[ndx] = item->GetSerialNumber(); + gis->serial_number[ndx] = item->GetSerialNumber2(); gis->charges[ndx] = item->GetCharges() == 0 ? 1 : item->GetCharges(); ndx++; } @@ -1122,7 +1137,7 @@ GetItems_Struct *Client::GetTraderItems() return gis; } -uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ +uint16 Client::FindTraderItem(std::string &serial_number, uint16 Quantity){ const EQ::ItemInstance* item= nullptr; uint16 SlotID = 0; @@ -1134,7 +1149,7 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ item = GetInv().GetItem(SlotID); - if (item && item->GetSerialNumber() == SerialNumber && + if (item && item->GetSerialNumber2().compare(serial_number) == 0 && (item->GetCharges() >= Quantity || (item->GetCharges() <= 0 && Quantity == 1))) { return SlotID; @@ -1143,7 +1158,7 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ } } LogTrading("Could NOT find a match for Item: [{}] with a quantity of: [{}] on Trader: [{}]\n", - SerialNumber , Quantity, GetName()); + serial_number , Quantity, GetName()); return 0; } @@ -1154,7 +1169,7 @@ void Client::NukeTraderItem( int16 quantity, Client *customer, uint16 trader_slot, - int32 serial_number, + const std::string &serial_number, int32 item_id ) { @@ -1173,7 +1188,7 @@ void Client::NukeTraderItem( tdis->unknown_000 = 0; tdis->trader_id = customer->GetID(); - tdis->item_id = serial_number; + tdis->item_id = Strings::ToUnsignedBigInt(serial_number); tdis->unknown_012 = 0; customer->QueuePacket(outapp); safe_delete(outapp); @@ -1210,7 +1225,7 @@ void Client::NukeTraderItem( safe_delete(outapp2); } -void Client::FindAndNukeTraderItem(int32 serial_number, int16 quantity, Client *customer, uint16 trader_slot) +void Client::FindAndNukeTraderItem(std::string &serial_number, int16 quantity, Client *customer, uint16 trader_slot) { const EQ::ItemInstance *item = nullptr; bool stackable = false; @@ -1247,7 +1262,7 @@ void Client::FindAndNukeTraderItem(int32 serial_number, int16 quantity, Client * std::vector delete_queue{}; for (int i = 0; i < item_limit; i++) { - if (test_slot && trader_items.at(i).item_sn == serial_number) { + if (test_slot && trader_items.at(i).item_sn.compare(serial_number) == 0) { delete_queue.push_back(trader_items.at(i)); NukeTraderItem( slot_id, @@ -1273,8 +1288,8 @@ void Client::FindAndNukeTraderItem(int32 serial_number, int16 quantity, Client * return; } else { - TraderRepository::UpdateQuantity(database, CharacterID(), item->GetSerialNumber(), charges - quantity); - NukeTraderItem(slot_id, charges, quantity, customer, trader_slot, item->GetSerialNumber(), item->GetID()); + TraderRepository::UpdateQuantity(database, CharacterID(), item->GetSerialNumber2(), charges - quantity); + NukeTraderItem(slot_id, charges, quantity, customer, trader_slot, item->GetSerialNumber2(), item->GetID()); return; } } @@ -1362,7 +1377,8 @@ void Client::BuyTraderItem(TraderBuy_Struct *tbs, Client *Trader, const EQApplic tbs->item_id = Strings::ToUnsignedBigInt(tbs->serial_number); } - buy_item = Trader->FindTraderItemBySerialNumber(tbs->item_id); + auto sn = std::string(tbs->serial_number); + buy_item = Trader->FindTraderItemBySerialNumber(sn); if (!buy_item) { LogTrading("Unable to find item id [{}] item_sn [{}] on trader", tbs->item_id, tbs->serial_number); @@ -1519,7 +1535,7 @@ void Client::BuyTraderItem(TraderBuy_Struct *tbs, Client *Trader, const EQApplic strn0cpy(outtbs->item_name, buy_item->GetItem()->Name, sizeof(outtbs->item_name)); strn0cpy( outtbs->serial_number, - fmt::format("{:016}", buy_item->GetSerialNumber()).c_str(), + buy_item->GetSerialNumber2().data(), sizeof(outtbs->serial_number) ); @@ -1545,7 +1561,7 @@ void Client::BuyTraderItem(TraderBuy_Struct *tbs, Client *Trader, const EQApplic BazaarAuditTrail(Trader->GetName(), GetName(), buy_item->GetItem()->Name, outtbs->quantity, outtbs->price, 0); } - Trader->FindAndNukeTraderItem(tbs->item_id, outtbs->quantity, this, 0); + Trader->FindAndNukeTraderItem(sn, outtbs->quantity, this, 0); if (item_id > 0 && Trader->ClientVersion() >= EQ::versions::ClientVersion::RoF) { // Convert Serial Number back to ItemID for RoF+ @@ -1646,8 +1662,8 @@ static void UpdateTraderCustomerItemsAdded( inst->SetCharges(i.item_charges); inst->SetPrice(i.item_cost); - inst->SetSerialNumber(i.item_sn); - inst->SetMerchantSlot(i.item_sn); + inst->SetSerialNumber2(i.item_sn); + //FIXinst->SetMerchantSlot(i.item_sn); if (inst->IsStackable()) { inst->SetMerchantCount(i.item_charges); } @@ -1698,10 +1714,10 @@ static void UpdateTraderCustomerPriceChanged( // RoF+ use Item IDs for now tdis->item_id = trader_items.at(i).item_id; } - else { - tdis->item_id = trader_items.at(i).item_sn; - } - tdis->item_id = trader_items.at(i).item_sn; + //FIX else { + // tdis->item_id = trader_items.at(i).item_sn; + // } + //tdis->item_id = trader_items.at(i).item_sn; LogTrading("Telling customer to remove item [{}] with [{}] charges and S/N [{}]", item_id, charges, trader_items.at(i).item_sn); @@ -1750,8 +1766,8 @@ static void UpdateTraderCustomerPriceChanged( continue; } - inst->SetSerialNumber(trader_items.at(i).item_sn); - inst->SetMerchantSlot(trader_items.at(i).item_sn); + inst->SetSerialNumber2(trader_items.at(i).item_sn); + //inst->SetMerchantSlot(trader_items.at(i).item_sn); LogTrading("Sending price update for [{}], Serial No. [{}] with [{}] charges", item->Name, trader_items.at(i).item_sn, trader_items.at(i).item_charges); @@ -2465,7 +2481,7 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app) LogTrading( "Received Price Update for [{}] Item Serial No. [{}] New Price [{}]", GetName(), - tpus->SerialNumber, + tpus->serial_number, tpus->NewPrice ); @@ -2486,7 +2502,7 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app) uint32 old_price = 0; for (int i = 0; i < item_limit; i++) { - if ((trader_items.at(i).item_id > 0) && (trader_items.at(i).item_sn == tpus->SerialNumber)) { + if ((trader_items.at(i).item_id > 0) && (trader_items.at(i).item_sn.compare(tpus->serial_number) == 0)) { // We found the item that the Trader wants to change the price of (or add back up for sale). // id_of_item_to_update = trader_items.at(i).item_id; @@ -2521,7 +2537,7 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app) int32 charges_on_item_to_add = 0; for (int i = 0; i < GetInv().GetLookup()->InventoryTypeSize.Bazaar; i++) { - if ((newgis->items[i] > 0) && (newgis->serial_number[i] == tpus->SerialNumber)) { + if (newgis->items[i] > 0 && newgis->serial_number[i].compare(tpus->serial_number) == 0) { id_of_item_to_add = newgis->items[i]; charges_on_item_to_add = newgis->charges[i]; @@ -2772,10 +2788,11 @@ void Client::DoBazaarInspect(BazaarInspect_Struct &in) { if (RuleB(Bazaar, UseAlternateBazaarSearch)) { if (in.trader_id >= TraderRepository::TRADER_CONVERT_ID) { + auto sn = std::string(in.serial_number); auto trader = TraderRepository::GetTraderByInstanceAndSerialnumber( database, in.trader_id - TraderRepository::TRADER_CONVERT_ID, - fmt::format("{}", in.serial_number).c_str() + sn ); if (!trader.trader_id) { @@ -2865,7 +2882,8 @@ std::string Client::DetermineMoneyString(uint64 cp) void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicationPacket *app) { auto in = (TraderBuy_Struct *) app->pBuffer; - auto trader_item = TraderRepository::GetItemBySerialNumber(database, tbs->serial_number, tbs->trader_id); + auto sn = std::string(tbs->serial_number); + auto trader_item = TraderRepository::GetItemBySerialNumber(database, sn, tbs->trader_id); if (!trader_item.id || GetTraderTransactionDate() < trader_item.listing_date) { LogTrading("Attempt to purchase an item outside of the Bazaar trader_id [{}] item serial_number " "[{}] The Traders data was outdated.", diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 747302e24..840979d8d 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -3791,8 +3791,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } } - auto item_sn = Strings::ToUnsignedBigInt(in->trader_buy_struct.serial_number); auto outapp = std::make_unique(OP_Trader, static_cast(sizeof(TraderBuy_Struct))); + auto sn = std::string(in->trader_buy_struct.serial_number); auto data = (TraderBuy_Struct *) outapp->pBuffer; memcpy(data, &in->trader_buy_struct, sizeof(TraderBuy_Struct)); @@ -3803,7 +3803,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) TraderRepository::UpdateActiveTransaction(database, in->id, false); - auto item = trader_pc->FindTraderItemBySerialNumber(item_sn); + auto item = trader_pc->FindTraderItemBySerialNumber(sn); if (item && PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::TRADER_SELL)) { auto e = PlayerEvent::TraderSellEvent{ @@ -3826,7 +3826,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e); } - trader_pc->RemoveItemBySerialNumber(item_sn, in->trader_buy_struct.quantity); + trader_pc->RemoveItemBySerialNumber(sn, in->trader_buy_struct.quantity); trader_pc->AddMoneyToPP(in->trader_buy_struct.price * in->trader_buy_struct.quantity, true); trader_pc->QueuePacket(outapp.get()); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0dc143675..3c48ff7ae 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -306,7 +306,7 @@ void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id) ); } -std::unique_ptr ZoneDatabase::LoadSingleTraderItem(uint32 char_id, int serial_number) +std::unique_ptr ZoneDatabase::LoadSingleTraderItem(uint32 char_id, const std::string &serial_number) { auto results = TraderRepository::GetWhere( database, @@ -354,8 +354,8 @@ std::unique_ptr ZoneDatabase::LoadSingleTraderItem(uint32 char } inst->SetCharges(charges); - inst->SetSerialNumber(serial_number); - inst->SetMerchantSlot(serial_number); + inst->SetSerialNumber2(serial_number); + //FIX inst->SetMerchantSlot(serial_number); inst->SetPrice(cost); if (inst->IsStackable()) { diff --git a/zone/zonedb.h b/zone/zonedb.h index cda0a5ab2..6e54108e8 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -394,7 +394,7 @@ public: void DeleteTraderItem(uint32 char_id); void DeleteTraderItem(uint32 char_id,uint16 slot_id); - std::unique_ptr LoadSingleTraderItem(uint32 char_id, int serial_number); + std::unique_ptr LoadSingleTraderItem(uint32 char_id, const std::string &serial_number); Trader_Struct* LoadTraderItem(uint32 char_id); TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id);