From f521cbeb31e90e4c5c25edb6686544530ddbaf99 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 16 Dec 2013 10:41:35 +0100 Subject: Fixed cClientHandle::Tick() being called from two threads. When the player was initialized, the Tick() function continued to stream chunk, while the cWorld called Tick() from its tick thread. Final fix for #187. --- src/ClientHandle.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++------ src/ClientHandle.h | 4 ++++ src/Entities/Player.cpp | 22 ---------------------- src/Entities/Player.h | 2 -- src/Server.cpp | 2 +- 5 files changed, 48 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index d082725b6..8a41b5fac 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1476,12 +1476,6 @@ void cClientHandle::Tick(float a_Dt) } m_Protocol->DataReceived(IncomingData.data(), IncomingData.size()); - if (m_State == csAuthenticated) - { - StreamChunks(); - m_State = csDownloadingWorld; - } - m_TimeSinceLastPacket += a_Dt; if (m_TimeSinceLastPacket > 30000.f) // 30 seconds time-out { @@ -1536,6 +1530,49 @@ void cClientHandle::Tick(float a_Dt) +void cClientHandle::ServerTick(float a_Dt) +{ + // Handle clients that are waiting for final close while destroyed: + if (m_State == csDestroyedWaiting) + { + // Do not wait while the client is not in the world, simply cut them off. + m_State = csDestroyed; + return; + } + + // Process received network data: + AString IncomingData; + { + cCSLock Lock(m_CSIncomingData); + std::swap(IncomingData, m_IncomingData); + } + m_Protocol->DataReceived(IncomingData.data(), IncomingData.size()); + + if (m_State == csAuthenticated) + { + StreamChunks(); + + // Remove the client handle from the server, it will be ticked from its cPlayer object from now on + cRoot::Get()->GetServer()->ClientMovedToWorld(this); + + // Add the player to the world (start ticking from there): + m_State = csDownloadingWorld; + m_Player->GetWorld()->AddPlayer(m_Player); + return; + } + + m_TimeSinceLastPacket += a_Dt; + if (m_TimeSinceLastPacket > 30000.f) // 30 seconds time-out + { + SendDisconnect("Nooooo!! You timed out! D: Come back!"); + Destroy(); + } +} + + + + + void cClientHandle::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle) { m_Protocol->SendAttachEntity(a_Entity, a_Vehicle); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 147a5b2b3..18274f6ae 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -79,7 +79,11 @@ public: inline bool IsLoggedIn(void) const { return (m_State >= csAuthenticating); } + /// Called while the client is being ticked from the world via its cPlayer object void Tick(float a_Dt); + + /// Called while the client is being ticked from the cServer object + void ServerTick(float a_Dt); void Destroy(void); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 5165c2f8a..7e7d77433 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -137,28 +137,6 @@ cPlayer::~cPlayer(void) -bool cPlayer::Initialize(cWorld * a_World) -{ - ASSERT(a_World != NULL); - - if (super::Initialize(a_World)) - { - // Remove the client handle from the server, it will be ticked from this object from now on - if (m_ClientHandle != NULL) - { - cRoot::Get()->GetServer()->ClientMovedToWorld(m_ClientHandle); - } - - GetWorld()->AddPlayer(this); - return true; - } - return false; -} - - - - - void cPlayer::Destroyed() { CloseWindow(false); diff --git a/src/Entities/Player.h b/src/Entities/Player.h index a09f7f489..59e941040 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -41,8 +41,6 @@ public: cPlayer(cClientHandle * a_Client, const AString & a_PlayerName); virtual ~cPlayer(); - virtual bool Initialize(cWorld * a_World) override; - virtual void SpawnOn(cClientHandle & a_Client) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; diff --git a/src/Server.cpp b/src/Server.cpp index f90f7a474..a93be9a5b 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -402,7 +402,7 @@ void cServer::TickClients(float a_Dt) itr = m_Clients.erase(itr); continue; } - (*itr)->Tick(a_Dt); + (*itr)->ServerTick(a_Dt); ++itr; } // for itr - m_Clients[] } -- cgit v1.2.3