Files
Tower-Defense/src/game/server/ServerConnexion.cpp

189 lines
6.6 KiB
C++

#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 <chrono>
#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<std::uint64_t>(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<std::uint8_t, protocol::PlayerInfo> 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<protocol::MobSend>& 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