#include #include #include #include #include #include #include #include #include #include #include #include "Game/Player.h" #include OverlayService::OverlayService(World& aWorld, entt::dispatcher& aDispatcher) : m_world(aWorld) { m_chatMessageConnection = aDispatcher.sink>().connect<&OverlayService::HandleChatMessage>(this); m_playerDialogueConnection = aDispatcher.sink>().connect<&OverlayService::OnPlayerDialogue>(this); m_teleportConnection = aDispatcher.sink>().connect<&OverlayService::OnTeleport>(this); m_playerHealthConnection = aDispatcher.sink>().connect<&OverlayService::OnPlayerHealthUpdate>(this); } void sendPlayerMessage(const ChatMessageType acType, const String acContent, Player* aSendingPlayer) noexcept { NotifyChatMessageBroadcast notifyMessage{}; std::regex escapeHtml{"<[^>]+>\\s+(?=<)|<[^>]+>"}; notifyMessage.MessageType = acType; notifyMessage.PlayerName = std::regex_replace(aSendingPlayer->GetUsername(), escapeHtml, ""); notifyMessage.ChatMessage = std::regex_replace(acContent, escapeHtml, ""); auto character = aSendingPlayer->GetCharacter(); switch (notifyMessage.MessageType) { case kGlobalChat: GameServer::Get()->SendToPlayers(notifyMessage); break; case kSystemMessage: spdlog::error("PlayerId {} attempted to send a System Message.", aSendingPlayer->GetId()); break; case kPlayerDialogue: GameServer::Get()->SendToParty(notifyMessage, aSendingPlayer->GetParty()); break; case kPartyChat: GameServer::Get()->SendToParty(notifyMessage, aSendingPlayer->GetParty()); break; case kLocalChat: if (character) { if (!GameServer::Get()->SendToPlayersInRange(notifyMessage, *character)) spdlog::error("{}: SendToPlayersInRange failed", __FUNCTION__); } break; default: spdlog::error("{} is not a known MessageType", static_cast(notifyMessage.MessageType)); break; } } void OverlayService::HandleChatMessage(const PacketEvent& acMessage) const noexcept { auto [canceled, reason] = m_world.GetScriptService().HandleChatMessage(*acMessage.pPlayer->GetCharacter(), acMessage.Packet.ChatMessage); if (canceled) return; sendPlayerMessage(acMessage.Packet.MessageType, acMessage.Packet.ChatMessage, acMessage.pPlayer); } void OverlayService::OnPlayerDialogue(const PacketEvent& acMessage) const noexcept { sendPlayerMessage(kPlayerDialogue, acMessage.Packet.Text, acMessage.pPlayer); } void OverlayService::OnTeleport(const PacketEvent& acMessage) const noexcept { Player* pTargetPlayer = m_world.GetPlayerManager().GetById(acMessage.Packet.PlayerId); if (!pTargetPlayer) return; NotifyTeleport response{}; auto character = pTargetPlayer->GetCharacter(); if (character) { const auto* pMovementComponent = m_world.try_get(*character); if (pMovementComponent) { const auto& cellComponent = pTargetPlayer->GetCellComponent(); response.CellId = cellComponent.Cell; response.Position = pMovementComponent->Position; response.WorldSpaceId = cellComponent.WorldSpaceId; } } acMessage.pPlayer->Send(response); } void OverlayService::OnPlayerHealthUpdate(const PacketEvent& acMessage) const noexcept { NotifyPlayerHealthUpdate notify{}; notify.PlayerId = acMessage.pPlayer->GetId(); notify.Percentage = acMessage.Packet.Percentage; GameServer::Get()->SendToParty(notify, acMessage.pPlayer->GetParty(), acMessage.GetSender()); }