mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-01 15:46:37 +00:00
[Player Event Logs] Migrate and Deprecate QS Legacy Logging (#4542)
* First pass of player_event_loot_items * Second pass of player_event_loot_items * Third pass of player_event_loot_items * Example without RecordDetailEvent template * Cleanup the removal of the template * Fourth Pass Add retention for etl tables Rename tables/fields to etl nomenclature Combine database work to one atomic load * Reposition to reduce db tasks * Refactor etl processing for easier additions * Add merchant purchase event testing passed though appears that the event itself has a few bugs. Will fix them in another commit * Fix PlayerEventMerchantPurchase in client_packet.cpp * WIP - Handin * Handin Event added * Cleanup * All a rentention period of 0 days which deletes all current records. * Updates Cleanup and refactor a few items. * Cleanup and Formatting Cleanup and Formatting * Add etl for Playerevent::Trade PlayerEvent::Speech (new event to mirror functionality of qs_speech * Add etl for Playerevent::KilledNPC, KilledNamedNPC and KilledRaidNPC * Add etl for Playerevent::AA_purchase Add etl for Playerevent::AA_purchase * Cleanup before PR * Review comment updates. * Add world cli etl:settings to output a json on all player event details. * Add reserve for all etl_queues Correct a failed test case for improper next id for etl tables when table is first created. * Potential solution for a dedicated database connection for player events. * Simple thread for player_events. Likely there is a better way to do this. * Add zone to qs communications for recordplayerevents First pass of enabling zone to qs direct transport to allow for PlayerEvents to bypass world. * Cleanup a linux compile issue * Add augments to LOOT ITEM and DESTROY ITEM * Add augments to ITEMCREATION, FORAGESUCCESS, FISHSUCCESS, DESTROYITEM, LOOTITEM, DROPPEDITEM, TRADERPURCHASE, TRADERSELL, GUILDTRIBUTEDONATE and cleaned up the naming convention of augments * Formatting fixes * Swap out GetNextTableId * Statically load counter * Add counter.clear() since the counter is static * Upload optional QS conversion scripts * Remove all qs_tables and code referencing them * Update database.cpp * Simplify ProcessBatchQueue * Simplify PorcessBatchQueue * Simplify event truncation * Build event truncation to bulk query by retention groups * Post rebase * Update player_events.h * Fix build * Update npc.cpp * First pass of direct zone to qs sending for player events * Remove keepalive logic * Fix event ordering * Cleanup * Update player_event_logs.cpp * Wipe event data after ETL processed * Split up database connections, hot reload logs for QS * Load rules from database vs qs_database * Update player_event_logs.cpp * Hot toggle queryserv connect --------- Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
@@ -1081,51 +1081,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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1146,51 +1146,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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include "player_event_logs.h"
|
||||
#include "player_event_discord_formatter.h"
|
||||
#include <cereal/archives/json.hpp>
|
||||
|
||||
#include "../platform.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"
|
||||
#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
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -21,6 +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].etl_enabled = false;
|
||||
}
|
||||
|
||||
SetSettingsDefaults();
|
||||
@@ -65,6 +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.etl_enabled = false;
|
||||
settings_to_insert.emplace_back(c);
|
||||
}
|
||||
}
|
||||
@@ -73,6 +82,8 @@ void PlayerEventLogs::Init()
|
||||
PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert);
|
||||
}
|
||||
|
||||
LoadEtlIds();
|
||||
|
||||
bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld();
|
||||
bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ();
|
||||
|
||||
@@ -121,23 +132,319 @@ void PlayerEventLogs::ProcessBatchQueue()
|
||||
return;
|
||||
}
|
||||
|
||||
static std::map<uint32, uint32> counter{};
|
||||
counter.clear();
|
||||
for (auto const &e: m_record_batch_queue) {
|
||||
counter[e.event_type_id]++;
|
||||
}
|
||||
|
||||
BenchTimer benchmark;
|
||||
|
||||
EtlQueues etl_queues{};
|
||||
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:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to deserialize event data
|
||||
auto Deserialize = [](const std::string &data, auto &out) {
|
||||
std::stringstream ss(data);
|
||||
cereal::JSONInputArchive ar(ss);
|
||||
out.serialize(ar);
|
||||
};
|
||||
|
||||
// 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++;
|
||||
}
|
||||
};
|
||||
|
||||
// Define event processors
|
||||
std::unordered_map<PlayerEvent::EventType, std::function<void(PlayerEventLogsRepository::PlayerEventLogs &)>> 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<PlayerEvent::EventType>(r.event_type_id));
|
||||
if (it != event_processors.end()) {
|
||||
it->second(r); // Call the appropriate lambda
|
||||
r.event_data = "{}"; // Clear event data
|
||||
}
|
||||
else {
|
||||
LogError("Non-Implemented ETL routing [{}]", r.event_type_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to flush and clear queues
|
||||
auto flush_queue = [&](auto insert_many, auto &queue) {
|
||||
if (!queue.empty()) {
|
||||
insert_many(*m_database, queue);
|
||||
queue.clear();
|
||||
}
|
||||
};
|
||||
|
||||
// flush many
|
||||
PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue);
|
||||
LogPlayerEventsDetail(
|
||||
|
||||
// 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);
|
||||
|
||||
LogPlayerEvents(
|
||||
"Processing batch player event log queue of [{}] took [{}]",
|
||||
m_record_batch_queue.size(),
|
||||
benchmark.elapsed()
|
||||
);
|
||||
|
||||
// empty
|
||||
m_record_batch_queue = {};
|
||||
m_record_batch_queue.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();
|
||||
m_record_batch_queue.emplace_back(log);
|
||||
@@ -588,7 +895,7 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogInfo(
|
||||
LogPlayerEventsDetail(
|
||||
"Player event [{}] ({}) Discord formatter not implemented",
|
||||
e.player_event_log.event_type_name,
|
||||
e.player_event_log.event_type_id
|
||||
@@ -602,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();
|
||||
}
|
||||
|
||||
@@ -613,29 +921,115 @@ void PlayerEventLogs::Process()
|
||||
|
||||
void PlayerEventLogs::ProcessRetentionTruncation()
|
||||
{
|
||||
LogPlayerEvents("Running truncation");
|
||||
LogPlayerEventsDetail("Running truncation");
|
||||
|
||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
||||
// Map of repository-specific deletion functions
|
||||
std::unordered_map<PlayerEvent::EventType, std::function<uint32(const std::string &)>> 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);
|
||||
}}
|
||||
};
|
||||
|
||||
// Group event types by retention interval
|
||||
std::unordered_map<int, std::vector<int>> retention_groups;
|
||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
||||
if (m_settings[i].retention_days > 0) {
|
||||
int deleted_count = PlayerEventLogsRepository::DeleteWhere(
|
||||
*m_database,
|
||||
fmt::format(
|
||||
"event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)",
|
||||
i,
|
||||
m_settings[i].retention_days
|
||||
)
|
||||
);
|
||||
retention_groups[m_settings[i].retention_days].push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (deleted_count > 0) {
|
||||
LogInfo(
|
||||
"Truncated [{}] events of type [{}] ({}) older than [{}] days",
|
||||
deleted_count,
|
||||
PlayerEvent::EventName[i],
|
||||
i,
|
||||
m_settings[i].retention_days
|
||||
);
|
||||
for (const auto &[retention_days, event_types]: retention_groups) {
|
||||
std::string condition = fmt::format(
|
||||
"created_at < (NOW() - INTERVAL {} DAY)",
|
||||
retention_days
|
||||
);
|
||||
|
||||
// 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<PlayerEvent::EventType>(m_settings[event_type_id].id));
|
||||
if (it != repository_deleters.end()) {
|
||||
total_deleted_count += it->second(condition);
|
||||
}
|
||||
else {
|
||||
LogError("Non-Implemented ETL Event Type [{}]", static_cast<uint32>(m_settings[event_type_id].id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (total_deleted_count > 0) {
|
||||
LogInfo(
|
||||
"Truncated [{}] ETL events older than [{}] days",
|
||||
total_deleted_count,
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,8 +1102,143 @@ void PlayerEventLogs::SetSettingsDefaults()
|
||||
m_settings[PlayerEvent::PARCEL_DELETE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::BARTER_TRANSACTION].event_enabled = 1;
|
||||
m_settings[PlayerEvent::EVOLVE_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::SPEECH].event_enabled = 0;
|
||||
|
||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
||||
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
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 = e(PlayerEvent::LOOT_ITEM),
|
||||
.table_name = "player_event_loot_items",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventLootItemsRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::MERCHANT_SELL,
|
||||
{
|
||||
.enabled = e(PlayerEvent::MERCHANT_SELL),
|
||||
.table_name = "player_event_merchant_sell",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventMerchantSellRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::MERCHANT_PURCHASE,
|
||||
{
|
||||
.enabled = e(PlayerEvent::MERCHANT_PURCHASE),
|
||||
.table_name = "player_event_merchant_purchase",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventMerchantPurchaseRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::NPC_HANDIN,
|
||||
{
|
||||
.enabled = e(PlayerEvent::NPC_HANDIN),
|
||||
.table_name = "player_event_npc_handin",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventNpcHandinRepository::TableName()))
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::TRADE,
|
||||
{
|
||||
.enabled = e(PlayerEvent::TRADE),
|
||||
.table_name = "player_event_trade",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventTradeRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::SPEECH,
|
||||
{
|
||||
.enabled = e(PlayerEvent::SPEECH),
|
||||
.table_name = "player_event_speech",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventSpeechRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::KILLED_NPC,
|
||||
{
|
||||
.enabled = e(PlayerEvent::KILLED_NPC),
|
||||
.table_name = "player_event_killed_npc",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventKilledNpcRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::KILLED_NAMED_NPC,
|
||||
{
|
||||
.enabled = e(PlayerEvent::KILLED_NAMED_NPC),
|
||||
.table_name = "player_event_killed_named_npc",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventKilledNamedNpcRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::KILLED_RAID_NPC,
|
||||
{
|
||||
.enabled = e(PlayerEvent::KILLED_RAID_NPC),
|
||||
.table_name = "player_event_killed_raid_npc",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventKilledRaidNpcRepository::TableName()))
|
||||
}
|
||||
},
|
||||
{
|
||||
PlayerEvent::AA_PURCHASE,
|
||||
{
|
||||
.enabled = e(PlayerEvent::AA_PURCHASE),
|
||||
.table_name = "player_event_aa_purchase",
|
||||
.next_id = static_cast<int64>(m_database->GetNextTableId(PlayerEventAaPurchaseRepository::TableName()))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,38 @@
|
||||
#ifndef EQEMU_PLAYER_EVENT_LOGS_H
|
||||
#define EQEMU_PLAYER_EVENT_LOGS_H
|
||||
|
||||
#include "../repositories/player_event_log_settings_repository.h"
|
||||
#include "player_events.h"
|
||||
#include "../servertalk.h"
|
||||
#include "../repositories/player_event_logs_repository.h"
|
||||
#include "../timer.h"
|
||||
#include "../json/json_archive_single_line.h"
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <mutex>
|
||||
#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"
|
||||
#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_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"
|
||||
#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 {
|
||||
public:
|
||||
Database player_event_database{};
|
||||
|
||||
void Init();
|
||||
bool LoadDatabaseConnection();
|
||||
void ReloadSettings();
|
||||
void LoadEtlIds();
|
||||
PlayerEventLogs *SetDatabase(Database *db);
|
||||
bool ValidateDatabaseConnection();
|
||||
bool IsEventEnabled(PlayerEvent::EventType event);
|
||||
@@ -21,7 +40,7 @@ public:
|
||||
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
|
||||
@@ -59,7 +78,29 @@ public:
|
||||
std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id);
|
||||
|
||||
static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e);
|
||||
|
||||
struct EtlQueues {
|
||||
std::vector<PlayerEventLootItemsRepository::PlayerEventLootItems> loot_items;
|
||||
std::vector<PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase> merchant_purchase;
|
||||
std::vector<PlayerEventMerchantSellRepository::PlayerEventMerchantSell> merchant_sell;
|
||||
std::vector<PlayerEventNpcHandinRepository::PlayerEventNpcHandin> npc_handin;
|
||||
std::vector<PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries> npc_handin_entries;
|
||||
std::vector<PlayerEventTradeRepository::PlayerEventTrade> trade;
|
||||
std::vector<PlayerEventTradeEntriesRepository::PlayerEventTradeEntries> trade_entries;
|
||||
std::vector<PlayerEventSpeechRepository::PlayerEventSpeech> speech;
|
||||
std::vector<PlayerEventKilledNpcRepository::PlayerEventKilledNpc> killed_npc;
|
||||
std::vector<PlayerEventKilledNamedNpcRepository::PlayerEventKilledNamedNpc> killed_named_npc;
|
||||
std::vector<PlayerEventKilledRaidNpcRepository::PlayerEventKilledRaidNpc> killed_raid_npc;
|
||||
std::vector<PlayerEventAaPurchaseRepository::PlayerEventAaPurchase> aa_purchase;
|
||||
};
|
||||
|
||||
private:
|
||||
struct EtlSettings {
|
||||
bool enabled;
|
||||
std::string table_name;
|
||||
int64 next_id;
|
||||
};
|
||||
|
||||
Database *m_database; // reference to database
|
||||
PlayerEventLogSettingsRepository::PlayerEventLogSettings m_settings[PlayerEvent::EventType::MAX]{};
|
||||
|
||||
@@ -69,6 +110,8 @@ private:
|
||||
static std::unique_ptr<ServerPacket>
|
||||
BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e);
|
||||
|
||||
std::map<PlayerEvent::EventType, EtlSettings> m_etl_settings{};
|
||||
|
||||
// timers
|
||||
Timer m_process_batch_events_timer; // events processing timer
|
||||
Timer m_process_retention_truncation_timer; // timer for truncating events based on retention settings
|
||||
@@ -78,6 +121,9 @@ private:
|
||||
void ProcessBatchQueue();
|
||||
void ProcessRetentionTruncation();
|
||||
void SetSettingsDefaults();
|
||||
|
||||
public:
|
||||
std::map<PlayerEvent::EventType, EtlSettings> &GetEtlSettings() { return m_etl_settings;}
|
||||
};
|
||||
|
||||
extern PlayerEventLogs player_event_logs;
|
||||
|
||||
+267
-111
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "../types.h"
|
||||
#include "../rulesys.h"
|
||||
#include "../repositories/player_event_logs_repository.h"
|
||||
|
||||
namespace PlayerEvent {
|
||||
@@ -62,6 +63,7 @@ namespace PlayerEvent {
|
||||
PARCEL_RETRIEVE,
|
||||
PARCEL_DELETE,
|
||||
BARTER_TRANSACTION,
|
||||
SPEECH,
|
||||
EVOLVE_ITEM,
|
||||
MAX // dont remove
|
||||
};
|
||||
@@ -126,6 +128,7 @@ namespace PlayerEvent {
|
||||
"Parcel Item Retrieved",
|
||||
"Parcel Prune Routine",
|
||||
"Barter Transaction",
|
||||
"Player Speech",
|
||||
"Evolve Item Update"
|
||||
};
|
||||
|
||||
@@ -206,12 +209,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
|
||||
@@ -223,56 +226,57 @@ 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)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// used in Trade event
|
||||
struct TradeItem {
|
||||
int64 item_id;
|
||||
std::string item_name;
|
||||
int32 slot;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
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<class Archive>
|
||||
// void serialize(Archive &ar)
|
||||
// {
|
||||
// ar(
|
||||
// CEREAL_NVP(item_id),
|
||||
// CEREAL_NVP(item_name),
|
||||
// CEREAL_NVP(slot)
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
|
||||
// used in Trade event
|
||||
class TradeItemEntry {
|
||||
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<class Archive>
|
||||
void serialize(Archive &ar)
|
||||
@@ -280,12 +284,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)
|
||||
);
|
||||
}
|
||||
@@ -399,9 +411,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<class Archive>
|
||||
@@ -418,6 +430,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
|
||||
@@ -426,6 +444,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)
|
||||
);
|
||||
}
|
||||
@@ -433,6 +457,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
|
||||
@@ -441,6 +471,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)
|
||||
);
|
||||
}
|
||||
@@ -450,6 +486,13 @@ namespace PlayerEvent {
|
||||
uint32 item_id;
|
||||
std::string item_name;
|
||||
int16 charges;
|
||||
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;
|
||||
|
||||
// cereal
|
||||
@@ -459,8 +502,15 @@ namespace PlayerEvent {
|
||||
ar(
|
||||
CEREAL_NVP(item_id),
|
||||
CEREAL_NVP(item_name),
|
||||
CEREAL_NVP(reason),
|
||||
CEREAL_NVP(charges)
|
||||
CEREAL_NVP(charges),
|
||||
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)
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -503,6 +553,12 @@ namespace PlayerEvent {
|
||||
uint32 item_id;
|
||||
std::string item_name;
|
||||
int16 charges;
|
||||
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;
|
||||
|
||||
@@ -514,6 +570,12 @@ namespace PlayerEvent {
|
||||
CEREAL_NVP(item_id),
|
||||
CEREAL_NVP(item_name),
|
||||
CEREAL_NVP(charges),
|
||||
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)
|
||||
);
|
||||
@@ -726,6 +788,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;
|
||||
@@ -736,6 +804,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)
|
||||
@@ -791,6 +865,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;
|
||||
@@ -806,6 +886,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),
|
||||
@@ -819,6 +905,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;
|
||||
@@ -834,6 +926,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),
|
||||
@@ -964,8 +1062,16 @@ namespace PlayerEvent {
|
||||
};
|
||||
|
||||
struct GuildTributeDonateItem {
|
||||
uint32 item_id;
|
||||
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<class Archive>
|
||||
@@ -973,14 +1079,20 @@ 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)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
struct GuildTributeDonatePlat {
|
||||
uint32 plat;
|
||||
uint32 guild_favor;
|
||||
uint32 plat;
|
||||
uint32 guild_favor;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
@@ -995,15 +1107,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<class Archive>
|
||||
@@ -1011,31 +1123,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<class Archive>
|
||||
@@ -1043,33 +1155,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 item_id;
|
||||
uint32 quantity;
|
||||
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 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<class Archive>
|
||||
@@ -1077,18 +1189,18 @@ 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)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1140,30 +1252,74 @@ namespace PlayerEvent {
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
struct PlayerSpeech {
|
||||
std::string to;
|
||||
std::string from;
|
||||
uint32 guild_id;
|
||||
int16 min_status;
|
||||
uint32 type;
|
||||
std::string message;
|
||||
|
||||
template<class Archive>
|
||||
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
|
||||
|
||||
#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)
|
||||
|
||||
Reference in New Issue
Block a user