diff --git a/common/bazaar.cpp b/common/bazaar.cpp index 789182821..b24fcb1d1 100644 --- a/common/bazaar.cpp +++ b/common/bazaar.cpp @@ -8,13 +8,14 @@ std::vector Bazaar::GetSearchResults( SharedDatabase &db, BazaarSearchCriteria_Struct search, - uint32 char_zone_id + uint32 char_zone_id, + int32 char_zone_instance_id ) { LogTrading( "Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] " "max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] " - "search_scope [{}] char_zone_id [{}]", + "search_scope [{}] char_zone_id [{}], char_zone_instance_id [{}]", search.item_name, search.min_cost, search.max_cost, @@ -26,7 +27,8 @@ Bazaar::GetSearchResults( search.trader_entity_id, search.trader_id, search.search_scope, - char_zone_id + char_zone_id, + char_zone_instance_id ); std::string search_criteria_trader("TRUE "); @@ -34,14 +36,19 @@ Bazaar::GetSearchResults( if (search.search_scope == NonRoFBazaarSearchScope) { search_criteria_trader.append( fmt::format( - " AND trader.char_entity_id = {} AND trader.char_zone_id = {}", + " AND trader.char_entity_id = {} AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}", search.trader_entity_id, - Zones::BAZAAR + Zones::BAZAAR, + char_zone_instance_id ) ); } else if (search.search_scope == Local_Scope) { - search_criteria_trader.append(fmt::format(" AND trader.char_zone_id = {}", char_zone_id)); + search_criteria_trader.append(fmt::format( + " AND trader.char_zone_id = {} AND trader.char_zone_instance_id = {}", + char_zone_id, + char_zone_instance_id) + ); } else if (search.trader_id > 0) { search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id)); @@ -62,7 +69,7 @@ Bazaar::GetSearchResults( std::string query = fmt::format( "SELECT COUNT(item_id), trader.char_id, trader.item_id, trader.item_sn, trader.item_charges, trader.item_cost, " "trader.slot_id, SUM(trader.item_charges), trader.char_zone_id, trader.char_entity_id, character_data.name, " - "aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6 " + "aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6, trader.char_zone_instance_id " "FROM trader, character_data " "WHERE {} AND trader.char_id = character_data.id " "GROUP BY trader.item_sn, trader.item_charges, trader.char_id", @@ -122,19 +129,20 @@ Bazaar::GetSearchResults( continue; } - r.count = Strings::ToInt(row[0]); - r.trader_id = Strings::ToInt(row[1]); - r.serial_number = Strings::ToInt(row[3]); - r.cost = Strings::ToInt(row[5]); - r.slot_id = Strings::ToInt(row[6]); - r.sum_charges = Strings::ToInt(row[7]); - r.stackable = item->Stackable; - r.icon_id = item->Icon; - r.trader_zone_id = Strings::ToInt(row[8]); - r.trader_entity_id = Strings::ToInt(row[9]); - r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3])); - r.item_name = fmt::format("{:.63}\0", item->Name); - r.trader_name = fmt::format("{:.63}\0", std::string(row[10]).c_str()); + r.count = Strings::ToInt(row[0]); + r.trader_id = Strings::ToInt(row[1]); + r.serial_number = Strings::ToInt(row[3]); + r.cost = Strings::ToInt(row[5]); + r.slot_id = Strings::ToInt(row[6]); + r.sum_charges = Strings::ToInt(row[7]); + r.stackable = item->Stackable; + r.icon_id = item->Icon; + r.trader_zone_id = Strings::ToInt(row[8]); + r.trader_zone_instance_id = Strings::ToInt(row[17]); + r.trader_entity_id = Strings::ToInt(row[9]); + r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3])); + r.item_name = fmt::format("{:.63}\0", item->Name); + r.trader_name = fmt::format("{:.63}\0", std::string(row[10]).c_str()); LogTradingDetail( "Searching against item [{}] ({}) for trader [{}]", diff --git a/common/bazaar.h b/common/bazaar.h index 6ce906724..fca2573af 100644 --- a/common/bazaar.h +++ b/common/bazaar.h @@ -7,7 +7,7 @@ class Bazaar { public: static std::vector - GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id); + GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id, int char_zone_instance_id); }; diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 636899094..61186a205 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5770,6 +5770,17 @@ MODIFY COLUMN `exp_modifier` float NOT NULL DEFAULT 1.0 AFTER `aa_modifier`; CREATE INDEX idx_character_expires ON data_buckets (character_id, expires); CREATE INDEX idx_npc_expires ON data_buckets (npc_id, expires); CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires); +)" + }, + ManifestEntry{ + .version = 9286, + .description = "2024_11_26_bazaar_find_trader.sql", + .check = "SHOW COLUMNS FROM `trader` LIKE 'char_zone_instance_id'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `trader` + ADD COLUMN `char_zone_instance_id` INT NULL DEFAULT '0' AFTER `char_zone_id`; )" } // -- template; copy/paste this when you need to create a new entry diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 322bdf639..33e860654 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -3742,7 +3742,8 @@ struct GetItems_Struct{ struct BecomeTrader_Struct { uint32 action; - uint32 zone_id; + uint16 zone_id; + uint16 zone_instance_id; uint32 trader_id; uint32 entity_id; char trader_name[64]; @@ -6347,6 +6348,7 @@ enum BazaarTraderBarterActions { TraderAck2 = 22, AddTraderToBazaarWindow = 24, RemoveTraderFromBazaarWindow = 25, + FirstOpenSearch = 26, ClickTrader = 28, DeliveryCostUpdate = 29 }; @@ -6386,6 +6388,7 @@ struct BazaarSearchResultsFromDB_Struct { uint32 icon_id; uint32 sum_charges; uint32 trader_zone_id; + int32 trader_zone_instance_id; uint32 trader_entity_id; uint32 item_stat; bool stackable; @@ -6407,6 +6410,7 @@ struct BazaarSearchResultsFromDB_Struct { CEREAL_NVP(icon_id), CEREAL_NVP(sum_charges), CEREAL_NVP(trader_zone_id), + CEREAL_NVP(trader_zone_instance_id), CEREAL_NVP(trader_entity_id), CEREAL_NVP(item_stat), CEREAL_NVP(stackable), diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 9024f93b9..0406225ba 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -583,19 +583,21 @@ namespace RoF2 auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(BecomeTrader_Struct)); auto eq = (BecomeTrader_Struct *) outapp->pBuffer; - eq->action = emu->action; - eq->entity_id = emu->entity_id; - eq->trader_id = emu->trader_id; - eq->zone_id = emu->zone_id; + eq->action = emu->action; + eq->entity_id = emu->entity_id; + eq->trader_id = emu->trader_id; + eq->zone_id = emu->zone_id; + eq->zone_instance_id = emu->zone_instance_id; strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name)); LogTrading( - "(RoF2) AddTraderToBazaarWindow action [{}] trader_id [{}] entity_id [{}] zone_id [{}]", + "(RoF2) AddTraderToBazaarWindow action [{}] trader_id [{}] entity_id [{}] " + "zone_id [{}] zone_instance_id [{}]", eq->action, eq->trader_id, eq->entity_id, - eq->zone_id - ); + eq->zone_id, + eq->zone_instance_id); dest->FastQueuePacket(&outapp); break; } @@ -6218,6 +6220,11 @@ namespace RoF2 FINISH_DIRECT_DECODE(); break; } + case structs::RoF2BazaarTraderBuyerActions::FirstOpenSearch: { + __packet->SetOpcode(OP_BazaarSearch); + LogTrading("(RoF2) First time opening Bazaar Search since zoning. Action [{}]", action); + break; + } case structs::RoF2BazaarTraderBuyerActions::WelcomeMessage: { __packet->SetOpcode(OP_BazaarSearch); LogTrading("(RoF2) WelcomeMessage action [{}]", action); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index fa43b65b3..1bbf7c26c 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -3119,7 +3119,8 @@ enum RoF2BazaarTraderBuyerActions { BazaarInspect = 18, ClickTrader = 28, ItemMove = 19, - ReconcileItems = 20 + ReconcileItems = 20, + FirstOpenSearch = 26 }; enum RoF2BuyerActions { diff --git a/common/repositories/base/base_trader_repository.h b/common/repositories/base/base_trader_repository.h index d7cdbbefc..7670587df 100644 --- a/common/repositories/base/base_trader_repository.h +++ b/common/repositories/base/base_trader_repository.h @@ -28,13 +28,14 @@ public: uint32_t aug_slot_4; uint32_t aug_slot_5; uint32_t aug_slot_6; - int32_t item_sn; + uint32_t item_sn; int32_t item_charges; - uint64_t item_cost; + uint32_t item_cost; uint8_t slot_id; uint32_t char_entity_id; uint32_t char_zone_id; - int8_t active_transaction; + int32_t char_zone_instance_id; + uint8_t active_transaction; }; static std::string PrimaryKey() @@ -60,6 +61,7 @@ public: "slot_id", "char_entity_id", "char_zone_id", + "char_zone_instance_id", "active_transaction", }; } @@ -82,6 +84,7 @@ public: "slot_id", "char_entity_id", "char_zone_id", + "char_zone_instance_id", "active_transaction", }; } @@ -123,22 +126,23 @@ public: { Trader e{}; - e.id = 0; - e.char_id = 0; - e.item_id = 0; - e.aug_slot_1 = 0; - e.aug_slot_2 = 0; - e.aug_slot_3 = 0; - e.aug_slot_4 = 0; - e.aug_slot_5 = 0; - e.aug_slot_6 = 0; - e.item_sn = 0; - e.item_charges = 0; - e.item_cost = 0; - e.slot_id = 0; - e.char_entity_id = 0; - e.char_zone_id = 0; - e.active_transaction = 0; + e.id = 0; + e.char_id = 0; + e.item_id = 0; + e.aug_slot_1 = 0; + e.aug_slot_2 = 0; + e.aug_slot_3 = 0; + e.aug_slot_4 = 0; + e.aug_slot_5 = 0; + e.aug_slot_6 = 0; + e.item_sn = 0; + e.item_charges = 0; + e.item_cost = 0; + e.slot_id = 0; + e.char_entity_id = 0; + e.char_zone_id = 0; + e.char_zone_instance_id = 0; + e.active_transaction = 0; return e; } @@ -175,22 +179,23 @@ public: if (results.RowCount() == 1) { Trader e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - 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(atoi(row[9])) : 0; - e.item_charges = row[10] ? static_cast(atoi(row[10])) : 0; - e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0; - e.slot_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.char_entity_id = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.char_zone_id = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; - e.active_transaction = row[15] ? static_cast(atoi(row[15])) : 0; + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + 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_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; + e.char_entity_id = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.char_zone_id = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.char_zone_instance_id = row[15] ? static_cast(atoi(row[15])) : 0; + e.active_transaction = row[16] ? static_cast(strtoul(row[16], nullptr, 10)) : 0; return e; } @@ -238,7 +243,8 @@ public: v.push_back(columns[12] + " = " + std::to_string(e.slot_id)); v.push_back(columns[13] + " = " + std::to_string(e.char_entity_id)); v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id)); - v.push_back(columns[15] + " = " + std::to_string(e.active_transaction)); + v.push_back(columns[15] + " = " + std::to_string(e.char_zone_instance_id)); + v.push_back(columns[16] + " = " + std::to_string(e.active_transaction)); auto results = db.QueryDatabase( fmt::format( @@ -275,6 +281,7 @@ public: v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_zone_id)); + v.push_back(std::to_string(e.char_zone_instance_id)); v.push_back(std::to_string(e.active_transaction)); auto results = db.QueryDatabase( @@ -320,6 +327,7 @@ public: v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_zone_id)); + v.push_back(std::to_string(e.char_zone_instance_id)); v.push_back(std::to_string(e.active_transaction)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); @@ -354,22 +362,23 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { Trader e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - 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(atoi(row[9])) : 0; - e.item_charges = row[10] ? static_cast(atoi(row[10])) : 0; - e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0; - e.slot_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.char_entity_id = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.char_zone_id = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; - e.active_transaction = row[15] ? static_cast(atoi(row[15])) : 0; + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + 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_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; + e.char_entity_id = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.char_zone_id = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.char_zone_instance_id = row[15] ? static_cast(atoi(row[15])) : 0; + e.active_transaction = row[16] ? static_cast(strtoul(row[16], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -394,22 +403,23 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { Trader e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - 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(atoi(row[9])) : 0; - e.item_charges = row[10] ? static_cast(atoi(row[10])) : 0; - e.item_cost = row[11] ? strtoull(row[11], nullptr, 10) : 0; - e.slot_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.char_entity_id = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.char_zone_id = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; - e.active_transaction = row[15] ? static_cast(atoi(row[15])) : 0; + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + 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_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; + e.char_entity_id = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.char_zone_id = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.char_zone_instance_id = row[15] ? static_cast(atoi(row[15])) : 0; + e.active_transaction = row[16] ? static_cast(strtoul(row[16], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -499,6 +509,7 @@ public: v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_zone_id)); + v.push_back(std::to_string(e.char_zone_instance_id)); v.push_back(std::to_string(e.active_transaction)); auto results = db.QueryDatabase( @@ -537,6 +548,7 @@ public: v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.char_entity_id)); v.push_back(std::to_string(e.char_zone_id)); + v.push_back(std::to_string(e.char_zone_instance_id)); v.push_back(std::to_string(e.active_transaction)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); diff --git a/common/repositories/trader_repository.h b/common/repositories/trader_repository.h index 6c6ab35d2..b27363811 100644 --- a/common/repositories/trader_repository.h +++ b/common/repositories/trader_repository.h @@ -16,6 +16,7 @@ public: struct DistinctTraders_Struct { uint32 trader_id; uint32 zone_id; + uint32 zone_instance_id; uint32 entity_id; std::string trader_name; }; @@ -35,7 +36,8 @@ public: GetBazaarSearchResults( SharedDatabase &db, BazaarSearchCriteria_Struct search, - uint32 char_zone_id + uint32 char_zone_id, + int32 char_zone_instance_id ); static BulkTraders_Struct GetDistinctTraders(Database &db) @@ -44,7 +46,7 @@ public: std::vector distinct_traders; auto results = db.QueryDatabase( - "SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_entity_id, c.name " + "SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name " "FROM trader AS t " "JOIN character_data AS c ON t.char_id = c.id;" ); @@ -54,10 +56,11 @@ public: for (auto row: results) { DistinctTraders_Struct e{}; - e.trader_id = Strings::ToInt(row[0]); - e.zone_id = Strings::ToInt(row[1]); - e.entity_id = Strings::ToInt(row[2]); - e.trader_name = row[3] ? row[3] : ""; + e.trader_id = Strings::ToInt(row[0]); + e.zone_id = Strings::ToInt(row[1]); + e.zone_instance_id = Strings::ToInt(row[2]); + e.entity_id = Strings::ToInt(row[3]); + e.trader_name = row[4] ? row[4] : ""; all_entries.name_length += e.trader_name.length() + 1; all_entries.traders.push_back(e); diff --git a/common/version.h b/common/version.h index a144157a7..232d3afc5 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9285 +#define CURRENT_BINARY_DATABASE_VERSION 9286 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #endif diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 73a333f82..4236a4851 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -912,10 +912,6 @@ void Client::CompleteConnect() CastToClient()->FastQueuePacket(&outapp); } - if (ClientVersion() >= EQ::versions::ClientVersion::RoF) { - SendBulkBazaarTraders(); - } - // TODO: load these states // We at least will set them to the correct state for now if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) { @@ -3921,6 +3917,10 @@ void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app) SendBazaarWelcome(); break; } + case FirstOpenSearch: { + SendBulkBazaarTraders(); + break; + } default: { LogError("Malformed BazaarSearch_Struct packet received, ignoring\n"); } diff --git a/zone/trading.cpp b/zone/trading.cpp index f963f7ca1..4be42c099 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1093,15 +1093,16 @@ void Client::TraderStartTrader(const EQApplicationPacket *app) inst->SetPrice(in->item_cost[i]); TraderRepository::Trader trader_item{}; - trader_item.id = 0; - trader_item.char_entity_id = GetID(); - trader_item.char_id = CharacterID(); - trader_item.char_zone_id = GetZoneID(); - trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges(); - trader_item.item_cost = inst->GetPrice(); - trader_item.item_id = inst->GetID(); - trader_item.item_sn = in->serial_number[i]; - trader_item.slot_id = i; + trader_item.id = 0; + trader_item.char_entity_id = GetID(); + trader_item.char_id = CharacterID(); + trader_item.char_zone_id = GetZoneID(); + trader_item.char_zone_instance_id = GetInstanceID(); + trader_item.item_charges = inst->GetCharges() == 0 ? 1 : inst->GetCharges(); + trader_item.item_cost = inst->GetPrice(); + trader_item.item_id = inst->GetID(); + trader_item.item_sn = in->serial_number[i]; + trader_item.slot_id = i; if (inst->IsAugmented()) { auto augs = inst->GetAugmentIDs(); trader_item.aug_slot_1 = augs.at(0); @@ -1796,7 +1797,7 @@ void Client::SendBarterWelcome() void Client::DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria) { - auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID()); + auto results = Bazaar::GetSearchResults(database, search_criteria, GetZoneID(), GetInstanceID()); if (results.empty()) { SendBazaarDone(GetID()); return; @@ -2940,9 +2941,11 @@ void Client::SendBecomeTrader(BazaarTraderBarterActions action, uint32 entity_id auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct)); auto data = (BecomeTrader_Struct *) outapp->pBuffer; - data->action = action; - data->entity_id = trader->GetID(); - data->trader_id = trader->CharacterID(); + data->action = action; + data->entity_id = trader->GetID(); + data->trader_id = trader->CharacterID(); + data->zone_id = trader->GetZoneID(); + data->zone_instance_id = trader->GetInstanceID(); strn0cpy(data->trader_name, trader->GetCleanName(), sizeof(data->trader_name)); QueuePacket(outapp); @@ -3088,14 +3091,15 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app) auto item_detail = FindTraderItemBySerialNumber(newgis->serial_number[i]); TraderRepository::Trader trader_item{}; - trader_item.id = 0; - trader_item.char_entity_id = GetID(); - trader_item.char_id = CharacterID(); - trader_item.char_zone_id = GetZoneID(); - trader_item.item_charges = newgis->charges[i]; - trader_item.item_cost = tpus->NewPrice; - trader_item.item_id = newgis->items[i]; - trader_item.item_sn = newgis->serial_number[i]; + trader_item.id = 0; + trader_item.char_entity_id = GetID(); + trader_item.char_id = CharacterID(); + trader_item.char_zone_id = GetZoneID(); + trader_item.char_zone_instance_id = GetInstanceID(); + trader_item.item_charges = newgis->charges[i]; + trader_item.item_cost = tpus->NewPrice; + trader_item.item_id = newgis->items[i]; + trader_item.item_sn = newgis->serial_number[i]; if (item_detail->IsAugmented()) { auto augs = item_detail->GetAugmentIDs(); trader_item.aug_slot_1 = augs.at(0); @@ -3224,7 +3228,8 @@ void Client::SendBulkBazaarTraders() VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results.count); for (auto t : results.traders) { - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.zone_id); + VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_id); + VARSTRUCT_ENCODE_TYPE(uint16, bufptr, t.zone_instance_id); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.trader_id); VARSTRUCT_ENCODE_TYPE(uint32, bufptr, t.entity_id); VARSTRUCT_ENCODE_STRING(bufptr, t.trader_name.c_str()); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 7b6b870e2..cb1d6ffa3 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -3929,9 +3929,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) out->action = 0; } } - out->entity_id = in->entity_id; - out->zone_id = in->zone_id; - out->trader_id = in->trader_id; + + out->entity_id = in->entity_id; + out->zone_id = in->zone_id; + out->zone_instance_id = in->instance_id; + out->trader_id = in->trader_id; strn0cpy(out->trader_name, in->trader_name, sizeof(out->trader_name)); c.second->QueuePacket(outapp);