Cuberite
A lightweight, fast and extensible game server for Minecraft
SpawnPrepare.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h"
3 
4 #include "SpawnPrepare.h"
5 #include "World.h"
6 
7 
8 
9 
10 
12  public cChunkCoordCallback
13 {
14 public:
15  cSpawnPrepareCallback(std::shared_ptr<cSpawnPrepare> a_SpawnPrepare) :
16  m_SpawnPrepare(std::move(a_SpawnPrepare))
17  {
18  ASSERT(m_SpawnPrepare != nullptr);
19  }
20 protected:
21 
22  std::shared_ptr<cSpawnPrepare> m_SpawnPrepare;
23 
24  virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess) override
25  {
26  m_SpawnPrepare->PreparedChunkCallback(a_Coords.m_ChunkX, a_Coords.m_ChunkZ);
27  }
28 };
29 
30 
31 
32 
33 
34 cSpawnPrepare::cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx, sMakeSharedTag):
35  m_World(a_World),
36  m_SpawnChunkX(a_SpawnChunkX),
37  m_SpawnChunkZ(a_SpawnChunkZ),
38  m_PrepareDistance(a_PrepareDistance),
39  m_NextIdx(a_FirstIdx),
40  m_MaxIdx(a_PrepareDistance * a_PrepareDistance),
41  m_NumPrepared(0),
42  m_LastReportTime(std::chrono::steady_clock::now()),
43  m_LastReportChunkCount(0)
44 {
45 }
46 
47 
48 
49 
50 
51 void cSpawnPrepare::PrepareChunks(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance)
52 {
53 
54  // Queue the initial chunks:
55  int MaxIdx = a_PrepareDistance * a_PrepareDistance;
56  int maxQueue = std::min(MaxIdx - 1, 100); // Number of chunks to queue at once
57  auto prep = std::make_shared<cSpawnPrepare>(a_World, a_SpawnChunkX, a_SpawnChunkZ, a_PrepareDistance, maxQueue, sMakeSharedTag{});
58  for (int i = 0; i < maxQueue; i++)
59  {
60  int chunkX, chunkZ;
61  prep->DecodeChunkCoords(i, chunkX, chunkZ);
62  a_World.PrepareChunk(chunkX, chunkZ, std::make_unique<cSpawnPrepareCallback>(prep));
63  } // for i
64 
65  // Wait for the lighting thread to prepare everything. Event is set in the Call() callback:
66  if (MaxIdx > 0)
67  {
68  prep->m_EvtFinished.Wait();
69  }
70 }
71 
72 
73 
74 
75 
76 void cSpawnPrepare::DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ)
77 {
78  // A zigzag pattern from the top to bottom, each row alternating between forward-x and backward-x:
79  int z = a_Idx / m_PrepareDistance;
80  int x = a_Idx % m_PrepareDistance;
81  if ((z & 1) == 0)
82  {
83  // Reverse every second row:
84  x = m_PrepareDistance - 1 - x;
85  }
86  a_ChunkZ = m_SpawnChunkZ + z - m_PrepareDistance / 2;
87  a_ChunkX = m_SpawnChunkX + x - m_PrepareDistance / 2;
88 }
89 
90 
91 
92 
93 
94 void cSpawnPrepare::PreparedChunkCallback(int a_ChunkX, int a_ChunkZ)
95 {
96  // Check if this was the last chunk:
97  m_NumPrepared += 1;
98  if (m_NumPrepared >= m_MaxIdx)
99  {
100  m_EvtFinished.Set();
101  // Must return here, because "this" may have gotten deleted by the previous line
102  return;
103  }
104 
105  // Queue another chunk, if appropriate:
106  if (m_NextIdx < m_MaxIdx)
107  {
108  int chunkX, chunkZ;
109  DecodeChunkCoords(m_NextIdx, chunkX, chunkZ);
110  m_World.GetLightingThread().QueueChunk(chunkX, chunkZ, std::make_unique<cSpawnPrepareCallback>(shared_from_this()));
111  m_NextIdx += 1;
112  }
113 
114  // Report progress every 1 second:
115  auto Now = std::chrono::steady_clock::now();
116  if (Now - m_LastReportTime > std::chrono::seconds(1))
117  {
118  float PercentDone = static_cast<float>(m_NumPrepared * 100) / m_MaxIdx;
119  float ChunkSpeed = static_cast<float>((m_NumPrepared - m_LastReportChunkCount) * 1000) / std::chrono::duration_cast<std::chrono::milliseconds>(Now - m_LastReportTime).count();
120  LOG("Preparing spawn (%s): %.02f%% (%d/%d; %.02f chunks / sec)",
121  m_World.GetName().c_str(), PercentDone, m_NumPrepared.load(std::memory_order_seq_cst), m_MaxIdx, ChunkSpeed
122  );
123  m_LastReportTime = Now;
125  }
126 }
127 
#define ASSERT(x)
Definition: Globals.h:276
void LOG(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:55
Definition: FastNBT.h:132
Wraps the chunk coords into a single structure.
Definition: ChunkDef.h:57
int m_ChunkZ
Definition: ChunkDef.h:60
int m_ChunkX
Definition: ChunkDef.h:59
Interface class used as a callback for operations that involve chunk coords.
Definition: ChunkDef.h:467
void QueueChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallbackAfter)
Queues the entire chunk for lighting.
void Set(void)
Sets the event - releases one thread that has been waiting in Wait().
Definition: Event.cpp:52
virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess) override
Called with the chunk's coords, and an optional operation status flag for operations that support it.
std::shared_ptr< cSpawnPrepare > m_SpawnPrepare
cSpawnPrepareCallback(std::shared_ptr< cSpawnPrepare > a_SpawnPrepare)
static void PrepareChunks(cWorld &a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance)
std::chrono::steady_clock::time_point m_LastReportTime
The timestamp of the last progress report emitted.
Definition: SpawnPrepare.h:39
int m_LastReportChunkCount
Number of chunks prepared when the last progress report was emitted.
Definition: SpawnPrepare.h:42
void PreparedChunkCallback(int a_ChunkX, int a_ChunkZ)
int m_MaxIdx
The maximum index of the prepared chunks.
Definition: SpawnPrepare.h:30
std::atomic< int > m_NumPrepared
Total number of chunks already finished preparing.
Definition: SpawnPrepare.h:33
void DecodeChunkCoords(int a_Idx, int &a_ChunkX, int &a_ChunkZ)
Decodes the index into chunk coords.
cEvent m_EvtFinished
Event used to signal that the preparation is finished.
Definition: SpawnPrepare.h:36
cWorld & m_World
Definition: SpawnPrepare.h:21
int m_NextIdx
The index of the next chunk to be queued in the lighting thread.
Definition: SpawnPrepare.h:27
int m_PrepareDistance
Definition: SpawnPrepare.h:24
cSpawnPrepare(cWorld &a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx, sMakeSharedTag)
Private tag allows public constructors that can only be used with private access.
Definition: SpawnPrepare.h:13
Definition: World.h:53
void PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallAfter={})
Queues the chunk for preparing - making sure that it's generated and lit.
Definition: World.cpp:2542
const AString & GetName(void) const
Returns the name of the world.
Definition: World.h:691
cLightingThread & GetLightingThread(void)
Definition: World.h:771