[Player Events] Zone Fetch Settings from QS if Enabled (#4915)

* [Player Events] Zone Fetch Settings from QS if Enabled

* Update zonelist.cpp

* Update zoneserver.cpp
This commit is contained in:
Chris Miles 2025-06-25 12:21:35 -05:00 committed by GitHub
parent f025e5741b
commit fb4d003e19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 151 additions and 24 deletions

View File

@ -536,6 +536,20 @@ std::string PlayerEventLogs::GetDiscordWebhookUrlFromEventType(int32_t event_typ
return ""; return "";
} }
void PlayerEventLogs::LoadPlayerEventSettingsFromQS(
const std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> &settings
)
{
for (const auto &e : settings) {
if (e.id >= PlayerEvent::MAX || e.id < 0) {
continue;
}
m_settings[e.id] = e;
}
LogInfo("Applied [{}] player event log settings from QS", settings.size());
}
// GM_COMMAND | [x] Implemented Formatter // GM_COMMAND | [x] Implemented Formatter
// ZONING | [x] Implemented Formatter // ZONING | [x] Implemented Formatter
// AA_GAIN | [x] Implemented Formatter // AA_GAIN | [x] Implemented Formatter

View File

@ -73,9 +73,11 @@ public:
return BuildPlayerEventPacket(c); return BuildPlayerEventPacket(c);
} }
[[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const; [[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings * GetSettings() const;
bool IsEventDiscordEnabled(int32_t event_type_id); bool IsEventDiscordEnabled(int32_t event_type_id);
std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id); std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id);
void LoadPlayerEventSettingsFromQS(const std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings>& settings);
static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e); static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e);

View File

@ -15,7 +15,7 @@
#include "../../database.h" #include "../../database.h"
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
#include <cereal/cereal.hpp>
class BasePlayerEventLogSettingsRepository { class BasePlayerEventLogSettingsRepository {
public: public:
struct PlayerEventLogSettings { struct PlayerEventLogSettings {
@ -25,6 +25,20 @@ public:
int32_t retention_days; int32_t retention_days;
int32_t discord_webhook_id; int32_t discord_webhook_id;
uint8_t etl_enabled; uint8_t etl_enabled;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(id),
CEREAL_NVP(event_name),
CEREAL_NVP(event_enabled),
CEREAL_NVP(retention_days),
CEREAL_NVP(discord_webhook_id),
CEREAL_NVP(etl_enabled)
);
}
}; };
static std::string PrimaryKey() static std::string PrimaryKey()

View File

@ -273,8 +273,9 @@
#define ServerOP_WWTaskUpdate 0x4758 #define ServerOP_WWTaskUpdate 0x4758
// player events // player events
#define ServerOP_QSSendQuery 0x5000 #define ServerOP_QSSendQuery 0x5000
#define ServerOP_PlayerEvent 0x5100 #define ServerOP_PlayerEvent 0x5100
#define ServerOP_SendPlayerEventSettings 0x5101
enum { enum {
CZUpdateType_Character, CZUpdateType_Character,
@ -1778,6 +1779,7 @@ struct BazaarPurchaseMessaging_Struct {
uint32 id; uint32 id;
}; };
#pragma pack() #pragma pack()
#endif #endif

View File

@ -21,10 +21,13 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "zonelist.h"
extern WorldServer worldserver; extern WorldServer worldserver;
extern const queryservconfig *Config; extern const queryservconfig *Config;
extern QSDatabase qs_database; extern QSDatabase qs_database;
extern LFGuildManager lfguildmanager; extern LFGuildManager lfguildmanager;
extern ZSList zs_list;
WorldServer::WorldServer() WorldServer::WorldServer()
{ {
@ -78,6 +81,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
if (o->type == ServerReload::Type::Logs) { if (o->type == ServerReload::Type::Logs) {
LogSys.LoadLogDatabaseSettings(); LogSys.LoadLogDatabaseSettings();
player_event_logs.ReloadSettings(); player_event_logs.ReloadSettings();
zs_list.SendPlayerEventLogSettings();
} }
break; break;

View File

@ -5,6 +5,8 @@
void ZSList::Add(ZoneServer* zoneserver) { void ZSList::Add(ZoneServer* zoneserver) {
zone_server_list.emplace_back(std::unique_ptr<ZoneServer>(zoneserver)); zone_server_list.emplace_back(std::unique_ptr<ZoneServer>(zoneserver));
zoneserver->SetIsZoneConnected(true); zoneserver->SetIsZoneConnected(true);
zoneserver->SendPlayerEventLogSettings();
} }
void ZSList::Remove(const std::string &uuid) void ZSList::Remove(const std::string &uuid)
@ -18,3 +20,10 @@ void ZSList::Remove(const std::string &uuid)
iter++; iter++;
} }
} }
void ZSList::SendPlayerEventLogSettings()
{
for (auto &zs : zone_server_list) {
zs->SendPlayerEventLogSettings();
}
}

