summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/SpawnPrepare.cpp105
-rw-r--r--src/SpawnPrepare.h47
-rw-r--r--src/World.cpp138
4 files changed, 156 insertions, 136 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a23e02789..5556ddc4d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -62,6 +62,7 @@ SET (SRCS
Scoreboard.cpp
Server.cpp
SetChunkData.cpp
+ SpawnPrepare.cpp
Statistics.cpp
StringCompression.cpp
StringUtils.cpp
@@ -133,6 +134,7 @@ SET (HDRS
Server.h
SetChunkData.h
SettingsRepositoryInterface.h
+ SpawnPrepare.h
Statistics.h
StringCompression.h
StringUtils.h
diff --git a/src/SpawnPrepare.cpp b/src/SpawnPrepare.cpp
new file mode 100644
index 000000000..80d2c52a1
--- /dev/null
+++ b/src/SpawnPrepare.cpp
@@ -0,0 +1,105 @@
+
+#include "Globals.h"
+
+#include "SpawnPrepare.h"
+#include "World.h"
+
+
+
+
+
+
+
+cSpawnPrepare::cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx):
+ m_World(a_World),
+ m_SpawnChunkX(a_SpawnChunkX),
+ m_SpawnChunkZ(a_SpawnChunkZ),
+ m_PrepareDistance(a_PrepareDistance),
+ m_NextIdx(a_FirstIdx),
+ m_MaxIdx(a_PrepareDistance * a_PrepareDistance),
+ m_NumPrepared(0),
+ m_LastReportTime(std::chrono::steady_clock::now()),
+ m_LastReportChunkCount(0)
+{
+}
+
+
+
+
+
+
+
+void cSpawnPrepare::PrepareChunks(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance)
+{
+
+ // Queue the initial chunks:
+ int MaxIdx = a_PrepareDistance * a_PrepareDistance;
+ int maxQueue = std::min(MaxIdx - 1, 100); // Number of chunks to queue at once
+ cSpawnPrepare prep(a_World, a_SpawnChunkX, a_SpawnChunkZ, a_PrepareDistance, maxQueue);
+ for (int i = 0; i < maxQueue; i++)
+ {
+ int chunkX, chunkZ;
+ prep.DecodeChunkCoords(i, chunkX, chunkZ);
+ a_World.PrepareChunk(chunkX, chunkZ, &prep);
+ } // for i
+
+ // Wait for the lighting thread to prepare everything. Event is set in the Call() callback:
+ prep.m_EvtFinished.Wait();
+}
+
+
+
+
+
+void cSpawnPrepare::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;
+}
+
+
+
+
+
+void cSpawnPrepare::Call(int a_ChunkX, int a_ChunkZ)
+{
+ // 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;
+ }
+}
+
diff --git a/src/SpawnPrepare.h b/src/SpawnPrepare.h
new file mode 100644
index 000000000..bd5c0e0c6
--- /dev/null
+++ b/src/SpawnPrepare.h
@@ -0,0 +1,47 @@
+
+#pragma once
+
+class cWorld;
+
+
+
+/** Generates and lights the spawn area of the world. Runs as a separate thread. */
+class cSpawnPrepare:
+ public cChunkCoordCallback
+{
+
+public:
+ static void PrepareChunks(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance);
+
+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 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;
+
+ cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx);
+
+ virtual void Call(int a_ChunkX, int a_ChunkZ) override;
+
+ /** Decodes the index into chunk coords. Provides the specific chunk ordering. */
+ void DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ);
+};
+
diff --git a/src/World.cpp b/src/World.cpp
index 27bb3bdbd..aabbd7276 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: