#pragma once #include #include #include #include "network/TCPListener.h" #include "protocol/Protocol.h" #include "protocol/PacketDispatcher.h" #include "protocol/PacketHandler.h" #include "ServerGame.h" #include "ServerConnexion.h" #include "Lobby.h" #define SERVER_TPS 20 #define SERVER_TICK 1000 / SERVER_TPS namespace td { namespace server { typedef std::map ConnexionMap; class TickCounter { private: float m_TPS; std::uint64_t m_LastTPSTime; std::uint8_t m_TickCount; public: TickCounter() {} void Reset() { m_TPS = SERVER_TPS; m_LastTPSTime = utils::GetTime(); m_TickCount = 0; } bool Update() { // return true when tps is updated m_TickCount++; if (m_TickCount >= SERVER_TPS) { std::uint64_t timeElapsedSinceLast20Ticks = td::utils::GetTime() - m_LastTPSTime; m_TPS = (float)SERVER_TPS / (float)(timeElapsedSinceLast20Ticks / 1000.0f); m_TickCount = 0; m_LastTPSTime = td::utils::GetTime(); return true; } return false; } float GetTPS() const { return m_TPS; } }; class Server { private: network::TCPListener m_Listener; ConnexionMap m_Connections; ServerGame m_Game{ this }; Lobby m_Lobby{ this }; TickCounter m_TickCounter; std::thread m_Thread; bool m_ServerRunning; public: Server(const std::string& worldFilePath); virtual ~Server(); bool Start(std::uint16_t port); void Stop(); // force the server to stop void Close(); // at the end of a game void RemoveConnexion(std::uint8_t connexionID); void BroadcastPacket(const protocol::Packet* packet); float GetTPS() const { return m_TickCounter.GetTPS(); } bool IsRunning() { return m_ServerRunning; } const ServerGame& GetGame() const { return m_Game; } ServerGame& GetGame() { return m_Game; } const Lobby& GetLobby() const { return m_Lobby; } const ConnexionMap& GetConnexions() const { return m_Connections; } ConnexionMap& GetConnexions() { return m_Connections; } const game::PlayerList& GetPlayers() const { return m_Game.GetPlayers(); } game::PlayerList& GetPlayers() { return m_Game.GetPlayers(); } private: void Accept(); void UpdateSockets(); void Clean(); void StartThread(); void StopThread(); void Tick(std::uint64_t delta); void OnPlayerJoin(std::uint8_t id); void OnPlayerLeave(std::uint8_t id); }; } // namespace server } // namespace td