View File

@ -12,9 +12,10 @@ class ZoneServer;
class ZSList { class ZSList {
public: public:
std::list<std::unique_ptr<ZoneServer>> &GetZsList() { return zone_server_list; } std::list<std::unique_ptr<ZoneServer>>& GetZsList() { return zone_server_list; }
void Add(ZoneServer *zoneserver); void Add(ZoneServer* zoneserver);
void Remove(const std::string &uuid); void Remove(const std::string& uuid);
void SendPlayerEventLogSettings();
private: private:
std::list<std::unique_ptr<ZoneServer>> zone_server_list; std::list<std::unique_ptr<ZoneServer>> zone_server_list;

View File

@ -7,6 +7,7 @@
extern DiscordManager discord_manager; extern DiscordManager discord_manager;
ZoneServer::ZoneServer( ZoneServer::ZoneServer(
std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection, std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection,
EQ::Net::ConsoleServer *in_console EQ::Net::ConsoleServer *in_console
@ -46,3 +47,27 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
} }
} }
} }
void ZoneServer::SendPlayerEventLogSettings()
{
EQ::Net::DynamicPacket dyn_pack;
std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> settings(
player_event_logs.GetSettings(),
player_event_logs.GetSettings() + PlayerEvent::EventType::MAX
);
dyn_pack.PutSerialize(0, settings);
auto packet_size = sizeof(ServerSendPlayerEvent_Struct) + dyn_pack.Length();
auto pack = std::make_unique<ServerPacket>(
ServerOP_SendPlayerEventSettings,
static_cast<uint32_t>(packet_size)
);
auto* buf = reinterpret_cast<ServerSendPlayerEvent_Struct*>(pack->pBuffer);
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
SendPacket(pack.release());
}

View File

@ -16,11 +16,12 @@ class ZoneServer : public WorldTCPConnection {
public: public:
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection, EQ::Net::ConsoleServer *in_console); ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection, EQ::Net::ConsoleServer *in_console);
~ZoneServer(); ~ZoneServer();
void SendPacket(ServerPacket *pack) { m_connection->SendPacket(pack); } void SendPacket(ServerPacket *pack) { m_connection->SendPacket(pack); }
void SetIsZoneConnected(bool in) { m_is_zone_connected = in; } void SetIsZoneConnected(bool in) { m_is_zone_connected = in; }
bool GetIsZoneConnected() { return m_is_zone_connected; } bool GetIsZoneConnected() { return m_is_zone_connected; }
void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); void HandleMessage(uint16 opcode, const EQ::Net::Packet &p);
std::string GetUUID() const { return m_connection->GetUUID(); } std::string GetUUID() const { return m_connection->GetUUID(); }
void SendPlayerEventLogSettings();
private: private:
std::shared_ptr<EQ::Net::ServertalkServerConnection> m_connection{}; std::shared_ptr<EQ::Net::ServertalkServerConnection> m_connection{};

View File

