summaryrefslogtreecommitdiffstats
path: root/src/Generating
diff options
context:
space:
mode:
authorMattes D <github@xoft.cz>2014-12-10 22:35:16 +0100
committerMattes D <github@xoft.cz>2014-12-10 22:35:16 +0100
commitfcd3d1bfedbfbe535f406e3db933486bad913ab4 (patch)
tree24ad1b9b30473e686ded1e2a89a02ce04fb2cc91 /src/Generating
parentLighting thread: skip chunks that are already lit. (diff)
downloadcuberite-fcd3d1bfedbfbe535f406e3db933486bad913ab4.tar
cuberite-fcd3d1bfedbfbe535f406e3db933486bad913ab4.tar.gz
cuberite-fcd3d1bfedbfbe535f406e3db933486bad913ab4.tar.bz2
cuberite-fcd3d1bfedbfbe535f406e3db933486bad913ab4.tar.lz
cuberite-fcd3d1bfedbfbe535f406e3db933486bad913ab4.tar.xz
cuberite-fcd3d1bfedbfbe535f406e3db933486bad913ab4.tar.zst
cuberite-fcd3d1bfedbfbe535f406e3db933486bad913ab4.zip
Diffstat (limited to 'src/Generating')
-rw-r--r--src/Generating/ChunkGenerator.cpp47
-rw-r--r--src/Generating/ChunkGenerator.h47
2 files changed, 63 insertions, 31 deletions
diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp
index d2e7b47b4..854aac60d 100644
--- a/src/Generating/ChunkGenerator.cpp
+++ b/src/Generating/ChunkGenerator.cpp
@@ -110,29 +110,19 @@ void cChunkGenerator::Stop(void)
-void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate)
+void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate, cChunkCoordCallback * a_Callback)
{
ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
{
cCSLock Lock(m_CS);
- // Check if it is already in the queue:
- for (cChunkCoordsWithBoolList::iterator itr = m_Queue.begin(); itr != m_Queue.end(); ++itr)
- {
- if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
- {
- // Already in the queue, bail out
- return;
- }
- } // for itr - m_Queue[]
-
// Add to queue, issue a warning if too many:
if (m_Queue.size() >= QUEUE_WARNING_LIMIT)
{
LOGWARN("WARNING: Adding chunk [%i, %i] to generation queue; Queue is too big! (" SIZE_T_FMT ")", a_ChunkX, a_ChunkZ, m_Queue.size());
}
- m_Queue.push_back(cChunkCoordsWithBool(a_ChunkX, a_ChunkZ, a_ForceGenerate));
+ m_Queue.push_back(cQueueItem{a_ChunkX, a_ChunkZ, a_ForceGenerate, a_Callback});
}
m_Event.Set();
@@ -242,9 +232,9 @@ void cChunkGenerator::Execute(void)
continue;
}
- cChunkCoordsWithBool coords = m_Queue.front(); // Get next coord from queue
+ cQueueItem item = m_Queue.front(); // Get next chunk from the queue
bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
- m_Queue.erase(m_Queue.begin()); // Remove coordinate from queue
+ m_Queue.erase(m_Queue.begin()); // Remove the item from the queue
Lock.Unlock(); // Unlock ASAP
m_evtRemoved.Set();
@@ -258,22 +248,35 @@ void cChunkGenerator::Execute(void)
LastReportTick = clock();
}
- if (!coords.m_ForceGenerate && m_ChunkSink->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
+ // Skip the chunk if it's already generated and regeneration is not forced:
+ if (!item.m_ForceGenerate && m_ChunkSink->IsChunkValid(item.m_ChunkX, item.m_ChunkZ))
{
- LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ);
- // Already generated, ignore request
+ LOGD("Chunk [%d, %d] already generated, skipping generation", item.m_ChunkX, item.m_ChunkZ);
+ if (item.m_Callback != nullptr)
+ {
+ item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ);
+ }
continue;
}
- if (SkipEnabled && !m_ChunkSink->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkZ))
+ // Skip the chunk if the generator is overloaded:
+ if (SkipEnabled && !m_ChunkSink->HasChunkAnyClients(item.m_ChunkX, item.m_ChunkZ))
{
- LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
+ LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", item.m_ChunkX, item.m_ChunkZ);
+ if (item.m_Callback != nullptr)
+ {
+ item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ);
+ }
continue;
}
- LOGD("Generating chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
- DoGenerate(coords.m_ChunkX, coords.m_ChunkZ);
-
+ // Generate the chunk:
+ LOGD("Generating chunk [%d, %d]", item.m_ChunkX, item.m_ChunkZ);
+ DoGenerate(item.m_ChunkX, item.m_ChunkZ);
+ if (item.m_Callback != nullptr)
+ {
+ item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ);
+ }
NumChunksGenerated++;
} // while (!bStop)
}
diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h
index 190d9e616..4af486ae1 100644
--- a/src/Generating/ChunkGenerator.h
+++ b/src/Generating/ChunkGenerator.h
@@ -119,8 +119,12 @@ public:
bool Start(cPluginInterface & a_PluginInterface, cChunkSink & a_ChunkSink, cIniFile & a_IniFile);
void Stop(void);
- /// Queues the chunk for generation; removes duplicate requests
- void QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate);
+ /** Queues the chunk for generation
+ If a-ForceGenerate is set, the chunk is regenerated even if the data is already present in the chunksink.
+ a_Callback is called after the chunk is generated. If the chunk was already present, the callback is still called, even if not regenerating.
+ It is legal to set the callback to nullptr, no callback is called then.
+ If the generator becomes overloaded and skips this chunk, the callback is still called. */
+ void QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate, cChunkCoordCallback * a_Callback = nullptr);
/// Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading.
void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap);
@@ -131,22 +135,46 @@ public:
int GetSeed(void) const { return m_Seed; }
- /// Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome
+ /** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome */
EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ);
- /// Reads a block type from the ini file; returns the blocktype on success, emits a warning and returns a_Default's representation on failure.
+ /** Reads a block type from the ini file; returns the blocktype on success, emits a warning and returns a_Default's representation on failure. */
static BLOCKTYPE GetIniBlock(cIniFile & a_IniFile, const AString & a_SectionName, const AString & a_ValueName, const AString & a_Default);
private:
+ struct cQueueItem
+ {
+ /** The chunk coords */
+ int m_ChunkX, m_ChunkZ;
+
+ /** Force the regeneration of an already existing chunk */
+ bool m_ForceGenerate;
+
+ /** Callback to call after generating.*/
+ cChunkCoordCallback * m_Callback;
+ };
+
+ typedef std::list<cQueueItem> cGenQueue;
+
+
+ /** Seed used for the generator. */
int m_Seed;
- cCriticalSection m_CS;
- cChunkCoordsWithBoolList m_Queue;
- cEvent m_Event; ///< Set when an item is added to the queue or the thread should terminate
- cEvent m_evtRemoved; ///< Set when an item is removed from the queue
+ /** CS protecting access to the queue. */
+ cCriticalSection m_CS;
+
+ /** Queue of the chunks to be generated. Protected against multithreaded access by m_CS. */
+ cGenQueue m_Queue;
+
+ /** Set when an item is added to the queue or the thread should terminate. */
+ cEvent m_Event;
+
+ /** Set when an item is removed from the queue. */
+ cEvent m_evtRemoved;
- cGenerator * m_Generator; ///< The actual generator engine used to generate chunks
+ /** The actual generator engine used to generate chunks. */
+ cGenerator * m_Generator;
/** The plugin interface that may modify the generated chunks */
cPluginInterface * m_PluginInterface;
@@ -158,6 +186,7 @@ private:
// cIsThread override:
virtual void Execute(void) override;
+ /** Generates the specified chunk and sets it into the chunksink. */
void DoGenerate(int a_ChunkX, int a_ChunkZ);
};