diff options
Diffstat (limited to 'src/World.cpp')
-rw-r--r-- | src/World.cpp | 148 |
1 files changed, 7 insertions, 141 deletions
diff --git a/src/World.cpp b/src/World.cpp index 3c39de317..f7d2165c7 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -58,6 +58,7 @@ #endif #include "Broadcaster.h" +#include "SpawnPrepare.h" @@ -72,140 +73,6 @@ const int TIME_SPAWN_DIVISOR = 148; //////////////////////////////////////////////////////////////////////////////// -// cSpawnPrepare: - -/** Generates and lights the spawn area of the world. Runs as a separate thread. */ -class cSpawnPrepare: - public cIsThread, - public cChunkCoordCallback -{ - typedef cIsThread super; - -public: - cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance): - super("SpawnPrepare"), - m_World(a_World), - m_SpawnChunkX(a_SpawnChunkX), - m_SpawnChunkZ(a_SpawnChunkZ), - m_PrepareDistance(a_PrepareDistance), - m_MaxIdx(a_PrepareDistance * a_PrepareDistance), - m_NumPrepared(0), - m_LastReportChunkCount(0) - { - // Start the thread: - Start(); - - // Wait for start confirmation, so that the thread can be waited-upon after the constructor returns: - m_EvtStarted.Wait(); - } - - - // cIsThread override: - virtual void Execute(void) override - { - // Confirm thread start: - m_EvtStarted.Set(); - - // Queue the initial chunks: - m_MaxIdx = m_PrepareDistance * m_PrepareDistance; - int maxQueue = std::min(m_MaxIdx - 1, 100); // Number of chunks to queue at once - m_NextIdx = maxQueue; - m_LastReportTime = std::chrono::steady_clock::now(); - for (int i = 0; i < maxQueue; i++) - { - int chunkX, chunkZ; - DecodeChunkCoords(i, chunkX, chunkZ); - m_World.PrepareChunk(chunkX, chunkZ, this); - } // for i - - // Wait for the lighting thread to prepare everything. Event is set in the Call() callback: - m_EvtFinished.Wait(); - } - -protected: - cWorld & m_World; - int m_SpawnChunkX; - int m_SpawnChunkZ; - int m_PrepareDistance; - - /** The index of the next chunk to be queued in the lighting thread. */ - int m_NextIdx; - - /** The maximum index of the prepared chunks. Queueing stops when m_NextIdx reaches this number. */ - int m_MaxIdx; - - /** Total number of chunks already finished preparing. Preparation finishes when this number reaches m_MaxIdx. */ - int m_NumPrepared; - - /** Event used to signal that the thread has started. */ - cEvent m_EvtStarted; - - /** Event used to signal that the preparation is finished. */ - cEvent m_EvtFinished; - - /** The timestamp of the last progress report emitted. */ - std::chrono::steady_clock::time_point m_LastReportTime; - - /** Number of chunks prepared when the last progress report was emitted. */ - int m_LastReportChunkCount; - - // cChunkCoordCallback override: - virtual void Call(int a_ChunkX, int a_ChunkZ) override - { - // Check if this was the last chunk: - m_NumPrepared += 1; - if (m_NumPrepared >= m_MaxIdx) - { - m_EvtFinished.Set(); - // Must return here, because "this" may have gotten deleted by the previous line - return; - } - - // Queue another chunk, if appropriate: - if (m_NextIdx < m_MaxIdx) - { - int chunkX, chunkZ; - DecodeChunkCoords(m_NextIdx, chunkX, chunkZ); - m_World.GetLightingThread().QueueChunk(chunkX, chunkZ, this); - m_NextIdx += 1; - } - - // Report progress every 1 second: - auto Now = std::chrono::steady_clock::now(); - if (Now - m_LastReportTime > std::chrono::seconds(1)) - { - float PercentDone = static_cast<float>(m_NumPrepared * 100) / m_MaxIdx; - float ChunkSpeed = static_cast<float>((m_NumPrepared - m_LastReportChunkCount) * 1000) / std::chrono::duration_cast<std::chrono::milliseconds>(Now - m_LastReportTime).count(); - LOG("Preparing spawn (%s): %.02f%% (%d/%d; %.02f chunks / sec)", - m_World.GetName().c_str(), PercentDone, m_NumPrepared, m_MaxIdx, ChunkSpeed - ); - m_LastReportTime = Now; - m_LastReportChunkCount = m_NumPrepared; - } - } - - - /** Decodes the index into chunk coords. Provides the specific chunk ordering. */ - void DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ) - { - // A zigzag pattern from the top to bottom, each row alternating between forward-x and backward-x: - int z = a_Idx / m_PrepareDistance; - int x = a_Idx % m_PrepareDistance; - if ((z & 1) == 0) - { - // Reverse every second row: - x = m_PrepareDistance - 1 - x; - } - a_ChunkZ = m_SpawnChunkZ + z - m_PrepareDistance / 2; - a_ChunkX = m_SpawnChunkX + x - m_PrepareDistance / 2; - } -}; - - - - - -//////////////////////////////////////////////////////////////////////////////// // cWorld::cLock: cWorld::cLock::cLock(cWorld & a_World) : @@ -470,8 +337,7 @@ void cWorld::InitializeSpawn(void) int ViewDist = IniFile.GetValueSetI("SpawnPosition", "PregenerateDistance", DefaultViewDist); IniFile.WriteFile(m_IniFileName); - cSpawnPrepare prep(*this, ChunkX, ChunkZ, ViewDist); - prep.Wait(); + cSpawnPrepare::PrepareChunks(*this, ChunkX, ChunkZ, ViewDist); #ifdef TEST_LINEBLOCKTRACER // DEBUG: Test out the cLineBlockTracer class by tracing a few lines: @@ -2072,7 +1938,7 @@ void cWorld::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_V -void cWorld::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) +void cWorld::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) { m_ChunkMap->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, a_Byte1, a_Byte2, a_BlockType, a_Exclude); } @@ -3006,9 +2872,9 @@ void cWorld::TouchChunk(int a_ChunkX, int a_ChunkZ) -void cWorld::PrepareChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallAfter) +void cWorld::PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_CallAfter) { - m_ChunkMap->PrepareChunk(a_ChunkX, a_ChunkZ, a_CallAfter); + m_ChunkMap->PrepareChunk(a_ChunkX, a_ChunkZ, std::move(a_CallAfter)); } @@ -3132,9 +2998,9 @@ void cWorld::GenerateChunk(int a_ChunkX, int a_ChunkZ) -void cWorld::QueueLightChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback) +void cWorld::QueueLightChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_Callback) { - m_Lighting.QueueChunk(a_ChunkX, a_ChunkZ, a_Callback); + m_Lighting.QueueChunk(a_ChunkX, a_ChunkZ, std::move(a_Callback)); } |