diff options
Diffstat (limited to '')
-rw-r--r-- | src/Generating/ChunkDesc.cpp | 3 | ||||
-rw-r--r-- | src/Generating/ChunkGenerator.cpp | 108 | ||||
-rw-r--r-- | src/Generating/ChunkGenerator.h | 18 |
3 files changed, 33 insertions, 96 deletions
diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index 6ba63d5ce..b7f189fea 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -8,7 +8,8 @@ #include "../BlockArea.h" #include "../Cuboid.h" #include "../Noise/Noise.h" -#include "../BlockEntities/BlockEntity.h" +#include "BlockEntities/BlockEntity.h" +#include "Entities/Entity.h" diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index e7c2e4125..c5d830d0d 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -15,9 +15,6 @@ /** If the generation queue size exceeds this number, a warning will be output */ const unsigned int QUEUE_WARNING_LIMIT = 1000; -/** If the generation queue size exceeds this number, chunks with no clients will be skipped */ -const unsigned int QUEUE_SKIP_LIMIT = 500; - @@ -114,6 +111,11 @@ void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_Forc { ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ)); + if (!a_ForceGenerate && m_ChunkSink->IsChunkValid(a_ChunkX, a_ChunkZ)) + { + return; + } + { cCSLock Lock(m_CS); @@ -122,7 +124,7 @@ void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_Forc { 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(cQueueItem{a_ChunkX, a_ChunkZ, a_ForceGenerate, a_Callback}); + m_Queue.emplace_back(sQueueItem{ a_ChunkX, a_ChunkZ, a_Callback }); } m_Event.Set(); @@ -144,20 +146,6 @@ void cChunkGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::Biom -void cChunkGenerator::WaitForQueueEmpty(void) -{ - cCSLock Lock(m_CS); - while (!m_ShouldTerminate && !m_Queue.empty()) - { - cCSUnlock Unlock(Lock); - m_evtRemoved.Wait(); - } -} - - - - - int cChunkGenerator::GetQueueLength(void) { cCSLock Lock(m_CS); @@ -204,80 +192,39 @@ void cChunkGenerator::Execute(void) while (!m_ShouldTerminate) { - cCSLock Lock(m_CS); - while (m_Queue.empty()) - { - if ((NumChunksGenerated > 16) && (clock() - LastReportTick > CLOCKS_PER_SEC)) - { - /* LOG("Chunk generator performance: %.2f ch / sec (%d ch total)", - static_cast<double>(NumChunksGenerated) * CLOCKS_PER_SEC/ (clock() - GenerationStart), - NumChunksGenerated - ); */ - } - cCSUnlock Unlock(Lock); - m_Event.Wait(); - if (m_ShouldTerminate) - { - return; - } - NumChunksGenerated = 0; - GenerationStart = clock(); - LastReportTick = clock(); - } + m_Event.Wait(); - if (m_Queue.empty()) + decltype(m_Queue) QueuedChunks; { - // Sometimes the queue remains empty - // If so, we can't do any front() operations on it! - continue; + cCSLock Lock(m_CS); + std::swap(QueuedChunks, m_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 the item from the queue - Lock.Unlock(); // Unlock ASAP - m_evtRemoved.Set(); - - // Display perf info once in a while: - if ((NumChunksGenerated > 512) && (clock() - LastReportTick > 2 * CLOCKS_PER_SEC)) - { - LOG("Chunk generator performance: %.2f ch / sec (%d ch total)", - static_cast<double>(NumChunksGenerated) * CLOCKS_PER_SEC / (clock() - GenerationStart), - NumChunksGenerated - ); - LastReportTick = clock(); - } + NumChunksGenerated = 0; + GenerationStart = clock(); + LastReportTick = clock(); - // Skip the chunk if it's already generated and regeneration is not forced. Report as success: - if (!item.m_ForceGenerate && m_ChunkSink->IsChunkValid(item.m_ChunkX, item.m_ChunkZ)) + for (const auto & Item : QueuedChunks) { - LOGD("Chunk [%d, %d] already generated, skipping generation", item.m_ChunkX, item.m_ChunkZ); - if (item.m_Callback != nullptr) + // Display perf info once in a while: + if ((NumChunksGenerated > 512) && (clock() - LastReportTick > 2 * CLOCKS_PER_SEC)) { - item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ, true); + LOG("Chunk generator performance: %.2f ch / sec (%d ch total)", + static_cast<double>(NumChunksGenerated) * CLOCKS_PER_SEC / (clock() - GenerationStart), + NumChunksGenerated + ); + LastReportTick = clock(); } - continue; - } - // 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]", item.m_ChunkX, item.m_ChunkZ); - if (item.m_Callback != nullptr) + // 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, false); + Item.m_Callback->Call(Item.m_ChunkX, Item.m_ChunkZ, true); } - continue; + NumChunksGenerated++; } - - // 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, true); - } - NumChunksGenerated++; } // while (!bStop) } @@ -288,7 +235,6 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ) { ASSERT(m_PluginInterface != nullptr); ASSERT(m_ChunkSink != nullptr); - ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ)); cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ); m_PluginInterface->CallHookChunkGenerating(ChunkDesc); diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h index 5c778fda4..4e5c045a0 100644 --- a/src/Generating/ChunkGenerator.h +++ b/src/Generating/ChunkGenerator.h @@ -9,7 +9,6 @@ The requests are not added to the queue if there is already a request with the s Before generating, the thread checks if the chunk hasn't been already generated. It is theoretically possible to have multiple generator threads by having multiple instances of this object, but then it MAY happen that the chunk is generated twice. -If the generator queue is overloaded, the generator skips chunks with no clients in them */ @@ -102,8 +101,7 @@ public: If this callback returns false, the chunk is not generated. */ 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. */ + /** Called to check whether the specified chunk is in the queued state. */ virtual bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) = 0; } ; @@ -117,15 +115,12 @@ public: /** 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. */ + It is legal to set the callback to nullptr, no callback is called then. */ 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); - void WaitForQueueEmpty(void); - int GetQueueLength(void); int GetSeed(void) const { return m_Seed; } @@ -138,20 +133,15 @@ public: private: - struct cQueueItem + struct sQueueItem { /** 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; @@ -160,7 +150,7 @@ private: cCriticalSection m_CS; /** Queue of the chunks to be generated. Protected against multithreaded access by m_CS. */ - cGenQueue m_Queue; + std::vector<sQueueItem> m_Queue; /** Set when an item is added to the queue or the thread should terminate. */ cEvent m_Event; |