#include "server/game/ServerGame.h" #include "server/Server.h" #include "td/protocol/packets/DisconnectPacket.h" #include "td/protocol/packets/UpdatePlayerTeamPacket.h" #include "td/protocol/packets/UpdateGameStatePacket.h" #include "td/protocol/packets/UpdateMoneyPacket.h" #include "td/protocol/packets/UpdateExpPacket.h" #include "td/protocol/packets/UpdateMobStatesPacket.h" #include "td/protocol/packets/WorldDataPacket.h" #include "td/protocol/packets/WorldBeginDataPacket.h" namespace td { namespace server { ServerGame::ServerGame(server::Server* server) : game::Game(&m_ServerWorld), m_Server(server), m_ServerWorld(server, this), m_GoldMineTimer{ 1000, std::bind(&ServerGame::UpdateGoldMines, this) }, m_MobStatesTimer{ 5000, std::bind(&ServerGame::UpdateMobStates, this) }, m_EndGameCooldown{ 1000 * 10 } { BindListener(this); } void ServerGame::Tick(std::uint64_t delta) { if (m_GameState == game::GameState::Game) { Game::Tick(delta); m_MobStatesTimer.Update(delta); UpdatePlayerStats(); } else if (m_GameState == game::GameState::EndGame) { if (m_EndGameCooldown.Update(delta)) { NotifyListeners(&game::GameListener::OnGameClose); } } } void ServerGame::StartGame() { BalanceTeams(); protocol::WorldBeginDataPacket headerMapData(m_World); m_Server->BroadcastPacket(&headerMapData); protocol::WorldDataPacket mapData(m_World); m_Server->BroadcastPacket(&mapData); InitPlayerStats(); m_GameState = game::GameState::Game; } void ServerGame::InitPlayerStats() { static const unsigned int START_GOLD = 100; static const unsigned int START_EXP = 0; for (auto& [id, player] : m_Server->GetPlayers()) { player.SetGold(START_GOLD); player.SetExp(START_EXP); player.getUpgrades().SetGoldPerSecond(5); } } void ServerGame::UpdatePlayerStats() { m_GoldMineTimer.Update(); } void ServerGame::UpdateGoldMines() { for (auto& [id, player] : m_Server->GetPlayers()) { player.AddGold(player.getUpgrades().GetGoldPerSecond()); // Update player money and exp every second protocol::UpdateMoneyPacket moneyPacket(player.GetGold()); m_Server->GetConnexions()[player.GetID()].SendPacket(&moneyPacket); protocol::UpdateExpPacket expPacket(player.GetExp()); m_Server->GetConnexions()[player.GetID()].SendPacket(&expPacket); } } void ServerGame::UpdateMobStates() { protocol::UpdateMobStatesPacket packet; for (auto mob : m_World->GetMobList()) { packet.addMobState({ mob->GetMobID(), mob->GetCenter(), mob->GetHealth(), mob->GetDirection() }); } m_Server->BroadcastPacket(&packet); } void ServerGame::BalanceTeams() { for (auto& playerInfo : Game::m_Players) { game::Player& player = playerInfo.second; if (player.GetTeamColor() == game::TeamColor::None) { game::Team& redTeam = GetRedTeam(); game::Team& blueTeam = GetBlueTeam(); if (blueTeam.GetPlayerCount() > redTeam.GetPlayerCount()) { player.SetTeamColor(game::TeamColor::Red); redTeam.AddPlayer(&player); } else { player.SetTeamColor(game::TeamColor::Blue); blueTeam.AddPlayer(&player); } protocol::UpdatePlayerTeamPacket packet(player.GetID(), player.GetTeamColor()); m_Server->BroadcastPacket(&packet); } } } void ServerGame::Reset() { Game::Reset(); // update players teams to none for (auto& playerInfo : m_Players) { game::Player& player = playerInfo.second; protocol::UpdatePlayerTeamPacket packet(player.GetID(), player.GetTeamColor()); m_Server->BroadcastPacket(&packet); } } void ServerGame::OnGameStateUpdate(game::GameState newState) { SetGameState(newState); protocol::UpdateGameStatePacket packet(newState); m_Server->BroadcastPacket(&packet); } void ServerGame::OnGameBegin() { NotifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::Game); StartGame(); } void ServerGame::OnGameEnd() { NotifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::EndGame); m_EndGameCooldown.ApplyCooldown(); } void ServerGame::OnGameClose() { NotifyListeners(&game::GameListener::OnGameStateUpdate, game::GameState::Closed); // Put back to lobby state m_Server->Restart(); } } // namespace game } // namespace td