Fixed a race condition between chunk loader and generator.
When using ChunkWorx to generate multiple chunks, the server would sometimes fail an assert because it would generate a chunk even when it was successfully loaded. This was caused by chunks queued in cWorld's m_SetChunkDataQueue and thus being marked as "InQueue" although they were already loaded. Solved by adding a new parameter to chunk coord callbacks specifying whether the operation succeeded or failed, and using that instead of the chunk presence flag to decide whether to generate or not.
This commit is contained in:
@@ -164,32 +164,6 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallba
|
||||
|
||||
|
||||
|
||||
void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_LoadQueue.RemoveIf([=](cChunkCoordsWithCallback & a_Item)
|
||||
{
|
||||
return (a_Item.m_ChunkX == a_ChunkX) && (a_Item.m_ChunkZ == a_ChunkZ);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorldStorage::UnqueueSave(const cChunkCoords & a_Chunk)
|
||||
{
|
||||
m_SaveQueue.RemoveIf([=](cChunkCoordsWithCallback & a_Item)
|
||||
{
|
||||
return (a_Item.m_ChunkX == a_Chunk.m_ChunkX) && (a_Item.m_ChunkZ == a_Chunk.m_ChunkZ);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorldStorage::InitSchemas(int a_StorageCompressionFactor)
|
||||
{
|
||||
// The first schema added is considered the default
|
||||
@@ -266,7 +240,7 @@ bool cWorldStorage::LoadOneChunk(void)
|
||||
// Call the callback, if specified:
|
||||
if (ToLoad.m_Callback != nullptr)
|
||||
{
|
||||
ToLoad.m_Callback->Call(ToLoad.m_ChunkX, ToLoad.m_ChunkZ);
|
||||
ToLoad.m_Callback->Call(ToLoad.m_ChunkX, ToLoad.m_ChunkZ, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -286,19 +260,21 @@ bool cWorldStorage::SaveOneChunk(void)
|
||||
}
|
||||
|
||||
// Save the chunk, if it's valid:
|
||||
bool Status = false;
|
||||
if (m_World->IsChunkValid(ToSave.m_ChunkX, ToSave.m_ChunkZ))
|
||||
{
|
||||
m_World->MarkChunkSaving(ToSave.m_ChunkX, ToSave.m_ChunkZ);
|
||||
if (m_SaveSchema->SaveChunk(cChunkCoords(ToSave.m_ChunkX, ToSave.m_ChunkZ)))
|
||||
{
|
||||
m_World->MarkChunkSaved(ToSave.m_ChunkX, ToSave.m_ChunkZ);
|
||||
Status = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Call the callback, if specified:
|
||||
if (ToSave.m_Callback != nullptr)
|
||||
{
|
||||
ToSave.m_Callback->Call(ToSave.m_ChunkX, ToSave.m_ChunkZ);
|
||||
ToSave.m_Callback->Call(ToSave.m_ChunkX, ToSave.m_ChunkZ, Status);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,13 +63,15 @@ public:
|
||||
|
||||
cWorldStorage(void);
|
||||
~cWorldStorage();
|
||||
|
||||
|
||||
/** Queues a chunk to be loaded, asynchronously.
|
||||
The callback, if specified, will be called with the result of the load operation. */
|
||||
void QueueLoadChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback = nullptr);
|
||||
|
||||
/** Queues a chunk to be saved, asynchronously.
|
||||
The callback, if specified, will be called with the result of the save operation. */
|
||||
void QueueSaveChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback = nullptr);
|
||||
|
||||
void UnqueueLoad(int a_ChunkX, int a_ChunkZ);
|
||||
void UnqueueSave(const cChunkCoords & a_Chunk);
|
||||
|
||||
bool Start(cWorld * a_World, const AString & a_StorageSchemaName, int a_StorageCompressionFactor); // Hide the cIsThread's Start() method, we need to provide args
|
||||
void Stop(void); // Hide the cIsThread's Stop() method, we need to signal the event
|
||||
void WaitForFinish(void);
|
||||
|
||||
Reference in New Issue
Block a user