#include "game/server/ServerConnexion.h" #include "protocol/PacketDispatcher.h" #include "protocol/PacketFactory.h" #include "game/server/Server.h" #include "misc/Time.h" #include "misc/Random.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); } 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) { if (m_Player->getName().empty() && !packet->getPlayerName().empty()) { m_Player->setName(packet->getPlayerName()); 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); } } void ServerConnexion::HandlePacket(const protocol::SelectTeamPacket* packet) { if (m_Server->getGame().getGameState() != game::GameState::Lobby) return; if ((std::int8_t)packet->getSelectedTeam() >= -1 || (std::int8_t)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) { if (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::UpdateGameStatePacket statePacket(m_Server->getGame().getGameState()); sendPacket(&statePacket); protocol::ConnexionInfoPacket conPacket(m_ID); sendPacket(&conPacket); if (m_Server->getGame().getGameState() == game::GameState::Game) { protocol::WorldBeginDataPacket headerDataPacket(m_Server->getGame().getWorld()); protocol::WorldBeginDataPacket dataPacket(m_Server->getGame().getWorld()); sendPacket(&headerDataPacket); sendPacket(&dataPacket); } } 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(); if (!world->CanPlaceLittleTower({ packet->getTowerX(), packet->getTowerY() }, m_ID)) return; if (towerInfo.isBigTower()) if (!world->CanPlaceBigTower({ packet->getTowerX(), packet->getTowerY() }, m_ID)) return; game::TowerPtr tower = world->placeTowerAt(towerType, packet->getTowerX(), packet->getTowerY(), m_ID); 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); } ServerConnexion::~ServerConnexion() { if (GetDispatcher() != nullptr) GetDispatcher()->UnregisterHandler(this); } } // namespace server } // namespace td