[Fix] Add price change check to the Bazaar Search Window purchase mechanics (#4632)

This commit is contained in:
Mitch Freeman 2025-02-01 16:30:07 -04:00 committed by GitHub
parent 29701d0ea7
commit 0a20100d12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 37 additions and 3 deletions

View File

@ -6378,6 +6378,19 @@ CREATE INDEX idx_trader_active_transaction ON trader (active_transaction);
)", )",
.content_schema_update = false .content_schema_update = false
}, },
ManifestEntry{
.version = 9296,
.description = "2025_02_01_trader_table_listing_date.sql",
.check = "SHOW CREATE TABLE `trader`",
.condition = "missing",
.match = "listing_date",
.sql = R"(
ALTER TABLE `trader`
ADD COLUMN `listing_date` DATETIME NULL DEFAULT NULL AFTER `active_transaction`,
ADD INDEX `idx_trader_listing_date` (`listing_date`);
)",
.content_schema_update = false
}
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
// ManifestEntry{ // ManifestEntry{

View File

@ -36,6 +36,7 @@ public:
uint32_t char_zone_id; uint32_t char_zone_id;
int32_t char_zone_instance_id; int32_t char_zone_instance_id;
uint8_t active_transaction; uint8_t active_transaction;
time_t listing_date;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@ -63,6 +64,7 @@ public:
"char_zone_id", "char_zone_id",
"char_zone_instance_id", "char_zone_instance_id",
"active_transaction", "active_transaction",
"listing_date",
}; };
} }
@ -86,6 +88,7 @@ public:
"char_zone_id", "char_zone_id",
"char_zone_instance_id", "char_zone_instance_id",
"active_transaction", "active_transaction",
"UNIX_TIMESTAMP(listing_date)",
}; };
} }
@ -143,6 +146,7 @@ public:
e.char_zone_id = 0; e.char_zone_id = 0;
e.char_zone_instance_id = 0; e.char_zone_instance_id = 0;
e.active_transaction = 0; e.active_transaction = 0;
e.listing_date = 0;
return e; return e;
} }
@ -196,6 +200,7 @@ public:
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0; e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0; e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.listing_date = strtoll(row[17] ? row[17] : "-1", nullptr, 10);
return e; return e;
} }
@ -245,6 +250,7 @@ public:
v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id)); v.push_back(columns[14] + " = " + std::to_string(e.char_zone_id));
v.push_back(columns[15] + " = " + std::to_string(e.char_zone_instance_id)); v.push_back(columns[15] + " = " + std::to_string(e.char_zone_instance_id));
v.push_back(columns[16] + " = " + std::to_string(e.active_transaction)); v.push_back(columns[16] + " = " + std::to_string(e.active_transaction));
v.push_back(columns[17] + " = FROM_UNIXTIME(" + (e.listing_date > 0 ? std::to_string(e.listing_date) : "null") + ")");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -283,6 +289,7 @@ public:
v.push_back(std::to_string(e.char_zone_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.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
v.push_back("FROM_UNIXTIME(" + (e.listing_date > 0 ? std::to_string(e.listing_date) : "null") + ")");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -329,6 +336,7 @@ public:
v.push_back(std::to_string(e.char_zone_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.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
v.push_back("FROM_UNIXTIME(" + (e.listing_date > 0 ? std::to_string(e.listing_date) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@ -379,6 +387,7 @@ public:
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0; e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0; e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.listing_date = strtoll(row[17] ? row[17] : "-1", nullptr, 10);
all_entries.push_back(e); all_entries.push_back(e);
} }
@ -420,6 +429,7 @@ public:
e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.char_zone_id = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0; e.char_zone_instance_id = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0; e.active_transaction = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.listing_date = strtoll(row[17] ? row[17] : "-1", nullptr, 10);
all_entries.push_back(e); all_entries.push_back(e);
} }
@ -511,6 +521,7 @@ public:
v.push_back(std::to_string(e.char_zone_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.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
v.push_back("FROM_UNIXTIME(" + (e.listing_date > 0 ? std::to_string(e.listing_date) : "null") + ")");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -550,6 +561,7 @@ public:
v.push_back(std::to_string(e.char_zone_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.char_zone_instance_id));
v.push_back(std::to_string(e.active_transaction)); v.push_back(std::to_string(e.active_transaction));
v.push_back("FROM_UNIXTIME(" + (e.listing_date > 0 ? std::to_string(e.listing_date) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }

View File

@ -130,7 +130,8 @@ public:
} }
for (auto &i: items) { for (auto &i: items) {
i.item_cost = new_price; i.item_cost = new_price;
i.listing_date = time(nullptr);
} }
return ReplaceMany(db, items); return ReplaceMany(db, items);
@ -178,6 +179,7 @@ public:
auto m = trader_item[0]; auto m = trader_item[0];
m.item_charges = quantity; m.item_charges = quantity;
m.listing_date = time(nullptr);
return UpdateOne(db, m); return UpdateOne(db, m);
} }
@ -221,6 +223,7 @@ public:
} }
e.active_transaction = status == true ? 1 : 0; e.active_transaction = status == true ? 1 : 0;
e.listing_date = time(nullptr);
return UpdateOne(db, e); return UpdateOne(db, e);
} }

