#include "server/ServerConnexion.h" #include "td/protocol/PacketDispatcher.h" #include "td/protocol/PacketFactory.h" #include "server/Server.h" #include "td/protocol/packets/ConnectionInfoPacket.h" #include "td/protocol/packets/DisconnectPacket.h" #include "td/protocol/packets/KeepAlivePacket.h" #include "td/protocol/packets/PlaceTowerPacket.h" #include "td/protocol/packets/PlayerLoginPacket.h" #include "td/protocol/packets/PlayerJoinPacket.h" #include "td/protocol/packets/PlayerListPacket.h" #include "td/protocol/packets/RemoveTowerPacket.h" #include "td/protocol/packets/SelectTeamPacket.h" #include "td/protocol/packets/SendMobsPacket.h" #include "td/protocol/packets/SpawnMobPacket.h" #include "td/protocol/packets/UpdatePlayerTeamPacket.h" #include "td/protocol/packets/UpdateGameStatePacket.h" #include "td/protocol/packets/UpgradeTowerPacket.h" #include "td/protocol/packets/WorldBeginDataPacket.h" #include "td/protocol/packets/WorldDataPacket.h" #include "td/protocol/packets/WorldAddTowerPacket.h" #include "td/misc/Time.h" #include "td/misc/Random.h" #include "td/misc/Format.h" #include #define KEEP_ALIVE_TIMEOUT 10 * 1000 // 10s namespace td { namespace server { /* NEVER TRUST USER INPUT */ ServerConnexion::ServerConnexion() : m_Player(0) { } ServerConnexion::ServerConnexion(network::TCPSocket& socket, std::uint8_t id) : Connexion::Connexion(&m_Dispatcher, socket), m_ID(id), m_Player(0) { Connexion::UpdateSocket(); } ServerConnexion::ServerConnexion(ServerConnexion&& move) : Connexion::Connexion(std::move(move)), m_Server(move.m_Server), m_ID(move.m_ID), m_KeepAlive(move.m_KeepAlive), m_Player(move.m_Player) { move.m_Server = nullptr; RegisterHandlers(); } void ServerConnexion::RegisterHandlers() { GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLogin, this); GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this); GetDispatcher()->RegisterHandler(protocol::PacketType::SelectTeam, this); GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this); GetDispatcher()->RegisterHandler(protocol::PacketType::PlaceTower, this); GetDispatcher()->RegisterHandler(protocol::PacketType::SendMobs, this); GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this); GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this); } bool ServerConnexion::UpdateSocket() { CheckKeepAlive(); return Connexion::UpdateSocket(); } void ServerConnexion::CheckKeepAlive() { std::uint64_t time = utils::GetTime(); if (time - m_KeepAlive.sendTime > KEEP_ALIVE_TIMEOUT) { if (m_KeepAlive.recievedResponse) { SendKeepAlive(); } else { protocol::DisconnectPacket packet("Time out"); SendPacket(&packet); CloseConnection(); } } } void ServerConnexion::SendKeepAlive() { m_KeepAlive.keepAliveID = utils::GetRandomInt(0, RAND_MAX); m_KeepAlive.recievedResponse = false; protocol::KeepAlivePacket keepAlivePacket(m_KeepAlive.keepAliveID); SendPacket(&keepAlivePacket); std::uint64_t time = utils::GetTime(); m_KeepAlive.sendTime = time; } void ServerConnexion::HandlePacket(const protocol::PlayerLoginPacket* packet) { SAFE_CHECK(m_Player->GetName().empty() && !packet->GetPlayerName().empty()); m_Player->SetName(packet->GetPlayerName()); utils::LOG(utils::format("\t[%s] joined !", m_Player->GetName().c_str())); protocol::PlayerJoinPacket joinPacket(m_ID, m_Player->GetName()); m_Server->BroadcastPacket(&joinPacket); std::map playerNames; for (const auto& pair : m_Server->GetPlayers()) { const game::Player& player = pair.second; if (!player.GetName().empty()) { protocol::PlayerInfo playerInfo; playerInfo.name = player.GetName(); playerInfo.team = player.GetTeamColor(); playerNames.insert({ player.GetID(), playerInfo }); } } protocol::PlayerListPacket listPacket(playerNames); SendPacket(&listPacket); protocol::UpdateGameStatePacket statePacket(m_Server->GetGame().GetGameState()); SendPacket(&statePacket); m_Server->GetGame().NotifyListeners(&game::GameListener::OnPlayerJoin, m_ID); protocol::WorldBeginDataPacket headerDataPacket(m_Server->GetGame().GetWorld()); protocol::WorldDataPacket dataPacket(m_Server->GetGame().GetWorld()); SendPacket(&headerDataPacket); SendPacket(&dataPacket); // place towers for (auto tower : m_Server->GetGame().GetWorld()->GetTowers()) { protocol::WorldAddTowerPacket packet(tower->GetID(), static_cast(tower->GetCenterX() - 0.5f), static_cast(tower->GetCenterY() - 0.5f), tower->GetType(), tower->GetBuilder()); SendPacket(&packet); } // spawn mobs for (auto mob : m_Server->GetGame().GetWorld()->GetMobList()) { protocol::SpawnMobPacket packet(mob->GetMobID(), mob->GetType(), mob->GetLevel(), mob->GetSender(), mob->GetCenterX(), mob->GetCenterY(), mob->GetDirection()); SendPacket(&packet); // TODO : update health } } void ServerConnexion::HandlePacket(const protocol::SelectTeamPacket* packet) { SAFE_CHECK(m_Server->GetGame().GetGameState() == game::GameState::Lobby); SAFE_CHECK(static_cast(packet->GetSelectedTeam()) >= -1 || static_cast(packet->GetSelectedTeam()) <= 1); if (m_Player->GetTeamColor() == game::TeamColor::None) { // join a team m_Server->GetGame().GetTeam(packet->GetSelectedTeam()).AddPlayer(m_Player); } else if (packet->GetSelectedTeam() == game::TeamColor::None) { // leave a team m_Server->GetGame().GetTeam(m_Player->GetTeamColor()).RemovePlayer(m_Player); m_Player->SetTeamColor(game::TeamColor::None); } else { // change team m_Server->GetGame().GetTeam(m_Player->GetTeamColor()).RemovePlayer(m_Player); m_Server->GetGame().GetTeam(packet->GetSelectedTeam()).AddPlayer(m_Player); } m_Player->SetTeamColor(packet->GetSelectedTeam()); protocol::UpdatePlayerTeamPacket updateTeamPacket(m_ID, packet->GetSelectedTeam()); m_Server->BroadcastPacket(&updateTeamPacket); } void ServerConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) { SAFE_CHECK(packet->GetAliveID() == m_KeepAlive.keepAliveID); m_KeepAlive.recievedResponse = true; } void ServerConnexion::HandlePacket(const protocol::DisconnectPacket* packet) { CloseConnection(); } void ServerConnexion::SetServer(Server* server) { m_Server = server; m_Player = &m_Server->GetPlayers().at(m_ID); InitConnection(); SendKeepAlive(); } void ServerConnexion::InitConnection() { protocol::ConnexionInfoPacket conPacket(m_ID); SendPacket(&conPacket); } void ServerConnexion::HandlePacket(const protocol::PlaceTowerPacket* packet) { game::TowerType towerType = packet->GetTowerType(); const game::TowerInfo& towerInfo = game::GetTowerInfo(towerType); server::ServerWorld* world = m_Server->GetGame().GetServerWorld(); Vec2f towerPos = { static_cast(packet->GetTowerX()), static_cast(packet->GetTowerY()) }; SAFE_CHECK(world->CanPlaceLittleTower(towerPos, m_ID)); if (towerInfo.IsBigTower()) SAFE_CHECK(world->CanPlaceBigTower(towerPos, m_ID)); game::TowerPtr tower = world->PlaceTowerAt(towerType, packet->GetTowerX(), packet->GetTowerY(), m_ID); world->GetWorldNotifier().NotifyListeners(&game::WorldListener::OnTowerAdd, tower); protocol::WorldAddTowerPacket addTowerPacket(tower->GetID(), packet->GetTowerX(), packet->GetTowerY(), packet->GetTowerType(), m_ID); m_Server->BroadcastPacket(&addTowerPacket); } void ServerConnexion::HandlePacket(const protocol::SendMobsPacket* packet) { const std::vector& mobSent = packet->GetMobSends(); //TODO: verify the packet for (protocol::MobSend mobSend : mobSent) { m_Server->GetGame().GetServerWorld()->SpawnMobs(mobSend.mobType, mobSend.mobLevel, m_ID, mobSend.mobCount); } } void ServerConnexion::HandlePacket(const protocol::UpgradeTowerPacket* packet) { //TODO: verify the packet m_Server->BroadcastPacket(packet); } void ServerConnexion::HandlePacket(const protocol::RemoveTowerPacket* packet) { //TODO: verify the packet m_Server->BroadcastPacket(packet); } ServerConnexion::~ServerConnexion() { SAFE_CHECK(GetDispatcher() != nullptr); GetDispatcher()->UnregisterHandler(this); } } // namespace server } // namespace td