diff --git a/source/Server.cpp b/source/Server.cpp index 509c84af3..4247a1dfe 100644 --- a/source/Server.cpp +++ b/source/Server.cpp @@ -59,18 +59,42 @@ typedef std::list< cClientHandle* > ClientList; -struct cServer::sServerState +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cServer::cTickThread: + +cServer::cTickThread::cTickThread(cServer & a_Server) : + super("ServerTickThread"), + m_Server(a_Server) { - sServerState() - : pTickThread(NULL) - , bStopTickThread(false) - {} +} - cThread* pTickThread; bool bStopTickThread; - cEvent RestartEvent; - std::string ServerID; -}; + + + +void cServer::cTickThread::Execute(void) +{ + cTimer Timer; + + long long msPerTick = 50; // TODO - Put this in server config file + long long LastTime = Timer.GetNowTime(); + + while (!m_ShouldTerminate) + { + long long NowTime = Timer.GetNowTime(); + float DeltaTime = (float)(NowTime-LastTime); + m_ShouldTerminate = !m_Server.Tick(DeltaTime); + long long TickTime = Timer.GetNowTime() - NowTime; + + if (TickTime < msPerTick) + { + // Stretch tick time until it's at least msPerTick + cSleep::MilliSleep((unsigned int)(msPerTick - TickTime)); + } + + LastTime = NowTime; + } +} @@ -80,14 +104,12 @@ struct cServer::sServerState // cServer: cServer::cServer(void) : - m_pState(new sServerState), m_ListenThreadIPv4(*this, cSocket::IPv4, "Client"), m_ListenThreadIPv6(*this, cSocket::IPv6, "Client"), - m_Millisecondsf(0), - m_Milliseconds(0), m_bIsConnected(false), m_bRestarting(false), - m_RCONServer(*this) + m_RCONServer(*this), + m_TickThread(*this) { } @@ -95,19 +117,6 @@ cServer::cServer(void) : -cServer::~cServer() -{ - // TODO: Shut down the server gracefully - m_pState->bStopTickThread = true; - delete m_pState->pTickThread; m_pState->pTickThread = NULL; - - delete m_pState; -} - - - - - void cServer::ClientDestroying(const cClientHandle * a_Client) { m_SocketThreads.StopReading(a_Client); @@ -199,18 +208,17 @@ bool cServer::InitServer(cIniFile & a_SettingsIni) m_bIsConnected = true; - m_pState->ServerID = "-"; + m_ServerID = "-"; if (a_SettingsIni.GetValueSetB("Authentication", "Authenticate", true)) { MTRand mtrand1; - unsigned int r1 = (mtrand1.randInt()%1147483647) + 1000000000; - unsigned int r2 = (mtrand1.randInt()%1147483647) + 1000000000; + unsigned int r1 = (mtrand1.randInt() % 1147483647) + 1000000000; + unsigned int r2 = (mtrand1.randInt() % 1147483647) + 1000000000; std::ostringstream sid; sid << std::hex << r1; sid << std::hex << r2; - std::string ServerID = sid.str(); - ServerID.resize(16, '0'); - m_pState->ServerID = ServerID; + m_ServerID = sid.str(); + m_ServerID.resize(16, '0'); } m_ClientViewDistance = a_SettingsIni.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE); @@ -309,15 +317,8 @@ void cServer::BroadcastChat(const AString & a_Message, const cClientHandle * a_E bool cServer::Tick(float a_Dt) { - m_Millisecondsf += a_Dt; - if (m_Millisecondsf > 1.f) - { - m_Milliseconds += (int)m_Millisecondsf; - m_Millisecondsf = m_Millisecondsf - (int)m_Millisecondsf; - } - - cRoot::Get()->TickWorlds(a_Dt); // TODO - Maybe give all worlds their own thread? - + cRoot::Get()->TickWorlds(a_Dt); + cClientHandleList RemoveClients; { cCSLock Lock(m_CSClients); @@ -338,8 +339,6 @@ bool cServer::Tick(float a_Dt) delete *itr; } // for itr - RemoveClients[] - cRoot::Get()->GetPluginManager()->Tick(a_Dt); - if (!m_bRestarting) { return true; @@ -347,7 +346,7 @@ bool cServer::Tick(float a_Dt) else { m_bRestarting = false; - m_pState->RestartEvent.Set(); + m_RestartEvent.Set(); return false; } } @@ -356,42 +355,8 @@ bool cServer::Tick(float a_Dt) -void ServerTickThread( void * a_Param ) -{ - LOG("ServerTickThread"); - cServer *CServerObj = (cServer*)a_Param; - - cTimer Timer; - - long long msPerTick = 50; // TODO - Put this in server config file - long long LastTime = Timer.GetNowTime(); - - bool bKeepGoing = true; - while( bKeepGoing ) - { - long long NowTime = Timer.GetNowTime(); - float DeltaTime = (float)(NowTime-LastTime); - bKeepGoing = CServerObj->Tick( DeltaTime ); - long long TickTime = Timer.GetNowTime() - NowTime; - - if( TickTime < msPerTick ) // Stretch tick time until it's at least msPerTick - { - cSleep::MilliSleep( (unsigned int)( msPerTick - TickTime ) ); - } - - LastTime = NowTime; - } - - LOG("TICK THREAD STOPPED"); -} - - - - - bool cServer::Start(void) { - m_pState->pTickThread = new cThread( ServerTickThread, this, "cServer::ServerTickThread" ); if (!m_ListenThreadIPv4.Start()) { return false; @@ -400,7 +365,10 @@ bool cServer::Start(void) { return false; } - m_pState->pTickThread->Start( true ); + if (!m_TickThread.Start()) + { + return false; + } return true; } @@ -503,13 +471,13 @@ void cServer::SendMessage(const AString & a_Message, cPlayer * a_Player /* = NUL -void cServer::Shutdown() +void cServer::Shutdown(void) { m_ListenThreadIPv4.Stop(); m_ListenThreadIPv6.Stop(); m_bRestarting = true; - m_pState->RestartEvent.Wait(); + m_RestartEvent.Wait(); cRoot::Get()->SaveAllChunks(); @@ -526,15 +494,6 @@ void cServer::Shutdown() -const AString & cServer::GetServerID(void) const -{ - return m_pState->ServerID; -} - - - - - void cServer::KickUser(int a_ClientID, const AString & a_Reason) { cCSLock Lock(m_CSClients); @@ -568,7 +527,7 @@ void cServer::AuthenticateUser(int a_ClientID) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cServer::cClientPacketThread: +// cServer::cNotifyWriteThread: cServer::cNotifyWriteThread::cNotifyWriteThread(void) : super("ClientPacketThread"), diff --git a/source/Server.h b/source/Server.h index 44e20eec1..983dc4de8 100644 --- a/source/Server.h +++ b/source/Server.h @@ -52,8 +52,6 @@ public: // tolua_export void BroadcastChat(const AString & a_Message, const cClientHandle * a_Exclude = NULL); // tolua_export - bool Tick(float a_Dt); - bool Start(void); bool Command(cClientHandle & a_Client, AString & a_Cmd); @@ -71,7 +69,7 @@ public: // tolua_export void KickUser(int a_ClientID, const AString & a_Reason); void AuthenticateUser(int a_ClientID); // Called by cAuthenticator to auth the specified user - const AString & GetServerID(void) const; // tolua_export + const AString & GetServerID(void) const { return m_ServerID; } // tolua_export void ClientDestroying(const cClientHandle * a_Client); // Called by cClientHandle::Destroy(); stop m_SocketThreads from calling back into a_Client @@ -114,8 +112,22 @@ private: void NotifyClientWrite(const cClientHandle * a_Client); } ; - struct sServerState; - sServerState * m_pState; + /// The server tick thread takes care of the players who aren't yet spawned in a world + class cTickThread : + public cIsThread + { + typedef cIsThread super; + + public: + cTickThread(cServer & a_Server); + + protected: + cServer & m_Server; + + // cIsThread overrides: + virtual void Execute(void) override; + } ; + cNotifyWriteThread m_NotifyWriteThread; @@ -129,10 +141,6 @@ private: int m_ClientViewDistance; // The default view distance for clients; settable in Settings.ini - // Time since server was started - float m_Millisecondsf; - unsigned int m_Milliseconds; - bool m_bIsConnected; // true - connected false - not connected bool m_bRestarting; @@ -146,13 +154,20 @@ private: int m_MaxPlayers; int m_NumPlayers; + cTickThread m_TickThread; + cEvent m_RestartEvent; + + /// The server ID used for client authentication + AString m_ServerID; + cServer(void); - ~cServer(); /// Loads, or generates, if missing, RSA keys for protocol encryption void PrepareKeys(void); + bool Tick(float a_Dt); + // cListenThread::cCallback overrides: virtual void OnConnectionAccepted(cSocket & a_Socket) override; }; // tolua_export