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 )
|
||||
{
|
||||
m_LoadedByClient.remove( a_Client );
|
||||
|
||||
if ( !a_Client->IsDestroyed() )
|
||||
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
|
||||
{
|
||||
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() );
|
||||
cPacket_DestroyEntity DestroyEntity( *itr );
|
||||
a_Client->Send( DestroyEntity );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 NumChunks = 0;
|
||||
|
@ -102,8 +102,8 @@ public:
|
||||
/// Removes the client from the chunk
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from all chunks specified
|
||||
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
|
||||
/// Removes the client from all chunks it is present in
|
||||
void RemoveClientFromChunks(cClientHandle * a_Client);
|
||||
|
||||
/// 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);
|
||||
@ -162,6 +162,8 @@ private:
|
||||
|
||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||
|
||||
void RemoveClient(cClientHandle * a_Client);
|
||||
|
||||
protected:
|
||||
|
||||
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
|
||||
void cClientHandle::RemoveFromAllChunks()
|
||||
{
|
||||
cCSLock Lock(m_CSChunkLists);
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
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
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from all chunks specified
|
||||
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
|
||||
/// Removes the client from all chunks it is present in
|
||||
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)
|
||||
void SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
Loading…
Reference in New Issue
Block a user