@ -114,7 +114,8 @@ if ($requested_table_to_generate ne "all") {
my @cereal_enabled_tables = ( my @cereal_enabled_tables = (
"data_buckets", "data_buckets",
"player_event_logs" "player_event_logs",
"player_event_log_settings"
); );
my $generated_base_repository_files = ""; my $generated_base_repository_files = "";

View File

@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "dynamic_zone_manager.h" #include "dynamic_zone_manager.h"
#include "ucs.h" #include "ucs.h"
#include "clientlist.h" #include "clientlist.h"
#include "queryserv.h"
#include "../common/repositories/trader_repository.h" #include "../common/repositories/trader_repository.h"
#include "../common/repositories/buyer_repository.h" #include "../common/repositories/buyer_repository.h"
@ -44,6 +45,7 @@ extern uint32 numzones;
extern WebInterfaceList web_interface; extern WebInterfaceList web_interface;
extern SharedTaskManager shared_task_manager; extern SharedTaskManager shared_task_manager;
extern ClientList client_list; extern ClientList client_list;
extern QueryServConnection QSLink;
volatile bool UCSServerAvailable_ = false; volatile bool UCSServerAvailable_ = false;
void CatchSignal(int sig_num); void CatchSignal(int sig_num);
@ -984,6 +986,7 @@ void ZSList::SendServerReload(ServerReload::Type type, uchar *packet)
LogSys.LoadLogDatabaseSettings(); LogSys.LoadLogDatabaseSettings();
player_event_logs.ReloadSettings(); player_event_logs.ReloadSettings();
UCSLink.SendPacket(&pack); UCSLink.SendPacket(&pack);
QSLink.SendPacket(&pack);
} else if (type == ServerReload::Type::Tasks) { } else if (type == ServerReload::Type::Tasks) {
shared_task_manager.LoadTaskData(); shared_task_manager.LoadTaskData();
} else if (type == ServerReload::Type::DzTemplates) { } else if (type == ServerReload::Type::DzTemplates) {

View File

@ -1,12 +1,13 @@
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/servertalk.h" #include "../common/servertalk.h"
#include "../common/strings.h" #include "../common/strings.h"
#include "../common/events/player_event_logs.h"
#include "queryserv.h" #include "queryserv.h"
#include "worldserver.h" #include "worldserver.h"
extern WorldServer worldserver; extern WorldServer worldserver;
extern QueryServ *QServ; extern QueryServ* QServ;
QueryServ::QueryServ() QueryServ::QueryServ()
{ {
@ -20,18 +21,29 @@ void QueryServ::SendQuery(std::string Query)
{ {
auto pack = new ServerPacket(ServerOP_QSSendQuery, Query.length() + 5); auto pack = new ServerPacket(ServerOP_QSSendQuery, Query.length() + 5);
pack->WriteUInt32(Query.length()); /* Pack Query String Size so it can be dynamically broken out at queryserv */ pack->WriteUInt32(Query.length()); /* Pack Query String Size so it can be dynamically broken out at queryserv */
pack->WriteString(Query.c_str()); /* Query */ pack->WriteString(Query.c_str()); /* Query */
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
void QueryServ::Connect() void QueryServ::Connect()
{ {
m_connection = std::make_unique<EQ::Net::ServertalkClient>(Config->QSHost, Config->QSPort, false, "Zone", Config->SharedKey); m_connection = std::make_unique<EQ::Net::ServertalkClient>(
Config->QSHost,
Config->QSPort,
false,
"Zone",
Config->SharedKey
);
m_connection->OnMessage(std::bind(&QueryServ::HandleMessage, this, std::placeholders::_1, std::placeholders::_2)); m_connection->OnMessage(std::bind(&QueryServ::HandleMessage, this, std::placeholders::_1, std::placeholders::_2));
m_connection->OnConnect([this](EQ::Net::ServertalkClient *client) { m_connection->OnConnect([this](EQ::Net::ServertalkClient* client)
{
m_is_qs_connected = true; m_is_qs_connected = true;
LogInfo("Query Server connection established to [{}] [{}]", client->Handle()->RemoteIP(), client->Handle()->RemotePort()); LogInfo(
"Query Server connection established to [{}] [{}]",
client->Handle()->RemoteIP(),
client->Handle()->RemotePort()
);
}); });
LogInfo( LogInfo(
@ -41,7 +53,7 @@ void QueryServ::Connect()
); );
} }
bool QueryServ::SendPacket(ServerPacket *pack) bool QueryServ::SendPacket(ServerPacket* pack)
{ {
if (m_connection.get() == nullptr) { if (m_connection.get() == nullptr) {
Connect(); Connect();
@ -59,14 +71,50 @@ bool QueryServ::SendPacket(ServerPacket *pack)
return false; return false;
} }
void QueryServ::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) void QueryServ::HandleMessage(uint16 opcode, const EQ::Net::Packet& p)
{ {
ServerPacket tpack(opcode, p); ServerPacket tpack(opcode, p);
auto pack = &tpack; auto pack = &tpack;
switch (opcode) { switch (opcode) {
default: { case ServerOP_SendPlayerEventSettings:
LogInfo("Unknown ServerOP Received <red>[{}]", opcode); {
if (pack->size < sizeof(ServerSendPlayerEvent_Struct)) {
LogError("ServerOP_SendPlayerEventSettings: packet too small");
break;
}
auto* data = reinterpret_cast<const ServerSendPlayerEvent_Struct*>(pack->pBuffer);
const uint32_t expected_size = sizeof(ServerSendPlayerEvent_Struct) + data->cereal_size;
if (pack->size < expected_size) {
LogError(
"ServerOP_SendPlayerEventSettings: packet size mismatch, expected {}, got {}", expected_size,
pack->size
);
break;
}
std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> settings;
try {
EQ::Util::MemoryStreamReader ms(const_cast<char*>(data->cereal_data), data->cereal_size);
cereal::BinaryInputArchive ar(ms);
ar(settings);
}
catch (const std::exception& ex) {
LogError("Failed to deserialize PlayerEventLogSettings: {}", ex.what());
break;
}
player_event_logs.LoadPlayerEventSettingsFromQS(settings);
LogInfo("Loaded {} PlayerEventLogSettings from queryserv", settings.size());
break;
}
default:
{
LogInfo("Unknown ServerOP Received [{}]", opcode);
break; break;
} }
} }

View File

@ -4591,7 +4591,10 @@ void WorldServer::ProcessReload(const ServerReload::Request& request)
case ServerReload::Type::Logs: case ServerReload::Type::Logs:
LogSys.LoadLogDatabaseSettings(); LogSys.LoadLogDatabaseSettings();
player_event_logs.ReloadSettings(); // if QS process is enabled, we get settings from QS
if (!RuleB(Logging, PlayerEventsQSProcess)) {
player_event_logs.ReloadSettings();
}
break; break;
case ServerReload::Type::Loot: case ServerReload::Type::Loot: