[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 "";
}
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
// ZONING | [x] Implemented Formatter
// AA_GAIN | [x] Implemented Formatter

View File

@ -73,9 +73,11 @@ public:
return BuildPlayerEventPacket(c);
}
[[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings *GetSettings() const;
bool IsEventDiscordEnabled(int32_t event_type_id);
std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id);
[[nodiscard]] const PlayerEventLogSettingsRepository::PlayerEventLogSettings * GetSettings() const;
bool IsEventDiscordEnabled(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);

View File

@ -15,7 +15,7 @@
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
#include <cereal/cereal.hpp>
class BasePlayerEventLogSettingsRepository {
public:
struct PlayerEventLogSettings {
@ -25,6 +25,20 @@ public:
int32_t retention_days;
int32_t discord_webhook_id;
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()

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@
extern DiscordManager discord_manager;
ZoneServer::ZoneServer(
std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection,
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:
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> in_connection, EQ::Net::ConsoleServer *in_console);
~ZoneServer();
void SendPacket(ServerPacket *pack) { m_connection->SendPacket(pack); }
void SetIsZoneConnected(bool in) { m_is_zone_connected = in; }
bool GetIsZoneConnected() { return m_is_zone_connected; }
void HandleMessage(uint16 opcode, const EQ::Net::Packet &p);
void SendPacket(ServerPacket *pack) { m_connection->SendPacket(pack); }
void SetIsZoneConnected(bool in) { m_is_zone_connected = in; }
bool GetIsZoneConnected() { return m_is_zone_connected; }
void HandleMessage(uint16 opcode, const EQ::Net::Packet &p);
std::string GetUUID() const { return m_connection->GetUUID(); }
void SendPlayerEventLogSettings();
private:
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 = (
"data_buckets",
"player_event_logs"
"player_event_logs",
"player_event_log_settings"
);
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 "ucs.h"
#include "clientlist.h"
#include "queryserv.h"
#include "../common/repositories/trader_repository.h"
#include "../common/repositories/buyer_repository.h"
@ -44,6 +45,7 @@ extern uint32 numzones;
extern WebInterfaceList web_interface;
extern SharedTaskManager shared_task_manager;
extern ClientList client_list;
extern QueryServConnection QSLink;
volatile bool UCSServerAvailable_ = false;
void CatchSignal(int sig_num);
@ -984,6 +986,7 @@ void ZSList::SendServerReload(ServerReload::Type type, uchar *packet)
LogSys.LoadLogDatabaseSettings();
player_event_logs.ReloadSettings();
UCSLink.SendPacket(&pack);
QSLink.SendPacket(&pack);
} else if (type == ServerReload::Type::Tasks) {
shared_task_manager.LoadTaskData();
} else if (type == ServerReload::Type::DzTemplates) {

View File

@ -1,12 +1,13 @@
#include "../common/global_define.h"
#include "../common/servertalk.h"
#include "../common/strings.h"
#include "../common/events/player_event_logs.h"
#include "queryserv.h"
#include "worldserver.h"
extern WorldServer worldserver;
extern QueryServ *QServ;
extern QueryServ* QServ;
QueryServ::QueryServ()
{
@ -20,18 +21,29 @@ void QueryServ::SendQuery(std::string Query)
{
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->WriteString(Query.c_str()); /* Query */
pack->WriteString(Query.c_str()); /* Query */
worldserver.SendPacket(pack);
safe_delete(pack);
}
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->OnConnect([this](EQ::Net::ServertalkClient *client) {
m_connection->OnConnect([this](EQ::Net::ServertalkClient* client)
{
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(
@ -41,7 +53,7 @@ void QueryServ::Connect()
);
}
bool QueryServ::SendPacket(ServerPacket *pack)
bool QueryServ::SendPacket(ServerPacket* pack)
{
if (m_connection.get() == nullptr) {
Connect();
@ -59,14 +71,50 @@ bool QueryServ::SendPacket(ServerPacket *pack)
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);
auto pack = &tpack;
auto pack = &tpack;
switch (opcode) {
default: {
LogInfo("Unknown ServerOP Received <red>[{}]", opcode);
case ServerOP_SendPlayerEventSettings:
{
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;
}
}

View File

@ -4591,7 +4591,10 @@ void WorldServer::ProcessReload(const ServerReload::Request& request)
case ServerReload::Type::Logs:
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;
case ServerReload::Type::Loot: