Cuberite
A lightweight, fast and extensible game server for Minecraft
LightingThread.cpp
Go to the documentation of this file.
1 
2 // LightingThread.cpp
3 
4 // Implements the cLightingThread class representing the thread that processes requests for lighting
5 
6 #include "Globals.h"
7 #include "LightingThread.h"
8 #include "ChunkMap.h"
9 #include "World.h"
10 
11 
12 
13 
14 
16 class cReader :
17  public cChunkDataCallback
18 {
19  virtual void ChunkData(const cChunkData & a_ChunkBuffer) override
20  {
21  BLOCKTYPE * OutputRows = m_BlockTypes;
22  int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3;
23  for (size_t i = 0; i != cChunkData::NumSections; ++i)
24  {
25  auto * Section = a_ChunkBuffer.GetSection(i);
26  if (Section == nullptr)
27  {
28  // Skip to the next section
30  continue;
31  }
32 
33  for (size_t OffsetY = 0; OffsetY != cChunkData::SectionHeight; ++OffsetY)
34  {
35  for (size_t Z = 0; Z != cChunkDef::Width; ++Z)
36  {
37  auto InPtr = Section->m_BlockTypes + Z * cChunkDef::Width + OffsetY * cChunkDef::Width * cChunkDef::Width;
38  std::copy_n(InPtr, cChunkDef::Width, OutputRows + OutputIdx * cChunkDef::Width);
39 
40  OutputIdx += 3;
41  }
42  // Skip into the next y-level in the 3x3 chunk blob; each level has cChunkDef::Width * 9 rows
43  // We've already walked cChunkDef::Width * 3 in the "for z" cycle, that makes cChunkDef::Width * 6 rows left to skip
44  OutputIdx += cChunkDef::Width * 6;
45  }
46  }
47  } // BlockTypes()
48 
49 
50  virtual void HeightMap(const cChunkDef::HeightMap * a_Heightmap) override
51  {
52  // Copy the entire heightmap, distribute it into the 3x3 chunk blob:
53  typedef struct {HEIGHTTYPE m_Row[16]; } ROW;
54  const ROW * InputRows = reinterpret_cast<const ROW *>(a_Heightmap);
55  ROW * OutputRows = reinterpret_cast<ROW *>(m_HeightMap);
56  int InputIdx = 0;
57  int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3;
58  for (int z = 0; z < cChunkDef::Width; z++)
59  {
60  OutputRows[OutputIdx] = InputRows[InputIdx++];
61  OutputIdx += 3;
62  } // for z
63 
64  // Find the highest block in the entire chunk, use it as a base for m_MaxHeight:
65  HEIGHTTYPE MaxHeight = m_MaxHeight;
66  for (size_t i = 0; i < ARRAYCOUNT(*a_Heightmap); i++)
67  {
68  if ((*a_Heightmap)[i] > MaxHeight)
69  {
70  MaxHeight = (*a_Heightmap)[i];
71  }
72  }
73  m_MaxHeight = MaxHeight;
74  }
75 
76 public:
77  int m_ReadingChunkX; // 0, 1 or 2; x-offset of the chunk we're reading from the BlockTypes start
78  int m_ReadingChunkZ; // 0, 1 or 2; z-offset of the chunk we're reading from the BlockTypes start
79  HEIGHTTYPE m_MaxHeight; // Maximum value in this chunk's heightmap
80  BLOCKTYPE * m_BlockTypes; // 3x3 chunks of block types, organized as a single XZY blob of data (instead of 3x3 XZY blobs)
81  HEIGHTTYPE * m_HeightMap; // 3x3 chunks of height map, organized as a single XZY blob of data (instead of 3x3 XZY blobs)
82 
83  cReader(BLOCKTYPE * a_BlockTypes, HEIGHTTYPE * a_HeightMap) :
84  m_ReadingChunkX(0),
85  m_ReadingChunkZ(0),
86  m_MaxHeight(0),
87  m_BlockTypes(a_BlockTypes),
88  m_HeightMap(a_HeightMap)
89  {
90  std::fill_n(m_BlockTypes, cChunkDef::NumBlocks * 9, E_BLOCK_AIR);
91  }
92 } ;
93 
94 
95 
96 
97 
99 // cLightingThread:
100 
102  super("cLightingThread"),
103  m_World(a_World),
104  m_MaxHeight(0),
105  m_NumSeeds(0)
106 {
107 }
108 
109 
110 
111 
112 
114 {
115  Stop();
116 }
117 
118 
119 
120 
121 
123 {
124  {
125  cCSLock Lock(m_CS);
126  for (cChunkStays::iterator itr = m_PendingQueue.begin(), end = m_PendingQueue.end(); itr != end; ++itr)
127  {
128  (*itr)->Disable();
129  delete *itr;
130  }
131  m_PendingQueue.clear();
132  for (cChunkStays::iterator itr = m_Queue.begin(), end = m_Queue.end(); itr != end; ++itr)
133  {
134  (*itr)->Disable();
135  delete *itr;
136  }
137  m_Queue.clear();
138  }
139  m_ShouldTerminate = true;
141 
142  super::Stop();
143 }
144 
145 
146 
147 
148 
149 void cLightingThread::QueueChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_CallbackAfter)
150 {
151  cChunkStay * ChunkStay = new cLightingChunkStay(*this, a_ChunkX, a_ChunkZ, std::move(a_CallbackAfter));
152  {
153  // The ChunkStay will enqueue itself using the QueueChunkStay() once it is fully loaded
154  // In the meantime, put it into the PendingQueue so that it can be removed when stopping the thread
155  cCSLock Lock(m_CS);
156  m_PendingQueue.push_back(ChunkStay);
157  }
158  ChunkStay->Enable(*m_World.GetChunkMap());
159 }
160 
161 
162 
163 
164 
166 {
167  cCSLock Lock(m_CS);
168  while (!m_ShouldTerminate && (!m_Queue.empty() || !m_PendingQueue.empty()))
169  {
170  cCSUnlock Unlock(Lock);
172  }
173 }
174 
175 
176 
177 
178 
180 {
181  cCSLock Lock(m_CS);
182  return m_Queue.size() + m_PendingQueue.size();
183 }
184 
185 
186 
187 
188 
190 {
191  for (;;)
192  {
193  {
194  cCSLock Lock(m_CS);
195  if (m_Queue.empty())
196  {
197  cCSUnlock Unlock(Lock);
199  }
200  }
201 
202  if (m_ShouldTerminate)
203  {
204  return;
205  }
206 
207  // Process one items from the queue:
208  cLightingChunkStay * Item;
209  {
210  cCSLock Lock(m_CS);
211  if (m_Queue.empty())
212  {
213  continue;
214  }
215  Item = static_cast<cLightingChunkStay *>(m_Queue.front());
216  m_Queue.pop_front();
217  if (m_Queue.empty())
218  {
220  }
221  } // CSLock(m_CS)
222 
223  LightChunk(*Item);
224  Item->Disable();
225  delete Item;
226  }
227 }
228 
229 
230 
231 
232 
234 {
235  // If the chunk is already lit, skip it (report as success):
236  if (m_World.IsChunkLighted(a_Item.m_ChunkX, a_Item.m_ChunkZ))
237  {
238  if (a_Item.m_CallbackAfter != nullptr)
239  {
240  a_Item.m_CallbackAfter->Call({a_Item.m_ChunkX, a_Item.m_ChunkZ}, true);
241  }
242  return;
243  }
244 
245  cChunkDef::BlockNibbles BlockLight, SkyLight;
246 
247  ReadChunks(a_Item.m_ChunkX, a_Item.m_ChunkZ);
248 
251 
252  PrepareSkyLight();
253 
254  /*
255  // DEBUG: Save chunk data with highlighted seeds for visual inspection:
256  cFile f4;
257  if (
258  f4.Open(Printf("Chunk_%d_%d_seeds.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite)
259  )
260  {
261  for (int z = 0; z < cChunkDef::Width * 3; z++)
262  {
263  for (int y = cChunkDef::Height / 2; y >= 0; y--)
264  {
265  unsigned char Seeds [cChunkDef::Width * 3];
266  memcpy(Seeds, m_BlockTypes + y * BlocksPerYLayer + z * cChunkDef::Width * 3, cChunkDef::Width * 3);
267  for (int x = 0; x < cChunkDef::Width * 3; x++)
268  {
269  if (m_IsSeed1[y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x])
270  {
271  Seeds[x] = E_BLOCK_DIAMOND_BLOCK;
272  }
273  }
274  f4.Write(Seeds, cChunkDef::Width * 3);
275  }
276  }
277  f4.Close();
278  }
279  //*/
280 
282 
283  /*
284  // DEBUG: Save XY slices of the chunk data and lighting for visual inspection:
285  cFile f1, f2, f3;
286  if (
287  f1.Open(Printf("Chunk_%d_%d_data.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) &&
288  f2.Open(Printf("Chunk_%d_%d_sky.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) &&
289  f3.Open(Printf("Chunk_%d_%d_glow.grab", a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite)
290  )
291  {
292  for (int z = 0; z < cChunkDef::Width * 3; z++)
293  {
294  for (int y = cChunkDef::Height / 2; y >= 0; y--)
295  {
296  f1.Write(m_BlockTypes + y * BlocksPerYLayer + z * cChunkDef::Width * 3, cChunkDef::Width * 3);
297  unsigned char SkyLight [cChunkDef::Width * 3];
298  unsigned char BlockLight[cChunkDef::Width * 3];
299  for (int x = 0; x < cChunkDef::Width * 3; x++)
300  {
301  SkyLight[x] = m_SkyLight [y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x] << 4;
302  BlockLight[x] = m_BlockLight[y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x] << 4;
303  }
304  f2.Write(SkyLight, cChunkDef::Width * 3);
305  f3.Write(BlockLight, cChunkDef::Width * 3);
306  }
307  }
308  f1.Close();
309  f2.Close();
310  f3.Close();
311  }
312  //*/
313 
314  CompressLight(m_BlockLight, BlockLight);
315  CompressLight(m_SkyLight, SkyLight);
316 
317  m_World.ChunkLighted(a_Item.m_ChunkX, a_Item.m_ChunkZ, BlockLight, SkyLight);
318 
319  if (a_Item.m_CallbackAfter != nullptr)
320  {
321  a_Item.m_CallbackAfter->Call({a_Item.m_ChunkX, a_Item.m_ChunkZ}, true);
322  }
323 }
324 
325 
326 
327 
328 
329 void cLightingThread::ReadChunks(int a_ChunkX, int a_ChunkZ)
330 {
332 
333  for (int z = 0; z < 3; z++)
334  {
335  Reader.m_ReadingChunkZ = z;
336  for (int x = 0; x < 3; x++)
337  {
338  Reader.m_ReadingChunkX = x;
339  VERIFY(m_World.GetChunkData({a_ChunkX + x - 1, a_ChunkZ + z - 1}, Reader));
340  } // for z
341  } // for x
342 
343  memset(m_BlockLight, 0, sizeof(m_BlockLight));
344  memset(m_SkyLight, 0, sizeof(m_SkyLight));
345  m_MaxHeight = Reader.m_MaxHeight;
346 }
347 
348 
349 
350 
351 
353 {
354  // Clear seeds:
355  memset(m_IsSeed1, 0, sizeof(m_IsSeed1));
356  m_NumSeeds = 0;
357 
358  // Fill the top of the chunk with all-light:
359  if (m_MaxHeight < cChunkDef::Height - 1)
360  {
362  }
363 
364  // Walk every column that has all XZ neighbors
365  for (int z = 1; z < cChunkDef::Width * 3 - 1; z++)
366  {
367  int BaseZ = z * cChunkDef::Width * 3;
368  for (int x = 1; x < cChunkDef::Width * 3 - 1; x++)
369  {
370  int idx = BaseZ + x;
371  // Find the lowest block in this column that receives full sunlight (go through transparent blocks):
372  int Current = m_HeightMap[idx];
373  ASSERT(Current < cChunkDef::Height);
374  while (
375  (Current >= 0) &&
377  !cBlockInfo::IsSkylightDispersant(m_BlockTypes[idx + Current * BlocksPerYLayer])
378  )
379  {
380  Current -= 1; // Sunlight goes down unchanged through this block
381  }
382  Current += 1; // Point to the last sunlit block, rather than the first non-transparent one
383  // The other neighbors don't need transparent-block-checking. At worst we'll have a few dud seeds above the ground.
384  int Neighbor1 = m_HeightMap[idx + 1] + 1; // X + 1
385  int Neighbor2 = m_HeightMap[idx - 1] + 1; // X - 1
386  int Neighbor3 = m_HeightMap[idx + cChunkDef::Width * 3] + 1; // Z + 1
387  int Neighbor4 = m_HeightMap[idx - cChunkDef::Width * 3] + 1; // Z - 1
388  int MaxNeighbor = std::max(std::max(Neighbor1, Neighbor2), std::max(Neighbor3, Neighbor4)); // Maximum of the four neighbors
389 
390  // Fill the column from m_MaxHeight to Current with all-light:
391  for (int y = m_MaxHeight, Index = idx + y * BlocksPerYLayer; y >= Current; y--, Index -= BlocksPerYLayer)
392  {
393  m_SkyLight[Index] = 15;
394  }
395 
396  // Add Current as a seed:
397  if (Current < cChunkDef::Height)
398  {
399  int CurrentIdx = idx + Current * BlocksPerYLayer;
400  m_IsSeed1[CurrentIdx] = true;
401  m_SeedIdx1[m_NumSeeds++] = static_cast<UInt32>(CurrentIdx);
402  }
403 
404  // Add seed from Current up to the highest neighbor:
405  for (int y = Current + 1, Index = idx + y * BlocksPerYLayer; y < MaxNeighbor; y++, Index += BlocksPerYLayer)
406  {
407  m_IsSeed1[Index] = true;
408  m_SeedIdx1[m_NumSeeds++] = static_cast<UInt32>(Index);
409  }
410  }
411  }
412 }
413 
414 
415 
416 
417 
419 {
420  // Clear seeds:
421  memset(m_IsSeed1, 0, sizeof(m_IsSeed1));
422  memset(m_IsSeed2, 0, sizeof(m_IsSeed2));
423  m_NumSeeds = 0;
424 
425  // Add each emissive block into the seeds:
426  for (int Idx = 0; Idx < (m_MaxHeight * BlocksPerYLayer); ++Idx)
427  {
429  {
430  // Not a light-emissive block
431  continue;
432  }
433 
434  // Add current block as a seed:
435  m_IsSeed1[Idx] = true;
436  m_SeedIdx1[m_NumSeeds++] = static_cast<UInt32>(Idx);
437 
438  // Light it up:
440  }
441 }
442 
443 
444 
445 
446 
448 {
449  size_t NumSeeds2 = 0;
450  while (m_NumSeeds > 0)
451  {
452  // Buffer 1 -> buffer 2
453  memset(m_IsSeed2, 0, sizeof(m_IsSeed2));
454  NumSeeds2 = 0;
456  if (NumSeeds2 == 0)
457  {
458  return;
459  }
460 
461  // Buffer 2 -> buffer 1
462  memset(m_IsSeed1, 0, sizeof(m_IsSeed1));
463  m_NumSeeds = 0;
465  }
466 }
467 
468 
469 
470 
471 
473  NIBBLETYPE * a_Light,
474  size_t a_NumSeedsIn, unsigned char * a_IsSeedIn, unsigned int * a_SeedIdxIn,
475  size_t & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut
476 )
477 {
478  UNUSED(a_IsSeedIn);
479  size_t NumSeedsOut = 0;
480  for (size_t i = 0; i < a_NumSeedsIn; i++)
481  {
482  UInt32 SeedIdx = static_cast<UInt32>(a_SeedIdxIn[i]);
483  int SeedX = SeedIdx % (cChunkDef::Width * 3);
484  int SeedZ = (SeedIdx / (cChunkDef::Width * 3)) % (cChunkDef::Width * 3);
485 
486  // Propagate seed:
487  if (SeedX < cChunkDef::Width * 3 - 1)
488  {
489  PropagateLight(a_Light, SeedIdx, SeedIdx + 1, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut);
490  }
491  if (SeedX > 0)
492  {
493  PropagateLight(a_Light, SeedIdx, SeedIdx - 1, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut);
494  }
495  if (SeedZ < cChunkDef::Width * 3 - 1)
496  {
497  PropagateLight(a_Light, SeedIdx, SeedIdx + cChunkDef::Width * 3, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut);
498  }
499  if (SeedZ > 0)
500  {
501  PropagateLight(a_Light, SeedIdx, SeedIdx - cChunkDef::Width * 3, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut);
502  }
503  if (SeedIdx < (cChunkDef::Height - 1) * BlocksPerYLayer)
504  {
505  PropagateLight(a_Light, SeedIdx, SeedIdx + BlocksPerYLayer, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut);
506  }
507  if (SeedIdx >= BlocksPerYLayer)
508  {
509  PropagateLight(a_Light, SeedIdx, SeedIdx - BlocksPerYLayer, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut);
510  }
511  } // for i - a_SeedIdxIn[]
512  a_NumSeedsOut = NumSeedsOut;
513 }
514 
515 
516 
517 
518 
519 void cLightingThread::CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_ChunkLight)
520 {
521  int InIdx = cChunkDef::Width * 49; // Index to the first nibble of the middle chunk in the a_LightArray
522  int OutIdx = 0;
523  for (int y = 0; y < cChunkDef::Height; y++)
524  {
525  for (int z = 0; z < cChunkDef::Width; z++)
526  {
527  for (int x = 0; x < cChunkDef::Width; x += 2)
528  {
529  a_ChunkLight[OutIdx++] = static_cast<NIBBLETYPE>(a_LightArray[InIdx + 1] << 4) | a_LightArray[InIdx];
530  InIdx += 2;
531  }
532  InIdx += cChunkDef::Width * 2;
533  }
534  // Skip into the next y-level in the 3x3 chunk blob; each level has cChunkDef::Width * 9 rows
535  // We've already walked cChunkDef::Width * 3 in the "for z" cycle, that makes cChunkDef::Width * 6 rows left to skip
536  InIdx += cChunkDef::Width * cChunkDef::Width * 6;
537  }
538 }
539 
540 
541 
542 
543 
545 {
546  // Move the ChunkStay from the Pending queue to the lighting queue.
547  {
548  cCSLock Lock(m_CS);
549  m_PendingQueue.remove(&a_ChunkStay);
550  m_Queue.push_back(&a_ChunkStay);
551  }
553 }
554 
555 
556 
557 
558 
560 // cLightingThread::cLightingChunkStay:
561 
562 cLightingThread::cLightingChunkStay::cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_CallbackAfter) :
563  m_LightingThread(a_LightingThread),
564  m_ChunkX(a_ChunkX),
565  m_ChunkZ(a_ChunkZ),
566  m_CallbackAfter(std::move(a_CallbackAfter))
567 {
568  Add(a_ChunkX + 1, a_ChunkZ + 1);
569  Add(a_ChunkX + 1, a_ChunkZ);
570  Add(a_ChunkX + 1, a_ChunkZ - 1);
571  Add(a_ChunkX, a_ChunkZ + 1);
572  Add(a_ChunkX, a_ChunkZ);
573  Add(a_ChunkX, a_ChunkZ - 1);
574  Add(a_ChunkX - 1, a_ChunkZ + 1);
575  Add(a_ChunkX - 1, a_ChunkZ);
576  Add(a_ChunkX - 1, a_ChunkZ - 1);
577 }
578 
579 
580 
581 
582 
584 {
586 
587  // Keep the ChunkStay alive:
588  return false;
589 }
590 
591 
592 
593 
594 
596 {
597  // Nothing needed in this callback
598 }
599 
600 
601 
602 
Definition: FastNBT.h:131
void Set(void)
Sets the event - releases one thread that has been waiting in Wait().
Definition: Event.cpp:53
std::unique_ptr< cChunkCoordCallback > m_CallbackAfter
std::atomic< bool > m_ShouldTerminate
The overriden Execute() method should check this value periodically and terminate if this is true...
Definition: IsThread.h:32
Makes chunks stay loaded until this object is cleared or destroyed Works by setting internal flags in...
Definition: ChunkStay.h:35
void QueueChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallbackAfter)
Queues the entire chunk for lighting.
#define VERIFY(x)
Definition: Globals.h:339
BLOCKTYPE * m_BlockTypes
virtual void OnDisabled(void) override
Called by the ChunkMap when the ChunkStay is disabled.
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
const sChunkSection * GetSection(size_t a_SectionNum) const
Return a pointer to the chunk section or nullptr if all air.
Definition: ChunkData.cpp:288
virtual void HeightMap(const cChunkDef::HeightMap *a_Heightmap) override
void ReadChunks(int a_ChunkX, int a_ChunkZ)
Prepares m_BlockTypes and m_HeightMap data; zeroes out the light arrays.
static const int Width
Definition: ChunkDef.h:134
static const int NumBlocks
Definition: ChunkDef.h:136
static bool IsSkylightDispersant(BLOCKTYPE a_Type)
Definition: BlockInfo.h:36
void ChunkLighted(int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles &a_BlockLight, const cChunkDef::BlockNibbles &a_SkyLight)
Definition: World.cpp:2361
void PrepareBlockLight(void)
Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight.
cChunkStays m_PendingQueue
The ChunkStays that are waiting for load.
virtual void Execute(void) override
This is the main thread entrypoint.
HEIGHTTYPE * m_HeightMap
HEIGHTTYPE m_MaxHeight
The highest block in the current 3x3 chunk data.
unsigned char m_IsSeed2[BlocksPerYLayer *cChunkDef::Height]
void Enable(cChunkMap &a_ChunkMap)
Enables the ChunkStay on the specified chunkmap, causing it to load and generate chunks.
Definition: ChunkStay.cpp:80
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
static const int BlocksPerYLayer
unsigned char HEIGHTTYPE
The type used by the heightmap.
Definition: ChunkDef.h:48
HEIGHTTYPE m_MaxHeight
static NIBBLETYPE GetLightValue(BLOCKTYPE a_Type)
Definition: BlockInfo.h:30
static const int Height
Definition: ChunkDef.h:135
void LightChunk(cLightingChunkStay &a_Item)
Lights the entire chunk.
void CalcLight(NIBBLETYPE *a_Light)
Calculates light in the light array specified, using stored seeds.
void CompressLight(NIBBLETYPE *a_LightArray, NIBBLETYPE *a_ChunkLight)
Compresses from 1-block-per-byte (faster calc) into 2-blocks-per-byte (MC storage): ...
void Wait(void)
Waits until the event has been set.
Definition: Event.cpp:24
virtual void Disable(void)
Disables the ChunkStay, the chunks are released and the ChunkStay object can be edited with Add() and...
Definition: ChunkStay.cpp:93
Definition: World.h:65
int m_ReadingChunkX
void PrepareSkyLight(void)
Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight.
size_t GetQueueLength(void)
Temporary RAII unlock for a cCSLock.
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ)
Definition: World.cpp:2961
cLightingChunkStay(cLightingThread &a_LightingThread, int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallbackAfter)
Chunk data callback that takes the chunk data and puts them into cLightingThread&#39;s m_BlockTypes[] / m...
virtual bool OnAllChunksAvailable(void) override
Caled once all of the contained chunks are available.
#define ASSERT(x)
Definition: Globals.h:335
virtual ~cLightingThread() override
NIBBLETYPE m_SkyLight[BlocksPerYLayer *cChunkDef::Height]
void WaitForQueueEmpty(void)
Blocks until the queue is empty or the thread is terminated.
cLightingThread(cWorld &a_World)
void Stop(void)
Signals the thread to terminate and waits until it&#39;s finished.
Definition: IsThread.cpp:110
#define UNUSED
Definition: Globals.h:152
bool GetChunkData(cChunkCoords a_Coords, cChunkDataCallback &a_Callback) const
Calls the callback with the chunk&#39;s data, if available (with ChunkCS locked).
Definition: World.cpp:2374
unsigned int m_SeedIdx2[BlocksPerYLayer *cChunkDef::Height]
cCriticalSection m_CS
The mutex to protect m_Queue and m_PendingQueue.
cChunkMap * GetChunkMap(void)
Definition: World.h:1044
NIBBLETYPE m_BlockLight[BlocksPerYLayer *cChunkDef::Height]
static bool IsTransparent(BLOCKTYPE a_Type)
Definition: BlockInfo.h:32
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
cChunkStays m_Queue
The ChunkStays that are loaded and are waiting to be lit.
unsigned int UInt32
Definition: Globals.h:113
unsigned char m_IsSeed1[BlocksPerYLayer *cChunkDef::Height]
static const size_t NumSections
Definition: ChunkData.h:24
BLOCKTYPE m_BlockTypes[BlocksPerYLayer *cChunkDef::Height]
NIBBLETYPE BlockNibbles[NumBlocks/2]
The type used for block data in nibble format, AXIS_ORDER ordering.
Definition: ChunkDef.h:153
void Add(int a_ChunkX, int a_ChunkZ)
Adds a chunk to be locked from unloading.
Definition: ChunkStay.cpp:42
unsigned int m_SeedIdx1[BlocksPerYLayer *cChunkDef::Height]
void CalcLightStep(NIBBLETYPE *a_Light, size_t a_NumSeedsIn, unsigned char *a_IsSeedIn, unsigned int *a_SeedIdxIn, size_t &a_NumSeedsOut, unsigned char *a_IsSeedOut, unsigned int *a_SeedIdxOut)
Does one step in the light calculation - one seed propagation and seed recalculation.
cReader(BLOCKTYPE *a_BlockTypes, HEIGHTTYPE *a_HeightMap)
void PropagateLight(NIBBLETYPE *a_Light, unsigned int a_SrcIdx, unsigned int a_DstIdx, size_t &a_NumSeedsOut, unsigned char *a_IsSeedOut, unsigned int *a_SeedIdxOut)
HEIGHTTYPE HeightMap[Width *Width]
The type used for any heightmap operations and storage; idx = x + Width * z; Height points to the hig...
Definition: ChunkDef.h:142
int m_ReadingChunkZ
void QueueChunkStay(cLightingChunkStay &a_ChunkStay)
Queues a chunkstay that has all of its chunks loaded.
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:290
virtual void ChunkData(const cChunkData &a_ChunkBuffer) override
static const int SectionHeight
Definition: ChunkData.h:23
HEIGHTTYPE m_HeightMap[BlocksPerYLayer]