View File

@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9295 #define CURRENT_BINARY_DATABASE_VERSION 9296
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
#endif #endif

View File

@ -1139,6 +1139,8 @@ public:
uint32 GetTraderCount() { return m_trader_count; } uint32 GetTraderCount() { return m_trader_count; }
void IncrementTraderCount() { m_trader_count += 1; } void IncrementTraderCount() { m_trader_count += 1; }
void DecrementTraderCount() { m_trader_count > 0 ? m_trader_count -= 1 : m_trader_count = 0; } void DecrementTraderCount() { m_trader_count > 0 ? m_trader_count -= 1 : m_trader_count = 0; }
void SetTraderTransactionDate() { m_trader_transaction_date = time(nullptr); }
time_t GetTraderTransactionDate() { return m_trader_transaction_date; }
eqFilterMode GetFilter(eqFilterType filter_id) const { return ClientFilters[filter_id]; } eqFilterMode GetFilter(eqFilterType filter_id) const { return ClientFilters[filter_id]; }
void SetFilter(eqFilterType filter_id, eqFilterMode filter_mode) { ClientFilters[filter_id] = filter_mode; } void SetFilter(eqFilterType filter_id, eqFilterMode filter_mode) { ClientFilters[filter_id] = filter_mode; }
@ -1976,6 +1978,7 @@ private:
uint8 firstlogon; uint8 firstlogon;
uint32 mercid; // current merc uint32 mercid; // current merc
uint8 mercSlot; // selected merc slot uint8 mercSlot; // selected merc slot
time_t m_trader_transaction_date;
uint32 m_trader_count{}; uint32 m_trader_count{};
uint32 m_buyer_id; uint32 m_buyer_id;
uint32 m_barter_time; uint32 m_barter_time;

View File

@ -1106,6 +1106,7 @@ void Client::TraderStartTrader(const EQApplicationPacket *app)
trader_item.item_id = inst->GetID(); trader_item.item_id = inst->GetID();
trader_item.item_sn = in->serial_number[i]; trader_item.item_sn = in->serial_number[i];
trader_item.slot_id = i; trader_item.slot_id = i;
trader_item.listing_date = time(nullptr);
if (inst->IsAugmented()) { if (inst->IsAugmented()) {
auto augs = inst->GetAugmentIDs(); auto augs = inst->GetAugmentIDs();
trader_item.aug_slot_1 = augs.at(0); trader_item.aug_slot_1 = augs.at(0);
@ -1812,6 +1813,7 @@ void Client::DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria)
return; return;
} }
SetTraderTransactionDate();
std::stringstream ss{}; std::stringstream ss{};
cereal::BinaryOutputArchive ar(ss); cereal::BinaryOutputArchive ar(ss);
ar(results); ar(results);
@ -2798,6 +2800,7 @@ void Client::TraderPriceUpdate(const EQApplicationPacket *app)
trader_item.item_cost = tpus->NewPrice; trader_item.item_cost = tpus->NewPrice;
trader_item.item_id = newgis->items[i]; trader_item.item_id = newgis->items[i];
trader_item.item_sn = newgis->serial_number[i]; trader_item.item_sn = newgis->serial_number[i];
trader_item.listing_date = time(nullptr);
if (item_detail->IsAugmented()) { if (item_detail->IsAugmented()) {
auto augs = item_detail->GetAugmentIDs(); auto augs = item_detail->GetAugmentIDs();
trader_item.aug_slot_1 = augs.at(0); trader_item.aug_slot_1 = augs.at(0);
@ -3072,7 +3075,7 @@ void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicati
{ {
auto in = (TraderBuy_Struct *) app->pBuffer; auto in = (TraderBuy_Struct *) app->pBuffer;
auto trader_item = TraderRepository::GetItemBySerialNumber(database, tbs->serial_number, tbs->trader_id); auto trader_item = TraderRepository::GetItemBySerialNumber(database, tbs->serial_number, tbs->trader_id);
if (!trader_item.id) { if (!trader_item.id || GetTraderTransactionDate() < trader_item.listing_date) {
LogTrading("Attempt to purchase an item outside of the Bazaar trader_id <red>[{}] item serial_number " LogTrading("Attempt to purchase an item outside of the Bazaar trader_id <red>[{}] item serial_number "
"<red>[{}] The Traders data was outdated.", "<red>[{}] The Traders data was outdated.",
tbs->trader_id, tbs->trader_id,