[Logging] Implement Player Event Logging system (#2833)

* Plumbing

* Batch processing in world

* Cleanup

* Cleanup

* Update player_event_logs.cpp

* Add player zoning event

* Use generics

* Comments

* Add events

* Add more events

* AA_GAIN, AA_PURCHASE, FORAGE_SUCCESS, FORAGE_FAILURE

* FISH_SUCCESS, FISH_FAILURE, ITEM_DESTROY

* Add charges to ITEM_DESTROY

* WENT_ONLINE, WENT_OFFLINE

* LEVEL_GAIN, LEVEL_LOSS

* LOOT_ITEM

* MERCHANT_PURCHASE

* MERCHANT_SELL

* SKILL_UP

* Add events

* Add more events

* TASK_ACCEPT, TASK_COMPLETE, and TASK_UPDATE

* GROUNDSPAWN_PICKUP

* SAY

* REZ_ACCEPTED

* COMBINE_FAILURE and COMBINE_SUCCESS

* DROPPED_ITEM

* DEATH

* SPLIT_MONEY

* TRADER_PURCHASE and TRADER_SELL

* DISCOVER_ITEM

* Convert GM_COMMAND to use new macro

* Convert ZONING event to use macro

* Revert some code changes

* Revert "Revert some code changes"

This reverts commit d53682f997e89a053a660761085913245db91e9d.

* Add cereal generation support to repositories

* TRADE

* Formatting

* Cleanup

* Relocate discord_manager to discord folder

* Discord sending plumbing

* Rename UCS's Database class to UCSDatabase to be more specific and not collide with base Database class for repository usage

* More discord sending plumbing

* More discord message formatting work

* More discord formatting work

* Discord formatting of events

* Format WENT_ONLINE, WENT_OFFLINE

* Add merchant purchase event

* Handle Discord MERCHANT_SELL formatter

* Update player_event_discord_formatter.cpp

* Tweaks

* Implement retention truncation

* Put mutex locking on batch queue, put processor on its own thread

* Process on initial bootup

* Implement optional QS processing, implement keepalive from world to QS

* Reload player event settings when logs are reloaded in game

* Set settings defaults

* Update player_event_logs.cpp

* Update player_event_logs.cpp

* Set retention days on boot

* Update player_event_logs.cpp

* Player Handin Event Testing.

Testing player handin stuff.

* Cleanup.

* Finish NPC Handin.

* set a reference to the client inside of the trade object as well for plugins to process

* Fix for windows _inline

* Bump to cpp20 default, ignore excessive warnings on windows

* Bump FMT to 6.1.2 for cpp20 compat and swap fmt::join for Strings::Join

* Windows compile fixes

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Create 2022_12_19_player_events_tables.sql

* [Formatters] Work on Discord Formatters

* Handin money.

* Format header

* [Formatters] Work on Discord Formatters

* Format

* Format

* [Formatters] More Formatter work, need to test further.

* [Formatters] More Work on Formatters.

* Add missing #endif

* [Formatters] Work on Formatters, fix Bot formatting in ^create help

* NPC Handin Discord Formatter

* Update player_event_logs.cpp

* Discover Item Discord Formatter

* Dropped Item Discord Formatter

* Split Money Discord Formatter

* Trader Discord Formatters

* Cleanup.

* Trade Event Discord Formatter Groundwork

* SAY don't record GM commands

* GM_Command don't record #help

* Update player_event_logs.cpp

* Fill in more event data

* Post rebase fixes

* Post rebase fix

* Discord formatting adjustments

* Add event deprecation or unimplemented tag support

* Trade events

* Add return money and sanity checks.

* Update schema

* Update ucs.cpp

* Update client.cpp

* Update 2022_12_19_player_events_tables.sql

* Implement archive single line

* Replace hackers table and functions with PossibleHack player event

* Replace very old eventlog table since the same events are covered by player event logs

* Update bot_command.cpp

* Record NPC kill events ALL / Named / Raid

* Add BatchEventProcessIntervalSeconds rule

* Naming

* Update CMakeLists.txt

* Update database_schema.h

* Remove logging function and methods

* DB version

* Cleanup SendPlayerHandinEvent

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
Co-authored-by: Aeadoin <109764533+Aeadoin@users.noreply.github.com>
This commit is contained in:
Chris Miles
2023-02-12 21:31:01 -06:00
committed by GitHub
parent 1cc32d92cf
commit d9f545a5ec
92 changed files with 6480 additions and 1391 deletions
+34 -25
View File
@@ -55,6 +55,7 @@
#include "zone.h"
#include "zonedb.h"
#include "../common/zone_store.h"
#include "../common/events/player_event_logs.h"
extern QueryServ* QServ;
extern Zone* zone;
@@ -184,6 +185,7 @@ bool Client::Process() {
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline);
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
RecordPlayerEventLog(PlayerEvent::WENT_OFFLINE, PlayerEvent::EmptyEvent{});
return false; //delete client
}
@@ -542,7 +544,7 @@ bool Client::Process() {
if (client_state == DISCONNECTED) {
OnDisconnect(true);
std::cout << "Client disconnected (cs=d): " << GetName() << std::endl;
database.SetMQDetectionFlag(AccountName(), GetName(), "/MQInstantCamp: Possible instant camp disconnect.", zone->GetShortName());
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "/MQInstantCamp: Possible instant camp disconnect"});
return false;
}
@@ -693,6 +695,7 @@ void Client::OnDisconnect(bool hard_disconnect) {
MyRaid->MemberZoned(this);
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
RecordPlayerEventLog(PlayerEvent::WENT_OFFLINE, PlayerEvent::EmptyEvent{});
/* QS: PlayerLogConnectDisconnect */
if (RuleB(QueryServ, PlayerLogConnectDisconnect)){
@@ -1155,12 +1158,8 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
if (HasSpellScribed(m->spell_id)) {
MemSpell(m->spell_id, m->slot);
} else {
database.SetMQDetectionFlag(
AccountName(),
GetName(),
"OP_MemorizeSpell but we don't have this spell scribed...",
zone->GetShortName()
);
std::string message = fmt::format("OP_MemorizeSpell [{}] but we don't have this spell scribed", m->spell_id);
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
}
break;
}
@@ -1299,10 +1298,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
NPC *banker = entity_list.GetClosestBanker(this, distance);
if(!banker || distance > USE_NPC_RANGE2)
{
auto hacked_string = fmt::format("Player tried to make use of a banker(coin move) but "
"{} is non-existant or too far away ({} units).",
banker ? banker->GetName() : "UNKNOWN NPC", distance);
database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName());
auto message = fmt::format(
"Player tried to make use of a banker (coin move) but "
"banker [{}] is non-existent or too far away [{}] units",
banker ? banker->GetName() : "UNKNOWN NPC", distance
);
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
return;
}
@@ -1330,11 +1332,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
NPC *banker = entity_list.GetClosestBanker(this, distance);
if(!banker || distance > USE_NPC_RANGE2)
{
auto hacked_string =
fmt::format("Player tried to make use of a banker(shared coin move) but {} is "
"non-existant or too far away ({} units).",
banker ? banker->GetName() : "UNKNOWN NPC", distance);
database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName());
auto message = fmt::format(
"Player tried to make use of a banker (shared coin move) but banker [{}] is "
"non-existent or too far away [{}] units",
banker ? banker->GetName() : "UNKNOWN NPC", distance
);
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
return;
}
if(mc->cointype1 == COINTYPE_PP) // there's only platinum here
@@ -1386,10 +1390,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
NPC *banker = entity_list.GetClosestBanker(this, distance);
if(!banker || distance > USE_NPC_RANGE2)
{
auto hacked_string = fmt::format("Player tried to make use of a banker(coin move) but "
"{} is non-existant or too far away ({} units).",
banker ? banker->GetName() : "UNKNOWN NPC", distance);
database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName());
auto message = fmt::format(
"Player tried to make use of a banker(coin move) but "
"banker [{}] is non-existent or too far away [{}] units",
banker ? banker->GetName() : "UNKNOWN NPC", distance
);
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
return;
}
switch(mc->cointype2)
@@ -1429,11 +1436,13 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
NPC *banker = entity_list.GetClosestBanker(this, distance);
if(!banker || distance > USE_NPC_RANGE2)
{
auto hacked_string =
fmt::format("Player tried to make use of a banker(shared coin move) but {} is "
"non-existant or too far away ({} units).",
banker ? banker->GetName() : "UNKNOWN NPC", distance);
database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName());
auto message = fmt::format(
"Player tried to make use of a banker (shared coin move) but banker [{}] is "
"non-existent or too far away [{}] units",
banker ? banker->GetName() : "UNKNOWN NPC", distance
);
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
return;
}
if(mc->cointype2 == COINTYPE_PP) // there's only platinum here