eqemu-server/world/shared_task_world_messaging.cpp
Chris Miles d9f545a5ec
[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>
2023-02-12 21:31:01 -06:00

363 lines
12 KiB
C++

#include "shared_task_world_messaging.h"
#include "cliententry.h"
#include "worlddb.h"
#include "../common/shared_tasks.h"
#include "../common/eqemu_logsys.h"
#include "../common/repositories/tasks_repository.h"
#include "../common/tasks.h"
#include "cliententry.h"
#include "clientlist.h"
#include "zonelist.h"
#include "zoneserver.h"
#include "shared_task_manager.h"
#include "../common/repositories/shared_task_members_repository.h"
#include "../common/repositories/task_activities_repository.h"
#include "dynamic_zone.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
extern SharedTaskManager shared_task_manager;
void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack)
{
switch (pack->opcode) {
case ServerOP_SharedTaskRequest: {
auto *r = (ServerSharedTaskRequest_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskRequest] Received request from character [{}] task_id [{}] npc_type_id [{}]",
r->requested_character_id,
r->requested_task_id,
r->requested_npc_type_id
);
shared_task_manager.AttemptSharedTaskCreation(
r->requested_task_id,
r->requested_character_id,
r->requested_npc_type_id
);
break;
}
case ServerOP_SharedTaskQuit: {
auto *r = (ServerSharedTaskQuit_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskQuit] Received request from character [{}] task_id [{}] remove_from_db [{}]",
r->requested_character_id,
r->task_id,
r->remove_from_db
);
auto s = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(r->task_id, r->requested_character_id);
if (s) {
auto member = s->FindMemberFromCharacterID(r->requested_character_id);
if (member.character_id != 0) {
shared_task_manager.RemoveMember(s, member, r->remove_from_db);
}
}
break;
}
case ServerOP_SharedTaskKickPlayers: {
auto r = reinterpret_cast<ServerSharedTaskKickPlayers_Struct *>(pack->pBuffer);
LogTasksDetail(
"[ServerOP_SharedTaskKickPlayers] Received request from character [{}] task_id [{}]",
r->source_character_id,
r->task_id
);
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(r->task_id, r->source_character_id);
if (t) {
auto leader = t->GetLeader();
if (leader.character_id != r->source_character_id) {
client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name});
}
else {
shared_task_manager.RemoveEveryoneFromSharedTask(t, r->source_character_id);
}
}
break;
}
case ServerOP_SharedTaskUpdate: {
auto *r = (ServerSharedTaskActivityUpdate_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskUpdate] Received request from character [{}] task_id [{}] activity_id [{}] donecount [{}] ignore_quest_update [{}]",
r->source_character_id,
r->task_id,
r->activity_id,
r->done_count,
(r->ignore_quest_update ? "true" : "false")
);
shared_task_manager.SharedTaskActivityUpdate(
r->source_character_id,
r->task_id,
r->activity_id,
r->done_count,
r->ignore_quest_update
);
break;
}
case ServerOP_SharedTaskRequestMemberlist: {
auto *r = (ServerSharedTaskRequestMemberlist_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskRequestMemberlist] Received request from character [{}] task_id [{}]",
r->source_character_id,
r->task_id
);
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(r->task_id, r->source_character_id);
if (t) {
LogTasksDetail(
"[ServerOP_SharedTaskRequestMemberlist] Found shared task character [{}] shared_task_id [{}]",
r->source_character_id,
t->GetDbSharedTask().id
);
shared_task_manager.SendSharedTaskMemberList(
r->source_character_id,
t->GetMembers()
);
}
break;
}
case ServerOP_SharedTaskRemovePlayer: {
auto *r = (ServerSharedTaskRemovePlayer_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskRemovePlayer] Received request from character [{}] task_id [{}] player_name [{}]",
r->source_character_id,
r->task_id,
r->player_name
);
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(r->task_id, r->source_character_id);
if (t) {
LogTasksDetail(
"[ServerOP_SharedTaskRemovePlayer] Found shared task character [{}] shared_task_id [{}]",
r->source_character_id,
t->GetDbSharedTask().id
);
auto leader = t->GetLeader();
if (leader.character_id != r->source_character_id) {
client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name});
}
else {
LogTasksDetail(
"[ServerOP_SharedTaskRemovePlayer] character_id [{}] shared_task_id [{}] is_leader",
r->source_character_id,
t->GetDbSharedTask().id
);
auto member = t->FindMemberFromCharacterName(r->player_name);
if (member.character_id == 0) {
shared_task_manager.SendLeaderMessageID(t, Chat::Red, TaskStr::IS_NOT_MEMBER, {r->player_name});
}
else {
shared_task_manager.RemoveMember(t, member, true);
shared_task_manager.SendLeaderMessageID(t, Chat::Yellow, TaskStr::PLAYER_REMOVED, {member.character_name, t->GetTaskData().title});
}
}
}
break;
}
case ServerOP_SharedTaskMakeLeader: {
auto *r = (ServerSharedTaskMakeLeader_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskMakeLeader] Received request from character [{}] task_id [{}] player_name [{}]",
r->source_character_id,
r->task_id,
r->player_name
);
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(r->task_id, r->source_character_id);
if (t) {
LogTasksDetail(
"[ServerOP_SharedTaskMakeLeader] Found shared task character [{}] shared_task_id [{}]",
r->source_character_id,
t->GetDbSharedTask().id
);
auto leader = t->GetLeader();
if (leader.character_id != r->source_character_id) {
client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name});
}
else if (strcasecmp(leader.character_name.c_str(), r->player_name) == 0) {
client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::YOU_ALREADY_LEADER);
}
else {
LogTasksDetail(
"[ServerOP_SharedTaskMakeLeader] character_id [{}] shared_task_id [{}] is_leader",
r->source_character_id,
t->GetDbSharedTask().id
);
std::string character_name = r->player_name;
shared_task_manager.MakeLeaderByPlayerName(t, character_name);
}
}
break;
}
case ServerOP_SharedTaskAddPlayer: {
auto *r = (ServerSharedTaskAddPlayer_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskAddPlayer] Received request from character [{}] task_id [{}] player_name [{}]",
r->source_character_id,
r->task_id,
r->player_name
);
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(r->task_id, r->source_character_id);
if (t) {
LogTasksDetail(
"[ServerOP_SharedTaskAddPlayer] Found shared task character [{}] shared_task_id [{}]",
r->source_character_id,
t->GetDbSharedTask().id
);
auto leader = t->GetLeader();
if (leader.character_id != r->source_character_id) {
// taskadd is client sided with System color in newer clients, server side might still be red
client_list.SendCharacterMessageID(r->source_character_id, Chat::Red, TaskStr::NOT_LEADER, {leader.character_name});
}
else {
LogTasksDetail(
"[ServerOP_SharedTaskAddPlayer] character_id [{}] shared_task_id [{}] is_leader",
r->source_character_id,
t->GetDbSharedTask().id
);
std::string character_name = r->player_name;
shared_task_manager.InvitePlayerByPlayerName(t, character_name);
}
}
break;
}
case ServerOP_SharedTaskInviteAcceptedPlayer: {
auto *r = (ServerSharedTaskInviteAccepted_Struct *) pack->pBuffer;
LogTasksDetail(
"[ServerOP_SharedTaskInviteAcceptedPlayer] Received request from source_character_id [{}] shared_task_id [{}] accepted [{}]",
r->source_character_id,
r->shared_task_id,
r->accepted
);
auto t = shared_task_manager.FindSharedTaskById(r->shared_task_id);
if (t && shared_task_manager.IsInvitationActive(r->shared_task_id, r->source_character_id)) {
LogTasksDetail(
"[ServerOP_SharedTaskInviteAcceptedPlayer] Found shared task character [{}] shared_task_id [{}]",
r->source_character_id,
t->GetDbSharedTask().id
);
shared_task_manager.RemoveActiveInvitation(r->shared_task_id, r->source_character_id);
if (r->accepted) {
shared_task_manager.AddPlayerByCharacterIdAndName(t, r->source_character_id, r->player_name);
}
else {
shared_task_manager.SendLeaderMessageID(t, Chat::Red, TaskStr::PLAYER_DECLINED_OFFER, {r->player_name});
}
}
break;
}
case ServerOP_SharedTaskCreateDynamicZone: {
auto buf = reinterpret_cast<ServerSharedTaskCreateDynamicZone_Struct *>(pack->pBuffer);
LogTasksDetail(
"[ServerOP_SharedTaskCreateDynamicZone] Received request from source_character_id [{}] task_id [{}]",
buf->source_character_id,
buf->task_id
);
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->source_character_id);
if (t) {
DynamicZone dz;
dz.LoadSerializedDzPacket(buf->cereal_data, buf->cereal_size);
shared_task_manager.CreateDynamicZone(t, dz);
}
break;
}
case ServerOP_SharedTaskPurgeAllCommand: {
LogTasksDetail("[ServerOP_SharedTaskPurgeAllCommand] Received request to purge all shared tasks");
shared_task_manager.PurgeAllSharedTasks();
auto p = std::make_unique<ServerPacket>(
ServerOP_SharedTaskPurgeAllCommand,
0
);
zoneserver_list.SendPacket(p.get());
break;
}
case ServerOP_SharedTaskPlayerList: {
auto buf = reinterpret_cast<ServerSharedTaskPlayerList_Struct *>(pack->pBuffer);
LogTasksDetail(
"[ServerOP_SharedTaskPlayerList] Received request from source_character_id [{}] task_id [{}]",
buf->source_character_id,
buf->task_id
);
auto s = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->source_character_id);
if (s) {
std::vector<std::string> player_names;
for (const auto &member : s->GetMembers()) {
player_names.emplace_back(member.character_name);
if (member.is_leader) {
client_list.SendCharacterMessageID(buf->source_character_id, Chat::Yellow, TaskStr::LEADER_PRINT, {member.character_name});
}
}
std::string player_list = fmt::format("{}", Strings::Join(player_names, ", "));
client_list.SendCharacterMessageID(buf->source_character_id, Chat::Yellow, TaskStr::MEMBERS_PRINT, {player_list});
}
break;
}
case ServerOP_SharedTaskLock: {
auto buf = reinterpret_cast<ServerSharedTaskLock_Struct*>(pack->pBuffer);
auto shared_task = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->source_character_id);
if (shared_task)
{
shared_task_manager.LockTask(shared_task, buf->lock);
}
break;
}
case ServerOP_SharedTaskEndByDz: {
auto buf = reinterpret_cast<ServerSharedTaskEnd_Struct*>(pack->pBuffer);
auto shared_task = shared_task_manager.FindSharedTaskByDzId(buf->dz_id);
if (shared_task)
{
shared_task_manager.Terminate(*shared_task, buf->send_fail, true);
}
break;
}
case ServerOP_SharedTaskEnd: {
auto buf = reinterpret_cast<ServerSharedTaskEnd_Struct*>(pack->pBuffer);
auto shared_task = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->character_id);
if (shared_task)
{
shared_task_manager.Terminate(*shared_task, buf->send_fail, true);
}
break;
}
default:
break;
}
}