From 3dc0935737a5eeed747f23b37ad0816edc9a3fa0 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:39:57 -0300 Subject: [PATCH 01/42] First pass of player_event_loot_items --- common/events/player_event_logs.cpp | 50 +- common/events/player_event_logs.h | 15 +- .../base/base_player_event_logs_repository.h | 21 +- .../base_player_event_loot_items_repository.h | 451 ++++++++++++++++++ .../player_event_loot_items_repository.h | 50 ++ 5 files changed, 573 insertions(+), 14 deletions(-) create mode 100644 common/repositories/base/base_player_event_loot_items_repository.h create mode 100644 common/repositories/player_event_loot_items_repository.h diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 5baa3e5485..87ebc0642c 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1,8 +1,12 @@ -#include #include "player_event_logs.h" -#include "player_event_discord_formatter.h" +#include + +#include + #include "../platform.h" +#include "../repositories/player_event_loot_items_repository.h" #include "../rulesys.h" +#include "player_event_discord_formatter.h" const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour @@ -125,6 +129,12 @@ void PlayerEventLogs::ProcessBatchQueue() // flush many PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); + + // flush detailed tables + if (!m_record_loot_items.empty()) { + PlayerEventLootItemsRepository::InsertMany(*m_database, m_record_loot_items); + } + LogPlayerEventsDetail( "Processing batch player event log queue of [{}] took [{}]", m_record_batch_queue.size(), @@ -132,14 +142,46 @@ void PlayerEventLogs::ProcessBatchQueue() ); // empty - m_record_batch_queue = {}; + m_record_batch_queue.clear(); + m_record_loot_items.clear(); + m_batch_queue_lock.unlock(); } // adds a player event to the queue -void PlayerEventLogs::AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &log) +void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log) { m_batch_queue_lock.lock(); + std::mt19937_64 generator(time(nullptr)); + uint64 details_id = 0; + + switch (log.event_type_id) { + case PlayerEvent::EventType::LOOT_ITEM: { + details_id = generator(); + PlayerEvent::LootItemEvent e{}; + { + std::stringstream ss; + ss << log.event_data; + cereal::JSONInputArchive ar(ss); + e.serialize(ar); + } + + auto pelir = PlayerEventLootItemsRepository::NewEntity(); + pelir.charges = e.charges; + pelir.corpse_name = e.corpse_name; + pelir.item_id = e.item_id; + pelir.item_name = e.item_name; + pelir.npc_id = e.npc_id; + pelir.player_event_logs_details_id = details_id; + log.details_id = details_id; + + m_record_loot_items.push_back(pelir); + break; + } + default: { + } + } + m_record_batch_queue.emplace_back(log); m_batch_queue_lock.unlock(); } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 814f075ba7..9e9560b6de 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -1,14 +1,16 @@ #ifndef EQEMU_PLAYER_EVENT_LOGS_H #define EQEMU_PLAYER_EVENT_LOGS_H +#include +#include +#include "../json/json_archive_single_line.h" #include "../repositories/player_event_log_settings_repository.h" -#include "player_events.h" -#include "../servertalk.h" #include "../repositories/player_event_logs_repository.h" +#include "../servertalk.h" #include "../timer.h" -#include "../json/json_archive_single_line.h" -#include -#include +#include "player_events.h" + +#include "../repositories/player_event_loot_items_repository.h" class PlayerEventLogs { public: @@ -21,7 +23,7 @@ class PlayerEventLogs { void Process(); // batch queue - void AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &logs); + void AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &logs); // main event record generic function // can ingest any struct event types @@ -68,6 +70,7 @@ class PlayerEventLogs { static void FillPlayerEvent(const PlayerEvent::PlayerEvent &p, PlayerEventLogsRepository::PlayerEventLogs &n); static std::unique_ptr BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); + std::vector m_record_loot_items{}; // timers Timer m_process_batch_events_timer; // events processing timer diff --git a/common/repositories/base/base_player_event_logs_repository.h b/common/repositories/base/base_player_event_logs_repository.h index 91f0074b14..830e8aeecf 100644 --- a/common/repositories/base/base_player_event_logs_repository.h +++ b/common/repositories/base/base_player_event_logs_repository.h @@ -31,6 +31,7 @@ class BasePlayerEventLogsRepository { int32_t event_type_id; std::string event_type_name; std::string event_data; + uint64_t details_id; time_t created_at; // cereal @@ -50,6 +51,7 @@ class BasePlayerEventLogsRepository { CEREAL_NVP(event_type_id), CEREAL_NVP(event_type_name), CEREAL_NVP(event_data), + CEREAL_NVP(details_id), CEREAL_NVP(created_at) ); } @@ -75,6 +77,7 @@ class BasePlayerEventLogsRepository { "event_type_id", "event_type_name", "event_data", + "details_id", "created_at", }; } @@ -94,6 +97,7 @@ class BasePlayerEventLogsRepository { "event_type_id", "event_type_name", "event_data", + "details_id", "UNIX_TIMESTAMP(created_at)", }; } @@ -147,6 +151,7 @@ class BasePlayerEventLogsRepository { e.event_type_id = 0; e.event_type_name = ""; e.event_data = ""; + e.details_id = 0; e.created_at = 0; return e; @@ -196,7 +201,8 @@ class BasePlayerEventLogsRepository { e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; e.event_type_name = row[10] ? row[10] : ""; e.event_data = row[11] ? row[11] : ""; - e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + e.details_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); return e; } @@ -241,7 +247,8 @@ class BasePlayerEventLogsRepository { v.push_back(columns[9] + " = " + std::to_string(e.event_type_id)); v.push_back(columns[10] + " = '" + Strings::Escape(e.event_type_name) + "'"); v.push_back(columns[11] + " = '" + Strings::Escape(e.event_data) + "'"); - v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[12] + " = " + std::to_string(e.details_id)); + v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -275,6 +282,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.details_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -317,6 +325,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.details_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); @@ -363,7 +372,8 @@ class BasePlayerEventLogsRepository { e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; e.event_type_name = row[10] ? row[10] : ""; e.event_data = row[11] ? row[11] : ""; - e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + e.details_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -400,7 +410,8 @@ class BasePlayerEventLogsRepository { e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; e.event_type_name = row[10] ? row[10] : ""; e.event_data = row[11] ? row[11] : ""; - e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + e.details_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -487,6 +498,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.details_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -522,6 +534,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.details_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h new file mode 100644 index 0000000000..4cc548a111 --- /dev/null +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -0,0 +1,451 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventLootItemsRepository { +public: + struct PlayerEventLootItems { + uint64_t id; + uint64_t player_event_logs_details_id; + uint32_t item_id; + std::string item_name; + int32_t charges; + uint32_t npc_id; + std::string corpse_name; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "player_event_logs_details_id", + "item_id", + "item_name", + "charges", + "npc_id", + "corpse_name", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "player_event_logs_details_id", + "item_id", + "item_name", + "charges", + "npc_id", + "corpse_name", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_loot_items"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventLootItems NewEntity() + { + PlayerEventLootItems e{}; + + e.id = 0; + e.player_event_logs_details_id = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.npc_id = 0; + e.corpse_name = ""; + + return e; + } + + static PlayerEventLootItems GetPlayerEventLootItems( + const std::vector &player_event_loot_itemss, + int player_event_loot_items_id + ) + { + for (auto &player_event_loot_items : player_event_loot_itemss) { + if (player_event_loot_items.id == player_event_loot_items_id) { + return player_event_loot_items; + } + } + + return NewEntity(); + } + + static PlayerEventLootItems FindOne( + Database& db, + int player_event_loot_items_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_loot_items_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventLootItems e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_logs_details_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_name = row[3] ? row[3] : ""; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.npc_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.corpse_name = row[6] ? row[6] : ""; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_loot_items_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_loot_items_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventLootItems &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.player_event_logs_details_id)); + v.push_back(columns[2] + " = " + std::to_string(e.item_id)); + v.push_back(columns[3] + " = '" + Strings::Escape(e.item_name) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.charges)); + v.push_back(columns[5] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.corpse_name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventLootItems InsertOne( + Database& db, + PlayerEventLootItems e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_logs_details_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_logs_details_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventLootItems e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_logs_details_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_name = row[3] ? row[3] : ""; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.npc_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.corpse_name = row[6] ? row[6] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventLootItems e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_logs_details_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_name = row[3] ? row[3] : ""; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.npc_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.corpse_name = row[6] ? row[6] : ""; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventLootItems &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_logs_details_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_logs_details_id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h new file mode 100644 index 0000000000..6e3fa159fb --- /dev/null +++ b/common/repositories/player_event_loot_items_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_loot_items_repository.h" + +class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventLootItemsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventLootItemsRepository::GetWhereNeverExpires() + * PlayerEventLootItemsRepository::GetWhereXAndY() + * PlayerEventLootItemsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H From c9c3f806b9126513e2a144d84e371ea2434db2a7 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Tue, 15 Oct 2024 23:42:06 -0300 Subject: [PATCH 02/42] Second pass of player_event_loot_items --- common/database/database_update_manifest.cpp | 39 ++++++ common/events/player_event_logs.cpp | 48 +++---- common/events/player_event_logs.h | 31 ++++- ...ase_player_event_log_settings_repository.h | 24 ++++ .../base/base_player_event_logs_repository.h | 130 +++++++++--------- .../base_player_event_loot_items_repository.h | 81 ++++++----- .../player_event_log_settings_repository.h | 7 + .../player_event_loot_items_repository.h | 4 +- 8 files changed, 227 insertions(+), 137 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index cd484122b9..16b2add383 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5805,6 +5805,45 @@ ALTER TABLE `zone` ADD COLUMN `shard_at_player_count` int(11) NULL DEFAULT 0 AFTER `seconds_before_idle`; )", .content_schema_update = true + }, + ManifestEntry{ + .version = 9289, + .description = "2024_10_08_add_detail_player_event_logging.sql", + .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'detail_logs'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `player_event_log_settings` + ADD COLUMN `detail_logs` BIGINT(20) NOT NULL DEFAULT '0' AFTER `discord_webhook_id`, + ADD COLUMN `detail_table_name` VARCHAR(50) NULL DEFAULT NULL AFTER `detail_logs`; + +ALTER TABLE `player_event_logs` + ADD COLUMN `player_event_x_id` BIGINT(20) NOT NULL DEFAULT '0' AFTER `event_data`; +)" + }, + ManifestEntry{ + .version = 9290, + .description = "2024_10_08_remove_qs_logging.sql", + .check = "SHOW TABLES LIKE 'player_event_loot_items'", + .condition = "empty", + .match = "", + .sql = R"( +UPDATE `player_event_log_settings` SET `detail_logs` = 1, `detail_table_name` = 'player_event_loot_items' WHERE `id` = 14; + +CREATE TABLE `player_event_loot_items` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `item_id` INT(10) UNSIGNED NULL DEFAULT NULL, + `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `charges` INT(11) NULL DEFAULT NULL, + `npc_id` INT(10) UNSIGNED NULL DEFAULT NULL, + `corpse_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + PRIMARY KEY (`id`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1 +; +)" } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 87ebc0642c..4f4fd579d2 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -25,6 +25,8 @@ void PlayerEventLogs::Init() m_settings[i].event_enabled = 1; m_settings[i].retention_days = 0; m_settings[i].discord_webhook_id = 0; + m_settings[i].detail_logs = 0; + m_settings[i].detail_table_name = ""; } SetSettingsDefaults(); @@ -64,11 +66,13 @@ void PlayerEventLogs::Init() if (is_missing_in_database && is_implemented && !is_deprecated) { LogInfo("[New] PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i); - auto c = PlayerEventLogSettingsRepository::NewEntity(); - c.id = i; - c.event_name = PlayerEvent::EventName[i]; - c.event_enabled = m_settings[i].event_enabled; - c.retention_days = m_settings[i].retention_days; + auto c = PlayerEventLogSettingsRepository::NewEntity(); + c.id = i; + c.event_name = PlayerEvent::EventName[i]; + c.event_enabled = m_settings[i].event_enabled; + c.retention_days = m_settings[i].retention_days; + c.detail_logs = false; + c.detail_table_name = ""; settings_to_insert.emplace_back(c); } } @@ -77,6 +81,18 @@ void PlayerEventLogs::Init() PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert); } + s = PlayerEventLogSettingsRepository::All(*m_database); + for (auto &e: s) { + if (e.id >= PlayerEvent::MAX) { + continue; + } + + if (e.detail_logs) { + auto last_id = PlayerEventLogSettingsRepository::GetNextIdForTable(*m_database, e.detail_table_name); + GetDetailTableIDCache().emplace(static_cast(e.id), last_id); + } + } + bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld(); bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ(); @@ -152,30 +168,10 @@ void PlayerEventLogs::ProcessBatchQueue() void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log) { m_batch_queue_lock.lock(); - std::mt19937_64 generator(time(nullptr)); - uint64 details_id = 0; switch (log.event_type_id) { case PlayerEvent::EventType::LOOT_ITEM: { - details_id = generator(); - PlayerEvent::LootItemEvent e{}; - { - std::stringstream ss; - ss << log.event_data; - cereal::JSONInputArchive ar(ss); - e.serialize(ar); - } - - auto pelir = PlayerEventLootItemsRepository::NewEntity(); - pelir.charges = e.charges; - pelir.corpse_name = e.corpse_name; - pelir.item_id = e.item_id; - pelir.item_name = e.item_name; - pelir.npc_id = e.npc_id; - pelir.player_event_logs_details_id = details_id; - log.details_id = details_id; - - m_record_loot_items.push_back(pelir); + RecordDetailEvent(log); break; } default: { diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 9e9560b6de..9a77b31ef7 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -1,24 +1,26 @@ #ifndef EQEMU_PLAYER_EVENT_LOGS_H #define EQEMU_PLAYER_EVENT_LOGS_H +#include #include #include +#include #include "../json/json_archive_single_line.h" #include "../repositories/player_event_log_settings_repository.h" #include "../repositories/player_event_logs_repository.h" #include "../servertalk.h" #include "../timer.h" -#include "player_events.h" - #include "../repositories/player_event_loot_items_repository.h" class PlayerEventLogs { public: void Init(); void ReloadSettings(); + void IncrementDetailTableIDCache(PlayerEvent::EventType event_type) { m_last_id_cache_detail_tables[event_type]++; } PlayerEventLogs *SetDatabase(Database *db); bool ValidateDatabaseConnection(); bool IsEventEnabled(PlayerEvent::EventType event); + std::map& GetDetailTableIDCache() { return m_last_id_cache_detail_tables; } void Process(); @@ -56,14 +58,38 @@ class PlayerEventLogs { return BuildPlayerEventPacket(c); } + template void RecordDetailEvent(PlayerEventLogsRepository::PlayerEventLogs &log) + { + I in{}; + O out{}; + + { + std::stringstream ss; + ss << log.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out = in; + log.player_event_x_id = + GetDetailTableIDCache().contains(static_cast(log.event_type_id)) + ? GetDetailTableIDCache().at(static_cast(log.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(log.event_type_id)); + + m_record_loot_items.push_back(out); + } + [[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const; bool IsEventDiscordEnabled(int32_t event_type_id); std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id); static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e); + private: Database *m_database; // reference to database PlayerEventLogSettingsRepository::PlayerEventLogSettings m_settings[PlayerEvent::EventType::MAX]{}; + std::map m_last_id_cache_detail_tables{}; // batch queue is used to record events in batch std::vector m_record_batch_queue{}; @@ -71,6 +97,7 @@ class PlayerEventLogs { static std::unique_ptr BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); std::vector m_record_loot_items{}; + std::vector m_record_testing{}; // timers Timer m_process_batch_events_timer; // events processing timer diff --git a/common/repositories/base/base_player_event_log_settings_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h index e74156cf1a..fd7caf11c7 100644 --- a/common/repositories/base/base_player_event_log_settings_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -24,6 +24,8 @@ class BasePlayerEventLogSettingsRepository { int8_t event_enabled; int32_t retention_days; int32_t discord_webhook_id; + int32_t detail_logs; + std::string detail_table_name; }; static std::string PrimaryKey() @@ -39,6 +41,8 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", + "detail_logs", + "detail_table_name", }; } @@ -50,6 +54,8 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", + "detail_logs", + "detail_table_name", }; } @@ -95,6 +101,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = 0; e.retention_days = 0; e.discord_webhook_id = 0; + e.detail_logs = 0; + e.detail_table_name = ""; return e; } @@ -136,6 +144,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.detail_logs = row[5] ? static_cast(atoi(row[5])) : 0; + e.detail_table_name = row[6] ? row[6] : ""; return e; } @@ -174,6 +184,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(columns[2] + " = " + std::to_string(e.event_enabled)); v.push_back(columns[3] + " = " + std::to_string(e.retention_days)); v.push_back(columns[4] + " = " + std::to_string(e.discord_webhook_id)); + v.push_back(columns[5] + " = " + std::to_string(e.detail_logs)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.detail_table_name) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -200,6 +212,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.detail_logs)); + v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -234,6 +248,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.detail_logs)); + v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -272,6 +288,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.detail_logs = row[5] ? static_cast(atoi(row[5])) : 0; + e.detail_table_name = row[6] ? row[6] : ""; all_entries.push_back(e); } @@ -301,6 +319,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.detail_logs = row[5] ? static_cast(atoi(row[5])) : 0; + e.detail_table_name = row[6] ? row[6] : ""; all_entries.push_back(e); } @@ -380,6 +400,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.detail_logs)); + v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -407,6 +429,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.detail_logs)); + v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_player_event_logs_repository.h b/common/repositories/base/base_player_event_logs_repository.h index 830e8aeecf..43145fa70a 100644 --- a/common/repositories/base/base_player_event_logs_repository.h +++ b/common/repositories/base/base_player_event_logs_repository.h @@ -31,7 +31,7 @@ class BasePlayerEventLogsRepository { int32_t event_type_id; std::string event_type_name; std::string event_data; - uint64_t details_id; + uint64_t player_event_x_id; time_t created_at; // cereal @@ -51,7 +51,7 @@ class BasePlayerEventLogsRepository { CEREAL_NVP(event_type_id), CEREAL_NVP(event_type_name), CEREAL_NVP(event_data), - CEREAL_NVP(details_id), + CEREAL_NVP(player_event_x_id), CEREAL_NVP(created_at) ); } @@ -77,7 +77,7 @@ class BasePlayerEventLogsRepository { "event_type_id", "event_type_name", "event_data", - "details_id", + "player_event_x_id", "created_at", }; } @@ -97,7 +97,7 @@ class BasePlayerEventLogsRepository { "event_type_id", "event_type_name", "event_data", - "details_id", + "player_event_x_id", "UNIX_TIMESTAMP(created_at)", }; } @@ -139,20 +139,20 @@ class BasePlayerEventLogsRepository { { PlayerEventLogs e{}; - e.id = 0; - e.account_id = 0; - e.character_id = 0; - e.zone_id = 0; - e.instance_id = 0; - e.x = 0; - e.y = 0; - e.z = 0; - e.heading = 0; - e.event_type_id = 0; - e.event_type_name = ""; - e.event_data = ""; - e.details_id = 0; - e.created_at = 0; + e.id = 0; + e.account_id = 0; + e.character_id = 0; + e.zone_id = 0; + e.instance_id = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; + e.event_type_id = 0; + e.event_type_name = ""; + e.event_data = ""; + e.player_event_x_id = 0; + e.created_at = 0; return e; } @@ -189,20 +189,20 @@ class BasePlayerEventLogsRepository { if (results.RowCount() == 1) { PlayerEventLogs e{}; - e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; - e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; - e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; - e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; - e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.x = row[5] ? strtof(row[5], nullptr) : 0; - e.y = row[6] ? strtof(row[6], nullptr) : 0; - e.z = row[7] ? strtof(row[7], nullptr) : 0; - e.heading = row[8] ? strtof(row[8], nullptr) : 0; - e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; - e.event_type_name = row[10] ? row[10] : ""; - e.event_data = row[11] ? row[11] : ""; - e.details_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; - e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; + e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; + e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; + e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.x = row[5] ? strtof(row[5], nullptr) : 0; + e.y = row[6] ? strtof(row[6], nullptr) : 0; + e.z = row[7] ? strtof(row[7], nullptr) : 0; + e.heading = row[8] ? strtof(row[8], nullptr) : 0; + e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.player_event_x_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); return e; } @@ -247,7 +247,7 @@ class BasePlayerEventLogsRepository { v.push_back(columns[9] + " = " + std::to_string(e.event_type_id)); v.push_back(columns[10] + " = '" + Strings::Escape(e.event_type_name) + "'"); v.push_back(columns[11] + " = '" + Strings::Escape(e.event_data) + "'"); - v.push_back(columns[12] + " = " + std::to_string(e.details_id)); + v.push_back(columns[12] + " = " + std::to_string(e.player_event_x_id)); v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -282,7 +282,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.details_id)); + v.push_back(std::to_string(e.player_event_x_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -325,7 +325,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.details_id)); + v.push_back(std::to_string(e.player_event_x_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); @@ -360,20 +360,20 @@ class BasePlayerEventLogsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLogs e{}; - e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; - e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; - e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; - e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; - e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.x = row[5] ? strtof(row[5], nullptr) : 0; - e.y = row[6] ? strtof(row[6], nullptr) : 0; - e.z = row[7] ? strtof(row[7], nullptr) : 0; - e.heading = row[8] ? strtof(row[8], nullptr) : 0; - e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; - e.event_type_name = row[10] ? row[10] : ""; - e.event_data = row[11] ? row[11] : ""; - e.details_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; - e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; + e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; + e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; + e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.x = row[5] ? strtof(row[5], nullptr) : 0; + e.y = row[6] ? strtof(row[6], nullptr) : 0; + e.z = row[7] ? strtof(row[7], nullptr) : 0; + e.heading = row[8] ? strtof(row[8], nullptr) : 0; + e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.player_event_x_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -398,20 +398,20 @@ class BasePlayerEventLogsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLogs e{}; - e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; - e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; - e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; - e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; - e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.x = row[5] ? strtof(row[5], nullptr) : 0; - e.y = row[6] ? strtof(row[6], nullptr) : 0; - e.z = row[7] ? strtof(row[7], nullptr) : 0; - e.heading = row[8] ? strtof(row[8], nullptr) : 0; - e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; - e.event_type_name = row[10] ? row[10] : ""; - e.event_data = row[11] ? row[11] : ""; - e.details_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; - e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; + e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; + e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; + e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.x = row[5] ? strtof(row[5], nullptr) : 0; + e.y = row[6] ? strtof(row[6], nullptr) : 0; + e.z = row[7] ? strtof(row[7], nullptr) : 0; + e.heading = row[8] ? strtof(row[8], nullptr) : 0; + e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.player_event_x_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -498,7 +498,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.details_id)); + v.push_back(std::to_string(e.player_event_x_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -534,7 +534,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.details_id)); + v.push_back(std::to_string(e.player_event_x_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h index 4cc548a111..deb1892c20 100644 --- a/common/repositories/base/base_player_event_loot_items_repository.h +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -20,12 +20,22 @@ class BasePlayerEventLootItemsRepository { public: struct PlayerEventLootItems { uint64_t id; - uint64_t player_event_logs_details_id; uint32_t item_id; std::string item_name; int32_t charges; uint32_t npc_id; std::string corpse_name; + + PlayerEventLootItems &operator=(const PlayerEvent::LootItemEvent &in) + { + charges = in.charges; + corpse_name = in.corpse_name; + item_id = in.item_id; + item_name = in.item_name; + npc_id = in.npc_id; + + return *this; + } }; static std::string PrimaryKey() @@ -37,7 +47,6 @@ class BasePlayerEventLootItemsRepository { { return { "id", - "player_event_logs_details_id", "item_id", "item_name", "charges", @@ -50,7 +59,6 @@ class BasePlayerEventLootItemsRepository { { return { "id", - "player_event_logs_details_id", "item_id", "item_name", "charges", @@ -96,13 +104,12 @@ class BasePlayerEventLootItemsRepository { { PlayerEventLootItems e{}; - e.id = 0; - e.player_event_logs_details_id = 0; - e.item_id = 0; - e.item_name = ""; - e.charges = 0; - e.npc_id = 0; - e.corpse_name = ""; + e.id = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.npc_id = 0; + e.corpse_name = ""; return e; } @@ -139,13 +146,12 @@ class BasePlayerEventLootItemsRepository { if (results.RowCount() == 1) { PlayerEventLootItems e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.player_event_logs_details_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.item_name = row[3] ? row[3] : ""; - e.charges = row[4] ? static_cast(atoi(row[4])) : 0; - e.npc_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.corpse_name = row[6] ? row[6] : ""; + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.corpse_name = row[5] ? row[5] : ""; return e; } @@ -179,12 +185,11 @@ class BasePlayerEventLootItemsRepository { auto columns = Columns(); - v.push_back(columns[1] + " = " + std::to_string(e.player_event_logs_details_id)); - v.push_back(columns[2] + " = " + std::to_string(e.item_id)); - v.push_back(columns[3] + " = '" + Strings::Escape(e.item_name) + "'"); - v.push_back(columns[4] + " = " + std::to_string(e.charges)); - v.push_back(columns[5] + " = " + std::to_string(e.npc_id)); - v.push_back(columns[6] + " = '" + Strings::Escape(e.corpse_name) + "'"); + v.push_back(columns[1] + " = " + std::to_string(e.item_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.item_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); + v.push_back(columns[4] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.corpse_name) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -207,7 +212,6 @@ class BasePlayerEventLootItemsRepository { std::vector v; v.push_back(std::to_string(e.id)); - v.push_back(std::to_string(e.player_event_logs_details_id)); v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); @@ -243,7 +247,6 @@ class BasePlayerEventLootItemsRepository { std::vector v; v.push_back(std::to_string(e.id)); - v.push_back(std::to_string(e.player_event_logs_details_id)); v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); @@ -282,13 +285,12 @@ class BasePlayerEventLootItemsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLootItems e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.player_event_logs_details_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.item_name = row[3] ? row[3] : ""; - e.charges = row[4] ? static_cast(atoi(row[4])) : 0; - e.npc_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.corpse_name = row[6] ? row[6] : ""; + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.corpse_name = row[5] ? row[5] : ""; all_entries.push_back(e); } @@ -313,13 +315,12 @@ class BasePlayerEventLootItemsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLootItems e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.player_event_logs_details_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.item_name = row[3] ? row[3] : ""; - e.charges = row[4] ? static_cast(atoi(row[4])) : 0; - e.npc_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.corpse_name = row[6] ? row[6] : ""; + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.corpse_name = row[5] ? row[5] : ""; all_entries.push_back(e); } @@ -395,7 +396,6 @@ class BasePlayerEventLootItemsRepository { std::vector v; v.push_back(std::to_string(e.id)); - v.push_back(std::to_string(e.player_event_logs_details_id)); v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); @@ -424,7 +424,6 @@ class BasePlayerEventLootItemsRepository { std::vector v; v.push_back(std::to_string(e.id)); - v.push_back(std::to_string(e.player_event_logs_details_id)); v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); diff --git a/common/repositories/player_event_log_settings_repository.h b/common/repositories/player_event_log_settings_repository.h index 770db7c3f5..2157c7e202 100644 --- a/common/repositories/player_event_log_settings_repository.h +++ b/common/repositories/player_event_log_settings_repository.h @@ -2,6 +2,7 @@ #define EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H #include "../database.h" +#include "../events/player_events.h" #include "../strings.h" #include "base/base_player_event_log_settings_repository.h" @@ -45,6 +46,12 @@ class PlayerEventLogSettingsRepository: public BasePlayerEventLogSettingsReposit // Custom extended repository methods here + static uint64 GetNextIdForTable(Database& db, std::string& table_name) + { + auto results = db.QueryDatabase(fmt::format("SELECT COALESCE(MAX(id), 0) FROM {}", table_name)); + + return results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) + 1 : 0; + } }; #endif //EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index 6e3fa159fb..f2659154ec 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -2,6 +2,7 @@ #define EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H #include "../database.h" +#include "../events/player_events.h" #include "../strings.h" #include "base/base_player_event_loot_items_repository.h" @@ -42,9 +43,6 @@ class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository * method that can be re-used easily elsewhere especially if it can use a base repository * method and encapsulate filters there */ - - // Custom extended repository methods here - }; #endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H From f097afa83d1954ebf4aba77ea592adf86d0a0323 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:43:45 -0300 Subject: [PATCH 03/42] Third pass of player_event_loot_items --- common/CMakeLists.txt | 4 + common/database/database_update_manifest.cpp | 28 + common/database_schema.h | 2 + common/events/player_event_logs.cpp | 32 +- common/events/player_event_logs.h | 5 +- ...se_player_event_merchant_sell_repository.h | 515 ++++++++++++++++++ .../player_event_log_settings_repository.h | 2 +- .../player_event_loot_items_repository.h | 1 - .../player_event_merchant_sell_repository.h | 50 ++ 9 files changed, 630 insertions(+), 9 deletions(-) create mode 100644 common/repositories/base/base_player_event_merchant_sell_repository.h create mode 100644 common/repositories/player_event_merchant_sell_repository.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 0a1766fc8c..450917b0ed 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -279,6 +279,8 @@ SET(repositories repositories/base/base_player_titlesets_repository.h repositories/base/base_player_event_log_settings_repository.h repositories/base/base_player_event_logs_repository.h + repositories/base/base_player_event_loot_items_repository.h + repositories/base/base_player_event_merchant_sell_repository.h repositories/base/base_quest_globals_repository.h repositories/base/base_raid_details_repository.h repositories/base/base_raid_members_repository.h @@ -462,6 +464,8 @@ SET(repositories repositories/player_titlesets_repository.h repositories/player_event_log_settings_repository.h repositories/player_event_logs_repository.h + repositories/player_event_loot_items_repository.h + repositories/player_event_merchant_sell_repository.h repositories/quest_globals_repository.h repositories/raid_details_repository.h repositories/raid_members_repository.h diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 16b2add383..6008491e42 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5843,8 +5843,36 @@ COLLATE='latin1_swedish_ci' ENGINE=InnoDB AUTO_INCREMENT=1 ; +)" + }, + ManifestEntry{ + .version = 9287, + .description = "2024_10_08_remove_qs_logging.sql", + .check = "SHOW TABLES LIKE 'player_event_merchant_sell'", + .condition = "empty", + .match = "", + .sql = R"( +UPDATE `player_event_log_settings` SET `detail_logs` = 1, `detail_table_name` = 'player_event_merchant_sell' WHERE `id` = 16; + +CREATE TABLE `player_event_merchant_sell` ( + `id` BIGINT UNSIGNED NULL AUTO_INCREMENT, + `npc_id` INT UNSIGNED NULL DEFAULT '0', + `merchant_name` VARCHAR(64) NULL DEFAULT NULL, + `merchant_type` INT UNSIGNED NULL DEFAULT '0', + `item_id` INT UNSIGNED NULL DEFAULT '0', + `item_name` VARCHAR(64) NULL DEFAULT NULL, + `charges` INT NULL DEFAULT '0', + `cost` INT UNSIGNED NULL DEFAULT '0', + `alternate_currency_id` INT UNSIGNED NULL DEFAULT '0', + `player_money_balance` BIGINT UNSIGNED NULL DEFAULT '0', + `player_currency_balance` BIGINT UNSIGNED NULL DEFAULT '0', + PRIMARY KEY (`id`) +) +COLLATE='latin1_swedish_ci' +; )" } + // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, diff --git a/common/database_schema.h b/common/database_schema.h index e0b87b94d3..1fdef741a2 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -357,6 +357,8 @@ namespace DatabaseSchema { "spawn2_disabled", "player_event_log_settings", "player_event_logs", + "player_event_loot_items", + "player_event_merchant_sell", "shared_task_activity_state", "shared_task_dynamic_zones", "shared_task_members", diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 4f4fd579d2..35cd7b106d 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -4,9 +4,10 @@ #include #include "../platform.h" -#include "../repositories/player_event_loot_items_repository.h" #include "../rulesys.h" #include "player_event_discord_formatter.h" +#include "../repositories/player_event_loot_items_repository.h" +#include "../repositories/player_event_merchant_sell_repository.h" const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour @@ -147,8 +148,27 @@ void PlayerEventLogs::ProcessBatchQueue() PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); // flush detailed tables - if (!m_record_loot_items.empty()) { - PlayerEventLootItemsRepository::InsertMany(*m_database, m_record_loot_items); + std::vector queue_14{}; + std::vector queue_16{}; + + if (!m_record_details_queue.empty()) { + for (auto const &[key, value]: m_record_details_queue) { + switch (key) { + case PlayerEvent::EventType::LOOT_ITEM: { + queue_14.push_back(std::any_cast(value)); + break; + } + case PlayerEvent::EventType::MERCHANT_SELL: { + queue_16.push_back(std::any_cast(value)); + break; + } + default: { + } + } + } + + if (!queue_14.empty()) { PlayerEventLootItemsRepository::InsertMany(*m_database, queue_14); } + if (!queue_16.empty()) { PlayerEventMerchantSellRepository::InsertMany(*m_database, queue_16); } } LogPlayerEventsDetail( @@ -159,7 +179,7 @@ void PlayerEventLogs::ProcessBatchQueue() // empty m_record_batch_queue.clear(); - m_record_loot_items.clear(); + m_record_details_queue.clear(); m_batch_queue_lock.unlock(); } @@ -174,6 +194,10 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log RecordDetailEvent(log); break; } + case PlayerEvent::EventType::MERCHANT_SELL: { + RecordDetailEvent(log); + break; + } default: { } } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 9a77b31ef7..b62f170c30 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -77,7 +77,7 @@ class PlayerEventLogs { : 0; IncrementDetailTableIDCache(static_cast(log.event_type_id)); - m_record_loot_items.push_back(out); + m_record_details_queue.emplace(static_cast(log.event_type_id), out); } [[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const; @@ -96,8 +96,7 @@ class PlayerEventLogs { static void FillPlayerEvent(const PlayerEvent::PlayerEvent &p, PlayerEventLogsRepository::PlayerEventLogs &n); static std::unique_ptr BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); - std::vector m_record_loot_items{}; - std::vector m_record_testing{}; + std::map m_record_details_queue{}; // timers Timer m_process_batch_events_timer; // events processing timer diff --git a/common/repositories/base/base_player_event_merchant_sell_repository.h b/common/repositories/base/base_player_event_merchant_sell_repository.h new file mode 100644 index 0000000000..badb80b9e9 --- /dev/null +++ b/common/repositories/base/base_player_event_merchant_sell_repository.h @@ -0,0 +1,515 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventMerchantSellRepository { +public: + struct PlayerEventMerchantSell { + uint64_t id; + uint32_t npc_id; + std::string merchant_name; + uint32_t merchant_type; + uint32_t item_id; + std::string item_name; + int32_t charges; + uint32_t cost; + uint32_t alternate_currency_id; + uint64_t player_money_balance; + uint64_t player_currency_balance; + + PlayerEventMerchantSell &operator=(const PlayerEvent::MerchantSellEvent &in) + { + npc_id = in.npc_id; + merchant_name = in.merchant_name; + merchant_type = in.merchant_type; + item_id = in.item_id; + item_name = in.item_name; + charges = in.charges; + cost = in.cost; + alternate_currency_id = in.alternate_currency_id; + player_money_balance = in.player_money_balance; + player_currency_balance = in.player_currency_balance; + + return *this; + } + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_merchant_sell"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventMerchantSell NewEntity() + { + PlayerEventMerchantSell e{}; + + e.id = 0; + e.npc_id = 0; + e.merchant_name = ""; + e.merchant_type = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.cost = 0; + e.alternate_currency_id = 0; + e.player_money_balance = 0; + e.player_currency_balance = 0; + + return e; + } + + static PlayerEventMerchantSell GetPlayerEventMerchantSell( + const std::vector &player_event_merchant_sells, + int player_event_merchant_sell_id + ) + { + for (auto &player_event_merchant_sell : player_event_merchant_sells) { + if (player_event_merchant_sell.id == player_event_merchant_sell_id) { + return player_event_merchant_sell; + } + } + + return NewEntity(); + } + + static PlayerEventMerchantSell FindOne( + Database& db, + int player_event_merchant_sell_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_merchant_sell_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventMerchantSell e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_merchant_sell_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_merchant_sell_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventMerchantSell &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.merchant_type)); + v.push_back(columns[4] + " = " + std::to_string(e.item_id)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.item_name) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.charges)); + v.push_back(columns[7] + " = " + std::to_string(e.cost)); + v.push_back(columns[8] + " = " + std::to_string(e.alternate_currency_id)); + v.push_back(columns[9] + " = " + std::to_string(e.player_money_balance)); + v.push_back(columns[10] + " = " + std::to_string(e.player_currency_balance)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventMerchantSell InsertOne( + Database& db, + PlayerEventMerchantSell e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantSell e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantSell e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventMerchantSell &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H diff --git a/common/repositories/player_event_log_settings_repository.h b/common/repositories/player_event_log_settings_repository.h index 2157c7e202..3edaa02158 100644 --- a/common/repositories/player_event_log_settings_repository.h +++ b/common/repositories/player_event_log_settings_repository.h @@ -5,6 +5,7 @@ #include "../events/player_events.h" #include "../strings.h" #include "base/base_player_event_log_settings_repository.h" +#include "base/base_player_event_loot_items_repository.h" class PlayerEventLogSettingsRepository: public BasePlayerEventLogSettingsRepository { public: @@ -53,5 +54,4 @@ class PlayerEventLogSettingsRepository: public BasePlayerEventLogSettingsReposit return results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) + 1 : 0; } }; - #endif //EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index f2659154ec..0bee6757c6 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -2,7 +2,6 @@ #define EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H #include "../database.h" -#include "../events/player_events.h" #include "../strings.h" #include "base/base_player_event_loot_items_repository.h" diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h new file mode 100644 index 0000000000..7c769fe94f --- /dev/null +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_merchant_sell_repository.h" + +class PlayerEventMerchantSellRepository: public BasePlayerEventMerchantSellRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventMerchantSellRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventMerchantSellRepository::GetWhereNeverExpires() + * PlayerEventMerchantSellRepository::GetWhereXAndY() + * PlayerEventMerchantSellRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H From abbd8eca05bac994f67f3a5e92797ced5d3b0057 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Wed, 16 Oct 2024 20:03:57 -0300 Subject: [PATCH 04/42] Example without RecordDetailEvent template --- common/events/player_event_logs.cpp | 57 ++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 35cd7b106d..149bea22c0 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -191,11 +191,64 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log switch (log.event_type_id) { case PlayerEvent::EventType::LOOT_ITEM: { - RecordDetailEvent(log); + //RecordDetailEvent(log); + PlayerEvent::LootItemEvent in{}; + PlayerEventLootItemsRepository::PlayerEventLootItems out{}; + + { + std::stringstream ss; + ss << log.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + //out = in; + out.charges = in.charges; + out.corpse_name = in.corpse_name; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.npc_id = in.npc_id; + + log.player_event_x_id = + GetDetailTableIDCache().contains(static_cast(log.event_type_id)) + ? GetDetailTableIDCache().at(static_cast(log.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(log.event_type_id)); + + m_record_details_queue.emplace(static_cast(log.event_type_id), out); break; } case PlayerEvent::EventType::MERCHANT_SELL: { - RecordDetailEvent(log); + //RecordDetailEvent(log); + PlayerEvent::MerchantSellEvent in{}; + PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; + + { + std::stringstream ss; + ss << log.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + //out = in; + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + + log.player_event_x_id = + GetDetailTableIDCache().contains(static_cast(log.event_type_id)) + ? GetDetailTableIDCache().at(static_cast(log.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(log.event_type_id)); + + m_record_details_queue.emplace(static_cast(log.event_type_id), out); break; } default: { From e21631b678152d4c2cfad8d85dcb7d056868bbd9 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:03:50 -0300 Subject: [PATCH 05/42] Cleanup the removal of the template --- common/events/player_event_logs.cpp | 14 ++++------- common/events/player_event_logs.h | 24 +------------------ .../base_player_event_loot_items_repository.h | 11 --------- ...se_player_event_merchant_sell_repository.h | 16 ------------- 4 files changed, 6 insertions(+), 59 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 149bea22c0..282f42369e 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -151,8 +151,8 @@ void PlayerEventLogs::ProcessBatchQueue() std::vector queue_14{}; std::vector queue_16{}; - if (!m_record_details_queue.empty()) { - for (auto const &[key, value]: m_record_details_queue) { + if (!m_record_etl_queue.empty()) { + for (auto const &[key, value]: m_record_etl_queue) { switch (key) { case PlayerEvent::EventType::LOOT_ITEM: { queue_14.push_back(std::any_cast(value)); @@ -179,7 +179,7 @@ void PlayerEventLogs::ProcessBatchQueue() // empty m_record_batch_queue.clear(); - m_record_details_queue.clear(); + m_record_etl_queue.clear(); m_batch_queue_lock.unlock(); } @@ -191,7 +191,6 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log switch (log.event_type_id) { case PlayerEvent::EventType::LOOT_ITEM: { - //RecordDetailEvent(log); PlayerEvent::LootItemEvent in{}; PlayerEventLootItemsRepository::PlayerEventLootItems out{}; @@ -202,7 +201,6 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log in.serialize(ar); } - //out = in; out.charges = in.charges; out.corpse_name = in.corpse_name; out.item_id = in.item_id; @@ -215,11 +213,10 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log : 0; IncrementDetailTableIDCache(static_cast(log.event_type_id)); - m_record_details_queue.emplace(static_cast(log.event_type_id), out); + m_record_etl_queue.emplace(static_cast(log.event_type_id), out); break; } case PlayerEvent::EventType::MERCHANT_SELL: { - //RecordDetailEvent(log); PlayerEvent::MerchantSellEvent in{}; PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; @@ -230,7 +227,6 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log in.serialize(ar); } - //out = in; out.npc_id = in.npc_id; out.merchant_name = in.merchant_name; out.merchant_type = in.merchant_type; @@ -248,7 +244,7 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log : 0; IncrementDetailTableIDCache(static_cast(log.event_type_id)); - m_record_details_queue.emplace(static_cast(log.event_type_id), out); + m_record_etl_queue.emplace(static_cast(log.event_type_id), out); break; } default: { diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index b62f170c30..ea571cd4ee 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -58,28 +58,6 @@ class PlayerEventLogs { return BuildPlayerEventPacket(c); } - template void RecordDetailEvent(PlayerEventLogsRepository::PlayerEventLogs &log) - { - I in{}; - O out{}; - - { - std::stringstream ss; - ss << log.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out = in; - log.player_event_x_id = - GetDetailTableIDCache().contains(static_cast(log.event_type_id)) - ? GetDetailTableIDCache().at(static_cast(log.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(log.event_type_id)); - - m_record_details_queue.emplace(static_cast(log.event_type_id), out); - } - [[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const; bool IsEventDiscordEnabled(int32_t event_type_id); std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id); @@ -96,7 +74,7 @@ class PlayerEventLogs { static void FillPlayerEvent(const PlayerEvent::PlayerEvent &p, PlayerEventLogsRepository::PlayerEventLogs &n); static std::unique_ptr BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); - std::map m_record_details_queue{}; + std::map m_record_etl_queue{}; // timers Timer m_process_batch_events_timer; // events processing timer diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h index deb1892c20..40e0d1946d 100644 --- a/common/repositories/base/base_player_event_loot_items_repository.h +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -25,17 +25,6 @@ class BasePlayerEventLootItemsRepository { int32_t charges; uint32_t npc_id; std::string corpse_name; - - PlayerEventLootItems &operator=(const PlayerEvent::LootItemEvent &in) - { - charges = in.charges; - corpse_name = in.corpse_name; - item_id = in.item_id; - item_name = in.item_name; - npc_id = in.npc_id; - - return *this; - } }; static std::string PrimaryKey() diff --git a/common/repositories/base/base_player_event_merchant_sell_repository.h b/common/repositories/base/base_player_event_merchant_sell_repository.h index badb80b9e9..47d9b0ca65 100644 --- a/common/repositories/base/base_player_event_merchant_sell_repository.h +++ b/common/repositories/base/base_player_event_merchant_sell_repository.h @@ -30,22 +30,6 @@ class BasePlayerEventMerchantSellRepository { uint32_t alternate_currency_id; uint64_t player_money_balance; uint64_t player_currency_balance; - - PlayerEventMerchantSell &operator=(const PlayerEvent::MerchantSellEvent &in) - { - npc_id = in.npc_id; - merchant_name = in.merchant_name; - merchant_type = in.merchant_type; - item_id = in.item_id; - item_name = in.item_name; - charges = in.charges; - cost = in.cost; - alternate_currency_id = in.alternate_currency_id; - player_money_balance = in.player_money_balance; - player_currency_balance = in.player_currency_balance; - - return *this; - } }; static std::string PrimaryKey() From 0d0e1e7570bc090de93fadf5b8a5d3327dc7c5b4 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Thu, 17 Oct 2024 23:11:23 -0300 Subject: [PATCH 06/42] Fourth Pass Add retention for etl tables Rename tables/fields to etl nomenclature Combine database work to one atomic load --- common/database/database_update_manifest.cpp | 27 ++-- common/events/player_event_logs.cpp | 87 ++++++++---- common/events/player_event_logs.h | 3 +- ...ase_player_event_log_settings_repository.h | 48 +++---- .../base/base_player_event_logs_repository.h | 130 +++++++++--------- .../player_event_logs_repository.h | 10 ++ 6 files changed, 172 insertions(+), 133 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 6008491e42..601679f280 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5809,15 +5809,18 @@ ADD COLUMN `shard_at_player_count` int(11) NULL DEFAULT 0 AFTER `seconds_before_ ManifestEntry{ .version = 9289, .description = "2024_10_08_add_detail_player_event_logging.sql", - .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'detail_logs'", + .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'etl_logging'", .condition = "empty", .match = "", .sql = R"( ALTER TABLE `player_event_log_settings` - ADD COLUMN `detail_logs` BIGINT(20) NOT NULL DEFAULT '0' AFTER `discord_webhook_id`, - ADD COLUMN `detail_table_name` VARCHAR(50) NULL DEFAULT NULL AFTER `detail_logs`; + ADD COLUMN `etl_logging` BIGINT(20) NOT NULL DEFAULT '0' AFTER `discord_webhook_id`, + ADD COLUMN `etl_table_name` VARCHAR(50) NULL DEFAULT NULL AFTER `etl_logging`; ALTER TABLE `player_event_logs` + ADD COLUMN `etl_table_id` BIGINT(20) NOT NULL DEFAULT '0' AFTER `event_data`; + +UPDATE `player_event_log_settings` SET `etl_logging` = 1, `etl_table_name` = 'player_event_loot_items' WHERE `id` = 14; ADD COLUMN `player_event_x_id` BIGINT(20) NOT NULL DEFAULT '0' AFTER `event_data`; )" }, @@ -5840,19 +5843,9 @@ CREATE TABLE `player_event_loot_items` ( PRIMARY KEY (`id`) USING BTREE ) COLLATE='latin1_swedish_ci' -ENGINE=InnoDB -AUTO_INCREMENT=1 -; -)" - }, - ManifestEntry{ - .version = 9287, - .description = "2024_10_08_remove_qs_logging.sql", - .check = "SHOW TABLES LIKE 'player_event_merchant_sell'", - .condition = "empty", - .match = "", - .sql = R"( -UPDATE `player_event_log_settings` SET `detail_logs` = 1, `detail_table_name` = 'player_event_merchant_sell' WHERE `id` = 16; +AUTO_INCREMENT=1; + +UPDATE `player_event_log_settings` SET `etl_logging` = 1, `etl_table_name` = 'player_event_merchant_sell' WHERE `id` = 16; CREATE TABLE `player_event_merchant_sell` ( `id` BIGINT UNSIGNED NULL AUTO_INCREMENT, @@ -5869,7 +5862,7 @@ CREATE TABLE `player_event_merchant_sell` ( PRIMARY KEY (`id`) ) COLLATE='latin1_swedish_ci' -; +AUTO_INCREMENT=1; )" } diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 282f42369e..9a2b1fe4c1 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -26,8 +26,8 @@ void PlayerEventLogs::Init() m_settings[i].event_enabled = 1; m_settings[i].retention_days = 0; m_settings[i].discord_webhook_id = 0; - m_settings[i].detail_logs = 0; - m_settings[i].detail_table_name = ""; + m_settings[i].etl_logging = 0; + m_settings[i].etl_table_name = ""; } SetSettingsDefaults(); @@ -67,13 +67,13 @@ void PlayerEventLogs::Init() if (is_missing_in_database && is_implemented && !is_deprecated) { LogInfo("[New] PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i); - auto c = PlayerEventLogSettingsRepository::NewEntity(); - c.id = i; - c.event_name = PlayerEvent::EventName[i]; - c.event_enabled = m_settings[i].event_enabled; - c.retention_days = m_settings[i].retention_days; - c.detail_logs = false; - c.detail_table_name = ""; + auto c = PlayerEventLogSettingsRepository::NewEntity(); + c.id = i; + c.event_name = PlayerEvent::EventName[i]; + c.event_enabled = m_settings[i].event_enabled; + c.retention_days = m_settings[i].retention_days; + c.etl_logging = false; + c.etl_table_name = ""; settings_to_insert.emplace_back(c); } } @@ -82,17 +82,7 @@ void PlayerEventLogs::Init() PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert); } - s = PlayerEventLogSettingsRepository::All(*m_database); - for (auto &e: s) { - if (e.id >= PlayerEvent::MAX) { - continue; - } - - if (e.detail_logs) { - auto last_id = PlayerEventLogSettingsRepository::GetNextIdForTable(*m_database, e.detail_table_name); - GetDetailTableIDCache().emplace(static_cast(e.id), last_id); - } - } + LoadETLIDs(); bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld(); bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ(); @@ -207,9 +197,9 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log out.item_name = in.item_name; out.npc_id = in.npc_id; - log.player_event_x_id = - GetDetailTableIDCache().contains(static_cast(log.event_type_id)) - ? GetDetailTableIDCache().at(static_cast(log.event_type_id)) + log.etl_table_id = + GetETLIDCache().contains(static_cast(log.event_type_id)) + ? GetETLIDCache().at(static_cast(log.event_type_id)) : 0; IncrementDetailTableIDCache(static_cast(log.event_type_id)); @@ -238,9 +228,9 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log out.player_money_balance = in.player_money_balance; out.player_currency_balance = in.player_currency_balance; - log.player_event_x_id = - GetDetailTableIDCache().contains(static_cast(log.event_type_id)) - ? GetDetailTableIDCache().at(static_cast(log.event_type_id)) + log.etl_table_id = + GetETLIDCache().contains(static_cast(log.event_type_id)) + ? GetETLIDCache().at(static_cast(log.event_type_id)) : 0; IncrementDetailTableIDCache(static_cast(log.event_type_id)); @@ -728,6 +718,32 @@ void PlayerEventLogs::ProcessRetentionTruncation() for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { if (m_settings[i].retention_days > 0) { + if (m_settings[i].etl_logging) { + auto results = PlayerEventLogsRepository::GetWhere( + *m_database, + fmt::format( + "event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)", + i, + m_settings[i].retention_days) + ); + if (!results.empty()) { + std::vector etl_ids{}; + for (auto const &r: results) { + etl_ids.push_back(std::to_string(r.etl_table_id)); + } + + auto deleted_count = PlayerEventLogsRepository::DeleteETLRecords(*m_database, m_settings[i].etl_table_name, etl_ids); + LogInfo( + "Truncated [{}] events of type [{}] ({}) older than [{}] days from etl table {}", + deleted_count, + PlayerEvent::EventName[i], + i, + m_settings[i].retention_days, + m_settings[i].etl_table_name + ); + } + } + int deleted_count = PlayerEventLogsRepository::DeleteWhere( *m_database, fmt::format( @@ -737,6 +753,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() ) ); + LoadETLIDs(); + if (deleted_count > 0) { LogInfo( "Truncated [{}] events of type [{}] ({}) older than [{}] days", @@ -823,3 +841,20 @@ void PlayerEventLogs::SetSettingsDefaults() m_settings[i].retention_days = RETENTION_DAYS_DEFAULT; } } + +void PlayerEventLogs::LoadETLIDs() +{ + GetETLIDCache().clear(); + + auto results = PlayerEventLogSettingsRepository::All(*m_database); + for (auto &e: results) { + if (e.id >= PlayerEvent::MAX) { + continue; + } + + if (e.etl_logging) { + auto last_id = PlayerEventLogSettingsRepository::GetNextIdForTable(*m_database, e.etl_table_name); + GetETLIDCache().emplace(static_cast(e.id), last_id); + } + } +} \ No newline at end of file diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index ea571cd4ee..90192ddfaf 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -16,11 +16,12 @@ class PlayerEventLogs { public: void Init(); void ReloadSettings(); + void LoadETLIDs(); void IncrementDetailTableIDCache(PlayerEvent::EventType event_type) { m_last_id_cache_detail_tables[event_type]++; } PlayerEventLogs *SetDatabase(Database *db); bool ValidateDatabaseConnection(); bool IsEventEnabled(PlayerEvent::EventType event); - std::map& GetDetailTableIDCache() { return m_last_id_cache_detail_tables; } + std::map& GetETLIDCache() { return m_last_id_cache_detail_tables; } void Process(); diff --git a/common/repositories/base/base_player_event_log_settings_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h index fd7caf11c7..a96bd7a65b 100644 --- a/common/repositories/base/base_player_event_log_settings_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -24,8 +24,8 @@ class BasePlayerEventLogSettingsRepository { int8_t event_enabled; int32_t retention_days; int32_t discord_webhook_id; - int32_t detail_logs; - std::string detail_table_name; + int64_t etl_logging; + std::string etl_table_name; }; static std::string PrimaryKey() @@ -41,8 +41,8 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", - "detail_logs", - "detail_table_name", + "etl_logging", + "etl_table_name", }; } @@ -54,8 +54,8 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", - "detail_logs", - "detail_table_name", + "etl_logging", + "etl_table_name", }; } @@ -101,8 +101,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = 0; e.retention_days = 0; e.discord_webhook_id = 0; - e.detail_logs = 0; - e.detail_table_name = ""; + e.etl_logging = 0; + e.etl_table_name = ""; return e; } @@ -144,8 +144,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.detail_logs = row[5] ? static_cast(atoi(row[5])) : 0; - e.detail_table_name = row[6] ? row[6] : ""; + e.etl_logging = row[5] ? strtoll(row[5], nullptr, 10) : 0; + e.etl_table_name = row[6] ? row[6] : ""; return e; } @@ -184,8 +184,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(columns[2] + " = " + std::to_string(e.event_enabled)); v.push_back(columns[3] + " = " + std::to_string(e.retention_days)); v.push_back(columns[4] + " = " + std::to_string(e.discord_webhook_id)); - v.push_back(columns[5] + " = " + std::to_string(e.detail_logs)); - v.push_back(columns[6] + " = '" + Strings::Escape(e.detail_table_name) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.etl_logging)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.etl_table_name) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -212,8 +212,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.detail_logs)); - v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); + v.push_back(std::to_string(e.etl_logging)); + v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -248,8 +248,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.detail_logs)); - v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); + v.push_back(std::to_string(e.etl_logging)); + v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -288,8 +288,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.detail_logs = row[5] ? static_cast(atoi(row[5])) : 0; - e.detail_table_name = row[6] ? row[6] : ""; + e.etl_logging = row[5] ? strtoll(row[5], nullptr, 10) : 0; + e.etl_table_name = row[6] ? row[6] : ""; all_entries.push_back(e); } @@ -319,8 +319,8 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.detail_logs = row[5] ? static_cast(atoi(row[5])) : 0; - e.detail_table_name = row[6] ? row[6] : ""; + e.etl_logging = row[5] ? strtoll(row[5], nullptr, 10) : 0; + e.etl_table_name = row[6] ? row[6] : ""; all_entries.push_back(e); } @@ -400,8 +400,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.detail_logs)); - v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); + v.push_back(std::to_string(e.etl_logging)); + v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -429,8 +429,8 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.detail_logs)); - v.push_back("'" + Strings::Escape(e.detail_table_name) + "'"); + v.push_back(std::to_string(e.etl_logging)); + v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_player_event_logs_repository.h b/common/repositories/base/base_player_event_logs_repository.h index 43145fa70a..3a23feec83 100644 --- a/common/repositories/base/base_player_event_logs_repository.h +++ b/common/repositories/base/base_player_event_logs_repository.h @@ -31,7 +31,7 @@ class BasePlayerEventLogsRepository { int32_t event_type_id; std::string event_type_name; std::string event_data; - uint64_t player_event_x_id; + int64_t etl_table_id; time_t created_at; // cereal @@ -51,7 +51,7 @@ class BasePlayerEventLogsRepository { CEREAL_NVP(event_type_id), CEREAL_NVP(event_type_name), CEREAL_NVP(event_data), - CEREAL_NVP(player_event_x_id), + CEREAL_NVP(etl_table_id), CEREAL_NVP(created_at) ); } @@ -77,7 +77,7 @@ class BasePlayerEventLogsRepository { "event_type_id", "event_type_name", "event_data", - "player_event_x_id", + "etl_table_id", "created_at", }; } @@ -97,7 +97,7 @@ class BasePlayerEventLogsRepository { "event_type_id", "event_type_name", "event_data", - "player_event_x_id", + "etl_table_id", "UNIX_TIMESTAMP(created_at)", }; } @@ -139,20 +139,20 @@ class BasePlayerEventLogsRepository { { PlayerEventLogs e{}; - e.id = 0; - e.account_id = 0; - e.character_id = 0; - e.zone_id = 0; - e.instance_id = 0; - e.x = 0; - e.y = 0; - e.z = 0; - e.heading = 0; - e.event_type_id = 0; - e.event_type_name = ""; - e.event_data = ""; - e.player_event_x_id = 0; - e.created_at = 0; + e.id = 0; + e.account_id = 0; + e.character_id = 0; + e.zone_id = 0; + e.instance_id = 0; + e.x = 0; + e.y = 0; + e.z = 0; + e.heading = 0; + e.event_type_id = 0; + e.event_type_name = ""; + e.event_data = ""; + e.etl_table_id = 0; + e.created_at = 0; return e; } @@ -189,20 +189,20 @@ class BasePlayerEventLogsRepository { if (results.RowCount() == 1) { PlayerEventLogs e{}; - e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; - e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; - e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; - e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; - e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.x = row[5] ? strtof(row[5], nullptr) : 0; - e.y = row[6] ? strtof(row[6], nullptr) : 0; - e.z = row[7] ? strtof(row[7], nullptr) : 0; - e.heading = row[8] ? strtof(row[8], nullptr) : 0; - e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; - e.event_type_name = row[10] ? row[10] : ""; - e.event_data = row[11] ? row[11] : ""; - e.player_event_x_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; - e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; + e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; + e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; + e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.x = row[5] ? strtof(row[5], nullptr) : 0; + e.y = row[6] ? strtof(row[6], nullptr) : 0; + e.z = row[7] ? strtof(row[7], nullptr) : 0; + e.heading = row[8] ? strtof(row[8], nullptr) : 0; + e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.etl_table_id = row[12] ? strtoll(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); return e; } @@ -247,7 +247,7 @@ class BasePlayerEventLogsRepository { v.push_back(columns[9] + " = " + std::to_string(e.event_type_id)); v.push_back(columns[10] + " = '" + Strings::Escape(e.event_type_name) + "'"); v.push_back(columns[11] + " = '" + Strings::Escape(e.event_data) + "'"); - v.push_back(columns[12] + " = " + std::to_string(e.player_event_x_id)); + v.push_back(columns[12] + " = " + std::to_string(e.etl_table_id)); v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -282,7 +282,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.player_event_x_id)); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -325,7 +325,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.player_event_x_id)); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); @@ -360,20 +360,20 @@ class BasePlayerEventLogsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLogs e{}; - e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; - e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; - e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; - e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; - e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.x = row[5] ? strtof(row[5], nullptr) : 0; - e.y = row[6] ? strtof(row[6], nullptr) : 0; - e.z = row[7] ? strtof(row[7], nullptr) : 0; - e.heading = row[8] ? strtof(row[8], nullptr) : 0; - e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; - e.event_type_name = row[10] ? row[10] : ""; - e.event_data = row[11] ? row[11] : ""; - e.player_event_x_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; - e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; + e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; + e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; + e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.x = row[5] ? strtof(row[5], nullptr) : 0; + e.y = row[6] ? strtof(row[6], nullptr) : 0; + e.z = row[7] ? strtof(row[7], nullptr) : 0; + e.heading = row[8] ? strtof(row[8], nullptr) : 0; + e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.etl_table_id = row[12] ? strtoll(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -398,20 +398,20 @@ class BasePlayerEventLogsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLogs e{}; - e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; - e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; - e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; - e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; - e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.x = row[5] ? strtof(row[5], nullptr) : 0; - e.y = row[6] ? strtof(row[6], nullptr) : 0; - e.z = row[7] ? strtof(row[7], nullptr) : 0; - e.heading = row[8] ? strtof(row[8], nullptr) : 0; - e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; - e.event_type_name = row[10] ? row[10] : ""; - e.event_data = row[11] ? row[11] : ""; - e.player_event_x_id = row[12] ? strtoull(row[12], nullptr, 10) : 0; - e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? strtoll(row[0], nullptr, 10) : 0; + e.account_id = row[1] ? strtoll(row[1], nullptr, 10) : 0; + e.character_id = row[2] ? strtoll(row[2], nullptr, 10) : 0; + e.zone_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.x = row[5] ? strtof(row[5], nullptr) : 0; + e.y = row[6] ? strtof(row[6], nullptr) : 0; + e.z = row[7] ? strtof(row[7], nullptr) : 0; + e.heading = row[8] ? strtof(row[8], nullptr) : 0; + e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; + e.event_type_name = row[10] ? row[10] : ""; + e.event_data = row[11] ? row[11] : ""; + e.etl_table_id = row[12] ? strtoll(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -498,7 +498,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.player_event_x_id)); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -534,7 +534,7 @@ class BasePlayerEventLogsRepository { v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); - v.push_back(std::to_string(e.player_event_x_id)); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); diff --git a/common/repositories/player_event_logs_repository.h b/common/repositories/player_event_logs_repository.h index 97a6d64312..f64be2f389 100644 --- a/common/repositories/player_event_logs_repository.h +++ b/common/repositories/player_event_logs_repository.h @@ -44,7 +44,17 @@ class PlayerEventLogsRepository: public BasePlayerEventLogsRepository { */ // Custom extended repository methods here + static uint32 DeleteETLRecords(Database &db, std::string &table_name, const std::vector &etl_ids) + { + auto const query = fmt::format("DELETE FROM {} WHERE `id` IN({})", table_name, Strings::Implode(", ", etl_ids)); + auto const results = db.QueryDatabase(query); + if (!results.Success()) { + return 0; + } + + return results.RowsAffected(); + } }; #endif //EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H From ff35f4f042146d0c678e95039b807505102fc6a8 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Thu, 17 Oct 2024 23:22:52 -0300 Subject: [PATCH 07/42] Reposition to reduce db tasks --- common/events/player_event_logs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 9a2b1fe4c1..a2f11f7597 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -753,8 +753,6 @@ void PlayerEventLogs::ProcessRetentionTruncation() ) ); - LoadETLIDs(); - if (deleted_count > 0) { LogInfo( "Truncated [{}] events of type [{}] ({}) older than [{}] days", @@ -766,6 +764,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() } } } + + LoadETLIDs(); } void PlayerEventLogs::ReloadSettings() From 43d32ae091de900e72e859245c7274f362df9405 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sat, 19 Oct 2024 23:18:23 -0300 Subject: [PATCH 08/42] Refactor etl processing for easier additions --- common/database/database_update_manifest.cpp | 9 +- common/events/player_event_logs.cpp | 70 +++++++------- common/events/player_event_logs.h | 28 ++++++ ...ase_player_event_log_settings_repository.h | 36 +++----- .../player_event_loot_items_repository.h | 91 ++++++++++++------- .../player_event_merchant_sell_repository.h | 30 ++++++ 6 files changed, 166 insertions(+), 98 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 601679f280..191859fb21 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5809,13 +5809,12 @@ ADD COLUMN `shard_at_player_count` int(11) NULL DEFAULT 0 AFTER `seconds_before_ ManifestEntry{ .version = 9289, .description = "2024_10_08_add_detail_player_event_logging.sql", - .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'etl_logging'", + .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'has_etl'", .condition = "empty", .match = "", .sql = R"( ALTER TABLE `player_event_log_settings` - ADD COLUMN `etl_logging` BIGINT(20) NOT NULL DEFAULT '0' AFTER `discord_webhook_id`, - ADD COLUMN `etl_table_name` VARCHAR(50) NULL DEFAULT NULL AFTER `etl_logging`; + ADD COLUMN `has_etl` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `discord_webhook_id`; ALTER TABLE `player_event_logs` ADD COLUMN `etl_table_id` BIGINT(20) NOT NULL DEFAULT '0' AFTER `event_data`; @@ -5831,7 +5830,7 @@ UPDATE `player_event_log_settings` SET `etl_logging` = 1, `etl_table_name` = 'pl .condition = "empty", .match = "", .sql = R"( -UPDATE `player_event_log_settings` SET `detail_logs` = 1, `detail_table_name` = 'player_event_loot_items' WHERE `id` = 14; +UPDATE `player_event_log_settings` SET `has_etl` = 1, `etl_table_name` = 'player_event_loot_items' WHERE `id` = 14; CREATE TABLE `player_event_loot_items` ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, @@ -5845,7 +5844,7 @@ CREATE TABLE `player_event_loot_items` ( COLLATE='latin1_swedish_ci' AUTO_INCREMENT=1; -UPDATE `player_event_log_settings` SET `etl_logging` = 1, `etl_table_name` = 'player_event_merchant_sell' WHERE `id` = 16; +UPDATE `player_event_log_settings` SET `has_etl` = 1, `etl_table_name` = 'player_event_merchant_sell' WHERE `id` = 16; CREATE TABLE `player_event_merchant_sell` ( `id` BIGINT UNSIGNED NULL AUTO_INCREMENT, diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index a2f11f7597..87c07a92d3 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -14,6 +14,7 @@ const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 // general initialization routine void PlayerEventLogs::Init() { + m_process_batch_events_timer.SetTimer(RuleI(Logging, BatchPlayerEventProcessIntervalSeconds) * 1000); m_process_retention_truncation_timer.SetTimer(PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL); @@ -26,8 +27,7 @@ void PlayerEventLogs::Init() m_settings[i].event_enabled = 1; m_settings[i].retention_days = 0; m_settings[i].discord_webhook_id = 0; - m_settings[i].etl_logging = 0; - m_settings[i].etl_table_name = ""; + m_settings[i].has_etl = 0; } SetSettingsDefaults(); @@ -72,8 +72,7 @@ void PlayerEventLogs::Init() c.event_name = PlayerEvent::EventName[i]; c.event_enabled = m_settings[i].event_enabled; c.retention_days = m_settings[i].retention_days; - c.etl_logging = false; - c.etl_table_name = ""; + c.has_etl = false; settings_to_insert.emplace_back(c); } } @@ -138,39 +137,29 @@ void PlayerEventLogs::ProcessBatchQueue() PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); // flush detailed tables - std::vector queue_14{}; - std::vector queue_16{}; - if (!m_record_etl_queue.empty()) { for (auto const &[key, value]: m_record_etl_queue) { - switch (key) { - case PlayerEvent::EventType::LOOT_ITEM: { - queue_14.push_back(std::any_cast(value)); - break; - } - case PlayerEvent::EventType::MERCHANT_SELL: { - queue_16.push_back(std::any_cast(value)); - break; - } - default: { - } - } + m_etl_data[key].etl_queue.push_back(value); } - if (!queue_14.empty()) { PlayerEventLootItemsRepository::InsertMany(*m_database, queue_14); } - if (!queue_16.empty()) { PlayerEventMerchantSellRepository::InsertMany(*m_database, queue_16); } - } + for (auto &[key, value]:m_etl_data) { + if (!value.etl_queue.empty()) { + value.etl_load_func_ptr(*m_database, value.etl_queue); + value.etl_queue.clear(); + } + } - LogPlayerEventsDetail( - "Processing batch player event log queue of [{}] took [{}]", - m_record_batch_queue.size(), - benchmark.elapsed() - ); + LogPlayerEventsDetail( + "Processing batch player event log queue of [{}] took [{}]", + m_record_batch_queue.size(), + benchmark.elapsed() + ); - // empty - m_record_batch_queue.clear(); - m_record_etl_queue.clear(); + // empty + m_record_batch_queue.clear(); + m_record_etl_queue.clear(); + } m_batch_queue_lock.unlock(); } @@ -718,7 +707,7 @@ void PlayerEventLogs::ProcessRetentionTruncation() for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { if (m_settings[i].retention_days > 0) { - if (m_settings[i].etl_logging) { + if (m_settings[i].has_etl) { auto results = PlayerEventLogsRepository::GetWhere( *m_database, fmt::format( @@ -732,14 +721,14 @@ void PlayerEventLogs::ProcessRetentionTruncation() etl_ids.push_back(std::to_string(r.etl_table_id)); } - auto deleted_count = PlayerEventLogsRepository::DeleteETLRecords(*m_database, m_settings[i].etl_table_name, etl_ids); + auto deleted_count = PlayerEventLogsRepository::DeleteETLRecords(*m_database, m_etl_data[static_cast(i)].etl_table_name, etl_ids); LogInfo( "Truncated [{}] events of type [{}] ({}) older than [{}] days from etl table {}", deleted_count, PlayerEvent::EventName[i], i, m_settings[i].retention_days, - m_settings[i].etl_table_name + m_etl_data[static_cast(i)].etl_table_name ); } } @@ -852,9 +841,18 @@ void PlayerEventLogs::LoadETLIDs() continue; } - if (e.etl_logging) { - auto last_id = PlayerEventLogSettingsRepository::GetNextIdForTable(*m_database, e.etl_table_name); + if (e.has_etl) { + if (!m_etl_data.contains(static_cast(e.id))) { + LogError( + "Error retrieving Event Type [{}]. Database mismatch. Check 'has_etl' field in " + "player_event_log_settings", + e.id); + return; + } + + auto etl_table_name = m_etl_data.at(static_cast(e.id)).etl_table_name; + auto last_id = PlayerEventLogSettingsRepository::GetNextIdForTable(*m_database, etl_table_name); GetETLIDCache().emplace(static_cast(e.id), last_id); } } -} \ No newline at end of file +} diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 90192ddfaf..c8de2cf060 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -11,6 +11,7 @@ #include "../servertalk.h" #include "../timer.h" #include "../repositories/player_event_loot_items_repository.h" +#include "../repositories/player_event_merchant_sell_repository.h" class PlayerEventLogs { public: @@ -86,6 +87,33 @@ class PlayerEventLogs { void ProcessBatchQueue(); void ProcessRetentionTruncation(); void SetSettingsDefaults(); + +public: + struct EtlInfo_Struct { + std::string etl_table_name; + std::vector etl_queue; + std::function &)> etl_load_func_ptr; + }; + + std::map m_etl_data = { + { + PlayerEvent::LOOT_ITEM, + { + .etl_table_name = "player_event_loot_items", + .etl_queue = {}, + .etl_load_func_ptr = {&PlayerEventLootItemsRepository::InsertManyFromStdAny}, + } + }, + { + PlayerEvent::MERCHANT_SELL, + { + .etl_table_name = "player_event_merchant_sell", + .etl_queue = {}, + .etl_load_func_ptr = { &PlayerEventMerchantSellRepository::InsertManyFromStdAny }, + } + } + }; + }; extern PlayerEventLogs player_event_logs; diff --git a/common/repositories/base/base_player_event_log_settings_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h index a96bd7a65b..c06ce0f37b 100644 --- a/common/repositories/base/base_player_event_log_settings_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -24,8 +24,7 @@ class BasePlayerEventLogSettingsRepository { int8_t event_enabled; int32_t retention_days; int32_t discord_webhook_id; - int64_t etl_logging; - std::string etl_table_name; + uint8_t has_etl; }; static std::string PrimaryKey() @@ -41,8 +40,7 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", - "etl_logging", - "etl_table_name", + "has_etl", }; } @@ -54,8 +52,7 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", - "etl_logging", - "etl_table_name", + "has_etl", }; } @@ -101,8 +98,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = 0; e.retention_days = 0; e.discord_webhook_id = 0; - e.etl_logging = 0; - e.etl_table_name = ""; + e.has_etl = 0; return e; } @@ -144,8 +140,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.etl_logging = row[5] ? strtoll(row[5], nullptr, 10) : 0; - e.etl_table_name = row[6] ? row[6] : ""; + e.has_etl = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; return e; } @@ -184,8 +179,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(columns[2] + " = " + std::to_string(e.event_enabled)); v.push_back(columns[3] + " = " + std::to_string(e.retention_days)); v.push_back(columns[4] + " = " + std::to_string(e.discord_webhook_id)); - v.push_back(columns[5] + " = " + std::to_string(e.etl_logging)); - v.push_back(columns[6] + " = '" + Strings::Escape(e.etl_table_name) + "'"); + v.push_back(columns[5] + " = " + std::to_string(e.has_etl)); auto results = db.QueryDatabase( fmt::format( @@ -212,8 +206,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.etl_logging)); - v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); + v.push_back(std::to_string(e.has_etl)); auto results = db.QueryDatabase( fmt::format( @@ -248,8 +241,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.etl_logging)); - v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); + v.push_back(std::to_string(e.has_etl)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -288,8 +280,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.etl_logging = row[5] ? strtoll(row[5], nullptr, 10) : 0; - e.etl_table_name = row[6] ? row[6] : ""; + e.has_etl = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -319,8 +310,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.etl_logging = row[5] ? strtoll(row[5], nullptr, 10) : 0; - e.etl_table_name = row[6] ? row[6] : ""; + e.has_etl = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -400,8 +390,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.etl_logging)); - v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); + v.push_back(std::to_string(e.has_etl)); auto results = db.QueryDatabase( fmt::format( @@ -429,8 +418,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.etl_logging)); - v.push_back("'" + Strings::Escape(e.etl_table_name) + "'"); + v.push_back(std::to_string(e.has_etl)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index 0bee6757c6..647f8f5601 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -9,39 +9,64 @@ class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository public: /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventLootItemsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventLootItemsRepository::GetWhereNeverExpires() - * PlayerEventLootItemsRepository::GetWhereXAndY() - * PlayerEventLootItemsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventLootItemsRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventLootItemsRepository::GetWhereNeverExpires() + * PlayerEventLootItemsRepository::GetWhereXAndY() + * PlayerEventLootItemsRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + static int InsertManyFromStdAny(Database &db, const std::vector &entries) + { + std::vector insert_chunks; + + for (auto &r: entries) { + auto e = std::any_cast(r); + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = + db.QueryDatabase(fmt::format("{} VALUES {}", BaseInsert(), Strings::Implode(",", insert_chunks))); + + return results.Success() ? results.RowsAffected() : 0; + } }; #endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h index 7c769fe94f..bdf46c952d 100644 --- a/common/repositories/player_event_merchant_sell_repository.h +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -44,7 +44,37 @@ class PlayerEventMerchantSellRepository: public BasePlayerEventMerchantSellRepos */ // Custom extended repository methods here + static int InsertManyFromStdAny(Database &db, const std::vector &entries) + { + std::vector insert_chunks; + for (auto &r: entries) { + auto e = std::any_cast(r); + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = + db.QueryDatabase(fmt::format("{} VALUES {}", BaseInsert(), Strings::Implode(",", insert_chunks)) + ); + + return results.Success() ? results.RowsAffected() : 0; + } }; #endif //EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H From 9356a9f5fa37bb4d5d57e852176dd847ef89285f Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 20 Oct 2024 11:54:26 -0300 Subject: [PATCH 09/42] Add merchant purchase event testing passed though appears that the event itself has a few bugs. Will fix them in another commit --- common/CMakeLists.txt | 2 + common/database/database_update_manifest.cpp | 19 + common/events/player_event_logs.cpp | 32 ++ common/events/player_event_logs.h | 22 +- ...layer_event_merchant_purchase_repository.h | 499 ++++++++++++++++++ ...layer_event_merchant_purchase_repository.h | 80 +++ 6 files changed, 648 insertions(+), 6 deletions(-) create mode 100644 common/repositories/base/base_player_event_merchant_purchase_repository.h create mode 100644 common/repositories/player_event_merchant_purchase_repository.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 450917b0ed..6b00c4f312 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -280,6 +280,7 @@ SET(repositories repositories/base/base_player_event_log_settings_repository.h repositories/base/base_player_event_logs_repository.h repositories/base/base_player_event_loot_items_repository.h + repositories/base/base_player_event_merchant_purchase_repository.h repositories/base/base_player_event_merchant_sell_repository.h repositories/base/base_quest_globals_repository.h repositories/base/base_raid_details_repository.h @@ -465,6 +466,7 @@ SET(repositories repositories/player_event_log_settings_repository.h repositories/player_event_logs_repository.h repositories/player_event_loot_items_repository.h + repositories/player_event_merchant_purchase_repository.h repositories/player_event_merchant_sell_repository.h repositories/quest_globals_repository.h repositories/raid_details_repository.h diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 191859fb21..61b56773ed 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5862,6 +5862,25 @@ CREATE TABLE `player_event_merchant_sell` ( ) COLLATE='latin1_swedish_ci' AUTO_INCREMENT=1; + +UPDATE `player_event_log_settings` SET `has_etl` = 1, `etl_table_name` = 'player_event_merchant_purchase' WHERE `id` = 15; + +CREATE TABLE `player_event_merchant_purchase` ( + `id` BIGINT UNSIGNED NULL AUTO_INCREMENT, + `npc_id` INT UNSIGNED NULL DEFAULT '0', + `merchant_name` VARCHAR(64) NULL DEFAULT NULL, + `merchant_type` INT UNSIGNED NULL DEFAULT '0', + `item_id` INT UNSIGNED NULL DEFAULT '0', + `item_name` VARCHAR(64) NULL DEFAULT NULL, + `charges` INT NULL DEFAULT '0', + `cost` INT UNSIGNED NULL DEFAULT '0', + `alternate_currency_id` INT UNSIGNED NULL DEFAULT '0', + `player_money_balance` BIGINT UNSIGNED NULL DEFAULT '0', + `player_currency_balance` BIGINT UNSIGNED NULL DEFAULT '0', + PRIMARY KEY (`id`) +) +COLLATE='latin1_swedish_ci' +AUTO_INCREMENT=1; )" } diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 87c07a92d3..c1c5fb9db8 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -8,6 +8,7 @@ #include "player_event_discord_formatter.h" #include "../repositories/player_event_loot_items_repository.h" #include "../repositories/player_event_merchant_sell_repository.h" +#include "../repositories/player_event_merchant_purchase_repository.h" const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour @@ -226,6 +227,37 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log m_record_etl_queue.emplace(static_cast(log.event_type_id), out); break; } + case PlayerEvent::EventType::MERCHANT_PURCHASE: { + PlayerEvent::MerchantPurchaseEvent in{}; + PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; + + { + std::stringstream ss; + ss << log.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + + log.etl_table_id = + GetETLIDCache().contains(static_cast(log.event_type_id)) + ? GetETLIDCache().at(static_cast(log.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(log.event_type_id)); + + m_record_etl_queue.emplace(static_cast(log.event_type_id), out); + break; + } default: { } } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index c8de2cf060..7c214652ad 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -12,6 +12,7 @@ #include "../timer.h" #include "../repositories/player_event_loot_items_repository.h" #include "../repositories/player_event_merchant_sell_repository.h" +#include "../repositories/player_event_merchant_purchase_repository.h" class PlayerEventLogs { public: @@ -99,19 +100,28 @@ class PlayerEventLogs { { PlayerEvent::LOOT_ITEM, { - .etl_table_name = "player_event_loot_items", - .etl_queue = {}, - .etl_load_func_ptr = {&PlayerEventLootItemsRepository::InsertManyFromStdAny}, + .etl_table_name = "player_event_loot_items", + .etl_queue = {}, + .etl_load_func_ptr = { &PlayerEventLootItemsRepository::InsertManyFromStdAny }, } }, { PlayerEvent::MERCHANT_SELL, { - .etl_table_name = "player_event_merchant_sell", - .etl_queue = {}, - .etl_load_func_ptr = { &PlayerEventMerchantSellRepository::InsertManyFromStdAny }, + .etl_table_name = "player_event_merchant_sell", + .etl_queue = {}, + .etl_load_func_ptr = { &PlayerEventMerchantSellRepository::InsertManyFromStdAny }, } + }, + { + PlayerEvent::MERCHANT_PURCHASE, + { + .etl_table_name = "player_event_merchant_purchase", + .etl_queue = {}, + .etl_load_func_ptr = { &PlayerEventMerchantPurchaseRepository::InsertManyFromStdAny }, + } } + }; }; diff --git a/common/repositories/base/base_player_event_merchant_purchase_repository.h b/common/repositories/base/base_player_event_merchant_purchase_repository.h new file mode 100644 index 0000000000..af32d46e9b --- /dev/null +++ b/common/repositories/base/base_player_event_merchant_purchase_repository.h @@ -0,0 +1,499 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventMerchantPurchaseRepository { +public: + struct PlayerEventMerchantPurchase { + uint64_t id; + uint32_t npc_id; + std::string merchant_name; + uint32_t merchant_type; + uint32_t item_id; + std::string item_name; + int32_t charges; + uint32_t cost; + uint32_t alternate_currency_id; + uint64_t player_money_balance; + uint64_t player_currency_balance; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_merchant_purchase"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventMerchantPurchase NewEntity() + { + PlayerEventMerchantPurchase e{}; + + e.id = 0; + e.npc_id = 0; + e.merchant_name = ""; + e.merchant_type = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.cost = 0; + e.alternate_currency_id = 0; + e.player_money_balance = 0; + e.player_currency_balance = 0; + + return e; + } + + static PlayerEventMerchantPurchase GetPlayerEventMerchantPurchase( + const std::vector &player_event_merchant_purchases, + int player_event_merchant_purchase_id + ) + { + for (auto &player_event_merchant_purchase : player_event_merchant_purchases) { + if (player_event_merchant_purchase.id == player_event_merchant_purchase_id) { + return player_event_merchant_purchase; + } + } + + return NewEntity(); + } + + static PlayerEventMerchantPurchase FindOne( + Database& db, + int player_event_merchant_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_merchant_purchase_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventMerchantPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_merchant_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_merchant_purchase_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventMerchantPurchase &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.merchant_type)); + v.push_back(columns[4] + " = " + std::to_string(e.item_id)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.item_name) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.charges)); + v.push_back(columns[7] + " = " + std::to_string(e.cost)); + v.push_back(columns[8] + " = " + std::to_string(e.alternate_currency_id)); + v.push_back(columns[9] + " = " + std::to_string(e.player_money_balance)); + v.push_back(columns[10] + " = " + std::to_string(e.player_currency_balance)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventMerchantPurchase InsertOne( + Database& db, + PlayerEventMerchantPurchase e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventMerchantPurchase &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_purchase_repository.h b/common/repositories/player_event_merchant_purchase_repository.h new file mode 100644 index 0000000000..75a476e6db --- /dev/null +++ b/common/repositories/player_event_merchant_purchase_repository.h @@ -0,0 +1,80 @@ +#ifndef EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_merchant_purchase_repository.h" + +class PlayerEventMerchantPurchaseRepository: public BasePlayerEventMerchantPurchaseRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventMerchantPurchaseRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventMerchantPurchaseRepository::GetWhereNeverExpires() + * PlayerEventMerchantPurchaseRepository::GetWhereXAndY() + * PlayerEventMerchantPurchaseRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + static int InsertManyFromStdAny(Database &db, const std::vector &entries) + { + std::vector insert_chunks; + + for (auto &r: entries) { + auto e = std::any_cast(r); + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = + db.QueryDatabase(fmt::format("{} VALUES {}", BaseInsert(), Strings::Implode(",", insert_chunks)) + ); + + return results.Success() ? results.RowsAffected() : 0; + } +}; + +#endif //EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H From 4524f6a17fd19fbca83ce2b62fbcdcfd4b61b337 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 20 Oct 2024 14:06:04 -0300 Subject: [PATCH 10/42] Fix PlayerEventMerchantPurchase in client_packet.cpp --- zone/client_packet.cpp | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 55085620ff..bf0a791c46 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13914,8 +13914,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) sizeof(Merchant_Sell_Struct), app->size); return; } - RDTSC_Timer t1; - t1.start(); + Merchant_Sell_Struct* mp = (Merchant_Sell_Struct*)app->pBuffer; #if EQDEBUG >= 5 LogDebug("[{}], purchase item", GetName()); @@ -14116,8 +14115,6 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) SendItemPacket(mp->itemslot, inst, ItemPacketMerchant); } } - safe_delete(inst); - safe_delete(outapp); if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_PURCHASE)) { auto e = PlayerEvent::MerchantPurchaseEvent{ @@ -14204,23 +14201,6 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) parse->EventPlayer(EVENT_MERCHANT_BUY, this, export_string, 0); } - if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_PURCHASE)) { - auto e = PlayerEvent::MerchantPurchaseEvent{ - .npc_id = tmp->GetNPCTypeID(), - .merchant_name = tmp->GetCleanName(), - .merchant_type = tmp->CastToNPC()->MerchantType, - .item_id = item->ID, - .item_name = item->Name, - .charges = static_cast(mpo->quantity), - .cost = mpo->price, - .alternate_currency_id = 0, - .player_money_balance = GetCarriedMoney(), - .player_currency_balance = 0, - }; - RecordPlayerEventLog(PlayerEvent::MERCHANT_PURCHASE, e); - } - - if (RuleB(Character, EnableDiscoveredItems) && !IsDiscovered(item_id)) { if (!GetGM()) { DiscoverItem(item_id); @@ -14236,9 +14216,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) } } - t1.stop(); - std::cout << "At 1: " << t1.getDuration() << std::endl; - return; + safe_delete(inst); + safe_delete(outapp); } void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) { From 3899d92f23ce9379f1a89eae00638c4b8b737fad Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 20 Oct 2024 14:10:39 -0300 Subject: [PATCH 11/42] WIP - Handin --- common/CMakeLists.txt | 4 + common/events/player_event_logs.cpp | 56 +- ...ayer_event_npc_handin_entries_repository.h | 523 ++++++++++++++++++ .../base_player_event_npc_handin_repository.h | 511 +++++++++++++++++ ...ayer_event_npc_handin_entries_repository.h | 50 ++ .../player_event_npc_handin_repository.h | 50 ++ 6 files changed, 1189 insertions(+), 5 deletions(-) create mode 100644 common/repositories/base/base_player_event_npc_handin_entries_repository.h create mode 100644 common/repositories/base/base_player_event_npc_handin_repository.h create mode 100644 common/repositories/player_event_npc_handin_entries_repository.h create mode 100644 common/repositories/player_event_npc_handin_repository.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6b00c4f312..ecb12a29e3 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -282,6 +282,8 @@ SET(repositories repositories/base/base_player_event_loot_items_repository.h repositories/base/base_player_event_merchant_purchase_repository.h repositories/base/base_player_event_merchant_sell_repository.h + repositories/base/base_player_event_npc_handin_repository.h + repositories/base/base_player_event_npc_handin_entries_repository.h repositories/base/base_quest_globals_repository.h repositories/base/base_raid_details_repository.h repositories/base/base_raid_members_repository.h @@ -468,6 +470,8 @@ SET(repositories repositories/player_event_loot_items_repository.h repositories/player_event_merchant_purchase_repository.h repositories/player_event_merchant_sell_repository.h + repositories/player_event_npc_handin_repository.h + repositories/player_event_npc_handin_entries_repository.h repositories/quest_globals_repository.h repositories/raid_details_repository.h repositories/raid_members_repository.h diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index c1c5fb9db8..f8265ce751 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -9,6 +9,8 @@ #include "../repositories/player_event_loot_items_repository.h" #include "../repositories/player_event_merchant_sell_repository.h" #include "../repositories/player_event_merchant_purchase_repository.h" +#include "../repositories/player_event_npc_handin_repository.h" +#include "../repositories/player_event_npc_handin_entries_repository.h" const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour @@ -155,12 +157,11 @@ void PlayerEventLogs::ProcessBatchQueue() m_record_batch_queue.size(), benchmark.elapsed() ); - - // empty - m_record_batch_queue.clear(); - m_record_etl_queue.clear(); - } + + // empty + m_record_batch_queue.clear(); + m_record_etl_queue.clear(); m_batch_queue_lock.unlock(); } @@ -238,6 +239,51 @@ void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log in.serialize(ar); } + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + + log.etl_table_id = + GetETLIDCache().contains(static_cast(log.event_type_id)) + ? GetETLIDCache().at(static_cast(log.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(log.event_type_id)); + + m_record_etl_queue.emplace(static_cast(log.event_type_id), out); + break; + } + case PlayerEvent::EventType::NPC_HANDIN: { + PlayerEvent::HandinEvent in{}; + PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; + PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries out_entries{}; + + { + std::stringstream ss; + ss << log.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.handin_copper = in.handin_money.copper; + out.handin_silver = in.handin_money.silver; + out.handin_gold = in.handin_money.gold; + out.handin_platinum = in.handin_money.platinum; + out.return_copper = in.return_money.copper; + out.return_silver = in.return_money.silver; + out.return_gold = in.return_money.gold; + out.return_platinum = in.return_money.platinum; + out.is_quest_handin = in.is_quest_handin; + + out.npc_id = in.npc_id; out.merchant_name = in.merchant_name; out.merchant_type = in.merchant_type; diff --git a/common/repositories/base/base_player_event_npc_handin_entries_repository.h b/common/repositories/base/base_player_event_npc_handin_entries_repository.h new file mode 100644 index 0000000000..4d2ee2ead8 --- /dev/null +++ b/common/repositories/base/base_player_event_npc_handin_entries_repository.h @@ -0,0 +1,523 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventNpcHandinEntriesRepository { +public: + struct PlayerEventNpcHandinEntries { + uint64_t id; + uint64_t player_event_npc_handin_id; + uint32_t type; + uint32_t item_id; + int32_t charges; + uint32_t evolve_level; + uint64_t evolve_amount; + uint32_t augment_1_id; + uint32_t augment_2_id; + uint32_t augment_3_id; + uint32_t augment_4_id; + uint32_t augment_5_id; + uint32_t augment_6_id; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "player_event_npc_handin_id", + "type", + "item_id", + "charges", + "evolve_level", + "evolve_amount", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "player_event_npc_handin_id", + "type", + "item_id", + "charges", + "evolve_level", + "evolve_amount", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_npc_handin_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventNpcHandinEntries NewEntity() + { + PlayerEventNpcHandinEntries e{}; + + e.id = 0; + e.player_event_npc_handin_id = 0; + e.type = 0; + e.item_id = 0; + e.charges = 0; + e.evolve_level = 0; + e.evolve_amount = 0; + e.augment_1_id = 0; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 0; + e.augment_5_id = 0; + e.augment_6_id = 0; + + return e; + } + + static PlayerEventNpcHandinEntries GetPlayerEventNpcHandinEntries( + const std::vector &player_event_npc_handin_entriess, + int player_event_npc_handin_entries_id + ) + { + for (auto &player_event_npc_handin_entries : player_event_npc_handin_entriess) { + if (player_event_npc_handin_entries.id == player_event_npc_handin_entries_id) { + return player_event_npc_handin_entries; + } + } + + return NewEntity(); + } + + static PlayerEventNpcHandinEntries FindOne( + Database& db, + int player_event_npc_handin_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_npc_handin_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventNpcHandinEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_npc_handin_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.type = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.evolve_level = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.evolve_amount = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.augment_1_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_2_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_3_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_4_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_5_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.augment_6_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_npc_handin_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_npc_handin_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventNpcHandinEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.player_event_npc_handin_id)); + v.push_back(columns[2] + " = " + std::to_string(e.type)); + v.push_back(columns[3] + " = " + std::to_string(e.item_id)); + v.push_back(columns[4] + " = " + std::to_string(e.charges)); + v.push_back(columns[5] + " = " + std::to_string(e.evolve_level)); + v.push_back(columns[6] + " = " + std::to_string(e.evolve_amount)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_1_id)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_2_id)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_3_id)); + v.push_back(columns[10] + " = " + std::to_string(e.augment_4_id)); + v.push_back(columns[11] + " = " + std::to_string(e.augment_5_id)); + v.push_back(columns[12] + " = " + std::to_string(e.augment_6_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventNpcHandinEntries InsertOne( + Database& db, + PlayerEventNpcHandinEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandinEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_npc_handin_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.type = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.evolve_level = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.evolve_amount = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.augment_1_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_2_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_3_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_4_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_5_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.augment_6_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandinEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_npc_handin_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.type = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.evolve_level = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.evolve_amount = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.augment_1_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_2_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_3_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_4_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_5_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.augment_6_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventNpcHandinEntries &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_npc_handin_repository.h b/common/repositories/base/base_player_event_npc_handin_repository.h new file mode 100644 index 0000000000..ec6af19727 --- /dev/null +++ b/common/repositories/base/base_player_event_npc_handin_repository.h @@ -0,0 +1,511 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventNpcHandinRepository { +public: + struct PlayerEventNpcHandin { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint64_t handin_copper; + uint64_t handin_silver; + uint64_t handin_gold; + uint64_t handin_platinum; + uint64_t return_copper; + uint64_t return_silver; + uint64_t return_gold; + uint64_t return_platinum; + uint8_t is_quest_handin; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "handin_copper", + "handin_silver", + "handin_gold", + "handin_platinum", + "return_copper", + "return_silver", + "return_gold", + "return_platinum", + "is_quest_handin", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "handin_copper", + "handin_silver", + "handin_gold", + "handin_platinum", + "return_copper", + "return_silver", + "return_gold", + "return_platinum", + "is_quest_handin", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_npc_handin"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventNpcHandin NewEntity() + { + PlayerEventNpcHandin e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.handin_copper = 0; + e.handin_silver = 0; + e.handin_gold = 0; + e.handin_platinum = 0; + e.return_copper = 0; + e.return_silver = 0; + e.return_gold = 0; + e.return_platinum = 0; + e.is_quest_handin = 0; + + return e; + } + + static PlayerEventNpcHandin GetPlayerEventNpcHandin( + const std::vector &player_event_npc_handins, + int player_event_npc_handin_id + ) + { + for (auto &player_event_npc_handin : player_event_npc_handins) { + if (player_event_npc_handin.id == player_event_npc_handin_id) { + return player_event_npc_handin; + } + } + + return NewEntity(); + } + + static PlayerEventNpcHandin FindOne( + Database& db, + int player_event_npc_handin_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_npc_handin_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventNpcHandin e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.handin_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.handin_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.handin_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.handin_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.return_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.return_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_npc_handin_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_npc_handin_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventNpcHandin &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.handin_copper)); + v.push_back(columns[4] + " = " + std::to_string(e.handin_silver)); + v.push_back(columns[5] + " = " + std::to_string(e.handin_gold)); + v.push_back(columns[6] + " = " + std::to_string(e.handin_platinum)); + v.push_back(columns[7] + " = " + std::to_string(e.return_copper)); + v.push_back(columns[8] + " = " + std::to_string(e.return_silver)); + v.push_back(columns[9] + " = " + std::to_string(e.return_gold)); + v.push_back(columns[10] + " = " + std::to_string(e.return_platinum)); + v.push_back(columns[11] + " = " + std::to_string(e.is_quest_handin)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventNpcHandin InsertOne( + Database& db, + PlayerEventNpcHandin e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandin e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.handin_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.handin_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.handin_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.handin_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.return_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.return_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandin e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.handin_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.handin_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.handin_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.handin_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.return_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.return_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventNpcHandin &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_entries_repository.h b/common/repositories/player_event_npc_handin_entries_repository.h new file mode 100644 index 0000000000..e1c95bb3fb --- /dev/null +++ b/common/repositories/player_event_npc_handin_entries_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_npc_handin_entries_repository.h" + +class PlayerEventNpcHandinEntriesRepository: public BasePlayerEventNpcHandinEntriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventNpcHandinEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventNpcHandinEntriesRepository::GetWhereNeverExpires() + * PlayerEventNpcHandinEntriesRepository::GetWhereXAndY() + * PlayerEventNpcHandinEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_repository.h b/common/repositories/player_event_npc_handin_repository.h new file mode 100644 index 0000000000..d01a24c745 --- /dev/null +++ b/common/repositories/player_event_npc_handin_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_npc_handin_repository.h" + +class PlayerEventNpcHandinRepository: public BasePlayerEventNpcHandinRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventNpcHandinRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventNpcHandinRepository::GetWhereNeverExpires() + * PlayerEventNpcHandinRepository::GetWhereXAndY() + * PlayerEventNpcHandinRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H From 06c61b17220a0c4c1bde304330c29bf02582aa1c Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 20 Oct 2024 16:39:21 -0300 Subject: [PATCH 12/42] Handin Event added --- common/events/player_event_logs.cpp | 430 +++++++++++++++++----------- common/events/player_event_logs.h | 47 +-- 2 files changed, 266 insertions(+), 211 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index f8265ce751..b5d700eb7c 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -136,27 +136,230 @@ void PlayerEventLogs::ProcessBatchQueue() BenchTimer benchmark; + EtlQueues_Struct etl_queues{}; + auto out_entries_next_id = PlayerEventNpcHandinEntriesRepository::GetMaxId(*m_database) + 1; + + for (auto &r:m_record_batch_queue) { + switch (r.event_type_id) { + case PlayerEvent::EventType::LOOT_ITEM: { + PlayerEvent::LootItemEvent in{}; + PlayerEventLootItemsRepository::PlayerEventLootItems out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.charges = in.charges; + out.corpse_name = in.corpse_name; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.npc_id = in.npc_id; + + r.etl_table_id = + GetETLIDCache().contains(static_cast(r.event_type_id)) + ? GetETLIDCache().at(static_cast(r.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(r.event_type_id)); + + etl_queues.queue_14.push_back(out); + m_record_etl_queue.emplace(static_cast(r.event_type_id), out); + break; + } + case PlayerEvent::EventType::MERCHANT_SELL: { + PlayerEvent::MerchantSellEvent in{}; + PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + + r.etl_table_id = + GetETLIDCache().contains(static_cast(r.event_type_id)) + ? GetETLIDCache().at(static_cast(r.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(r.event_type_id)); + + etl_queues.queue_16.push_back(out); + m_record_etl_queue.emplace(static_cast(r.event_type_id), out); + break; + } + case PlayerEvent::EventType::MERCHANT_PURCHASE: { + PlayerEvent::MerchantPurchaseEvent in{}; + PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + + r.etl_table_id = + GetETLIDCache().contains(static_cast(r.event_type_id)) + ? GetETLIDCache().at(static_cast(r.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(r.event_type_id)); + + m_record_etl_queue.emplace(static_cast(r.event_type_id), out); + etl_queues.queue_15.push_back(out); + break; + } + case PlayerEvent::EventType::NPC_HANDIN: { + PlayerEvent::HandinEvent in{}; + PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; + PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries out_entries{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.handin_copper = in.handin_money.copper; + out.handin_silver = in.handin_money.silver; + out.handin_gold = in.handin_money.gold; + out.handin_platinum = in.handin_money.platinum; + out.return_copper = in.return_money.copper; + out.return_silver = in.return_money.silver; + out.return_gold = in.return_money.gold; + out.return_platinum = in.return_money.platinum; + out.is_quest_handin = in.is_quest_handin; + + r.etl_table_id = + GetETLIDCache().contains(static_cast(r.event_type_id)) + ? GetETLIDCache().at(static_cast(r.event_type_id)) + : 0; + IncrementDetailTableIDCache(static_cast(r.event_type_id)); + + if (!in.handin_items.empty()) { + for (auto const &i: in.handin_items) { + out_entries.charges = i.charges; + out_entries.evolve_amount = 0; + out_entries.evolve_level = 0; + out_entries.item_id = i.item_id; + out_entries.player_event_npc_handin_id = r.etl_table_id; + out_entries.type = 1; + + if (!i.augment_ids.empty()) { + uint32 augments[6]{}; + for (int x = 0; x < i.augment_ids.size(); x++) { + augments[x] = i.augment_ids[x]; + } + out_entries.augment_1_id = augments[0]; + out_entries.augment_2_id = augments[1]; + out_entries.augment_3_id = augments[2]; + out_entries.augment_4_id = augments[3]; + out_entries.augment_5_id = augments[4]; + out_entries.augment_6_id = augments[5]; + } + etl_queues.queue_22_entries.push_back(out_entries); + } + } + + if (!in.return_items.empty()) { + for (auto const &i: in.handin_items) { + out_entries.charges = i.charges; + out_entries.evolve_amount = 0; + out_entries.evolve_level = 0; + out_entries.item_id = i.item_id; + out_entries.player_event_npc_handin_id = r.etl_table_id; + out_entries.type = 2; + if (!i.augment_ids.empty()) { + uint32 augments[6]{}; + for (int x = 0; x < i.augment_ids.size(); x++) { + augments[x] = i.augment_ids[x]; + } + out_entries.augment_1_id = augments[0]; + out_entries.augment_2_id = augments[1]; + out_entries.augment_3_id = augments[2]; + out_entries.augment_4_id = augments[3]; + out_entries.augment_5_id = augments[4]; + out_entries.augment_6_id = augments[5]; + } + etl_queues.queue_22_entries.push_back(out_entries); + } + } + + m_record_etl_queue.emplace(static_cast(r.event_type_id), out); + etl_queues.queue_22.push_back(out); + break; + } + default: { + } + } + } + // flush many PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); // flush detailed tables if (!m_record_etl_queue.empty()) { for (auto const &[key, value]: m_record_etl_queue) { - m_etl_data[key].etl_queue.push_back(value); - } + switch (key) { + case PlayerEvent::LOOT_ITEM: { + PlayerEventLootItemsRepository::InsertMany(*m_database, etl_queues.queue_14); + etl_queues.queue_14.clear(); + break; + } + case PlayerEvent::MERCHANT_SELL: { + PlayerEventMerchantSellRepository::InsertMany(*m_database, etl_queues.queue_16); + etl_queues.queue_16.clear(); + break; + } + case PlayerEvent::MERCHANT_PURCHASE: { + PlayerEventMerchantPurchaseRepository::InsertMany(*m_database, etl_queues.queue_15); + etl_queues.queue_15.clear(); + break; + } + case PlayerEvent::NPC_HANDIN: { + PlayerEventNpcHandinRepository::InsertMany(*m_database, etl_queues.queue_22); + PlayerEventNpcHandinEntriesRepository::InsertMany(*m_database, etl_queues.queue_22_entries); + etl_queues.queue_22.clear(); + etl_queues.queue_22_entries.clear(); + break; + } + default: { - for (auto &[key, value]:m_etl_data) { - if (!value.etl_queue.empty()) { - value.etl_load_func_ptr(*m_database, value.etl_queue); - value.etl_queue.clear(); + } } - } - LogPlayerEventsDetail( - "Processing batch player event log queue of [{}] took [{}]", - m_record_batch_queue.size(), - benchmark.elapsed() - ); + LogPlayerEventsDetail( + "Processing batch player event log queue of [{}] took [{}]", + m_record_batch_queue.size(), + benchmark.elapsed() + ); + } } // empty @@ -169,145 +372,6 @@ void PlayerEventLogs::ProcessBatchQueue() void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log) { m_batch_queue_lock.lock(); - - switch (log.event_type_id) { - case PlayerEvent::EventType::LOOT_ITEM: { - PlayerEvent::LootItemEvent in{}; - PlayerEventLootItemsRepository::PlayerEventLootItems out{}; - - { - std::stringstream ss; - ss << log.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.charges = in.charges; - out.corpse_name = in.corpse_name; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.npc_id = in.npc_id; - - log.etl_table_id = - GetETLIDCache().contains(static_cast(log.event_type_id)) - ? GetETLIDCache().at(static_cast(log.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(log.event_type_id)); - - m_record_etl_queue.emplace(static_cast(log.event_type_id), out); - break; - } - case PlayerEvent::EventType::MERCHANT_SELL: { - PlayerEvent::MerchantSellEvent in{}; - PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; - - { - std::stringstream ss; - ss << log.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.merchant_name = in.merchant_name; - out.merchant_type = in.merchant_type; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.charges = in.charges; - out.cost = in.cost; - out.alternate_currency_id = in.alternate_currency_id; - out.player_money_balance = in.player_money_balance; - out.player_currency_balance = in.player_currency_balance; - - log.etl_table_id = - GetETLIDCache().contains(static_cast(log.event_type_id)) - ? GetETLIDCache().at(static_cast(log.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(log.event_type_id)); - - m_record_etl_queue.emplace(static_cast(log.event_type_id), out); - break; - } - case PlayerEvent::EventType::MERCHANT_PURCHASE: { - PlayerEvent::MerchantPurchaseEvent in{}; - PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; - - { - std::stringstream ss; - ss << log.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.merchant_name = in.merchant_name; - out.merchant_type = in.merchant_type; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.charges = in.charges; - out.cost = in.cost; - out.alternate_currency_id = in.alternate_currency_id; - out.player_money_balance = in.player_money_balance; - out.player_currency_balance = in.player_currency_balance; - - log.etl_table_id = - GetETLIDCache().contains(static_cast(log.event_type_id)) - ? GetETLIDCache().at(static_cast(log.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(log.event_type_id)); - - m_record_etl_queue.emplace(static_cast(log.event_type_id), out); - break; - } - case PlayerEvent::EventType::NPC_HANDIN: { - PlayerEvent::HandinEvent in{}; - PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; - PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries out_entries{}; - - { - std::stringstream ss; - ss << log.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.handin_copper = in.handin_money.copper; - out.handin_silver = in.handin_money.silver; - out.handin_gold = in.handin_money.gold; - out.handin_platinum = in.handin_money.platinum; - out.return_copper = in.return_money.copper; - out.return_silver = in.return_money.silver; - out.return_gold = in.return_money.gold; - out.return_platinum = in.return_money.platinum; - out.is_quest_handin = in.is_quest_handin; - - - out.npc_id = in.npc_id; - out.merchant_name = in.merchant_name; - out.merchant_type = in.merchant_type; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.charges = in.charges; - out.cost = in.cost; - out.alternate_currency_id = in.alternate_currency_id; - out.player_money_balance = in.player_money_balance; - out.player_currency_balance = in.player_currency_balance; - - log.etl_table_id = - GetETLIDCache().contains(static_cast(log.event_type_id)) - ? GetETLIDCache().at(static_cast(log.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(log.event_type_id)); - - m_record_etl_queue.emplace(static_cast(log.event_type_id), out); - break; - } - default: { - } - } - m_record_batch_queue.emplace_back(log); m_batch_queue_lock.unlock(); } @@ -799,14 +863,46 @@ void PlayerEventLogs::ProcessRetentionTruncation() etl_ids.push_back(std::to_string(r.etl_table_id)); } - auto deleted_count = PlayerEventLogsRepository::DeleteETLRecords(*m_database, m_etl_data[static_cast(i)].etl_table_name, etl_ids); + uint32 deleted_count = 0; + switch (m_settings[i].id) { + case PlayerEvent::LOOT_ITEM: { + deleted_count = PlayerEventLootItemsRepository::DeleteWhere( + *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) + ); + break; + } + case PlayerEvent::MERCHANT_SELL: { + deleted_count = PlayerEventMerchantSellRepository::DeleteWhere( + *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) + ); + break; + } + case PlayerEvent::MERCHANT_PURCHASE: { + deleted_count = PlayerEventMerchantPurchaseRepository::DeleteWhere( + *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) + ); + break; + } + case PlayerEvent::NPC_HANDIN: { + deleted_count = PlayerEventNpcHandinRepository::DeleteWhere( + *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) + ); + deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere( + *m_database, fmt::format("`player_event_npc_handin_id` IN({})", Strings::Implode(", ", etl_ids)) + ); + break; + } + default: { + + } + } + LogInfo( - "Truncated [{}] events of type [{}] ({}) older than [{}] days from etl table {}", + "Truncated [{}] events of type [{}] ({}) older than [{}] days from etl table", deleted_count, PlayerEvent::EventName[i], i, - m_settings[i].retention_days, - m_etl_data[static_cast(i)].etl_table_name + m_settings[i].retention_days ); } } @@ -913,24 +1009,8 @@ void PlayerEventLogs::LoadETLIDs() { GetETLIDCache().clear(); - auto results = PlayerEventLogSettingsRepository::All(*m_database); - for (auto &e: results) { - if (e.id >= PlayerEvent::MAX) { - continue; - } - - if (e.has_etl) { - if (!m_etl_data.contains(static_cast(e.id))) { - LogError( - "Error retrieving Event Type [{}]. Database mismatch. Check 'has_etl' field in " - "player_event_log_settings", - e.id); - return; - } - - auto etl_table_name = m_etl_data.at(static_cast(e.id)).etl_table_name; - auto last_id = PlayerEventLogSettingsRepository::GetNextIdForTable(*m_database, etl_table_name); - GetETLIDCache().emplace(static_cast(e.id), last_id); - } - } + GetETLIDCache().emplace(PlayerEvent::LOOT_ITEM, PlayerEventLootItemsRepository::GetMaxId(*m_database) + 1); + GetETLIDCache().emplace(PlayerEvent::MERCHANT_SELL, PlayerEventMerchantSellRepository::GetMaxId(*m_database) + 1); + GetETLIDCache().emplace(PlayerEvent::MERCHANT_PURCHASE, PlayerEventMerchantPurchaseRepository::GetMaxId(*m_database) + 1); + GetETLIDCache().emplace(PlayerEvent::NPC_HANDIN, PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1); } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 7c214652ad..00c6a0d8bb 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -8,11 +8,13 @@ #include "../json/json_archive_single_line.h" #include "../repositories/player_event_log_settings_repository.h" #include "../repositories/player_event_logs_repository.h" -#include "../servertalk.h" -#include "../timer.h" #include "../repositories/player_event_loot_items_repository.h" -#include "../repositories/player_event_merchant_sell_repository.h" #include "../repositories/player_event_merchant_purchase_repository.h" +#include "../repositories/player_event_merchant_sell_repository.h" +#include "../repositories/player_event_npc_handin_entries_repository.h" +#include "../repositories/player_event_npc_handin_repository.h" +#include "../servertalk.h" +#include "../timer.h" class PlayerEventLogs { public: @@ -90,40 +92,13 @@ class PlayerEventLogs { void SetSettingsDefaults(); public: - struct EtlInfo_Struct { - std::string etl_table_name; - std::vector etl_queue; - std::function &)> etl_load_func_ptr; - }; - - std::map m_etl_data = { - { - PlayerEvent::LOOT_ITEM, - { - .etl_table_name = "player_event_loot_items", - .etl_queue = {}, - .etl_load_func_ptr = { &PlayerEventLootItemsRepository::InsertManyFromStdAny }, - } - }, - { - PlayerEvent::MERCHANT_SELL, - { - .etl_table_name = "player_event_merchant_sell", - .etl_queue = {}, - .etl_load_func_ptr = { &PlayerEventMerchantSellRepository::InsertManyFromStdAny }, - } - }, - { - PlayerEvent::MERCHANT_PURCHASE, - { - .etl_table_name = "player_event_merchant_purchase", - .etl_queue = {}, - .etl_load_func_ptr = { &PlayerEventMerchantPurchaseRepository::InsertManyFromStdAny }, - } - } - + struct EtlQueues_Struct { + std::vector queue_14; + std::vector queue_15; + std::vector queue_16; + std::vector queue_22; + std::vector queue_22_entries; }; - }; extern PlayerEventLogs player_event_logs; From f26f43c6cbc6606d1ce44d612b2379df5536e2a5 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 20 Oct 2024 16:49:25 -0300 Subject: [PATCH 13/42] Cleanup --- .../player_event_loot_items_repository.h | 25 --------------- ...layer_event_merchant_purchase_repository.h | 31 ------------------- .../player_event_merchant_sell_repository.h | 31 ------------------- 3 files changed, 87 deletions(-) diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index 647f8f5601..6b68dd2c50 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -42,31 +42,6 @@ class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository * method that can be re-used easily elsewhere especially if it can use a base repository * method and encapsulate filters there */ - static int InsertManyFromStdAny(Database &db, const std::vector &entries) - { - std::vector insert_chunks; - - for (auto &r: entries) { - auto e = std::any_cast(r); - std::vector v; - - v.push_back(std::to_string(e.id)); - v.push_back(std::to_string(e.item_id)); - v.push_back("'" + Strings::Escape(e.item_name) + "'"); - v.push_back(std::to_string(e.charges)); - v.push_back(std::to_string(e.npc_id)); - v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); - - insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); - } - - std::vector v; - - auto results = - db.QueryDatabase(fmt::format("{} VALUES {}", BaseInsert(), Strings::Implode(",", insert_chunks))); - - return results.Success() ? results.RowsAffected() : 0; - } }; #endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_purchase_repository.h b/common/repositories/player_event_merchant_purchase_repository.h index 75a476e6db..ceea389ad2 100644 --- a/common/repositories/player_event_merchant_purchase_repository.h +++ b/common/repositories/player_event_merchant_purchase_repository.h @@ -44,37 +44,6 @@ class PlayerEventMerchantPurchaseRepository: public BasePlayerEventMerchantPurch */ // Custom extended repository methods here - static int InsertManyFromStdAny(Database &db, const std::vector &entries) - { - std::vector insert_chunks; - - for (auto &r: entries) { - auto e = std::any_cast(r); - std::vector v; - - v.push_back(std::to_string(e.id)); - v.push_back(std::to_string(e.npc_id)); - v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); - v.push_back(std::to_string(e.merchant_type)); - v.push_back(std::to_string(e.item_id)); - v.push_back("'" + Strings::Escape(e.item_name) + "'"); - v.push_back(std::to_string(e.charges)); - v.push_back(std::to_string(e.cost)); - v.push_back(std::to_string(e.alternate_currency_id)); - v.push_back(std::to_string(e.player_money_balance)); - v.push_back(std::to_string(e.player_currency_balance)); - - insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); - } - - std::vector v; - - auto results = - db.QueryDatabase(fmt::format("{} VALUES {}", BaseInsert(), Strings::Implode(",", insert_chunks)) - ); - - return results.Success() ? results.RowsAffected() : 0; - } }; #endif //EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h index bdf46c952d..66621542de 100644 --- a/common/repositories/player_event_merchant_sell_repository.h +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -44,37 +44,6 @@ class PlayerEventMerchantSellRepository: public BasePlayerEventMerchantSellRepos */ // Custom extended repository methods here - static int InsertManyFromStdAny(Database &db, const std::vector &entries) - { - std::vector insert_chunks; - - for (auto &r: entries) { - auto e = std::any_cast(r); - std::vector v; - - v.push_back(std::to_string(e.id)); - v.push_back(std::to_string(e.npc_id)); - v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); - v.push_back(std::to_string(e.merchant_type)); - v.push_back(std::to_string(e.item_id)); - v.push_back("'" + Strings::Escape(e.item_name) + "'"); - v.push_back(std::to_string(e.charges)); - v.push_back(std::to_string(e.cost)); - v.push_back(std::to_string(e.alternate_currency_id)); - v.push_back(std::to_string(e.player_money_balance)); - v.push_back(std::to_string(e.player_currency_balance)); - - insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); - } - - std::vector v; - - auto results = - db.QueryDatabase(fmt::format("{} VALUES {}", BaseInsert(), Strings::Implode(",", insert_chunks)) - ); - - return results.Success() ? results.RowsAffected() : 0; - } }; #endif //EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H From 76c9554d915a5f942f7581bc7d1fb98e7556db2d Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 20 Oct 2024 16:51:17 -0300 Subject: [PATCH 14/42] All a rentention period of 0 days which deletes all current records. --- common/events/player_event_logs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index b5d700eb7c..cb8a5fdc5d 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -848,7 +848,7 @@ void PlayerEventLogs::ProcessRetentionTruncation() LogPlayerEvents("Running truncation"); for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { - if (m_settings[i].retention_days > 0) { + if (m_settings[i].retention_days >= 0) { if (m_settings[i].has_etl) { auto results = PlayerEventLogsRepository::GetWhere( *m_database, From c76994f8256d5f2e8dd504e82920fb5b272e4bcb Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 20 Oct 2024 22:01:51 -0300 Subject: [PATCH 15/42] Updates Cleanup and refactor a few items. --- common/database/database_update_manifest.cpp | 266 ++++++++++++++---- common/database_schema.h | 3 + common/events/player_event_logs.cpp | 261 +++++++++-------- common/events/player_event_logs.h | 34 ++- ...ase_player_event_log_settings_repository.h | 24 +- .../base_player_event_loot_items_repository.h | 12 + ...layer_event_merchant_purchase_repository.h | 12 + ...se_player_event_merchant_sell_repository.h | 12 + .../base_player_event_npc_handin_repository.h | 12 + .../player_event_logs_repository.h | 11 - common/version.h | 2 +- 11 files changed, 440 insertions(+), 209 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 61b56773ed..5d1567f7cf 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5809,81 +5809,243 @@ ADD COLUMN `shard_at_player_count` int(11) NULL DEFAULT 0 AFTER `seconds_before_ ManifestEntry{ .version = 9289, .description = "2024_10_08_add_detail_player_event_logging.sql", - .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'has_etl'", + .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'etl_enabled'", .condition = "empty", .match = "", .sql = R"( ALTER TABLE `player_event_log_settings` - ADD COLUMN `has_etl` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `discord_webhook_id`; - + ADD COLUMN `etl_enabled` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `discord_webhook_id`; ALTER TABLE `player_event_logs` ADD COLUMN `etl_table_id` BIGINT(20) NOT NULL DEFAULT '0' AFTER `event_data`; - -UPDATE `player_event_log_settings` SET `etl_logging` = 1, `etl_table_name` = 'player_event_loot_items' WHERE `id` = 14; - ADD COLUMN `player_event_x_id` BIGINT(20) NOT NULL DEFAULT '0' AFTER `event_data`; -)" - }, - ManifestEntry{ - .version = 9290, - .description = "2024_10_08_remove_qs_logging.sql", - .check = "SHOW TABLES LIKE 'player_event_loot_items'", - .condition = "empty", - .match = "", - .sql = R"( -UPDATE `player_event_log_settings` SET `has_etl` = 1, `etl_table_name` = 'player_event_loot_items' WHERE `id` = 14; - +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 14; CREATE TABLE `player_event_loot_items` ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, `item_id` INT(10) UNSIGNED NULL DEFAULT NULL, `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', `charges` INT(11) NULL DEFAULT NULL, + `augment_1_id` INT UNSIGNED NULL DEFAULT '0', + `augment_2_id` INT UNSIGNED NULL DEFAULT '0'`, + `augment_3_id` INT UNSIGNED NULL DEFAULT '0', + `augment_4_id` INT UNSIGNED NULL DEFAULT '0', + `augment_5_id` INT UNSIGNED NULL DEFAULT '0', + `augment_6_id` INT UNSIGNED NULL DEFAULT '0', `npc_id` INT(10) UNSIGNED NULL DEFAULT NULL, `corpse_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', - PRIMARY KEY (`id`) USING BTREE + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `item_id_npc_id` (`item_id`, `npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE ) COLLATE='latin1_swedish_ci' +ENGINE=InnoDB AUTO_INCREMENT=1; - -UPDATE `player_event_log_settings` SET `has_etl` = 1, `etl_table_name` = 'player_event_merchant_sell' WHERE `id` = 16; - +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 16; CREATE TABLE `player_event_merchant_sell` ( - `id` BIGINT UNSIGNED NULL AUTO_INCREMENT, - `npc_id` INT UNSIGNED NULL DEFAULT '0', - `merchant_name` VARCHAR(64) NULL DEFAULT NULL, - `merchant_type` INT UNSIGNED NULL DEFAULT '0', - `item_id` INT UNSIGNED NULL DEFAULT '0', - `item_name` VARCHAR(64) NULL DEFAULT NULL, - `charges` INT NULL DEFAULT '0', - `cost` INT UNSIGNED NULL DEFAULT '0', - `alternate_currency_id` INT UNSIGNED NULL DEFAULT '0', - `player_money_balance` BIGINT UNSIGNED NULL DEFAULT '0', - `player_currency_balance` BIGINT UNSIGNED NULL DEFAULT '0', - PRIMARY KEY (`id`) + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `merchant_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `merchant_type` INT(10) UNSIGNED NULL DEFAULT '0', + `item_id` INT(10) UNSIGNED NULL DEFAULT '0', + `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `charges` INT(11) NULL DEFAULT '0', + `cost` INT(10) UNSIGNED NULL DEFAULT '0', + `alternate_currency_id` INT(10) UNSIGNED NULL DEFAULT '0', + `player_money_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `player_currency_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `item_id_npc_id` (`item_id`, `npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE ) COLLATE='latin1_swedish_ci' +ENGINE=InnoDB AUTO_INCREMENT=1; - -UPDATE `player_event_log_settings` SET `has_etl` = 1, `etl_table_name` = 'player_event_merchant_purchase' WHERE `id` = 15; - +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 15; CREATE TABLE `player_event_merchant_purchase` ( - `id` BIGINT UNSIGNED NULL AUTO_INCREMENT, - `npc_id` INT UNSIGNED NULL DEFAULT '0', - `merchant_name` VARCHAR(64) NULL DEFAULT NULL, - `merchant_type` INT UNSIGNED NULL DEFAULT '0', - `item_id` INT UNSIGNED NULL DEFAULT '0', - `item_name` VARCHAR(64) NULL DEFAULT NULL, - `charges` INT NULL DEFAULT '0', - `cost` INT UNSIGNED NULL DEFAULT '0', - `alternate_currency_id` INT UNSIGNED NULL DEFAULT '0', - `player_money_balance` BIGINT UNSIGNED NULL DEFAULT '0', - `player_currency_balance` BIGINT UNSIGNED NULL DEFAULT '0', - PRIMARY KEY (`id`) + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `merchant_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `merchant_type` INT(10) UNSIGNED NULL DEFAULT '0', + `item_id` INT(10) UNSIGNED NULL DEFAULT '0', + `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `charges` INT(11) NULL DEFAULT '0', + `cost` INT(10) UNSIGNED NULL DEFAULT '0', + `alternate_currency_id` INT(10) UNSIGNED NULL DEFAULT '0', + `player_money_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `player_currency_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `item_id_npc_id` (`item_id`, `npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 22; +CREATE TABLE `player_event_npc_handin` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `handin_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `handin_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `handin_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `handin_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `is_quest_handin` TINYINT(3) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id_is_quest_handin` (`npc_id`, `is_quest_handin`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +CREATE TABLE `player_event_npc_handin_entries` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `player_event_npc_handin_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0', + `type` INT(10) UNSIGNED NULL DEFAULT NULL, + `item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `charges` INT(11) NOT NULL DEFAULT '0', + `evolve_level` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `evolve_amount` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0', + `augment_1_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_2_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_3_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_4_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_5_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_6_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `type_item_id` (`type`, `item_id`) USING BTREE, + INDEX `player_event_npc_handin_id` (`player_event_npc_handin_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 27; +CREATE TABLE `player_event_trade` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `char1_id` INT(10) UNSIGNED NULL DEFAULT '0', + `char2_id` INT(10) UNSIGNED NULL DEFAULT '0', + `char1_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char1_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char1_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char1_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `char1_id_char2_id` (`char1_id`, `char2_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +CREATE TABLE `player_event_trade_entries` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `player_event_trade_id` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char_id` INT(10) UNSIGNED NULL DEFAULT '0', + `slot` SMALLINT(6) NULL DEFAULT '0', + `item_id` INT(10) UNSIGNED NULL DEFAULT '0', + `charges` SMALLINT(6) NULL DEFAULT '0', + `augment_1_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_2_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_3_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_4_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_5_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_6_id` INT(10) UNSIGNED NULL DEFAULT '0', + `in_bag` TINYINT(4) NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `player_event_trade_id` (`player_event_trade_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE ) COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 0 WHERE `id` = 54; +CREATE TABLE `player_event_speech` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `to_char_id` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `from_char_id` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `guild_id` INT(10) UNSIGNED NULL DEFAULT '0', + `type` INT(10) UNSIGNED NULL DEFAULT '0', + `min_status` INT(10) UNSIGNED NULL DEFAULT '0', + `message` LONGTEXT NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `to_char_id_from_char_id` (`to_char_id`, `from_char_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 44; +CREATE TABLE `player_event_killed_npc` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `combat_time_seconds` INT(10) UNSIGNED NULL DEFAULT '0', + `total_damage_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `total_heal_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id` (`npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 45; +CREATE TABLE `player_event_killed_named_npc` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `combat_time_seconds` INT(10) UNSIGNED NULL DEFAULT '0', + `total_damage_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `total_heal_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id` (`npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 46; +CREATE TABLE `player_event_killed_raid_npc` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `combat_time_seconds` INT(10) UNSIGNED NULL DEFAULT '0', + `total_damage_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `total_heal_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id` (`npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 4; +CREATE TABLE `player_event_aa_purchase` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `aa_ability_id` INT(11) NULL DEFAULT '0', + `cost` INT(11) NULL DEFAULT '0', + `previous_id` INT(11) NULL DEFAULT '0', + `next_id` INT(11) NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +; )" - } - // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, @@ -5895,7 +6057,7 @@ AUTO_INCREMENT=1; // //)" - // Used for testing + // Used for testing // ManifestEntry{ // .version = 9229, // .description = "new_database_check_test", @@ -5922,7 +6084,7 @@ AUTO_INCREMENT=1; //)", // } -}; + }; // see struct definitions for what each field does // struct ManifestEntry { diff --git a/common/database_schema.h b/common/database_schema.h index 1fdef741a2..f941cf0b3d 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -359,6 +359,9 @@ namespace DatabaseSchema { "player_event_logs", "player_event_loot_items", "player_event_merchant_sell", + "player_event_merchant_purchase", + "player_event_merchant_npc_handin", + "player_event_merchant_npc_handin_entries", "shared_task_activity_state", "shared_task_dynamic_zones", "shared_task_members", diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index cb8a5fdc5d..31d421eb66 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1,8 +1,6 @@ #include "player_event_logs.h" #include -#include - #include "../platform.h" #include "../rulesys.h" #include "player_event_discord_formatter.h" @@ -30,7 +28,7 @@ void PlayerEventLogs::Init() m_settings[i].event_enabled = 1; m_settings[i].retention_days = 0; m_settings[i].discord_webhook_id = 0; - m_settings[i].has_etl = 0; + m_settings[i].etl_enabled = false; } SetSettingsDefaults(); @@ -75,7 +73,7 @@ void PlayerEventLogs::Init() c.event_name = PlayerEvent::EventName[i]; c.event_enabled = m_settings[i].event_enabled; c.retention_days = m_settings[i].retention_days; - c.has_etl = false; + c.etl_enabled = false; settings_to_insert.emplace_back(c); } } @@ -136,8 +134,7 @@ void PlayerEventLogs::ProcessBatchQueue() BenchTimer benchmark; - EtlQueues_Struct etl_queues{}; - auto out_entries_next_id = PlayerEventNpcHandinEntriesRepository::GetMaxId(*m_database) + 1; + EtlQueues etl_queues{}; for (auto &r:m_record_batch_queue) { switch (r.event_type_id) { @@ -157,15 +154,15 @@ void PlayerEventLogs::ProcessBatchQueue() out.item_id = in.item_id; out.item_name = in.item_name; out.npc_id = in.npc_id; + out.created_at = r.created_at; - r.etl_table_id = - GetETLIDCache().contains(static_cast(r.event_type_id)) - ? GetETLIDCache().at(static_cast(r.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(r.event_type_id)); + if (m_etl_info.contains(PlayerEvent::EventType::LOOT_ITEM)) { + r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::LOOT_ITEM).etl_next_id; + m_etl_info.at(PlayerEvent::EventType::LOOT_ITEM).etl_next_id++; + } - etl_queues.queue_14.push_back(out); - m_record_etl_queue.emplace(static_cast(r.event_type_id), out); + etl_queues.queue_loot_items.push_back(out); + m_record_etl_queue.emplace(PlayerEvent::EventType::LOOT_ITEM, out); break; } case PlayerEvent::EventType::MERCHANT_SELL: { @@ -189,15 +186,15 @@ void PlayerEventLogs::ProcessBatchQueue() out.alternate_currency_id = in.alternate_currency_id; out.player_money_balance = in.player_money_balance; out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; - r.etl_table_id = - GetETLIDCache().contains(static_cast(r.event_type_id)) - ? GetETLIDCache().at(static_cast(r.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(r.event_type_id)); + if (m_etl_info.contains(PlayerEvent::EventType::MERCHANT_SELL)) { + r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::MERCHANT_SELL).etl_next_id; + m_etl_info.at(PlayerEvent::EventType::MERCHANT_SELL).etl_next_id++; + } - etl_queues.queue_16.push_back(out); - m_record_etl_queue.emplace(static_cast(r.event_type_id), out); + etl_queues.queue_merchant_sell.push_back(out); + m_record_etl_queue.emplace(PlayerEvent::EventType::MERCHANT_SELL, out); break; } case PlayerEvent::EventType::MERCHANT_PURCHASE: { @@ -221,15 +218,15 @@ void PlayerEventLogs::ProcessBatchQueue() out.alternate_currency_id = in.alternate_currency_id; out.player_money_balance = in.player_money_balance; out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; - r.etl_table_id = - GetETLIDCache().contains(static_cast(r.event_type_id)) - ? GetETLIDCache().at(static_cast(r.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(r.event_type_id)); + if (m_etl_info.contains(PlayerEvent::EventType::MERCHANT_PURCHASE)) { + r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::MERCHANT_PURCHASE).etl_next_id; + m_etl_info.at(PlayerEvent::EventType::MERCHANT_PURCHASE).etl_next_id++; + } - m_record_etl_queue.emplace(static_cast(r.event_type_id), out); - etl_queues.queue_15.push_back(out); + etl_queues.queue_merchant_purchase.push_back(out); + m_record_etl_queue.emplace(PlayerEvent::EventType::MERCHANT_PURCHASE, out); break; } case PlayerEvent::EventType::NPC_HANDIN: { @@ -244,23 +241,23 @@ void PlayerEventLogs::ProcessBatchQueue() in.serialize(ar); } - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.handin_copper = in.handin_money.copper; - out.handin_silver = in.handin_money.silver; - out.handin_gold = in.handin_money.gold; - out.handin_platinum = in.handin_money.platinum; - out.return_copper = in.return_money.copper; - out.return_silver = in.return_money.silver; - out.return_gold = in.return_money.gold; - out.return_platinum = in.return_money.platinum; - out.is_quest_handin = in.is_quest_handin; - - r.etl_table_id = - GetETLIDCache().contains(static_cast(r.event_type_id)) - ? GetETLIDCache().at(static_cast(r.event_type_id)) - : 0; - IncrementDetailTableIDCache(static_cast(r.event_type_id)); + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.handin_copper = in.handin_money.copper; + out.handin_silver = in.handin_money.silver; + out.handin_gold = in.handin_money.gold; + out.handin_platinum = in.handin_money.platinum; + out.return_copper = in.return_money.copper; + out.return_silver = in.return_money.silver; + out.return_gold = in.return_money.gold; + out.return_platinum = in.return_money.platinum; + out.is_quest_handin = in.is_quest_handin; + out.created_at = r.created_at; + + if (m_etl_info.contains(PlayerEvent::EventType::NPC_HANDIN)) { + r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::NPC_HANDIN).etl_next_id; + m_etl_info.at(PlayerEvent::EventType::NPC_HANDIN).etl_next_id++; + } if (!in.handin_items.empty()) { for (auto const &i: in.handin_items) { @@ -270,6 +267,7 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.item_id = i.item_id; out_entries.player_event_npc_handin_id = r.etl_table_id; out_entries.type = 1; + out.created_at = r.created_at; if (!i.augment_ids.empty()) { uint32 augments[6]{}; @@ -283,7 +281,7 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.augment_5_id = augments[4]; out_entries.augment_6_id = augments[5]; } - etl_queues.queue_22_entries.push_back(out_entries); + etl_queues.queue_npc_handin_entries.push_back(out_entries); } } @@ -295,6 +293,8 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.item_id = i.item_id; out_entries.player_event_npc_handin_id = r.etl_table_id; out_entries.type = 2; + out.created_at = r.created_at; + if (!i.augment_ids.empty()) { uint32 augments[6]{}; for (int x = 0; x < i.augment_ids.size(); x++) { @@ -307,12 +307,12 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.augment_5_id = augments[4]; out_entries.augment_6_id = augments[5]; } - etl_queues.queue_22_entries.push_back(out_entries); + etl_queues.queue_npc_handin_entries.push_back(out_entries); } } - m_record_etl_queue.emplace(static_cast(r.event_type_id), out); - etl_queues.queue_22.push_back(out); + m_record_etl_queue.emplace(PlayerEvent::EventType::NPC_HANDIN, out); + etl_queues.queue_npc_handin.push_back(out); break; } default: { @@ -328,29 +328,29 @@ void PlayerEventLogs::ProcessBatchQueue() for (auto const &[key, value]: m_record_etl_queue) { switch (key) { case PlayerEvent::LOOT_ITEM: { - PlayerEventLootItemsRepository::InsertMany(*m_database, etl_queues.queue_14); - etl_queues.queue_14.clear(); + PlayerEventLootItemsRepository::InsertMany(*m_database, etl_queues.queue_loot_items); + etl_queues.queue_loot_items.clear(); break; } case PlayerEvent::MERCHANT_SELL: { - PlayerEventMerchantSellRepository::InsertMany(*m_database, etl_queues.queue_16); - etl_queues.queue_16.clear(); + PlayerEventMerchantSellRepository::InsertMany(*m_database, etl_queues.queue_merchant_sell); + etl_queues.queue_merchant_sell.clear(); break; } case PlayerEvent::MERCHANT_PURCHASE: { - PlayerEventMerchantPurchaseRepository::InsertMany(*m_database, etl_queues.queue_15); - etl_queues.queue_15.clear(); + PlayerEventMerchantPurchaseRepository::InsertMany(*m_database, etl_queues.queue_merchant_purchase); + etl_queues.queue_merchant_purchase.clear(); break; } case PlayerEvent::NPC_HANDIN: { - PlayerEventNpcHandinRepository::InsertMany(*m_database, etl_queues.queue_22); - PlayerEventNpcHandinEntriesRepository::InsertMany(*m_database, etl_queues.queue_22_entries); - etl_queues.queue_22.clear(); - etl_queues.queue_22_entries.clear(); + PlayerEventNpcHandinRepository::InsertMany(*m_database, etl_queues.queue_npc_handin); + PlayerEventNpcHandinEntriesRepository::InsertMany(*m_database, etl_queues.queue_npc_handin_entries); + etl_queues.queue_npc_handin.clear(); + etl_queues.queue_npc_handin_entries.clear(); break; } default: { - + LogError("Non-Implemented ETL event type [{}] ", static_cast(key)); } } @@ -849,64 +849,60 @@ void PlayerEventLogs::ProcessRetentionTruncation() for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { if (m_settings[i].retention_days >= 0) { - if (m_settings[i].has_etl) { - auto results = PlayerEventLogsRepository::GetWhere( - *m_database, - fmt::format( - "event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)", - i, - m_settings[i].retention_days) - ); - if (!results.empty()) { - std::vector etl_ids{}; - for (auto const &r: results) { - etl_ids.push_back(std::to_string(r.etl_table_id)); + if (m_settings[i].etl_enabled) { + uint32 deleted_count; + switch (m_settings[i].id) { + case PlayerEvent::LOOT_ITEM: { + deleted_count = PlayerEventLootItemsRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; } - - uint32 deleted_count = 0; - switch (m_settings[i].id) { - case PlayerEvent::LOOT_ITEM: { - deleted_count = PlayerEventLootItemsRepository::DeleteWhere( - *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) - ); - break; - } - case PlayerEvent::MERCHANT_SELL: { - deleted_count = PlayerEventMerchantSellRepository::DeleteWhere( - *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) - ); - break; - } - case PlayerEvent::MERCHANT_PURCHASE: { - deleted_count = PlayerEventMerchantPurchaseRepository::DeleteWhere( - *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) - ); - break; - } - case PlayerEvent::NPC_HANDIN: { - deleted_count = PlayerEventNpcHandinRepository::DeleteWhere( - *m_database, fmt::format("`id` IN({})", Strings::Implode(", ", etl_ids)) - ); - deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere( - *m_database, fmt::format("`player_event_npc_handin_id` IN({})", Strings::Implode(", ", etl_ids)) - ); - break; - } - default: { - - } + case PlayerEvent::MERCHANT_SELL: { + deleted_count = PlayerEventMerchantSellRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } + case PlayerEvent::MERCHANT_PURCHASE: { + deleted_count = PlayerEventMerchantPurchaseRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } + case PlayerEvent::NPC_HANDIN: { + deleted_count = PlayerEventNpcHandinRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } + default: { + LogError("NonImplemented ETL Event Type [{}] ", static_cast(m_settings[i].id)); } - - LogInfo( - "Truncated [{}] events of type [{}] ({}) older than [{}] days from etl table", - deleted_count, - PlayerEvent::EventName[i], - i, - m_settings[i].retention_days - ); } + + LogInfo( + "Truncated [{}] events of type [{}] ({}) older than [{}] days from etl table", + deleted_count, + PlayerEvent::EventName[i], + i, + m_settings[i].retention_days); } + int deleted_count = PlayerEventLogsRepository::DeleteWhere( *m_database, fmt::format( @@ -1007,10 +1003,39 @@ void PlayerEventLogs::SetSettingsDefaults() void PlayerEventLogs::LoadETLIDs() { - GetETLIDCache().clear(); - - GetETLIDCache().emplace(PlayerEvent::LOOT_ITEM, PlayerEventLootItemsRepository::GetMaxId(*m_database) + 1); - GetETLIDCache().emplace(PlayerEvent::MERCHANT_SELL, PlayerEventMerchantSellRepository::GetMaxId(*m_database) + 1); - GetETLIDCache().emplace(PlayerEvent::MERCHANT_PURCHASE, PlayerEventMerchantPurchaseRepository::GetMaxId(*m_database) + 1); - GetETLIDCache().emplace(PlayerEvent::NPC_HANDIN, PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1); + m_etl_info.clear(); + m_etl_info = { + { + PlayerEvent::LOOT_ITEM, + { + .etl_enabled = true, + .etl_table_name = "player_event_loot_items", + .etl_next_id = PlayerEventLootItemsRepository::GetMaxId(*m_database) + 1 + } + }, + { + PlayerEvent::MERCHANT_SELL, + { + .etl_enabled = true, + .etl_table_name = "player_event_merchant_sell", + .etl_next_id = BasePlayerEventMerchantSellRepository::GetMaxId(*m_database) + 1 + } + }, + { + PlayerEvent::MERCHANT_PURCHASE, + { + .etl_enabled = true, + .etl_table_name = "player_event_merchant_purchase", + .etl_next_id = PlayerEventMerchantPurchaseRepository::GetMaxId(*m_database) + 1 + } + }, + { + PlayerEvent::NPC_HANDIN, + { + .etl_enabled = true, + .etl_table_name = "player_event_npc_handin", + .etl_next_id = PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1 + } + }, + }; } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 00c6a0d8bb..dd0c13fabc 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -4,8 +4,10 @@ #include #include #include -#include #include "../json/json_archive_single_line.h" +#include "../servertalk.h" +#include "../timer.h" + #include "../repositories/player_event_log_settings_repository.h" #include "../repositories/player_event_logs_repository.h" #include "../repositories/player_event_loot_items_repository.h" @@ -13,19 +15,15 @@ #include "../repositories/player_event_merchant_sell_repository.h" #include "../repositories/player_event_npc_handin_entries_repository.h" #include "../repositories/player_event_npc_handin_repository.h" -#include "../servertalk.h" -#include "../timer.h" class PlayerEventLogs { public: void Init(); void ReloadSettings(); void LoadETLIDs(); - void IncrementDetailTableIDCache(PlayerEvent::EventType event_type) { m_last_id_cache_detail_tables[event_type]++; } PlayerEventLogs *SetDatabase(Database *db); bool ValidateDatabaseConnection(); bool IsEventEnabled(PlayerEvent::EventType event); - std::map& GetETLIDCache() { return m_last_id_cache_detail_tables; } void Process(); @@ -69,17 +67,32 @@ class PlayerEventLogs { static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e); + struct EtlQueues { + std::vector queue_loot_items; + std::vector queue_merchant_purchase; + std::vector queue_merchant_sell; + std::vector queue_npc_handin; + std::vector queue_npc_handin_entries; + }; + private: + struct EtlInfo { + bool etl_enabled; + std::string etl_table_name; + int64 etl_next_id; + }; + Database *m_database; // reference to database PlayerEventLogSettingsRepository::PlayerEventLogSettings m_settings[PlayerEvent::EventType::MAX]{}; - std::map m_last_id_cache_detail_tables{}; // batch queue is used to record events in batch std::vector m_record_batch_queue{}; static void FillPlayerEvent(const PlayerEvent::PlayerEvent &p, PlayerEventLogsRepository::PlayerEventLogs &n); static std::unique_ptr BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); + std::map m_record_etl_queue{}; + std::map m_etl_info{}; // timers Timer m_process_batch_events_timer; // events processing timer @@ -90,15 +103,6 @@ class PlayerEventLogs { void ProcessBatchQueue(); void ProcessRetentionTruncation(); void SetSettingsDefaults(); - -public: - struct EtlQueues_Struct { - std::vector queue_14; - std::vector queue_15; - std::vector queue_16; - std::vector queue_22; - std::vector queue_22_entries; - }; }; extern PlayerEventLogs player_event_logs; diff --git a/common/repositories/base/base_player_event_log_settings_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h index c06ce0f37b..4a2457576e 100644 --- a/common/repositories/base/base_player_event_log_settings_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -24,7 +24,7 @@ class BasePlayerEventLogSettingsRepository { int8_t event_enabled; int32_t retention_days; int32_t discord_webhook_id; - uint8_t has_etl; + uint8_t etl_enabled; }; static std::string PrimaryKey() @@ -40,7 +40,7 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", - "has_etl", + "etl_enabled", }; } @@ -52,7 +52,7 @@ class BasePlayerEventLogSettingsRepository { "event_enabled", "retention_days", "discord_webhook_id", - "has_etl", + "etl_enabled", }; } @@ -98,7 +98,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = 0; e.retention_days = 0; e.discord_webhook_id = 0; - e.has_etl = 0; + e.etl_enabled = 0; return e; } @@ -140,7 +140,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.has_etl = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.etl_enabled = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; return e; } @@ -179,7 +179,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(columns[2] + " = " + std::to_string(e.event_enabled)); v.push_back(columns[3] + " = " + std::to_string(e.retention_days)); v.push_back(columns[4] + " = " + std::to_string(e.discord_webhook_id)); - v.push_back(columns[5] + " = " + std::to_string(e.has_etl)); + v.push_back(columns[5] + " = " + std::to_string(e.etl_enabled)); auto results = db.QueryDatabase( fmt::format( @@ -206,7 +206,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.has_etl)); + v.push_back(std::to_string(e.etl_enabled)); auto results = db.QueryDatabase( fmt::format( @@ -241,7 +241,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.has_etl)); + v.push_back(std::to_string(e.etl_enabled)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -280,7 +280,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.has_etl = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.etl_enabled = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -310,7 +310,7 @@ class BasePlayerEventLogSettingsRepository { e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; - e.has_etl = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.etl_enabled = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -390,7 +390,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.has_etl)); + v.push_back(std::to_string(e.etl_enabled)); auto results = db.QueryDatabase( fmt::format( @@ -418,7 +418,7 @@ class BasePlayerEventLogSettingsRepository { v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); - v.push_back(std::to_string(e.has_etl)); + v.push_back(std::to_string(e.etl_enabled)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h index 40e0d1946d..ead31db299 100644 --- a/common/repositories/base/base_player_event_loot_items_repository.h +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -25,6 +25,7 @@ class BasePlayerEventLootItemsRepository { int32_t charges; uint32_t npc_id; std::string corpse_name; + time_t created_at; }; static std::string PrimaryKey() @@ -41,6 +42,7 @@ class BasePlayerEventLootItemsRepository { "charges", "npc_id", "corpse_name", + "created_at", }; } @@ -53,6 +55,7 @@ class BasePlayerEventLootItemsRepository { "charges", "npc_id", "corpse_name", + "UNIX_TIMESTAMP(created_at)", }; } @@ -99,6 +102,7 @@ class BasePlayerEventLootItemsRepository { e.charges = 0; e.npc_id = 0; e.corpse_name = ""; + e.created_at = 0; return e; } @@ -141,6 +145,7 @@ class BasePlayerEventLootItemsRepository { e.charges = row[3] ? static_cast(atoi(row[3])) : 0; e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; e.corpse_name = row[5] ? row[5] : ""; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); return e; } @@ -179,6 +184,7 @@ class BasePlayerEventLootItemsRepository { v.push_back(columns[3] + " = " + std::to_string(e.charges)); v.push_back(columns[4] + " = " + std::to_string(e.npc_id)); v.push_back(columns[5] + " = '" + Strings::Escape(e.corpse_name) + "'"); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -206,6 +212,7 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -241,6 +248,7 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -280,6 +288,7 @@ class BasePlayerEventLootItemsRepository { e.charges = row[3] ? static_cast(atoi(row[3])) : 0; e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; e.corpse_name = row[5] ? row[5] : ""; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -310,6 +319,7 @@ class BasePlayerEventLootItemsRepository { e.charges = row[3] ? static_cast(atoi(row[3])) : 0; e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; e.corpse_name = row[5] ? row[5] : ""; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -390,6 +400,7 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -418,6 +429,7 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.charges)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_player_event_merchant_purchase_repository.h b/common/repositories/base/base_player_event_merchant_purchase_repository.h index af32d46e9b..99ed4e7c5d 100644 --- a/common/repositories/base/base_player_event_merchant_purchase_repository.h +++ b/common/repositories/base/base_player_event_merchant_purchase_repository.h @@ -30,6 +30,7 @@ class BasePlayerEventMerchantPurchaseRepository { uint32_t alternate_currency_id; uint64_t player_money_balance; uint64_t player_currency_balance; + time_t created_at; }; static std::string PrimaryKey() @@ -51,6 +52,7 @@ class BasePlayerEventMerchantPurchaseRepository { "alternate_currency_id", "player_money_balance", "player_currency_balance", + "created_at", }; } @@ -68,6 +70,7 @@ class BasePlayerEventMerchantPurchaseRepository { "alternate_currency_id", "player_money_balance", "player_currency_balance", + "UNIX_TIMESTAMP(created_at)", }; } @@ -119,6 +122,7 @@ class BasePlayerEventMerchantPurchaseRepository { e.alternate_currency_id = 0; e.player_money_balance = 0; e.player_currency_balance = 0; + e.created_at = 0; return e; } @@ -166,6 +170,7 @@ class BasePlayerEventMerchantPurchaseRepository { e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); return e; } @@ -209,6 +214,7 @@ class BasePlayerEventMerchantPurchaseRepository { v.push_back(columns[8] + " = " + std::to_string(e.alternate_currency_id)); v.push_back(columns[9] + " = " + std::to_string(e.player_money_balance)); v.push_back(columns[10] + " = " + std::to_string(e.player_currency_balance)); + v.push_back(columns[11] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -241,6 +247,7 @@ class BasePlayerEventMerchantPurchaseRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -281,6 +288,7 @@ class BasePlayerEventMerchantPurchaseRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -325,6 +333,7 @@ class BasePlayerEventMerchantPurchaseRepository { e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -360,6 +369,7 @@ class BasePlayerEventMerchantPurchaseRepository { e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -445,6 +455,7 @@ class BasePlayerEventMerchantPurchaseRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -478,6 +489,7 @@ class BasePlayerEventMerchantPurchaseRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_player_event_merchant_sell_repository.h b/common/repositories/base/base_player_event_merchant_sell_repository.h index 47d9b0ca65..13c0181654 100644 --- a/common/repositories/base/base_player_event_merchant_sell_repository.h +++ b/common/repositories/base/base_player_event_merchant_sell_repository.h @@ -30,6 +30,7 @@ class BasePlayerEventMerchantSellRepository { uint32_t alternate_currency_id; uint64_t player_money_balance; uint64_t player_currency_balance; + time_t created_at; }; static std::string PrimaryKey() @@ -51,6 +52,7 @@ class BasePlayerEventMerchantSellRepository { "alternate_currency_id", "player_money_balance", "player_currency_balance", + "created_at", }; } @@ -68,6 +70,7 @@ class BasePlayerEventMerchantSellRepository { "alternate_currency_id", "player_money_balance", "player_currency_balance", + "UNIX_TIMESTAMP(created_at)", }; } @@ -119,6 +122,7 @@ class BasePlayerEventMerchantSellRepository { e.alternate_currency_id = 0; e.player_money_balance = 0; e.player_currency_balance = 0; + e.created_at = 0; return e; } @@ -166,6 +170,7 @@ class BasePlayerEventMerchantSellRepository { e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); return e; } @@ -209,6 +214,7 @@ class BasePlayerEventMerchantSellRepository { v.push_back(columns[8] + " = " + std::to_string(e.alternate_currency_id)); v.push_back(columns[9] + " = " + std::to_string(e.player_money_balance)); v.push_back(columns[10] + " = " + std::to_string(e.player_currency_balance)); + v.push_back(columns[11] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -241,6 +247,7 @@ class BasePlayerEventMerchantSellRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -281,6 +288,7 @@ class BasePlayerEventMerchantSellRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -325,6 +333,7 @@ class BasePlayerEventMerchantSellRepository { e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -360,6 +369,7 @@ class BasePlayerEventMerchantSellRepository { e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -445,6 +455,7 @@ class BasePlayerEventMerchantSellRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -478,6 +489,7 @@ class BasePlayerEventMerchantSellRepository { v.push_back(std::to_string(e.alternate_currency_id)); v.push_back(std::to_string(e.player_money_balance)); v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_player_event_npc_handin_repository.h b/common/repositories/base/base_player_event_npc_handin_repository.h index ec6af19727..acf460c50b 100644 --- a/common/repositories/base/base_player_event_npc_handin_repository.h +++ b/common/repositories/base/base_player_event_npc_handin_repository.h @@ -31,6 +31,7 @@ class BasePlayerEventNpcHandinRepository { uint64_t return_gold; uint64_t return_platinum; uint8_t is_quest_handin; + time_t created_at; }; static std::string PrimaryKey() @@ -53,6 +54,7 @@ class BasePlayerEventNpcHandinRepository { "return_gold", "return_platinum", "is_quest_handin", + "created_at", }; } @@ -71,6 +73,7 @@ class BasePlayerEventNpcHandinRepository { "return_gold", "return_platinum", "is_quest_handin", + "UNIX_TIMESTAMP(created_at)", }; } @@ -123,6 +126,7 @@ class BasePlayerEventNpcHandinRepository { e.return_gold = 0; e.return_platinum = 0; e.is_quest_handin = 0; + e.created_at = 0; return e; } @@ -171,6 +175,7 @@ class BasePlayerEventNpcHandinRepository { e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); return e; } @@ -215,6 +220,7 @@ class BasePlayerEventNpcHandinRepository { v.push_back(columns[9] + " = " + std::to_string(e.return_gold)); v.push_back(columns[10] + " = " + std::to_string(e.return_platinum)); v.push_back(columns[11] + " = " + std::to_string(e.is_quest_handin)); + v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -248,6 +254,7 @@ class BasePlayerEventNpcHandinRepository { v.push_back(std::to_string(e.return_gold)); v.push_back(std::to_string(e.return_platinum)); v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -289,6 +296,7 @@ class BasePlayerEventNpcHandinRepository { v.push_back(std::to_string(e.return_gold)); v.push_back(std::to_string(e.return_platinum)); v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -334,6 +342,7 @@ class BasePlayerEventNpcHandinRepository { e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -370,6 +379,7 @@ class BasePlayerEventNpcHandinRepository { e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -456,6 +466,7 @@ class BasePlayerEventNpcHandinRepository { v.push_back(std::to_string(e.return_gold)); v.push_back(std::to_string(e.return_platinum)); v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -490,6 +501,7 @@ class BasePlayerEventNpcHandinRepository { v.push_back(std::to_string(e.return_gold)); v.push_back(std::to_string(e.return_platinum)); v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/player_event_logs_repository.h b/common/repositories/player_event_logs_repository.h index f64be2f389..14740208f0 100644 --- a/common/repositories/player_event_logs_repository.h +++ b/common/repositories/player_event_logs_repository.h @@ -44,17 +44,6 @@ class PlayerEventLogsRepository: public BasePlayerEventLogsRepository { */ // Custom extended repository methods here - static uint32 DeleteETLRecords(Database &db, std::string &table_name, const std::vector &etl_ids) - { - auto const query = fmt::format("DELETE FROM {} WHERE `id` IN({})", table_name, Strings::Implode(", ", etl_ids)); - auto const results = db.QueryDatabase(query); - - if (!results.Success()) { - return 0; - } - - return results.RowsAffected(); - } }; #endif //EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H diff --git a/common/version.h b/common/version.h index 9ca78821e1..192a206141 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 9288 +#define CURRENT_BINARY_DATABASE_VERSION 9287 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #endif From 507f0cb7590f015bdda7c5365bc19ef800d13c54 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Mon, 21 Oct 2024 22:09:22 -0300 Subject: [PATCH 16/42] Cleanup and Formatting Cleanup and Formatting --- common/database/database_update_manifest.cpp | 3 +- common/events/player_event_logs.cpp | 138 +++++++++---------- common/events/player_event_logs.h | 23 ++-- 3 files changed, 76 insertions(+), 88 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 5d1567f7cf..88e487cd29 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -6046,6 +6046,7 @@ COLLATE='latin1_swedish_ci' ENGINE=InnoDB ; )" + } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, @@ -6084,7 +6085,7 @@ ENGINE=InnoDB //)", // } - }; +}; // see struct definitions for what each field does // struct ManifestEntry { diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 31d421eb66..7585a4cde7 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -82,7 +82,7 @@ void PlayerEventLogs::Init() PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert); } - LoadETLIDs(); + LoadEtlIds(); bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld(); bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ(); @@ -156,13 +156,12 @@ void PlayerEventLogs::ProcessBatchQueue() out.npc_id = in.npc_id; out.created_at = r.created_at; - if (m_etl_info.contains(PlayerEvent::EventType::LOOT_ITEM)) { - r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::LOOT_ITEM).etl_next_id; - m_etl_info.at(PlayerEvent::EventType::LOOT_ITEM).etl_next_id++; + if (m_etl_settings.contains(PlayerEvent::EventType::LOOT_ITEM)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id; + m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id++; } - etl_queues.queue_loot_items.push_back(out); - m_record_etl_queue.emplace(PlayerEvent::EventType::LOOT_ITEM, out); + etl_queues.loot_items.push_back(out); break; } case PlayerEvent::EventType::MERCHANT_SELL: { @@ -188,13 +187,12 @@ void PlayerEventLogs::ProcessBatchQueue() out.player_currency_balance = in.player_currency_balance; out.created_at = r.created_at; - if (m_etl_info.contains(PlayerEvent::EventType::MERCHANT_SELL)) { - r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::MERCHANT_SELL).etl_next_id; - m_etl_info.at(PlayerEvent::EventType::MERCHANT_SELL).etl_next_id++; + if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_SELL)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id; + m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id++; } - etl_queues.queue_merchant_sell.push_back(out); - m_record_etl_queue.emplace(PlayerEvent::EventType::MERCHANT_SELL, out); + etl_queues.merchant_sell.push_back(out); break; } case PlayerEvent::EventType::MERCHANT_PURCHASE: { @@ -220,13 +218,12 @@ void PlayerEventLogs::ProcessBatchQueue() out.player_currency_balance = in.player_currency_balance; out.created_at = r.created_at; - if (m_etl_info.contains(PlayerEvent::EventType::MERCHANT_PURCHASE)) { - r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::MERCHANT_PURCHASE).etl_next_id; - m_etl_info.at(PlayerEvent::EventType::MERCHANT_PURCHASE).etl_next_id++; + if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_PURCHASE)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id; + m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id++; } - etl_queues.queue_merchant_purchase.push_back(out); - m_record_etl_queue.emplace(PlayerEvent::EventType::MERCHANT_PURCHASE, out); + etl_queues.merchant_purchase.push_back(out); break; } case PlayerEvent::EventType::NPC_HANDIN: { @@ -254,9 +251,9 @@ void PlayerEventLogs::ProcessBatchQueue() out.is_quest_handin = in.is_quest_handin; out.created_at = r.created_at; - if (m_etl_info.contains(PlayerEvent::EventType::NPC_HANDIN)) { - r.etl_table_id = m_etl_info.at(PlayerEvent::EventType::NPC_HANDIN).etl_next_id; - m_etl_info.at(PlayerEvent::EventType::NPC_HANDIN).etl_next_id++; + if (m_etl_settings.contains(PlayerEvent::EventType::NPC_HANDIN)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id; + m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id++; } if (!in.handin_items.empty()) { @@ -281,7 +278,7 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.augment_5_id = augments[4]; out_entries.augment_6_id = augments[5]; } - etl_queues.queue_npc_handin_entries.push_back(out_entries); + etl_queues.npc_handin_entries.push_back(out_entries); } } @@ -307,15 +304,15 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.augment_5_id = augments[4]; out_entries.augment_6_id = augments[5]; } - etl_queues.queue_npc_handin_entries.push_back(out_entries); + etl_queues.npc_handin_entries.push_back(out_entries); } } - m_record_etl_queue.emplace(PlayerEvent::EventType::NPC_HANDIN, out); - etl_queues.queue_npc_handin.push_back(out); + etl_queues.npc_handin.push_back(out); break; } default: { + LogError("Non-Implemented ETL routing [{}]", r.event_type_id); } } } @@ -324,47 +321,38 @@ void PlayerEventLogs::ProcessBatchQueue() PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); // flush detailed tables - if (!m_record_etl_queue.empty()) { - for (auto const &[key, value]: m_record_etl_queue) { - switch (key) { - case PlayerEvent::LOOT_ITEM: { - PlayerEventLootItemsRepository::InsertMany(*m_database, etl_queues.queue_loot_items); - etl_queues.queue_loot_items.clear(); - break; - } - case PlayerEvent::MERCHANT_SELL: { - PlayerEventMerchantSellRepository::InsertMany(*m_database, etl_queues.queue_merchant_sell); - etl_queues.queue_merchant_sell.clear(); - break; - } - case PlayerEvent::MERCHANT_PURCHASE: { - PlayerEventMerchantPurchaseRepository::InsertMany(*m_database, etl_queues.queue_merchant_purchase); - etl_queues.queue_merchant_purchase.clear(); - break; - } - case PlayerEvent::NPC_HANDIN: { - PlayerEventNpcHandinRepository::InsertMany(*m_database, etl_queues.queue_npc_handin); - PlayerEventNpcHandinEntriesRepository::InsertMany(*m_database, etl_queues.queue_npc_handin_entries); - etl_queues.queue_npc_handin.clear(); - etl_queues.queue_npc_handin_entries.clear(); - break; - } - default: { - LogError("Non-Implemented ETL event type [{}] ", static_cast(key)); - } - } + if (!etl_queues.loot_items.empty()) { + PlayerEventLootItemsRepository::InsertMany(*m_database, etl_queues.loot_items); + etl_queues.loot_items.clear(); + } - LogPlayerEventsDetail( - "Processing batch player event log queue of [{}] took [{}]", - m_record_batch_queue.size(), - benchmark.elapsed() - ); + if (!etl_queues.merchant_sell.empty()) { + PlayerEventMerchantSellRepository::InsertMany(*m_database, etl_queues.merchant_sell); + etl_queues.merchant_sell.clear(); + } + + if (!etl_queues.merchant_purchase.empty()) { + PlayerEventMerchantPurchaseRepository::InsertMany(*m_database, etl_queues.merchant_purchase); + etl_queues.merchant_purchase.clear(); + } + + if (!etl_queues.npc_handin.empty()) { + PlayerEventNpcHandinRepository::InsertMany(*m_database, etl_queues.npc_handin); + etl_queues.npc_handin.clear(); + if (!etl_queues.npc_handin_entries.empty()) { + PlayerEventNpcHandinEntriesRepository::InsertMany(*m_database, etl_queues.npc_handin_entries); + etl_queues.npc_handin_entries.clear(); } } + LogPlayerEventsDetail( + "Processing batch player event log queue of [{}] took [{}]", + m_record_batch_queue.size(), + benchmark.elapsed() + ); + // empty m_record_batch_queue.clear(); - m_record_etl_queue.clear(); m_batch_queue_lock.unlock(); } @@ -848,7 +836,7 @@ void PlayerEventLogs::ProcessRetentionTruncation() LogPlayerEvents("Running truncation"); for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { - if (m_settings[i].retention_days >= 0) { + if (m_settings[i].retention_days > 0) { if (m_settings[i].etl_enabled) { uint32 deleted_count; switch (m_settings[i].id) { @@ -924,7 +912,7 @@ void PlayerEventLogs::ProcessRetentionTruncation() } } - LoadETLIDs(); + LoadEtlIds(); } void PlayerEventLogs::ReloadSettings() @@ -1001,40 +989,40 @@ void PlayerEventLogs::SetSettingsDefaults() } } -void PlayerEventLogs::LoadETLIDs() +void PlayerEventLogs::LoadEtlIds() { - m_etl_info.clear(); - m_etl_info = { + m_etl_settings.clear(); + m_etl_settings = { { PlayerEvent::LOOT_ITEM, { - .etl_enabled = true, - .etl_table_name = "player_event_loot_items", - .etl_next_id = PlayerEventLootItemsRepository::GetMaxId(*m_database) + 1 + .enabled = true, + .table_name = "player_event_loot_items", + .next_id = PlayerEventLootItemsRepository::GetMaxId(*m_database) + 1 } }, { PlayerEvent::MERCHANT_SELL, { - .etl_enabled = true, - .etl_table_name = "player_event_merchant_sell", - .etl_next_id = BasePlayerEventMerchantSellRepository::GetMaxId(*m_database) + 1 + .enabled = true, + .table_name = "player_event_merchant_sell", + .next_id = BasePlayerEventMerchantSellRepository::GetMaxId(*m_database) + 1 } }, { PlayerEvent::MERCHANT_PURCHASE, { - .etl_enabled = true, - .etl_table_name = "player_event_merchant_purchase", - .etl_next_id = PlayerEventMerchantPurchaseRepository::GetMaxId(*m_database) + 1 + .enabled = true, + .table_name = "player_event_merchant_purchase", + .next_id = PlayerEventMerchantPurchaseRepository::GetMaxId(*m_database) + 1 } }, { PlayerEvent::NPC_HANDIN, { - .etl_enabled = true, - .etl_table_name = "player_event_npc_handin", - .etl_next_id = PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1 + .enabled = true, + .table_name = "player_event_npc_handin", + .next_id = PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1 } }, }; diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index dd0c13fabc..1ec2738ee0 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -20,7 +20,7 @@ class PlayerEventLogs { public: void Init(); void ReloadSettings(); - void LoadETLIDs(); + void LoadEtlIds(); PlayerEventLogs *SetDatabase(Database *db); bool ValidateDatabaseConnection(); bool IsEventEnabled(PlayerEvent::EventType event); @@ -68,18 +68,18 @@ class PlayerEventLogs { static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e); struct EtlQueues { - std::vector queue_loot_items; - std::vector queue_merchant_purchase; - std::vector queue_merchant_sell; - std::vector queue_npc_handin; - std::vector queue_npc_handin_entries; + std::vector loot_items; + std::vector merchant_purchase; + std::vector merchant_sell; + std::vector npc_handin; + std::vector npc_handin_entries; }; private: - struct EtlInfo { - bool etl_enabled; - std::string etl_table_name; - int64 etl_next_id; + struct EtlSettings { + bool enabled; + std::string table_name; + int64 next_id; }; Database *m_database; // reference to database @@ -91,8 +91,7 @@ class PlayerEventLogs { static std::unique_ptr BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); - std::map m_record_etl_queue{}; - std::map m_etl_info{}; + std::map m_etl_settings{}; // timers Timer m_process_batch_events_timer; // events processing timer From b350d911c45faff8acf44c969920bbdcf59a00b2 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Wed, 23 Oct 2024 21:21:24 -0300 Subject: [PATCH 17/42] Add etl for Playerevent::Trade PlayerEvent::Speech (new event to mirror functionality of qs_speech --- common/CMakeLists.txt | 6 + common/database/database_update_manifest.cpp | 2 +- common/events/player_event_logs.cpp | 152 +++++ common/events/player_event_logs.h | 9 +- common/events/player_events.h | 24 +- .../base_player_event_speech_repository.h | 463 +++++++++++++++ ...se_player_event_trade_entries_repository.h | 535 ++++++++++++++++++ .../base/base_player_event_trade_repository.h | 511 +++++++++++++++++ .../player_event_speech_repository.h | 50 ++ .../player_event_trade_entries_repository.h | 50 ++ .../player_event_trade_repository.h | 50 ++ zone/client.cpp | 18 +- zone/task_manager.cpp | 4 +- 13 files changed, 1868 insertions(+), 6 deletions(-) create mode 100644 common/repositories/base/base_player_event_speech_repository.h create mode 100644 common/repositories/base/base_player_event_trade_entries_repository.h create mode 100644 common/repositories/base/base_player_event_trade_repository.h create mode 100644 common/repositories/player_event_speech_repository.h create mode 100644 common/repositories/player_event_trade_entries_repository.h create mode 100644 common/repositories/player_event_trade_repository.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ecb12a29e3..a7636017dd 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -284,6 +284,9 @@ SET(repositories repositories/base/base_player_event_merchant_sell_repository.h repositories/base/base_player_event_npc_handin_repository.h repositories/base/base_player_event_npc_handin_entries_repository.h + repositories/base/base_player_event_speech_repository.h + repositories/base/base_player_event_trade_repository.h + repositories/base/base_player_event_trade_entries_repository.h repositories/base/base_quest_globals_repository.h repositories/base/base_raid_details_repository.h repositories/base/base_raid_members_repository.h @@ -472,6 +475,9 @@ SET(repositories repositories/player_event_merchant_sell_repository.h repositories/player_event_npc_handin_repository.h repositories/player_event_npc_handin_entries_repository.h + repositories/player_event_speech_repository.h + repositories/player_event_trade_repository.h + repositories/player_event_trade_entries_repository.h repositories/quest_globals_repository.h repositories/raid_details_repository.h repositories/raid_members_repository.h diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 88e487cd29..c99ce40716 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -6058,7 +6058,7 @@ ENGINE=InnoDB // //)" - // Used for testing + // Used for testing // ManifestEntry{ // .version = 9229, // .description = "new_database_check_test", diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 7585a4cde7..0e623fc39e 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -311,6 +311,105 @@ void PlayerEventLogs::ProcessBatchQueue() etl_queues.npc_handin.push_back(out); break; } + case PlayerEvent::EventType::TRADE: { + PlayerEvent::TradeEvent in{}; + PlayerEventTradeRepository::PlayerEventTrade out{}; + PlayerEventTradeEntriesRepository::PlayerEventTradeEntries out_entries{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.char1_id = in.character_1_id; + out.char1_platinum = in.character_1_give_money.platinum; + out.char1_gold = in.character_1_give_money.gold; + out.char1_silver = in.character_1_give_money.silver; + out.char1_copper = in.character_1_give_money.copper; + out.char2_id = in.character_2_id; + out.char2_platinum = in.character_2_give_money.platinum; + out.char2_gold = in.character_2_give_money.gold; + out.char2_silver = in.character_2_give_money.silver; + out.char2_copper = in.character_2_give_money.copper; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::TRADE)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id; + m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id++; + } + + if (!in.character_1_give_items.empty()) { + for (auto const &i: in.character_1_give_items) { + out_entries.char_id = in.character_1_id; + out_entries.charges = i.charges; + out_entries.slot = i.slot; + out_entries.item_id = i.item_id; + out_entries.player_event_trade_id = r.etl_table_id; + out_entries.in_bag = i.in_bag; + out.created_at = r.created_at; + out_entries.augment_1_id = i.aug_1_item_id; + out_entries.augment_2_id = i.aug_2_item_id; + out_entries.augment_3_id = i.aug_3_item_id; + out_entries.augment_4_id = i.aug_4_item_id; + out_entries.augment_5_id = i.aug_5_item_id; + out_entries.augment_6_id = i.aug_6_item_id; + out_entries.created_at = r.created_at; + } + etl_queues.trade_entries.push_back(out_entries); + } + + if (!in.character_2_give_items.empty()) { + for (auto const &i: in.character_2_give_items) { + out_entries.char_id = in.character_2_id; + out_entries.charges = i.charges; + out_entries.slot = i.slot; + out_entries.item_id = i.item_id; + out_entries.player_event_trade_id = r.etl_table_id; + out_entries.in_bag = i.in_bag; + out.created_at = r.created_at; + out_entries.augment_1_id = i.aug_1_item_id; + out_entries.augment_2_id = i.aug_2_item_id; + out_entries.augment_3_id = i.aug_3_item_id; + out_entries.augment_4_id = i.aug_4_item_id; + out_entries.augment_5_id = i.aug_5_item_id; + out_entries.augment_6_id = i.aug_6_item_id; + out_entries.created_at = r.created_at; + } + etl_queues.trade_entries.push_back(out_entries); + } + + etl_queues.trade.push_back(out); + break; + } + case PlayerEvent::EventType::SPEECH: { + PlayerEvent::PlayerSpeech in{}; + PlayerEventSpeechRepository::PlayerEventSpeech out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.from_char_id = in.from; + out.to_char_id = in.to; + out.type = in.type; + out.min_status = in.min_status; + out.message = in.message; + out.guild_id = in.guild_id; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::SPEECH)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id; + m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id++; + } + + etl_queues.speech.push_back(out); + break; + } default: { LogError("Non-Implemented ETL routing [{}]", r.event_type_id); } @@ -345,6 +444,21 @@ void PlayerEventLogs::ProcessBatchQueue() } } + if (!etl_queues.trade.empty()) { + PlayerEventTradeRepository::InsertMany(*m_database, etl_queues.trade); + etl_queues.trade.clear(); + if (!etl_queues.trade_entries.empty()) { + PlayerEventTradeEntriesRepository::InsertMany(*m_database, etl_queues.trade_entries); + etl_queues.trade_entries.clear(); + } + } + + if (!etl_queues.speech.empty()) { + PlayerEventSpeechRepository::InsertMany(*m_database, etl_queues.speech); + etl_queues.speech.clear(); + } + + LogPlayerEventsDetail( "Processing batch player event log queue of [{}] took [{}]", m_record_batch_queue.size(), @@ -877,6 +991,27 @@ void PlayerEventLogs::ProcessRetentionTruncation() m_settings[i].retention_days)); break; } + case PlayerEvent::TRADE: { + deleted_count = PlayerEventTradeRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + deleted_count += PlayerEventTradeEntriesRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } + case PlayerEvent::SPEECH: { + deleted_count = PlayerEventSpeechRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } default: { LogError("NonImplemented ETL Event Type [{}] ", static_cast(m_settings[i].id)); } @@ -983,6 +1118,7 @@ void PlayerEventLogs::SetSettingsDefaults() m_settings[PlayerEvent::PARCEL_RETRIEVE].event_enabled = 1; m_settings[PlayerEvent::PARCEL_DELETE].event_enabled = 1; m_settings[PlayerEvent::BARTER_TRANSACTION].event_enabled = 1; + m_settings[PlayerEvent::SPEECH].event_enabled = 1; for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { m_settings[i].retention_days = RETENTION_DAYS_DEFAULT; @@ -1025,5 +1161,21 @@ void PlayerEventLogs::LoadEtlIds() .next_id = PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1 } }, + { + PlayerEvent::TRADE, + { + .enabled = true, + .table_name = "player_event_trade", + .next_id = PlayerEventTradeRepository::GetMaxId(*m_database) + 1 + } + }, + { + PlayerEvent::SPEECH, + { + .enabled = true, + .table_name = "player_event_speech", + .next_id = PlayerEventSpeechRepository::GetMaxId(*m_database) + 1 + } + } }; } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 1ec2738ee0..e36fe89ddb 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -13,8 +13,12 @@ #include "../repositories/player_event_loot_items_repository.h" #include "../repositories/player_event_merchant_purchase_repository.h" #include "../repositories/player_event_merchant_sell_repository.h" -#include "../repositories/player_event_npc_handin_entries_repository.h" #include "../repositories/player_event_npc_handin_repository.h" +#include "../repositories/player_event_npc_handin_entries_repository.h" +#include "../repositories/player_event_trade_repository.h" +#include "../repositories/player_event_trade_entries_repository.h" +#include "../repositories/player_event_speech_repository.h" + class PlayerEventLogs { public: @@ -73,6 +77,9 @@ class PlayerEventLogs { std::vector merchant_sell; std::vector npc_handin; std::vector npc_handin_entries; + std::vector trade; + std::vector trade_entries; + std::vector speech; }; private: diff --git a/common/events/player_events.h b/common/events/player_events.h index 6384f8e0e4..a393415ad7 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -62,6 +62,7 @@ namespace PlayerEvent { PARCEL_RETRIEVE, PARCEL_DELETE, BARTER_TRANSACTION, + SPEECH, MAX // dont remove }; @@ -124,7 +125,8 @@ namespace PlayerEvent { "Parcel Item Sent", "Parcel Item Retrieved", "Parcel Prune Routine", - "Barter Transaction" + "Barter Transaction", + "Player Speech" }; // Generic struct used by all events @@ -1115,6 +1117,26 @@ namespace PlayerEvent { ); } }; + + struct PlayerSpeech { + std::string to; + std::string from; + uint32 guild_id; + int16 min_status; + uint32 type; + std::string message; + + template void serialize(Archive &ar) + { + ar(CEREAL_NVP(to), + CEREAL_NVP(from), + CEREAL_NVP(guild_id), + CEREAL_NVP(min_status), + CEREAL_NVP(type), + CEREAL_NVP(message) + ); + } + }; } #endif //EQEMU_PLAYER_EVENTS_H diff --git a/common/repositories/base/base_player_event_speech_repository.h b/common/repositories/base/base_player_event_speech_repository.h new file mode 100644 index 0000000000..80823f3e6a --- /dev/null +++ b/common/repositories/base/base_player_event_speech_repository.h @@ -0,0 +1,463 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventSpeechRepository { +public: + struct PlayerEventSpeech { + uint64_t id; + std::string to_char_id; + std::string from_char_id; + uint32_t guild_id; + uint32_t type; + uint32_t min_status; + std::string message; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "to_char_id", + "from_char_id", + "guild_id", + "type", + "min_status", + "message", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "to_char_id", + "from_char_id", + "guild_id", + "type", + "min_status", + "message", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_speech"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventSpeech NewEntity() + { + PlayerEventSpeech e{}; + + e.id = 0; + e.to_char_id = ""; + e.from_char_id = ""; + e.guild_id = 0; + e.type = 0; + e.min_status = 0; + e.message = ""; + e.created_at = 0; + + return e; + } + + static PlayerEventSpeech GetPlayerEventSpeech( + const std::vector &player_event_speechs, + int player_event_speech_id + ) + { + for (auto &player_event_speech : player_event_speechs) { + if (player_event_speech.id == player_event_speech_id) { + return player_event_speech; + } + } + + return NewEntity(); + } + + static PlayerEventSpeech FindOne( + Database& db, + int player_event_speech_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_speech_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventSpeech e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.to_char_id = row[1] ? row[1] : ""; + e.from_char_id = row[2] ? row[2] : ""; + e.guild_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.type = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.min_status = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.message = row[6] ? row[6] : ""; + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_speech_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_speech_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventSpeech &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = '" + Strings::Escape(e.to_char_id) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.guild_id)); + v.push_back(columns[4] + " = " + std::to_string(e.type)); + v.push_back(columns[5] + " = " + std::to_string(e.min_status)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.message) + "'"); + v.push_back(columns[7] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventSpeech InsertOne( + Database& db, + PlayerEventSpeech e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventSpeech e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.to_char_id = row[1] ? row[1] : ""; + e.from_char_id = row[2] ? row[2] : ""; + e.guild_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.type = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.min_status = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.message = row[6] ? row[6] : ""; + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventSpeech e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.to_char_id = row[1] ? row[1] : ""; + e.from_char_id = row[2] ? row[2] : ""; + e.guild_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.type = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.min_status = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.message = row[6] ? row[6] : ""; + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventSpeech &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_trade_entries_repository.h b/common/repositories/base/base_player_event_trade_entries_repository.h new file mode 100644 index 0000000000..ae117e32a9 --- /dev/null +++ b/common/repositories/base/base_player_event_trade_entries_repository.h @@ -0,0 +1,535 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventTradeEntriesRepository { +public: + struct PlayerEventTradeEntries { + uint64_t id; + uint64_t player_event_trade_id; + uint32_t char_id; + int16_t slot; + uint32_t item_id; + int16_t charges; + uint32_t augment_1_id; + uint32_t augment_2_id; + uint32_t augment_3_id; + uint32_t augment_4_id; + uint32_t augment_5_id; + uint32_t augment_6_id; + int8_t in_bag; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "player_event_trade_id", + "char_id", + "slot", + "item_id", + "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + "in_bag", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "player_event_trade_id", + "char_id", + "slot", + "item_id", + "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + "in_bag", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_trade_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventTradeEntries NewEntity() + { + PlayerEventTradeEntries e{}; + + e.id = 0; + e.player_event_trade_id = 0; + e.char_id = 0; + e.slot = 0; + e.item_id = 0; + e.charges = 0; + e.augment_1_id = 0; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 0; + e.augment_5_id = 0; + e.augment_6_id = 0; + e.in_bag = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventTradeEntries GetPlayerEventTradeEntries( + const std::vector &player_event_trade_entriess, + int player_event_trade_entries_id + ) + { + for (auto &player_event_trade_entries : player_event_trade_entriess) { + if (player_event_trade_entries.id == player_event_trade_entries_id) { + return player_event_trade_entries; + } + } + + return NewEntity(); + } + + static PlayerEventTradeEntries FindOne( + Database& db, + int player_event_trade_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_trade_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventTradeEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_trade_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.char_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.slot = row[3] ? static_cast(atoi(row[3])) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.charges = row[5] ? static_cast(atoi(row[5])) : 0; + e.augment_1_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_2_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_3_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_4_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_5_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_6_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.in_bag = row[12] ? static_cast(atoi(row[12])) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_trade_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_trade_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventTradeEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.player_event_trade_id)); + v.push_back(columns[2] + " = " + std::to_string(e.char_id)); + v.push_back(columns[3] + " = " + std::to_string(e.slot)); + v.push_back(columns[4] + " = " + std::to_string(e.item_id)); + v.push_back(columns[5] + " = " + std::to_string(e.charges)); + v.push_back(columns[6] + " = " + std::to_string(e.augment_1_id)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_2_id)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_3_id)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_4_id)); + v.push_back(columns[10] + " = " + std::to_string(e.augment_5_id)); + v.push_back(columns[11] + " = " + std::to_string(e.augment_6_id)); + v.push_back(columns[12] + " = " + std::to_string(e.in_bag)); + v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventTradeEntries InsertOne( + Database& db, + PlayerEventTradeEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTradeEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_trade_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.char_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.slot = row[3] ? static_cast(atoi(row[3])) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.charges = row[5] ? static_cast(atoi(row[5])) : 0; + e.augment_1_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_2_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_3_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_4_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_5_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_6_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.in_bag = row[12] ? static_cast(atoi(row[12])) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTradeEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_trade_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.char_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.slot = row[3] ? static_cast(atoi(row[3])) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.charges = row[5] ? static_cast(atoi(row[5])) : 0; + e.augment_1_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_2_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_3_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_4_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_5_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_6_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.in_bag = row[12] ? static_cast(atoi(row[12])) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventTradeEntries &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_trade_repository.h b/common/repositories/base/base_player_event_trade_repository.h new file mode 100644 index 0000000000..58409a5cbd --- /dev/null +++ b/common/repositories/base/base_player_event_trade_repository.h @@ -0,0 +1,511 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventTradeRepository { +public: + struct PlayerEventTrade { + uint32_t id; + uint32_t char1_id; + uint32_t char2_id; + uint64_t char1_copper; + uint64_t char1_silver; + uint64_t char1_gold; + uint64_t char1_platinum; + uint64_t char2_copper; + uint64_t char2_silver; + uint64_t char2_gold; + uint64_t char2_platinum; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "char1_id", + "char2_id", + "char1_copper", + "char1_silver", + "char1_gold", + "char1_platinum", + "char2_copper", + "char2_silver", + "char2_gold", + "char2_platinum", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "char1_id", + "char2_id", + "char1_copper", + "char1_silver", + "char1_gold", + "char1_platinum", + "char2_copper", + "char2_silver", + "char2_gold", + "char2_platinum", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_trade"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventTrade NewEntity() + { + PlayerEventTrade e{}; + + e.id = 0; + e.char1_id = 0; + e.char2_id = 0; + e.char1_copper = 0; + e.char1_silver = 0; + e.char1_gold = 0; + e.char1_platinum = 0; + e.char2_copper = 0; + e.char2_silver = 0; + e.char2_gold = 0; + e.char2_platinum = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventTrade GetPlayerEventTrade( + const std::vector &player_event_trades, + int player_event_trade_id + ) + { + for (auto &player_event_trade : player_event_trades) { + if (player_event_trade.id == player_event_trade_id) { + return player_event_trade; + } + } + + return NewEntity(); + } + + static PlayerEventTrade FindOne( + Database& db, + int player_event_trade_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_trade_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventTrade e{}; + + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char1_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.char2_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.char1_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.char1_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.char1_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.char1_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.char2_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.char2_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.char2_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.char2_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_trade_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_trade_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventTrade &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.char1_id)); + v.push_back(columns[2] + " = " + std::to_string(e.char2_id)); + v.push_back(columns[3] + " = " + std::to_string(e.char1_copper)); + v.push_back(columns[4] + " = " + std::to_string(e.char1_silver)); + v.push_back(columns[5] + " = " + std::to_string(e.char1_gold)); + v.push_back(columns[6] + " = " + std::to_string(e.char1_platinum)); + v.push_back(columns[7] + " = " + std::to_string(e.char2_copper)); + v.push_back(columns[8] + " = " + std::to_string(e.char2_silver)); + v.push_back(columns[9] + " = " + std::to_string(e.char2_gold)); + v.push_back(columns[10] + " = " + std::to_string(e.char2_platinum)); + v.push_back(columns[11] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventTrade InsertOne( + Database& db, + PlayerEventTrade e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTrade e{}; + + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char1_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.char2_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.char1_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.char1_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.char1_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.char1_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.char2_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.char2_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.char2_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.char2_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTrade e{}; + + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char1_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.char2_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.char1_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.char1_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.char1_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.char1_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.char2_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.char2_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.char2_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.char2_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventTrade &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H diff --git a/common/repositories/player_event_speech_repository.h b/common/repositories/player_event_speech_repository.h new file mode 100644 index 0000000000..7702c24679 --- /dev/null +++ b/common/repositories/player_event_speech_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_speech_repository.h" + +class PlayerEventSpeechRepository: public BasePlayerEventSpeechRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventSpeechRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventSpeechRepository::GetWhereNeverExpires() + * PlayerEventSpeechRepository::GetWhereXAndY() + * PlayerEventSpeechRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/player_event_trade_entries_repository.h b/common/repositories/player_event_trade_entries_repository.h new file mode 100644 index 0000000000..b257488c07 --- /dev/null +++ b/common/repositories/player_event_trade_entries_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_trade_entries_repository.h" + +class PlayerEventTradeEntriesRepository: public BasePlayerEventTradeEntriesRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventTradeEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventTradeEntriesRepository::GetWhereNeverExpires() + * PlayerEventTradeEntriesRepository::GetWhereXAndY() + * PlayerEventTradeEntriesRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_trade_repository.h b/common/repositories/player_event_trade_repository.h new file mode 100644 index 0000000000..194d197021 --- /dev/null +++ b/common/repositories/player_event_trade_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_trade_repository.h" + +class PlayerEventTradeRepository: public BasePlayerEventTradeRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventTradeRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventTradeRepository::GetWhereNeverExpires() + * PlayerEventTradeRepository::GetWhereXAndY() + * PlayerEventTradeRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H diff --git a/zone/client.cpp b/zone/client.cpp index be693e453e..56d4a4c686 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -928,6 +928,21 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } } + if (PlayerEvent::EventType::SPEECH) { + PlayerEvent::PlayerSpeech e{}; + e.message = message; + e.min_status = Admin(); + e.type = chan_num; + e.to = targetname; + e.from = GetName(); + + if (chan_num == ChatChannel_Guild) { + e.guild_id = GuildID(); + } + + RecordPlayerEventLog(PlayerEvent::SPEECH, e); + } + /* Logs Player Chat */ if (RuleB(QueryServ, PlayerLogChat)) { auto pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1); @@ -12284,7 +12299,8 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) }; RecordPlayerEventLogWithClient(trader, PlayerEvent::TRADE, e); - RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e); + //Not sure the usefulness of sending the same data twice?? + //RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e); } void Client::NPCHandinEventLog(Trade* t, NPC* n) diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 34cb4d6c40..3e6ec9992b 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -198,9 +198,9 @@ bool TaskManager::LoadTasks(int single_task) ad->target_name = a.target_name; ad->item_list = a.item_list; ad->skill_list = a.skill_list; - ad->skill_id = Strings::IsNumber(a.skill_list) ? Strings::ToInt(a.skill_list) : 0; // for older clients + ad->skill_id = !a.skill_list.empty() && Strings::IsNumber(a.skill_list) ? Strings::ToInt(a.skill_list) : 0; // for older clients ad->spell_list = a.spell_list; - ad->spell_id = Strings::IsNumber(a.spell_list) ? Strings::ToInt(a.spell_list) : 0; // for older clients + ad->spell_id = !a.skill_list.empty() && Strings::IsNumber(a.spell_list) ? Strings::ToInt(a.spell_list) : 0; // for older clients ad->description_override = a.description_override; ad->npc_match_list = a.npc_match_list; ad->item_id_list = a.item_id_list; From 77b3752b88061ad611a3d7823956c37890c63bff Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:46:30 -0300 Subject: [PATCH 18/42] Add etl for Playerevent::KilledNPC, KilledNamedNPC and KilledRaidNPC --- common/CMakeLists.txt | 6 + common/events/player_event_logs.cpp | 142 +++++- common/events/player_event_logs.h | 6 + ...player_event_killed_named_npc_repository.h | 451 ++++++++++++++++++ .../base_player_event_killed_npc_repository.h | 451 ++++++++++++++++++ ..._player_event_killed_raid_npc_repository.h | 451 ++++++++++++++++++ ...player_event_killed_named_npc_repository.h | 50 ++ .../player_event_killed_npc_repository.h | 50 ++ .../player_event_killed_raid_npc_repository.h | 50 ++ zone/client.cpp | 22 +- zone/client_packet.cpp | 5 + 11 files changed, 1673 insertions(+), 11 deletions(-) create mode 100644 common/repositories/base/base_player_event_killed_named_npc_repository.h create mode 100644 common/repositories/base/base_player_event_killed_npc_repository.h create mode 100644 common/repositories/base/base_player_event_killed_raid_npc_repository.h create mode 100644 common/repositories/player_event_killed_named_npc_repository.h create mode 100644 common/repositories/player_event_killed_npc_repository.h create mode 100644 common/repositories/player_event_killed_raid_npc_repository.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index a7636017dd..7f982e8ec6 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -277,6 +277,9 @@ SET(repositories repositories/base/base_pets_equipmentset_repository.h repositories/base/base_pets_equipmentset_entries_repository.h repositories/base/base_player_titlesets_repository.h + repositories/base/base_player_event_killed_npc_repository.h + repositories/base/base_player_event_killed_named_npc_repository.h + repositories/base/base_player_event_killed_raid_npc_repository.h repositories/base/base_player_event_log_settings_repository.h repositories/base/base_player_event_logs_repository.h repositories/base/base_player_event_loot_items_repository.h @@ -468,6 +471,9 @@ SET(repositories repositories/pets_equipmentset_repository.h repositories/pets_equipmentset_entries_repository.h repositories/player_titlesets_repository.h + repositories/player_event_killed_npc_repository.h + repositories/player_event_killed_named_npc_repository.h + repositories/player_event_killed_raid_npc_repository.h repositories/player_event_log_settings_repository.h repositories/player_event_logs_repository.h repositories/player_event_loot_items_repository.h diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 0e623fc39e..a7897662bd 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -137,7 +137,7 @@ void PlayerEventLogs::ProcessBatchQueue() EtlQueues etl_queues{}; for (auto &r:m_record_batch_queue) { - switch (r.event_type_id) { + switch (r.event_type_id && m_settings[r.event_type_id].etl_enabled) { case PlayerEvent::EventType::LOOT_ITEM: { PlayerEvent::LootItemEvent in{}; PlayerEventLootItemsRepository::PlayerEventLootItems out{}; @@ -410,6 +410,84 @@ void PlayerEventLogs::ProcessBatchQueue() etl_queues.speech.push_back(out); break; } + case PlayerEvent::EventType::KILLED_NPC: { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledNpcRepository::PlayerEventKilledNpc out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NPC)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id; + m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id++; + } + + etl_queues.killed_npc.push_back(out); + break; + } + case PlayerEvent::EventType::KILLED_NAMED_NPC: { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledNamedNpcRepository::PlayerEventKilledNamedNpc out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NAMED_NPC)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id; + m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id++; + } + + etl_queues.killed_named_npc.push_back(out); + break; + } + case PlayerEvent::EventType::KILLED_RAID_NPC: { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledRaidNpcRepository::PlayerEventKilledRaidNpc out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_RAID_NPC)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id; + m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id++; + } + + etl_queues.killed_raid_npc.push_back(out); + break; + } default: { LogError("Non-Implemented ETL routing [{}]", r.event_type_id); } @@ -458,6 +536,20 @@ void PlayerEventLogs::ProcessBatchQueue() etl_queues.speech.clear(); } + if (!etl_queues.killed_npc.empty()) { + PlayerEventKilledNpcRepository::InsertMany(*m_database, etl_queues.killed_npc); + etl_queues.killed_npc.clear(); + } + + if (!etl_queues.killed_named_npc.empty()) { + PlayerEventKilledNamedNpcRepository::InsertMany(*m_database, etl_queues.killed_named_npc); + etl_queues.killed_named_npc.clear(); + } + + if (!etl_queues.killed_raid_npc.empty()) { + PlayerEventKilledRaidNpcRepository::InsertMany(*m_database, etl_queues.killed_raid_npc); + etl_queues.killed_raid_npc.clear(); + } LogPlayerEventsDetail( "Processing batch player event log queue of [{}] took [{}]", @@ -1012,6 +1104,30 @@ void PlayerEventLogs::ProcessRetentionTruncation() m_settings[i].retention_days)); break; } + case PlayerEvent::KILLED_NPC: { + deleted_count = PlayerEventKilledNpcRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } + case PlayerEvent::KILLED_NAMED_NPC: { + deleted_count = PlayerEventKilledNamedNpcRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } + case PlayerEvent::KILLED_RAID_NPC: { + deleted_count = PlayerEventKilledRaidNpcRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } default: { LogError("NonImplemented ETL Event Type [{}] ", static_cast(m_settings[i].id)); } @@ -1176,6 +1292,30 @@ void PlayerEventLogs::LoadEtlIds() .table_name = "player_event_speech", .next_id = PlayerEventSpeechRepository::GetMaxId(*m_database) + 1 } + }, + { + PlayerEvent::KILLED_NPC, + { + .enabled = true, + .table_name = "player_event_killed_npc", + .next_id = PlayerEventKilledNpcRepository::GetMaxId(*m_database) + 1 + } + }, + { + PlayerEvent::KILLED_NAMED_NPC, + { + .enabled = true, + .table_name = "player_event_killed_named_npc", + .next_id = PlayerEventKilledNamedNpcRepository::GetMaxId(*m_database) + 1 + } + }, + { + PlayerEvent::KILLED_RAID_NPC, + { + .enabled = true, + .table_name = "player_event_killed_raid_npc", + .next_id = PlayerEventKilledRaidNpcRepository::GetMaxId(*m_database) + 1 + } } }; } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index e36fe89ddb..3951a00ca5 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -18,6 +18,9 @@ #include "../repositories/player_event_trade_repository.h" #include "../repositories/player_event_trade_entries_repository.h" #include "../repositories/player_event_speech_repository.h" +#include "../repositories/player_event_killed_npc_repository.h" +#include "../repositories/player_event_killed_named_npc_repository.h" +#include "../repositories/player_event_killed_raid_npc_repository.h" class PlayerEventLogs { @@ -80,6 +83,9 @@ class PlayerEventLogs { std::vector trade; std::vector trade_entries; std::vector speech; + std::vector killed_npc; + std::vector killed_named_npc; + std::vector killed_raid_npc; }; private: diff --git a/common/repositories/base/base_player_event_killed_named_npc_repository.h b/common/repositories/base/base_player_event_killed_named_npc_repository.h new file mode 100644 index 0000000000..027e5afbf9 --- /dev/null +++ b/common/repositories/base/base_player_event_killed_named_npc_repository.h @@ -0,0 +1,451 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventKilledNamedNpcRepository { +public: + struct PlayerEventKilledNamedNpc { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint32_t combat_time_seconds; + uint64_t total_damage_per_second_taken; + uint64_t total_heal_per_second_taken; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_killed_named_npc"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventKilledNamedNpc NewEntity() + { + PlayerEventKilledNamedNpc e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.combat_time_seconds = 0; + e.total_damage_per_second_taken = 0; + e.total_heal_per_second_taken = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventKilledNamedNpc GetPlayerEventKilledNamedNpc( + const std::vector &player_event_killed_named_npcs, + int player_event_killed_named_npc_id + ) + { + for (auto &player_event_killed_named_npc : player_event_killed_named_npcs) { + if (player_event_killed_named_npc.id == player_event_killed_named_npc_id) { + return player_event_killed_named_npc; + } + } + + return NewEntity(); + } + + static PlayerEventKilledNamedNpc FindOne( + Database& db, + int player_event_killed_named_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_killed_named_npc_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventKilledNamedNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_killed_named_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_killed_named_npc_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventKilledNamedNpc &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.combat_time_seconds)); + v.push_back(columns[4] + " = " + std::to_string(e.total_damage_per_second_taken)); + v.push_back(columns[5] + " = " + std::to_string(e.total_heal_per_second_taken)); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventKilledNamedNpc InsertOne( + Database& db, + PlayerEventKilledNamedNpc e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNamedNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNamedNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventKilledNamedNpc &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_npc_repository.h b/common/repositories/base/base_player_event_killed_npc_repository.h new file mode 100644 index 0000000000..13fb3fe86d --- /dev/null +++ b/common/repositories/base/base_player_event_killed_npc_repository.h @@ -0,0 +1,451 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventKilledNpcRepository { +public: + struct PlayerEventKilledNpc { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint32_t combat_time_seconds; + uint64_t total_damage_per_second_taken; + uint64_t total_heal_per_second_taken; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_killed_npc"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventKilledNpc NewEntity() + { + PlayerEventKilledNpc e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.combat_time_seconds = 0; + e.total_damage_per_second_taken = 0; + e.total_heal_per_second_taken = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventKilledNpc GetPlayerEventKilledNpc( + const std::vector &player_event_killed_npcs, + int player_event_killed_npc_id + ) + { + for (auto &player_event_killed_npc : player_event_killed_npcs) { + if (player_event_killed_npc.id == player_event_killed_npc_id) { + return player_event_killed_npc; + } + } + + return NewEntity(); + } + + static PlayerEventKilledNpc FindOne( + Database& db, + int player_event_killed_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_killed_npc_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventKilledNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_killed_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_killed_npc_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventKilledNpc &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.combat_time_seconds)); + v.push_back(columns[4] + " = " + std::to_string(e.total_damage_per_second_taken)); + v.push_back(columns[5] + " = " + std::to_string(e.total_heal_per_second_taken)); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventKilledNpc InsertOne( + Database& db, + PlayerEventKilledNpc e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventKilledNpc &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_raid_npc_repository.h b/common/repositories/base/base_player_event_killed_raid_npc_repository.h new file mode 100644 index 0000000000..beba705c69 --- /dev/null +++ b/common/repositories/base/base_player_event_killed_raid_npc_repository.h @@ -0,0 +1,451 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventKilledRaidNpcRepository { +public: + struct PlayerEventKilledRaidNpc { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint32_t combat_time_seconds; + uint64_t total_damage_per_second_taken; + uint64_t total_heal_per_second_taken; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_killed_raid_npc"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventKilledRaidNpc NewEntity() + { + PlayerEventKilledRaidNpc e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.combat_time_seconds = 0; + e.total_damage_per_second_taken = 0; + e.total_heal_per_second_taken = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventKilledRaidNpc GetPlayerEventKilledRaidNpc( + const std::vector &player_event_killed_raid_npcs, + int player_event_killed_raid_npc_id + ) + { + for (auto &player_event_killed_raid_npc : player_event_killed_raid_npcs) { + if (player_event_killed_raid_npc.id == player_event_killed_raid_npc_id) { + return player_event_killed_raid_npc; + } + } + + return NewEntity(); + } + + static PlayerEventKilledRaidNpc FindOne( + Database& db, + int player_event_killed_raid_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_killed_raid_npc_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventKilledRaidNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_killed_raid_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_killed_raid_npc_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventKilledRaidNpc &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.combat_time_seconds)); + v.push_back(columns[4] + " = " + std::to_string(e.total_damage_per_second_taken)); + v.push_back(columns[5] + " = " + std::to_string(e.total_heal_per_second_taken)); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventKilledRaidNpc InsertOne( + Database& db, + PlayerEventKilledRaidNpc e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledRaidNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledRaidNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventKilledRaidNpc &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_named_npc_repository.h b/common/repositories/player_event_killed_named_npc_repository.h new file mode 100644 index 0000000000..e5dc32f541 --- /dev/null +++ b/common/repositories/player_event_killed_named_npc_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_killed_named_npc_repository.h" + +class PlayerEventKilledNamedNpcRepository: public BasePlayerEventKilledNamedNpcRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventKilledNamedNpcRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventKilledNamedNpcRepository::GetWhereNeverExpires() + * PlayerEventKilledNamedNpcRepository::GetWhereXAndY() + * PlayerEventKilledNamedNpcRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_npc_repository.h b/common/repositories/player_event_killed_npc_repository.h new file mode 100644 index 0000000000..94f09ebf7d --- /dev/null +++ b/common/repositories/player_event_killed_npc_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_killed_npc_repository.h" + +class PlayerEventKilledNpcRepository: public BasePlayerEventKilledNpcRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventKilledNpcRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventKilledNpcRepository::GetWhereNeverExpires() + * PlayerEventKilledNpcRepository::GetWhereXAndY() + * PlayerEventKilledNpcRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_raid_npc_repository.h b/common/repositories/player_event_killed_raid_npc_repository.h new file mode 100644 index 0000000000..57600aff5c --- /dev/null +++ b/common/repositories/player_event_killed_raid_npc_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_killed_raid_npc_repository.h" + +class PlayerEventKilledRaidNpcRepository: public BasePlayerEventKilledRaidNpcRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventKilledRaidNpcRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventKilledRaidNpcRepository::GetWhereNeverExpires() + * PlayerEventKilledRaidNpcRepository::GetWhereXAndY() + * PlayerEventKilledRaidNpcRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/zone/client.cpp b/zone/client.cpp index 56d4a4c686..1392192e70 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -928,19 +928,21 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } } - if (PlayerEvent::EventType::SPEECH) { + if (player_event_logs.IsEventEnabled(PlayerEvent::EventType::SPEECH)) { PlayerEvent::PlayerSpeech e{}; - e.message = message; - e.min_status = Admin(); - e.type = chan_num; - e.to = targetname; - e.from = GetName(); + std::string msg = message; + if (!msg.empty() && msg.at(0) != '#' && msg.at(0) != '^') { + e.message = message; + e.min_status = Admin(); + e.type = chan_num; + e.to = targetname; + e.from = GetName(); + if (chan_num == ChatChannel_Guild) { + e.guild_id = GuildID(); + } - if (chan_num == ChatChannel_Guild) { - e.guild_id = GuildID(); + RecordPlayerEventLog(PlayerEvent::SPEECH, e); } - - RecordPlayerEventLog(PlayerEvent::SPEECH, e); } /* Logs Player Chat */ diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index bf0a791c46..d4c4347345 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -16649,6 +16649,11 @@ struct RecordKillCheck { void Client::RecordKilledNPCEvent(NPC *n) { + if (!n) { + LogError("NPC passed was invalid."); + return; + } + bool is_named = Strings::Contains(n->GetName(), "#") && !n->IsRaidTarget(); std::vector checks = { From 45e01365ca0ae8eb599da6208b628da0d75f3998 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Tue, 5 Nov 2024 19:03:45 -0400 Subject: [PATCH 19/42] Add etl for Playerevent::AA_purchase Add etl for Playerevent::AA_purchase --- common/events/player_event_logs.cpp | 75 ++- common/events/player_event_logs.h | 3 + ...base_player_event_aa_purchase_repository.h | 439 ++++++++++++++++++ .../player_event_aa_purchase_repository.h | 50 ++ 4 files changed, 549 insertions(+), 18 deletions(-) create mode 100644 common/repositories/base/base_player_event_aa_purchase_repository.h create mode 100644 common/repositories/player_event_aa_purchase_repository.h diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index a7897662bd..280768f00c 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -488,6 +488,31 @@ void PlayerEventLogs::ProcessBatchQueue() etl_queues.killed_raid_npc.push_back(out); break; } + case PlayerEvent::EventType::AA_PURCHASE: { + PlayerEvent::AAPurchasedEvent in{}; + PlayerEventAaPurchaseRepository::PlayerEventAaPurchase out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } + + out.aa_ability_id = in.aa_id; + out.cost = in.aa_cost; + out.previous_id = in.aa_previous_id; + out.next_id = in.aa_next_id; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::AA_PURCHASE)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id; + m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id++; + } + + etl_queues.aa_purchase.push_back(out); + break; + } default: { LogError("Non-Implemented ETL routing [{}]", r.event_type_id); } @@ -551,6 +576,11 @@ void PlayerEventLogs::ProcessBatchQueue() etl_queues.killed_raid_npc.clear(); } + if (!etl_queues.aa_purchase.empty()) { + PlayerEventAaPurchaseRepository::InsertMany(*m_database, etl_queues.aa_purchase); + etl_queues.aa_purchase.clear(); + } + LogPlayerEventsDetail( "Processing batch player event log queue of [{}] took [{}]", m_record_batch_queue.size(), @@ -1043,8 +1073,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { if (m_settings[i].retention_days > 0) { + uint32 deleted_count; if (m_settings[i].etl_enabled) { - uint32 deleted_count; switch (m_settings[i].id) { case PlayerEvent::LOOT_ITEM: { deleted_count = PlayerEventLootItemsRepository::DeleteWhere( @@ -1128,28 +1158,29 @@ void PlayerEventLogs::ProcessRetentionTruncation() m_settings[i].retention_days)); break; } + case PlayerEvent::AA_PURCHASE: { + deleted_count = PlayerEventAaPurchaseRepository::DeleteWhere( + *m_database, + fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days)); + break; + } default: { LogError("NonImplemented ETL Event Type [{}] ", static_cast(m_settings[i].id)); } } - - LogInfo( - "Truncated [{}] events of type [{}] ({}) older than [{}] days from etl table", - deleted_count, - PlayerEvent::EventName[i], - i, - m_settings[i].retention_days); } - - - int deleted_count = PlayerEventLogsRepository::DeleteWhere( - *m_database, - fmt::format( - "event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)", - i, - m_settings[i].retention_days - ) - ); + else { + deleted_count = PlayerEventLogsRepository::DeleteWhere( + *m_database, + fmt::format( + "event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)", + i, + m_settings[i].retention_days + ) + ); + } if (deleted_count > 0) { LogInfo( @@ -1316,6 +1347,14 @@ void PlayerEventLogs::LoadEtlIds() .table_name = "player_event_killed_raid_npc", .next_id = PlayerEventKilledRaidNpcRepository::GetMaxId(*m_database) + 1 } + }, + { + PlayerEvent::AA_PURCHASE, + { + .enabled = true, + .table_name = "player_event_aa_purchase", + .next_id = PlayerEventAaPurchaseRepository::GetMaxId(*m_database) + 1 + } } }; } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 3951a00ca5..79e1c75050 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -21,6 +21,8 @@ #include "../repositories/player_event_killed_npc_repository.h" #include "../repositories/player_event_killed_named_npc_repository.h" #include "../repositories/player_event_killed_raid_npc_repository.h" +#include "../repositories/player_event_aa_purchase_repository.h" + class PlayerEventLogs { @@ -86,6 +88,7 @@ class PlayerEventLogs { std::vector killed_npc; std::vector killed_named_npc; std::vector killed_raid_npc; + std::vector aa_purchase; }; private: diff --git a/common/repositories/base/base_player_event_aa_purchase_repository.h b/common/repositories/base/base_player_event_aa_purchase_repository.h new file mode 100644 index 0000000000..ca8fb27246 --- /dev/null +++ b/common/repositories/base/base_player_event_aa_purchase_repository.h @@ -0,0 +1,439 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventAaPurchaseRepository { +public: + struct PlayerEventAaPurchase { + uint64_t id; + int32_t aa_ability_id; + int32_t cost; + int32_t previous_id; + int32_t next_id; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "aa_ability_id", + "cost", + "previous_id", + "next_id", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "aa_ability_id", + "cost", + "previous_id", + "next_id", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_aa_purchase"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventAaPurchase NewEntity() + { + PlayerEventAaPurchase e{}; + + e.id = 0; + e.aa_ability_id = 0; + e.cost = 0; + e.previous_id = 0; + e.next_id = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventAaPurchase GetPlayerEventAaPurchase( + const std::vector &player_event_aa_purchases, + int player_event_aa_purchase_id + ) + { + for (auto &player_event_aa_purchase : player_event_aa_purchases) { + if (player_event_aa_purchase.id == player_event_aa_purchase_id) { + return player_event_aa_purchase; + } + } + + return NewEntity(); + } + + static PlayerEventAaPurchase FindOne( + Database& db, + int player_event_aa_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_aa_purchase_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventAaPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.aa_ability_id = row[1] ? static_cast(atoi(row[1])) : 0; + e.cost = row[2] ? static_cast(atoi(row[2])) : 0; + e.previous_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.next_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.created_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_aa_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_aa_purchase_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventAaPurchase &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.aa_ability_id)); + v.push_back(columns[2] + " = " + std::to_string(e.cost)); + v.push_back(columns[3] + " = " + std::to_string(e.previous_id)); + v.push_back(columns[4] + " = " + std::to_string(e.next_id)); + v.push_back(columns[5] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventAaPurchase InsertOne( + Database& db, + PlayerEventAaPurchase e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventAaPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.aa_ability_id = row[1] ? static_cast(atoi(row[1])) : 0; + e.cost = row[2] ? static_cast(atoi(row[2])) : 0; + e.previous_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.next_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.created_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventAaPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.aa_ability_id = row[1] ? static_cast(atoi(row[1])) : 0; + e.cost = row[2] ? static_cast(atoi(row[2])) : 0; + e.previous_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.next_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.created_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventAaPurchase &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_aa_purchase_repository.h b/common/repositories/player_event_aa_purchase_repository.h new file mode 100644 index 0000000000..d778f9c30f --- /dev/null +++ b/common/repositories/player_event_aa_purchase_repository.h @@ -0,0 +1,50 @@ +#ifndef EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_aa_purchase_repository.h" + +class PlayerEventAaPurchaseRepository: public BasePlayerEventAaPurchaseRepository { +public: + + /** + * This file was auto generated and can be modified and extended upon + * + * Base repository methods are automatically + * generated in the "base" version of this repository. The base repository + * is immutable and to be left untouched, while methods in this class + * are used as extension methods for more specific persistence-layer + * accessors or mutators. + * + * Base Methods (Subject to be expanded upon in time) + * + * Note: Not all tables are designed appropriately to fit functionality with all base methods + * + * InsertOne + * UpdateOne + * DeleteOne + * FindOne + * GetWhere(std::string where_filter) + * DeleteWhere(std::string where_filter) + * InsertMany + * All + * + * Example custom methods in a repository + * + * PlayerEventAaPurchaseRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * PlayerEventAaPurchaseRepository::GetWhereNeverExpires() + * PlayerEventAaPurchaseRepository::GetWhereXAndY() + * PlayerEventAaPurchaseRepository::DeleteWhereXAndY() + * + * Most of the above could be covered by base methods, but if you as a developer + * find yourself re-using logic for other parts of the code, its best to just make a + * method that can be re-used easily elsewhere especially if it can use a base repository + * method and encapsulate filters there + */ + + // Custom extended repository methods here + +}; + +#endif //EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H From 443673c770b2760f6ec2bfcf2c985e0561834c0a Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:16:06 -0400 Subject: [PATCH 20/42] Cleanup before PR --- common/CMakeLists.txt | 2 ++ common/database_schema.h | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 7f982e8ec6..05bc8a3d0c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -277,6 +277,7 @@ SET(repositories repositories/base/base_pets_equipmentset_repository.h repositories/base/base_pets_equipmentset_entries_repository.h repositories/base/base_player_titlesets_repository.h + repositories/base/base_player_event_aa_purchase_repository.h repositories/base/base_player_event_killed_npc_repository.h repositories/base/base_player_event_killed_named_npc_repository.h repositories/base/base_player_event_killed_raid_npc_repository.h @@ -471,6 +472,7 @@ SET(repositories repositories/pets_equipmentset_repository.h repositories/pets_equipmentset_entries_repository.h repositories/player_titlesets_repository.h + repositories/player_event_aa_purchase_repository.h repositories/player_event_killed_npc_repository.h repositories/player_event_killed_named_npc_repository.h repositories/player_event_killed_raid_npc_repository.h diff --git a/common/database_schema.h b/common/database_schema.h index f941cf0b3d..0ea284faad 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -355,13 +355,20 @@ namespace DatabaseSchema { "saylink", "server_scheduled_events", "spawn2_disabled", + "player_event_aa_purchase", + "player_event_killed_npc", + "player_event_killed_named_npc", + "player_event_killed_raid_npc", "player_event_log_settings", "player_event_logs", "player_event_loot_items", - "player_event_merchant_sell", "player_event_merchant_purchase", - "player_event_merchant_npc_handin", - "player_event_merchant_npc_handin_entries", + "player_event_merchant_sell", + "player_event_npc_handin", + "player_event_npc_handin_entries", + "player_event_speech", + "player_event_trade", + "player_event_trade_entries", "shared_task_activity_state", "shared_task_dynamic_zones", "shared_task_members", From cac5feb0658c0fcea65a0f3904f9d4c3803ca3b8 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:51:21 -0400 Subject: [PATCH 21/42] Review comment updates. --- common/events/player_event_logs.cpp | 667 ++++++++++++++-------------- zone/client.cpp | 4 +- 2 files changed, 337 insertions(+), 334 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 280768f00c..06c9166a2e 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -137,384 +137,387 @@ void PlayerEventLogs::ProcessBatchQueue() EtlQueues etl_queues{}; for (auto &r:m_record_batch_queue) { - switch (r.event_type_id && m_settings[r.event_type_id].etl_enabled) { - case PlayerEvent::EventType::LOOT_ITEM: { - PlayerEvent::LootItemEvent in{}; - PlayerEventLootItemsRepository::PlayerEventLootItems out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } + if (m_settings[r.event_type_id].etl_enabled) { + switch (r.event_type_id) { + case PlayerEvent::EventType::LOOT_ITEM: { + PlayerEvent::LootItemEvent in{}; + PlayerEventLootItemsRepository::PlayerEventLootItems out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.charges = in.charges; - out.corpse_name = in.corpse_name; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.npc_id = in.npc_id; - out.created_at = r.created_at; + out.charges = in.charges; + out.corpse_name = in.corpse_name; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.npc_id = in.npc_id; + out.created_at = r.created_at; - if (m_etl_settings.contains(PlayerEvent::EventType::LOOT_ITEM)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id; - m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id++; - } + if (m_etl_settings.contains(PlayerEvent::EventType::LOOT_ITEM)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id; + m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id++; + } - etl_queues.loot_items.push_back(out); - break; - } - case PlayerEvent::EventType::MERCHANT_SELL: { - PlayerEvent::MerchantSellEvent in{}; - PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.loot_items.push_back(out); + break; } + case PlayerEvent::EventType::MERCHANT_SELL: { + PlayerEvent::MerchantSellEvent in{}; + PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.npc_id = in.npc_id; - out.merchant_name = in.merchant_name; - out.merchant_type = in.merchant_type; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.charges = in.charges; - out.cost = in.cost; - out.alternate_currency_id = in.alternate_currency_id; - out.player_money_balance = in.player_money_balance; - out.player_currency_balance = in.player_currency_balance; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_SELL)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id; - m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id++; - } + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_SELL)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id; + m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id++; + } - etl_queues.merchant_sell.push_back(out); - break; - } - case PlayerEvent::EventType::MERCHANT_PURCHASE: { - PlayerEvent::MerchantPurchaseEvent in{}; - PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.merchant_sell.push_back(out); + break; } + case PlayerEvent::EventType::MERCHANT_PURCHASE: { + PlayerEvent::MerchantPurchaseEvent in{}; + PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.npc_id = in.npc_id; - out.merchant_name = in.merchant_name; - out.merchant_type = in.merchant_type; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.charges = in.charges; - out.cost = in.cost; - out.alternate_currency_id = in.alternate_currency_id; - out.player_money_balance = in.player_money_balance; - out.player_currency_balance = in.player_currency_balance; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_PURCHASE)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id; - m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id++; - } + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_PURCHASE)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id; + m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id++; + } - etl_queues.merchant_purchase.push_back(out); - break; - } - case PlayerEvent::EventType::NPC_HANDIN: { - PlayerEvent::HandinEvent in{}; - PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; - PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries out_entries{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.merchant_purchase.push_back(out); + break; } + case PlayerEvent::EventType::NPC_HANDIN: { + PlayerEvent::HandinEvent in{}; + PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; + PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries out_entries{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.handin_copper = in.handin_money.copper; - out.handin_silver = in.handin_money.silver; - out.handin_gold = in.handin_money.gold; - out.handin_platinum = in.handin_money.platinum; - out.return_copper = in.return_money.copper; - out.return_silver = in.return_money.silver; - out.return_gold = in.return_money.gold; - out.return_platinum = in.return_money.platinum; - out.is_quest_handin = in.is_quest_handin; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::NPC_HANDIN)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id; - m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id++; - } - if (!in.handin_items.empty()) { - for (auto const &i: in.handin_items) { - out_entries.charges = i.charges; - out_entries.evolve_amount = 0; - out_entries.evolve_level = 0; - out_entries.item_id = i.item_id; - out_entries.player_event_npc_handin_id = r.etl_table_id; - out_entries.type = 1; - out.created_at = r.created_at; - - if (!i.augment_ids.empty()) { - uint32 augments[6]{}; - for (int x = 0; x < i.augment_ids.size(); x++) { - augments[x] = i.augment_ids[x]; + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.handin_copper = in.handin_money.copper; + out.handin_silver = in.handin_money.silver; + out.handin_gold = in.handin_money.gold; + out.handin_platinum = in.handin_money.platinum; + out.return_copper = in.return_money.copper; + out.return_silver = in.return_money.silver; + out.return_gold = in.return_money.gold; + out.return_platinum = in.return_money.platinum; + out.is_quest_handin = in.is_quest_handin; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::NPC_HANDIN)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id; + m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id++; + } + + if (!in.handin_items.empty()) { + for (auto const &i: in.handin_items) { + out_entries.charges = i.charges; + out_entries.evolve_amount = 0; + out_entries.evolve_level = 0; + out_entries.item_id = i.item_id; + out_entries.player_event_npc_handin_id = r.etl_table_id; + out_entries.type = 1; + out.created_at = r.created_at; + + if (!i.augment_ids.empty()) { + uint32 augments[6]{}; + for (int x = 0; x < i.augment_ids.size(); x++) { + augments[x] = i.augment_ids[x]; + } + out_entries.augment_1_id = augments[0]; + out_entries.augment_2_id = augments[1]; + out_entries.augment_3_id = augments[2]; + out_entries.augment_4_id = augments[3]; + out_entries.augment_5_id = augments[4]; + out_entries.augment_6_id = augments[5]; } - out_entries.augment_1_id = augments[0]; - out_entries.augment_2_id = augments[1]; - out_entries.augment_3_id = augments[2]; - out_entries.augment_4_id = augments[3]; - out_entries.augment_5_id = augments[4]; - out_entries.augment_6_id = augments[5]; + etl_queues.npc_handin_entries.push_back(out_entries); } - etl_queues.npc_handin_entries.push_back(out_entries); } - } - if (!in.return_items.empty()) { - for (auto const &i: in.handin_items) { - out_entries.charges = i.charges; - out_entries.evolve_amount = 0; - out_entries.evolve_level = 0; - out_entries.item_id = i.item_id; - out_entries.player_event_npc_handin_id = r.etl_table_id; - out_entries.type = 2; - out.created_at = r.created_at; - - if (!i.augment_ids.empty()) { - uint32 augments[6]{}; - for (int x = 0; x < i.augment_ids.size(); x++) { - augments[x] = i.augment_ids[x]; + if (!in.return_items.empty()) { + for (auto const &i: in.handin_items) { + out_entries.charges = i.charges; + out_entries.evolve_amount = 0; + out_entries.evolve_level = 0; + out_entries.item_id = i.item_id; + out_entries.player_event_npc_handin_id = r.etl_table_id; + out_entries.type = 2; + out.created_at = r.created_at; + + if (!i.augment_ids.empty()) { + uint32 augments[6]{}; + for (int x = 0; x < i.augment_ids.size(); x++) { + augments[x] = i.augment_ids[x]; + } + out_entries.augment_1_id = augments[0]; + out_entries.augment_2_id = augments[1]; + out_entries.augment_3_id = augments[2]; + out_entries.augment_4_id = augments[3]; + out_entries.augment_5_id = augments[4]; + out_entries.augment_6_id = augments[5]; } - out_entries.augment_1_id = augments[0]; - out_entries.augment_2_id = augments[1]; - out_entries.augment_3_id = augments[2]; - out_entries.augment_4_id = augments[3]; - out_entries.augment_5_id = augments[4]; - out_entries.augment_6_id = augments[5]; + etl_queues.npc_handin_entries.push_back(out_entries); } - etl_queues.npc_handin_entries.push_back(out_entries); } - } - etl_queues.npc_handin.push_back(out); - break; - } - case PlayerEvent::EventType::TRADE: { - PlayerEvent::TradeEvent in{}; - PlayerEventTradeRepository::PlayerEventTrade out{}; - PlayerEventTradeEntriesRepository::PlayerEventTradeEntries out_entries{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.npc_handin.push_back(out); + break; } + case PlayerEvent::EventType::TRADE: { + PlayerEvent::TradeEvent in{}; + PlayerEventTradeRepository::PlayerEventTrade out{}; + PlayerEventTradeEntriesRepository::PlayerEventTradeEntries out_entries{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.char1_id = in.character_1_id; - out.char1_platinum = in.character_1_give_money.platinum; - out.char1_gold = in.character_1_give_money.gold; - out.char1_silver = in.character_1_give_money.silver; - out.char1_copper = in.character_1_give_money.copper; - out.char2_id = in.character_2_id; - out.char2_platinum = in.character_2_give_money.platinum; - out.char2_gold = in.character_2_give_money.gold; - out.char2_silver = in.character_2_give_money.silver; - out.char2_copper = in.character_2_give_money.copper; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::TRADE)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id; - m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id++; - } + out.char1_id = in.character_1_id; + out.char1_platinum = in.character_1_give_money.platinum; + out.char1_gold = in.character_1_give_money.gold; + out.char1_silver = in.character_1_give_money.silver; + out.char1_copper = in.character_1_give_money.copper; + out.char2_id = in.character_2_id; + out.char2_platinum = in.character_2_give_money.platinum; + out.char2_gold = in.character_2_give_money.gold; + out.char2_silver = in.character_2_give_money.silver; + out.char2_copper = in.character_2_give_money.copper; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::TRADE)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id; + m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id++; + } - if (!in.character_1_give_items.empty()) { - for (auto const &i: in.character_1_give_items) { - out_entries.char_id = in.character_1_id; - out_entries.charges = i.charges; - out_entries.slot = i.slot; - out_entries.item_id = i.item_id; - out_entries.player_event_trade_id = r.etl_table_id; - out_entries.in_bag = i.in_bag; - out.created_at = r.created_at; - out_entries.augment_1_id = i.aug_1_item_id; - out_entries.augment_2_id = i.aug_2_item_id; - out_entries.augment_3_id = i.aug_3_item_id; - out_entries.augment_4_id = i.aug_4_item_id; - out_entries.augment_5_id = i.aug_5_item_id; - out_entries.augment_6_id = i.aug_6_item_id; - out_entries.created_at = r.created_at; + if (!in.character_1_give_items.empty()) { + for (auto const &i: in.character_1_give_items) { + out_entries.char_id = in.character_1_id; + out_entries.charges = i.charges; + out_entries.slot = i.slot; + out_entries.item_id = i.item_id; + out_entries.player_event_trade_id = r.etl_table_id; + out_entries.in_bag = i.in_bag; + out.created_at = r.created_at; + out_entries.augment_1_id = i.aug_1_item_id; + out_entries.augment_2_id = i.aug_2_item_id; + out_entries.augment_3_id = i.aug_3_item_id; + out_entries.augment_4_id = i.aug_4_item_id; + out_entries.augment_5_id = i.aug_5_item_id; + out_entries.augment_6_id = i.aug_6_item_id; + out_entries.created_at = r.created_at; + } + etl_queues.trade_entries.push_back(out_entries); } - etl_queues.trade_entries.push_back(out_entries); - } - if (!in.character_2_give_items.empty()) { - for (auto const &i: in.character_2_give_items) { - out_entries.char_id = in.character_2_id; - out_entries.charges = i.charges; - out_entries.slot = i.slot; - out_entries.item_id = i.item_id; - out_entries.player_event_trade_id = r.etl_table_id; - out_entries.in_bag = i.in_bag; - out.created_at = r.created_at; - out_entries.augment_1_id = i.aug_1_item_id; - out_entries.augment_2_id = i.aug_2_item_id; - out_entries.augment_3_id = i.aug_3_item_id; - out_entries.augment_4_id = i.aug_4_item_id; - out_entries.augment_5_id = i.aug_5_item_id; - out_entries.augment_6_id = i.aug_6_item_id; - out_entries.created_at = r.created_at; + if (!in.character_2_give_items.empty()) { + for (auto const &i: in.character_2_give_items) { + out_entries.char_id = in.character_2_id; + out_entries.charges = i.charges; + out_entries.slot = i.slot; + out_entries.item_id = i.item_id; + out_entries.player_event_trade_id = r.etl_table_id; + out_entries.in_bag = i.in_bag; + out.created_at = r.created_at; + out_entries.augment_1_id = i.aug_1_item_id; + out_entries.augment_2_id = i.aug_2_item_id; + out_entries.augment_3_id = i.aug_3_item_id; + out_entries.augment_4_id = i.aug_4_item_id; + out_entries.augment_5_id = i.aug_5_item_id; + out_entries.augment_6_id = i.aug_6_item_id; + out_entries.created_at = r.created_at; + } + etl_queues.trade_entries.push_back(out_entries); } - etl_queues.trade_entries.push_back(out_entries); - } - etl_queues.trade.push_back(out); - break; - } - case PlayerEvent::EventType::SPEECH: { - PlayerEvent::PlayerSpeech in{}; - PlayerEventSpeechRepository::PlayerEventSpeech out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.trade.push_back(out); + break; } + case PlayerEvent::EventType::SPEECH: { + PlayerEvent::PlayerSpeech in{}; + PlayerEventSpeechRepository::PlayerEventSpeech out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.from_char_id = in.from; - out.to_char_id = in.to; - out.type = in.type; - out.min_status = in.min_status; - out.message = in.message; - out.guild_id = in.guild_id; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::SPEECH)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id; - m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id++; - } + out.from_char_id = in.from; + out.to_char_id = in.to; + out.type = in.type; + out.min_status = in.min_status; + out.message = in.message; + out.guild_id = in.guild_id; + out.created_at = r.created_at; + + if (m_etl_settings.contains(PlayerEvent::EventType::SPEECH)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id; + m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id++; + } - etl_queues.speech.push_back(out); - break; - } - case PlayerEvent::EventType::KILLED_NPC: { - PlayerEvent::KilledNPCEvent in{}; - PlayerEventKilledNpcRepository::PlayerEventKilledNpc out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.speech.push_back(out); + break; } + case PlayerEvent::EventType::KILLED_NPC: { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledNpcRepository::PlayerEventKilledNpc out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.combat_time_seconds = in.combat_time_seconds; - out.total_damage_per_second_taken = in.total_damage_per_second_taken; - out.total_heal_per_second_taken = in.total_heal_per_second_taken; - out.created_at = r.created_at; + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; - if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NPC)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id; - m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id++; - } + if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NPC)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id; + m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id++; + } - etl_queues.killed_npc.push_back(out); - break; - } - case PlayerEvent::EventType::KILLED_NAMED_NPC: { - PlayerEvent::KilledNPCEvent in{}; - PlayerEventKilledNamedNpcRepository::PlayerEventKilledNamedNpc out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.killed_npc.push_back(out); + break; } + case PlayerEvent::EventType::KILLED_NAMED_NPC: { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledNamedNpcRepository::PlayerEventKilledNamedNpc out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.combat_time_seconds = in.combat_time_seconds; - out.total_damage_per_second_taken = in.total_damage_per_second_taken; - out.total_heal_per_second_taken = in.total_heal_per_second_taken; - out.created_at = r.created_at; + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; - if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NAMED_NPC)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id; - m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id++; - } + if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NAMED_NPC)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id; + m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id++; + } - etl_queues.killed_named_npc.push_back(out); - break; - } - case PlayerEvent::EventType::KILLED_RAID_NPC: { - PlayerEvent::KilledNPCEvent in{}; - PlayerEventKilledRaidNpcRepository::PlayerEventKilledRaidNpc out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.killed_named_npc.push_back(out); + break; } + case PlayerEvent::EventType::KILLED_RAID_NPC: { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledRaidNpcRepository::PlayerEventKilledRaidNpc out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.combat_time_seconds = in.combat_time_seconds; - out.total_damage_per_second_taken = in.total_damage_per_second_taken; - out.total_heal_per_second_taken = in.total_heal_per_second_taken; - out.created_at = r.created_at; + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; - if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_RAID_NPC)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id; - m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id++; - } + if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_RAID_NPC)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id; + m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id++; + } - etl_queues.killed_raid_npc.push_back(out); - break; - } - case PlayerEvent::EventType::AA_PURCHASE: { - PlayerEvent::AAPurchasedEvent in{}; - PlayerEventAaPurchaseRepository::PlayerEventAaPurchase out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); + etl_queues.killed_raid_npc.push_back(out); + break; } + case PlayerEvent::EventType::AA_PURCHASE: { + PlayerEvent::AAPurchasedEvent in{}; + PlayerEventAaPurchaseRepository::PlayerEventAaPurchase out{}; + + { + std::stringstream ss; + ss << r.event_data; + cereal::JSONInputArchive ar(ss); + in.serialize(ar); + } - out.aa_ability_id = in.aa_id; - out.cost = in.aa_cost; - out.previous_id = in.aa_previous_id; - out.next_id = in.aa_next_id; - out.created_at = r.created_at; + out.aa_ability_id = in.aa_id; + out.cost = in.aa_cost; + out.previous_id = in.aa_previous_id; + out.next_id = in.aa_next_id; + out.created_at = r.created_at; - if (m_etl_settings.contains(PlayerEvent::EventType::AA_PURCHASE)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id; - m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id++; - } + if (m_etl_settings.contains(PlayerEvent::EventType::AA_PURCHASE)) { + r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id; + m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id++; + } - etl_queues.aa_purchase.push_back(out); - break; - } - default: { - LogError("Non-Implemented ETL routing [{}]", r.event_type_id); + etl_queues.aa_purchase.push_back(out); + break; + } + default: { + LogError("Non-Implemented ETL routing [{}]", r.event_type_id); + } } } } diff --git a/zone/client.cpp b/zone/client.cpp index 1392192e70..495ce4ad94 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -936,7 +936,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s e.min_status = Admin(); e.type = chan_num; e.to = targetname; - e.from = GetName(); + e.from = GetCleanName(); if (chan_num == ChatChannel_Guild) { e.guild_id = GuildID(); } @@ -12302,7 +12302,7 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) RecordPlayerEventLogWithClient(trader, PlayerEvent::TRADE, e); //Not sure the usefulness of sending the same data twice?? - //RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e); + RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e); } void Client::NPCHandinEventLog(Trade* t, NPC* n) From 728f0592de60c81ea4581a9e290463a26fb44c73 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sat, 16 Nov 2024 23:04:09 -0400 Subject: [PATCH 22/42] Add world cli etl:settings to output a json on all player event details. --- common/events/player_event_logs.cpp | 30 ++++++++++++++------- common/events/player_event_logs.h | 3 +++ world/cli/etl_get_settings.cpp | 41 +++++++++++++++++++++++++++++ world/world_server_cli.cpp | 2 ++ world/world_server_cli.h | 1 + 5 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 world/cli/etl_get_settings.cpp diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 06c9166a2e..7717b99859 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1277,12 +1277,22 @@ void PlayerEventLogs::SetSettingsDefaults() void PlayerEventLogs::LoadEtlIds() { + auto e = [&](auto p) -> bool { + for (PlayerEventLogSettingsRepository::PlayerEventLogSettings const& c : m_settings) { + if(c.id == p) { + return c.etl_enabled ? true : false; + } + } + + return false; + }; + m_etl_settings.clear(); m_etl_settings = { { PlayerEvent::LOOT_ITEM, { - .enabled = true, + .enabled = e(PlayerEvent::LOOT_ITEM), .table_name = "player_event_loot_items", .next_id = PlayerEventLootItemsRepository::GetMaxId(*m_database) + 1 } @@ -1290,7 +1300,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::MERCHANT_SELL, { - .enabled = true, + .enabled = e(PlayerEvent::MERCHANT_SELL), .table_name = "player_event_merchant_sell", .next_id = BasePlayerEventMerchantSellRepository::GetMaxId(*m_database) + 1 } @@ -1298,7 +1308,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::MERCHANT_PURCHASE, { - .enabled = true, + .enabled = e(PlayerEvent::MERCHANT_PURCHASE), .table_name = "player_event_merchant_purchase", .next_id = PlayerEventMerchantPurchaseRepository::GetMaxId(*m_database) + 1 } @@ -1306,7 +1316,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::NPC_HANDIN, { - .enabled = true, + .enabled = e(PlayerEvent::NPC_HANDIN), .table_name = "player_event_npc_handin", .next_id = PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1 } @@ -1314,7 +1324,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::TRADE, { - .enabled = true, + .enabled = e(PlayerEvent::TRADE), .table_name = "player_event_trade", .next_id = PlayerEventTradeRepository::GetMaxId(*m_database) + 1 } @@ -1322,7 +1332,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::SPEECH, { - .enabled = true, + .enabled = e(PlayerEvent::SPEECH), .table_name = "player_event_speech", .next_id = PlayerEventSpeechRepository::GetMaxId(*m_database) + 1 } @@ -1330,7 +1340,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::KILLED_NPC, { - .enabled = true, + .enabled = e(PlayerEvent::KILLED_NPC), .table_name = "player_event_killed_npc", .next_id = PlayerEventKilledNpcRepository::GetMaxId(*m_database) + 1 } @@ -1338,7 +1348,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::KILLED_NAMED_NPC, { - .enabled = true, + .enabled = e(PlayerEvent::KILLED_NAMED_NPC), .table_name = "player_event_killed_named_npc", .next_id = PlayerEventKilledNamedNpcRepository::GetMaxId(*m_database) + 1 } @@ -1346,7 +1356,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::KILLED_RAID_NPC, { - .enabled = true, + .enabled = e(PlayerEvent::KILLED_RAID_NPC), .table_name = "player_event_killed_raid_npc", .next_id = PlayerEventKilledRaidNpcRepository::GetMaxId(*m_database) + 1 } @@ -1354,7 +1364,7 @@ void PlayerEventLogs::LoadEtlIds() { PlayerEvent::AA_PURCHASE, { - .enabled = true, + .enabled = e(PlayerEvent::AA_PURCHASE), .table_name = "player_event_aa_purchase", .next_id = PlayerEventAaPurchaseRepository::GetMaxId(*m_database) + 1 } diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 79e1c75050..f3de7b3def 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -118,6 +118,9 @@ class PlayerEventLogs { void ProcessBatchQueue(); void ProcessRetentionTruncation(); void SetSettingsDefaults(); + +public: + std::map &GetEtlSettings() { return m_etl_settings;} }; extern PlayerEventLogs player_event_logs; diff --git a/world/cli/etl_get_settings.cpp b/world/cli/etl_get_settings.cpp new file mode 100644 index 0000000000..cd8ad82b22 --- /dev/null +++ b/world/cli/etl_get_settings.cpp @@ -0,0 +1,41 @@ +#include "../../common/events/player_event_logs.h" +#include "../../common/json/json.h" + +void WorldserverCLI::EtlGetSettings(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Displays server player event logs that are etl enabled"; + + if (cmd[{ "-h", "--help" }]) { + return; + } + + Json::Value etl_settings; + Json::Value player_events; + + player_event_logs.SetDatabase(&database)->Init(); + auto event_settings = player_event_logs.GetSettings(); + auto etl_details = player_event_logs.GetEtlSettings(); + + for (auto i = 0; i < PlayerEvent::EventType::MAX; i++) { + player_events["event_id"] = event_settings[i].id; + player_events["enabled"] = event_settings[i].event_enabled ? true : false; + player_events["retention"] = event_settings[i].retention_days; + player_events["discord_id"] = event_settings[i].discord_webhook_id; + player_events["etl_enabled"] = event_settings[i].etl_enabled ? true : false; + player_events["table_name"] = ""; + + auto it = etl_details.find(static_cast(event_settings[i].id)); + + if (it != std::end(etl_details)) { + player_events["table_name"] = it->second.table_name; + player_events["etl_enabled"] = it->second.enabled; + } + + etl_settings["etl_settings"].append(player_events); + } + + std::stringstream payload; + payload << etl_settings; + + std::cout << payload.str() << std::endl; +} diff --git a/world/world_server_cli.cpp b/world/world_server_cli.cpp index 973374c018..3af88f9535 100644 --- a/world/world_server_cli.cpp +++ b/world/world_server_cli.cpp @@ -34,6 +34,7 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) function_map["test:repository2"] = &WorldserverCLI::TestRepository2; function_map["test:db-concurrency"] = &WorldserverCLI::TestDatabaseConcurrency; function_map["test:string-benchmark"] = &WorldserverCLI::TestStringBenchmarkCommand; + function_map["etl:settings"] = &WorldserverCLI::EtlGetSettings; EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } @@ -56,3 +57,4 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) #include "cli/test_repository_2.cpp" #include "cli/test_string_benchmark.cpp" #include "cli/version.cpp" +#include "cli/etl_get_settings.cpp" diff --git a/world/world_server_cli.h b/world/world_server_cli.h index 0edebd2614..1066158b9c 100644 --- a/world/world_server_cli.h +++ b/world/world_server_cli.h @@ -25,6 +25,7 @@ class WorldserverCLI { static void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description); static void TestDatabaseConcurrency(int argc, char **argv, argh::parser &cmd, std::string &description); static void TestStringBenchmarkCommand(int argc, char **argv, argh::parser &cmd, std::string &description); + static void EtlGetSettings(int argc, char **argv, argh::parser &cmd, std::string &description); }; From 5e6e5e252153f5b153ef3def9a038edd80cd84a5 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 17 Nov 2024 19:04:05 -0400 Subject: [PATCH 23/42] Add reserve for all etl_queues Correct a failed test case for improper next id for etl tables when table is first created. --- common/events/player_event_logs.cpp | 40 ++++++++++++++----- common/events/player_event_logs.h | 1 - .../player_event_aa_purchase_repository.h | 10 +++++ ...player_event_killed_named_npc_repository.h | 10 +++++ .../player_event_killed_npc_repository.h | 10 +++++ .../player_event_killed_raid_npc_repository.h | 10 +++++ .../player_event_loot_items_repository.h | 11 +++++ ...layer_event_merchant_purchase_repository.h | 11 +++++ .../player_event_merchant_sell_repository.h | 11 +++++ ...ayer_event_npc_handin_entries_repository.h | 10 +++++ .../player_event_npc_handin_repository.h | 10 +++++ .../player_event_speech_repository.h | 10 +++++ .../player_event_trade_entries_repository.h | 10 +++++ .../player_event_trade_repository.h | 10 +++++ 14 files changed, 153 insertions(+), 11 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 7717b99859..c2bf519c63 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -132,9 +132,25 @@ void PlayerEventLogs::ProcessBatchQueue() return; } + std::map counter{}; + for (auto const& e: m_record_batch_queue) { + counter[e.event_type_id]++; + } + + BenchTimer benchmark; EtlQueues etl_queues{}; + etl_queues.trade.reserve(counter[PlayerEvent::TRADE] ? counter[PlayerEvent::TRADE] : 0); + etl_queues.speech.reserve(counter[PlayerEvent::SPEECH] ? counter[PlayerEvent::SPEECH] : 0); + etl_queues.loot_items.reserve(counter[PlayerEvent::LOOT_ITEM] ? counter[PlayerEvent::LOOT_ITEM] : 0); + etl_queues.killed_npc.reserve(counter[PlayerEvent::KILLED_NPC] ? counter[PlayerEvent::KILLED_NPC] : 0); + etl_queues.npc_handin.reserve(counter[PlayerEvent::NPC_HANDIN] ? counter[PlayerEvent::NPC_HANDIN] : 0); + etl_queues.aa_purchase.reserve(counter[PlayerEvent::AA_PURCHASE] ? counter[PlayerEvent::AA_PURCHASE] : 0); + etl_queues.merchant_sell.reserve(counter[PlayerEvent::MERCHANT_SELL] ? counter[PlayerEvent::MERCHANT_SELL] : 0); + etl_queues.killed_raid_npc.reserve(counter[PlayerEvent::KILLED_RAID_NPC] ? counter[PlayerEvent::KILLED_RAID_NPC] : 0); + etl_queues.killed_named_npc.reserve(counter[PlayerEvent::KILLED_NAMED_NPC] ? counter[PlayerEvent::KILLED_NAMED_NPC] : 0); + etl_queues.merchant_purchase.reserve(counter[PlayerEvent::MERCHANT_PURCHASE] ? counter[PlayerEvent::MERCHANT_PURCHASE] : 0); for (auto &r:m_record_batch_queue) { if (m_settings[r.event_type_id].etl_enabled) { @@ -259,6 +275,7 @@ void PlayerEventLogs::ProcessBatchQueue() } if (!in.handin_items.empty()) { + etl_queues.npc_handin_entries.reserve(etl_queues.npc_handin_entries.size() + in.handin_items.size()); for (auto const &i: in.handin_items) { out_entries.charges = i.charges; out_entries.evolve_amount = 0; @@ -285,6 +302,7 @@ void PlayerEventLogs::ProcessBatchQueue() } if (!in.return_items.empty()) { + etl_queues.npc_handin_entries.reserve(etl_queues.npc_handin_entries.size() + in.return_items.size()); for (auto const &i: in.handin_items) { out_entries.charges = i.charges; out_entries.evolve_amount = 0; @@ -343,6 +361,7 @@ void PlayerEventLogs::ProcessBatchQueue() } if (!in.character_1_give_items.empty()) { + etl_queues.trade_entries.reserve(etl_queues.trade_entries.size() + in.character_1_give_items.size()); for (auto const &i: in.character_1_give_items) { out_entries.char_id = in.character_1_id; out_entries.charges = i.charges; @@ -363,6 +382,7 @@ void PlayerEventLogs::ProcessBatchQueue() } if (!in.character_2_give_items.empty()) { + etl_queues.trade_entries.reserve(etl_queues.trade_entries.size() + in.character_2_give_items.size()); for (auto const &i: in.character_2_give_items) { out_entries.char_id = in.character_2_id; out_entries.charges = i.charges; @@ -1294,7 +1314,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::LOOT_ITEM), .table_name = "player_event_loot_items", - .next_id = PlayerEventLootItemsRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventLootItemsRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1302,7 +1322,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::MERCHANT_SELL), .table_name = "player_event_merchant_sell", - .next_id = BasePlayerEventMerchantSellRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventMerchantSellRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1310,7 +1330,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::MERCHANT_PURCHASE), .table_name = "player_event_merchant_purchase", - .next_id = PlayerEventMerchantPurchaseRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventMerchantPurchaseRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1318,7 +1338,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::NPC_HANDIN), .table_name = "player_event_npc_handin", - .next_id = PlayerEventNpcHandinRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventNpcHandinRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1326,7 +1346,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::TRADE), .table_name = "player_event_trade", - .next_id = PlayerEventTradeRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventTradeRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1334,7 +1354,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::SPEECH), .table_name = "player_event_speech", - .next_id = PlayerEventSpeechRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventSpeechRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1342,7 +1362,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::KILLED_NPC), .table_name = "player_event_killed_npc", - .next_id = PlayerEventKilledNpcRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventKilledNpcRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1350,7 +1370,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::KILLED_NAMED_NPC), .table_name = "player_event_killed_named_npc", - .next_id = PlayerEventKilledNamedNpcRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventKilledNamedNpcRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1358,7 +1378,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::KILLED_RAID_NPC), .table_name = "player_event_killed_raid_npc", - .next_id = PlayerEventKilledRaidNpcRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventKilledRaidNpcRepository::GetNextAutoIncrementId(*m_database) } }, { @@ -1366,7 +1386,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::AA_PURCHASE), .table_name = "player_event_aa_purchase", - .next_id = PlayerEventAaPurchaseRepository::GetMaxId(*m_database) + 1 + .next_id = PlayerEventAaPurchaseRepository::GetNextAutoIncrementId(*m_database) } } }; diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index f3de7b3def..3f8c30b1dc 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -1,7 +1,6 @@ #ifndef EQEMU_PLAYER_EVENT_LOGS_H #define EQEMU_PLAYER_EVENT_LOGS_H -#include #include #include #include "../json/json_archive_single_line.h" diff --git a/common/repositories/player_event_aa_purchase_repository.h b/common/repositories/player_event_aa_purchase_repository.h index d778f9c30f..5fbc40f7ce 100644 --- a/common/repositories/player_event_aa_purchase_repository.h +++ b/common/repositories/player_event_aa_purchase_repository.h @@ -44,7 +44,17 @@ class PlayerEventAaPurchaseRepository: public BasePlayerEventAaPurchaseRepositor */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_killed_named_npc_repository.h b/common/repositories/player_event_killed_named_npc_repository.h index e5dc32f541..93859717f9 100644 --- a/common/repositories/player_event_killed_named_npc_repository.h +++ b/common/repositories/player_event_killed_named_npc_repository.h @@ -44,7 +44,17 @@ class PlayerEventKilledNamedNpcRepository: public BasePlayerEventKilledNamedNpcR */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_npc_repository.h b/common/repositories/player_event_killed_npc_repository.h index 94f09ebf7d..b2501a591c 100644 --- a/common/repositories/player_event_killed_npc_repository.h +++ b/common/repositories/player_event_killed_npc_repository.h @@ -44,7 +44,17 @@ class PlayerEventKilledNpcRepository: public BasePlayerEventKilledNpcRepository */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_raid_npc_repository.h b/common/repositories/player_event_killed_raid_npc_repository.h index 57600aff5c..2416dd7cca 100644 --- a/common/repositories/player_event_killed_raid_npc_repository.h +++ b/common/repositories/player_event_killed_raid_npc_repository.h @@ -44,7 +44,17 @@ class PlayerEventKilledRaidNpcRepository: public BasePlayerEventKilledRaidNpcRep */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index 6b68dd2c50..03a2f553fb 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -42,6 +42,17 @@ class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository * method that can be re-used easily elsewhere especially if it can use a base repository * method and encapsulate filters there */ + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_purchase_repository.h b/common/repositories/player_event_merchant_purchase_repository.h index ceea389ad2..214b476a1d 100644 --- a/common/repositories/player_event_merchant_purchase_repository.h +++ b/common/repositories/player_event_merchant_purchase_repository.h @@ -44,6 +44,17 @@ class PlayerEventMerchantPurchaseRepository: public BasePlayerEventMerchantPurch */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h index 66621542de..73e38a4ee8 100644 --- a/common/repositories/player_event_merchant_sell_repository.h +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -44,6 +44,17 @@ class PlayerEventMerchantSellRepository: public BasePlayerEventMerchantSellRepos */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_entries_repository.h b/common/repositories/player_event_npc_handin_entries_repository.h index e1c95bb3fb..3e9cf8592b 100644 --- a/common/repositories/player_event_npc_handin_entries_repository.h +++ b/common/repositories/player_event_npc_handin_entries_repository.h @@ -44,7 +44,17 @@ class PlayerEventNpcHandinEntriesRepository: public BasePlayerEventNpcHandinEntr */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_repository.h b/common/repositories/player_event_npc_handin_repository.h index d01a24c745..03cf198415 100644 --- a/common/repositories/player_event_npc_handin_repository.h +++ b/common/repositories/player_event_npc_handin_repository.h @@ -44,7 +44,17 @@ class PlayerEventNpcHandinRepository: public BasePlayerEventNpcHandinRepository */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H diff --git a/common/repositories/player_event_speech_repository.h b/common/repositories/player_event_speech_repository.h index 7702c24679..ac4690d7f5 100644 --- a/common/repositories/player_event_speech_repository.h +++ b/common/repositories/player_event_speech_repository.h @@ -44,7 +44,17 @@ class PlayerEventSpeechRepository: public BasePlayerEventSpeechRepository { */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/player_event_trade_entries_repository.h b/common/repositories/player_event_trade_entries_repository.h index b257488c07..9b88770b82 100644 --- a/common/repositories/player_event_trade_entries_repository.h +++ b/common/repositories/player_event_trade_entries_repository.h @@ -44,7 +44,17 @@ class PlayerEventTradeEntriesRepository: public BasePlayerEventTradeEntriesRepos */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_trade_repository.h b/common/repositories/player_event_trade_repository.h index 194d197021..9b78ca7fe8 100644 --- a/common/repositories/player_event_trade_repository.h +++ b/common/repositories/player_event_trade_repository.h @@ -44,7 +44,17 @@ class PlayerEventTradeRepository: public BasePlayerEventTradeRepository { */ // Custom extended repository methods here + static int64 GetNextAutoIncrementId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", + TableName() + ) + ); + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } }; #endif //EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H From 68fac3e3f1b17c24b590d54e03dd60eb81b31ff8 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 17 Nov 2024 19:39:41 -0400 Subject: [PATCH 24/42] Potential solution for a dedicated database connection for player events. --- common/events/player_event_logs.cpp | 26 ++++++++++++++++++++++++++ common/events/player_event_logs.h | 4 ++++ world/main.cpp | 4 +++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index c2bf519c63..40188b2993 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1391,3 +1391,29 @@ void PlayerEventLogs::LoadEtlIds() } }; } + +bool PlayerEventLogs::LoadDatabaseConnection() +{ + const auto c = EQEmuConfig::get(); + + LogInfo( + "Connecting to MySQL for PlayerEvents [{}]@[{}]:[{}]", + c->DatabaseUsername.c_str(), + c->DatabaseHost.c_str(), + c->DatabasePort + ); + + if (!player_event_database.Connect( + c->DatabaseHost.c_str(), + c->DatabaseUsername.c_str(), + c->DatabasePassword.c_str(), + c->DatabaseDB.c_str(), + c->DatabasePort + )) { + LogError("Cannot continue without a database connection for player events."); + return false; + } + + SetDatabase(&player_event_database); + return true; +} \ No newline at end of file diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 3f8c30b1dc..20220a8bed 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -6,6 +6,7 @@ #include "../json/json_archive_single_line.h" #include "../servertalk.h" #include "../timer.h" +#include "../eqemu_config.h" #include "../repositories/player_event_log_settings_repository.h" #include "../repositories/player_event_logs_repository.h" @@ -26,7 +27,10 @@ class PlayerEventLogs { public: + Database player_event_database{}; + void Init(); + bool LoadDatabaseConnection(); void ReloadSettings(); void LoadEtlIds(); PlayerEventLogs *SetDatabase(Database *db); diff --git a/world/main.cpp b/world/main.cpp index aff459fb9a..b77b6ea3a3 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -374,7 +374,9 @@ int main(int argc, char **argv) ); Timer player_event_process_timer(1000); - player_event_logs.SetDatabase(&database)->Init(); + if (player_event_logs.LoadDatabaseConnection()) { + player_event_logs.Init(); + } auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); From dffff73348fc978eff56284fd6fa6fbf2d958460 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 17 Nov 2024 20:18:34 -0400 Subject: [PATCH 25/42] Simple thread for player_events. Likely there is a better way to do this. --- world/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/main.cpp b/world/main.cpp index b77b6ea3a3..164c2ae645 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -441,7 +441,7 @@ int main(int argc, char **argv) } if (player_event_process_timer.Check()) { - player_event_logs.Process(); + std::jthread event_thread(&PlayerEventLogs::Process, &player_event_logs); } if (PurgeInstanceTimer.Check()) { From 8cdb9a1f584c0a5b0f4c214a9858238f9e18a549 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sat, 23 Nov 2024 20:50:58 -0400 Subject: [PATCH 26/42] Add zone to qs communications for recordplayerevents First pass of enabling zone to qs direct transport to allow for PlayerEvents to bypass world. --- common/eqemu_config.cpp | 2 + common/eqemu_config.h | 4 +- common/events/player_events.h | 55 ++++++++++++------ queryserv/CMakeLists.txt | 4 ++ queryserv/queryserv.cpp | 79 +++++++++++++++++++++++--- queryserv/worldserver.cpp | 4 +- queryserv/zonelist.cpp | 36 ++++++++++++ queryserv/zonelist.h | 25 ++++++++ queryserv/zoneserver.cpp | 66 +++++++++++++++++++++ queryserv/zoneserver.h | 104 ++++++++++++++++++++++++++++++++++ zone/cheat_manager.cpp | 2 + zone/corpse.cpp | 4 +- zone/forage.cpp | 2 + zone/gm_commands/guild.cpp | 25 +++++++- zone/groups.cpp | 4 +- zone/inventory.cpp | 2 + zone/main.cpp | 3 + zone/object.cpp | 6 +- zone/parcels.cpp | 1 + zone/queryserv.cpp | 35 +++++++++++- zone/queryserv.h | 41 ++++++++++++-- zone/raids.cpp | 4 +- zone/spells.cpp | 8 ++- zone/worldserver.cpp | 20 ++++--- 24 files changed, 484 insertions(+), 52 deletions(-) create mode 100644 queryserv/zonelist.cpp create mode 100644 queryserv/zonelist.h create mode 100644 queryserv/zoneserver.cpp create mode 100644 queryserv/zoneserver.h diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 40374de8bf..fe06c9265d 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -147,6 +147,8 @@ void EQEmuConfig::parse_config() QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString(); QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString(); QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString(); + QSHost = _root["server"]["queryserver"].get("host", "localhost").asString(); + QSPort = Strings::ToUnsignedInt(_root["server"]["queryserver"].get("port", "9500").asString()); /** * Zones diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 0ce295ece7..e3924c2609 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -81,7 +81,9 @@ class EQEmuConfig std::string QSDatabaseUsername; std::string QSDatabasePassword; std::string QSDatabaseDB; - uint16 QSDatabasePort; + uint16 QSDatabasePort; + std::string QSHost; + int QSPort; // From std::string SpellsFile; diff --git a/common/events/player_events.h b/common/events/player_events.h index a393415ad7..ed9f5fd3b9 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -4,6 +4,7 @@ #include #include #include "../types.h" +#include "../rulesys.h" #include "../repositories/player_event_logs_repository.h" namespace PlayerEvent { @@ -1143,24 +1144,46 @@ namespace PlayerEvent { #define RecordPlayerEventLog(event_type, event_data) do {\ if (player_event_logs.IsEventEnabled(event_type)) {\ - worldserver.SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ - }\ + if (RuleB(Logging, PlayerEventsQSProcess)) {\ + QServ->SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + } \ + else { \ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ + }\ } while (0) #define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\ if (player_event_logs.IsEventEnabled(event_type)) {\ - worldserver.SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - (c)->GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ - }\ + if (RuleB(Logging, PlayerEventsQSProcess)) {\ + QServ->SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ + else {\ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ + }\ } while (0) diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index bd6e37ecd5..82613065a3 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -6,6 +6,8 @@ SET(qserv_sources queryserv.cpp queryservconfig.cpp worldserver.cpp + zonelist.cpp + zoneserver.cpp ) SET(qserv_headers @@ -13,6 +15,8 @@ SET(qserv_headers lfguild.h queryservconfig.h worldserver.h + zonelist.h + zoneserver.h ) ADD_EXECUTABLE(queryserv ${qserv_sources} ${qserv_headers}) diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index a504b8e77a..991c7816ef 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -21,7 +21,6 @@ #include "../common/eqemu_logsys.h" #include "../common/opcodemgr.h" #include "../common/rulesys.h" -#include "../common/servertalk.h" #include "../common/platform.h" #include "../common/crash.h" #include "../common/strings.h" @@ -37,18 +36,24 @@ #include #include #include +#include "../common/net/servertalk_server.h" +#include "../common/net/console_server.h" +#include "../queryserv/zonelist.h" +#include "../queryserv/zoneserver.h" volatile bool RunLoops = true; -QSDatabase database; -LFGuildManager lfguildmanager; -std::string WorldShortName; +QSDatabase database; +LFGuildManager lfguildmanager; +std::string WorldShortName; const queryservconfig *Config; WorldServer *worldserver = 0; -EQEmuLogSys LogSys; -PathManager path; -ZoneStore zone_store; -PlayerEventLogs player_event_logs; +EQEmuLogSys LogSys; +PathManager path; +ZoneStore zone_store; +PlayerEventLogs player_event_logs; +ZSList zoneserver_list; +uint32 numzones = 0; void CatchSignal(int sig_num) { @@ -101,6 +106,61 @@ int main() return 1; } + //rules: + { + std::string tmp; + if (database.GetVariable("RuleSet", tmp)) { + LogInfo("Loading rule set [{}]", tmp.c_str()); + if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) { + LogError("Failed to load ruleset [{}], falling back to defaults", tmp.c_str()); + } + } + else { + if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { + LogInfo("No rule set configured, using default rules"); + } + } + + EQ::InitializeDynamicLookups(); + } + + std::unique_ptr console; + EQ::Net::ServertalkServerOptions server_opts; + auto server_connection = std::make_unique(); + server_opts.port = Config->QSPort; + server_opts.ipv6 = false; + server_opts.credentials = Config->SharedKey; + server_connection->Listen(server_opts); + LogInfo("Server (TCP) listener started on port [{}]", Config->QSPort); + + server_connection->OnConnectionIdentified( + "Zone", [&console](std::shared_ptr connection) { + numzones++; + zoneserver_list.Add(new ZoneServer(connection, console.get())); + + LogInfo( + "New Zone Server connection from [{}] at [{}:{}] zone_count [{}]", + connection->Handle()->RemoteIP(), + connection->Handle()->RemotePort(), + connection->GetUUID(), + numzones + ); + } + ); + + server_connection->OnConnectionRemoved( + "Zone", [](std::shared_ptr connection) { + numzones--; + zoneserver_list.Remove(connection->GetUUID()); + + LogInfo( + "Removed Zone Server connection from [{}] total zone_count [{}]", + connection->GetUUID(), + numzones + ); + } + ); + /* Initial Connection to Worldserver */ worldserver = new WorldServer; worldserver->Connect(); @@ -124,7 +184,7 @@ int main() } if (player_event_process_timer.Check()) { - player_event_logs.Process(); + std::jthread player_event_thread(&PlayerEventLogs::Process, &player_event_logs); } }; @@ -133,6 +193,7 @@ int main() EQ::EventLoop::Get().Run(); + safe_delete(worldserver); LogSys.CloseFileLogs(); } diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index f46baf983a..db1d66ce05 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -41,7 +41,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA extern WorldServer worldserver; extern const queryservconfig *Config; -extern QSDatabase database; +extern QSDatabase database; extern LFGuildManager lfguildmanager; WorldServer::WorldServer() @@ -103,6 +103,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) break; } case ServerOP_KeepAlive: { + ServerPacket pack(ServerOP_KeepAlive, 0); + SendPacket(&pack); break; } case ServerOP_Speech: { diff --git a/queryserv/zonelist.cpp b/queryserv/zonelist.cpp new file mode 100644 index 0000000000..6a5a1c9a59 --- /dev/null +++ b/queryserv/zonelist.cpp @@ -0,0 +1,36 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "zonelist.h" +#include "zoneserver.h" +#include "../common/strings.h" + +void ZSList::Add(ZoneServer* zoneserver) { + zone_server_list.emplace_back(std::unique_ptr(zoneserver)); +} + +void ZSList::Remove(const std::string &uuid) +{ + auto iter = zone_server_list.begin(); + while (iter != zone_server_list.end()) { + if ((*iter)->GetUUID().compare(uuid) == 0) { + zone_server_list.erase(iter); + return; + } + iter++; + } +} diff --git a/queryserv/zonelist.h b/queryserv/zonelist.h new file mode 100644 index 0000000000..28b183babc --- /dev/null +++ b/queryserv/zonelist.h @@ -0,0 +1,25 @@ +#ifndef ZONELIST_H_ +#define ZONELIST_H_ +// +#include "../common/types.h" +#include +//../common/eqtime.h" +// #include "../common/timer.h" +// #include "../common/event/timer.h" +#include +#include +#include + +class WorldTCPConnection; +class ZoneServer; + +class ZSList { +public: + void Add(ZoneServer *zoneserver); + void Remove(const std::string &uuid); + +private: + std::list> zone_server_list; +}; + +#endif /*ZONELIST_H_*/ \ No newline at end of file diff --git a/queryserv/zoneserver.cpp b/queryserv/zoneserver.cpp new file mode 100644 index 0000000000..7c00520267 --- /dev/null +++ b/queryserv/zoneserver.cpp @@ -0,0 +1,66 @@ + +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "zoneserver.h" +#include "../common/global_define.h" +#include "../common/eqemu_logsys.h" +#include "../common/repositories/player_event_logs_repository.h" +#include "../common/events/player_event_logs.h" + +ZoneServer::ZoneServer(std::shared_ptr in_connection, EQ::Net::ConsoleServer *in_console) + : tcpc(in_connection) { + + tcpc->OnMessage(std::bind(&ZoneServer::HandleMessage, this, std::placeholders::_1, std::placeholders::_2)); + console = in_console; +} + +ZoneServer::~ZoneServer() +{ +} + +void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) +{ + ServerPacket tpack(opcode, p); + auto pack = &tpack; + + switch (opcode) { + case ServerOP_KeepAlive: { + SendPacket(pack); + break; + } + case ServerOP_PlayerEvent: { + auto n = PlayerEvent::PlayerEventContainer{}; + auto s = reinterpret_cast(pack->pBuffer); + EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size); + cereal::BinaryInputArchive archive(ss); + archive(n); + + player_event_logs.AddToQueue(n.player_event_log); + + // if discord enabled for event, ship to UCS to process + // if (player_event_logs.IsEventDiscordEnabled(n.player_event_log.event_type_id)) { + // UCSLink.SendPacket(pack); + // } + break; + } + default: { + LogInfo("Unknown ServerOP Received [{}]", opcode); + break; + } + } +} diff --git a/queryserv/zoneserver.h b/queryserv/zoneserver.h new file mode 100644 index 0000000000..80f00c6c91 --- /dev/null +++ b/queryserv/zoneserver.h @@ -0,0 +1,104 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef ZONESERVER_H +#define ZONESERVER_H + +#include "../world/world_tcp_connection.h" +#include "../common/net/servertalk_server.h" +#include "../common/event/timer.h" +#include "../common/timer.h" +#include "../common/emu_constants.h" +#include "../world/console.h" +#include +#include + +class Client; +class ServerPacket; + +class ZoneServer : public WorldTCPConnection { +public: + ZoneServer(std::shared_ptr in_connection, EQ::Net::ConsoleServer *in_console); + ~ZoneServer(); + // virtual inline bool IsZoneServer() { return true; } + // + void SendPacket(ServerPacket* pack) { tcpc->SendPacket(pack); } + // void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...); + // void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message); + void SendKeepAlive(); + // bool SetZone(uint32 in_zone_id, uint32 in_instance_id = 0, bool in_is_static_zone = false); + // void TriggerBootup(uint32 in_zone_id = 0, uint32 in_instance_id = 0, const char* admin_name = 0, bool is_static_zone = false); + // void Disconnect() { auto handle = tcpc->Handle(); if (handle) { handle->Disconnect(); } } + // void IncomingClient(Client* client); + // void LSBootUpdate(uint32 zone_id, uint32 instance_id = 0, bool startup = false); + // void LSSleepUpdate(uint32 zone_id); + // uint32 GetPrevZoneID() { return zone_server_previous_zone_id; } + // void ChangeWID(uint32 iCharID, uint32 iWID); + // void SendGroupIDs(); + void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); + + // inline const char* GetZoneName() const { return zone_name; } + // inline const char* GetZoneLongName() const { return long_name; } + // const char* GetCompileTime() const{ return compiled; } + // void SetCompile(char* in_compile){ strcpy(compiled,in_compile); } + // inline uint32 GetZoneID() const { return zone_server_zone_id; } + // inline bool IsConnected() const { return tcpc->Handle() ? tcpc->Handle()->IsConnected() : false; } + // inline std::string GetIP() const { return tcpc->Handle() ? tcpc->Handle()->RemoteIP() : ""; } + // inline uint16 GetPort() const { return tcpc->Handle() ? tcpc->Handle()->RemotePort() : 0; } + // inline const char* GetCAddress() const { return client_address; } + // inline const char* GetCLocalAddress() const { return client_local_address; } + // inline uint16 GetCPort() const { return client_port; } + // inline uint32 GetID() const { return zone_server_id; } + // inline bool IsBootingUp() const { return is_booting_up; } + // inline bool IsStaticZone() const{ return is_static_zone; } + // inline uint32 NumPlayers() const { return zone_player_count; } + // inline void AddPlayer() { zone_player_count++; } + // inline void RemovePlayer() { zone_player_count--; } + // inline const char * GetLaunchName() const { return(launcher_name.c_str()); } + // inline const char * GetLaunchedName() const { return(launched_name.c_str()); } + std::string GetUUID() const { return tcpc->GetUUID(); } + + // inline uint32 GetInstanceID() { return instance_id; } + // + // inline uint32 GetZoneOSProcessID() { return zone_os_process_id; } + +private: + std::shared_ptr tcpc; + std::unique_ptr boot_timer_obj; + + // uint32 zone_server_id; + // char client_address[250]; + // char client_local_address[250]; + // uint16 client_port; + // bool is_booting_up; + // bool is_static_zone; + // uint32 zone_player_count; + // char compiled[25]; + // char zone_name[32]; + // char long_name[256]; + // uint32 zone_server_zone_id; + // uint32 zone_server_previous_zone_id; + // Timer zone_boot_timer; + // uint32 instance_id; //instance ids contain a zone id, and a zone version + // uint32 zone_os_process_id; + // std::string launcher_name; //the launcher which started us + // std::string launched_name; //the name of the zone we launched. + EQ::Net::ConsoleServer *console; +}; + +#endif + diff --git a/zone/cheat_manager.cpp b/zone/cheat_manager.cpp index 5a84dc09d6..2d4696658b 100644 --- a/zone/cheat_manager.cpp +++ b/zone/cheat_manager.cpp @@ -3,8 +3,10 @@ #include "quest_parser_collection.h" #include "../common/events/player_event_logs.h" #include "worldserver.h" +#include "queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; void CheatManager::SetClient(Client *cli) { diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 4a0d8de09e..fb05d04908 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -31,12 +31,14 @@ #include "../common/repositories/character_corpses_repository.h" #include "../common/repositories/character_corpse_items_repository.h" #include +#include "queryserv.h" extern EntityList entity_list; -extern Zone *zone; +extern Zone *zone; extern WorldServer worldserver; extern npcDecayTimes_Struct npcCorpseDecayTimes[100]; +extern QueryServ *QServ; void Corpse::SendEndLootErrorPacket(Client *client) { diff --git a/zone/forage.cpp b/zone/forage.cpp index 1037c1fbb1..9e4adef55f 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -35,8 +35,10 @@ #include "../common/repositories/fishing_repository.h" #include "../common/events/player_event_logs.h" #include "worldserver.h" +#include "queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; #ifdef _WINDOWS #define snprintf _snprintf diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index 6e1f66d1c0..f16de18f4c 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -1,7 +1,9 @@ #include "../client.h" #include "../worldserver.h" +#include "queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; #include "../guild_mgr.h" #include "../doors.h" @@ -600,7 +602,28 @@ void command_guild(Client* c, const Seperator* sep) else { auto guild_id = Strings::ToUnsignedInt(sep->arg[2]); auto guild = guild_mgr.GetGuildByGuildID(guild_id); - c->SendGuildMembersList(); + + PlayerEvent::LootItemEvent e{}; + e.charges = -1; + e.corpse_name = "Test Corpse Name"; + e.item_id = 123456789; + e.item_name = "Test Item Name"; + e.npc_id = 987654321; + + RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); +// RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); + // auto d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); + // QServ->SendPacket(d.get()); + // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); + // QServ->SendPacket(d.get()); + // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); + // QServ->SendPacket(d.get()); + // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); + // QServ->SendPacket(d.get()); + // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); + // QServ->SendPacket(d.get()); + // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); + // QServ->SendPacket(d.get()); } } } diff --git a/zone/groups.cpp b/zone/groups.cpp index e61bbade79..5ce14c0d2e 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -25,10 +25,12 @@ #include "../common/events/player_event_logs.h" #include "../common/repositories/group_id_repository.h" #include "../common/repositories/group_leaders_repository.h" +#include "queryserv.h" -extern EntityList entity_list; +extern EntityList entity_list; extern WorldServer worldserver; +extern QueryServ *QServ; /* note about how groups work: diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 30f4c31daf..5004bd24f8 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -26,8 +26,10 @@ #include "../common/events/player_event_logs.h" #include "bot.h" #include "../common/repositories/character_corpse_items_repository.h" +#include "queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; // @merth: this needs to be touched up uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { diff --git a/zone/main.cpp b/zone/main.cpp index a05af774a4..a695d969bb 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -470,6 +470,8 @@ int main(int argc, char **argv) LogInfo("Loading quests"); parse->ReloadQuests(); + QServ->Connect(); + worldserver.Connect(); worldserver.SetScheduler(&event_scheduler); @@ -658,6 +660,7 @@ int main(int argc, char **argv) LogSys.CloseFileLogs(); safe_delete(mutex); + safe_delete(QServ); return 0; } diff --git a/zone/object.cpp b/zone/object.cpp index f740bf93c8..fb15edbad6 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -31,15 +31,17 @@ #include "../common/events/player_event_logs.h" #include "../common/repositories/ground_spawns_repository.h" #include "../common/repositories/object_repository.h" +#include "queryserv.h" const char DEFAULT_OBJECT_NAME[] = "IT63_ACTORDEF"; const char DEFAULT_OBJECT_NAME_SUFFIX[] = "_ACTORDEF"; -extern Zone* zone; -extern EntityList entity_list; +extern Zone *zone; +extern EntityList entity_list; extern WorldServer worldserver; +extern QueryServ *QServ; // Loading object from database Object::Object( diff --git a/zone/parcels.cpp b/zone/parcels.cpp index e3661906f9..34642a5304 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -27,6 +27,7 @@ #include "../common/ruletypes.h" extern WorldServer worldserver; +extern QueryServ *QServ; void Client::SendBulkParcels() { diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index de26c6be17..8c52b4da78 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -24,7 +24,7 @@ Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) extern WorldServer worldserver; -extern QueryServ *QServ; +extern QueryServ *QServ; QueryServ::QueryServ() { @@ -52,3 +52,36 @@ void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Eve Strings::Escape(Event_Desc).c_str()); SendQuery(query); } + +void QueryServ::Connect() +{ + m_connection = std::make_unique(Config->QSHost, Config->QSPort, false, "Zone", Config->SharedKey); + m_keepalive = std::make_unique(30000, true, std::bind(&QueryServ::OnKeepAlive, this, std::placeholders::_1)); + + LogInfo( + "New Query Server connection to [{}:{}]", + Config->QSHost, + Config->QSPort + ); +} + +bool QueryServ::SendPacket(ServerPacket *pack) +{ + if (m_connection.get() == nullptr) { + Connect(); + } + + if (!m_connection.get()) { + return false; + } + + m_connection->SendPacket(pack); + return true; +} + +void QueryServ::OnKeepAlive(EQ::Timer *t) +{ + ServerPacket pack(ServerOP_KeepAlive, 0); + m_connection->SendPacket(&pack); + +} diff --git a/zone/queryserv.h b/zone/queryserv.h index 69392037cc..4bdf1431f1 100644 --- a/zone/queryserv.h +++ b/zone/queryserv.h @@ -1,6 +1,12 @@ #ifndef QUERYSERV_ZONE_H #define QUERYSERV_ZONE_H +//#include "../common/types.h" +#include "../common/net/servertalk_server.h" +#include "../common/net/servertalk_client_connection.h" +//#include "../common/servertalk.h" +#include "../common/event/timer.h" + /* enum PlayerGenericLogEventTypes @@ -26,12 +32,35 @@ enum PlayerGenericLogEventTypes { }; -class QueryServ{ - public: - QueryServ(); - ~QueryServ(); - void SendQuery(std::string Query); - void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc); +class QueryServ { +public: + QueryServ(); + ~QueryServ(); + void SendQuery(std::string Query); + void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc); + void Connect(); + bool SendPacket(ServerPacket *pack); + +private: + void OnKeepAlive(EQ::Timer *t); + + std::unique_ptr m_connection; + std::unique_ptr m_keepalive; +}; + +class QueryServConnection +{ +public: + QueryServConnection(); + void AddConnection(std::shared_ptr connection); + void RemoveConnection(std::shared_ptr connection); + void HandleGenericMessage(uint16_t opcode, EQ::Net::Packet &p); + void HandleLFGuildUpdateMessage(uint16_t opcode, EQ::Net::Packet &p); + bool SendPacket(ServerPacket* pack); + void OnKeepAlive(EQ::Timer *t); +private: + std::map> m_streams; + std::unique_ptr m_keepalive; }; #endif /* QUERYSERV_ZONE_H */ diff --git a/zone/raids.cpp b/zone/raids.cpp index 4dd710e3af..d7c2ea6eb8 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -33,9 +33,11 @@ #include "bot.h" #include "worldserver.h" +#include "queryserv.h" -extern EntityList entity_list; +extern EntityList entity_list; extern WorldServer worldserver; +extern QueryServ *QServ; Raid::Raid(uint32 raidID) : GroupIDConsumer(raidID) diff --git a/zone/spells.cpp b/zone/spells.cpp index 4ca95255c3..50c62bd91f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -89,6 +89,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include #include +#include "queryserv.h" #ifndef WIN32 #include @@ -106,10 +107,11 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "mob.h" #include "water_map.h" -extern Zone* zone; +extern Zone *zone; extern volatile bool is_zone_loaded; -extern WorldServer worldserver; -extern FastMath g_Math; +extern WorldServer worldserver; +extern FastMath g_Math; +extern QueryServ *QServ; using EQ::spells::CastingSlot; diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 768fe4a4fc..4d0a6a0a05 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -60,16 +60,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/repositories/guild_tributes_repository.h" #include "../common/patches/patches.h" #include "../common/skill_caps.h" - -extern EntityList entity_list; -extern Zone* zone; -extern volatile bool is_zone_loaded; -extern void Shutdown(); -extern WorldServer worldserver; -extern PetitionList petition_list; -extern uint32 numclients; -extern volatile bool RunLoops; +#include "queryserv.h" + +extern EntityList entity_list; +extern Zone *zone; +extern volatile bool is_zone_loaded; +extern void Shutdown(); +extern WorldServer worldserver; +extern PetitionList petition_list; +extern uint32 numclients; +extern volatile bool RunLoops; extern QuestParserCollection *parse; +extern QueryServ *QServ; // QuestParserCollection *parse = 0; From c450ea598d3834b4e9249a291efed9994b371524 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:20:00 -0400 Subject: [PATCH 27/42] Cleanup a linux compile issue --- common/events/player_events.h | 12 ++++++------ zone/gm_commands/guild.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/events/player_events.h b/common/events/player_events.h index ed9f5fd3b9..83b3dc8049 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -1143,7 +1143,7 @@ namespace PlayerEvent { #endif //EQEMU_PLAYER_EVENTS_H #define RecordPlayerEventLog(event_type, event_data) do {\ - if (player_event_logs.IsEventEnabled(event_type)) {\ + if (player_event_logs.IsEventEnabled(event_type)) {\ if (RuleB(Logging, PlayerEventsQSProcess)) {\ QServ->SendPacket(\ player_event_logs.RecordEvent(\ @@ -1166,12 +1166,12 @@ namespace PlayerEvent { } while (0) #define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\ - if (player_event_logs.IsEventEnabled(event_type)) {\ + if (player_event_logs.IsEventEnabled(event_type)) {\ if (RuleB(Logging, PlayerEventsQSProcess)) {\ - QServ->SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - (c)->GetPlayerEvent(),\ + QServ->SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ event_data\ ).get()\ );\ diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index f16de18f4c..10fa035d6c 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -1,6 +1,6 @@ #include "../client.h" #include "../worldserver.h" -#include "queryserv.h" +#include "../queryserv.h" extern WorldServer worldserver; extern QueryServ *QServ; From 494c2ad205eac5c4a3332f61d8a8c215e4e19396 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:18:50 -0400 Subject: [PATCH 28/42] Add augments to LOOT ITEM and DESTROY ITEM --- common/events/player_event_logs.cpp | 18 ++- common/events/player_events.h | 62 +++++--- .../base_player_event_loot_items_repository.h | 134 ++++++++++++++---- zone/client_packet.cpp | 16 ++- zone/corpse.cpp | 17 ++- zone/gm_commands/guild.cpp | 34 +++-- zone/inventory.cpp | 32 +++-- 7 files changed, 224 insertions(+), 89 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 40188b2993..fd4cf296f6 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -166,12 +166,18 @@ void PlayerEventLogs::ProcessBatchQueue() in.serialize(ar); } - out.charges = in.charges; - out.corpse_name = in.corpse_name; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.npc_id = in.npc_id; - out.created_at = r.created_at; + out.charges = in.charges; + out.corpse_name = in.corpse_name; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.augment_1_id = in.aug1; + out.augment_2_id = in.aug2; + out.augment_3_id = in.aug3; + out.augment_4_id = in.aug4; + out.augment_5_id = in.aug5; + out.augment_6_id = in.aug6; + out.npc_id = in.npc_id; + out.created_at = r.created_at; if (m_etl_settings.contains(PlayerEvent::EventType::LOOT_ITEM)) { r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id; diff --git a/common/events/player_events.h b/common/events/player_events.h index 83b3dc8049..8cf498b32d 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -236,22 +236,22 @@ namespace PlayerEvent { }; // used in Trade event - struct TradeItem { - int64 item_id; - std::string item_name; - int32 slot; - - // cereal - template - void serialize(Archive &ar) - { - ar( - CEREAL_NVP(item_id), - CEREAL_NVP(item_name), - CEREAL_NVP(slot) - ); - } - }; + // struct TradeItem { + // int64 item_id; + // std::string item_name; + // int32 slot; + // + // // cereal + // template + // void serialize(Archive &ar) + // { + // ar( + // CEREAL_NVP(item_id), + // CEREAL_NVP(item_name), + // CEREAL_NVP(slot) + // ); + // } + // }; // used in Trade event class TradeItemEntry { @@ -451,6 +451,13 @@ namespace PlayerEvent { uint32 item_id; std::string item_name; int16 charges; + uint32 aug1; + uint32 aug2; + uint32 aug3; + uint32 aug4; + uint32 aug5; + uint32 aug6; + bool attuned; std::string reason; // cereal @@ -460,8 +467,15 @@ namespace PlayerEvent { ar( CEREAL_NVP(item_id), CEREAL_NVP(item_name), - CEREAL_NVP(reason), - CEREAL_NVP(charges) + CEREAL_NVP(charges), + CEREAL_NVP(aug1), + CEREAL_NVP(aug2), + CEREAL_NVP(aug3), + CEREAL_NVP(aug4), + CEREAL_NVP(aug5), + CEREAL_NVP(aug6), + CEREAL_NVP(attuned), + CEREAL_NVP(reason) ); } }; @@ -504,6 +518,12 @@ namespace PlayerEvent { uint32 item_id; std::string item_name; int16 charges; + uint32 aug1; + uint32 aug2; + uint32 aug3; + uint32 aug4; + uint32 aug5; + uint32 aug6; uint32 npc_id; std::string corpse_name; @@ -515,6 +535,12 @@ namespace PlayerEvent { CEREAL_NVP(item_id), CEREAL_NVP(item_name), CEREAL_NVP(charges), + CEREAL_NVP(aug1), + CEREAL_NVP(aug2), + CEREAL_NVP(aug3), + CEREAL_NVP(aug4), + CEREAL_NVP(aug5), + CEREAL_NVP(aug6), CEREAL_NVP(npc_id), CEREAL_NVP(corpse_name) ); diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h index ead31db299..42c1c928a1 100644 --- a/common/repositories/base/base_player_event_loot_items_repository.h +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -23,6 +23,12 @@ class BasePlayerEventLootItemsRepository { uint32_t item_id; std::string item_name; int32_t charges; + uint32_t augment_1_id; + uint32_t augment_2_id; + uint32_t augment_3_id; + uint32_t augment_4_id; + uint32_t augment_5_id; + uint32_t augment_6_id; uint32_t npc_id; std::string corpse_name; time_t created_at; @@ -40,6 +46,12 @@ class BasePlayerEventLootItemsRepository { "item_id", "item_name", "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", "npc_id", "corpse_name", "created_at", @@ -53,6 +65,12 @@ class BasePlayerEventLootItemsRepository { "item_id", "item_name", "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", "npc_id", "corpse_name", "UNIX_TIMESTAMP(created_at)", @@ -96,13 +114,19 @@ class BasePlayerEventLootItemsRepository { { PlayerEventLootItems e{}; - e.id = 0; - e.item_id = 0; - e.item_name = ""; - e.charges = 0; - e.npc_id = 0; - e.corpse_name = ""; - e.created_at = 0; + e.id = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.augment_1_id = 0; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 0; + e.augment_5_id = 0; + e.augment_6_id = 0; + e.npc_id = 0; + e.corpse_name = ""; + e.created_at = 0; return e; } @@ -139,13 +163,19 @@ class BasePlayerEventLootItemsRepository { if (results.RowCount() == 1) { PlayerEventLootItems e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_name = row[2] ? row[2] : ""; - e.charges = row[3] ? static_cast(atoi(row[3])) : 0; - e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.corpse_name = row[5] ? row[5] : ""; - e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.augment_1_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_2_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_3_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_4_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_5_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_6_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.npc_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.corpse_name = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); return e; } @@ -182,9 +212,15 @@ class BasePlayerEventLootItemsRepository { v.push_back(columns[1] + " = " + std::to_string(e.item_id)); v.push_back(columns[2] + " = '" + Strings::Escape(e.item_name) + "'"); v.push_back(columns[3] + " = " + std::to_string(e.charges)); - v.push_back(columns[4] + " = " + std::to_string(e.npc_id)); - v.push_back(columns[5] + " = '" + Strings::Escape(e.corpse_name) + "'"); - v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[4] + " = " + std::to_string(e.augment_1_id)); + v.push_back(columns[5] + " = " + std::to_string(e.augment_2_id)); + v.push_back(columns[6] + " = " + std::to_string(e.augment_3_id)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_4_id)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_5_id)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_6_id)); + v.push_back(columns[10] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[11] + " = '" + Strings::Escape(e.corpse_name) + "'"); + v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -210,6 +246,12 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); @@ -246,6 +288,12 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); @@ -282,13 +330,19 @@ class BasePlayerEventLootItemsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLootItems e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_name = row[2] ? row[2] : ""; - e.charges = row[3] ? static_cast(atoi(row[3])) : 0; - e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.corpse_name = row[5] ? row[5] : ""; - e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.augment_1_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_2_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_3_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_4_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_5_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_6_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.npc_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.corpse_name = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -313,13 +367,19 @@ class BasePlayerEventLootItemsRepository { for (auto row = results.begin(); row != results.end(); ++row) { PlayerEventLootItems e{}; - e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_name = row[2] ? row[2] : ""; - e.charges = row[3] ? static_cast(atoi(row[3])) : 0; - e.npc_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.corpse_name = row[5] ? row[5] : ""; - e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.augment_1_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_2_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_3_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_4_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_5_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_6_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.npc_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.corpse_name = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -398,6 +458,12 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); @@ -427,6 +493,12 @@ class BasePlayerEventLootItemsRepository { v.push_back(std::to_string(e.item_id)); v.push_back("'" + Strings::Escape(e.item_name) + "'"); v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); v.push_back(std::to_string(e.npc_id)); v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d4c4347345..1686e1a6dd 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5649,11 +5649,17 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) SetIntoxication(GetIntoxication()+IntoxicationIncrease); if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY) && inst->GetItem()) { - auto e = PlayerEvent::DestroyItemEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .reason = "Client deleted", + auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .aug1 = inst->GetAugment(0)->GetID(), + .aug2 = inst->GetAugment(1)->GetID(), + .aug3 = inst->GetAugment(2)->GetID(), + .aug4 = inst->GetAugment(3)->GetID(), + .aug5 = inst->GetAugment(4)->GetID(), + .aug6 = inst->GetAugment(5)->GetID(), + .attuned = inst->IsAttuned(), + .reason = "Client deleted" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index fb05d04908..4ff413d4c6 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1570,12 +1570,17 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) } if (player_event_logs.IsEventEnabled(PlayerEvent::LOOT_ITEM) && !IsPlayerCorpse()) { - auto e = PlayerEvent::LootItemEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .npc_id = GetNPCTypeID(), - .corpse_name = EntityList::RemoveNumbers(corpse_name) + auto e = PlayerEvent::LootItemEvent{ .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .aug1 = inst->GetAugment(0)->GetID(), + .aug2 = inst->GetAugment(1)->GetID(), + .aug3 = inst->GetAugment(2)->GetID(), + .aug4 = inst->GetAugment(3)->GetID(), + .aug5 = inst->GetAugment(4)->GetID(), + .aug6 = inst->GetAugment(5)->GetID(), + .npc_id = GetNPCTypeID(), + .corpse_name = EntityList::RemoveNumbers(corpse_name) }; RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index 10fa035d6c..25b6dc8b04 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -609,21 +609,29 @@ void command_guild(Client* c, const Seperator* sep) e.item_id = 123456789; e.item_name = "Test Item Name"; e.npc_id = 987654321; + e.aug1 = 11; + e.aug2 = 0; + e.aug3 = 0; + e.aug4 = 44; + e.aug5 = 55, + e.aug6 = 66; RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); -// RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); - // auto d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); - // QServ->SendPacket(d.get()); - // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); - // QServ->SendPacket(d.get()); - // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); - // QServ->SendPacket(d.get()); - // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); - // QServ->SendPacket(d.get()); - // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); - // QServ->SendPacket(d.get()); - // d = player_event_logs.RecordEvent(PlayerEvent::LOOT_ITEM, c->GetPlayerEvent(), e); - // QServ->SendPacket(d.get()); + + PlayerEvent::DestroyItemEvent e2{}; + e2.charges = -1; + e2.attuned = true; + e2.aug1 = 11; + e2.aug2 = 0; + e2.aug3 = 0; + e2.aug4 = 44; + e2.aug5 = 55; + e2.aug6 = 66; + e2.item_id = 123456789; + e2.item_name = "Test Item Destroy Name"; + e2.reason = "Test Item Destroy Reason"; + + RecordPlayerEventLogWithClient(c, PlayerEvent::ITEM_DESTROY, e2); } } } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 5004bd24f8..4608190dbd 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1761,11 +1761,17 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { DeleteItemInInventory(EQ::invslot::slotCursor, 0, true); if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { - auto e = PlayerEvent::DestroyItemEvent{ - .item_id = test_inst->GetItem()->ID, - .item_name = test_inst->GetItem()->Name, - .charges = test_inst->GetCharges(), - .reason = "Duplicate lore item", + auto e = PlayerEvent::DestroyItemEvent{ .item_id = test_inst->GetItem()->ID, + .item_name = test_inst->GetItem()->Name, + .charges = test_inst->GetCharges(), + .aug1 = test_inst->GetAugment(0)->GetID(), + .aug2 = test_inst->GetAugment(1)->GetID(), + .aug3 = test_inst->GetAugment(2)->GetID(), + .aug4 = test_inst->GetAugment(3)->GetID(), + .aug5 = test_inst->GetAugment(4)->GetID(), + .aug6 = test_inst->GetAugment(5)->GetID(), + .attuned = test_inst->IsAttuned(), + .reason = "Duplicate lore item" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); @@ -1785,11 +1791,17 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { - auto e = PlayerEvent::DestroyItemEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .reason = "Client destroy cursor", + auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .aug1 = inst->GetAugment(0)->GetID(), + .aug2 = inst->GetAugment(1)->GetID(), + .aug3 = inst->GetAugment(2)->GetID(), + .aug4 = inst->GetAugment(3)->GetID(), + .aug5 = inst->GetAugment(4)->GetID(), + .aug6 = inst->GetAugment(5)->GetID(), + .attuned = inst->IsAttuned(), + .reason = "Client destroy cursor" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); From a4a01e148b42e1d08276fbeb9cbd3c8e77108a16 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Mon, 30 Dec 2024 21:06:47 -0400 Subject: [PATCH 29/42] Add augments to ITEMCREATION, FORAGESUCCESS, FISHSUCCESS, DESTROYITEM, LOOTITEM, DROPPEDITEM, TRADERPURCHASE, TRADERSELL, GUILDTRIBUTEDONATE and cleaned up the naming convention of augments --- common/database.cpp | 24 +- .../events/player_event_discord_formatter.cpp | 72 ++--- common/events/player_event_logs.cpp | 36 +-- common/events/player_events.h | 271 ++++++++++++------ zone/client.cpp | 152 +++++----- zone/client_packet.cpp | 34 ++- zone/corpse.cpp | 22 +- zone/forage.cpp | 22 +- zone/gm_commands/guild.cpp | 44 +-- zone/gm_commands/parcels.cpp | 12 + zone/inventory.cpp | 81 +++--- zone/parcels.cpp | 48 ++-- zone/trading.cpp | 52 ++-- zone/worldserver.cpp | 18 +- 14 files changed, 511 insertions(+), 377 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a3405970dd..bf8f557530 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2148,18 +2148,18 @@ void Database::PurgeCharacterParcels() pel.event_type_name = PlayerEvent::EventName[pel.event_type_id]; std::stringstream ss; for (auto const &r: results) { - pd.from_name = r.from_name; - pd.item_id = r.item_id; - pd.aug_slot_1 = r.aug_slot_1; - pd.aug_slot_2 = r.aug_slot_2; - pd.aug_slot_3 = r.aug_slot_3; - pd.aug_slot_4 = r.aug_slot_4; - pd.aug_slot_5 = r.aug_slot_5; - pd.aug_slot_6 = r.aug_slot_6; - pd.note = r.note; - pd.quantity = r.quantity; - pd.sent_date = r.sent_date; - pd.char_id = r.char_id; + pd.from_name = r.from_name; + pd.item_id = r.item_id; + pd.augment_1_id = r.aug_slot_1; + pd.augment_2_id = r.aug_slot_2; + pd.augment_3_id = r.aug_slot_3; + pd.augment_4_id = r.aug_slot_4; + pd.augment_5_id = r.aug_slot_5; + pd.augment_6_id = r.aug_slot_6; + pd.note = r.note; + pd.quantity = r.quantity; + pd.sent_date = r.sent_date; + pd.char_id = r.char_id; { cereal::JSONOutputArchiveSingleLine ar(ss); pd.serialize(ar); diff --git a/common/events/player_event_discord_formatter.cpp b/common/events/player_event_discord_formatter.cpp index 578ec672bc..aab0c01db8 100644 --- a/common/events/player_event_discord_formatter.cpp +++ b/common/events/player_event_discord_formatter.cpp @@ -1057,51 +1057,51 @@ std::string PlayerEventDiscordFormatter::FormatTradeEvent( if (!e.character_1_give_items.empty()) { for (const auto &i: e.character_1_give_items) { std::string augment_info; - if (i.aug_1_item_id > 0) { + if (i.augment_1_id > 0) { augment_info += fmt::format( "Augment 1: {} ({})", - i.aug_1_item_name, - i.aug_1_item_id + i.augment_1_name, + i.augment_1_id ); } - if (i.aug_2_item_id > 0) { + if (i.augment_2_id > 0) { augment_info += fmt::format( "Augment 2: {} ({})", - i.aug_2_item_name, - i.aug_2_item_id + i.augment_2_name, + i.augment_2_id ); } - if (i.aug_3_item_id > 0) { + if (i.augment_3_id > 0) { augment_info += fmt::format( "Augment 3: {} ({})", - i.aug_3_item_name, - i.aug_3_item_id + i.augment_3_name, + i.augment_3_id ); } - if (i.aug_4_item_id > 0) { + if (i.augment_4_id > 0) { augment_info += fmt::format( "Augment 4: {} ({})\n", - i.aug_4_item_name, - i.aug_4_item_id + i.augment_4_name, + i.augment_4_id ); } - if (i.aug_5_item_id > 0) { + if (i.augment_5_id > 0) { augment_info += fmt::format( "Augment 5: {} ({})\n", - i.aug_5_item_name, - i.aug_5_item_id + i.augment_5_name, + i.augment_5_id ); } - if (i.aug_6_item_id > 0) { + if (i.augment_6_id > 0) { augment_info += fmt::format( "Augment 6: {} ({})", - i.aug_6_item_name, - i.aug_6_item_id + i.augment_6_name, + i.augment_6_id ); } @@ -1122,51 +1122,51 @@ std::string PlayerEventDiscordFormatter::FormatTradeEvent( if (!e.character_2_give_items.empty()) { for (const auto &i: e.character_2_give_items) { std::string augment_info; - if (i.aug_1_item_id > 0) { + if (i.augment_1_id > 0) { augment_info += fmt::format( "Augment 1: {} ({})", - i.aug_1_item_name, - i.aug_1_item_id + i.augment_1_name, + i.augment_1_id ); } - if (i.aug_2_item_id > 0) { + if (i.augment_2_id > 0) { augment_info += fmt::format( "Augment 2: {} ({})", - i.aug_2_item_name, - i.aug_2_item_id + i.augment_2_name, + i.augment_2_id ); } - if (i.aug_3_item_id > 0) { + if (i.augment_3_id > 0) { augment_info += fmt::format( "Augment 3: {} ({})", - i.aug_3_item_name, - i.aug_3_item_id + i.augment_3_name, + i.augment_3_id ); } - if (i.aug_4_item_id > 0) { + if (i.augment_4_id > 0) { augment_info += fmt::format( "Augment 4: {} ({})\n", - i.aug_4_item_name, - i.aug_4_item_id + i.augment_4_name, + i.augment_4_id ); } - if (i.aug_5_item_id > 0) { + if (i.augment_5_id > 0) { augment_info += fmt::format( "Augment 5: {} ({})\n", - i.aug_5_item_name, - i.aug_5_item_id + i.augment_5_name, + i.augment_5_id ); } - if (i.aug_6_item_id > 0) { + if (i.augment_6_id > 0) { augment_info += fmt::format( "Augment 6: {} ({})", - i.aug_6_item_name, - i.aug_6_item_id + i.augment_6_name, + i.augment_6_id ); } diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index fd4cf296f6..6ae6a21aaf 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -170,12 +170,12 @@ void PlayerEventLogs::ProcessBatchQueue() out.corpse_name = in.corpse_name; out.item_id = in.item_id; out.item_name = in.item_name; - out.augment_1_id = in.aug1; - out.augment_2_id = in.aug2; - out.augment_3_id = in.aug3; - out.augment_4_id = in.aug4; - out.augment_5_id = in.aug5; - out.augment_6_id = in.aug6; + out.augment_1_id = in.augment_1_id; + out.augment_2_id = in.augment_2_id; + out.augment_3_id = in.augment_3_id; + out.augment_4_id = in.augment_4_id; + out.augment_5_id = in.augment_5_id; + out.augment_6_id = in.augment_6_id; out.npc_id = in.npc_id; out.created_at = r.created_at; @@ -376,12 +376,12 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.player_event_trade_id = r.etl_table_id; out_entries.in_bag = i.in_bag; out.created_at = r.created_at; - out_entries.augment_1_id = i.aug_1_item_id; - out_entries.augment_2_id = i.aug_2_item_id; - out_entries.augment_3_id = i.aug_3_item_id; - out_entries.augment_4_id = i.aug_4_item_id; - out_entries.augment_5_id = i.aug_5_item_id; - out_entries.augment_6_id = i.aug_6_item_id; + out_entries.augment_1_id = i.augment_1_id; + out_entries.augment_2_id = i.augment_2_id; + out_entries.augment_3_id = i.augment_3_id; + out_entries.augment_4_id = i.augment_4_id; + out_entries.augment_5_id = i.augment_5_id; + out_entries.augment_6_id = i.augment_6_id; out_entries.created_at = r.created_at; } etl_queues.trade_entries.push_back(out_entries); @@ -397,12 +397,12 @@ void PlayerEventLogs::ProcessBatchQueue() out_entries.player_event_trade_id = r.etl_table_id; out_entries.in_bag = i.in_bag; out.created_at = r.created_at; - out_entries.augment_1_id = i.aug_1_item_id; - out_entries.augment_2_id = i.aug_2_item_id; - out_entries.augment_3_id = i.aug_3_item_id; - out_entries.augment_4_id = i.aug_4_item_id; - out_entries.augment_5_id = i.aug_5_item_id; - out_entries.augment_6_id = i.aug_6_item_id; + out_entries.augment_1_id = i.augment_1_id; + out_entries.augment_2_id = i.augment_2_id; + out_entries.augment_3_id = i.augment_3_id; + out_entries.augment_4_id = i.augment_4_id; + out_entries.augment_5_id = i.augment_5_id; + out_entries.augment_6_id = i.augment_6_id; out_entries.created_at = r.created_at; } etl_queues.trade_entries.push_back(out_entries); diff --git a/common/events/player_events.h b/common/events/player_events.h index 8cf498b32d..3eceaa8c45 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -207,12 +207,12 @@ namespace PlayerEvent { std::string item_name; uint16 to_slot; int16 charges; - uint32 aug1; - uint32 aug2; - uint32 aug3; - uint32 aug4; - uint32 aug5; - uint32 aug6; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; bool attuned; // cereal @@ -224,12 +224,12 @@ namespace PlayerEvent { CEREAL_NVP(item_name), CEREAL_NVP(to_slot), CEREAL_NVP(charges), - CEREAL_NVP(aug1), - CEREAL_NVP(aug2), - CEREAL_NVP(aug3), - CEREAL_NVP(aug4), - CEREAL_NVP(aug5), - CEREAL_NVP(aug6), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(attuned) ); } @@ -258,22 +258,23 @@ namespace PlayerEvent { public: uint16 slot; uint32 item_id; + uint32 augment_1_id; + std::string augment_1_name; + uint32 augment_2_id; + std::string augment_2_name; + uint32 augment_3_id; + std::string augment_3_name; + uint32 augment_4_id; + std::string augment_4_name; + uint32 augment_5_id; + std::string augment_5_name; + uint32 augment_6_id; + std::string augment_6_name; std::string item_name; uint16 charges; - uint32 aug_1_item_id; - std::string aug_1_item_name; - uint32 aug_2_item_id; - std::string aug_2_item_name; - uint32 aug_3_item_id; - std::string aug_3_item_name; - uint32 aug_4_item_id; - std::string aug_4_item_name; - uint32 aug_5_item_id; - std::string aug_5_item_name; - uint32 aug_6_item_id; - std::string aug_6_item_name; bool in_bag; + // cereal template void serialize(Archive &ar) @@ -281,12 +282,20 @@ namespace PlayerEvent { ar( CEREAL_NVP(slot), CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_1_name), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_2_name), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_1_name), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_4_name), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_5_name), + CEREAL_NVP(augment_6_id), + CEREAL_NVP(augment_6_name), + CEREAL_NVP(item_name), CEREAL_NVP(charges), - CEREAL_NVP(aug_1_item_id), - CEREAL_NVP(aug_2_item_id), - CEREAL_NVP(aug_3_item_id), - CEREAL_NVP(aug_4_item_id), - CEREAL_NVP(aug_5_item_id), CEREAL_NVP(in_bag) ); } @@ -419,6 +428,12 @@ namespace PlayerEvent { struct ForageSuccessEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; // cereal @@ -427,6 +442,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name) ); } @@ -434,6 +455,12 @@ namespace PlayerEvent { struct FishSuccessEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; // cereal @@ -442,6 +469,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name) ); } @@ -451,12 +484,12 @@ namespace PlayerEvent { uint32 item_id; std::string item_name; int16 charges; - uint32 aug1; - uint32 aug2; - uint32 aug3; - uint32 aug4; - uint32 aug5; - uint32 aug6; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; bool attuned; std::string reason; @@ -468,12 +501,12 @@ namespace PlayerEvent { CEREAL_NVP(item_id), CEREAL_NVP(item_name), CEREAL_NVP(charges), - CEREAL_NVP(aug1), - CEREAL_NVP(aug2), - CEREAL_NVP(aug3), - CEREAL_NVP(aug4), - CEREAL_NVP(aug5), - CEREAL_NVP(aug6), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(attuned), CEREAL_NVP(reason) ); @@ -518,12 +551,12 @@ namespace PlayerEvent { uint32 item_id; std::string item_name; int16 charges; - uint32 aug1; - uint32 aug2; - uint32 aug3; - uint32 aug4; - uint32 aug5; - uint32 aug6; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; uint32 npc_id; std::string corpse_name; @@ -535,12 +568,12 @@ namespace PlayerEvent { CEREAL_NVP(item_id), CEREAL_NVP(item_name), CEREAL_NVP(charges), - CEREAL_NVP(aug1), - CEREAL_NVP(aug2), - CEREAL_NVP(aug3), - CEREAL_NVP(aug4), - CEREAL_NVP(aug5), - CEREAL_NVP(aug6), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(npc_id), CEREAL_NVP(corpse_name) ); @@ -753,6 +786,12 @@ namespace PlayerEvent { struct DroppedItemEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; int16 slot_id; uint32 charges; @@ -763,6 +802,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name), CEREAL_NVP(slot_id), CEREAL_NVP(charges) @@ -818,6 +863,12 @@ namespace PlayerEvent { struct TraderPurchaseEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; uint32 trader_id; std::string trader_name; @@ -833,6 +884,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name), CEREAL_NVP(trader_id), CEREAL_NVP(trader_name), @@ -846,6 +903,12 @@ namespace PlayerEvent { struct TraderSellEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; uint32 buyer_id; std::string buyer_name; @@ -861,6 +924,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name), CEREAL_NVP(buyer_id), CEREAL_NVP(buyer_name), @@ -992,6 +1061,14 @@ namespace PlayerEvent { struct GuildTributeDonateItem { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; + int16 charges; + bool attuned; uint32 guild_favor; // cereal @@ -1000,6 +1077,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(guild_favor) ); } @@ -1022,15 +1105,15 @@ namespace PlayerEvent { struct ParcelRetrieve { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; uint32 quantity; std::string from_player_name; uint32 sent_date; - uint32 aug_slot_1; - uint32 aug_slot_2; - uint32 aug_slot_3; - uint32 aug_slot_4; - uint32 aug_slot_5; - uint32 aug_slot_6; // cereal template @@ -1038,31 +1121,31 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(quantity), CEREAL_NVP(from_player_name), - CEREAL_NVP(sent_date), - CEREAL_NVP(aug_slot_1), - CEREAL_NVP(aug_slot_2), - CEREAL_NVP(aug_slot_3), - CEREAL_NVP(aug_slot_4), - CEREAL_NVP(aug_slot_5), - CEREAL_NVP(aug_slot_6) + CEREAL_NVP(sent_date) ); } }; struct ParcelSend { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; uint32 quantity; std::string from_player_name; std::string to_player_name; uint32 sent_date; - uint32 aug_slot_1; - uint32 aug_slot_2; - uint32 aug_slot_3; - uint32 aug_slot_4; - uint32 aug_slot_5; - uint32 aug_slot_6; // cereal template @@ -1070,33 +1153,33 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(quantity), CEREAL_NVP(from_player_name), CEREAL_NVP(to_player_name), - CEREAL_NVP(sent_date), - CEREAL_NVP(aug_slot_1), - CEREAL_NVP(aug_slot_2), - CEREAL_NVP(aug_slot_3), - CEREAL_NVP(aug_slot_4), - CEREAL_NVP(aug_slot_5), - CEREAL_NVP(aug_slot_6) + CEREAL_NVP(sent_date) ); } }; struct ParcelDelete { + uint32 char_id; uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; uint32 quantity; - uint32 char_id; + uint32 sent_date; std::string from_name; std::string note; - uint32 sent_date; - uint32 aug_slot_1; - uint32 aug_slot_2; - uint32 aug_slot_3; - uint32 aug_slot_4; - uint32 aug_slot_5; - uint32 aug_slot_6; // cereal template @@ -1104,17 +1187,17 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(quantity), CEREAL_NVP(char_id), CEREAL_NVP(from_name), CEREAL_NVP(note), - CEREAL_NVP(sent_date), - CEREAL_NVP(aug_slot_1), - CEREAL_NVP(aug_slot_2), - CEREAL_NVP(aug_slot_3), - CEREAL_NVP(aug_slot_4), - CEREAL_NVP(aug_slot_5), - CEREAL_NVP(aug_slot_6) + CEREAL_NVP(sent_date) ); } }; diff --git a/zone/client.cpp b/zone/client.cpp index 495ce4ad94..7e4294c950 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -12177,23 +12177,22 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) if (inst) { t_entries.emplace_back( PlayerEvent::TradeItemEntry{ - .slot = i, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = false, + .slot = i, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "",.item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = false, } ); @@ -12201,27 +12200,26 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { - t_entries.emplace_back( - PlayerEvent::TradeItemEntry{ - .slot = j, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = true, - } - ); + t_entries.emplace_back(PlayerEvent::TradeItemEntry{ + .slot = j, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = true, + } + ); } } } @@ -12235,52 +12233,50 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { const EQ::ItemInstance *inst = trader2->GetInv().GetItem(i); if (inst) { - t2_entries.emplace_back( - PlayerEvent::TradeItemEntry{ - .slot = i, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = false, - } + t2_entries.emplace_back(PlayerEvent::TradeItemEntry{ + .slot = i, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = false, + } ); if (inst->IsClassBag()) { for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { inst = trader2->GetInv().GetItem(i, j); if (inst) { - t2_entries.emplace_back( - PlayerEvent::TradeItemEntry{ - .slot = j, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = true, - } + t2_entries.emplace_back(PlayerEvent::TradeItemEntry{ + .slot = j, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = true, + } ); } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1686e1a6dd..ffc3c26550 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5649,17 +5649,17 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) SetIntoxication(GetIntoxication()+IntoxicationIncrease); if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY) && inst->GetItem()) { - auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .aug1 = inst->GetAugment(0)->GetID(), - .aug2 = inst->GetAugment(1)->GetID(), - .aug3 = inst->GetAugment(2)->GetID(), - .aug4 = inst->GetAugment(3)->GetID(), - .aug5 = inst->GetAugment(4)->GetID(), - .aug6 = inst->GetAugment(5)->GetID(), - .attuned = inst->IsAttuned(), - .reason = "Client deleted" + auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .attuned = inst->IsAttuned(), + .reason = "Client deleted" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); @@ -17063,11 +17063,15 @@ void Client::Handle_OP_GuildTributeDonateItem(const EQApplicationPacket *app) SendGuildTributeDonateItemReply(in, favor); if(player_event_logs.IsEventEnabled(PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM)) { - auto e = PlayerEvent::GuildTributeDonateItem { - .item_id = inst->GetID(), - .guild_favor = favor + auto e = PlayerEvent::GuildTributeDonateItem{ .item_id = inst->GetID(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .guild_favor = favor }; - RecordPlayerEventLog(PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM, e); } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 4ff413d4c6..f3486d33b6 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1570,17 +1570,17 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) } if (player_event_logs.IsEventEnabled(PlayerEvent::LOOT_ITEM) && !IsPlayerCorpse()) { - auto e = PlayerEvent::LootItemEvent{ .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .aug1 = inst->GetAugment(0)->GetID(), - .aug2 = inst->GetAugment(1)->GetID(), - .aug3 = inst->GetAugment(2)->GetID(), - .aug4 = inst->GetAugment(3)->GetID(), - .aug5 = inst->GetAugment(4)->GetID(), - .aug6 = inst->GetAugment(5)->GetID(), - .npc_id = GetNPCTypeID(), - .corpse_name = EntityList::RemoveNumbers(corpse_name) + auto e = PlayerEvent::LootItemEvent{ .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .npc_id = GetNPCTypeID(), + .corpse_name = EntityList::RemoveNumbers(corpse_name) }; RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); diff --git a/zone/forage.cpp b/zone/forage.cpp index 9e4adef55f..0a0a3e94e5 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -380,11 +380,15 @@ void Client::GoFish(bool guarantee, bool use_bait) if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::FISH_SUCCESS)) { - auto e = PlayerEvent::FishSuccessEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, + auto e = PlayerEvent::FishSuccessEvent{ .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, }; - RecordPlayerEventLog(PlayerEvent::FISH_SUCCESS, e); } @@ -514,8 +518,14 @@ void Client::ForageItem(bool guarantee) { if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::FORAGE_SUCCESS)) { auto e = PlayerEvent::ForageSuccessEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, }; RecordPlayerEventLog(PlayerEvent::FORAGE_SUCCESS, e); } diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index 25b6dc8b04..897f3275bd 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -604,32 +604,32 @@ void command_guild(Client* c, const Seperator* sep) auto guild = guild_mgr.GetGuildByGuildID(guild_id); PlayerEvent::LootItemEvent e{}; - e.charges = -1; - e.corpse_name = "Test Corpse Name"; - e.item_id = 123456789; - e.item_name = "Test Item Name"; - e.npc_id = 987654321; - e.aug1 = 11; - e.aug2 = 0; - e.aug3 = 0; - e.aug4 = 44; - e.aug5 = 55, - e.aug6 = 66; + e.charges = -1; + e.corpse_name = "Test Corpse Name"; + e.item_id = 123456789; + e.item_name = "Test Item Name"; + e.npc_id = 987654321; + e.augment_1_id = 11; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 44; + e.augment_5_id = 55; + e.augment_6_id = 66; RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); PlayerEvent::DestroyItemEvent e2{}; - e2.charges = -1; - e2.attuned = true; - e2.aug1 = 11; - e2.aug2 = 0; - e2.aug3 = 0; - e2.aug4 = 44; - e2.aug5 = 55; - e2.aug6 = 66; - e2.item_id = 123456789; - e2.item_name = "Test Item Destroy Name"; - e2.reason = "Test Item Destroy Reason"; + e2.charges = -1; + e2.attuned = true; + e.augment_1_id = 11; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 44; + e.augment_5_id = 55; + e.augment_6_id = 66; + e2.item_id = 123456789; + e2.item_name = "Test Item Destroy Name"; + e2.reason = "Test Item Destroy Reason"; RecordPlayerEventLogWithClient(c, PlayerEvent::ITEM_DESTROY, e2); } diff --git a/zone/gm_commands/parcels.cpp b/zone/gm_commands/parcels.cpp index 740d078e7e..710f1b4a9b 100644 --- a/zone/gm_commands/parcels.cpp +++ b/zone/gm_commands/parcels.cpp @@ -202,6 +202,12 @@ void command_parcels(Client *c, const Seperator *sep) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = parcel_out.item_id; + e.augment_1_id = inst->GetAugmentItemID(0); + e.augment_2_id = inst->GetAugmentItemID(1); + e.augment_3_id = inst->GetAugmentItemID(2); + e.augment_4_id = inst->GetAugmentItemID(3); + e.augment_5_id = inst->GetAugmentItemID(4); + e.augment_6_id = inst->GetAugmentItemID(5); e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; @@ -280,6 +286,12 @@ void command_parcels(Client *c, const Seperator *sep) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = parcel_out.item_id; + e.augment_1_id = inst->GetAugmentItemID(0); + e.augment_2_id = inst->GetAugmentItemID(1); + e.augment_3_id = inst->GetAugmentItemID(2); + e.augment_4_id = inst->GetAugmentItemID(3); + e.augment_5_id = inst->GetAugmentItemID(4); + e.augment_6_id = inst->GetAugmentItemID(5); e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 4608190dbd..218c10fe0a 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -636,17 +636,17 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_CREATION)) { auto e = PlayerEvent::ItemCreationEvent{}; - e.item_id = item->ID; - e.item_name = item->Name; - e.to_slot = to_slot; - e.charges = charges; - e.aug1 = aug1; - e.aug2 = aug2; - e.aug3 = aug3; - e.aug4 = aug4; - e.aug5 = aug5; - e.aug6 = aug6; - e.attuned = attuned; + e.item_id = item->ID; + e.item_name = item->Name; + e.to_slot = to_slot; + e.charges = charges; + e.augment_1_id = aug1; + e.augment_2_id = aug2; + e.augment_3_id = aug3; + e.augment_4_id = aug4; + e.augment_5_id = aug5; + e.augment_6_id = aug6; + e.attuned = attuned; RecordPlayerEventLog(PlayerEvent::ITEM_CREATION, e); } @@ -765,11 +765,16 @@ void Client::DropItem(int16 slot_id, bool recurse) int i = 0; if (player_event_logs.IsEventEnabled(PlayerEvent::DROPPED_ITEM)) { - auto e = PlayerEvent::DroppedItemEvent{ - .item_id = inst->GetID(), - .item_name = inst->GetItem()->Name, - .slot_id = slot_id, - .charges = (uint32) inst->GetCharges() + auto e = PlayerEvent::DroppedItemEvent{ .item_id = inst->GetID(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, + .slot_id = slot_id, + .charges = (uint32) inst->GetCharges() }; RecordPlayerEventLog(PlayerEvent::DROPPED_ITEM, e); } @@ -1761,17 +1766,17 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { DeleteItemInInventory(EQ::invslot::slotCursor, 0, true); if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { - auto e = PlayerEvent::DestroyItemEvent{ .item_id = test_inst->GetItem()->ID, - .item_name = test_inst->GetItem()->Name, - .charges = test_inst->GetCharges(), - .aug1 = test_inst->GetAugment(0)->GetID(), - .aug2 = test_inst->GetAugment(1)->GetID(), - .aug3 = test_inst->GetAugment(2)->GetID(), - .aug4 = test_inst->GetAugment(3)->GetID(), - .aug5 = test_inst->GetAugment(4)->GetID(), - .aug6 = test_inst->GetAugment(5)->GetID(), - .attuned = test_inst->IsAttuned(), - .reason = "Duplicate lore item" + auto e = PlayerEvent::DestroyItemEvent{ .item_id = test_inst->GetItem()->ID, + .item_name = test_inst->GetItem()->Name, + .charges = test_inst->GetCharges(), + .augment_1_id = test_inst->GetAugmentItemID(0), + .augment_2_id = test_inst->GetAugmentItemID(1), + .augment_3_id = test_inst->GetAugmentItemID(2), + .augment_4_id = test_inst->GetAugmentItemID(3), + .augment_5_id = test_inst->GetAugmentItemID(4), + .augment_6_id = test_inst->GetAugmentItemID(5), + .attuned = test_inst->IsAttuned(), + .reason = "Duplicate lore item" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); @@ -1791,17 +1796,17 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { - auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .aug1 = inst->GetAugment(0)->GetID(), - .aug2 = inst->GetAugment(1)->GetID(), - .aug3 = inst->GetAugment(2)->GetID(), - .aug4 = inst->GetAugment(3)->GetID(), - .aug5 = inst->GetAugment(4)->GetID(), - .aug6 = inst->GetAugment(5)->GetID(), - .attuned = inst->IsAttuned(), - .reason = "Client destroy cursor" + auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .attuned = inst->IsAttuned(), + .reason = "Client destroy cursor" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); diff --git a/zone/parcels.cpp b/zone/parcels.cpp index 34642a5304..925deb7e0e 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -462,12 +462,12 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = parcel_out.item_id; - e.aug_slot_1 = parcel_out.aug_slot_1; - e.aug_slot_2 = parcel_out.aug_slot_2; - e.aug_slot_3 = parcel_out.aug_slot_3; - e.aug_slot_4 = parcel_out.aug_slot_4; - e.aug_slot_5 = parcel_out.aug_slot_5; - e.aug_slot_6 = parcel_out.aug_slot_6; + e.augment_1_id = parcel_out.aug_slot_1; + e.augment_2_id = parcel_out.aug_slot_2; + e.augment_3_id = parcel_out.aug_slot_3; + e.augment_4_id = parcel_out.aug_slot_4; + e.augment_5_id = parcel_out.aug_slot_5; + e.augment_6_id = parcel_out.aug_slot_6; e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; @@ -478,12 +478,12 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = i.item_id; - e.aug_slot_1 = i.aug_slot_1; - e.aug_slot_2 = i.aug_slot_2; - e.aug_slot_3 = i.aug_slot_3; - e.aug_slot_4 = i.aug_slot_4; - e.aug_slot_5 = i.aug_slot_5; - e.aug_slot_6 = i.aug_slot_6; + e.augment_1_id = i.aug_slot_1; + e.augment_2_id = i.aug_slot_2; + e.augment_3_id = i.aug_slot_3; + e.augment_4_id = i.aug_slot_4; + e.augment_5_id = i.aug_slot_5; + e.augment_6_id = i.aug_slot_6; e.quantity = i.quantity; e.sent_date = parcel_out.sent_date; RecordPlayerEventLog(PlayerEvent::PARCEL_SEND, e); @@ -776,12 +776,12 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in) PlayerEvent::ParcelRetrieve e{}; e.from_player_name = p->second.from_name; e.item_id = p->second.item_id; - e.aug_slot_1 = p->second.aug_slot_1; - e.aug_slot_2 = p->second.aug_slot_2; - e.aug_slot_3 = p->second.aug_slot_3; - e.aug_slot_4 = p->second.aug_slot_4; - e.aug_slot_5 = p->second.aug_slot_5; - e.aug_slot_6 = p->second.aug_slot_6; + e.augment_1_id = p->second.aug_slot_1; + e.augment_2_id = p->second.aug_slot_2; + e.augment_3_id = p->second.aug_slot_3; + e.augment_4_id = p->second.aug_slot_4; + e.augment_5_id = p->second.aug_slot_5; + e.augment_6_id = p->second.aug_slot_6; e.quantity = p->second.quantity; e.sent_date = p->second.sent_date; RecordPlayerEventLog(PlayerEvent::PARCEL_RETRIEVE, e); @@ -789,12 +789,12 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in) for (auto const &i:results) { e.from_player_name = p->second.from_name; e.item_id = i.item_id; - e.aug_slot_1 = i.aug_slot_1; - e.aug_slot_2 = i.aug_slot_2; - e.aug_slot_3 = i.aug_slot_3; - e.aug_slot_4 = i.aug_slot_4; - e.aug_slot_5 = i.aug_slot_5; - e.aug_slot_6 = i.aug_slot_6; + e.augment_1_id = i.aug_slot_1; + e.augment_2_id = i.aug_slot_2; + e.augment_3_id = i.aug_slot_3; + e.augment_4_id = i.aug_slot_4; + e.augment_5_id = i.aug_slot_5; + e.augment_6_id = i.aug_slot_6; e.quantity = i.quantity; e.sent_date = p->second.sent_date; RecordPlayerEventLog(PlayerEvent::PARCEL_RETRIEVE, e); diff --git a/zone/trading.cpp b/zone/trading.cpp index 785fd2aec6..6e59305946 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1701,16 +1701,22 @@ void Client::BuyTraderItem(TraderBuy_Struct *tbs, Client *Trader, const EQApplic Trader->AddMoneyToPP(copper, silver, gold, platinum, true); if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_PURCHASE)) { - auto e = PlayerEvent::TraderPurchaseEvent{ - .item_id = buy_item->GetID(), - .item_name = buy_item->GetItem()->Name, - .trader_id = Trader->CharacterID(), - .trader_name = Trader->GetCleanName(), - .price = tbs->price, - .charges = outtbs->quantity, - .total_cost = (tbs->price * outtbs->quantity), - .player_money_balance = GetCarriedMoney(), - }; + auto e = PlayerEvent::TraderPurchaseEvent{ + .item_id = buy_item->GetID(), + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), + .item_name = buy_item->GetItem()->Name, + .trader_id = Trader->CharacterID(), + .trader_name = Trader->GetCleanName(), + .price = tbs->price, + .charges = outtbs->quantity, + .total_cost = (tbs->price * outtbs->quantity), + .player_money_balance = GetCarriedMoney(), + }; RecordPlayerEventLog(PlayerEvent::TRADER_PURCHASE, e); } @@ -1718,7 +1724,13 @@ void Client::BuyTraderItem(TraderBuy_Struct *tbs, Client *Trader, const EQApplic if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) { auto e = PlayerEvent::TraderSellEvent{ .item_id = buy_item->GetID(), - .item_name = buy_item->GetItem()->Name, + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), + .item_name = buy_item->GetItem()->Name, .buyer_id = CharacterID(), .buyer_name = GetCleanName(), .price = tbs->price, @@ -3434,6 +3446,12 @@ void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicati if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_PURCHASE)) { auto e = PlayerEvent::TraderPurchaseEvent{ .item_id = buy_item->GetID(), + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), .item_name = buy_item->GetItem()->Name, .trader_id = tbs->trader_id, .trader_name = tbs->seller_name, @@ -3498,12 +3516,12 @@ void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicati e.from_player_name = parcel_out.from_name; e.to_player_name = GetCleanName(); e.item_id = parcel_out.item_id; - e.aug_slot_1 = parcel_out.aug_slot_1; - e.aug_slot_2 = parcel_out.aug_slot_2; - e.aug_slot_3 = parcel_out.aug_slot_3; - e.aug_slot_4 = parcel_out.aug_slot_4; - e.aug_slot_5 = parcel_out.aug_slot_5; - e.aug_slot_6 = parcel_out.aug_slot_6; + e.augment_1_id = parcel_out.aug_slot_1; + e.augment_2_id = parcel_out.aug_slot_2; + e.augment_3_id = parcel_out.aug_slot_3; + e.augment_4_id = parcel_out.aug_slot_4; + e.augment_5_id = parcel_out.aug_slot_5; + e.augment_6_id = parcel_out.aug_slot_6; e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 4d0a6a0a05..4dbcd2fffd 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -3973,13 +3973,16 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) TraderRepository::UpdateActiveTransaction(database, in->id, false); - trader_pc->RemoveItemBySerialNumber(item_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()); - if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) { + auto buy_item = trader_pc->FindTraderItemBySerialNumber(item_sn); auto e = PlayerEvent::TraderSellEvent{ .item_id = in->trader_buy_struct.item_id, + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), .item_name = in->trader_buy_struct.item_name, .buyer_id = in->buyer_id, .buyer_name = in->trader_buy_struct.buyer_name, @@ -3988,9 +3991,12 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) .total_cost = (in->trader_buy_struct.price * in->trader_buy_struct.quantity), .player_money_balance = trader_pc->GetCarriedMoney(), }; + RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e); + } - RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e); - } + trader_pc->RemoveItemBySerialNumber(item_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()); break; } From b05294bd86e6d4c59458c1e908a77425fcdd99fb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 01:45:53 -0600 Subject: [PATCH 30/42] Update version.h --- common/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 192a206141..ebccaadfce 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 9287 +#define CURRENT_BINARY_DATABASE_VERSION 9289 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #endif From 26f29731cd51e2734e6bb42ccd66141c6126124e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 02:12:14 -0600 Subject: [PATCH 31/42] Formatting fixes --- common/events/player_events.h | 128 +++++++++++++++++----------------- zone/client_packet.cpp | 23 +++--- zone/corpse.cpp | 23 +++--- zone/forage.cpp | 19 ++--- zone/inventory.cpp | 67 +++++++++--------- zone/trading.cpp | 28 ++++---- zone/worldserver.cpp | 6 +- 7 files changed, 151 insertions(+), 143 deletions(-) diff --git a/common/events/player_events.h b/common/events/player_events.h index 3eceaa8c45..8401670096 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -409,9 +409,9 @@ namespace PlayerEvent { struct AAPurchasedEvent { uint32 aa_id; - int32 aa_cost; - int32 aa_previous_id; - int32 aa_next_id; + int32 aa_cost; + int32 aa_previous_id; + int32 aa_next_id; // cereal template @@ -1060,16 +1060,16 @@ namespace PlayerEvent { }; struct GuildTributeDonateItem { - uint32 item_id; - uint32 augment_1_id; - uint32 augment_2_id; - uint32 augment_3_id; - uint32 augment_4_id; - uint32 augment_5_id; - uint32 augment_6_id; - int16 charges; - bool attuned; - uint32 guild_favor; + uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; + int16 charges; + bool attuned; + uint32 guild_favor; // cereal template @@ -1089,8 +1089,8 @@ namespace PlayerEvent { }; struct GuildTributeDonatePlat { - uint32 plat; - uint32 guild_favor; + uint32 plat; + uint32 guild_favor; // cereal template @@ -1198,7 +1198,7 @@ namespace PlayerEvent { CEREAL_NVP(from_name), CEREAL_NVP(note), CEREAL_NVP(sent_date) - ); + ); } }; @@ -1236,14 +1236,16 @@ namespace PlayerEvent { uint32 type; std::string message; - template void serialize(Archive &ar) + template + void serialize(Archive &ar) { - ar(CEREAL_NVP(to), - CEREAL_NVP(from), - CEREAL_NVP(guild_id), - CEREAL_NVP(min_status), - CEREAL_NVP(type), - CEREAL_NVP(message) + ar( + CEREAL_NVP(to), + CEREAL_NVP(from), + CEREAL_NVP(guild_id), + CEREAL_NVP(min_status), + CEREAL_NVP(type), + CEREAL_NVP(message) ); } }; @@ -1252,47 +1254,47 @@ namespace PlayerEvent { #endif //EQEMU_PLAYER_EVENTS_H #define RecordPlayerEventLog(event_type, event_data) do {\ - if (player_event_logs.IsEventEnabled(event_type)) {\ - if (RuleB(Logging, PlayerEventsQSProcess)) {\ - QServ->SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ - } \ - else { \ - worldserver.SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ - }\ - }\ + if (player_event_logs.IsEventEnabled(event_type)) {\ + if (RuleB(Logging, PlayerEventsQSProcess)) {\ + QServ->SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + } \ + else { \ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ + }\ } while (0) #define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\ - if (player_event_logs.IsEventEnabled(event_type)) {\ - if (RuleB(Logging, PlayerEventsQSProcess)) {\ - QServ->SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - (c)->GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ - }\ - else {\ - worldserver.SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - (c)->GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ - }\ - }\ + if (player_event_logs.IsEventEnabled(event_type)) {\ + if (RuleB(Logging, PlayerEventsQSProcess)) {\ + QServ->SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ + else {\ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ + }\ } while (0) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index ffc3c26550..7290962a57 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5649,17 +5649,18 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) SetIntoxication(GetIntoxication()+IntoxicationIncrease); if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY) && inst->GetItem()) { - auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .augment_1_id = inst->GetAugmentItemID(0), - .augment_2_id = inst->GetAugmentItemID(1), - .augment_3_id = inst->GetAugmentItemID(2), - .augment_4_id = inst->GetAugmentItemID(3), - .augment_5_id = inst->GetAugmentItemID(4), - .augment_6_id = inst->GetAugmentItemID(5), - .attuned = inst->IsAttuned(), - .reason = "Client deleted" + auto e = PlayerEvent::DestroyItemEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .attuned = inst->IsAttuned(), + .reason = "Client deleted" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index f3486d33b6..079769c189 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1570,17 +1570,18 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) } if (player_event_logs.IsEventEnabled(PlayerEvent::LOOT_ITEM) && !IsPlayerCorpse()) { - auto e = PlayerEvent::LootItemEvent{ .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .augment_1_id = inst->GetAugmentItemID(0), - .augment_2_id = inst->GetAugmentItemID(1), - .augment_3_id = inst->GetAugmentItemID(2), - .augment_4_id = inst->GetAugmentItemID(3), - .augment_5_id = inst->GetAugmentItemID(4), - .augment_6_id = inst->GetAugmentItemID(5), - .npc_id = GetNPCTypeID(), - .corpse_name = EntityList::RemoveNumbers(corpse_name) + auto e = PlayerEvent::LootItemEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .npc_id = GetNPCTypeID(), + .corpse_name = EntityList::RemoveNumbers(corpse_name) }; RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); diff --git a/zone/forage.cpp b/zone/forage.cpp index 0a0a3e94e5..a6ad1b6486 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -380,20 +380,21 @@ void Client::GoFish(bool guarantee, bool use_bait) if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::FISH_SUCCESS)) { - auto e = PlayerEvent::FishSuccessEvent{ .item_id = inst->GetItem()->ID, - .augment_1_id = inst->GetAugmentItemID(0), - .augment_2_id = inst->GetAugmentItemID(1), - .augment_3_id = inst->GetAugmentItemID(2), - .augment_4_id = inst->GetAugmentItemID(3), - .augment_5_id = inst->GetAugmentItemID(4), - .augment_6_id = inst->GetAugmentItemID(5), - .item_name = inst->GetItem()->Name, + auto e = PlayerEvent::FishSuccessEvent{ + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, }; RecordPlayerEventLog(PlayerEvent::FISH_SUCCESS, e); } if (parse->PlayerHasQuestSub(EVENT_FISH_SUCCESS)) { - std::vector args = { inst }; + std::vector args = {inst}; parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args); } } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 218c10fe0a..5a962cfdb4 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -765,16 +765,17 @@ void Client::DropItem(int16 slot_id, bool recurse) int i = 0; if (player_event_logs.IsEventEnabled(PlayerEvent::DROPPED_ITEM)) { - auto e = PlayerEvent::DroppedItemEvent{ .item_id = inst->GetID(), - .augment_1_id = inst->GetAugmentItemID(0), - .augment_2_id = inst->GetAugmentItemID(1), - .augment_3_id = inst->GetAugmentItemID(2), - .augment_4_id = inst->GetAugmentItemID(3), - .augment_5_id = inst->GetAugmentItemID(4), - .augment_6_id = inst->GetAugmentItemID(5), - .item_name = inst->GetItem()->Name, - .slot_id = slot_id, - .charges = (uint32) inst->GetCharges() + auto e = PlayerEvent::DroppedItemEvent{ + .item_id = inst->GetID(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, + .slot_id = slot_id, + .charges = (uint32) inst->GetCharges() }; RecordPlayerEventLog(PlayerEvent::DROPPED_ITEM, e); } @@ -1766,17 +1767,18 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { DeleteItemInInventory(EQ::invslot::slotCursor, 0, true); if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { - auto e = PlayerEvent::DestroyItemEvent{ .item_id = test_inst->GetItem()->ID, - .item_name = test_inst->GetItem()->Name, - .charges = test_inst->GetCharges(), - .augment_1_id = test_inst->GetAugmentItemID(0), - .augment_2_id = test_inst->GetAugmentItemID(1), - .augment_3_id = test_inst->GetAugmentItemID(2), - .augment_4_id = test_inst->GetAugmentItemID(3), - .augment_5_id = test_inst->GetAugmentItemID(4), - .augment_6_id = test_inst->GetAugmentItemID(5), - .attuned = test_inst->IsAttuned(), - .reason = "Duplicate lore item" + auto e = PlayerEvent::DestroyItemEvent{ + .item_id = test_inst->GetItem()->ID, + .item_name = test_inst->GetItem()->Name, + .charges = test_inst->GetCharges(), + .augment_1_id = test_inst->GetAugmentItemID(0), + .augment_2_id = test_inst->GetAugmentItemID(1), + .augment_3_id = test_inst->GetAugmentItemID(2), + .augment_4_id = test_inst->GetAugmentItemID(3), + .augment_5_id = test_inst->GetAugmentItemID(4), + .augment_6_id = test_inst->GetAugmentItemID(5), + .attuned = test_inst->IsAttuned(), + .reason = "Duplicate lore item" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); @@ -1796,17 +1798,18 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { - auto e = PlayerEvent::DestroyItemEvent{ .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .augment_1_id = inst->GetAugmentItemID(0), - .augment_2_id = inst->GetAugmentItemID(1), - .augment_3_id = inst->GetAugmentItemID(2), - .augment_4_id = inst->GetAugmentItemID(3), - .augment_5_id = inst->GetAugmentItemID(4), - .augment_6_id = inst->GetAugmentItemID(5), - .attuned = inst->IsAttuned(), - .reason = "Client destroy cursor" + auto e = PlayerEvent::DestroyItemEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .attuned = inst->IsAttuned(), + .reason = "Client destroy cursor" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); diff --git a/zone/trading.cpp b/zone/trading.cpp index 6e59305946..5048990b2d 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1719,28 +1719,28 @@ void Client::BuyTraderItem(TraderBuy_Struct *tbs, Client *Trader, const EQApplic }; RecordPlayerEventLog(PlayerEvent::TRADER_PURCHASE, e); - } + } if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) { - auto e = PlayerEvent::TraderSellEvent{ - .item_id = buy_item->GetID(), - .augment_1_id = buy_item->GetAugmentItemID(0), + auto e = PlayerEvent::TraderSellEvent{ + .item_id = buy_item->GetID(), + .augment_1_id = buy_item->GetAugmentItemID(0), .augment_2_id = buy_item->GetAugmentItemID(1), .augment_3_id = buy_item->GetAugmentItemID(2), .augment_4_id = buy_item->GetAugmentItemID(3), .augment_5_id = buy_item->GetAugmentItemID(4), .augment_6_id = buy_item->GetAugmentItemID(5), .item_name = buy_item->GetItem()->Name, - .buyer_id = CharacterID(), - .buyer_name = GetCleanName(), - .price = tbs->price, - .charges = outtbs->quantity, - .total_cost = (tbs->price * outtbs->quantity), - .player_money_balance = Trader->GetCarriedMoney(), - }; - - RecordPlayerEventLogWithClient(Trader, PlayerEvent::TRADER_SELL, e); - } + .buyer_id = CharacterID(), + .buyer_name = GetCleanName(), + .price = tbs->price, + .charges = outtbs->quantity, + .total_cost = (tbs->price * outtbs->quantity), + .player_money_balance = Trader->GetCarriedMoney(), + }; + + RecordPlayerEventLogWithClient(Trader, PlayerEvent::TRADER_SELL, e); + } LogTrading("Trader Received: [{}] Platinum, [{}] Gold, [{}] Silver, [{}] Copper", platinum, gold, silver, copper); ReturnTraderReq(app, outtbs->quantity, item_id); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 4dbcd2fffd..2a7f8ebe1b 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -3975,7 +3975,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) { auto buy_item = trader_pc->FindTraderItemBySerialNumber(item_sn); - auto e = PlayerEvent::TraderSellEvent{ + auto e = PlayerEvent::TraderSellEvent{ .item_id = in->trader_buy_struct.item_id, .augment_1_id = buy_item->GetAugmentItemID(0), .augment_2_id = buy_item->GetAugmentItemID(1), @@ -3991,8 +3991,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) .total_cost = (in->trader_buy_struct.price * in->trader_buy_struct.quantity), .player_money_balance = trader_pc->GetCarriedMoney(), }; - RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e); - } + RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e); + } trader_pc->RemoveItemBySerialNumber(item_sn, in->trader_buy_struct.quantity); trader_pc->AddMoneyToPP(in->trader_buy_struct.price * in->trader_buy_struct.quantity, true); From 8dcd84bc84eed46e405b8b6f9ec863c82f746a83 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 02:34:51 -0600 Subject: [PATCH 32/42] Fix syntax error in database migration update --- common/database/database_update_manifest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index c99ce40716..69a5bc8d78 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5824,7 +5824,7 @@ CREATE TABLE `player_event_loot_items` ( `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', `charges` INT(11) NULL DEFAULT NULL, `augment_1_id` INT UNSIGNED NULL DEFAULT '0', - `augment_2_id` INT UNSIGNED NULL DEFAULT '0'`, + `augment_2_id` INT UNSIGNED NULL DEFAULT '0', `augment_3_id` INT UNSIGNED NULL DEFAULT '0', `augment_4_id` INT UNSIGNED NULL DEFAULT '0', `augment_5_id` INT UNSIGNED NULL DEFAULT '0', From fdebcf1688a25e6b77eadc4b572eb43465141c83 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 03:02:00 -0600 Subject: [PATCH 33/42] Swap out GetNextTableId --- common/database.cpp | 20 ++++++++ common/database.h | 2 + common/events/player_event_logs.cpp | 23 ++++----- .../player_event_aa_purchase_repository.h | 47 ------------------- ...player_event_killed_named_npc_repository.h | 47 ------------------- .../player_event_killed_npc_repository.h | 47 ------------------- .../player_event_killed_raid_npc_repository.h | 47 ------------------- .../player_event_log_settings_repository.h | 43 ----------------- .../player_event_logs_repository.h | 36 -------------- .../player_event_loot_items_repository.h | 47 +------------------ ...layer_event_merchant_purchase_repository.h | 47 ------------------- .../player_event_merchant_sell_repository.h | 47 ------------------- ...ayer_event_npc_handin_entries_repository.h | 47 ------------------- .../player_event_npc_handin_repository.h | 47 ------------------- .../player_event_speech_repository.h | 47 ------------------- .../player_event_trade_entries_repository.h | 47 ------------------- .../player_event_trade_repository.h | 47 ------------------- world/cli/etl_get_settings.cpp | 2 +- world/cli/test.cpp | 4 +- 19 files changed, 39 insertions(+), 655 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index bf8f557530..4ecfbb91ee 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2195,3 +2195,23 @@ void Database::ClearBuyerDetails() { BuyerRepository::DeleteBuyer(*this, 0); } + +uint64_t Database::GetNextTableId(const std::string &table_name) +{ + auto results = QueryDatabase(fmt::format("SHOW TABLE STATUS LIKE '{}'", table_name)); + for (auto row : results) { + for ( + int row_index = 0; + row_index < results.ColumnCount(); + row_index++ + ) { + std::string field_name = Strings::ToLower(results.FieldName(row_index)); + if (field_name == "auto_increment") { + std::string value = row[row_index] ? row[row_index] : "null"; + return Strings::ToUnsignedBigInt(value, 1); + } + } + } + + return 1; +} diff --git a/common/database.h b/common/database.h index b33a6acc93..3d263755ce 100644 --- a/common/database.h +++ b/common/database.h @@ -274,6 +274,8 @@ class Database : public DBcore { void Encode(std::string &in); void Decode(std::string &in); + uint64_t GetNextTableId(const std::string& table_name); + private: Mutex Mvarcache; VarCache_Struct varcache; diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 6ae6a21aaf..83a49e33d2 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1320,7 +1320,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::LOOT_ITEM), .table_name = "player_event_loot_items", - .next_id = PlayerEventLootItemsRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventLootItemsRepository::TableName())) } }, { @@ -1328,7 +1328,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::MERCHANT_SELL), .table_name = "player_event_merchant_sell", - .next_id = PlayerEventMerchantSellRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventMerchantSellRepository::TableName())) } }, { @@ -1336,7 +1336,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::MERCHANT_PURCHASE), .table_name = "player_event_merchant_purchase", - .next_id = PlayerEventMerchantPurchaseRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventMerchantPurchaseRepository::TableName())) } }, { @@ -1344,7 +1344,8 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::NPC_HANDIN), .table_name = "player_event_npc_handin", - .next_id = PlayerEventNpcHandinRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventNpcHandinRepository::TableName())) + } }, { @@ -1352,7 +1353,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::TRADE), .table_name = "player_event_trade", - .next_id = PlayerEventTradeRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventTradeRepository::TableName())) } }, { @@ -1360,7 +1361,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::SPEECH), .table_name = "player_event_speech", - .next_id = PlayerEventSpeechRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventSpeechRepository::TableName())) } }, { @@ -1368,7 +1369,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::KILLED_NPC), .table_name = "player_event_killed_npc", - .next_id = PlayerEventKilledNpcRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventKilledNpcRepository::TableName())) } }, { @@ -1376,7 +1377,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::KILLED_NAMED_NPC), .table_name = "player_event_killed_named_npc", - .next_id = PlayerEventKilledNamedNpcRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventKilledNamedNpcRepository::TableName())) } }, { @@ -1384,7 +1385,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::KILLED_RAID_NPC), .table_name = "player_event_killed_raid_npc", - .next_id = PlayerEventKilledRaidNpcRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventKilledRaidNpcRepository::TableName())) } }, { @@ -1392,7 +1393,7 @@ void PlayerEventLogs::LoadEtlIds() { .enabled = e(PlayerEvent::AA_PURCHASE), .table_name = "player_event_aa_purchase", - .next_id = PlayerEventAaPurchaseRepository::GetNextAutoIncrementId(*m_database) + .next_id = static_cast(m_database->GetNextTableId(PlayerEventAaPurchaseRepository::TableName())) } } }; @@ -1422,4 +1423,4 @@ bool PlayerEventLogs::LoadDatabaseConnection() SetDatabase(&player_event_database); return true; -} \ No newline at end of file +} diff --git a/common/repositories/player_event_aa_purchase_repository.h b/common/repositories/player_event_aa_purchase_repository.h index 5fbc40f7ce..189c6c619b 100644 --- a/common/repositories/player_event_aa_purchase_repository.h +++ b/common/repositories/player_event_aa_purchase_repository.h @@ -7,54 +7,7 @@ class PlayerEventAaPurchaseRepository: public BasePlayerEventAaPurchaseRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventAaPurchaseRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventAaPurchaseRepository::GetWhereNeverExpires() - * PlayerEventAaPurchaseRepository::GetWhereXAndY() - * PlayerEventAaPurchaseRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_killed_named_npc_repository.h b/common/repositories/player_event_killed_named_npc_repository.h index 93859717f9..bd93fa8ce5 100644 --- a/common/repositories/player_event_killed_named_npc_repository.h +++ b/common/repositories/player_event_killed_named_npc_repository.h @@ -7,54 +7,7 @@ class PlayerEventKilledNamedNpcRepository: public BasePlayerEventKilledNamedNpcRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventKilledNamedNpcRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventKilledNamedNpcRepository::GetWhereNeverExpires() - * PlayerEventKilledNamedNpcRepository::GetWhereXAndY() - * PlayerEventKilledNamedNpcRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_npc_repository.h b/common/repositories/player_event_killed_npc_repository.h index b2501a591c..fcbacf7c50 100644 --- a/common/repositories/player_event_killed_npc_repository.h +++ b/common/repositories/player_event_killed_npc_repository.h @@ -7,54 +7,7 @@ class PlayerEventKilledNpcRepository: public BasePlayerEventKilledNpcRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventKilledNpcRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventKilledNpcRepository::GetWhereNeverExpires() - * PlayerEventKilledNpcRepository::GetWhereXAndY() - * PlayerEventKilledNpcRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_raid_npc_repository.h b/common/repositories/player_event_killed_raid_npc_repository.h index 2416dd7cca..8b4002c7b0 100644 --- a/common/repositories/player_event_killed_raid_npc_repository.h +++ b/common/repositories/player_event_killed_raid_npc_repository.h @@ -7,54 +7,7 @@ class PlayerEventKilledRaidNpcRepository: public BasePlayerEventKilledRaidNpcRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventKilledRaidNpcRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventKilledRaidNpcRepository::GetWhereNeverExpires() - * PlayerEventKilledRaidNpcRepository::GetWhereXAndY() - * PlayerEventKilledRaidNpcRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_log_settings_repository.h b/common/repositories/player_event_log_settings_repository.h index 3edaa02158..10aebc135b 100644 --- a/common/repositories/player_event_log_settings_repository.h +++ b/common/repositories/player_event_log_settings_repository.h @@ -9,49 +9,6 @@ class PlayerEventLogSettingsRepository: public BasePlayerEventLogSettingsRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventLogSettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventLogSettingsRepository::GetWhereNeverExpires() - * PlayerEventLogSettingsRepository::GetWhereXAndY() - * PlayerEventLogSettingsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - - static uint64 GetNextIdForTable(Database& db, std::string& table_name) - { - auto results = db.QueryDatabase(fmt::format("SELECT COALESCE(MAX(id), 0) FROM {}", table_name)); - - return results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) + 1 : 0; - } }; #endif //EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/player_event_logs_repository.h b/common/repositories/player_event_logs_repository.h index 14740208f0..59de5e46c1 100644 --- a/common/repositories/player_event_logs_repository.h +++ b/common/repositories/player_event_logs_repository.h @@ -7,42 +7,6 @@ class PlayerEventLogsRepository: public BasePlayerEventLogsRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventLogsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventLogsRepository::GetWhereNeverExpires() - * PlayerEventLogsRepository::GetWhereXAndY() - * PlayerEventLogsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here }; diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index 03a2f553fb..5767d1fb4a 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -7,52 +7,7 @@ class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventLootItemsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventLootItemsRepository::GetWhereNeverExpires() - * PlayerEventLootItemsRepository::GetWhereXAndY() - * PlayerEventLootItemsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } + // Custom extended repository methods here }; #endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_purchase_repository.h b/common/repositories/player_event_merchant_purchase_repository.h index 214b476a1d..9be7aef6a0 100644 --- a/common/repositories/player_event_merchant_purchase_repository.h +++ b/common/repositories/player_event_merchant_purchase_repository.h @@ -7,54 +7,7 @@ class PlayerEventMerchantPurchaseRepository: public BasePlayerEventMerchantPurchaseRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventMerchantPurchaseRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventMerchantPurchaseRepository::GetWhereNeverExpires() - * PlayerEventMerchantPurchaseRepository::GetWhereXAndY() - * PlayerEventMerchantPurchaseRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h index 73e38a4ee8..c93131b7a4 100644 --- a/common/repositories/player_event_merchant_sell_repository.h +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -7,54 +7,7 @@ class PlayerEventMerchantSellRepository: public BasePlayerEventMerchantSellRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventMerchantSellRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventMerchantSellRepository::GetWhereNeverExpires() - * PlayerEventMerchantSellRepository::GetWhereXAndY() - * PlayerEventMerchantSellRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_entries_repository.h b/common/repositories/player_event_npc_handin_entries_repository.h index 3e9cf8592b..f3c6d3bbe6 100644 --- a/common/repositories/player_event_npc_handin_entries_repository.h +++ b/common/repositories/player_event_npc_handin_entries_repository.h @@ -7,54 +7,7 @@ class PlayerEventNpcHandinEntriesRepository: public BasePlayerEventNpcHandinEntriesRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventNpcHandinEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventNpcHandinEntriesRepository::GetWhereNeverExpires() - * PlayerEventNpcHandinEntriesRepository::GetWhereXAndY() - * PlayerEventNpcHandinEntriesRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_repository.h b/common/repositories/player_event_npc_handin_repository.h index 03cf198415..2b3e233868 100644 --- a/common/repositories/player_event_npc_handin_repository.h +++ b/common/repositories/player_event_npc_handin_repository.h @@ -7,54 +7,7 @@ class PlayerEventNpcHandinRepository: public BasePlayerEventNpcHandinRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventNpcHandinRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventNpcHandinRepository::GetWhereNeverExpires() - * PlayerEventNpcHandinRepository::GetWhereXAndY() - * PlayerEventNpcHandinRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H diff --git a/common/repositories/player_event_speech_repository.h b/common/repositories/player_event_speech_repository.h index ac4690d7f5..22f9158fb5 100644 --- a/common/repositories/player_event_speech_repository.h +++ b/common/repositories/player_event_speech_repository.h @@ -7,54 +7,7 @@ class PlayerEventSpeechRepository: public BasePlayerEventSpeechRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventSpeechRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventSpeechRepository::GetWhereNeverExpires() - * PlayerEventSpeechRepository::GetWhereXAndY() - * PlayerEventSpeechRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/player_event_trade_entries_repository.h b/common/repositories/player_event_trade_entries_repository.h index 9b88770b82..775d833702 100644 --- a/common/repositories/player_event_trade_entries_repository.h +++ b/common/repositories/player_event_trade_entries_repository.h @@ -7,54 +7,7 @@ class PlayerEventTradeEntriesRepository: public BasePlayerEventTradeEntriesRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventTradeEntriesRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventTradeEntriesRepository::GetWhereNeverExpires() - * PlayerEventTradeEntriesRepository::GetWhereXAndY() - * PlayerEventTradeEntriesRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_trade_repository.h b/common/repositories/player_event_trade_repository.h index 9b78ca7fe8..7813e6fcd6 100644 --- a/common/repositories/player_event_trade_repository.h +++ b/common/repositories/player_event_trade_repository.h @@ -7,54 +7,7 @@ class PlayerEventTradeRepository: public BasePlayerEventTradeRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventTradeRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventTradeRepository::GetWhereNeverExpires() - * PlayerEventTradeRepository::GetWhereXAndY() - * PlayerEventTradeRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - static int64 GetNextAutoIncrementId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT AUTO_INCREMENT FROM information_schema.tables WHERE TABLE_NAME = '{}';", - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } }; #endif //EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H diff --git a/world/cli/etl_get_settings.cpp b/world/cli/etl_get_settings.cpp index cd8ad82b22..6af88cd468 100644 --- a/world/cli/etl_get_settings.cpp +++ b/world/cli/etl_get_settings.cpp @@ -5,7 +5,7 @@ void WorldserverCLI::EtlGetSettings(int argc, char **argv, argh::parser &cmd, st { description = "Displays server player event logs that are etl enabled"; - if (cmd[{ "-h", "--help" }]) { + if (cmd[{"-h", "--help"}]) { return; } diff --git a/world/cli/test.cpp b/world/cli/test.cpp index 738741723a..07904b120f 100644 --- a/world/cli/test.cpp +++ b/world/cli/test.cpp @@ -10,5 +10,7 @@ void WorldserverCLI::TestCommand(int argc, char **argv, argh::parser &cmd, std:: return; } - + for (auto &table: DatabaseSchema::GetStateTables()) { + LogInfo("Table name [{}] next_free_id [{}]", table, database.GetNextTableId(table)); + } } From 407d3286fff3c19e1ae8da87f85d9b2bb660dc25 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 03:17:13 -0600 Subject: [PATCH 34/42] Statically load counter --- common/events/player_event_logs.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 83a49e33d2..60a9bac063 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -132,7 +132,7 @@ void PlayerEventLogs::ProcessBatchQueue() return; } - std::map counter{}; + static std::map counter{}; for (auto const& e: m_record_batch_queue) { counter[e.event_type_id]++; } @@ -1397,6 +1397,16 @@ void PlayerEventLogs::LoadEtlIds() } } }; + + for (auto &e : m_etl_settings) { + LogPlayerEventsDetail( + "ETL Settings [{}] Enabled [{}] Table [{}] NextId [{}]", + PlayerEvent::EventName[e.first], + e.second.enabled, + e.second.table_name, + e.second.next_id + ); + } } bool PlayerEventLogs::LoadDatabaseConnection() From fe21324753ccf4de30dc898b043737485e653fc8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 03:21:17 -0600 Subject: [PATCH 35/42] Add counter.clear() since the counter is static --- common/events/player_event_logs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 60a9bac063..437c677e27 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -133,11 +133,11 @@ void PlayerEventLogs::ProcessBatchQueue() } static std::map counter{}; + counter.clear(); for (auto const& e: m_record_batch_queue) { counter[e.event_type_id]++; } - BenchTimer benchmark; EtlQueues etl_queues{}; From a60e48de431f466f8bf3e09caef3193b4aa100f5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 03:48:13 -0600 Subject: [PATCH 36/42] Upload optional QS conversion scripts --- .../optional/2025_01_09_drop_qs_tables.sql | 17 ++++ .../2025_01_09_qs_to_player_event_convert.sql | 94 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 utils/sql/git/optional/2025_01_09_drop_qs_tables.sql create mode 100644 utils/sql/git/optional/2025_01_09_qs_to_player_event_convert.sql diff --git a/utils/sql/git/optional/2025_01_09_drop_qs_tables.sql b/utils/sql/git/optional/2025_01_09_drop_qs_tables.sql new file mode 100644 index 0000000000..7117d8e55b --- /dev/null +++ b/utils/sql/git/optional/2025_01_09_drop_qs_tables.sql @@ -0,0 +1,17 @@ +-- Drop all qs_ tables +DROP TABLE IF EXISTS + qs_merchant_transaction_record, + qs_merchant_transaction_record_entries, + qs_player_aa_rate_hourly, + qs_player_delete_record, + qs_player_delete_record_entries, + qs_player_events, + qs_player_handin_record, + qs_player_handin_record_entries, + qs_player_move_record, + qs_player_move_record_entries, + qs_player_npc_kill_record, + qs_player_npc_kill_record_entries, + qs_player_speech, + qs_player_trade_record, + qs_player_trade_record_entries; diff --git a/utils/sql/git/optional/2025_01_09_qs_to_player_event_convert.sql b/utils/sql/git/optional/2025_01_09_qs_to_player_event_convert.sql new file mode 100644 index 0000000000..dc808bca90 --- /dev/null +++ b/utils/sql/git/optional/2025_01_09_qs_to_player_event_convert.sql @@ -0,0 +1,94 @@ +-- ================================ +-- Conversion of Merchant Transactions +-- ================================ +INSERT INTO player_event_merchant_sell ( + npc_id, merchant_name, merchant_type, item_id, item_name, charges, cost, alternate_currency_id, + player_money_balance, player_currency_balance, created_at +) +SELECT + r.merchant_id, NULL AS merchant_name, NULL AS merchant_type, e.item_id, NULL AS item_name, e.charges, r.merchant_cp AS cost, NULL AS alternate_currency_id, + r.char_cp AS player_money_balance, NULL AS player_currency_balance, r.time AS created_at +FROM qs_merchant_transaction_record AS r + JOIN qs_merchant_transaction_record_entries AS e + ON r.transaction_id = e.event_id; + +-- ================================ +-- Conversion of Player Trades +-- ================================ +INSERT INTO player_event_trade ( + char1_id, char2_id, char1_copper, char1_silver, char1_gold, char1_platinum, + char2_copper, char2_silver, char2_gold, char2_platinum, created_at +) +SELECT + char1_id, char2_id, char1_cp, char1_sp, char1_gp, char1_pp, + char2_cp, char2_sp, char2_gp, char2_pp, time AS created_at +FROM qs_player_trade_record; + +INSERT INTO player_event_trade_entries ( + player_event_trade_id, char_id, slot, item_id, charges, augment_1_id, augment_2_id, augment_3_id, + augment_4_id, augment_5_id, augment_6_id, in_bag, created_at +) +SELECT + event_id, from_id AS char_id, from_slot AS slot, item_id, charges, aug_1 AS augment_1_id, aug_2 AS augment_2_id, aug_3 AS augment_3_id, + aug_4 AS augment_4_id, aug_5 AS augment_5_id, NULL AS augment_6_id, 0 AS in_bag, NULL AS created_at +FROM qs_player_trade_record_entries; + +-- ================================ +-- Conversion of NPC Hand-ins +-- ================================ +INSERT INTO player_event_npc_handin ( + npc_id, npc_name, handin_copper, handin_silver, handin_gold, handin_platinum, + return_copper, return_silver, return_gold, return_platinum, is_quest_handin, created_at +) +SELECT + npc_id, NULL AS npc_name, char_cp AS handin_copper, char_sp AS handin_silver, char_gp AS handin_gold, char_pp AS handin_platinum, + npc_cp AS return_copper, npc_sp AS return_silver, npc_gp AS return_gold, npc_pp AS return_platinum, + 0 AS is_quest_handin, time AS created_at +FROM qs_player_handin_record; + +INSERT INTO player_event_npc_handin_entries ( + player_event_npc_handin_id, type, item_id, charges, evolve_level, evolve_amount, + augment_1_id, augment_2_id, augment_3_id, augment_4_id, augment_5_id, augment_6_id, created_at +) +SELECT + event_id, NULL AS type, item_id, charges, 0 AS evolve_level, 0 AS evolve_amount, + aug_1 AS augment_1_id, aug_2 AS augment_2_id, aug_3 AS augment_3_id, aug_4 AS augment_4_id, aug_5 AS augment_5_id, 0 AS augment_6_id, NULL AS created_at +FROM qs_player_handin_record_entries; + +-- ================================ +-- Conversion of NPC Kill Records +-- ================================ +INSERT INTO player_event_killed_npc ( + npc_id, npc_name, combat_time_seconds, total_damage_per_second_taken, total_heal_per_second_taken, created_at +) +SELECT + npc_id, NULL AS npc_name, NULL AS combat_time_seconds, NULL AS total_damage_per_second_taken, NULL AS total_heal_per_second_taken, time AS created_at +FROM qs_player_npc_kill_record; + +INSERT INTO player_event_killed_named_npc ( + npc_id, npc_name, combat_time_seconds, total_damage_per_second_taken, total_heal_per_second_taken, created_at +) +SELECT + npc_id, NULL AS npc_name, NULL AS combat_time_seconds, NULL AS total_damage_per_second_taken, NULL AS total_heal_per_second_taken, time AS created_at +FROM qs_player_npc_kill_record WHERE type = 1; -- Example condition for named NPCs + +-- ================================ +-- Conversion of Player Speech +-- ================================ +INSERT INTO player_event_speech ( + from_char_id, to_char_id, guild_id, type, min_status, message, created_at +) +SELECT + `from` AS from_char_id, `to` AS to_char_id, guilddbid AS guild_id, type, minstatus AS min_status, message, + timerecorded AS created_at +FROM qs_player_speech; + +-- ================================ +-- Conversion of AA Purchases +-- ================================ +INSERT INTO player_event_aa_purchase ( + aa_ability_id, cost, previous_id, next_id, created_at +) +SELECT + NULL AS aa_ability_id, NULL AS cost, NULL AS previous_id, NULL AS next_id, NULL AS created_at +FROM qs_player_aa_rate_hourly; -- Adjust as necessary for the source table and logic From a32e3070b16ea33941a5516067d981e437990f2e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 04:12:08 -0600 Subject: [PATCH 37/42] Remove all qs_tables and code referencing them --- common/database/database_dump_service.cpp | 21 -- common/database/database_dump_service.h | 3 - common/database_schema.h | 26 -- common/servertalk.h | 174 +--------- queryserv/database.cpp | 379 +--------------------- queryserv/database.h | 28 -- queryserv/lfguild.cpp | 3 - queryserv/queryserv.cpp | 20 -- queryserv/worldserver.cpp | 69 +--- queryserv/zonelist.cpp | 17 - queryserv/zonelist.h | 7 +- queryserv/zoneserver.cpp | 18 - queryserv/zoneserver.h | 28 +- utils/sql/svn/2268_QueryServ.sql | 22 -- utils/sql/svn/2304_QueryServ.sql | 41 --- utils/sql/svn/2361_QueryServ.sql | 141 -------- world/cli/database_dump.cpp | 2 - world/zoneserver.cpp | 9 - zone/aa.cpp | 26 -- zone/attack.cpp | 88 ----- zone/bot_command.cpp | 6 - zone/client.cpp | 33 -- zone/client.h | 2 - zone/client_packet.cpp | 201 +----------- zone/client_process.cpp | 6 - zone/command.cpp | 11 - zone/embparser_api.cpp | 6 - zone/exp.cpp | 22 -- zone/inventory.cpp | 231 ------------- zone/object.cpp | 2 - zone/queryserv.cpp | 10 - zone/queryserv.h | 1 - zone/questmgr.cpp | 12 - zone/task_client_state.cpp | 23 -- zone/tradeskills.cpp | 13 - zone/trading.cpp | 238 -------------- zone/zoning.cpp | 6 - 37 files changed, 15 insertions(+), 1930 deletions(-) delete mode 100644 utils/sql/svn/2268_QueryServ.sql delete mode 100644 utils/sql/svn/2304_QueryServ.sql delete mode 100644 utils/sql/svn/2361_QueryServ.sql diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 62d0e070a9..2bce54033b 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -136,11 +136,6 @@ std::string DatabaseDumpService::GetLoginTableList() return Strings::Join(DatabaseSchema::GetLoginTables(), " "); } -std::string DatabaseDumpService::GetQueryServTables() -{ - return Strings::Join(DatabaseSchema::GetQueryServerTables(), " "); -} - std::string DatabaseDumpService::GetSystemTablesList() { auto system_tables = DatabaseSchema::GetServerTables(); @@ -272,11 +267,6 @@ void DatabaseDumpService::DatabaseDump() tables_to_dump += GetLoginTableList() + " "; dump_descriptor += "-login"; } - - if (IsDumpQueryServerTables()) { - tables_to_dump += GetQueryServTables(); - dump_descriptor += "-queryserv"; - } } if (IsDumpStaticInstanceData()) { @@ -401,7 +391,6 @@ void DatabaseDumpService::DatabaseDump() // LogDebug("[{}] dump-to-console", IsDumpOutputToConsole()); // LogDebug("[{}] dump-path", GetSetDumpPath()); // LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false")); -// LogDebug("[{}] query-serv", (IsDumpQueryServerTables() ? "true" : "false")); // LogDebug("[{}] has-compression-binary", (HasCompressionBinary() ? "true" : "false")); // LogDebug("[{}] content", (IsDumpContentTables() ? "true" : "false")); // LogDebug("[{}] no-data", (IsDumpWithNoData() ? "true" : "false")); @@ -511,16 +500,6 @@ const std::string &DatabaseDumpService::GetDumpFileName() const return dump_file_name; } -bool DatabaseDumpService::IsDumpQueryServerTables() const -{ - return dump_query_server_tables; -} - -void DatabaseDumpService::SetDumpQueryServerTables(bool dump_query_server_tables) -{ - DatabaseDumpService::dump_query_server_tables = dump_query_server_tables; -} - bool DatabaseDumpService::IsDumpOutputToConsole() const { return dump_output_to_console; diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index 568eac07f4..60b252afbe 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -45,8 +45,6 @@ class DatabaseDumpService { void SetDumpPath(const std::string &dump_path); const std::string &GetDumpFileName() const; void SetDumpFileName(const std::string &dump_file_name); - bool IsDumpQueryServerTables() const; - void SetDumpQueryServerTables(bool dump_query_server_tables); bool IsDumpOutputToConsole() const; void SetDumpOutputToConsole(bool dump_output_to_console); bool IsDumpDropTableSyntaxOnly() const; @@ -96,7 +94,6 @@ class DatabaseDumpService { bool HasCompressionBinary(); std::string GetDumpFileNameWithPath(); std::string GetSetDumpPath(); - std::string GetQueryServTables(); void RemoveSqlBackup(); void BuildCredentialsFile(); void RemoveCredentialsFile(); diff --git a/common/database_schema.h b/common/database_schema.h index 0ea284faad..47bd9dc1c5 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -287,32 +287,6 @@ namespace DatabaseSchema { }; } - /** - * Gets QueryServer tables - * - * @return - */ - static std::vector GetQueryServerTables() - { - return { - "qs_merchant_transaction_record", - "qs_merchant_transaction_record_entries", - "qs_player_aa_rate_hourly", - "qs_player_delete_record", - "qs_player_delete_record_entries", - "qs_player_events", - "qs_player_handin_record", - "qs_player_handin_record_entries", - "qs_player_move_record", - "qs_player_move_record_entries", - "qs_player_npc_kill_record", - "qs_player_npc_kill_record_entries", - "qs_player_speech", - "qs_player_trade_record", - "qs_player_trade_record_entries", - }; - } - /** * Gets state tables * Tables that keep track of server state diff --git a/common/servertalk.h b/common/servertalk.h index 62641ee583..25830afb45 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -304,19 +304,8 @@ #define ServerOP_WWSpell 0x4757 #define ServerOP_WWTaskUpdate 0x4758 -/** - * QueryServer - */ -#define ServerOP_QSPlayerLogTrades 0x5000 -#define ServerOP_QSPlayerLogHandins 0x5001 -#define ServerOP_QSPlayerLogNPCKills 0x5002 -#define ServerOP_QSPlayerLogDeletes 0x5003 -#define ServerOP_QSPlayerLogMoves 0x5004 -#define ServerOP_QSPlayerLogMerchantTransactions 0x5005 -#define ServerOP_QSSendQuery 0x5006 -#define ServerOP_QSPlayerDropItem 0x5007 - // player events +#define ServerOP_QSSendQuery 0x5000 #define ServerOP_PlayerEvent 0x5100 enum { @@ -400,7 +389,6 @@ enum { QSG_LFGuild = 0 }; enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_RequestPlayerInfo, QSG_LFGuild_UpdateGuildInfo, QSG_LFGuild_GuildMatches, QSG_LFGuild_RequestGuildInfo }; -#define ServerOP_Speech 0x5500 enum { UserToWorldStatusWorldUnavail = 0, @@ -1358,171 +1346,11 @@ struct ServerMailMessageHeader_Struct { char message[0]; }; -struct Server_Speech_Struct { - char to[64]; - char from[64]; - uint32 guilddbid; - int16 minstatus; - uint32 type; - char message[0]; -}; - -struct PlayerLogTradeItemsEntry_Struct { - uint32 from_character_id; - uint16 from_slot; - uint32 to_character_id; - uint16 to_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct PlayerLogTrade_Struct { - uint32 character_1_id; - MoneyUpdate_Struct character_1_money; - uint16 character_1_item_count; - uint32 character_2_id; - MoneyUpdate_Struct character_2_money; - uint16 character_2_item_count; - uint16 _detail_count; - PlayerLogTradeItemsEntry_Struct item_entries[0]; -}; - -struct QSDropItems_Struct { - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerDropItem_Struct { - uint32 char_id; - bool pickup; // 0 drop, 1 pickup - uint32 zone_id; - int x; - int y; - int z; - uint16 _detail_count; - QSDropItems_Struct items[0]; -}; - -struct QSHandinItems_Struct { - char action_type[7]; // handin, return or reward - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogHandin_Struct { - uint32 quest_id; - uint32 char_id; - MoneyUpdate_Struct char_money; - uint16 char_count; - uint32 npc_id; - MoneyUpdate_Struct npc_money; - uint16 npc_count; - uint16 _detail_count; - QSHandinItems_Struct items[0]; -}; - -struct QSPlayerLogNPCKillSub_Struct{ - uint32 NPCID; - uint32 ZoneID; - uint32 Type; -}; - -struct QSPlayerLogNPCKillsPlayers_Struct{ - uint32 char_id; -}; - -struct QSPlayerLogNPCKill_Struct{ - QSPlayerLogNPCKillSub_Struct s1; - QSPlayerLogNPCKillsPlayers_Struct Chars[0]; -}; - -struct QSDeleteItems_Struct { - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogDelete_Struct { - uint32 char_id; - uint16 stack_size; // '0' indicates full stack or non-stackable item move - uint16 char_count; - QSDeleteItems_Struct items[0]; -}; - -struct QSMoveItems_Struct { - uint16 from_slot; - uint16 to_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogMove_Struct { - uint32 char_id; - uint16 from_slot; - uint16 to_slot; - uint16 stack_size; // '0' indicates full stack or non-stackable item move - uint16 char_count; - bool postaction; - QSMoveItems_Struct items[0]; -}; - -struct QSTransactionItems_Struct { - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSMerchantLogTransaction_Struct { - uint32 zone_id; - uint32 merchant_id; - MoneyUpdate_Struct merchant_money; - uint16 merchant_count; - uint32 char_id; - MoneyUpdate_Struct char_money; - uint16 char_count; - QSTransactionItems_Struct items[0]; -}; - struct DiscordWebhookMessage_Struct { uint32 webhook_id; char message[2000]; }; -struct QSGeneralQuery_Struct { - char QueryString[0]; -}; - struct CZClientMessageString_Struct { uint32 string_id; uint16 chat_type; diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 5bd21ac5eb..db6be3ce2a 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -1,386 +1,9 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - - #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include -#include -#include -#include -#include -#include -#include -#include #include -#include - -// Disgrace: for windows compile -#ifdef _WINDOWS -#include -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else - -#include "../common/unix.h" -#include - -#endif - #include "database.h" -#include "../common/eq_packet_structs.h" #include "../common/strings.h" -#include "../common/servertalk.h" - -void QSDatabase::AddSpeech( - const char *from, - const char *to, - const char *message, - uint16 minstatus, - uint32 guilddbid, - uint8 type -) -{ - - auto escapedFrom = new char[strlen(from) * 2 + 1]; - auto escapedTo = new char[strlen(to) * 2 + 1]; - auto escapedMessage = new char[strlen(message) * 2 + 1]; - DoEscapeString(escapedFrom, from, strlen(from)); - DoEscapeString(escapedTo, to, strlen(to)); - DoEscapeString(escapedMessage, message, strlen(message)); - - std::string query = StringFormat( - "INSERT INTO `qs_player_speech` " - "SET `from` = '%s', `to` = '%s', `message`='%s', " - "`minstatus`='%i', `guilddbid`='%i', `type`='%i'", - escapedFrom, escapedTo, escapedMessage, minstatus, guilddbid, type - ); - safe_delete_array(escapedFrom); - safe_delete_array(escapedTo); - safe_delete_array(escapedMessage); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Speech Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - -} - -void QSDatabase::LogPlayerDropItem(QSPlayerDropItem_Struct *QS) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_drop_record` SET `time` = NOW(), " - "`char_id` = '%i', `pickup` = '%i', " - "`zone_id` = '%i', `x` = '%i', `y` = '%i', `z` = '%i' ", - QS->char_id, QS->pickup, QS->zone_id, QS->x, QS->y, QS->z - ); - - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Drop Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (QS->_detail_count == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < QS->_detail_count; i++) { - query = StringFormat( - "INSERT INTO `qs_player_drop_record_entries` SET `event_id` = '%i', " - "`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', " - "`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, - QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Drop Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - } -} - -void QSDatabase::LogPlayerTrade(PlayerLogTrade_Struct *QS, uint32 detailCount) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_trade_record` SET `time` = NOW(), " - "`char1_id` = '%i', `char1_pp` = '%i', `char1_gp` = '%i', " - "`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', " - "`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', " - "`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'", - QS->character_1_id, QS->character_1_money.platinum, QS->character_1_money.gold, - QS->character_1_money.silver, QS->character_1_money.copper, QS->character_1_item_count, - QS->character_2_id, QS->character_2_money.platinum, QS->character_2_money.gold, - QS->character_2_money.silver, QS->character_2_money.copper, QS->character_2_item_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Trade Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (detailCount == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < detailCount; i++) { - query = StringFormat( - "INSERT INTO `qs_player_trade_record_entries` SET `event_id` = '%i', " - "`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', " - "`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', " - "`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->item_entries[i].from_character_id, QS->item_entries[i].from_slot, - QS->item_entries[i].to_character_id, QS->item_entries[i].to_slot, QS->item_entries[i].item_id, - QS->item_entries[i].charges, QS->item_entries[i].aug_1, QS->item_entries[i].aug_2, - QS->item_entries[i].aug_3, QS->item_entries[i].aug_4, QS->item_entries[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Trade Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} - -void QSDatabase::LogPlayerHandin(QSPlayerLogHandin_Struct *QS, uint32 detailCount) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_handin_record` SET `time` = NOW(), " - "`quest_id` = '%i', `char_id` = '%i', `char_pp` = '%i', " - "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " - "`char_items` = '%i', `npc_id` = '%i', `npc_pp` = '%i', " - "`npc_gp` = '%i', `npc_sp` = '%i', `npc_cp` = '%i', " - "`npc_items`='%i'", - QS->quest_id, QS->char_id, QS->char_money.platinum, - QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, - QS->char_count, QS->npc_id, QS->npc_money.platinum, - QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper, - QS->npc_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Handin Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (detailCount == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < detailCount; i++) { - query = StringFormat( - "INSERT INTO `qs_player_handin_record_entries` SET `event_id` = '%i', " - "`action_type` = '%s', `char_slot` = '%i', `item_id` = '%i', " - "`charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', " - "`aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].action_type, QS->items[i].char_slot, - QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1, - QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5 - ); - auto results = QueryDatabase(query); - - if (!results.Success()) { - LogInfo("Failed Handin Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - } - -} - -void QSDatabase::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct *QS, uint32 members) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_npc_kill_record` " - "SET `npc_id` = '%i', `type` = '%i', " - "`zone_id` = '%i', `time` = NOW()", - QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed NPC Kill Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (members == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < members; i++) { - query = StringFormat( - "INSERT INTO `qs_player_npc_kill_record_entries` " - "SET `event_id` = '%i', `char_id` = '%i'", - lastIndex, QS->Chars[i].char_id - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed NPC Kill Log Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} - -void QSDatabase::LogPlayerDelete(QSPlayerLogDelete_Struct *QS, uint32 items) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_delete_record` SET `time` = NOW(), " - "`char_id` = '%i', `stack_size` = '%i', `char_items` = '%i'", - QS->char_id, QS->stack_size, QS->char_count, QS->char_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Delete Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (items == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < items; i++) { - query = StringFormat( - "INSERT INTO `qs_player_delete_record_entries` SET `event_id` = '%i', " - "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " - "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Delete Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} - -void QSDatabase::LogPlayerMove(QSPlayerLogMove_Struct *QS, uint32 items) -{ - /* These are item moves */ - - std::string query = StringFormat( - "INSERT INTO `qs_player_move_record` SET `time` = NOW(), " - "`char_id` = '%i', `from_slot` = '%i', `to_slot` = '%i', " - "`stack_size` = '%i', `char_items` = '%i', `postaction` = '%i'", - QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size, - QS->char_count, QS->postaction - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Move Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (items == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < items; i++) { - query = StringFormat( - "INSERT INTO `qs_player_move_record_entries` SET `event_id` = '%i', " - "`from_slot` = '%i', `to_slot` = '%i', `item_id` = '%i', `charges` = '%i', " - "`aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, - QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Move Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - } -} - -void QSDatabase::LogMerchantTransaction(QSMerchantLogTransaction_Struct *QS, uint32 items) -{ - /* Merchant transactions are from the perspective of the merchant, not the player */ - std::string query = StringFormat( - "INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), " - "`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', " - "`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', " - "`merchant_items` = '%i', `char_id` = '%i', `char_pp` = '%i', " - "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " - "`char_items` = '%i'", - QS->zone_id, QS->merchant_id, QS->merchant_money.platinum, - QS->merchant_money.gold, QS->merchant_money.silver, - QS->merchant_money.copper, QS->merchant_count, QS->char_id, - QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, - QS->char_money.copper, QS->char_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Transaction Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (items == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < items; i++) { - query = StringFormat( - "INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id` = '%i', " - "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " - "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Transaction Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} // this function does not delete the ServerPacket, so it must be handled at call site void QSDatabase::GeneralQueryReceive(ServerPacket *pack) @@ -388,7 +11,7 @@ void QSDatabase::GeneralQueryReceive(ServerPacket *pack) /* These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again */ - auto queryBuffer = new char[pack->ReadUInt32() + 1]; + auto queryBuffer = new char[pack->ReadUInt32() + 1]; pack->ReadString(queryBuffer); std::string query(queryBuffer); diff --git a/queryserv/database.h b/queryserv/database.h index 5072f5b55a..69b0b8e36c 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -1,22 +1,3 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - #ifndef CHATSERVER_DATABASE_H #define CHATSERVER_DATABASE_H @@ -33,17 +14,8 @@ #include #include - class QSDatabase : public Database { public: - void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type); - void LogPlayerTrade(PlayerLogTrade_Struct* QS, uint32 DetailCount); - void LogPlayerDropItem(QSPlayerDropItem_Struct* QS); - void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount); - void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members); - void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items); - void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items); - void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items); void GeneralQueryReceive(ServerPacket *pack); }; diff --git a/queryserv/lfguild.cpp b/queryserv/lfguild.cpp index 5e80a8511d..2be8ddb86a 100644 --- a/queryserv/lfguild.cpp +++ b/queryserv/lfguild.cpp @@ -1,10 +1,7 @@ -#include #include "lfguild.h" #include "database.h" #include "worldserver.h" -#include "../common/eqemu_logsys.h" #include "../common/strings.h" -#include "../common/packet_dump.h" #include "../common/rulesys.h" extern WorldServer *worldserver; diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index 991c7816ef..28529d89ab 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -1,22 +1,3 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/opcodemgr.h" @@ -30,7 +11,6 @@ #include "queryservconfig.h" #include "lfguild.h" #include "worldserver.h" -#include "../common/path_manager.h" #include "../common/zone_store.h" #include "../common/events/player_event_logs.h" #include diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index db1d66ce05..cd76481c75 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -1,22 +1,3 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/md5.h" @@ -107,53 +88,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) SendPacket(&pack); break; } - case ServerOP_Speech: { - Server_Speech_Struct *SSS = (Server_Speech_Struct *) p.Data(); - std::string tmp1 = SSS->from; - std::string tmp2 = SSS->to; - database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type); - break; - } - case ServerOP_QSPlayerLogTrades: { - PlayerLogTrade_Struct *QS = (PlayerLogTrade_Struct *) p.Data(); - database.LogPlayerTrade(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerDropItem: { - QSPlayerDropItem_Struct *QS = (QSPlayerDropItem_Struct *) p.Data(); - database.LogPlayerDropItem(QS); - break; - } - case ServerOP_QSPlayerLogHandins: { - QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct *) p.Data(); - database.LogPlayerHandin(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerLogNPCKills: { - QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct *) p.Data(); - uint32 Members = (uint32) (p.Length() - sizeof(QSPlayerLogNPCKill_Struct)); - if (Members > 0) { Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct); } - database.LogPlayerNPCKill(QS, Members); - break; - } - case ServerOP_QSPlayerLogDeletes: { - QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct *) p.Data(); - uint32 Items = QS->char_count; - database.LogPlayerDelete(QS, Items); - break; - } - case ServerOP_QSPlayerLogMoves: { - QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct *) p.Data(); - uint32 Items = QS->char_count; - database.LogPlayerMove(QS, Items); - break; - } - case ServerOP_QSPlayerLogMerchantTransactions: { - QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct *) p.Data(); - uint32 Items = QS->char_count + QS->merchant_count; - database.LogMerchantTransaction(QS, Items); - break; - } case ServerOP_QueryServGeneric: { /* The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets @@ -205,5 +139,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) pack.pBuffer = nullptr; break; } + default: + LogInfo("Unhandled opcode: {}", opcode); + break; } } diff --git a/queryserv/zonelist.cpp b/queryserv/zonelist.cpp index 6a5a1c9a59..4f150ea149 100644 --- a/queryserv/zonelist.cpp +++ b/queryserv/zonelist.cpp @@ -1,20 +1,3 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ #include "zonelist.h" #include "zoneserver.h" #include "../common/strings.h" diff --git a/queryserv/zonelist.h b/queryserv/zonelist.h index 28b183babc..6189840f5a 100644 --- a/queryserv/zonelist.h +++ b/queryserv/zonelist.h @@ -1,11 +1,8 @@ #ifndef ZONELIST_H_ #define ZONELIST_H_ -// + #include "../common/types.h" #include -//../common/eqtime.h" -// #include "../common/timer.h" -// #include "../common/event/timer.h" #include #include #include @@ -22,4 +19,4 @@ class ZSList { std::list> zone_server_list; }; -#endif /*ZONELIST_H_*/ \ No newline at end of file +#endif /*ZONELIST_H_*/ diff --git a/queryserv/zoneserver.cpp b/queryserv/zoneserver.cpp index 7c00520267..3afe4d6a81 100644 --- a/queryserv/zoneserver.cpp +++ b/queryserv/zoneserver.cpp @@ -1,21 +1,3 @@ - -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ #include "zoneserver.h" #include "../common/global_define.h" #include "../common/eqemu_logsys.h" diff --git a/queryserv/zoneserver.h b/queryserv/zoneserver.h index 80f00c6c91..5faddce5d8 100644 --- a/queryserv/zoneserver.h +++ b/queryserv/zoneserver.h @@ -1,20 +1,3 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ #ifndef ZONESERVER_H #define ZONESERVER_H @@ -24,7 +7,6 @@ #include "../common/timer.h" #include "../common/emu_constants.h" #include "../world/console.h" -#include #include class Client; @@ -36,10 +18,10 @@ class ZoneServer : public WorldTCPConnection { ~ZoneServer(); // virtual inline bool IsZoneServer() { return true; } // - void SendPacket(ServerPacket* pack) { tcpc->SendPacket(pack); } + void SendPacket(ServerPacket *pack) { tcpc->SendPacket(pack); } // void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...); // void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message); - void SendKeepAlive(); + void SendKeepAlive(); // bool SetZone(uint32 in_zone_id, uint32 in_instance_id = 0, bool in_is_static_zone = false); // void TriggerBootup(uint32 in_zone_id = 0, uint32 in_instance_id = 0, const char* admin_name = 0, bool is_static_zone = false); // void Disconnect() { auto handle = tcpc->Handle(); if (handle) { handle->Disconnect(); } } @@ -49,7 +31,7 @@ class ZoneServer : public WorldTCPConnection { // uint32 GetPrevZoneID() { return zone_server_previous_zone_id; } // void ChangeWID(uint32 iCharID, uint32 iWID); // void SendGroupIDs(); - void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); + void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); // inline const char* GetZoneName() const { return zone_name; } // inline const char* GetZoneLongName() const { return long_name; } @@ -70,7 +52,7 @@ class ZoneServer : public WorldTCPConnection { // inline void RemovePlayer() { zone_player_count--; } // inline const char * GetLaunchName() const { return(launcher_name.c_str()); } // inline const char * GetLaunchedName() const { return(launched_name.c_str()); } - std::string GetUUID() const { return tcpc->GetUUID(); } + std::string GetUUID() const { return tcpc->GetUUID(); } // inline uint32 GetInstanceID() { return instance_id; } // @@ -78,7 +60,7 @@ class ZoneServer : public WorldTCPConnection { private: std::shared_ptr tcpc; - std::unique_ptr boot_timer_obj; + std::unique_ptr boot_timer_obj; // uint32 zone_server_id; // char client_address[250]; diff --git a/utils/sql/svn/2268_QueryServ.sql b/utils/sql/svn/2268_QueryServ.sql deleted file mode 100644 index 95b7232ac5..0000000000 --- a/utils/sql/svn/2268_QueryServ.sql +++ /dev/null @@ -1,22 +0,0 @@ -SET FOREIGN_KEY_CHECKS=0; --- ---------------------------- --- Table structure for `qs_player_npc_kill_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_npc_kill_record`; -CREATE TABLE `qs_player_npc_kill_record` ( - `fight_id` int(11) NOT NULL AUTO_INCREMENT, - `npc_id` int(11) DEFAULT NULL, - `type` int(11) DEFAULT NULL, - `zone_id` int(11) DEFAULT NULL, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`fight_id`) -) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_npc_kill_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_npc_kill_record_entries`; -CREATE TABLE `qs_player_npc_kill_record_entries` ( - `event_id` int(11) DEFAULT '0', - `char_id` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/utils/sql/svn/2304_QueryServ.sql b/utils/sql/svn/2304_QueryServ.sql deleted file mode 100644 index 6f2c158c5c..0000000000 --- a/utils/sql/svn/2304_QueryServ.sql +++ /dev/null @@ -1,41 +0,0 @@ -SET FOREIGN_KEY_CHECKS=0; --- ---------------------------- --- Table structure for `qs_player_npc_kill_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_trade_record`; -CREATE TABLE `qs_player_trade_record` ( - `trade_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `char1_id` int(11) DEFAULT '0', - `char1_pp` int(11) DEFAULT '0', - `char1_gp` int(11) DEFAULT '0', - `char1_sp` int(11) DEFAULT '0', - `char1_cp` int(11) DEFAULT '0', - `char1_items` mediumint(7) DEFAULT '0', - `char2_id` int(11) DEFAULT '0', - `char2_pp` int(11) DEFAULT '0', - `char2_gp` int(11) DEFAULT '0', - `char2_sp` int(11) DEFAULT '0', - `char2_cp` int(11) DEFAULT '0', - `char2_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`trade_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_npc_kill_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_trade_record_entries`; -CREATE TABLE `qs_player_trade_record_entries` ( - `event_id` int(11) DEFAULT '0', - `from_id` int(11) DEFAULT '0', - `from_slot` mediumint(7) DEFAULT '0', - `to_id` int(11) DEFAULT '0', - `to_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/utils/sql/svn/2361_QueryServ.sql b/utils/sql/svn/2361_QueryServ.sql deleted file mode 100644 index faa195a323..0000000000 --- a/utils/sql/svn/2361_QueryServ.sql +++ /dev/null @@ -1,141 +0,0 @@ -SET FOREIGN_KEY_CHECKS=0; --- ---------------------------- --- Table structure for `qs_merchant_transaction_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_merchant_transaction_record`; -CREATE TABLE `qs_merchant_transaction_record` ( - `transaction_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `zone_id` int(11) DEFAULT '0', - `merchant_id` int(11) DEFAULT '0', - `merchant_pp` int(11) DEFAULT '0', - `merchant_gp` int(11) DEFAULT '0', - `merchant_sp` int(11) DEFAULT '0', - `merchant_cp` int(11) DEFAULT '0', - `merchant_items` mediumint(7) DEFAULT '0', - `char_id` int(11) DEFAULT '0', - `char_pp` int(11) DEFAULT '0', - `char_gp` int(11) DEFAULT '0', - `char_sp` int(11) DEFAULT '0', - `char_cp` int(11) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`transaction_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_merchant_transaction_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_merchant_transaction_record_entries`; -CREATE TABLE `qs_merchant_transaction_record_entries` ( - `event_id` int(11) DEFAULT '0', - `char_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_delete_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_delete_record`; -CREATE TABLE `qs_player_delete_record` ( - `delete_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `char_id` int(11) DEFAULT '0', - `stack_size` mediumint(7) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`delete_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_delete_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_delete_record_entries`; -CREATE TABLE `qs_player_delete_record_entries` ( - `event_id` int(11) DEFAULT '0', - `char_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_handin_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_handin_record`; -CREATE TABLE `qs_player_handin_record` ( - `handin_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `quest_id` int(11) DEFAULT '0', - `char_id` int(11) DEFAULT '0', - `char_pp` int(11) DEFAULT '0', - `char_gp` int(11) DEFAULT '0', - `char_sp` int(11) DEFAULT '0', - `char_cp` int(11) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - `npc_id` int(11) DEFAULT '0', - `npc_pp` int(11) DEFAULT '0', - `npc_gp` int(11) DEFAULT '0', - `npc_sp` int(11) DEFAULT '0', - `npc_cp` int(11) DEFAULT '0', - `npc_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`handin_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_handin_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_handin_record_entries`; -CREATE TABLE `qs_player_handin_record_entries` ( - `event_id` int(11) DEFAULT '0', - `action_type` char(6) Default 'action', - `char_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_move_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_move_record`; -CREATE TABLE `qs_player_move_record` ( - `move_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `char_id` int(11) DEFAULT '0', - `from_slot` mediumint(7) DEFAULT '0', - `to_slot` mediumint(7) DEFAULT '0', - `stack_size` mediumint(7) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - `postaction` tinyint(1) DEFAULT '0', - PRIMARY KEY (`move_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_move_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_move_record_entries`; -CREATE TABLE `qs_player_move_record_entries` ( - `event_id` int(11) DEFAULT '0', - `from_slot` mediumint(7) DEFAULT '0', - `to_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/world/cli/database_dump.cpp b/world/cli/database_dump.cpp index 0465396886..2a78be594c 100644 --- a/world/cli/database_dump.cpp +++ b/world/cli/database_dump.cpp @@ -14,7 +14,6 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std: "--merc-tables", "--state-tables", "--system-tables", - "--query-serv-tables", "--static-instance-data", "--table-structure-only", "--table-lock", @@ -45,7 +44,6 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std: s->SetDumpMercTables(cmd[{"--merc-tables"}] || dump_all); s->SetDumpStateTables(cmd[{"--state-tables"}] || dump_all); s->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all); - s->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all); s->SetDumpAllTables(dump_all); s->SetDumpWithNoData(cmd[{"--table-structure-only"}]); s->SetDumpTableLock(cmd[{"--table-lock"}]); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 25f6fdbd84..e64d9463d5 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1353,15 +1353,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { safe_delete(outapp); break; } - case ServerOP_Speech: - case ServerOP_QSSendQuery: - case ServerOP_QSPlayerLogDeletes: - case ServerOP_QSPlayerDropItem: - case ServerOP_QSPlayerLogHandins: - case ServerOP_QSPlayerLogMerchantTransactions: - case ServerOP_QSPlayerLogMoves: - case ServerOP_QSPlayerLogNPCKills: - case ServerOP_QSPlayerLogTrades: case ServerOP_QueryServGeneric: { QSLink.SendPacket(pack); break; diff --git a/zone/aa.cpp b/zone/aa.cpp index d75001d187..b147c566f2 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1202,19 +1202,6 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str() ); } - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)) { - const auto event_desc = fmt::format( - "Ranked AA Purchase :: aa_id:{} at cost:{} in zoneid:{} instid:{}", - rank->id, - cost, - GetZoneID(), - GetInstanceID() - ); - - QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); - } } else { if (send_message_and_save) { MessageString( @@ -1225,19 +1212,6 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str() ); } - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)) { - const auto event_desc = fmt::format( - "Initial AA Purchase :: aa_id:{} at cost:{} in zoneid:{} instid:{}", - rank->id, - cost, - GetZoneID(), - GetInstanceID() - ); - - QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); - } } if (parse->PlayerHasQuestSub(EVENT_AA_BUY)) { diff --git a/zone/attack.cpp b/zone/attack.cpp index e2d7cdf176..2ea660815d 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2158,14 +2158,6 @@ bool Client::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::Skil GoToDeath(); } - /* QS: PlayerLogDeaths */ - if (RuleB(QueryServ, PlayerLogDeaths)) { - const char * killer_name = ""; - if (killer_mob && killer_mob->GetCleanName()) { killer_name = killer_mob->GetCleanName(); } - std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", GetZoneID(), GetInstanceID(), killer_name, spell, damage); - QServ->PlayerLogEvent(Player_Log_Deaths, CharacterID(), event_desc); - } - if (player_event_logs.IsEventEnabled(PlayerEvent::DEATH)) { auto e = PlayerEvent::DeathEvent{ .killer_id = killer_mob ? static_cast(killer_mob->GetID()) : static_cast(0), @@ -2718,37 +2710,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy player_count++; } } - - // QueryServ Logging - Raid Kills - if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = new ServerPacket( - ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * player_count) - ); - - player_count = 0; - - auto QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - - QS->s1.NPCID = GetNPCTypeID(); - QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 2; // Raid Fight - - for (const auto& m : killer_raid->members) { - if (m.is_bot) { - continue; - } - - if (m.member && m.member->IsClient()) { - QS->Chars[player_count].char_id = m.member->CastToClient()->CharacterID(); - player_count++; - } - } - - worldserver.SendPacket(pack); - safe_delete(pack); - } } else if (give_exp_client->IsGrouped() && killer_group) { if (!is_ldon_treasure && MerchantType == 0) { killer_group->SplitExp(ExpSource::Kill, final_exp, this); @@ -2782,33 +2743,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy player_count++; } } - - // QueryServ Logging - Group Kills - if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = new ServerPacket( - ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * player_count) - ); - - player_count = 0; - - auto QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - - QS->s1.NPCID = GetNPCTypeID(); - QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 1; // Group Fight - - for (const auto& m : killer_group->members) { - if (m && m->IsClient()) { - QS->Chars[player_count].char_id = m->CastToClient()->CharacterID(); - player_count++; - } - } - - worldserver.SendPacket(pack); - safe_delete(pack); - } } else { if (!is_ldon_treasure && !MerchantType) { const uint32 con_level = give_exp->GetLevelCon(GetLevel()); @@ -2839,28 +2773,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy give_exp_client->GetDeity() ); } - - // QueryServ Logging - Solo - if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = new ServerPacket( - ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1) - ); - - auto QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - - QS->s1.NPCID = GetNPCTypeID(); - QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 0; // Solo Fight - QS->Chars[0].char_id = give_exp_client->CharacterID(); - - player_count++; - - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging } } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index b15531dd75..8ef88a1cd5 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1524,12 +1524,6 @@ int bot_command_real_dispatch(Client *c, const char *message) return(-1); } - /* QS: Player_Log_Issued_Commands */ - if (RuleB(QueryServ, PlayerLogIssuedCommandes)){ - std::string event_desc = StringFormat("Issued bot command :: '%s' in zoneid:%i instid:%i", message, c->GetZoneID(), c->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc); - } - if(cur->access >= COMMANDS_LOGGING_MIN_STATUS) { LogCommands("[{}] ([{}]) used bot command: [{}] (target=[{}])", c->GetName(), c->AccountName(), message, c->GetTarget()?c->GetTarget()->GetName():"NONE"); } diff --git a/zone/client.cpp b/zone/client.cpp index 7e4294c950..c35f0a70e5 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -945,30 +945,6 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } } - /* Logs Player Chat */ - if (RuleB(QueryServ, PlayerLogChat)) { - auto pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1); - Server_Speech_Struct* sem = (Server_Speech_Struct*) pack->pBuffer; - - if(chan_num == ChatChannel_Guild) - sem->guilddbid = GuildID(); - else - sem->guilddbid = 0; - - strcpy(sem->message, message); - sem->minstatus = Admin(); - sem->type = chan_num; - if(targetname != 0) - strcpy(sem->to, targetname); - - if(GetName() != 0) - strcpy(sem->from, GetName()); - - if(worldserver.Connected()) - worldserver.SendPacket(pack); - safe_delete(pack); - } - // Garble the message based on drunkness if (GetIntoxication() > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) { GarbleMessage(message, (int)(GetIntoxication() / 3)); @@ -6838,15 +6814,6 @@ int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_sc return 0; } - /* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */ - if (is_scripted) { - /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } - } - if (!amount) { return 0; } diff --git a/zone/client.h b/zone/client.h index a60b01b43e..f13cffc722 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1102,7 +1102,6 @@ class Client : public Mob void RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity = 1); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); - void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, LootItem** bag_item_data = 0); bool AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, LootItem** bag_item_data = 0); bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQ::invslot::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); @@ -1111,7 +1110,6 @@ class Client : public Mob void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id, bool recurse = true); - void DropItemQS(EQ::ItemInstance* inst, bool pickup); bool HasItemOnCorpse(uint32 item_id); bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7290962a57..d6626d13da 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -804,12 +804,6 @@ void Client::CompleteConnect() parse->EventPlayer(EVENT_CONNECT, this, "", 0); } - /* QS: PlayerLogConnectDisconnect */ - if (RuleB(QueryServ, PlayerLogConnectDisconnect)) { - std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Connect_State, CharacterID(), event_desc); - } - /** * Update last login since this doesn't get updated until a late save later so we can update online status */ @@ -2655,12 +2649,6 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) return; } - /* QS: PlayerLogAlternateCurrencyTransactions :: Merchant Purchase */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Merchant Purchase :: Spent alt_currency_id:%i cost:%i for itemid:%i in zoneid:%i instid:%i", alt_cur_id, cost, item->ID, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } - if (parse->PlayerHasQuestSub(EVENT_ALT_CURRENCY_MERCHANT_BUY)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -2746,12 +2734,6 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) uint32 removed = NukeItem(item_id, invWhereWorn | invWherePersonal | invWhereCursor); if (removed > 0) { AddAlternateCurrencyValue(reclaim->currency_id, removed); - - /* QS: PlayerLogAlternateCurrencyTransactions :: Item to Currency */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Reclaim :: Item to Currency :: alt_currency_id:%i amount:%i to currency tab in zoneid:%i instid:%i", reclaim->currency_id, removed, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } } } /* Cursor to Item storage */ @@ -2770,11 +2752,6 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor); AddAlternateCurrencyValue(reclaim->currency_id, -((int)reclaim->count)); } - /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Reclaim :: Cursor to Item :: alt_currency_id:%i amount:-%i in zoneid:%i instid:%i", reclaim->currency_id, reclaim->count, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } } } @@ -2873,12 +2850,6 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) sell->cost = cost; - /* QS: PlayerLogAlternateCurrencyTransactions :: Sold to Merchant*/ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Sold to Merchant :: itemid:%u npcid:%u alt_currency_id:%u cost:%u in zoneid:%u instid:%i", item->ID, npc_id, alt_cur_id, cost, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } - if (parse->PlayerHasQuestSub(EVENT_ALT_CURRENCY_MERCHANT_SELL)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -14140,61 +14111,6 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) RecordPlayerEventLog(PlayerEvent::MERCHANT_PURCHASE, e); } - // start QS code - // stacking purchases not supported at this time - entire process will need some work to catch them properly - if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - auto qspack = - new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, - sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct)); - QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; - - qsaudit->zone_id = zone->GetZoneID(); - qsaudit->merchant_id = tmp->CastToNPC()->MerchantType; - qsaudit->merchant_money.platinum = 0; - qsaudit->merchant_money.gold = 0; - qsaudit->merchant_money.silver = 0; - qsaudit->merchant_money.copper = 0; - qsaudit->merchant_count = 1; - qsaudit->char_id = character_id; - qsaudit->char_money.platinum = (mpo->price / 1000); - qsaudit->char_money.gold = (mpo->price / 100) % 10; - qsaudit->char_money.silver = (mpo->price / 10) % 10; - qsaudit->char_money.copper = mpo->price % 10; - qsaudit->char_count = 0; - - qsaudit->items[0].char_slot = freeslotid == INVALID_INDEX ? 0 : freeslotid; - qsaudit->items[0].item_id = item->ID; - qsaudit->items[0].charges = mpo->quantity; - - const EQ::ItemInstance* audit_inst = m_inv[freeslotid]; - - if (audit_inst) { - qsaudit->items[0].aug_1 = audit_inst->GetAugmentItemID(0); - qsaudit->items[0].aug_2 = audit_inst->GetAugmentItemID(1); - qsaudit->items[0].aug_3 = audit_inst->GetAugmentItemID(2); - qsaudit->items[0].aug_4 = audit_inst->GetAugmentItemID(3); - qsaudit->items[0].aug_5 = audit_inst->GetAugmentItemID(4); - } - else { - qsaudit->items[0].aug_1 = 0; - qsaudit->items[0].aug_2 = 0; - qsaudit->items[0].aug_3 = 0; - qsaudit->items[0].aug_4 = 0; - qsaudit->items[0].aug_5 = 0; - - if (freeslotid != INVALID_INDEX) { - LogError("Handle_OP_ShopPlayerBuy: QS Audit could not locate merchant ([{}]) purchased item in player ([{}]) inventory slot ([{}])", - qsaudit->merchant_id, qsaudit->char_id, freeslotid); - } - } - - audit_inst = nullptr; - - if (worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - if (parse->PlayerHasQuestSub(EVENT_MERCHANT_BUY)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -14362,41 +14278,6 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } } - // start QS code - if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - auto qspack = - new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, - sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct)); - QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; - - qsaudit->zone_id = zone->GetZoneID(); - qsaudit->merchant_id = vendor->CastToNPC()->MerchantType; - qsaudit->merchant_money.platinum = (price / 1000); - qsaudit->merchant_money.gold = (price / 100) % 10; - qsaudit->merchant_money.silver = (price / 10) % 10; - qsaudit->merchant_money.copper = price % 10; - qsaudit->merchant_count = 0; - qsaudit->char_id = character_id; - qsaudit->char_money.platinum = 0; - qsaudit->char_money.gold = 0; - qsaudit->char_money.silver = 0; - qsaudit->char_money.copper = 0; - qsaudit->char_count = 1; - - qsaudit->items[0].char_slot = mp->itemslot; - qsaudit->items[0].item_id = itemid; - qsaudit->items[0].charges = charges; - qsaudit->items[0].aug_1 = m_inv[mp->itemslot]->GetAugmentItemID(1); - qsaudit->items[0].aug_2 = m_inv[mp->itemslot]->GetAugmentItemID(2); - qsaudit->items[0].aug_3 = m_inv[mp->itemslot]->GetAugmentItemID(3); - qsaudit->items[0].aug_4 = m_inv[mp->itemslot]->GetAugmentItemID(4); - qsaudit->items[0].aug_5 = m_inv[mp->itemslot]->GetAugmentItemID(5); - - if (worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - if (parse->PlayerHasQuestSub(EVENT_MERCHANT_SELL)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -15333,48 +15214,8 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) else { other->PlayerTradeEventLog(other->trade, trade); - // start QS code - if (RuleB(QueryServ, PlayerLogTrades)) { - PlayerLogTrade_Struct event_entry; - std::list event_details; - - memset(&event_entry, 0, sizeof(PlayerLogTrade_Struct)); - - // Perform actual trade - FinishTrade(other, true, &event_entry, &event_details); - other->FinishTrade(this, false, &event_entry, &event_details); - - event_entry._detail_count = event_details.size(); - - auto qs_pack = new ServerPacket( - ServerOP_QSPlayerLogTrades, - sizeof(PlayerLogTrade_Struct) + - (sizeof(PlayerLogTradeItemsEntry_Struct) * event_entry._detail_count)); - PlayerLogTrade_Struct* qs_buf = (PlayerLogTrade_Struct*)qs_pack->pBuffer; - - memcpy(qs_buf, &event_entry, sizeof(PlayerLogTrade_Struct)); - - int offset = 0; - - for (auto iter = event_details.begin(); iter != event_details.end(); - ++iter, ++offset) { - PlayerLogTradeItemsEntry_Struct* detail = reinterpret_cast(*iter); - qs_buf->item_entries[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - // end QS code - } - else { - FinishTrade(other); - other->FinishTrade(this); - } + FinishTrade(other); + other->FinishTrade(this); other->trade->Reset(); trade->Reset(); @@ -15391,43 +15232,7 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) QueuePacket(outapp); safe_delete(outapp); if (with->IsNPC()) { - // Audit trade to database for player trade stream - if (RuleB(QueryServ, PlayerLogHandins)) { - QSPlayerLogHandin_Struct event_entry; - std::list event_details; - - memset(&event_entry, 0, sizeof(QSPlayerLogHandin_Struct)); - - FinishTrade(with->CastToNPC(), false, &event_entry, &event_details); - - event_entry._detail_count = event_details.size(); - - auto qs_pack = - new ServerPacket(ServerOP_QSPlayerLogHandins, - sizeof(QSPlayerLogHandin_Struct) + - (sizeof(QSHandinItems_Struct) * event_entry._detail_count)); - QSPlayerLogHandin_Struct* qs_buf = (QSPlayerLogHandin_Struct*)qs_pack->pBuffer; - - memcpy(qs_buf, &event_entry, sizeof(QSPlayerLogHandin_Struct)); - - int offset = 0; - - for (auto iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { - QSHandinItems_Struct* detail = reinterpret_cast(*iter); - qs_buf->items[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - } - else { - FinishTrade(with->CastToNPC()); - } + FinishTrade(with->CastToNPC()); } // TODO: Log Bot trades else if (with->IsBot()) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index fd0028268e..e02a86b943 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -691,12 +691,6 @@ void Client::OnDisconnect(bool hard_disconnect) { if (r) { r->MemberZoned(this); } - - /* QS: PlayerLogConnectDisconnect */ - if (RuleB(QueryServ, PlayerLogConnectDisconnect)) { - std::string event_desc = StringFormat("Disconnect :: in zoneid:%i instid:%i", GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Connect_State, CharacterID(), event_desc); - } } if (!bZoning) { diff --git a/zone/command.cpp b/zone/command.cpp index 1007e09d32..6d7935207e 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -493,17 +493,6 @@ int command_realdispatch(Client *c, std::string message, bool ignore_status) } } - /* QS: Player_Log_Issued_Commands */ - if (RuleB(QueryServ, PlayerLogIssuedCommandes)) { - auto event_desc = fmt::format( - "Issued command :: '{}' in Zone ID: {} Instance ID: {}", - message, - c->GetZoneID(), - c->GetInstanceID() - ); - QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc); - } - if (current_command->admin >= COMMANDS_LOGGING_MIN_STATUS) { LogCommands( "[{}] ([{}]) used command: [{}] (target=[{}])", diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index c451db90b8..7b23f79536 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2430,11 +2430,6 @@ void Perl__qs_send_query(std::string query) QServ->SendQuery(std::move(query)); } -void Perl__qs_player_event(int char_id, std::string message) -{ - QServ->PlayerLogEvent(Player_Log_Quest, char_id, message); -} - void Perl__log(int category, const char* message) { if (category < Logs::None || category >= Logs::MaxCategoryID) @@ -6780,7 +6775,6 @@ void perl_register_quest() package.add("popuptablerow", &Perl__popuptablerow); package.add("processmobswhilezoneempty", &Perl__processmobswhilezoneempty); package.add("pvp", &Perl__pvp); - package.add("qs_player_event", &Perl__qs_player_event); package.add("qs_send_query", &Perl__qs_send_query); package.add("rain", &Perl__rain); package.add("rebind", (void(*)(int, float, float, float))&Perl__rebind); diff --git a/zone/exp.cpp b/zone/exp.cpp index be6b8af2b8..06ebd893c1 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -933,17 +933,6 @@ void Client::SetLevel(uint8 set_level, bool command) RecordPlayerEventLog(PlayerEvent::LEVEL_GAIN, e); } - - if (RuleB(QueryServ, PlayerLogLevels)) { - const auto event_desc = fmt::format( - "Leveled UP :: to Level:{} from Level:{} in zoneid:{} instid:{}", - set_level, - m_pp.level, - GetZoneID(), - GetInstanceID() - ); - QServ->PlayerLogEvent(Player_Log_Levels, CharacterID(), event_desc); - } } else if (set_level < m_pp.level) { int levels_lost = (m_pp.level - set_level); @@ -960,17 +949,6 @@ void Client::SetLevel(uint8 set_level, bool command) RecordPlayerEventLog(PlayerEvent::LEVEL_LOSS, e); } - - if (RuleB(QueryServ, PlayerLogLevels)) { - const auto event_desc = fmt::format( - "Leveled DOWN :: to Level:{} from Level:{} in zoneid:{} instid:{}", - set_level, - m_pp.level, - GetZoneID(), - GetInstanceID() - ); - QServ->PlayerLogEvent(Player_Log_Levels, CharacterID(), event_desc); - } } m_pp.level = set_level; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 5a962cfdb4..bdfb9cb834 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -829,79 +829,10 @@ void Client::DropItem(int16 slot_id, bool recurse) object->StartDecay(); LogInventory("[{}] dropped [{}] from slot [{}]", GetCleanName(), inst->GetItem()->Name, slot_id); - DropItemQS(inst, false); safe_delete(inst); } -void Client::DropItemQS(EQ::ItemInstance* inst, bool pickup) { - if (RuleB(QueryServ, PlayerDropItems)) { - QSPlayerDropItem_Struct qs_audit; - std::list event_details; - memset(&qs_audit, 0, sizeof(QSPlayerDropItem_Struct)); - - qs_audit.char_id = character_id; - qs_audit.pickup = pickup; - qs_audit.zone_id = GetZoneID(); - qs_audit.x = (int) GetX(); - qs_audit.y = (int) GetY(); - qs_audit.z = (int) GetZ(); - - if (inst) { - auto detail = new QSDropItems_Struct; - detail->item_id = inst->GetID(); - detail->charges = inst->IsClassBag() ? 1 : inst->GetCharges(); - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - event_details.push_back(detail); - - if (inst->IsClassBag()) { - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items - const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); - if (bag_inst) { - detail = new QSDropItems_Struct; - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - event_details.push_back(detail); - } - } - } - } - qs_audit._detail_count = event_details.size(); - - auto qs_pack = new ServerPacket( - ServerOP_QSPlayerDropItem, - sizeof(QSPlayerDropItem_Struct) + - (sizeof(QSDropItems_Struct) * qs_audit._detail_count)); - QSPlayerDropItem_Struct* qs_buf = (QSPlayerDropItem_Struct*) qs_pack->pBuffer; - - memcpy(qs_buf, &qs_audit, sizeof(QSPlayerDropItem_Struct)); - - int offset = 0; - - for (auto iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { - QSDropItems_Struct* detail = reinterpret_cast(*iter); - qs_buf->items[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - } -} - // Drop inst void Client::DropInst(const EQ::ItemInstance* inst) { @@ -1050,55 +981,6 @@ void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_up return; } - // start QS code - if(RuleB(QueryServ, PlayerLogDeletes)) { - uint16 delete_count = 0; - - if(m_inv[slot_id]) { delete_count += m_inv.GetItem(slot_id)->GetTotalItemCount(); } - - auto qspack = - new ServerPacket(ServerOP_QSPlayerLogDeletes, - sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count)); - QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer; - uint16 parent_offset = 0; - - qsaudit->char_id = character_id; - qsaudit->stack_size = quantity; - qsaudit->char_count = delete_count; - - qsaudit->items[parent_offset].char_slot = slot_id; - qsaudit->items[parent_offset].item_id = m_inv[slot_id]->GetID(); - qsaudit->items[parent_offset].charges = m_inv[slot_id]->GetCharges(); - qsaudit->items[parent_offset].aug_1 = m_inv[slot_id]->GetAugmentItemID(1); - qsaudit->items[parent_offset].aug_2 = m_inv[slot_id]->GetAugmentItemID(2); - qsaudit->items[parent_offset].aug_3 = m_inv[slot_id]->GetAugmentItemID(3); - qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4); - qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); - - if (m_inv[slot_id]->IsClassBag()) { - for (uint8 bag_idx = EQ::invbag::SLOT_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { - EQ::ItemInstance* bagitem = m_inv[slot_id]->GetItem(bag_idx); - - if(bagitem) { - int16 bagslot_id = EQ::InventoryProfile::CalcSlotId(slot_id, bag_idx); - - qsaudit->items[++parent_offset].char_slot = bagslot_id; - qsaudit->items[parent_offset].item_id = bagitem->GetID(); - qsaudit->items[parent_offset].charges = bagitem->GetCharges(); - qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1); - qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2); - qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3); - qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4); - qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5); - } - } - } - - if(worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - bool isDeleted = m_inv.DeleteItem(slot_id, quantity); const EQ::ItemInstance* inst = nullptr; @@ -1732,7 +1614,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } if (move_in->from_slot == move_in->to_slot) { // Item summon, no further processing needed - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit if (ClientVersion() >= EQ::versions::ClientVersion::RoF) { return true; } // Can't do RoF+ if (move_in->to_slot == EQ::invslot::slotCursor) { @@ -1792,7 +1673,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (move_in->to_slot == (uint32)INVALID_INDEX) { if (move_in->from_slot == (uint32)EQ::invslot::slotCursor) { LogInventory("Client destroyed item from cursor slot [{}]", move_in->from_slot); - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit EQ::ItemInstance *inst = m_inv.GetItem(EQ::invslot::slotCursor); @@ -1832,7 +1712,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { LogInventory("Deleted item from slot [{}] as a result of an inventory container tradeskill combine", move_in->from_slot); - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit DeleteItemInInventory(move_in->from_slot); return true; // Item deletion } @@ -2004,8 +1883,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { safe_delete(inst); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit - return true; } else if (dst_slot_id >= EQ::invslot::WORLD_BEGIN && dst_slot_id <= EQ::invslot::WORLD_END) { @@ -2074,8 +1951,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv[src_slot_id], src_slot_id); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit - return true; } } @@ -2094,10 +1969,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return false; } - // Add cursor item to trade bucket - // Also sends trade information to other client of trade session - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - trade->AddEntity(dst_slot_id, move_in->number_in_stack); if (dstitemid == 0) { @@ -2106,8 +1977,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; } else { - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - SummonItem(src_inst->GetID(), src_inst->GetCharges()); DeleteItemInInventory(EQ::invslot::slotCursor); @@ -2328,8 +2197,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv.GetItem(dst_slot_id), dst_slot_id); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit - // Step 8: Re-calc stats CalcBonuses(); ApplyWeaponsStance(); @@ -2431,104 +2298,6 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { } } -void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { - int16 from_slot_id = static_cast(move_in->from_slot); - int16 to_slot_id = static_cast(move_in->to_slot); - int16 move_amount = static_cast(move_in->number_in_stack); - - if(!m_inv[from_slot_id] && !m_inv[to_slot_id]) { return; } - - uint16 move_count = 0; - - if(m_inv[from_slot_id]) { move_count += m_inv[from_slot_id]->GetTotalItemCount(); } - if(to_slot_id != from_slot_id) { if(m_inv[to_slot_id]) { move_count += m_inv[to_slot_id]->GetTotalItemCount(); } } - - auto qspack = new ServerPacket(ServerOP_QSPlayerLogMoves, - sizeof(QSPlayerLogMove_Struct) + (sizeof(QSMoveItems_Struct) * move_count)); - QSPlayerLogMove_Struct* qsaudit = (QSPlayerLogMove_Struct*)qspack->pBuffer; - - qsaudit->char_id = character_id; - qsaudit->stack_size = move_amount; - qsaudit->char_count = move_count; - qsaudit->postaction = postaction_call; - qsaudit->from_slot = from_slot_id; - qsaudit->to_slot = to_slot_id; - - move_count = 0; - - const EQ::ItemInstance* from_inst = m_inv[postaction_call?to_slot_id:from_slot_id]; - - if(from_inst) { - qsaudit->items[move_count].from_slot = from_slot_id; - qsaudit->items[move_count].to_slot = to_slot_id; - qsaudit->items[move_count].item_id = from_inst->GetID(); - qsaudit->items[move_count].charges = from_inst->GetCharges(); - qsaudit->items[move_count].aug_1 = from_inst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = from_inst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = from_inst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = from_inst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = from_inst->GetAugmentItemID(5); - - if (from_inst->IsType(EQ::item::ItemClassBag)) { - for (uint8 bag_idx = EQ::invbag::SLOT_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { - const EQ::ItemInstance* from_baginst = from_inst->GetItem(bag_idx); - - if(from_baginst) { - qsaudit->items[move_count].from_slot = EQ::InventoryProfile::CalcSlotId(from_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = EQ::InventoryProfile::CalcSlotId(to_slot_id, bag_idx); - qsaudit->items[move_count].item_id = from_baginst->GetID(); - qsaudit->items[move_count].charges = from_baginst->GetCharges(); - qsaudit->items[move_count].aug_1 = from_baginst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = from_baginst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = from_baginst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = from_baginst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = from_baginst->GetAugmentItemID(5); - } - } - } - } - - if(to_slot_id != from_slot_id) { - const EQ::ItemInstance* to_inst = m_inv[postaction_call?from_slot_id:to_slot_id]; - - if(to_inst) { - qsaudit->items[move_count].from_slot = to_slot_id; - qsaudit->items[move_count].to_slot = from_slot_id; - qsaudit->items[move_count].item_id = to_inst->GetID(); - qsaudit->items[move_count].charges = to_inst->GetCharges(); - qsaudit->items[move_count].aug_1 = to_inst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = to_inst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = to_inst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = to_inst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = to_inst->GetAugmentItemID(5); - - if (to_inst->IsType(EQ::item::ItemClassBag)) { - for (uint8 bag_idx = EQ::invbag::SLOT_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { - const EQ::ItemInstance* to_baginst = to_inst->GetItem(bag_idx); - - if(to_baginst) { - qsaudit->items[move_count].from_slot = EQ::InventoryProfile::CalcSlotId(to_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = EQ::InventoryProfile::CalcSlotId(from_slot_id, bag_idx); - qsaudit->items[move_count].item_id = to_baginst->GetID(); - qsaudit->items[move_count].charges = to_baginst->GetCharges(); - qsaudit->items[move_count].aug_1 = to_baginst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = to_baginst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = to_baginst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = to_baginst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = to_baginst->GetAugmentItemID(5); - } - } - } - } - } - - if(move_count && worldserver.Connected()) { - worldserver.SendPacket(qspack); - } - - safe_delete(qspack); -} - void Client::DyeArmor(EQ::TintProfile* dye){ int16 slot=0; for (int i = EQ::textures::textureBegin; i <= EQ::textures::LastTintableTexture; i++) { diff --git a/zone/object.cpp b/zone/object.cpp index fb15edbad6..af4993dbeb 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -663,8 +663,6 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) sender->DeleteItemInInventory(EQ::invslot::slotCursor, 1, true); } - sender->DropItemQS(m_inst, true); - if (!m_ground_spawn) { safe_delete(m_inst); } diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index 8c52b4da78..58252e712b 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -43,16 +43,6 @@ void QueryServ::SendQuery(std::string Query) safe_delete(pack); } -void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc) -{ - std::string query = StringFormat( - "INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))", - Event_Type, - Character_ID, - Strings::Escape(Event_Desc).c_str()); - SendQuery(query); -} - void QueryServ::Connect() { m_connection = std::make_unique(Config->QSHost, Config->QSPort, false, "Zone", Config->SharedKey); diff --git a/zone/queryserv.h b/zone/queryserv.h index 4bdf1431f1..c7c3f4120a 100644 --- a/zone/queryserv.h +++ b/zone/queryserv.h @@ -37,7 +37,6 @@ class QueryServ { QueryServ(); ~QueryServ(); void SendQuery(std::string Query); - void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc); void Connect(); bool SendPacket(ServerPacket *pack); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index cd44abf8b0..c5293d5a55 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1811,12 +1811,6 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti } InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration)); - - /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ - std::string event_desc = StringFormat("Update :: qglobal:%s to qvalue:%s zoneid:%i instid:%i", varname, newvalue, initiator->GetZoneID(), initiator->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); - } } /* Inserts global variable into quest_globals table */ @@ -1903,12 +1897,6 @@ void QuestManager::delglobal(const char *varname) { else qgCharid=-qgNpcid; // make char id negative npc id as a fudge - /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ - std::string event_desc = StringFormat("Deleted :: qglobal:%s zoneid:%i instid:%i", varname, initiator->GetZoneID(), initiator->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); - } - std::string query = StringFormat("DELETE FROM quest_globals " "WHERE name = '%s' " "&& (npcid=0 || npcid=%i) " diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index 2b7f89ea98..0dfa3d8a6c 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -914,17 +914,6 @@ int ClientTaskState::IncrementDoneCount( parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, client, export_string, 0); } } - /* QS: PlayerLogTaskUpdates :: Update */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)) { - std::string event_desc = StringFormat( - "Task Stage Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", - info->task_id, - info->activity[activity_id].activity_id, - info->activity[activity_id].done_count, - client->GetZoneID(), - client->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, client->CharacterID(), event_desc); - } // If this task is now complete, the Completed tasks will have been // updated in UnlockActivities. Send the completed task list to the @@ -947,18 +936,6 @@ int ClientTaskState::IncrementDoneCount( RecordPlayerEventLogWithClient(client, PlayerEvent::TASK_COMPLETE, e); } - /* QS: PlayerLogTaskUpdates :: Complete */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)) { - std::string event_desc = StringFormat( - "Task Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", - info->task_id, - info->activity[activity_id].activity_id, - info->activity[activity_id].done_count, - client->GetZoneID(), - client->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, client->CharacterID(), event_desc); - } - client->SendTaskActivityComplete(info->task_id, 0, task_index, task_data->type, 0); // If Experience and/or cash rewards are set, reward them from the task even if reward_method is METHODQUEST diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index d0abc1b5f0..1181a5f9d8 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1172,13 +1172,6 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { ); } - /* QS: Player_Log_Trade_Skill_Events */ - if (RuleB(QueryServ, PlayerLogTradeSkillEvents)) { - - std::string event_desc = StringFormat("Success :: fashioned recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, CharacterID(), event_desc); - } - if (RuleB(TaskSystem, EnableTaskSystem)) { UpdateTasksForItem(TaskActivityType::TradeSkill, itr->first, itr->second); } @@ -1203,12 +1196,6 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { } - /* QS: Player_Log_Trade_Skill_Events */ - if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){ - std::string event_desc = StringFormat("Failed :: recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, CharacterID(), event_desc); - } - itr = spec->onfail.begin(); while(itr != spec->onfail.end()) { //should we check these arguments? diff --git a/zone/trading.cpp b/zone/trading.cpp index 5048990b2d..c6ea33c52e 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -322,38 +322,12 @@ void Client::ResetTrade() { void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, std::list* event_details) { if(tradingWith && tradingWith->IsClient()) { Client * other = tradingWith->CastToClient(); - PlayerLogTrade_Struct * qs_audit = nullptr; - bool qs_log = false; if(other) { LogTrading("Finishing trade with client [{}]", other->GetName()); AddMoneyToPP(other->trade->cp, other->trade->sp, other->trade->gp, other->trade->pp, true); - // step 0: pre-processing - // QS code - if (RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { - qs_audit = (PlayerLogTrade_Struct*)event_entry; - qs_log = true; - - if (finalizer) { - qs_audit->character_2_id = character_id; - - qs_audit->character_2_money.platinum = trade->pp; - qs_audit->character_2_money.gold = trade->gp; - qs_audit->character_2_money.silver = trade->sp; - qs_audit->character_2_money.copper = trade->cp; - } - else { - qs_audit->character_1_id = character_id; - - qs_audit->character_1_money.platinum = trade->pp; - qs_audit->character_1_money.gold = trade->gp; - qs_audit->character_1_money.silver = trade->sp; - qs_audit->character_1_money.copper = trade->cp; - } - } - // step 1: process bags for (int16 trade_slot = EQ::invslot::TRADE_BEGIN; trade_slot <= EQ::invslot::TRADE_END; ++trade_slot) { const EQ::ItemInstance* inst = m_inv[trade_slot]; @@ -372,55 +346,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (free_slot != INVALID_INDEX) { if (other->PutItemInInventory(free_slot, *inst, true)) { LogTrading("Container [{}] ([{}]) successfully transferred, deleting from trade slot", inst->GetItem()->Name, inst->GetItem()->ID); - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = inst->GetID(); - detail->charges = 1; - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items - const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); - - if (bag_inst) { - detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = EQ::InventoryProfile::CalcSlotId(trade_slot, sub_slot); - detail->to_character_id = other->CharacterID(); - detail->to_slot = EQ::InventoryProfile::CalcSlotId(free_slot, sub_slot); - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - } - } - } } else { LogTrading("Transfer of container [{}] ([{}]) to [{}] failed, returning to giver", inst->GetItem()->Name, inst->GetItem()->ID, other->GetName()); @@ -482,28 +407,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(partial_slot, *partial_inst, true)) { LogTrading("Partial stack [{}] ([{}]) successfully transferred, deleting [{}] charges from trade slot", inst->GetItem()->Name, inst->GetItem()->ID, (old_charges - inst->GetCharges())); - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = partial_slot; - detail->item_id = inst->GetID(); - detail->charges = (old_charges - inst->GetCharges()); - detail->aug_1 = 0; - detail->aug_2 = 0; - detail->aug_3 = 0; - detail->aug_4 = 0; - detail->aug_5 = 0; - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - } } else { LogTrading("Transfer of partial stack [{}] ([{}]) to [{}] failed, returning [{}] charges to trade slot", @@ -550,24 +453,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st inst->SetCharges(0); } - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = character_id; - detail->to_slot = bias_slot; - detail->item_id = inst->GetID(); - detail->charges = (old_charges - inst->GetCharges()); - detail->aug_1 = 0; - detail->aug_2 = 0; - detail->aug_3 = 0; - detail->aug_4 = 0; - detail->aug_5 = 0; - - event_details->push_back(detail); - } - if (inst->GetCharges() == 0) { DeleteItemInInventory(trade_slot); break; @@ -590,56 +475,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (free_slot != INVALID_INDEX) { if (other->PutItemInInventory(free_slot, *inst, true)) { LogTrading("Item [{}] ([{}]) successfully transferred, deleting from trade slot", inst->GetItem()->Name, inst->GetItem()->ID); - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = inst->GetID(); - detail->charges = (!inst->IsStackable() ? 1 : inst->GetCharges()); - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - - // 'step 3' should never really see containers..but, just in case... - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items - const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); - - if (bag_inst) { - detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - } - } - } } else { LogTrading("Transfer of Item [{}] ([{}]) to [{}] failed, returning to giver", inst->GetItem()->Name, inst->GetItem()->ID, other->GetName()); @@ -666,79 +501,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st else if(tradingWith && tradingWith->IsNPC()) { NPCHandinEventLog(trade, tradingWith->CastToNPC()); - QSPlayerLogHandin_Struct* qs_audit = nullptr; - bool qs_log = false; - - // QS code - if(RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { - // Currently provides only basic functionality. Calling method will also - // need to be modified before item returns and rewards can be logged. - qs_audit = (QSPlayerLogHandin_Struct*)event_entry; - qs_log = true; - - qs_audit->quest_id = 0; - qs_audit->char_id = character_id; - qs_audit->char_money.platinum = trade->pp; - qs_audit->char_money.gold = trade->gp; - qs_audit->char_money.silver = trade->sp; - qs_audit->char_money.copper = trade->cp; - qs_audit->char_count = 0; - qs_audit->npc_id = tradingWith->GetNPCTypeID(); - qs_audit->npc_money.platinum = 0; - qs_audit->npc_money.gold = 0; - qs_audit->npc_money.silver = 0; - qs_audit->npc_money.copper = 0; - qs_audit->npc_count = 0; - } - - if(qs_log) { // This can be incorporated below when revisions are made - for (int16 trade_slot = EQ::invslot::TRADE_BEGIN; trade_slot <= EQ::invslot::TRADE_NPC_END; ++trade_slot) { - const EQ::ItemInstance* trade_inst = m_inv[trade_slot]; - - if(trade_inst) { - auto detail = new QSHandinItems_Struct; - - strcpy(detail->action_type, "HANDIN"); - - detail->char_slot = trade_slot; - detail->item_id = trade_inst->GetID(); - detail->charges = (!trade_inst->IsStackable() ? 1 : trade_inst->GetCharges()); - detail->aug_1 = trade_inst->GetAugmentItemID(1); - detail->aug_2 = trade_inst->GetAugmentItemID(2); - detail->aug_3 = trade_inst->GetAugmentItemID(3); - detail->aug_4 = trade_inst->GetAugmentItemID(4); - detail->aug_5 = trade_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - qs_audit->char_count += detail->charges; - - if (trade_inst->IsClassBag()) { - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { - const EQ::ItemInstance* trade_baginst = trade_inst->GetItem(sub_slot); - - if(trade_baginst) { - detail = new QSHandinItems_Struct; - - strcpy(detail->action_type, "HANDIN"); - - detail->char_slot = EQ::InventoryProfile::CalcSlotId(trade_slot, sub_slot); - detail->item_id = trade_baginst->GetID(); - detail->charges = (!trade_inst->IsStackable() ? 1 : trade_inst->GetCharges()); - detail->aug_1 = trade_baginst->GetAugmentItemID(1); - detail->aug_2 = trade_baginst->GetAugmentItemID(2); - detail->aug_3 = trade_baginst->GetAugmentItemID(3); - detail->aug_4 = trade_baginst->GetAugmentItemID(4); - detail->aug_5 = trade_baginst->GetAugmentItemID(5); - - event_details->push_back(detail); - qs_audit->char_count += detail->charges; - } - } - } - } - } - } - bool quest_npc = false; if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE)) { // This is a quest NPC diff --git a/zone/zoning.cpp b/zone/zoning.cpp index a02ab943a4..d515ff168a 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -489,12 +489,6 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc SendLogoutPackets(); - /* QS: PlayerLogZone */ - if (RuleB(QueryServ, PlayerLogZone)){ - std::string event_desc = StringFormat("Zoning :: zoneid:%u instid:%u x:%4.2f y:%4.2f z:%4.2f h:%4.2f zonemode:%d from zoneid:%u instid:%i", zone_id, instance_id, dest_x, dest_y, dest_z, dest_h, zone_mode, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Zoning, CharacterID(), event_desc); - } - /* Dont clear aggro until the zone is successful */ entity_list.RemoveFromHateLists(this); From 92eee2b8c4a81da606a88f395e5012917f416782 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 04:15:23 -0600 Subject: [PATCH 38/42] Update database.cpp --- common/database.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4ecfbb91ee..0d40b4a1a1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2199,12 +2199,9 @@ void Database::ClearBuyerDetails() uint64_t Database::GetNextTableId(const std::string &table_name) { auto results = QueryDatabase(fmt::format("SHOW TABLE STATUS LIKE '{}'", table_name)); - for (auto row : results) { - for ( - int row_index = 0; - row_index < results.ColumnCount(); - row_index++ - ) { + + for (auto row: results) { + for (int row_index = 0; row_index < results.ColumnCount(); row_index++) { std::string field_name = Strings::ToLower(results.FieldName(row_index)); if (field_name == "auto_increment") { std::string value = row[row_index] ? row[row_index] : "null"; From d94fe7ca2160918f1dd801200d3abd13e1c69b59 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 04:27:22 -0600 Subject: [PATCH 39/42] Simplify ProcessBatchQueue --- common/events/player_event_logs.cpp | 108 +++++++++++----------------- 1 file changed, 40 insertions(+), 68 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 437c677e27..586c74bff0 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -141,16 +141,25 @@ void PlayerEventLogs::ProcessBatchQueue() BenchTimer benchmark; EtlQueues etl_queues{}; - etl_queues.trade.reserve(counter[PlayerEvent::TRADE] ? counter[PlayerEvent::TRADE] : 0); - etl_queues.speech.reserve(counter[PlayerEvent::SPEECH] ? counter[PlayerEvent::SPEECH] : 0); - etl_queues.loot_items.reserve(counter[PlayerEvent::LOOT_ITEM] ? counter[PlayerEvent::LOOT_ITEM] : 0); - etl_queues.killed_npc.reserve(counter[PlayerEvent::KILLED_NPC] ? counter[PlayerEvent::KILLED_NPC] : 0); - etl_queues.npc_handin.reserve(counter[PlayerEvent::NPC_HANDIN] ? counter[PlayerEvent::NPC_HANDIN] : 0); - etl_queues.aa_purchase.reserve(counter[PlayerEvent::AA_PURCHASE] ? counter[PlayerEvent::AA_PURCHASE] : 0); - etl_queues.merchant_sell.reserve(counter[PlayerEvent::MERCHANT_SELL] ? counter[PlayerEvent::MERCHANT_SELL] : 0); - etl_queues.killed_raid_npc.reserve(counter[PlayerEvent::KILLED_RAID_NPC] ? counter[PlayerEvent::KILLED_RAID_NPC] : 0); - etl_queues.killed_named_npc.reserve(counter[PlayerEvent::KILLED_NAMED_NPC] ? counter[PlayerEvent::KILLED_NAMED_NPC] : 0); - etl_queues.merchant_purchase.reserve(counter[PlayerEvent::MERCHANT_PURCHASE] ? counter[PlayerEvent::MERCHANT_PURCHASE] : 0); + for (const auto& [type, count] : counter) { + if (count > 0) { + switch (type) { + case PlayerEvent::TRADE: etl_queues.trade.reserve(count); break; + case PlayerEvent::SPEECH: etl_queues.speech.reserve(count); break; + case PlayerEvent::LOOT_ITEM: etl_queues.loot_items.reserve(count); break; + case PlayerEvent::KILLED_NPC: etl_queues.killed_npc.reserve(count); break; + case PlayerEvent::NPC_HANDIN: etl_queues.npc_handin.reserve(count); break; + case PlayerEvent::AA_PURCHASE: etl_queues.aa_purchase.reserve(count); break; + case PlayerEvent::MERCHANT_SELL: etl_queues.merchant_sell.reserve(count); break; + case PlayerEvent::KILLED_RAID_NPC: etl_queues.killed_raid_npc.reserve(count); break; + case PlayerEvent::KILLED_NAMED_NPC: etl_queues.killed_named_npc.reserve(count); break; + case PlayerEvent::MERCHANT_PURCHASE: etl_queues.merchant_purchase.reserve(count); break; + default: + LogPlayerEvents("Unknown event type [{}]", type); + break; + } + } + } for (auto &r:m_record_batch_queue) { if (m_settings[r.event_type_id].etl_enabled) { @@ -548,67 +557,30 @@ void PlayerEventLogs::ProcessBatchQueue() } } - // flush many - PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); - - // flush detailed tables - if (!etl_queues.loot_items.empty()) { - PlayerEventLootItemsRepository::InsertMany(*m_database, etl_queues.loot_items); - etl_queues.loot_items.clear(); - } - - if (!etl_queues.merchant_sell.empty()) { - PlayerEventMerchantSellRepository::InsertMany(*m_database, etl_queues.merchant_sell); - etl_queues.merchant_sell.clear(); - } - - if (!etl_queues.merchant_purchase.empty()) { - PlayerEventMerchantPurchaseRepository::InsertMany(*m_database, etl_queues.merchant_purchase); - etl_queues.merchant_purchase.clear(); - } - - if (!etl_queues.npc_handin.empty()) { - PlayerEventNpcHandinRepository::InsertMany(*m_database, etl_queues.npc_handin); - etl_queues.npc_handin.clear(); - if (!etl_queues.npc_handin_entries.empty()) { - PlayerEventNpcHandinEntriesRepository::InsertMany(*m_database, etl_queues.npc_handin_entries); - etl_queues.npc_handin_entries.clear(); - } - } - - if (!etl_queues.trade.empty()) { - PlayerEventTradeRepository::InsertMany(*m_database, etl_queues.trade); - etl_queues.trade.clear(); - if (!etl_queues.trade_entries.empty()) { - PlayerEventTradeEntriesRepository::InsertMany(*m_database, etl_queues.trade_entries); - etl_queues.trade_entries.clear(); + // Helper to flush and clear queues + auto flush_queue = [&](auto insert_many, auto& queue) { + if (!queue.empty()) { + insert_many(*m_database, queue); + queue.clear(); } - } - - if (!etl_queues.speech.empty()) { - PlayerEventSpeechRepository::InsertMany(*m_database, etl_queues.speech); - etl_queues.speech.clear(); - } - - if (!etl_queues.killed_npc.empty()) { - PlayerEventKilledNpcRepository::InsertMany(*m_database, etl_queues.killed_npc); - etl_queues.killed_npc.clear(); - } - - if (!etl_queues.killed_named_npc.empty()) { - PlayerEventKilledNamedNpcRepository::InsertMany(*m_database, etl_queues.killed_named_npc); - etl_queues.killed_named_npc.clear(); - } + }; - if (!etl_queues.killed_raid_npc.empty()) { - PlayerEventKilledRaidNpcRepository::InsertMany(*m_database, etl_queues.killed_raid_npc); - etl_queues.killed_raid_npc.clear(); - } + // flush many + PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); - if (!etl_queues.aa_purchase.empty()) { - PlayerEventAaPurchaseRepository::InsertMany(*m_database, etl_queues.aa_purchase); - etl_queues.aa_purchase.clear(); - } + // flush etl queues + flush_queue(PlayerEventLootItemsRepository::InsertMany, etl_queues.loot_items); + flush_queue(PlayerEventMerchantSellRepository::InsertMany, etl_queues.merchant_sell); + flush_queue(PlayerEventMerchantPurchaseRepository::InsertMany, etl_queues.merchant_purchase); + flush_queue(PlayerEventNpcHandinRepository::InsertMany, etl_queues.npc_handin); + flush_queue(PlayerEventNpcHandinEntriesRepository::InsertMany, etl_queues.npc_handin_entries); + flush_queue(PlayerEventTradeRepository::InsertMany, etl_queues.trade); + flush_queue(PlayerEventTradeEntriesRepository::InsertMany, etl_queues.trade_entries); + flush_queue(PlayerEventSpeechRepository::InsertMany, etl_queues.speech); + flush_queue(PlayerEventKilledNpcRepository::InsertMany, etl_queues.killed_npc); + flush_queue(PlayerEventKilledNamedNpcRepository::InsertMany, etl_queues.killed_named_npc); + flush_queue(PlayerEventKilledRaidNpcRepository::InsertMany, etl_queues.killed_raid_npc); + flush_queue(PlayerEventAaPurchaseRepository::InsertMany, etl_queues.aa_purchase); LogPlayerEventsDetail( "Processing batch player event log queue of [{}] took [{}]", From 0495c43f4113b0a0302c38ff0e55f27f8e689e51 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 04:35:15 -0600 Subject: [PATCH 40/42] Simplify PorcessBatchQueue --- common/events/player_event_logs.cpp | 695 +++++++++++----------------- 1 file changed, 279 insertions(+), 416 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 586c74bff0..f49f635218 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -68,7 +68,7 @@ void PlayerEventLogs::Init() if (is_missing_in_database && is_implemented && !is_deprecated) { LogInfo("[New] PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i); - auto c = PlayerEventLogSettingsRepository::NewEntity(); + auto c = PlayerEventLogSettingsRepository::NewEntity(); c.id = i; c.event_name = PlayerEvent::EventName[i]; c.event_enabled = m_settings[i].event_enabled; @@ -134,431 +134,281 @@ void PlayerEventLogs::ProcessBatchQueue() static std::map counter{}; counter.clear(); - for (auto const& e: m_record_batch_queue) { + for (auto const &e: m_record_batch_queue) { counter[e.event_type_id]++; } BenchTimer benchmark; EtlQueues etl_queues{}; - for (const auto& [type, count] : counter) { + for (const auto &[type, count]: counter) { if (count > 0) { switch (type) { - case PlayerEvent::TRADE: etl_queues.trade.reserve(count); break; - case PlayerEvent::SPEECH: etl_queues.speech.reserve(count); break; - case PlayerEvent::LOOT_ITEM: etl_queues.loot_items.reserve(count); break; - case PlayerEvent::KILLED_NPC: etl_queues.killed_npc.reserve(count); break; - case PlayerEvent::NPC_HANDIN: etl_queues.npc_handin.reserve(count); break; - case PlayerEvent::AA_PURCHASE: etl_queues.aa_purchase.reserve(count); break; - case PlayerEvent::MERCHANT_SELL: etl_queues.merchant_sell.reserve(count); break; - case PlayerEvent::KILLED_RAID_NPC: etl_queues.killed_raid_npc.reserve(count); break; - case PlayerEvent::KILLED_NAMED_NPC: etl_queues.killed_named_npc.reserve(count); break; - case PlayerEvent::MERCHANT_PURCHASE: etl_queues.merchant_purchase.reserve(count); break; - default: - LogPlayerEvents("Unknown event type [{}]", type); + case PlayerEvent::TRADE: + etl_queues.trade.reserve(count); break; - } - } - } - - for (auto &r:m_record_batch_queue) { - if (m_settings[r.event_type_id].etl_enabled) { - switch (r.event_type_id) { - case PlayerEvent::EventType::LOOT_ITEM: { - PlayerEvent::LootItemEvent in{}; - PlayerEventLootItemsRepository::PlayerEventLootItems out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.charges = in.charges; - out.corpse_name = in.corpse_name; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.augment_1_id = in.augment_1_id; - out.augment_2_id = in.augment_2_id; - out.augment_3_id = in.augment_3_id; - out.augment_4_id = in.augment_4_id; - out.augment_5_id = in.augment_5_id; - out.augment_6_id = in.augment_6_id; - out.npc_id = in.npc_id; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::LOOT_ITEM)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id; - m_etl_settings.at(PlayerEvent::EventType::LOOT_ITEM).next_id++; - } - - etl_queues.loot_items.push_back(out); + case PlayerEvent::SPEECH: + etl_queues.speech.reserve(count); break; - } - case PlayerEvent::EventType::MERCHANT_SELL: { - PlayerEvent::MerchantSellEvent in{}; - PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.merchant_name = in.merchant_name; - out.merchant_type = in.merchant_type; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.charges = in.charges; - out.cost = in.cost; - out.alternate_currency_id = in.alternate_currency_id; - out.player_money_balance = in.player_money_balance; - out.player_currency_balance = in.player_currency_balance; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_SELL)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id; - m_etl_settings.at(PlayerEvent::EventType::MERCHANT_SELL).next_id++; - } - - etl_queues.merchant_sell.push_back(out); + case PlayerEvent::LOOT_ITEM: + etl_queues.loot_items.reserve(count); break; - } - case PlayerEvent::EventType::MERCHANT_PURCHASE: { - PlayerEvent::MerchantPurchaseEvent in{}; - PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.merchant_name = in.merchant_name; - out.merchant_type = in.merchant_type; - out.item_id = in.item_id; - out.item_name = in.item_name; - out.charges = in.charges; - out.cost = in.cost; - out.alternate_currency_id = in.alternate_currency_id; - out.player_money_balance = in.player_money_balance; - out.player_currency_balance = in.player_currency_balance; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::MERCHANT_PURCHASE)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id; - m_etl_settings.at(PlayerEvent::EventType::MERCHANT_PURCHASE).next_id++; - } - - etl_queues.merchant_purchase.push_back(out); + case PlayerEvent::KILLED_NPC: + etl_queues.killed_npc.reserve(count); break; - } - case PlayerEvent::EventType::NPC_HANDIN: { - PlayerEvent::HandinEvent in{}; - PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; - PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries out_entries{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.handin_copper = in.handin_money.copper; - out.handin_silver = in.handin_money.silver; - out.handin_gold = in.handin_money.gold; - out.handin_platinum = in.handin_money.platinum; - out.return_copper = in.return_money.copper; - out.return_silver = in.return_money.silver; - out.return_gold = in.return_money.gold; - out.return_platinum = in.return_money.platinum; - out.is_quest_handin = in.is_quest_handin; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::NPC_HANDIN)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id; - m_etl_settings.at(PlayerEvent::EventType::NPC_HANDIN).next_id++; - } - - if (!in.handin_items.empty()) { - etl_queues.npc_handin_entries.reserve(etl_queues.npc_handin_entries.size() + in.handin_items.size()); - for (auto const &i: in.handin_items) { - out_entries.charges = i.charges; - out_entries.evolve_amount = 0; - out_entries.evolve_level = 0; - out_entries.item_id = i.item_id; - out_entries.player_event_npc_handin_id = r.etl_table_id; - out_entries.type = 1; - out.created_at = r.created_at; - - if (!i.augment_ids.empty()) { - uint32 augments[6]{}; - for (int x = 0; x < i.augment_ids.size(); x++) { - augments[x] = i.augment_ids[x]; - } - out_entries.augment_1_id = augments[0]; - out_entries.augment_2_id = augments[1]; - out_entries.augment_3_id = augments[2]; - out_entries.augment_4_id = augments[3]; - out_entries.augment_5_id = augments[4]; - out_entries.augment_6_id = augments[5]; - } - etl_queues.npc_handin_entries.push_back(out_entries); - } - } - - if (!in.return_items.empty()) { - etl_queues.npc_handin_entries.reserve(etl_queues.npc_handin_entries.size() + in.return_items.size()); - for (auto const &i: in.handin_items) { - out_entries.charges = i.charges; - out_entries.evolve_amount = 0; - out_entries.evolve_level = 0; - out_entries.item_id = i.item_id; - out_entries.player_event_npc_handin_id = r.etl_table_id; - out_entries.type = 2; - out.created_at = r.created_at; - - if (!i.augment_ids.empty()) { - uint32 augments[6]{}; - for (int x = 0; x < i.augment_ids.size(); x++) { - augments[x] = i.augment_ids[x]; - } - out_entries.augment_1_id = augments[0]; - out_entries.augment_2_id = augments[1]; - out_entries.augment_3_id = augments[2]; - out_entries.augment_4_id = augments[3]; - out_entries.augment_5_id = augments[4]; - out_entries.augment_6_id = augments[5]; - } - etl_queues.npc_handin_entries.push_back(out_entries); - } - } - - etl_queues.npc_handin.push_back(out); + case PlayerEvent::NPC_HANDIN: + etl_queues.npc_handin.reserve(count); break; - } - case PlayerEvent::EventType::TRADE: { - PlayerEvent::TradeEvent in{}; - PlayerEventTradeRepository::PlayerEventTrade out{}; - PlayerEventTradeEntriesRepository::PlayerEventTradeEntries out_entries{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.char1_id = in.character_1_id; - out.char1_platinum = in.character_1_give_money.platinum; - out.char1_gold = in.character_1_give_money.gold; - out.char1_silver = in.character_1_give_money.silver; - out.char1_copper = in.character_1_give_money.copper; - out.char2_id = in.character_2_id; - out.char2_platinum = in.character_2_give_money.platinum; - out.char2_gold = in.character_2_give_money.gold; - out.char2_silver = in.character_2_give_money.silver; - out.char2_copper = in.character_2_give_money.copper; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::TRADE)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id; - m_etl_settings.at(PlayerEvent::EventType::TRADE).next_id++; - } - - if (!in.character_1_give_items.empty()) { - etl_queues.trade_entries.reserve(etl_queues.trade_entries.size() + in.character_1_give_items.size()); - for (auto const &i: in.character_1_give_items) { - out_entries.char_id = in.character_1_id; - out_entries.charges = i.charges; - out_entries.slot = i.slot; - out_entries.item_id = i.item_id; - out_entries.player_event_trade_id = r.etl_table_id; - out_entries.in_bag = i.in_bag; - out.created_at = r.created_at; - out_entries.augment_1_id = i.augment_1_id; - out_entries.augment_2_id = i.augment_2_id; - out_entries.augment_3_id = i.augment_3_id; - out_entries.augment_4_id = i.augment_4_id; - out_entries.augment_5_id = i.augment_5_id; - out_entries.augment_6_id = i.augment_6_id; - out_entries.created_at = r.created_at; - } - etl_queues.trade_entries.push_back(out_entries); - } - - if (!in.character_2_give_items.empty()) { - etl_queues.trade_entries.reserve(etl_queues.trade_entries.size() + in.character_2_give_items.size()); - for (auto const &i: in.character_2_give_items) { - out_entries.char_id = in.character_2_id; - out_entries.charges = i.charges; - out_entries.slot = i.slot; - out_entries.item_id = i.item_id; - out_entries.player_event_trade_id = r.etl_table_id; - out_entries.in_bag = i.in_bag; - out.created_at = r.created_at; - out_entries.augment_1_id = i.augment_1_id; - out_entries.augment_2_id = i.augment_2_id; - out_entries.augment_3_id = i.augment_3_id; - out_entries.augment_4_id = i.augment_4_id; - out_entries.augment_5_id = i.augment_5_id; - out_entries.augment_6_id = i.augment_6_id; - out_entries.created_at = r.created_at; - } - etl_queues.trade_entries.push_back(out_entries); - } - - etl_queues.trade.push_back(out); + case PlayerEvent::AA_PURCHASE: + etl_queues.aa_purchase.reserve(count); break; - } - case PlayerEvent::EventType::SPEECH: { - PlayerEvent::PlayerSpeech in{}; - PlayerEventSpeechRepository::PlayerEventSpeech out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.from_char_id = in.from; - out.to_char_id = in.to; - out.type = in.type; - out.min_status = in.min_status; - out.message = in.message; - out.guild_id = in.guild_id; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::SPEECH)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id; - m_etl_settings.at(PlayerEvent::EventType::SPEECH).next_id++; - } - - etl_queues.speech.push_back(out); + case PlayerEvent::MERCHANT_SELL: + etl_queues.merchant_sell.reserve(count); break; - } - case PlayerEvent::EventType::KILLED_NPC: { - PlayerEvent::KilledNPCEvent in{}; - PlayerEventKilledNpcRepository::PlayerEventKilledNpc out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.combat_time_seconds = in.combat_time_seconds; - out.total_damage_per_second_taken = in.total_damage_per_second_taken; - out.total_heal_per_second_taken = in.total_heal_per_second_taken; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NPC)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id; - m_etl_settings.at(PlayerEvent::EventType::KILLED_NPC).next_id++; - } - - etl_queues.killed_npc.push_back(out); + case PlayerEvent::KILLED_RAID_NPC: + etl_queues.killed_raid_npc.reserve(count); break; - } - case PlayerEvent::EventType::KILLED_NAMED_NPC: { - PlayerEvent::KilledNPCEvent in{}; - PlayerEventKilledNamedNpcRepository::PlayerEventKilledNamedNpc out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.combat_time_seconds = in.combat_time_seconds; - out.total_damage_per_second_taken = in.total_damage_per_second_taken; - out.total_heal_per_second_taken = in.total_heal_per_second_taken; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_NAMED_NPC)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id; - m_etl_settings.at(PlayerEvent::EventType::KILLED_NAMED_NPC).next_id++; - } - - etl_queues.killed_named_npc.push_back(out); + case PlayerEvent::KILLED_NAMED_NPC: + etl_queues.killed_named_npc.reserve(count); break; - } - case PlayerEvent::EventType::KILLED_RAID_NPC: { - PlayerEvent::KilledNPCEvent in{}; - PlayerEventKilledRaidNpcRepository::PlayerEventKilledRaidNpc out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } - - out.npc_id = in.npc_id; - out.npc_name = in.npc_name; - out.combat_time_seconds = in.combat_time_seconds; - out.total_damage_per_second_taken = in.total_damage_per_second_taken; - out.total_heal_per_second_taken = in.total_heal_per_second_taken; - out.created_at = r.created_at; - - if (m_etl_settings.contains(PlayerEvent::EventType::KILLED_RAID_NPC)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id; - m_etl_settings.at(PlayerEvent::EventType::KILLED_RAID_NPC).next_id++; - } - - etl_queues.killed_raid_npc.push_back(out); + case PlayerEvent::MERCHANT_PURCHASE: + etl_queues.merchant_purchase.reserve(count); break; - } - case PlayerEvent::EventType::AA_PURCHASE: { - PlayerEvent::AAPurchasedEvent in{}; - PlayerEventAaPurchaseRepository::PlayerEventAaPurchase out{}; - - { - std::stringstream ss; - ss << r.event_data; - cereal::JSONInputArchive ar(ss); - in.serialize(ar); - } + default: + LogPlayerEvents("Unknown event type [{}]", type); + break; + } + } + } - out.aa_ability_id = in.aa_id; - out.cost = in.aa_cost; - out.previous_id = in.aa_previous_id; - out.next_id = in.aa_next_id; - out.created_at = r.created_at; + // Helper to deserialize event data + auto Deserialize = [](const std::string &data, auto &out) { + std::stringstream ss(data); + cereal::JSONInputArchive ar(ss); + out.serialize(ar); + }; - if (m_etl_settings.contains(PlayerEvent::EventType::AA_PURCHASE)) { - r.etl_table_id = m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id; - m_etl_settings.at(PlayerEvent::EventType::AA_PURCHASE).next_id++; - } + // Helper to assign ETL table ID + auto AssignEtlId = [&]( + PlayerEventLogsRepository::PlayerEventLogs &r, + PlayerEvent::EventType type + ) { + if (m_etl_settings.contains(type)) { + r.etl_table_id = m_etl_settings.at(type).next_id++; + } + }; - etl_queues.aa_purchase.push_back(out); - break; - } - default: { - LogError("Non-Implemented ETL routing [{}]", r.event_type_id); - } + // Define event processors + std::unordered_map> event_processors = { + { + PlayerEvent::EventType::LOOT_ITEM, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::LootItemEvent in{}; + PlayerEventLootItemsRepository::PlayerEventLootItems out{}; + Deserialize(r.event_data, in); + + out.charges = in.charges; + out.corpse_name = in.corpse_name; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.augment_1_id = in.augment_1_id; + out.augment_2_id = in.augment_2_id; + out.augment_3_id = in.augment_3_id; + out.augment_4_id = in.augment_4_id; + out.augment_5_id = in.augment_5_id; + out.augment_6_id = in.augment_6_id; + out.npc_id = in.npc_id; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::LOOT_ITEM); + etl_queues.loot_items.push_back(out); + } + }, + { + PlayerEvent::EventType::MERCHANT_SELL, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::MerchantSellEvent in{}; + PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::MERCHANT_SELL); + etl_queues.merchant_sell.push_back(out); + }}, + { + PlayerEvent::EventType::MERCHANT_PURCHASE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::MerchantPurchaseEvent in{}; + PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::MERCHANT_PURCHASE); + etl_queues.merchant_purchase.push_back(out); + }}, + { + PlayerEvent::EventType::NPC_HANDIN, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::HandinEvent in{}; + PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.handin_copper = in.handin_money.copper; + out.handin_silver = in.handin_money.silver; + out.handin_gold = in.handin_money.gold; + out.handin_platinum = in.handin_money.platinum; + out.return_copper = in.return_money.copper; + out.return_silver = in.return_money.silver; + out.return_gold = in.return_money.gold; + out.return_platinum = in.return_money.platinum; + out.is_quest_handin = in.is_quest_handin; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::NPC_HANDIN); + etl_queues.npc_handin.push_back(out); + + for (const auto &i: in.handin_items) { + PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries entry{}; + entry.player_event_npc_handin_id = r.etl_table_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.type = 1; + etl_queues.npc_handin_entries.push_back(entry); + } + for (const auto &i: in.return_items) { + PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries entry{}; + entry.player_event_npc_handin_id = r.etl_table_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.type = 2; + etl_queues.npc_handin_entries.push_back(entry); + } + }}, + { + PlayerEvent::EventType::TRADE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::TradeEvent in{}; + PlayerEventTradeRepository::PlayerEventTrade out{}; + Deserialize(r.event_data, in); + + out.char1_id = in.character_1_id; + out.char2_id = in.character_2_id; + out.char1_copper = in.character_1_give_money.copper; + out.char1_silver = in.character_1_give_money.silver; + out.char1_gold = in.character_1_give_money.gold; + out.char1_platinum = in.character_1_give_money.platinum; + out.char2_copper = in.character_2_give_money.copper; + out.char2_silver = in.character_2_give_money.silver; + out.char2_gold = in.character_2_give_money.gold; + out.char2_platinum = in.character_2_give_money.platinum; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::TRADE); + etl_queues.trade.push_back(out); + + for (const auto &i: in.character_1_give_items) { + PlayerEventTradeEntriesRepository::PlayerEventTradeEntries entry{}; + entry.player_event_trade_id = r.etl_table_id; + entry.char_id = in.character_1_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.slot = i.slot; + etl_queues.trade_entries.push_back(entry); + } + for (const auto &i: in.character_2_give_items) { + PlayerEventTradeEntriesRepository::PlayerEventTradeEntries entry{}; + entry.player_event_trade_id = r.etl_table_id; + entry.char_id = in.character_2_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.slot = i.slot; + etl_queues.trade_entries.push_back(entry); + } + }}, + { + PlayerEvent::EventType::SPEECH, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::PlayerSpeech in{}; + PlayerEventSpeechRepository::PlayerEventSpeech out{}; + Deserialize(r.event_data, in); + + out.from_char_id = in.from; + out.to_char_id = in.to; + out.type = in.type; + out.min_status = in.min_status; + out.message = in.message; + out.guild_id = in.guild_id; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::SPEECH); + etl_queues.speech.push_back(out); + }}, + { + PlayerEvent::EventType::KILLED_NPC, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledNpcRepository::PlayerEventKilledNpc out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::KILLED_NPC); + etl_queues.killed_npc.push_back(out); + }}, + { + PlayerEvent::EventType::AA_PURCHASE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::AAPurchasedEvent in{}; + PlayerEventAaPurchaseRepository::PlayerEventAaPurchase out{}; + Deserialize(r.event_data, in); + + out.aa_ability_id = in.aa_id; + out.cost = in.aa_cost; + out.previous_id = in.aa_previous_id; + out.next_id = in.aa_next_id; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::AA_PURCHASE); + etl_queues.aa_purchase.push_back(out); + }}, + }; + + // Process the batch queue + for (auto &r: m_record_batch_queue) { + if (m_settings[r.event_type_id].etl_enabled) { + auto it = event_processors.find(static_cast(r.event_type_id)); + if (it != event_processors.end()) { + it->second(r); // Call the appropriate lambda + } + else { + LogError("Non-Implemented ETL routing [{}]", r.event_type_id); } } } // Helper to flush and clear queues - auto flush_queue = [&](auto insert_many, auto& queue) { + auto flush_queue = [&](auto insert_many, auto &queue) { if (!queue.empty()) { insert_many(*m_database, queue); queue.clear(); @@ -1059,7 +909,8 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe // general process function, used in world or QS depending on rule Logging:PlayerEventsQSProcess void PlayerEventLogs::Process() { - if (m_process_batch_events_timer.Check() || m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) { + if (m_process_batch_events_timer.Check() || + m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) { ProcessBatchQueue(); } @@ -1082,7 +933,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::MERCHANT_SELL: { @@ -1090,7 +942,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::MERCHANT_PURCHASE: { @@ -1098,7 +951,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::NPC_HANDIN: { @@ -1106,12 +960,14 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere( *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::TRADE: { @@ -1119,12 +975,14 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); deleted_count += PlayerEventTradeEntriesRepository::DeleteWhere( *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::SPEECH: { @@ -1132,7 +990,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::KILLED_NPC: { @@ -1140,7 +999,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::KILLED_NAMED_NPC: { @@ -1148,7 +1008,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::KILLED_RAID_NPC: { @@ -1156,7 +1017,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } case PlayerEvent::AA_PURCHASE: { @@ -1164,7 +1026,8 @@ void PlayerEventLogs::ProcessRetentionTruncation() *m_database, fmt::format( "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days)); + m_settings[i].retention_days + )); break; } default: { @@ -1276,8 +1139,8 @@ void PlayerEventLogs::SetSettingsDefaults() void PlayerEventLogs::LoadEtlIds() { auto e = [&](auto p) -> bool { - for (PlayerEventLogSettingsRepository::PlayerEventLogSettings const& c : m_settings) { - if(c.id == p) { + for (PlayerEventLogSettingsRepository::PlayerEventLogSettings const &c: m_settings) { + if (c.id == p) { return c.etl_enabled ? true : false; } } @@ -1370,7 +1233,7 @@ void PlayerEventLogs::LoadEtlIds() } }; - for (auto &e : m_etl_settings) { + for (auto &e: m_etl_settings) { LogPlayerEventsDetail( "ETL Settings [{}] Enabled [{}] Table [{}] NextId [{}]", PlayerEvent::EventName[e.first], From 976be4e6685374fd2c73d803ada76740c9a1047d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 04:41:00 -0600 Subject: [PATCH 41/42] Simplify event truncation --- common/events/player_event_logs.cpp | 182 ++++++++++------------------ 1 file changed, 67 insertions(+), 115 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index f49f635218..22206a1c1a 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -923,129 +923,81 @@ void PlayerEventLogs::ProcessRetentionTruncation() { LogPlayerEvents("Running truncation"); + // Map of repository-specific deletion functions + std::unordered_map> repository_deleters = { + {PlayerEvent::LOOT_ITEM, [&](const std::string& condition) { + return PlayerEventLootItemsRepository::DeleteWhere(*m_database, condition); + }}, + {PlayerEvent::MERCHANT_SELL, [&](const std::string& condition) { + return PlayerEventMerchantSellRepository::DeleteWhere(*m_database, condition); + }}, + {PlayerEvent::MERCHANT_PURCHASE, [&](const std::string& condition) { + return PlayerEventMerchantPurchaseRepository::DeleteWhere(*m_database, condition); + }}, + {PlayerEvent::NPC_HANDIN, [&](const std::string& condition) { + uint32 deleted_count = PlayerEventNpcHandinRepository::DeleteWhere(*m_database, condition); + deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere(*m_database, condition); + return deleted_count; + }}, + {PlayerEvent::TRADE, [&](const std::string& condition) { + uint32 deleted_count = PlayerEventTradeRepository::DeleteWhere(*m_database, condition); + deleted_count += PlayerEventTradeEntriesRepository::DeleteWhere(*m_database, condition); + return deleted_count; + }}, + {PlayerEvent::SPEECH, [&](const std::string& condition) { + return PlayerEventSpeechRepository::DeleteWhere(*m_database, condition); + }}, + {PlayerEvent::KILLED_NPC, [&](const std::string& condition) { + return PlayerEventKilledNpcRepository::DeleteWhere(*m_database, condition); + }}, + {PlayerEvent::KILLED_NAMED_NPC, [&](const std::string& condition) { + return PlayerEventKilledNamedNpcRepository::DeleteWhere(*m_database, condition); + }}, + {PlayerEvent::KILLED_RAID_NPC, [&](const std::string& condition) { + return PlayerEventKilledRaidNpcRepository::DeleteWhere(*m_database, condition); + }}, + {PlayerEvent::AA_PURCHASE, [&](const std::string& condition) { + return PlayerEventAaPurchaseRepository::DeleteWhere(*m_database, condition); + }} + }; + for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { if (m_settings[i].retention_days > 0) { - uint32 deleted_count; + std::string condition = fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + m_settings[i].retention_days + ); + + // ETL if (m_settings[i].etl_enabled) { - switch (m_settings[i].id) { - case PlayerEvent::LOOT_ITEM: { - deleted_count = PlayerEventLootItemsRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::MERCHANT_SELL: { - deleted_count = PlayerEventMerchantSellRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::MERCHANT_PURCHASE: { - deleted_count = PlayerEventMerchantPurchaseRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::NPC_HANDIN: { - deleted_count = PlayerEventNpcHandinRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::TRADE: { - deleted_count = PlayerEventTradeRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - deleted_count += PlayerEventTradeEntriesRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::SPEECH: { - deleted_count = PlayerEventSpeechRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::KILLED_NPC: { - deleted_count = PlayerEventKilledNpcRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::KILLED_NAMED_NPC: { - deleted_count = PlayerEventKilledNamedNpcRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::KILLED_RAID_NPC: { - deleted_count = PlayerEventKilledRaidNpcRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - case PlayerEvent::AA_PURCHASE: { - deleted_count = PlayerEventAaPurchaseRepository::DeleteWhere( - *m_database, - fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - )); - break; - } - default: { - LogError("NonImplemented ETL Event Type [{}] ", static_cast(m_settings[i].id)); - } + uint32 deleted_count = 0; + auto it = repository_deleters.find(static_cast(m_settings[i].id)); + if (it != repository_deleters.end()) { + deleted_count = it->second(condition); + } else { + LogError("Non-Implemented ETL Event Type [{}]", static_cast(m_settings[i].id)); } - } - else { - deleted_count = PlayerEventLogsRepository::DeleteWhere( - *m_database, - fmt::format( - "event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)", + + if (deleted_count > 0) { + LogInfo( + "Truncated [{}] ETL events of type [{}] ({}) older than [{}] days", + deleted_count, + PlayerEvent::EventName[i], i, m_settings[i].retention_days - ) - ); + ); + } } + uint32 deleted_count = PlayerEventLogsRepository::DeleteWhere( + *m_database, + fmt::format( + "event_type_id = {} AND {}", + i, + condition + ) + ); + if (deleted_count > 0) { LogInfo( "Truncated [{}] events of type [{}] ({}) older than [{}] days", From a0340ebc7d46e698b56fcb7fd8da70900fd27c26 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Jan 2025 04:42:49 -0600 Subject: [PATCH 42/42] Build event truncation to bulk query by retention groups --- common/events/player_event_logs.cpp | 83 ++++++++++++++++------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 22206a1c1a..1e8be1eb57 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -961,52 +961,63 @@ void PlayerEventLogs::ProcessRetentionTruncation() }} }; + // Group event types by retention interval + std::unordered_map> retention_groups; for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { if (m_settings[i].retention_days > 0) { - std::string condition = fmt::format( - "created_at < (NOW() - INTERVAL {} DAY)", - m_settings[i].retention_days - ); + retention_groups[m_settings[i].retention_days].push_back(i); + } + } + + for (const auto& [retention_days, event_types] : retention_groups) { + std::string condition = fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + retention_days + ); - // ETL - if (m_settings[i].etl_enabled) { - uint32 deleted_count = 0; - auto it = repository_deleters.find(static_cast(m_settings[i].id)); + // Handle ETL deletions for each event type in the group + uint32 total_deleted_count = 0; + for (int event_type_id : event_types) { + if (m_settings[event_type_id].etl_enabled) { + auto it = repository_deleters.find(static_cast(m_settings[event_type_id].id)); if (it != repository_deleters.end()) { - deleted_count = it->second(condition); + total_deleted_count += it->second(condition); } else { - LogError("Non-Implemented ETL Event Type [{}]", static_cast(m_settings[i].id)); - } - - if (deleted_count > 0) { - LogInfo( - "Truncated [{}] ETL events of type [{}] ({}) older than [{}] days", - deleted_count, - PlayerEvent::EventName[i], - i, - m_settings[i].retention_days - ); + LogError("Non-Implemented ETL Event Type [{}]", static_cast(m_settings[event_type_id].id)); } } + } - uint32 deleted_count = PlayerEventLogsRepository::DeleteWhere( - *m_database, - fmt::format( - "event_type_id = {} AND {}", - i, - condition - ) + if (total_deleted_count > 0) { + LogInfo( + "Truncated [{}] ETL events older than [{}] days", + total_deleted_count, + retention_days ); + } - if (deleted_count > 0) { - LogInfo( - "Truncated [{}] events of type [{}] ({}) older than [{}] days", - deleted_count, - PlayerEvent::EventName[i], - i, - m_settings[i].retention_days - ); - } + // Batch deletion for player_event_logs + std::string event_type_ids = fmt::format( + "({})", + fmt::join(event_types, ", ") + ); + + uint32 deleted_count = PlayerEventLogsRepository::DeleteWhere( + *m_database, + fmt::format( + "event_type_id IN {} AND {}", + event_type_ids, + condition + ) + ); + + if (deleted_count > 0) { + LogInfo( + "Truncated [{}] events of types [{}] older than [{}] days", + deleted_count, + event_type_ids, + retention_days + ); } }