Rewritten chunk status to specify whether the chunk is in queue.
This fixes #1370.
This commit is contained in:
parent
e15b8600a6
commit
137b021d26
|
@ -71,7 +71,7 @@ cChunk::cChunk(
|
||||||
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP,
|
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP,
|
||||||
cAllocationPool<cChunkData::sChunkSection> & a_Pool
|
cAllocationPool<cChunkData::sChunkSection> & a_Pool
|
||||||
) :
|
) :
|
||||||
m_IsValid(false),
|
m_Presence(cpInvalid),
|
||||||
m_IsLightValid(false),
|
m_IsLightValid(false),
|
||||||
m_IsDirty(false),
|
m_IsDirty(false),
|
||||||
m_IsSaving(false),
|
m_IsSaving(false),
|
||||||
|
@ -165,11 +165,22 @@ cChunk::~cChunk()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::SetValid(void)
|
void cChunk::SetPresence(cChunk::ePresence a_Presence)
|
||||||
{
|
{
|
||||||
m_IsValid = true;
|
m_Presence = a_Presence;
|
||||||
|
if (a_Presence == cpPresent)
|
||||||
m_World->GetChunkMap()->ChunkValidated();
|
{
|
||||||
|
m_World->GetChunkMap()->ChunkValidated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunk::SetShouldGenerateIfLoadFailed(bool a_ShouldGenerateIfLoadFailed)
|
||||||
|
{
|
||||||
|
m_ShouldGenerateIfLoadFailed = a_ShouldGenerateIfLoadFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,6 +189,9 @@ void cChunk::SetValid(void)
|
||||||
|
|
||||||
void cChunk::MarkRegenerating(void)
|
void cChunk::MarkRegenerating(void)
|
||||||
{
|
{
|
||||||
|
// Set as queued again:
|
||||||
|
SetPresence(cpQueued);
|
||||||
|
|
||||||
// Tell all clients attached to this chunk that they want this chunk:
|
// Tell all clients attached to this chunk that they want this chunk:
|
||||||
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
|
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
|
||||||
{
|
{
|
||||||
|
@ -191,7 +205,11 @@ void cChunk::MarkRegenerating(void)
|
||||||
|
|
||||||
bool cChunk::CanUnload(void)
|
bool cChunk::CanUnload(void)
|
||||||
{
|
{
|
||||||
return m_LoadedByClient.empty() && !m_IsDirty && (m_StayCount == 0);
|
return
|
||||||
|
m_LoadedByClient.empty() && // The chunk is not used by any client
|
||||||
|
!m_IsDirty && // The chunk has been saved properly or hasn't been touched since the load / gen
|
||||||
|
(m_StayCount == 0) && // The chunk is not in a ChunkStay
|
||||||
|
(m_Presence != cpQueued) ; // The chunk is not queued for loading / generating (otherwise multi-load / multi-gen could occur)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -223,7 +241,7 @@ void cChunk::MarkSaved(void)
|
||||||
void cChunk::MarkLoaded(void)
|
void cChunk::MarkLoaded(void)
|
||||||
{
|
{
|
||||||
m_IsDirty = false;
|
m_IsDirty = false;
|
||||||
SetValid();
|
SetPresence(cpPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,12 +250,17 @@ void cChunk::MarkLoaded(void)
|
||||||
|
|
||||||
void cChunk::MarkLoadFailed(void)
|
void cChunk::MarkLoadFailed(void)
|
||||||
{
|
{
|
||||||
if (m_IsValid)
|
ASSERT(m_Presence == cpQueued);
|
||||||
|
|
||||||
|
// If the chunk is marked as needed, generate it:
|
||||||
|
if (m_ShouldGenerateIfLoadFailed)
|
||||||
{
|
{
|
||||||
return;
|
m_World->GetGenerator().QueueGenerateChunk(m_PosX, m_PosZ, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Presence = cpInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_HasLoadFailed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -246,6 +269,8 @@ void cChunk::MarkLoadFailed(void)
|
||||||
|
|
||||||
void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
||||||
{
|
{
|
||||||
|
ASSERT(m_Presence == cpPresent);
|
||||||
|
|
||||||
a_Callback.HeightMap(&m_HeightMap);
|
a_Callback.HeightMap(&m_HeightMap);
|
||||||
a_Callback.BiomeData(&m_BiomeMap);
|
a_Callback.BiomeData(&m_BiomeMap);
|
||||||
|
|
||||||
|
@ -272,6 +297,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
|
||||||
{
|
{
|
||||||
ASSERT(a_SetChunkData.IsHeightMapValid());
|
ASSERT(a_SetChunkData.IsHeightMapValid());
|
||||||
ASSERT(a_SetChunkData.AreBiomesValid());
|
ASSERT(a_SetChunkData.AreBiomesValid());
|
||||||
|
ASSERT(IsQueued());
|
||||||
|
|
||||||
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
|
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
|
||||||
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
|
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
|
||||||
|
@ -317,7 +343,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
|
||||||
CreateBlockEntities();
|
CreateBlockEntities();
|
||||||
|
|
||||||
// Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize)
|
// Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize)
|
||||||
SetValid();
|
SetPresence(cpPresent);
|
||||||
|
|
||||||
// Wake up all simulators for their respective blocks:
|
// Wake up all simulators for their respective blocks:
|
||||||
WakeUpSimulators();
|
WakeUpSimulators();
|
||||||
|
|
44
src/Chunk.h
44
src/Chunk.h
|
@ -66,6 +66,14 @@ class cChunk :
|
||||||
public cChunkDef // The inheritance is "misused" here only to inherit the functions and constants defined in cChunkDef
|
public cChunkDef // The inheritance is "misused" here only to inherit the functions and constants defined in cChunkDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/** Represents the presence state of the chunk */
|
||||||
|
enum ePresence
|
||||||
|
{
|
||||||
|
cpInvalid, /**< The chunk is not present at all and is not queued in the loader / generator */
|
||||||
|
cpQueued, /**< The chunk is not present, but is queued for loading / generation */
|
||||||
|
cpPresent, /**< The chunk is present */
|
||||||
|
};
|
||||||
|
|
||||||
cChunk(
|
cChunk(
|
||||||
int a_ChunkX, int a_ChunkZ, // Chunk coords
|
int a_ChunkX, int a_ChunkZ, // Chunk coords
|
||||||
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
|
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
|
||||||
|
@ -75,11 +83,25 @@ public:
|
||||||
cChunk(cChunk & other);
|
cChunk(cChunk & other);
|
||||||
~cChunk();
|
~cChunk();
|
||||||
|
|
||||||
bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk block data is valid (loaded / generated)
|
/** Returns true iff the chunk block data is valid (loaded / generated) */
|
||||||
void SetValid(void); // Also wakes up any calls to cChunkMap::GetHeight()
|
bool IsValid(void) const {return (m_Presence == cpPresent); }
|
||||||
void MarkRegenerating(void); // Marks all clients attached to this chunk as wanting this chunk
|
|
||||||
bool IsDirty(void) const {return m_IsDirty; } // Returns true if the chunk has changed since it was last saved
|
/** Returns true iff the chunk is in the queue for loading / generating */
|
||||||
bool HasLoadFailed(void) const {return m_HasLoadFailed; } // Returns true if the chunk failed to load and hasn't been generated since then
|
bool IsQueued(void) const {return (m_Presence == cpQueued); }
|
||||||
|
|
||||||
|
/** Sets the chunk's presence.
|
||||||
|
Wakes up any calls to cChunkMap::GetHeight() when setting to cpPresent. */
|
||||||
|
void SetPresence(ePresence a_Presence);
|
||||||
|
|
||||||
|
/** Called to indicate whether the chunk should be queued in the generator if it fails to load. Set by cChunkMap::GetChunk(). */
|
||||||
|
void SetShouldGenerateIfLoadFailed(bool a_ShouldGenerateIfLoadFailed);
|
||||||
|
|
||||||
|
/** Marks all clients attached to this chunk as wanting this chunk. Also sets presence to cpQueued. */
|
||||||
|
void MarkRegenerating(void);
|
||||||
|
|
||||||
|
/** Returns true iff the chunk has changed since it was last saved. */
|
||||||
|
bool IsDirty(void) const {return m_IsDirty; }
|
||||||
|
|
||||||
bool CanUnload(void);
|
bool CanUnload(void);
|
||||||
|
|
||||||
bool IsLightValid(void) const {return m_IsLightValid; }
|
bool IsLightValid(void) const {return m_IsLightValid; }
|
||||||
|
@ -94,7 +116,10 @@ public:
|
||||||
void MarkSaving(void); // Marks the chunk as being saved.
|
void MarkSaving(void); // Marks the chunk as being saved.
|
||||||
void MarkSaved(void); // Marks the chunk as saved, if it didn't change from the last call to MarkSaving()
|
void MarkSaved(void); // Marks the chunk as saved, if it didn't change from the last call to MarkSaving()
|
||||||
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
|
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
|
||||||
void MarkLoadFailed(void); // Marks the chunk as failed to load. Ignored is the chunk is already valid
|
|
||||||
|
/** Marks the chunk as failed to load.
|
||||||
|
If m_ShouldGenerateIfLoadFailed is set, queues the chunk for generating. */
|
||||||
|
void MarkLoadFailed(void);
|
||||||
|
|
||||||
/** Gets all chunk data, calls the a_Callback's methods for each data type */
|
/** Gets all chunk data, calls the a_Callback's methods for each data type */
|
||||||
void GetAllData(cChunkDataCallback & a_Callback);
|
void GetAllData(cChunkDataCallback & a_Callback);
|
||||||
|
@ -434,7 +459,12 @@ private:
|
||||||
typedef std::vector<sSetBlockQueueItem> sSetBlockQueueVector;
|
typedef std::vector<sSetBlockQueueItem> sSetBlockQueueVector;
|
||||||
|
|
||||||
|
|
||||||
bool m_IsValid; // True if the chunk is loaded / generated
|
/** Holds the presence status of the chunk - if it is present, or in the loader / generator queue, or unloaded */
|
||||||
|
ePresence m_Presence;
|
||||||
|
|
||||||
|
/** If the chunk fails to load, should it be queued in the generator or reset back to invalid? */
|
||||||
|
bool m_ShouldGenerateIfLoadFailed;
|
||||||
|
|
||||||
bool m_IsLightValid; // True if the blocklight and skylight are calculated
|
bool m_IsLightValid; // True if the blocklight and skylight are calculated
|
||||||
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
||||||
bool m_IsSaving; // True if the chunk is being saved
|
bool m_IsSaving; // True if the chunk is being saved
|
||||||
|
|
|
@ -145,10 +145,9 @@ cChunkMap::cChunkLayer * cChunkMap::GetLayerForChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
|
|
||||||
cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
// No need to lock m_CSLayers, since it's already locked by the operation that called us
|
ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
|
||||||
ASSERT(m_CSLayers.IsLockedByCurrentThread());
|
|
||||||
|
|
||||||
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
cChunkLayer * Layer = GetLayerForChunk(a_ChunkX, a_ChunkZ);
|
||||||
if (Layer == NULL)
|
if (Layer == NULL)
|
||||||
{
|
{
|
||||||
// An error must have occurred, since layers are automatically created if they don't exist
|
// An error must have occurred, since layers are automatically created if they don't exist
|
||||||
|
@ -160,8 +159,10 @@ cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(Chunk->IsValid()))
|
if (!Chunk->IsValid() && !Chunk->IsQueued())
|
||||||
{
|
{
|
||||||
|
Chunk->SetPresence(cChunk::cpQueued);
|
||||||
|
Chunk->SetShouldGenerateIfLoadFailed(true);
|
||||||
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ, true);
|
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ, true);
|
||||||
}
|
}
|
||||||
return Chunk;
|
return Chunk;
|
||||||
|
@ -171,10 +172,11 @@ cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkZ)
|
cChunkPtr cChunkMap::GetChunkNoGen(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
// No need to lock m_CSLayers, since it's already locked by the operation that called us
|
ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
|
||||||
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
|
||||||
|
cChunkLayer * Layer = GetLayerForChunk(a_ChunkX, a_ChunkZ);
|
||||||
if (Layer == NULL)
|
if (Layer == NULL)
|
||||||
{
|
{
|
||||||
// An error must have occurred, since layers are automatically created if they don't exist
|
// An error must have occurred, since layers are automatically created if they don't exist
|
||||||
|
@ -186,8 +188,9 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(Chunk->IsValid()))
|
if (!Chunk->IsValid() && !Chunk->IsQueued())
|
||||||
{
|
{
|
||||||
|
Chunk->SetPresence(cChunk::cpQueued);
|
||||||
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ, false);
|
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +203,8 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkZ)
|
||||||
|
|
||||||
cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkZ)
|
cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
// No need to lock m_CSLayers, since it's already locked by the operation that called us
|
ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
|
||||||
|
|
||||||
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
||||||
if (Layer == NULL)
|
if (Layer == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1009,6 +1013,17 @@ bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkMap::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
|
||||||
|
return (Chunk != NULL) && Chunk->IsQueued();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
|
@ -2332,48 +2347,6 @@ void cChunkMap::TouchChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Loads the chunk synchronously, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before)
|
|
||||||
bool cChunkMap::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
cCSLock Lock(m_CSLayers);
|
|
||||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
|
||||||
if (Chunk == NULL)
|
|
||||||
{
|
|
||||||
// Internal error
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (Chunk->IsValid())
|
|
||||||
{
|
|
||||||
// Already loaded
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Chunk->HasLoadFailed())
|
|
||||||
{
|
|
||||||
// Already tried loading and it failed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_World->GetStorage().LoadChunk(a_ChunkX, a_ChunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid()
|
|
||||||
void cChunkMap::LoadChunks(const cChunkCoordsList & a_Chunks)
|
|
||||||
{
|
|
||||||
for (cChunkCoordsList::const_iterator itr = a_Chunks.begin(); itr != a_Chunks.end(); ++itr)
|
|
||||||
{
|
|
||||||
LoadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
|
||||||
} // for itr - a_Chunks[]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
|
|
|
@ -133,6 +133,9 @@ public:
|
||||||
/** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
|
/** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
|
||||||
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
|
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
|
||||||
|
|
||||||
|
/** Returns true iff the chunk is in the loader / generator queue. */
|
||||||
|
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
|
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
|
||||||
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ);
|
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ);
|
||||||
int GetHeight (int a_BlockX, int a_BlockZ); // Waits for the chunk to get loaded / generated
|
int GetHeight (int a_BlockX, int a_BlockZ); // Waits for the chunk to get loaded / generated
|
||||||
|
@ -278,12 +281,6 @@ public:
|
||||||
/** Touches the chunk, causing it to be loaded or generated */
|
/** Touches the chunk, causing it to be loaded or generated */
|
||||||
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
/** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
|
|
||||||
bool LoadChunk(int a_ChunkX, int a_ChunkZ);
|
|
||||||
|
|
||||||
/** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
|
|
||||||
void LoadChunks(const cChunkCoordsList & a_Chunks);
|
|
||||||
|
|
||||||
/** Marks the chunk as failed-to-load */
|
/** Marks the chunk as failed-to-load */
|
||||||
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
|
|
|
@ -283,7 +283,8 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
ASSERT(m_PluginInterface != NULL);
|
ASSERT(m_PluginInterface != NULL);
|
||||||
ASSERT(m_ChunkSink != NULL);
|
ASSERT(m_ChunkSink != NULL);
|
||||||
|
ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
|
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
|
||||||
m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
|
m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
|
||||||
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
|
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
|
||||||
|
|
|
@ -106,6 +106,10 @@ public:
|
||||||
If this callback returns false, the chunk is not generated.
|
If this callback returns false, the chunk is not generated.
|
||||||
*/
|
*/
|
||||||
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0;
|
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0;
|
||||||
|
|
||||||
|
/** Called to check whether the specified chunk is in the queued state.
|
||||||
|
Currently used only in Debug-mode asserts. */
|
||||||
|
virtual bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) = 0;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2374,6 +2374,8 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
|
||||||
|
|
||||||
void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
|
void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
|
||||||
{
|
{
|
||||||
|
ASSERT(IsChunkQueued(a_SetChunkData->GetChunkX(), a_SetChunkData->GetChunkZ()));
|
||||||
|
|
||||||
// Validate biomes, if needed:
|
// Validate biomes, if needed:
|
||||||
if (!a_SetChunkData->AreBiomesValid())
|
if (!a_SetChunkData->AreBiomesValid())
|
||||||
{
|
{
|
||||||
|
@ -2463,6 +2465,15 @@ bool cWorld::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWorld::IsChunkQueued(int a_ChunkX, int a_ChunkZ) const
|
||||||
|
{
|
||||||
|
return m_ChunkMap->IsChunkQueued(a_ChunkX, a_ChunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
|
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
|
||||||
{
|
{
|
||||||
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkZ);
|
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkZ);
|
||||||
|
@ -2787,24 +2798,6 @@ void cWorld::TouchChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cWorld::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
|
||||||
{
|
|
||||||
return m_ChunkMap->LoadChunk(a_ChunkX, a_ChunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::LoadChunks(const cChunkCoordsList & a_Chunks)
|
|
||||||
{
|
|
||||||
m_ChunkMap->LoadChunks(a_Chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
m_ChunkMap->ChunkLoadFailed(a_ChunkX, a_ChunkZ);
|
m_ChunkMap->ChunkLoadFailed(a_ChunkX, a_ChunkZ);
|
||||||
|
@ -3520,6 +3513,15 @@ bool cWorld::cChunkGeneratorCallbacks::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWorld::cChunkGeneratorCallbacks::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
return m_World->IsChunkQueued(a_ChunkX, a_ChunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
|
bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
return m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
|
return m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
|
||||||
|
|
14
src/World.h
14
src/World.h
|
@ -279,7 +279,12 @@ public:
|
||||||
/** Gets the chunk's blocks, only the block types */
|
/** Gets the chunk's blocks, only the block types */
|
||||||
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes);
|
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes);
|
||||||
|
|
||||||
bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const;
|
/** Returns true iff the chunk is in the loader / generator queue. */
|
||||||
|
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const;
|
||||||
|
|
||||||
|
/** Returns true iff the chunk is present and valid. */
|
||||||
|
bool IsChunkValid(int a_ChunkX, int a_ChunkZ) const;
|
||||||
|
|
||||||
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const;
|
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const;
|
||||||
|
|
||||||
/** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/
|
/** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/
|
||||||
|
@ -358,12 +363,6 @@ public:
|
||||||
/** Touches the chunk, causing it to be loaded or generated */
|
/** Touches the chunk, causing it to be loaded or generated */
|
||||||
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
/** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
|
|
||||||
bool LoadChunk(int a_ChunkX, int a_ChunkZ);
|
|
||||||
|
|
||||||
/** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
|
|
||||||
void LoadChunks(const cChunkCoordsList & a_Chunks);
|
|
||||||
|
|
||||||
/** Marks the chunk as failed-to-load: */
|
/** Marks the chunk as failed-to-load: */
|
||||||
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
|
@ -822,6 +821,7 @@ private:
|
||||||
virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override;
|
virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override;
|
||||||
virtual bool IsChunkValid (int a_ChunkX, int a_ChunkZ) override;
|
virtual bool IsChunkValid (int a_ChunkX, int a_ChunkZ) override;
|
||||||
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) override;
|
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) override;
|
||||||
|
virtual bool IsChunkQueued (int a_ChunkX, int a_ChunkZ) override;
|
||||||
|
|
||||||
// cPluginInterface overrides:
|
// cPluginInterface overrides:
|
||||||
virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override;
|
virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override;
|
||||||
|
|
|
@ -143,6 +143,8 @@ size_t cWorldStorage::GetSaveQueueLength(void)
|
||||||
|
|
||||||
void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate)
|
void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate)
|
||||||
{
|
{
|
||||||
|
ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
m_LoadQueue.EnqueueItem(sChunkLoad(a_ChunkX, a_ChunkZ, a_Generate));
|
m_LoadQueue.EnqueueItem(sChunkLoad(a_ChunkX, a_ChunkZ, a_Generate));
|
||||||
m_Event.Set();
|
m_Event.Set();
|
||||||
}
|
}
|
||||||
|
@ -153,6 +155,8 @@ void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate)
|
||||||
|
|
||||||
void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ)
|
void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
|
ASSERT(m_World->IsChunkValid(a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkZ));
|
m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||||
m_Event.Set();
|
m_Event.Set();
|
||||||
}
|
}
|
||||||
|
@ -244,6 +248,7 @@ bool cWorldStorage::LoadOneChunk(void)
|
||||||
{
|
{
|
||||||
sChunkLoad ToLoad(0, 0, false);
|
sChunkLoad ToLoad(0, 0, false);
|
||||||
bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
|
bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
|
||||||
|
|
||||||
if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ))
|
if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ))
|
||||||
{
|
{
|
||||||
if (ToLoad.m_Generate)
|
if (ToLoad.m_Generate)
|
||||||
|
@ -285,11 +290,7 @@ bool cWorldStorage::SaveOneChunk(void)
|
||||||
|
|
||||||
bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
if (m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
|
ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ));
|
||||||
{
|
|
||||||
// Already loaded (can happen, since the queue is async)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cChunkCoords Coords(a_ChunkX, a_ChunkZ);
|
cChunkCoords Coords(a_ChunkX, a_ChunkZ);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue