Fixed a deadlock by removing clients from all chunks upon their exit, not using the clients chunklists.
git-svn-id: http://mc-server.googlecode.com/svn/trunk@426 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
ed7b680d3c
commit
389062a1ed
@ -1196,17 +1196,26 @@ bool cChunk::AddClient(cClientHandle* a_Client)
|
|||||||
|
|
||||||
void cChunk::RemoveClient( cClientHandle* a_Client )
|
void cChunk::RemoveClient( cClientHandle* a_Client )
|
||||||
{
|
{
|
||||||
m_LoadedByClient.remove( a_Client );
|
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
|
||||||
|
|
||||||
if ( !a_Client->IsDestroyed() )
|
|
||||||
{
|
{
|
||||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
|
if (*itr != a_Client)
|
||||||
{
|
{
|
||||||
LOG("chunk [%i, %i] destroying entity #%i for player \"%s\"", m_PosX, m_PosZ, (*itr)->GetUniqueID(), a_Client->GetUsername().c_str() );
|
continue;
|
||||||
cPacket_DestroyEntity DestroyEntity( *itr );
|
|
||||||
a_Client->Send( DestroyEntity );
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
m_LoadedByClient.erase(itr);
|
||||||
|
|
||||||
|
if ( !a_Client->IsDestroyed() )
|
||||||
|
{
|
||||||
|
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
|
||||||
|
{
|
||||||
|
LOGD("chunk [%i, %i] destroying entity #%i for player \"%s\"", m_PosX, m_PosZ, (*itr)->GetUniqueID(), a_Client->GetUsername().c_str() );
|
||||||
|
cPacket_DestroyEntity DestroyEntity( *itr );
|
||||||
|
a_Client->Send( DestroyEntity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} // for itr - m_LoadedByClient[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -747,14 +747,14 @@ void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cCli
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks)
|
void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
|
|
||||||
for (cChunkCoordsList::const_iterator itr = a_Chunks.begin(); itr != a_Chunks.end(); ++itr)
|
for (cChunkLayerList::const_iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
||||||
{
|
{
|
||||||
GetChunkNoGen(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ)->RemoveClient(a_Client);
|
(*itr)->RemoveClient(a_Client);
|
||||||
}
|
} // for itr - m_Layers[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1006,6 +1006,21 @@ void cChunkMap::cChunkLayer::Tick(float a_Dt, MTRand & a_TickRand)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkMap::cChunkLayer::RemoveClient(cClientHandle * a_Client)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||||
|
{
|
||||||
|
if (m_Chunks[i] != NULL)
|
||||||
|
{
|
||||||
|
m_Chunks[i]->RemoveClient(a_Client);
|
||||||
|
}
|
||||||
|
} // for i - m_Chunks[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cChunkMap::cChunkLayer::GetNumChunksLoaded(void) const
|
int cChunkMap::cChunkLayer::GetNumChunksLoaded(void) const
|
||||||
{
|
{
|
||||||
int NumChunks = 0;
|
int NumChunks = 0;
|
||||||
|
@ -102,8 +102,8 @@ public:
|
|||||||
/// Removes the client from the chunk
|
/// Removes the client from the chunk
|
||||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||||
|
|
||||||
/// Removes the client from all chunks specified
|
/// Removes the client from all chunks it is present in
|
||||||
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
|
void RemoveClientFromChunks(cClientHandle * a_Client);
|
||||||
|
|
||||||
/// Moves the entity from its current chunk to the new chunk specified
|
/// Moves the entity from its current chunk to the new chunk specified
|
||||||
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||||
@ -162,6 +162,8 @@ private:
|
|||||||
|
|
||||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||||
|
|
||||||
|
void RemoveClient(cClientHandle * a_Client);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
cChunkPtr m_Chunks[LAYER_SIZE * LAYER_SIZE];
|
cChunkPtr m_Chunks[LAYER_SIZE * LAYER_SIZE];
|
||||||
|
@ -461,14 +461,17 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
|||||||
// Removes the client from all chunks. Used when switching worlds or destroying the player
|
// Removes the client from all chunks. Used when switching worlds or destroying the player
|
||||||
void cClientHandle::RemoveFromAllChunks()
|
void cClientHandle::RemoveFromAllChunks()
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSChunkLists);
|
|
||||||
cWorld * World = m_Player->GetWorld();
|
cWorld * World = m_Player->GetWorld();
|
||||||
if (World != NULL)
|
if (World != NULL)
|
||||||
{
|
{
|
||||||
World->RemoveClientFromChunks(this, m_LoadedChunks);
|
World->RemoveClientFromChunks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSChunkLists);
|
||||||
|
m_LoadedChunks.clear();
|
||||||
|
m_ChunksToSend.clear();
|
||||||
}
|
}
|
||||||
m_LoadedChunks.clear();
|
|
||||||
m_ChunksToSend.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1345,9 +1345,9 @@ void cWorld::RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClient
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks)
|
void cWorld::RemoveClientFromChunks(cClientHandle * a_Client)
|
||||||
{
|
{
|
||||||
m_ChunkMap->RemoveClientFromChunks(a_Client, a_Chunks);
|
m_ChunkMap->RemoveClientFromChunks(a_Client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,8 +150,8 @@ public:
|
|||||||
/// Removes client from the chunk specified
|
/// Removes client from the chunk specified
|
||||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||||
|
|
||||||
/// Removes the client from all chunks specified
|
/// Removes the client from all chunks it is present in
|
||||||
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
|
void RemoveClientFromChunks(cClientHandle * a_Client);
|
||||||
|
|
||||||
/// Sends the chunk to the client specified, if the chunk is valid. If not valid, the request is ignored (ChunkSender will send that chunk when it becomes valid)
|
/// Sends the chunk to the client specified, if the chunk is valid. If not valid, the request is ignored (ChunkSender will send that chunk when it becomes valid)
|
||||||
void SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
void SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||||
|
Loading…
Reference in New Issue
Block a user