From 6978b56016274ddb3ee6afbfbb09af5c76e7d4f2 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Fri, 31 Jan 2025 00:30:05 -0600 Subject: [PATCH] cleanup --- dChatServer/ChatPacketHandler.cpp | 91 +++++++--------- dChatServer/ChatPacketHandler.h | 8 ++ dChatServer/ChatWeb.cpp | 100 ++++++++++++------ dChatServer/ChatWeb.h | 5 + dChatServer/PlayerContainer.cpp | 24 +---- dDatabase/GameDatabase/ITables/IActivityLog.h | 1 + 6 files changed, 127 insertions(+), 102 deletions(-) diff --git a/dChatServer/ChatPacketHandler.cpp b/dChatServer/ChatPacketHandler.cpp index 39f49944..ab19886b 100644 --- a/dChatServer/ChatPacketHandler.cpp +++ b/dChatServer/ChatPacketHandler.cpp @@ -20,7 +20,7 @@ #include "eGameMasterLevel.h" #include "ChatPackets.h" #include "json.hpp" -#include "Web.h" +#include "ChatWeb.h" void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) { //Get from the packet which player we want to do something with: @@ -428,50 +428,41 @@ void ChatPacketHandler::HandleShowAll(Packet* packet) { // that are sent to the server. Because of this, there are large gaps of unused data in chat messages void ChatPacketHandler::HandleChatMessage(Packet* packet) { CINSTREAM_SKIP_HEADER; - LWOOBJID playerID; - inStream.Read(playerID); - LOG("Got a message from player %llu", playerID); + ChatMessage data; + LWOOBJID sender; + inStream.Read(sender); + LOG("Got a message from player %llu", sender); - const auto& sender = Game::playerContainer.GetPlayerData(playerID); - if (!sender || sender.GetIsMuted()) return; + data.sender = Game::playerContainer.GetPlayerData(sender); + if (!data.sender || data.sender.GetIsMuted()) return; eChatChannel channel; uint32_t size; inStream.IgnoreBytes(4); - inStream.Read(channel); + inStream.Read(data.channel); inStream.Read(size); inStream.IgnoreBytes(77); - LOG("message size: %u", size); - LUWString message(size); - inStream.Read(message); + LOG("message size: %u", size); + data.message = LUWString(size); + inStream.Read(data.message); - LOG("Got message %s from (%s) via [%s]: %s", message.GetAsString().c_str(), sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str()); + LOG("Got message from (%s) via [%s]: %s", data.sender.playerName.c_str(), StringifiedEnum::ToString(data.channel).data(), data.message.GetAsString().c_str()); - // build chat json data - nlohmann::json data; - data["playerName"] = sender.playerName; - data["message"] = message.GetAsString(); - auto& zoneID = data["zone_id"]; - zoneID["map_id"] = sender.zoneID.GetMapID(); - zoneID["instance_id"] = sender.zoneID.GetInstanceID(); - zoneID["clone_id"] = sender.zoneID.GetCloneID(); switch (channel) { case eChatChannel::LOCAL: { - Game::web.SendWSMessage("chat_local", data); break; } case eChatChannel::TEAM: { - auto* team = Game::playerContainer.GetTeam(playerID); + auto* team = Game::playerContainer.GetTeam(data.sender.playerID); if (team == nullptr) return; + data.teamID = team->teamID; for (const auto memberId : team->memberIDs) { const auto& otherMember = Game::playerContainer.GetPlayerData(memberId); if (!otherMember) return; - SendPrivateChatMessage(sender, otherMember, otherMember, message, eChatChannel::TEAM, eChatMessageResponseCode::SENT); - data["teamID"] = team->teamID; - Game::web.SendWSMessage("chat_team", data); + SendPrivateChatMessage(data.sender, otherMember, otherMember, data.message, eChatChannel::TEAM, eChatMessageResponseCode::SENT); } break; } @@ -479,70 +470,68 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) { LOG("Unhandled Chat channel [%s]", StringifiedEnum::ToString(channel).data()); break; } + ChatWeb::SendWSChatMessage(data); } // the structure the client uses to send this packet is shared in many chat messages // that are sent to the server. Because of this, there are large gaps of unused data in chat messages void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) { + ChatMessage data; + data.channel = eChatChannel::GENERAL; + CINSTREAM_SKIP_HEADER; LWOOBJID playerID; inStream.Read(playerID); - const auto& sender = Game::playerContainer.GetPlayerData(playerID); - if (!sender || sender.GetIsMuted()) return; + data.sender = Game::playerContainer.GetPlayerData(playerID); + if (!data.sender || data.sender.GetIsMuted()) return; - eChatChannel channel; uint32_t size; - LUWString LUReceiverName; inStream.IgnoreBytes(4); - inStream.Read(channel); - if (channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!"); + inStream.Read(data.channel); + if (data.channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!"); inStream.Read(size); inStream.IgnoreBytes(77); + LUWString LUReceiverName; inStream.Read(LUReceiverName); auto receiverName = LUReceiverName.GetAsString(); inStream.IgnoreBytes(2); - LUWString message(size); - inStream.Read(message); + data.message = LUWString(size); + inStream.Read(data.message); - LOG("Got a message from (%s) via [%s]: %s to %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str(), receiverName.c_str()); + LOG("Got a message from (%s) via [%s]: %s to %s", data.sender.playerName.c_str(), StringifiedEnum::ToString(data.channel).data(), data.message.GetAsString().c_str(), receiverName.c_str()); - const auto& receiver = Game::playerContainer.GetPlayerData(receiverName); - if (!receiver) { + data.receiver = Game::playerContainer.GetPlayerData(receiverName); + if (!data.receiver) { PlayerData otherPlayer; otherPlayer.playerName = receiverName; auto responseType = Database::Get()->GetCharacterInfo(receiverName) ? eChatMessageResponseCode::NOTONLINE : eChatMessageResponseCode::GENERALERROR; - SendPrivateChatMessage(sender, otherPlayer, sender, message, eChatChannel::GENERAL, responseType); + SendPrivateChatMessage(data.sender, otherPlayer, data.sender, data.message, data.channel, responseType); return; } // Check to see if they are friends // only freinds can whispr each other - for (const auto& fr : receiver.friends) { - if (fr.friendID == sender.playerID) { - nlohmann::json data; - data["sender"] = sender.playerName; - data["receiver"] = receiverName; - data["message"] = message.GetAsString(); - data["zone_id"]["map_id"] = sender.zoneID.GetMapID(); - data["zone_id"]["instance_id"] = sender.zoneID.GetInstanceID(); - data["zone_id"]["clone_id"] = sender.zoneID.GetCloneID(); - Game::web.SendWSMessage("chat_private", data); - //To the sender: - SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::SENT); - //To the receiver: - SendPrivateChatMessage(sender, receiver, receiver, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::RECEIVEDNEWWHISPER); + for (const auto& fr : data.receiver.friends) { + if (fr.friendID == data.sender.playerID) { + data.channel = eChatChannel::PRIVATE_CHAT; + // To the sender: + SendPrivateChatMessage(data.sender, data.receiver, data.sender, data.message, data.channel, eChatMessageResponseCode::SENT); + // To the receiver: + SendPrivateChatMessage(data.sender, data.receiver, data.receiver, data.message, data.channel, eChatMessageResponseCode::RECEIVEDNEWWHISPER); + // To the WebSocket + ChatWeb::SendWSChatMessage(data); return; } } - SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::GENERAL, eChatMessageResponseCode::NOTFRIENDS); + SendPrivateChatMessage(data.sender, data.receiver, data.sender, data.message, data.channel, eChatMessageResponseCode::NOTFRIENDS); } void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) { diff --git a/dChatServer/ChatPacketHandler.h b/dChatServer/ChatPacketHandler.h index def9c9b9..e29a150f 100644 --- a/dChatServer/ChatPacketHandler.h +++ b/dChatServer/ChatPacketHandler.h @@ -44,6 +44,14 @@ enum class eChatMessageResponseCode : uint8_t { RECEIVERFREETRIAL, }; +struct ChatMessage { + LUWString message; + PlayerData sender; + PlayerData receiver; + eChatChannel channel; + LWOOBJID teamID; +}; + namespace ChatPacketHandler { void HandleFriendlistRequest(Packet* packet); void HandleFriendRequest(Packet* packet); diff --git a/dChatServer/ChatWeb.cpp b/dChatServer/ChatWeb.cpp index 9ff1d587..6216fdd6 100644 --- a/dChatServer/ChatWeb.cpp +++ b/dChatServer/ChatWeb.cpp @@ -56,7 +56,6 @@ void HandleHTTPAnnounceRequest(HTTPReply& reply, std::string body) { } } - void HandleWSChat(mg_connection* connection, json data) { auto check = JSONUtils::CheckRequiredData(data, { "user", "message" }); if (!check.empty()) { @@ -65,41 +64,80 @@ void HandleWSChat(mg_connection* connection, json data) { const auto user = data["user"].get(); const auto message = data["message"].get(); LOG_DEBUG("EXTERNAL Chat message from %s: %s", user.c_str(), message.c_str()); - //TODO: Send chat message to corret world server to broadcast to players + // TODO: use chat filter and respond if the message isn't allowed + // TODO: Send chat message to corret world server to broadcast to players } } -void ChatWeb::RegisterRoutes() { - // REST API v1 routes - std::string v1_route = "/api/v1/"; - Game::web.RegisterHTTPRoute({ - .path = v1_route + "players", - .method = eHTTPMethod::GET, - .handle = HandleHTTPPlayersRequest - }); +namespace ChatWeb { + void RegisterRoutes() { + // REST API v1 routes + std::string v1_route = "/api/v1/"; + Game::web.RegisterHTTPRoute({ + .path = v1_route + "players", + .method = eHTTPMethod::GET, + .handle = HandleHTTPPlayersRequest + }); - Game::web.RegisterHTTPRoute({ - .path = v1_route + "teams", - .method = eHTTPMethod::GET, - .handle = HandleHTTPTeamsRequest - }); + Game::web.RegisterHTTPRoute({ + .path = v1_route + "teams", + .method = eHTTPMethod::GET, + .handle = HandleHTTPTeamsRequest + }); - Game::web.RegisterHTTPRoute({ - .path = v1_route + "announce", - .method = eHTTPMethod::POST, - .handle = HandleHTTPAnnounceRequest - }); + Game::web.RegisterHTTPRoute({ + .path = v1_route + "announce", + .method = eHTTPMethod::POST, + .handle = HandleHTTPAnnounceRequest + }); - // WebSocket Events - Game::web.RegisterWSEvent({ - .name = "chat", - .handle = HandleWSChat - }); + // WebSocket Events + Game::web.RegisterWSEvent({ + .name = "chat", + .handle = HandleWSChat + }); - // WebSocket subscriptions - Game::web.RegisterWSSubscription("chat_local"); - Game::web.RegisterWSSubscription("chat_team"); - Game::web.RegisterWSSubscription("chat_private"); - Game::web.RegisterWSSubscription("player"); - Game::web.RegisterWSSubscription("team"); + // WebSocket subscriptions + Game::web.RegisterWSSubscription("chat_local"); + Game::web.RegisterWSSubscription("chat_team"); + Game::web.RegisterWSSubscription("chat_private"); + Game::web.RegisterWSSubscription("chat"); + Game::web.RegisterWSSubscription("player"); + Game::web.RegisterWSSubscription("team"); + } + + void SendWSPlayerUpdate(const PlayerData& player, eActivityType activityType) { + json data; + data["player_data"] = player; + data["update_type"] = magic_enum::enum_name(activityType); + Game::web.SendWSMessage("player_update", data); + } + + void SendWSChatMessage(const ChatMessage& chatMessage) { + json data; + data["message"] = chatMessage.message.GetAsString(); + data["sender"] = chatMessage.sender; + + data["channel"] = magic_enum::enum_name(chatMessage.channel); + + std::string event = "chat"; // generic catch all + switch (chatMessage.channel) { + case eChatChannel::LOCAL: + event = "chat_local"; + break; + case eChatChannel::TEAM: + event = "chat_team"; + data["teamID"] = chatMessage.teamID; + break; + case eChatChannel::PRIVATE_CHAT: + data["receiver"] = chatMessage.receiver; + event = "chat_private"; + break; + default: + LOG_DEBUG("Unhandled Chat channel [%s] in websocket send", StringifiedEnum::ToString(chatMessage.channel).data()); + break; + } + Game::web.SendWSMessage(event, data); + } } + diff --git a/dChatServer/ChatWeb.h b/dChatServer/ChatWeb.h index c2a28bc9..67b13aa1 100644 --- a/dChatServer/ChatWeb.h +++ b/dChatServer/ChatWeb.h @@ -5,9 +5,14 @@ #include #include "Web.h" +#include "PlayerContainer.h" +#include "IActivityLog.h" +#include "ChatPacketHandler.h" namespace ChatWeb { void RegisterRoutes(); + void SendWSPlayerUpdate(const PlayerData& player, eActivityType activityType); + void SendWSChatMessage(const ChatMessage& chatMessage); }; diff --git a/dChatServer/PlayerContainer.cpp b/dChatServer/PlayerContainer.cpp index 82973ae8..f26ecb51 100644 --- a/dChatServer/PlayerContainer.cpp +++ b/dChatServer/PlayerContainer.cpp @@ -12,8 +12,7 @@ #include "ChatPackets.h" #include "dConfig.h" #include "MessageType/Chat.h" -#include "json.hpp" -#include "Web.h" +#include "ChatWeb.h" void PlayerContainer::Initialize() { m_MaxNumberOfBestFriends = @@ -60,18 +59,8 @@ void PlayerContainer::InsertPlayer(Packet* packet) { m_PlayerCount++; LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID()); - // Send to connected websockets - nlohmann::json wsdata; - wsdata["action"] = "character_update"; - wsdata["type"] = "add"; - wsdata["playerName"] = data.playerName; - wsdata["playerID"] = data.playerID; - auto& zoneID = wsdata["zone_id"]; - zoneID["map_id"] = data.zoneID.GetMapID(); - zoneID["instance_id"] = data.zoneID.GetInstanceID(); - zoneID["clone_id"] = data.zoneID.GetCloneID(); - Game::web.SendWSMessage("player", wsdata); - Database::Get()->UpdateActivityLog(data.playerID, eActivityType::PlayerLoggedIn, data.zoneID.GetMapID()); + ChatWeb::SendWSPlayerUpdate(data, isLogin ? eActivityType::PlayerLoggedIn : eActivityType::PlayerChangedZone); + Database::Get()->UpdateActivityLog(data.playerID, isLogin ? eActivityType::PlayerLoggedIn : eActivityType::PlayerChangedZone, data.zoneID.GetMapID()); m_PlayersToRemove.erase(playerId); } @@ -125,12 +114,7 @@ void PlayerContainer::RemovePlayer(const LWOOBJID playerID) { } } - nlohmann::json wsdata; - wsdata["action"] = "character_update"; - wsdata["type"] = "remove"; - wsdata["playerName"] = player.playerName; - wsdata["playerID"] = player.playerID; - Game::web.SendWSMessage("player", wsdata); + ChatWeb::SendWSPlayerUpdate(player, eActivityType::PlayerLoggedOut); m_PlayerCount--; LOG("Removed user: %llu", playerID); diff --git a/dDatabase/GameDatabase/ITables/IActivityLog.h b/dDatabase/GameDatabase/ITables/IActivityLog.h index a67b61a4..98aa79db 100644 --- a/dDatabase/GameDatabase/ITables/IActivityLog.h +++ b/dDatabase/GameDatabase/ITables/IActivityLog.h @@ -8,6 +8,7 @@ enum class eActivityType : uint32_t { PlayerLoggedIn, PlayerLoggedOut, + PlayerChangedZone, }; class IActivityLog {