Cuberite
A lightweight, fast and extensible game server for Minecraft
ChunkMap.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
3 
4 #include "ChunkMap.h"
5 #include "World.h"
6 #include "Root.h"
7 #include "Entities/Player.h"
8 #include "Item.h"
9 #include "Chunk.h"
10 #include "Generating/Trees.h" // used in cChunkMap::ReplaceTreeBlocks() for tree block discrimination
11 #include "BlockArea.h"
12 #include "Bindings/PluginManager.h"
13 #include "Entities/TNTEntity.h"
14 #include "Blocks/BlockHandler.h"
15 #include "MobCensus.h"
16 #include "MobSpawner.h"
17 #include "BoundingBox.h"
18 #include "SetChunkData.h"
19 #include "Blocks/ChunkInterface.h"
20 #include "Entities/Pickup.h"
21 #include "DeadlockDetect.h"
23 
24 #ifndef _WIN32
25  #include <cstdlib> // abs
26 #endif
27 
28 #include "zlib/zlib.h"
29 #include "json/json.h"
30 
31 
32 
33 
34 
36 // cChunkMap:
37 
39  m_World(a_World),
40  m_Pool(
42  cpp14::make_unique<cStarvationCallbacks>(), 1600u, 5000u
43  )
44  )
45 {
46 }
47 
48 
49 
50 
51 
53 {
54  // Explicitly destroy all chunks, so that they're guaranteed to be
55  // destroyed before other internals. This fixes crashes on stopping the server.
56  // because the chunk destructor deletes entities and those may access the chunkmap.
57  // Also, the cChunkData destructor accesses the chunkMap's allocator.
58  m_Chunks.clear();
59 }
60 
61 
62 
63 
64 
65 cChunkPtr cChunkMap::ConstructChunk(int a_ChunkX, int a_ChunkZ)
66 {
67  auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
68  if (Chunk == nullptr)
69  {
70  return (
71  *m_Chunks.emplace(
72  ChunkCoordinate{ a_ChunkX, a_ChunkZ },
73  cpp14::make_unique<cChunk>(
74  a_ChunkX,
75  a_ChunkZ,
76  this,
77  GetWorld(),
78  FindChunk(a_ChunkX - 1, a_ChunkZ),
79  FindChunk(a_ChunkX + 1, a_ChunkZ),
80  FindChunk(a_ChunkX, a_ChunkZ - 1),
81  FindChunk(a_ChunkX, a_ChunkZ + 1),
82  *m_Pool
83  )
84  ).first
85  ).second.get();
86  }
87  return Chunk;
88 }
89 
90 
91 
92 
93 
94 cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
95 {
96  ASSERT(m_CSChunks.IsLockedByCurrentThread()); // m_CSChunks should already be locked by the operation that called us
97 
98  auto Chunk = ConstructChunk(a_ChunkX, a_ChunkZ);
99  if (Chunk == nullptr)
100  {
101  return nullptr;
102  }
103  if (!Chunk->IsValid() && !Chunk->IsQueued())
104  {
105  Chunk->SetPresence(cChunk::cpQueued);
106  Chunk->SetShouldGenerateIfLoadFailed(true);
107  m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ);
108  }
109  return Chunk;
110 }
111 
112 
113 
114 
115 
117 {
118  ASSERT(m_CSChunks.IsLockedByCurrentThread()); // m_CSChunks should already be locked by the operation that called us
119 
120  auto Chunk = ConstructChunk(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
121  if (Chunk == nullptr)
122  {
123  return nullptr;
124  }
125  if (!Chunk->IsValid() && !Chunk->IsQueued())
126  {
127  Chunk->SetPresence(cChunk::cpQueued);
128  m_World->GetStorage().QueueLoadChunk(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
129  }
130 
131  return Chunk;
132 }
133 
134 
135 
136 
137 
139 {
140  ASSERT(m_CSChunks.IsLockedByCurrentThread()); // m_CSChunks should already be locked by the operation that called us
141  return ConstructChunk(a_Coords.m_ChunkX, a_Coords.m_ChunkZ);
142 }
143 
144 
145 
146 
147 
148 cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ)
149 {
151 
152  auto Chunk = m_Chunks.find({ a_ChunkX, a_ChunkZ });
153  return (Chunk == m_Chunks.end()) ? nullptr : Chunk->second.get();
154 }
155 
156 
157 
158 
159 
160 void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client)
161 {
162  cCSLock Lock(m_CSChunks);
163  int ChunkX, ChunkZ;
164  cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
165  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
166  if ((Chunk == nullptr) || !Chunk->IsValid())
167  {
168  return;
169  }
170  Chunk->SendBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Client);
171 }
172 
173 
174 
175 
176 
177 bool cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
178 {
179  // a_Player rclked block entity at the coords specified, handle it
180  cCSLock Lock(m_CSChunks);
181  int ChunkX, ChunkZ;
182  cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
183  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
184  if ((Chunk == nullptr) || !Chunk->IsValid())
185  {
186  return false;
187  }
188  return Chunk->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ);
189 }
190 
191 
192 
193 
194 
195 bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback)
196 {
197  cCSLock Lock(m_CSChunks);
198  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
199  if (Chunk == nullptr)
200  {
201  return false;
202  }
203  return a_Callback(*Chunk);
204 }
205 
206 
207 
208 
209 
211 {
212  int ChunkX, ChunkZ;
213  cChunkDef::BlockToChunk(a_BlockPos.x, a_BlockPos.z, ChunkX, ChunkZ);
214  return DoWithChunk(ChunkX, ChunkZ, a_Callback);
215 }
216 
217 
218 
219 
220 
222 {
223  cCSLock Lock(m_CSChunks);
225  if ((Chunk == nullptr) || !Chunk->IsValid())
226  {
227  return;
228  }
229  m_World->GetSimulatorManager()->WakeUp(a_Block, Chunk);
230 }
231 
232 
233 
234 
235 
236 void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ)
237 {
238  cCSLock Lock(m_CSChunks);
239  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
240  if ((Chunk == nullptr) || !Chunk->IsValid())
241  {
242  return;
243  }
244  Chunk->MarkDirty();
245 }
246 
247 
248 
249 
250 
251 void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
252 {
253  cCSLock Lock(m_CSChunks);
254  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
255  if ((Chunk == nullptr) || !Chunk->IsValid())
256  {
257  return;
258  }
259  Chunk->MarkSaving();
260 }
261 
262 
263 
264 
265 
266 void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
267 {
268  cCSLock Lock(m_CSChunks);
269  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
270  if ((Chunk == nullptr) || !Chunk->IsValid())
271  {
272  return;
273  }
274  Chunk->MarkSaved();
275 }
276 
277 
278 
279 
280 
282 {
283  int ChunkX = a_SetChunkData.GetChunkX();
284  int ChunkZ = a_SetChunkData.GetChunkZ();
285  {
286  cCSLock Lock(m_CSChunks);
287  cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
288  if (Chunk == nullptr)
289  {
290  return;
291  }
292  Chunk->SetAllData(a_SetChunkData);
293 
294  if (a_SetChunkData.ShouldMarkDirty())
295  {
296  Chunk->MarkDirty();
297  }
298 
299  // Notify relevant ChunkStays:
300  cChunkStays ToBeDisabled;
301  for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
302  {
303  if ((*itr)->ChunkAvailable(ChunkX, ChunkZ))
304  {
305  // The chunkstay wants to be disabled, add it to a list of to-be-disabled chunkstays for later processing:
306  ToBeDisabled.push_back(*itr);
307  }
308  } // for itr - m_ChunkStays[]
309 
310  // Disable (and possibly remove) the chunkstays that chose to get disabled:
311  for (cChunkStays::iterator itr = ToBeDisabled.begin(), end = ToBeDisabled.end(); itr != end; ++itr)
312  {
313  (*itr)->Disable();
314  }
315  }
316 
317  // Notify plugins of the chunk becoming available
319 }
320 
321 
322 
323 
324 
326  int a_ChunkX, int a_ChunkZ,
327  const cChunkDef::BlockNibbles & a_BlockLight,
328  const cChunkDef::BlockNibbles & a_SkyLight
329 )
330 {
331  cCSLock Lock(m_CSChunks);
332  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
333  if (Chunk == nullptr)
334  {
335  return;
336  }
337  Chunk->SetLight(a_BlockLight, a_SkyLight);
338  Chunk->MarkDirty();
339 }
340 
341 
342 
343 
344 
345 bool cChunkMap::GetChunkData(cChunkCoords a_Coords, cChunkDataCallback & a_Callback)
346 {
347  if (!a_Callback.Coords(a_Coords.m_ChunkX, a_Coords.m_ChunkZ))
348  {
349  // The callback doesn't want the data
350  return false;
351  }
352  cCSLock Lock(m_CSChunks);
353  cChunkPtr Chunk = GetChunkNoGen(a_Coords);
354  if ((Chunk == nullptr) || !Chunk->IsValid())
355  {
356  // The chunk is not present
357  return false;
358  }
359  Chunk->GetAllData(a_Callback);
360  return true;
361 }
362 
363 
364 
365 
366 
367 bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes)
368 {
369  cCSLock Lock(m_CSChunks);
370  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
371  if ((Chunk == nullptr) || !Chunk->IsValid())
372  {
373  return false;
374  }
375  Chunk->GetBlockTypes(a_BlockTypes);
376  return true;
377 }
378 
379 
380 
381 
382 
383 bool cChunkMap::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
384 {
385  cCSLock Lock(m_CSChunks);
386  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
387  return (Chunk != nullptr) && Chunk->IsQueued();
388 }
389 
390 
391 
392 
393 
394 bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
395 {
396  cCSLock Lock(m_CSChunks);
397  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
398  return (Chunk != nullptr) && Chunk->IsValid();
399 }
400 
401 
402 
403 
404 
405 bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
406 {
407  cCSLock Lock(m_CSChunks);
408  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
409  return (Chunk != nullptr) && Chunk->HasAnyClients();
410 }
411 
412 
413 
414 
415 
416 int cChunkMap::GetHeight(int a_BlockX, int a_BlockZ)
417 {
418  for (;;)
419  {
420  cCSLock Lock(m_CSChunks);
421  int ChunkX, ChunkZ, BlockY = 0;
422  cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
423  cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
424  if (Chunk == nullptr)
425  {
426  return 0;
427  }
428 
429  if (Chunk->IsValid())
430  {
431  return Chunk->GetHeight(a_BlockX, a_BlockZ);
432  }
433 
434  // The chunk is not valid, wait for it to become valid:
435  cCSUnlock Unlock(Lock);
437  } // while (true)
438 }
439 
440 
441 
442 
443 
444 bool cChunkMap::TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height)
445 {
446  // Returns false if chunk not loaded / generated
447  cCSLock Lock(m_CSChunks);
448  int ChunkX, ChunkZ, BlockY = 0;
449  cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
450  cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
451  if ((Chunk == nullptr) || !Chunk->IsValid())
452  {
453  return false;
454  }
455  a_Height = Chunk->GetHeight(a_BlockX, a_BlockZ);
456  return true;
457 }
458 
459 
460 
461 
462 
463 void cChunkMap::FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
464 {
465  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
466  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
467 
468  cCSLock Lock(m_CSChunks);
469  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
470  if ((chunk != nullptr) && chunk->IsValid())
471  {
472  chunk->FastSetBlock(relPos, a_BlockType, a_BlockMeta);
473  }
474 }
475 
476 
477 
478 
479 
480 void cChunkMap::SetBlocks(const sSetBlockVector & a_Blocks)
481 {
482  cCSLock lock(m_CSChunks);
483  cChunkPtr chunk = nullptr;
484  int lastChunkX = 0x7fffffff; // Bogus coords so that chunk is updated on first pass
485  int lastChunkZ = 0x7fffffff;
486  for (auto block: a_Blocks)
487  {
488  // Update the chunk, if different from last time:
489  if ((block.m_ChunkX != lastChunkX) || (block.m_ChunkZ != lastChunkZ))
490  {
491  lastChunkX = block.m_ChunkX;
492  lastChunkZ = block.m_ChunkZ;
493  chunk = GetChunk(lastChunkX, lastChunkZ);
494  }
495 
496  // If the chunk is valid, set the block:
497  if (chunk != nullptr)
498  {
499  chunk->SetBlock({block.m_RelX, block.m_RelY, block.m_RelZ}, block.m_BlockType, block.m_BlockMeta);
500  }
501  } // for block - a_Blocks[]
502 }
503 
504 
505 
506 
507 
509 {
510  int BlockX = static_cast<int>(a_Player.GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
511  int BlockY = static_cast<int>(a_Player.GetPosY());
512  int BlockZ = static_cast<int>(a_Player.GetPosZ());
513  int ChunkX = 0, ChunkZ = 0;
514  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
515  int OtherChunkX = ChunkX + ((BlockX > 8) ? 1 : -1);
516  int OtherChunkZ = ChunkZ + ((BlockZ > 8) ? 1 : -1);
517 
518  // We suppose that each player keeps their chunks in memory, therefore it makes little sense to try to re-load or even generate them.
519  // The only time the chunks are not valid is when the player is downloading the initial world and they should not call this at that moment
520 
521  cCSLock Lock(m_CSChunks);
522  GetChunkNoLoad(ChunkX, ChunkZ)->CollectPickupsByPlayer(a_Player);
523 
524  // Check the neighboring chunks as well:
525  GetChunkNoLoad(OtherChunkX, ChunkZ)->CollectPickupsByPlayer (a_Player);
526  GetChunkNoLoad(OtherChunkX, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
527  GetChunkNoLoad(ChunkX, ChunkZ)->CollectPickupsByPlayer (a_Player);
528  GetChunkNoLoad(ChunkX, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
529 }
530 
531 
532 
533 
534 
536 {
537  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
538  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
539 
540  // Query the chunk, if loaded:
541  cCSLock Lock(m_CSChunks);
542  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
543  if ((chunk != nullptr) && chunk->IsValid())
544  {
545  return chunk->GetBlock(relPos);
546  }
547  return 0;
548 }
549 
550 
551 
552 
553 
555 {
556  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
557  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
558 
559  // Query the chunk, if loaded:
560  cCSLock Lock(m_CSChunks);
561  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
562  if ((chunk != nullptr) && chunk->IsValid())
563  {
564  return chunk->GetMeta(relPos);
565  }
566  return 0;
567 }
568 
569 
570 
571 
572 
574 {
575  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
576  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
577 
578  // Query the chunk, if loaded:
579  cCSLock Lock(m_CSChunks);
580  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
581  if ((chunk != nullptr) && chunk->IsValid())
582  {
583  return chunk->GetSkyLight(relPos);
584  }
585  return 0;
586 }
587 
588 
589 
590 
591 
593 {
594  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
595  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
596 
597  // Query the chunk, if loaded:
598  cCSLock Lock(m_CSChunks);
599  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
600  if ((chunk != nullptr) && chunk->IsValid())
601  {
602  return chunk->GetBlockLight(relPos);
603  }
604  return 0;
605 }
606 
607 
608 
609 
610 
611 void cChunkMap::SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta, bool a_ShouldMarkDirty, bool a_ShouldInformClients)
612 {
613  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
614  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
615 
616  // Query the chunk, if loaded:
617  cCSLock Lock(m_CSChunks);
618  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
619  if ((chunk != nullptr) && chunk->IsValid())
620  {
621  chunk->SetMeta(relPos, a_BlockMeta, a_ShouldMarkDirty, a_ShouldInformClients);
622  }
623 }
624 
625 
626 
627 
628 
629 void cChunkMap::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
630 {
631  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
632  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
633 
634  cCSLock Lock(m_CSChunks);
635  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
636  if ((chunk != nullptr) && chunk->IsValid())
637  {
638  BLOCKTYPE blockType;
639  NIBBLETYPE blockMeta;
640  GetBlockTypeMeta(a_BlockPos, blockType, blockMeta);
641  cChunkInterface ChunkInterface(this);
642  BlockHandler(blockType)->OnBroken(ChunkInterface, *m_World, a_BlockPos, blockType, blockMeta);
643  chunk->SetBlock(relPos, a_BlockType, a_BlockMeta);
644  m_World->GetSimulatorManager()->WakeUp(a_BlockPos, chunk);
645  BlockHandler(a_BlockType)->OnPlaced(ChunkInterface, *m_World, a_BlockPos, a_BlockType, a_BlockMeta);
646  }
647 }
648 
649 
650 
651 
652 
653 bool cChunkMap::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
654 {
655  auto chunkCoord = cChunkDef::BlockToChunk(a_BlockPos);
656  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoord);
657 
658  cCSLock Lock(m_CSChunks);
659  auto chunk = GetChunk(chunkCoord.m_ChunkX, chunkCoord.m_ChunkZ);
660  if ((chunk != nullptr) && chunk->IsValid())
661  {
662  chunk->GetBlockTypeMeta(relPos, a_BlockType, a_BlockMeta);
663  return true;
664  }
665  return false;
666 }
667 
668 
669 
670 
671 
672 bool cChunkMap::GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight)
673 {
674  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
675  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
676 
677  // Query the chunk, if loaded:
678  cCSLock Lock(m_CSChunks);
679  auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
680  if ((chunk != nullptr) && chunk->IsValid())
681  {
682  chunk->GetBlockInfo(relPos, a_BlockType, a_Meta, a_SkyLight, a_BlockLight);
683  return true;
684  }
685  return false;
686 }
687 
688 
689 
690 
691 
692 void cChunkMap::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType)
693 {
694  cCSLock Lock(m_CSChunks);
695  for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
696  {
697  auto chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
698  if ((chunk == nullptr) || !chunk->IsValid())
699  {
700  continue;
701  }
702  Vector3i relPos(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
703  if (chunk->GetBlock(relPos) == a_FilterBlockType)
704  {
705  chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta);
706  }
707  }
708 }
709 
710 
711 
712 
713 
715 {
716  cCSLock Lock(m_CSChunks);
717  for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
718  {
719  auto chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
720  if ((chunk == nullptr) || !chunk->IsValid())
721  {
722  continue;
723  }
724  Vector3i relPos(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
725  switch (chunk->GetBlock(relPos))
726  {
728  {
729  chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta);
730  break;
731  }
732  case E_BLOCK_LEAVES:
733  case E_BLOCK_NEW_LEAVES:
734  {
735  if ((itr->m_BlockType == E_BLOCK_LOG) || (itr->m_BlockType == E_BLOCK_NEW_LOG))
736  {
737  chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta);
738  }
739  break;
740  }
741  }
742  } // for itr - a_Blocks[]
743 }
744 
745 
746 
747 
748 
749 EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ)
750 {
751  int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ;
752  cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
753 
754  cCSLock Lock(m_CSChunks);
755  cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
756  if ((Chunk != nullptr) && Chunk->IsValid())
757  {
758  return Chunk->GetBiomeAt(X, Z);
759  }
760  else
761  {
762  return m_World->GetGenerator().GetBiomeAt(a_BlockX, a_BlockZ);
763  }
764 }
765 
766 
767 
768 
769 
770 bool cChunkMap::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
771 {
772  int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ;
773  cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
774 
775  cCSLock Lock(m_CSChunks);
776  cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
777  if ((Chunk != nullptr) && Chunk->IsValid())
778  {
779  Chunk->SetBiomeAt(X, Z, a_Biome);
780  return true;
781  }
782  return false;
783 }
784 
785 
786 
787 
788 
789 bool cChunkMap::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome)
790 {
791  // Translate coords to relative:
792  int Y = 0;
793  int MinChunkX, MinChunkZ, MinX = a_MinX, MinZ = a_MinZ;
794  int MaxChunkX, MaxChunkZ, MaxX = a_MaxX, MaxZ = a_MaxZ;
795  cChunkDef::AbsoluteToRelative(MinX, Y, MinZ, MinChunkX, MinChunkZ);
796  cChunkDef::AbsoluteToRelative(MaxX, Y, MaxZ, MaxChunkX, MaxChunkZ);
797 
798  // Go through all chunks, set:
799  bool res = true;
800  cCSLock Lock(m_CSChunks);
801  for (int x = MinChunkX; x <= MaxChunkX; x++)
802  {
803  int MinRelX = (x == MinChunkX) ? MinX : 0;
804  int MaxRelX = (x == MaxChunkX) ? MaxX : cChunkDef::Width - 1;
805  for (int z = MinChunkZ; z <= MaxChunkZ; z++)
806  {
807  int MinRelZ = (z == MinChunkZ) ? MinZ : 0;
808  int MaxRelZ = (z == MaxChunkZ) ? MaxZ : cChunkDef::Width - 1;
809  cChunkPtr Chunk = GetChunkNoLoad(x, z);
810  if ((Chunk != nullptr) && Chunk->IsValid())
811  {
812  Chunk->SetAreaBiome(MinRelX, MaxRelX, MinRelZ, MaxRelZ, a_Biome);
813  }
814  else
815  {
816  res = false;
817  }
818  } // for z
819  } // for x
820  return res;
821 }
822 
823 
824 
825 
826 
827 bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
828 {
829  bool res = true;
830  cCSLock Lock(m_CSChunks);
831  for (sSetBlockVector::iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
832  {
833  cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
834  if ((Chunk == nullptr) || !Chunk->IsValid())
835  {
836  if (!a_ContinueOnFailure)
837  {
838  return false;
839  }
840  res = false;
841  continue;
842  }
843  itr->m_BlockType = Chunk->GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
844  itr->m_BlockMeta = Chunk->GetMeta(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
845  }
846  return res;
847 }
848 
849 
850 
851 
852 
854 {
855  auto chunkCoords = cChunkDef::BlockToChunk(a_BlockPos);
856  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoords);
857 
858  {
859  cCSLock Lock(m_CSChunks);
860  auto destChunk = GetChunk(chunkCoords.m_ChunkX, chunkCoords.m_ChunkZ);
861  if ((destChunk == nullptr) || !destChunk->IsValid())
862  {
863  return false;
864  }
865 
866  destChunk->SetBlock(relPos, E_BLOCK_AIR, 0);
867  m_World->GetSimulatorManager()->WakeUp(a_BlockPos, destChunk);
868  }
869  return true;
870 }
871 
872 
873 
874 
875 
876 cItems cChunkMap::PickupsFromBlock(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool)
877 {
878  auto chunkCoords = cChunkDef::BlockToChunk(a_BlockPos);
879  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoords);
880 
881  cCSLock Lock(m_CSChunks);
882  auto destChunk = GetChunk(chunkCoords.m_ChunkX, chunkCoords.m_ChunkZ);
883  if ((destChunk == nullptr) || !destChunk->IsValid())
884  {
885  return {};
886  }
887  return destChunk->PickupsFromBlock(relPos, a_Digger, a_Tool);
888 }
889 
890 
891 
892 
893 
894 void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer & a_Player)
895 {
896  int ChunkX, ChunkZ;
897  cChunkDef::AbsoluteToRelative(a_X, a_Y, a_Z, ChunkX, ChunkZ);
898 
899  cCSLock Lock(m_CSChunks);
900  cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
901  if ((Chunk != nullptr) && (Chunk->IsValid()))
902  {
903  Chunk->SendBlockTo(a_X, a_Y, a_Z, a_Player.GetClientHandle());
904  }
905 }
906 
907 
908 
909 
910 
911 void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
912 {
913  cCSLock Lock(m_CSChunks);
914  cChunkPtr Chunk1 = GetChunkNoGen(a_ChunkX1, a_ChunkZ1);
915  if (Chunk1 == nullptr)
916  {
917  return;
918  }
919  cChunkPtr Chunk2 = GetChunkNoGen(a_ChunkX2, a_ChunkZ2);
920  if (Chunk2 == nullptr)
921  {
922  return;
923  }
924 
925  CompareChunkClients(Chunk1, Chunk2, a_Callback);
926 }
927 
928 
929 
930 
931 
932 void cChunkMap::CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback)
933 {
934  auto Clients1 = a_Chunk1->GetAllClients();
935  auto Clients2 = a_Chunk2->GetAllClients();
936 
937  // Find "removed" clients:
938  for (auto * Client : Clients1)
939  {
940  bool Found = (std::find(Clients2.begin(), Clients2.end(), Client) != Clients2.end());
941  if (!Found)
942  {
943  a_Callback.Removed(Client);
944  }
945  } // for Client - Clients1[]
946 
947  // Find "added" clients:
948  for (auto * Client : Clients2)
949  {
950  bool Found = (std::find(Clients1.begin(), Clients1.end(), Client) != Clients1.end());
951  if (!Found)
952  {
953  a_Callback.Added(Client);
954  }
955  } // for Client - Clients2[]
956 }
957 
958 
959 
960 
961 
962 bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
963 {
964  cCSLock Lock(m_CSChunks);
965  cChunkPtr Chunk = GetChunk(a_ChunkX, a_ChunkZ);
966  if (Chunk == nullptr)
967  {
968  return false;
969  }
970  return Chunk->AddClient(a_Client);
971 }
972 
973 
974 
975 
976 
977 void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
978 {
979  cCSLock Lock(m_CSChunks);
980  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
981  if (Chunk == nullptr)
982  {
983  return;
984  }
985  Chunk->RemoveClient(a_Client);
986 }
987 
988 
989 
990 
991 
993 {
994  cCSLock Lock(m_CSChunks);
995  for (const auto & Chunk : m_Chunks)
996  {
997  Chunk.second->RemoveClient(a_Client);
998  }
999 }
1000 
1001 
1002 
1003 
1004 
1006 {
1007  cCSLock Lock(m_CSChunks);
1008  cChunkPtr Chunk = GetChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
1009  if (Chunk == nullptr) // This will assert inside GetChunk in Debug builds
1010  {
1011  LOGWARNING("Entity at %p (%s, ID %d) spawning in a non-existent chunk, the entity is lost.",
1012  static_cast<void *>(a_Entity.get()), a_Entity->GetClass(), a_Entity->GetUniqueID()
1013  );
1014  return;
1015  }
1016  Chunk->AddEntity(std::move(a_Entity));
1017 }
1018 
1019 
1020 
1021 
1022 
1024 {
1025  cCSLock Lock(m_CSChunks);
1026  cChunkPtr Chunk = GetChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
1027  if (Chunk == nullptr) // This will assert inside GetChunk in Debug builds
1028  {
1029  LOGWARNING("Entity at %p (%s, ID %d) spawning in a non-existent chunk, the entity is lost.",
1030  static_cast<void *>(a_Entity.get()), a_Entity->GetClass(), a_Entity->GetUniqueID()
1031  );
1032  return;
1033  }
1034  if (!Chunk->HasEntity(a_Entity->GetUniqueID()))
1035  {
1036  Chunk->AddEntity(std::move(a_Entity));
1037  }
1038 }
1039 
1040 
1041 
1042 
1043 
1045 {
1046  cCSLock Lock(m_CSChunks);
1047  for (const auto & Chunk : m_Chunks)
1048  {
1049  if (Chunk.second->IsValid() && Chunk.second->HasEntity(a_UniqueID))
1050  {
1051  return true;
1052  }
1053  }
1054  return false;
1055 }
1056 
1057 
1058 
1059 
1060 
1062 {
1063  cCSLock Lock(m_CSChunks);
1064  cChunkPtr Chunk = a_Entity.GetParentChunk();
1065 
1066  if (Chunk == nullptr)
1067  {
1068  return nullptr;
1069  }
1070 
1071  // Remove the entity no matter whether the chunk itself is valid or not (#1190)
1072  return Chunk->RemoveEntity(a_Entity);
1073 }
1074 
1075 
1076 
1077 
1078 
1080 {
1081  cCSLock Lock(m_CSChunks);
1082  for (const auto & Chunk : m_Chunks)
1083  {
1084  if (Chunk.second->IsValid() && !Chunk.second->ForEachEntity(a_Callback))
1085  {
1086  return false;
1087  }
1088  }
1089  return true;
1090 }
1091 
1092 
1093 
1094 
1095 
1096 bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback)
1097 {
1098  cCSLock Lock(m_CSChunks);
1099  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1100  if ((Chunk == nullptr) || !Chunk->IsValid())
1101  {
1102  return false;
1103  }
1104  return Chunk->ForEachEntity(a_Callback);
1105 }
1106 
1107 
1108 
1109 
1110 
1112 {
1113  // Calculate the chunk range for the box:
1114  int MinChunkX = FloorC(a_Box.GetMinX() / cChunkDef::Width);
1115  int MinChunkZ = FloorC(a_Box.GetMinZ() / cChunkDef::Width);
1116  int MaxChunkX = FloorC((a_Box.GetMaxX() + cChunkDef::Width) / cChunkDef::Width);
1117  int MaxChunkZ = FloorC((a_Box.GetMaxZ() + cChunkDef::Width) / cChunkDef::Width);
1118 
1119  // Iterate over each chunk in the range:
1120  cCSLock Lock(m_CSChunks);
1121  for (int z = MinChunkZ; z <= MaxChunkZ; z++)
1122  {
1123  for (int x = MinChunkX; x <= MaxChunkX; x++)
1124  {
1125  cChunkPtr Chunk = GetChunkNoGen(x, z);
1126  if ((Chunk == nullptr) || !Chunk->IsValid())
1127  {
1128  continue;
1129  }
1130  if (!Chunk->ForEachEntityInBox(a_Box, a_Callback))
1131  {
1132  return false;
1133  }
1134  } // for x
1135  } // for z
1136  return true;
1137 }
1138 
1139 
1140 
1141 
1142 
1143 void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlocksAffected)
1144 {
1145  // Don't explode if outside of Y range (prevents the following test running into unallocated memory):
1146  if (!cChunkDef::IsValidHeight(FloorC(a_BlockY)))
1147  {
1148  return;
1149  }
1150 
1151  bool ShouldDestroyBlocks = true;
1152 
1153  // Don't explode if the explosion center is inside a liquid block:
1154  if (IsBlockLiquid(m_World->GetBlock(FloorC(a_BlockX), FloorC(a_BlockY), FloorC(a_BlockZ))))
1155  {
1156  ShouldDestroyBlocks = false;
1157  }
1158 
1159  int ExplosionSizeInt = CeilC(a_ExplosionSize);
1160  int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt;
1161 
1162  int bx = FloorC(a_BlockX);
1163  int by = FloorC(a_BlockY);
1164  int bz = FloorC(a_BlockZ);
1165 
1166  int MinY = std::max(FloorC(a_BlockY - ExplosionSizeInt), 0);
1167  int MaxY = std::min(CeilC(a_BlockY + ExplosionSizeInt), cChunkDef::Height - 1);
1168 
1169  if (ShouldDestroyBlocks)
1170  {
1171  cBlockArea area;
1172  a_BlocksAffected.reserve(8 * static_cast<size_t>(ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt));
1173  if (!area.Read(*m_World, bx - ExplosionSizeInt, static_cast<int>(ceil(a_BlockX + ExplosionSizeInt)), MinY, MaxY, bz - ExplosionSizeInt, static_cast<int>(ceil(a_BlockZ + ExplosionSizeInt))))
1174  {
1175  return;
1176  }
1177 
1178  for (int x = -ExplosionSizeInt; x < ExplosionSizeInt; x++)
1179  {
1180  for (int y = -ExplosionSizeInt; y < ExplosionSizeInt; y++)
1181  {
1182  if ((by + y >= cChunkDef::Height) || (by + y < 0))
1183  {
1184  // Outside of the world
1185  continue;
1186  }
1187  for (int z = -ExplosionSizeInt; z < ExplosionSizeInt; z++)
1188  {
1189  if ((x * x + y * y + z * z) > ExplosionSizeSq)
1190  {
1191  // Too far away
1192  continue;
1193  }
1194 
1195  BLOCKTYPE Block = area.GetBlockType(bx + x, by + y, bz + z);
1196  switch (Block)
1197  {
1198  case E_BLOCK_TNT:
1199  {
1200  // Activate the TNT, with a random fuse between 10 to 30 game ticks
1201  int FuseTime = GetRandomProvider().RandInt(10, 30);
1202  m_World->SpawnPrimedTNT({a_BlockX + x + 0.5, a_BlockY + y + 0.5, a_BlockZ + z + 0.5}, FuseTime);
1203  area.SetBlockTypeMeta(bx + x, by + y, bz + z, E_BLOCK_AIR, 0);
1204  a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
1205  break;
1206  }
1207 
1208  case E_BLOCK_OBSIDIAN:
1209  case E_BLOCK_BEACON:
1210  case E_BLOCK_BEDROCK:
1211  case E_BLOCK_BARRIER:
1212  case E_BLOCK_WATER:
1213  case E_BLOCK_LAVA:
1214  {
1215  // These blocks are not affected by explosions
1216  break;
1217  }
1218 
1220  {
1221  // Turn into simulated water:
1222  area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_WATER);
1223  break;
1224  }
1225 
1227  {
1228  // Turn into simulated lava:
1229  area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_LAVA);
1230  break;
1231  }
1232 
1233  case E_BLOCK_AIR:
1234  {
1235  // No pickups for air
1236  break;
1237  }
1238 
1239  default:
1240  {
1241  auto & Random = GetRandomProvider();
1242  if (Random.RandBool(0.25)) // 25% chance of pickups
1243  {
1244  auto pickups = area.PickupsFromBlock({bx + x, by + y, bz + z});
1245  m_World->SpawnItemPickups(pickups, bx + x, by + y, bz + z);
1246  }
1247  else if ((m_World->GetTNTShrapnelLevel() > slNone) && Random.RandBool(0.20)) // 20% chance of flinging stuff around
1248  {
1249  // If the block is shrapnel-able, make a falling block entity out of it:
1250  if (
1252  ((m_World->GetTNTShrapnelLevel() == slGravityAffectedOnly) && ((Block == E_BLOCK_SAND) || (Block == E_BLOCK_GRAVEL)))
1253  )
1254  {
1255  m_World->SpawnFallingBlock(bx + x, by + y + 5, bz + z, Block, area.GetBlockMeta(bx + x, by + y, bz + z));
1256  }
1257  }
1258 
1259  // Destroy any block entities
1261  {
1262  Vector3i BlockPos(bx + x, by + y, bz + z);
1263  DoWithBlockEntityAt(BlockPos.x, BlockPos.y, BlockPos.z, [](cBlockEntity & a_BE)
1264  {
1265  a_BE.Destroy();
1266  return true;
1267  }
1268  );
1269  }
1270 
1271  area.SetBlockTypeMeta(bx + x, by + y, bz + z, E_BLOCK_AIR, 0);
1272  a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
1273  break;
1274  }
1275  } // switch (BlockType)
1276  } // for z
1277  } // for y
1278  } // for x
1279  area.Write(*m_World, bx - ExplosionSizeInt, MinY, bz - ExplosionSizeInt);
1280  }
1281 
1282  Vector3d ExplosionPos{ a_BlockX, a_BlockY, a_BlockZ };
1283  cBoundingBox bbTNT(ExplosionPos, 0.5, 1);
1284  bbTNT.Expand(ExplosionSizeInt * 2, ExplosionSizeInt * 2, ExplosionSizeInt * 2);
1285 
1286  ForEachEntity([&](cEntity & a_Entity)
1287  {
1288  if (a_Entity.IsPickup() && (a_Entity.GetTicksAlive() < 20))
1289  {
1290  // If pickup age is smaller than one second, it is invincible (so we don't kill pickups that were just spawned)
1291  return false;
1292  }
1293 
1294  Vector3d DistanceFromExplosion = a_Entity.GetPosition() - ExplosionPos;
1295 
1296  if (!a_Entity.IsTNT() && !a_Entity.IsFallingBlock()) // Don't apply damage to other TNT entities and falling blocks, they should be invincible
1297  {
1298  cBoundingBox bbEntity(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight());
1299 
1300  if (!bbTNT.IsInside(bbEntity)) // If bbEntity is inside bbTNT, not vice versa!
1301  {
1302  return false;
1303  }
1304 
1305  // Ensure that the damage dealt is inversely proportional to the distance to the TNT centre - the closer a player is, the harder they are hit
1306  a_Entity.TakeDamage(dtExplosion, nullptr, static_cast<int>((1 / DistanceFromExplosion.Length()) * 6 * ExplosionSizeInt), 0);
1307  }
1308 
1309  double Length = DistanceFromExplosion.Length();
1310  if (Length <= ExplosionSizeInt) // Entity is impacted by explosion
1311  {
1312  float EntityExposure = a_Entity.GetExplosionExposureRate(ExplosionPos, static_cast<float>(a_ExplosionSize));
1313 
1314  // Exposure reduced by armor
1315  EntityExposure = EntityExposure * (1.0f - a_Entity.GetEnchantmentBlastKnockbackReduction());
1316 
1317  double Impact = (1 - ((Length / ExplosionSizeInt) / 2)) * EntityExposure;
1318 
1319  DistanceFromExplosion.Normalize();
1320  DistanceFromExplosion *= Impact;
1321 
1322  a_Entity.AddSpeed(DistanceFromExplosion);
1323  }
1324 
1325  return false;
1326  }
1327  );
1328 
1329  // Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
1331  {bx - ExplosionSizeInt - 1, MinY, bz - ExplosionSizeInt - 1},
1332  {bx + ExplosionSizeInt + 1, MaxY, bz + ExplosionSizeInt + 1}
1333  ));
1334 }
1335 
1336 
1337 
1338 
1339 
1341 {
1342  cCSLock Lock(m_CSChunks);
1343  bool res = false;
1344  for (const auto & Chunk : m_Chunks)
1345  {
1346  if (Chunk.second->IsValid() && Chunk.second->DoWithEntityByID(a_UniqueID, a_Callback, res))
1347  {
1348  return res;
1349  }
1350  }
1351  return false;
1352 }
1353 
1354 
1355 
1356 
1357 
1358 bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback)
1359 {
1360  cCSLock Lock(m_CSChunks);
1361  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1362  if ((Chunk == nullptr) || !Chunk->IsValid())
1363  {
1364  return false;
1365  }
1366  return Chunk->ForEachBlockEntity(a_Callback);
1367 }
1368 
1369 
1370 
1371 
1372 
1373 bool cChunkMap::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback a_Callback)
1374 {
1375  cCSLock Lock(m_CSChunks);
1376  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1377  if ((Chunk == nullptr) || !Chunk->IsValid())
1378  {
1379  return false;
1380  }
1381  return Chunk->ForEachBrewingstand(a_Callback);
1382 }
1383 
1384 
1385 
1386 
1387 
1388 bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback a_Callback)
1389 {
1390  cCSLock Lock(m_CSChunks);
1391  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1392  if ((Chunk == nullptr) || !Chunk->IsValid())
1393  {
1394  return false;
1395  }
1396  return Chunk->ForEachChest(a_Callback);
1397 }
1398 
1399 
1400 
1401 
1402 
1403 bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback a_Callback)
1404 {
1405  cCSLock Lock(m_CSChunks);
1406  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1407  if ((Chunk == nullptr) || !Chunk->IsValid())
1408  {
1409  return false;
1410  }
1411  return Chunk->ForEachDispenser(a_Callback);
1412 }
1413 
1414 
1415 
1416 
1417 
1418 bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback a_Callback)
1419 {
1420  cCSLock Lock(m_CSChunks);
1421  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1422  if ((Chunk == nullptr) || !Chunk->IsValid())
1423  {
1424  return false;
1425  }
1426  return Chunk->ForEachDropper(a_Callback);
1427 }
1428 
1429 
1430 
1431 
1432 
1433 bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback a_Callback)
1434 {
1435  cCSLock Lock(m_CSChunks);
1436  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1437  if ((Chunk == nullptr) || !Chunk->IsValid())
1438  {
1439  return false;
1440  }
1441  return Chunk->ForEachDropSpenser(a_Callback);
1442 }
1443 
1444 
1445 
1446 
1447 
1448 bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback a_Callback)
1449 {
1450  cCSLock Lock(m_CSChunks);
1451  cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
1452  if ((Chunk == nullptr) || !Chunk->IsValid())
1453  {
1454  return false;
1455  }
1456  return Chunk->ForEachFurnace(a_Callback);
1457 }
1458 
1459 
1460 
1461 
1462 
1463 bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback)
1464 {
1465  int ChunkX, ChunkZ;
1466  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1467  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1468  cCSLock Lock(m_CSChunks);
1469  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1470  if ((Chunk == nullptr) || !Chunk->IsValid())
1471  {
1472  return false;
1473  }
1474  return Chunk->DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1475 }
1476 
1477 
1478 
1479 
1480 
1481 bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback)
1482 {
1483  int ChunkX, ChunkZ;
1484  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1485  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1486  cCSLock Lock(m_CSChunks);
1487  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1488  if ((Chunk == nullptr) || !Chunk->IsValid())
1489  {
1490  return false;
1491  }
1492  return Chunk->DoWithBeaconAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1493 }
1494 
1495 
1496 
1497 
1498 
1499 bool cChunkMap::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback)
1500 {
1501  int ChunkX, ChunkZ;
1502  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1503  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1504  cCSLock Lock(m_CSChunks);
1505  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1506  if ((Chunk == nullptr) || !Chunk->IsValid())
1507  {
1508  return false;
1509  }
1510  return Chunk->DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1511 }
1512 
1513 
1514 
1515 
1516 
1517 bool cChunkMap::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback)
1518 {
1519  int ChunkX, ChunkZ;
1520  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1521  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1522  cCSLock Lock(m_CSChunks);
1523  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1524  if ((Chunk == nullptr) || !Chunk->IsValid())
1525  {
1526  return false;
1527  }
1528  return Chunk->DoWithBrewingstandAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1529 }
1530 
1531 
1532 
1533 
1534 
1535 bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback)
1536 {
1537  int ChunkX, ChunkZ;
1538  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1539  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1540  cCSLock Lock(m_CSChunks);
1541  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1542  if ((Chunk == nullptr) || !Chunk->IsValid())
1543  {
1544  return false;
1545  }
1546  return Chunk->DoWithChestAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1547 }
1548 
1549 
1550 
1551 
1552 
1553 bool cChunkMap::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback)
1554 {
1555  int ChunkX, ChunkZ;
1556  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1557  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1558  cCSLock Lock(m_CSChunks);
1559  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1560  if ((Chunk == nullptr) || !Chunk->IsValid())
1561  {
1562  return false;
1563  }
1564  return Chunk->DoWithDispenserAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1565 }
1566 
1567 
1568 
1569 
1570 
1571 bool cChunkMap::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback)
1572 {
1573  int ChunkX, ChunkZ;
1574  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1575  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1576  cCSLock Lock(m_CSChunks);
1577  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1578  if ((Chunk == nullptr) || !Chunk->IsValid())
1579  {
1580  return false;
1581  }
1582  return Chunk->DoWithDropperAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1583 }
1584 
1585 
1586 
1587 
1588 
1589 bool cChunkMap::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback)
1590 {
1591  int ChunkX, ChunkZ;
1592  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1593  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1594  cCSLock Lock(m_CSChunks);
1595  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1596  if ((Chunk == nullptr) || !Chunk->IsValid())
1597  {
1598  return false;
1599  }
1600  return Chunk->DoWithDropSpenserAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1601 }
1602 
1603 
1604 
1605 
1606 
1607 bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback)
1608 {
1609  int ChunkX, ChunkZ;
1610  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1611  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1612  cCSLock Lock(m_CSChunks);
1613  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1614  if ((Chunk == nullptr) || !Chunk->IsValid())
1615  {
1616  return false;
1617  }
1618  return Chunk->DoWithFurnaceAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1619 }
1620 
1621 
1622 
1623 
1624 
1625 bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
1626 {
1627  int ChunkX, ChunkZ;
1628  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1629  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1630  cCSLock Lock(m_CSChunks);
1631  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1632  if ((Chunk == nullptr) || !Chunk->IsValid())
1633  {
1634  return false;
1635  }
1636  return Chunk->DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1637 }
1638 
1639 
1640 
1641 
1642 
1643 bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback)
1644 {
1645  int ChunkX, ChunkZ;
1646  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1647  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1648  cCSLock Lock(m_CSChunks);
1649  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1650  if ((Chunk == nullptr) || !Chunk->IsValid())
1651  {
1652  return false;
1653  }
1654  return Chunk->DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1655 }
1656 
1657 
1658 
1659 
1660 
1661 bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback)
1662 {
1663  int ChunkX, ChunkZ;
1664  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1665  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1666  cCSLock Lock(m_CSChunks);
1667  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1668  if ((Chunk == nullptr) || !Chunk->IsValid())
1669  {
1670  return false;
1671  }
1672  return Chunk->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1673 }
1674 
1675 
1676 
1677 
1678 
1679 bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback)
1680 {
1681  int ChunkX, ChunkZ;
1682  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1683  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1684  cCSLock Lock(m_CSChunks);
1685  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1686  if ((Chunk == nullptr) || !Chunk->IsValid())
1687  {
1688  return false;
1689  }
1690  return Chunk->DoWithFlowerPotAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
1691 }
1692 
1693 
1694 
1695 
1696 
1697 bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
1698 {
1699  int ChunkX, ChunkZ;
1700  int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
1701  cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
1702  cCSLock Lock(m_CSChunks);
1703  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1704  if ((Chunk == nullptr) || !Chunk->IsValid())
1705  {
1706  return false;
1707  }
1708  return Chunk->GetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
1709 }
1710 
1711 
1712 
1713 
1714 
1715 void cChunkMap::TouchChunk(int a_ChunkX, int a_ChunkZ)
1716 {
1717  cCSLock Lock(m_CSChunks);
1718  GetChunk(a_ChunkX, a_ChunkZ);
1719 }
1720 
1721 
1722 
1723 
1724 
1725 void cChunkMap::PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_Callback)
1726 {
1727  cCSLock Lock(m_CSChunks);
1728  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
1729 
1730  // If the chunk is not prepared, queue it in the lighting thread, that will do all the needed processing:
1731  if ((Chunk == nullptr) || !Chunk->IsValid() || !Chunk->IsLightValid())
1732  {
1733  m_World->GetLightingThread().QueueChunk(a_ChunkX, a_ChunkZ, std::move(a_Callback));
1734  return;
1735  }
1736 
1737  // The chunk is present and lit, just call the callback, report as success:
1738  if (a_Callback != nullptr)
1739  {
1740  a_Callback->Call({a_ChunkX, a_ChunkZ}, true);
1741  }
1742 }
1743 
1744 
1745 
1746 
1747 
1748 bool cChunkMap::GenerateChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback)
1749 {
1750  cCSLock Lock(m_CSChunks);
1751  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
1752  if (Chunk == nullptr)
1753  {
1754  // Generic error while getting the chunk - out of memory?
1755  return false;
1756  }
1757 
1758  // Try loading the chunk:
1759  if ((Chunk == nullptr) || (!Chunk->IsValid()))
1760  {
1761  Chunk->SetPresence(cChunk::cpQueued);
1762  class cPrepareLoadCallback: public cChunkCoordCallback
1763  {
1764  public:
1765  cPrepareLoadCallback(cWorld & a_CBWorld, cChunkMap & a_CBChunkMap, cChunkCoordCallback * a_CBCallback):
1766  m_World(a_CBWorld),
1767  m_ChunkMap(a_CBChunkMap),
1768  m_Callback(a_CBCallback)
1769  {
1770  }
1771 
1772  // cChunkCoordCallback override:
1773  virtual void Call(cChunkCoords a_Coords, bool a_CBIsSuccess) override
1774  {
1775  // If success is reported, the chunk is already valid, no need to do anything else:
1776  if (a_CBIsSuccess)
1777  {
1778  if (m_Callback != nullptr)
1779  {
1780  m_Callback->Call(a_Coords, true);
1781  }
1782  return;
1783  }
1784 
1785  // The chunk failed to load, generate it:
1786  cCSLock CBLock(m_ChunkMap.m_CSChunks);
1787  cChunkPtr CBChunk = m_ChunkMap.GetChunkNoLoad(a_Coords.m_ChunkX, a_Coords.m_ChunkZ);
1788 
1789  if (CBChunk == nullptr)
1790  {
1791  // An error occurred, but we promised to call the callback, so call it even when there's no real chunk data:
1792  if (m_Callback != nullptr)
1793  {
1794  m_Callback->Call(a_Coords, false);
1795  }
1796  return;
1797  }
1798 
1799  CBChunk->SetPresence(cChunk::cpQueued);
1800  m_World.GetGenerator().QueueGenerateChunk(a_Coords, false, m_Callback);
1801  }
1802 
1803  protected:
1804  cWorld & m_World;
1805  cChunkMap & m_ChunkMap;
1806  cChunkCoordCallback * m_Callback;
1807  };
1808  m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ, new cPrepareLoadCallback(*m_World, *this, a_Callback));
1809  return true;
1810  }
1811 
1812  // The chunk is valid, just call the callback:
1813  if (a_Callback != nullptr)
1814  {
1815  a_Callback->Call({a_ChunkX, a_ChunkZ}, true);
1816  }
1817  return true;
1818 }
1819 
1820 
1821 
1822 
1823 
1824 void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
1825 {
1826  cCSLock Lock(m_CSChunks);
1827  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
1828  if (Chunk == nullptr)
1829  {
1830  return;
1831  }
1832  Chunk->MarkLoadFailed();
1833 }
1834 
1835 
1836 
1837 
1838 
1839 bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
1840 {
1841  cCSLock Lock(m_CSChunks);
1842  int ChunkX, ChunkZ;
1843  cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
1844  cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
1845  if ((Chunk == nullptr) || !Chunk->IsValid())
1846  {
1847  return false;
1848  }
1849  return Chunk->SetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
1850 }
1851 
1852 
1853 
1854 
1855 
1856 void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
1857 {
1858  cCSLock Lock(m_CSChunks);
1859  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
1860  if (Chunk == nullptr)
1861  {
1862  // Not present
1863  return;
1864  }
1865  Chunk->MarkRegenerating();
1866 }
1867 
1868 
1869 
1870 
1871 
1872 bool cChunkMap::IsChunkLighted(int a_ChunkX, int a_ChunkZ)
1873 {
1874  cCSLock Lock(m_CSChunks);
1875  cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
1876  if (Chunk == nullptr)
1877  {
1878  // Not present
1879  return false;
1880  }
1881  return Chunk->IsLightValid();
1882 }
1883 
1884 
1885 
1886 
1887 
1888 bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback)
1889 {
1890  bool Result = true;
1891  cCSLock Lock(m_CSChunks);
1892  for (int z = a_MinChunkZ; z <= a_MaxChunkZ; z++)
1893  {
1894  for (int x = a_MinChunkX; x <= a_MaxChunkX; x++)
1895  {
1896  cChunkPtr Chunk = GetChunkNoLoad(x, z);
1897  if ((Chunk == nullptr) || (!Chunk->IsValid()))
1898  {
1899  // Not present / not valid
1900  Result = false;
1901  continue;
1902  }
1903  if (!a_Callback.Coords(x, z))
1904  {
1905  continue;
1906  }
1907  Chunk->GetAllData(a_Callback);
1908  }
1909  }
1910  return Result;
1911 }
1912 
1913 
1914 
1915 
1916 
1917 bool cChunkMap::ForEachLoadedChunk(cFunctionRef<bool(int, int)> a_Callback)
1918 {
1919  cCSLock Lock(m_CSChunks);
1920  for (const auto & Chunk : m_Chunks)
1921  {
1922  if (Chunk.second->IsValid())
1923  {
1924  if (a_Callback(Chunk.first.ChunkX, Chunk.first.ChunkZ))
1925  {
1926  return false;
1927  }
1928  }
1929  }
1930  return true;
1931 }
1932 
1933 
1934 
1935 
1936 
1937 bool cChunkMap::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
1938 {
1939  // Convert block coords to chunks coords:
1940  int MinChunkX, MaxChunkX;
1941  int MinChunkZ, MaxChunkZ;
1942  int MinBlockX = a_MinBlockX;
1943  int MinBlockY = a_MinBlockY;
1944  int MinBlockZ = a_MinBlockZ;
1945  int MaxBlockX = a_MinBlockX + a_Area.GetSizeX();
1946  int MaxBlockY = a_MinBlockY + a_Area.GetSizeY();
1947  int MaxBlockZ = a_MinBlockZ + a_Area.GetSizeZ();
1948  cChunkDef::AbsoluteToRelative(MinBlockX, MinBlockY, MinBlockZ, MinChunkX, MinChunkZ);
1949  cChunkDef::AbsoluteToRelative(MaxBlockX, MaxBlockY, MaxBlockZ, MaxChunkX, MaxChunkZ);
1950 
1951  // Iterate over chunks, write data into each:
1952  bool Result = true;
1953  cCSLock Lock(m_CSChunks);
1954  for (int z = MinChunkZ; z <= MaxChunkZ; z++)
1955  {
1956  for (int x = MinChunkX; x <= MaxChunkX; x++)
1957  {
1958  cChunkPtr Chunk = GetChunkNoLoad(x, z);
1959  if ((Chunk == nullptr) || (!Chunk->IsValid()))
1960  {
1961  // Not present / not valid
1962  Result = false;
1963  continue;
1964  }
1965  Chunk->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes);
1966  } // for x
1967  } // for z
1968  return Result;
1969 }
1970 
1971 
1972 
1973 
1974 
1975 void cChunkMap::GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty)
1976 {
1977  a_NumChunksValid = 0;
1978  a_NumChunksDirty = 0;
1979  cCSLock Lock(m_CSChunks);
1980  for (const auto & Chunk : m_Chunks)
1981  {
1982  a_NumChunksValid++;
1983  if (Chunk.second->IsDirty())
1984  {
1985  a_NumChunksDirty++;
1986  }
1987  }
1988 }
1989 
1990 
1991 
1992 
1993 
1994 int cChunkMap::GrowPlantAt(Vector3i a_BlockPos, int a_NumStages)
1995 {
1996  auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
1997  auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
1998  cCSLock lock(m_CSChunks);
1999  auto chunk = GetChunkNoLoad(chunkPos);
2000  if (chunk == nullptr)
2001  {
2002  return 0;
2003  }
2004  return chunk->GrowPlantAt(relPos, a_NumStages);
2005 }
2006 
2007 
2008 
2009 
2010 
2011 void cChunkMap::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
2012 {
2013  int ChunkX, ChunkZ;
2014  cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
2015 
2016  cCSLock Lock(m_CSChunks);
2017  cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
2018  if (Chunk != nullptr)
2019  {
2020  Chunk->SetNextBlockTick(a_BlockX, a_BlockY, a_BlockZ);
2021  }
2022 }
2023 
2024 
2025 
2026 
2027 
2029 {
2030  cCSLock Lock(m_CSChunks);
2031  for (const auto & Chunk : m_Chunks)
2032  {
2033  // We do count every Mobs in the world. But we are assuming that every chunk not loaded by any client
2034  // doesn't affect us. Normally they should not have mobs because every "too far" mobs despawn
2035  // If they have (f.i. when player disconnect) we assume we don't have to make them live or despawn
2036  if (Chunk.second->IsValid() && Chunk.second->HasAnyClients())
2037  {
2038  Chunk.second->CollectMobCensus(a_ToFill);
2039  }
2040  }
2041 }
2042 
2043 
2044 
2045 
2046 
2047 void cChunkMap::SpawnMobs(cMobSpawner & a_MobSpawner)
2048 {
2049  cCSLock Lock(m_CSChunks);
2050  for (const auto & Chunk : m_Chunks)
2051  {
2052  // We only spawn close to players
2053  if (Chunk.second->IsValid() && Chunk.second->HasAnyClients())
2054  {
2055  Chunk.second->SpawnMobs(a_MobSpawner);
2056  }
2057  }
2058 }
2059 
2060 
2061 
2062 
2063 
2064 void cChunkMap::Tick(std::chrono::milliseconds a_Dt)
2065 {
2066  cCSLock Lock(m_CSChunks);
2067  for (const auto & Chunk : m_Chunks)
2068  {
2069  // Only tick chunks that are valid and should be ticked:
2070  if (Chunk.second->IsValid() && Chunk.second->ShouldBeTicked())
2071  {
2072  Chunk.second->Tick(a_Dt);
2073  }
2074  }
2075 }
2076 
2077 
2078 
2079 
2080 
2081 void cChunkMap::TickBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
2082 {
2083  cCSLock Lock(m_CSChunks);
2084  int ChunkX, ChunkZ;
2085  cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
2086  cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
2087  if ((Chunk == nullptr) || !Chunk->IsValid())
2088  {
2089  return;
2090  }
2091  Chunk->TickBlock(a_BlockX, a_BlockY, a_BlockZ);
2092 }
2093 
2094 
2095 
2096 
2097 
2099 {
2100  cCSLock Lock(m_CSChunks);
2101  for (auto itr = m_Chunks.begin(); itr != m_Chunks.end();)
2102  {
2103  if (
2104  (itr->second->CanUnload()) && // Can unload
2105  !cPluginManager::Get()->CallHookChunkUnloading(*GetWorld(), itr->first.ChunkX, itr->first.ChunkZ) // Plugins agree
2106  )
2107  {
2108  itr = m_Chunks.erase(itr);
2109  }
2110  else
2111  {
2112  ++itr;
2113  }
2114  }
2115 }
2116 
2117 
2118 
2119 
2120 
2122 {
2123  cCSLock Lock(m_CSChunks);
2124  for (const auto & Chunk : m_Chunks)
2125  {
2126  if (Chunk.second->IsValid() && Chunk.second->IsDirty())
2127  {
2128  GetWorld()->GetStorage().QueueSaveChunk(Chunk.first.ChunkX, Chunk.first.ChunkZ);
2129  }
2130  }
2131 }
2132 
2133 
2134 
2135 
2136 
2138 {
2139  cCSLock Lock(m_CSChunks);
2140  return m_Chunks.size();
2141 }
2142 
2143 
2144 
2145 
2146 
2148 {
2149  cCSLock Lock(m_CSChunks);
2150  size_t res = 0;
2151  for (const auto & Chunk : m_Chunks)
2152  {
2153  if (Chunk.second->IsValid() && Chunk.second->CanUnloadAfterSaving())
2154  {
2155  res += 1;
2156  }
2157  }
2158  return res;
2159 }
2160 
2161 
2162 
2163 
2164 
2166 {
2167  m_evtChunkValid.Set();
2168 }
2169 
2170 
2171 
2172 
2173 
2175 {
2176  auto chunkCoords = cChunkDef::BlockToChunk(a_AbsPos);
2177  auto relPos = cChunkDef::AbsoluteToRelative(a_AbsPos, chunkCoords);
2178 
2179  cCSLock Lock(m_CSChunks);
2180  cChunkPtr Chunk = GetChunkNoLoad(chunkCoords);
2181  if (Chunk != nullptr)
2182  {
2183  Chunk->QueueTickBlock(relPos);
2184  }
2185 }
2186 
2187 
2188 
2189 
2190 
2191 void cChunkMap::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked)
2192 {
2193  cCSLock Lock(m_CSChunks);
2194  cChunkPtr Chunk = GetChunk(a_ChunkX, a_ChunkZ);
2195  if (Chunk != nullptr)
2196  {
2197  Chunk->SetAlwaysTicked(a_AlwaysTicked);
2198  }
2199 }
2200 
2201 
2202 
2203 
2204 
2205 void cChunkMap::TrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect, const AString & a_WorldName)
2206 {
2207  a_DeadlockDetect.TrackCriticalSection(m_CSChunks, Printf("World %s chunkmap", a_WorldName.c_str()));
2208 }
2209 
2210 
2211 
2212 
2213 
2215 {
2216  a_DeadlockDetect.UntrackCriticalSection(m_CSChunks);
2217 }
2218 
2219 
2220 
2221 
2222 
2224 {
2225  cCSLock Lock(m_CSChunks);
2226 
2227  // Add it to the list:
2228  ASSERT(std::find(m_ChunkStays.begin(), m_ChunkStays.end(), &a_ChunkStay) == m_ChunkStays.end()); // Has not yet been added
2229  m_ChunkStays.push_back(&a_ChunkStay);
2230 
2231  // Schedule all chunks to be loaded / generated, and mark each as locked:
2232  const cChunkCoordsVector & WantedChunks = a_ChunkStay.GetChunks();
2233  for (cChunkCoordsVector::const_iterator itr = WantedChunks.begin(); itr != WantedChunks.end(); ++itr)
2234  {
2235  cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
2236  if (Chunk == nullptr)
2237  {
2238  continue;
2239  }
2240  Chunk->Stay(true);
2241  if (Chunk->IsValid())
2242  {
2243  if (a_ChunkStay.ChunkAvailable(itr->m_ChunkX, itr->m_ChunkZ))
2244  {
2245  // The chunkstay wants to be deactivated, disable it and bail out:
2246  a_ChunkStay.Disable();
2247  return;
2248  }
2249  }
2250  } // for itr - WantedChunks[]
2251 }
2252 
2253 
2254 
2255 
2256 
2259 {
2260  cCSLock Lock(m_CSChunks);
2261 
2262  // Remove from the list of active chunkstays:
2263  bool HasFound = false;
2264  for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
2265  {
2266  if (*itr == &a_ChunkStay)
2267  {
2268  m_ChunkStays.erase(itr);
2269  HasFound = true;
2270  break;
2271  }
2272  } // for itr - m_ChunkStays[]
2273 
2274  if (!HasFound)
2275  {
2276  ASSERT(!"Removing a cChunkStay that hasn't been added!");
2277  return;
2278  }
2279 
2280  // Unmark all contained chunks:
2281  const cChunkCoordsVector & Chunks = a_ChunkStay.GetChunks();
2282  for (cChunkCoordsVector::const_iterator itr = Chunks.begin(), end = Chunks.end(); itr != end; ++itr)
2283  {
2284  cChunkPtr Chunk = GetChunkNoLoad(itr->m_ChunkX, itr->m_ChunkZ);
2285  if (Chunk == nullptr)
2286  {
2287  continue;
2288  }
2289  Chunk->Stay(false);
2290  } // for itr - Chunks[]
2291  a_ChunkStay.OnDisabled();
2292 }
2293 
2294 
2295 
2296 
2297 
void UntrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect)
Removes this chunkmap&#39;s CS from the DeadlockDetect&#39;s tracked CSs.
Definition: ChunkMap.cpp:2214
double GetPosY(void) const
Definition: Entity.h:207
bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback a_Callback)
Calls the callback for each dispenser in the specified chunk.
Definition: ChunkMap.cpp:1403
BLOCKTYPE GetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ) const
Definition: BlockArea.cpp:1736
void MarkChunkDirty(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:236
bool IsValid(void) const
Returns true iff the chunk block data is valid (loaded / generated)
Definition: Chunk.h:72
bool ForEachBlockEntity(cBlockEntityCallback a_Callback)
Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true.
Definition: Chunk.cpp:1958
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback)
Calls the callback for the dropper at the specified coords.
Definition: ChunkMap.cpp:1571
void SpawnMobs(cMobSpawner &a_MobSpawner)
Try to Spawn Monsters inside all Chunks.
Definition: ChunkMap.cpp:2047
void Set(void)
Sets the event - releases one thread that has been waiting in Wait().
Definition: Event.cpp:53
void AddEntity(OwnedEntity a_Entity)
Definition: Chunk.cpp:1796
bool IsLightValid(void) const
Definition: Chunk.h:95
bool GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString &a_Line1, AString &a_Line2, AString &a_Line3, AString &a_Line4)
Retrieves the test on the sign at the specified coords.
Definition: ChunkMap.cpp:1697
BLOCKTYPE GetBlock(Vector3i a_BlockPos)
Definition: ChunkMap.cpp:535
std::list< cChunkStay * > cChunkStays
Definition: ChunkMap.h:455
bool ForEachDispenser(cDispenserCallback a_Callback)
Calls the callback for each dispenser; returns true if all dispensers processed, false if the callbac...
Definition: Chunk.cpp:1989
double GetPosX(void) const
Definition: Entity.h:206
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback)
Calls the callback for the bed at the specified coords; returns false if there&#39;s no bed at those coor...
Definition: Chunk.cpp:2078
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback a_Callback)
Calls the callback for each furnace in the specified chunk.
Definition: ChunkMap.cpp:1448
BLOCKTYPE GetBlock(Vector3i a_BlockPos)
Returns the block type at the specified position.
Definition: World.h:416
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: ChunkMap.cpp:629
T x
Definition: Vector3.h:17
Allocates memory storing unused elements in a linked list.
Makes chunks stay loaded until this object is cleared or destroyed Works by setting internal flags in...
Definition: ChunkStay.h:35
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback)
Calls the callback for the dispenser at the specified coords; returns false if there&#39;s no dropper at ...
Definition: Chunk.cpp:2123
cChunkPtr GetChunkNoGen(cChunkCoords a_Chunk)
Constructs a chunk and queues the chunk for loading if not valid, returning it; doesn&#39;t generate...
Definition: ChunkMap.cpp:116
void WakeUp(Vector3i a_Block, cChunk *a_Chunk)
void QueueChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallbackAfter)
Queues the entire chunk for lighting.
virtual void OnBroken(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta)
Called after a block gets broken (replaced with air), either by player or by natural means...
bool IsLockedByCurrentThread(void)
Returns true if the CS is currently locked by the thread calling this function.
The chunk is not present, but is queued for loading / generation.
Definition: Chunk.h:58
void SetAlwaysTicked(bool a_AlwaysTicked)
Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter.
Definition: Chunk.cpp:1568
cChunkPtr GetChunkNoLoad(cChunkCoords a_Coords)
Constructs a chunk, returning it.
Definition: ChunkMap.cpp:138
std::unique_ptr< T > make_unique(Args &&...args)
Definition: Globals.h:381
bool ShouldMarkDirty(void) const
Returns whether the chunk should be marked as dirty after its data is set.
Definition: SetChunkData.h:78
cChunk * GetParentChunk()
Returns the chunk responsible for ticking this entity.
Definition: Entity.h:540
bool IsTNT(void) const
Definition: Entity.h:178
void GetBlockTypes(BLOCKTYPE *a_BlockTypes)
Copies m_BlockData into a_BlockTypes, only the block types.
Definition: Chunk.cpp:370
void MarkLoadFailed(void)
Marks the chunk as failed to load.
Definition: Chunk.cpp:255
bool ForEachEntity(cEntityCallback a_Callback)
Calls the callback for each entity in the entire world; returns true if all entities processed...
Definition: ChunkMap.cpp:1079
bool ForEachDropSpenser(cDropSpenserCallback a_Callback)
Calls the callback for each dropspenser; returns true if all dropspensers processed, false if the callback aborted by returning true.
Definition: Chunk.cpp:2011
bool GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString &a_Line1, AString &a_Line2, AString &a_Line3, AString &a_Line4)
Retrieves the test on the sign at the specified coords; returns false if there&#39;s no sign at those coo...
Definition: Chunk.cpp:2202
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle &a_Client)
Definition: Chunk.cpp:2416
void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle *a_Client)
Definition: Chunk.cpp:1483
void TrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect, const AString &a_WorldName)
Adds this chunkmap&#39;s CS to the DeadlockDetect&#39;s tracked CSs.
Definition: ChunkMap.cpp:2205
MTRand & GetRandomProvider()
Returns the current thread&#39;s random number source.
Definition: FastRandom.cpp:20
double GetMinX(void) const
Definition: BoundingBox.h:92
bool ChunkAvailable(int a_ChunkX, int a_ChunkZ)
Called by cChunkMap when a chunk is available, checks m_NumLoaded and triggers the appropriate callba...
Definition: ChunkStay.cpp:106
void WriteBlockArea(cBlockArea &a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
Writes the specified cBlockArea at the coords specified.
Definition: Chunk.cpp:379
void QueueTickBlock(Vector3i a_AbsPos)
Queues the specified block for ticking (block update)
Definition: ChunkMap.cpp:2174
void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome)
Sets the biome in the specified relative coords area.
Definition: Chunk.cpp:1610
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback)
Calls the callback for the command block at the specified coords; returns false if there&#39;s no command...
Definition: Chunk.cpp:2169
bool IsQueued(void) const
Returns true iff the chunk is in the queue for loading / generating.
Definition: Chunk.h:75
void SetChunkData(cSetChunkData &a_SetChunkData)
Sets the chunk data as either loaded from the storage or generated.
Definition: ChunkMap.cpp:281
void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
Definition: ChunkMap.cpp:463
void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
Sets the blockticking to start at the specified block.
Definition: ChunkMap.cpp:2011
cChunkMap(cWorld *a_World)
Definition: ChunkMap.cpp:38
static const int Width
Definition: ChunkDef.h:134
bool IsInside(Vector3d a_Point)
Returns true if the point is inside the bounding box.
static bool IsValidHeight(int a_Height)
Validates a height-coordinate.
Definition: ChunkDef.h:212
Definition: Player.h:27
void Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ)
Expands the bounding box by the specified amount in each direction (so the box becomes larger by 2 * ...
Definition: BoundingBox.cpp:90
void AddEntityIfNotPresent(OwnedEntity a_Entity)
Adds the entity to its appropriate chunk, if the entity is not already added.
Definition: ChunkMap.cpp:1023
long int GetTicksAlive(void) const
Gets number of ticks this entity has existed for.
Definition: Entity.h:509
int GetSizeX(void) const
Definition: BlockArea.h:344
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback)
Calls the callback for the brewingstand at the specified coords; returns false if there&#39;s no brewings...
Definition: Chunk.cpp:2089
void SetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: BlockArea.cpp:1799
bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta)
Definition: ChunkMap.cpp:653
bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle *a_Client)
Adds client to a chunk, if not already present; returns true if added, false if present.
Definition: ChunkMap.cpp:962
virtual void Added(cClientHandle *a_Client)=0
Called for clients that are in Chunk2 and not in Chunk1.
UInt32 SpawnFallingBlock(Vector3i a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Spawns an falling block entity at the given position.
Definition: World.cpp:2008
void MarkSaved(void)
Definition: Chunk.cpp:232
void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked)
Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter for the specifie...
Definition: ChunkMap.cpp:2191
void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: Chunk.cpp:1313
void QueueTickBlock(Vector3i a_RelPos)
Queues block for ticking (m_ToTickQueue)
Definition: Chunk.cpp:1365
int GetChunkX(void) const
Definition: SetChunkData.h:49
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:1872
cChunkPtr ConstructChunk(int a_ChunkX, int a_ChunkZ)
Returns or creates and returns a chunk pointer corresponding to the given chunk coordinates.
Definition: ChunkMap.cpp:65
bool ForEachChest(cChestCallback a_Callback)
Calls the callback for each chest; returns true if all chests processed, false if the callback aborte...
Definition: Chunk.cpp:1978
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback)
Calls the callback for each entity in the specified chunk; returns true if all entities processed...
Definition: ChunkMap.cpp:1096
void CollectPickupsByPlayer(cPlayer &a_Player)
Definition: Chunk.cpp:1632
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback)
Calls the callback for the block entity at the specified coords; returns false if there&#39;s no block en...
Definition: Chunk.cpp:2058
double GetMinZ(void) const
Definition: BoundingBox.h:94
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback)
Calls the callback for the furnace at the specified coords; returns false if there&#39;s no furnace at th...
Definition: Chunk.cpp:2146
OwnedEntity RemoveEntity(cEntity &a_Entity)
Releases ownership of the given entity if it was found in this chunk.
Definition: Chunk.cpp:1816
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback)
Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn&#39;...
Definition: ChunkMap.cpp:195
cEvent m_evtChunkValid
Definition: ChunkMap.h:463
EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ)
Returns the biome at the specified coords.
cSimulatorManager * GetSimulatorManager(void)
Definition: World.h:713
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
std::vector< Vector3i > cVector3iArray
Definition: Vector3.h:454
bool DigBlock(Vector3i a_BlockPos)
Removes the block at the specified coords and wakes up simulators.
Definition: ChunkMap.cpp:853
cChunkStays m_ChunkStays
The cChunkStay descendants that are currently enabled in this chunkmap.
Definition: ChunkMap.h:468
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:23
void GetChunkStats(int &a_NumChunksValid, int &a_NumChunksDirty)
Returns the number of valid chunks and the number of dirty chunks.
Definition: ChunkMap.cpp:1975
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
Calls the callback for the noteblock at the specified coords; returns false if there&#39;s no noteblock a...
Definition: Chunk.cpp:2158
void SetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType)
Definition: BlockArea.cpp:1659
bool HasEntity(UInt32 a_EntityID)
Definition: Chunk.cpp:1855
cChunkPtr GetChunk(int a_ChunkX, int a_ChunkZ)
Constructs a chunk and queues it for loading / generating if not valid, returning it...
Definition: ChunkMap.cpp:94
EMCSBiome
Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft.
Definition: BiomeDef.h:21
double GetWidth(void) const
Definition: Entity.h:216
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
Definition: Chunk.h:49
void SpawnItemPickups(const cItems &a_Pickups, Vector3i a_BlockPos, double a_FlyAwaySpeed=1.0, bool a_IsPlayerCreated=false)
Spawns item pickups for each item in the list.
Definition: World.cpp:1936
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4)
Sets the sign text.
Definition: Chunk.cpp:1680
EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const
Definition: Chunk.h:226
void ReplaceBlocks(const sSetBlockVector &a_Blocks, BLOCKTYPE a_FilterBlockType)
Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType.
Definition: ChunkMap.cpp:692
eShrapnelLevel GetTNTShrapnelLevel(void) const
Definition: World.h:891
T y
Definition: Vector3.h:17
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback)
Calls the callback for the chest at the specified coords.
Definition: ChunkMap.cpp:1535
void DelChunkStay(cChunkStay &a_ChunkStay)
Removes the specified cChunkStay descendant from the internal list of ChunkStays. ...
Definition: ChunkMap.cpp:2258
void CollectMobCensus(cMobCensus &a_ToFill)
Make a Mob census, of all mobs, their family, their chunk and their distance to closest player...
Definition: ChunkMap.cpp:2028
void QueueGenerateChunk(cChunkCoords a_Coords, bool a_ForceRegeneration, cChunkCoordCallback *a_Callback=nullptr)
Queues the chunk for generation If a-ForceGenerate is set, the chunk is regenerated even if the data ...
bool IsChunkValid(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:394
bool ForEachEntityInBox(const cBoundingBox &a_Box, cEntityCallback a_Callback)
Calls the callback for each entity that has a nonempty intersection with the specified boundingbox...
Definition: Chunk.cpp:1888
NIBBLETYPE GetBlockMeta(Vector3i a_BlockPos)
Definition: ChunkMap.cpp:554
bool GenerateChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback *a_CallAfter=nullptr)
Queues the chunk for generating.
Definition: ChunkMap.cpp:1748
double GetHeight(void) const
Definition: Entity.h:204
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback)
Calls the callback for the dropspenser at the specified coords.
Definition: ChunkMap.cpp:1589
bool CallHookChunkUnloading(cWorld &a_World, int a_ChunkX, int a_ChunkZ)
T z
Definition: Vector3.h:17
static const int Height
Definition: ChunkDef.h:135
size_t GetNumUnusedDirtyChunks(void)
Returns the number of unused dirty chunks.
Definition: ChunkMap.cpp:2147
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback)
Calls the callback for the mob head block at the specified coords.
Definition: ChunkMap.cpp:1661
void MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::Regener...
Definition: ChunkMap.cpp:1856
void ChunkValidated(void)
Definition: ChunkMap.cpp:2165
void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray &a_BlockAffected)
Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates...
Definition: ChunkMap.cpp:1143
cCriticalSection m_CSChunks
Definition: ChunkMap.h:457
static void BlockToChunk(int a_X, int a_Z, int &a_ChunkX, int &a_ChunkZ)
Converts absolute block coords to chunk coords:
Definition: ChunkDef.h:234
bool ForEachEntity(cEntityCallback a_Callback)
Calls the callback for each entity; returns true if all entities processed, false if the callback abo...
Definition: Chunk.cpp:1871
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback)
Calls the callback for the beacon at the specified coords.
Definition: ChunkMap.cpp:1481
void TrackCriticalSection(cCriticalSection &a_CS, const AString &a_Name)
Adds the critical section for tracking.
bool UseBlockEntity(cPlayer *a_Player, int a_X, int a_Y, int a_Z)
a_Player rclked block entity at the coords specified, handle it returns true if the use was successfu...
Definition: ChunkMap.cpp:177
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback)
Calls the callback for the furnace at the specified coords.
Definition: ChunkMap.cpp:1607
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:405
NIBBLETYPE GetBlockSkyLight(Vector3i a_BlockPos)
Definition: ChunkMap.cpp:573
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
bool IsBlockLiquid(BLOCKTYPE a_BlockType)
Definition: Defines.h:484
void Normalize(void)
Definition: Vector3.h:44
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback)
Calls the callback for each block entity in the specified chunk.
Definition: ChunkMap.cpp:1358
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback)
Calls the callback for the flower pot at the specified coords; returns false if there&#39;s no flower pot...
Definition: Chunk.cpp:2191
void AddEntity(OwnedEntity a_Entity)
Adds the entity to its appropriate chunk, takes ownership of the entity pointer.
Definition: ChunkMap.cpp:1005
virtual void Removed(cClientHandle *a_Client)=0
Called for clients that are in Chunk1 and not in Chunk2,.
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
void MarkDirty(void)
Definition: Chunk.h:366
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback)
Calls the callback for the beacon at the specified coords; returns false if there&#39;s no beacon at thos...
Definition: Chunk.cpp:2067
This class is used to determine which monster can be spawned in which place it is essentially static ...
Definition: MobSpawner.h:15
Interface class used for comparing clients of two chunks.
Definition: ChunkDef.h:500
Definition: World.h:65
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:380
cLightingThread & GetLightingThread(void)
Definition: World.h:954
void AddChunkStay(cChunkStay &a_ChunkStay)
Adds a new cChunkStay descendant to the internal list of ChunkStays; loads its chunks.
Definition: ChunkMap.cpp:2223
size_t GetNumChunks(void)
Definition: ChunkMap.cpp:2137
bool DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback)
Calls the callback for the chunk at the block position specified, with ChunkMapCS locked; returns fal...
Definition: ChunkMap.cpp:210
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE *a_Blocks)
Copies the chunk&#39;s blocktypes into a_Blocks; returns true if successful.
Definition: ChunkMap.cpp:367
double Length(void) const
Definition: Vector3.h:95
void UntrackCriticalSection(cCriticalSection &a_CS)
Removes the CS from the tracking.
void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer &a_Player)
Sends the block at the specified coords to the specified player.
Definition: ChunkMap.cpp:894
~cChunkMap()
Definition: ChunkMap.cpp:52
NIBBLETYPE GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ) const
Definition: BlockArea.cpp:1754
bool CallHookChunkAvailable(cWorld &a_World, int a_ChunkX, int a_ChunkZ)
void AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ)
Definition: Entity.cpp:2136
static void AbsoluteToRelative(int &a_X, int &a_Y, int &a_Z, int &a_ChunkX, int &a_ChunkZ)
Converts absolute block coords into relative (chunk + block) coords:
Definition: ChunkDef.h:163
void PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallAfter={})
Queues the chunk for preparing - making sure that it&#39;s generated and lit.
Definition: ChunkMap.cpp:1725
AString & Printf(AString &str, const char *format, fmt::ArgList args)
Output the formatted text into the string.
Definition: StringUtils.cpp:55
EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ)
Returns the biome at the specified coords.
Definition: ChunkMap.cpp:749
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4)
Sets the sign text.
Definition: ChunkMap.cpp:1839
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback)
Calls the callback for the block entity at the specified coords.
Definition: ChunkMap.cpp:1463
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
Marks the chunk as failed-to-load.
Definition: ChunkMap.cpp:1824
Temporary RAII unlock for a cCSLock.
void QueueSaveChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback *a_Callback=nullptr)
Queues a chunk to be saved, asynchronously.
void UnloadUnusedChunks(void)
Definition: ChunkMap.cpp:2098
cWorld * GetWorld(void)
Definition: ChunkMap.h:387
bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome)
Sets the biome at the area.
Definition: ChunkMap.cpp:789
std::map< ChunkCoordinate, std::unique_ptr< cChunk >, ChunkCoordinate::Comparer > m_Chunks
A map of chunk coordinates to chunk pointers Uses a map (as opposed to unordered_map) because sorted ...
Definition: ChunkMap.h:461
#define ASSERT(x)
Definition: Globals.h:335
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:174
void SetBlocks(const sSetBlockVector &a_Blocks)
Performs the specified single-block set operations simultaneously, as if SetBlock() was called for ea...
Definition: ChunkMap.cpp:480
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback &a_Callback)
Compares clients of two chunks, calls the callback accordingly.
Definition: ChunkMap.cpp:911
void MarkRegenerating(void)
Marks all clients attached to this chunk as wanting this chunk.
Definition: Chunk.cpp:181
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ)
Returns true iff the chunk is in the loader / generator queue.
Definition: ChunkMap.cpp:383
void SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome)
Sets the biome at the specified relative coords.
Definition: Chunk.cpp:1600
virtual void OnDisabled(void)=0
Called by the ChunkMap when the ChunkStay is disabled.
Definition: Cuboid.h:9
bool ForEachFurnace(cFurnaceCallback a_Callback)
Calls the callback for each furnace; returns true if all furnaces processed, false if the callback ab...
Definition: Chunk.cpp:2023
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback)
Calls the callback for the dispenser at the specified coords; returns false if there&#39;s no dropspenser...
Definition: Chunk.cpp:2134
cWorldStorage & GetStorage(void)
Definition: World.h:1043
int m_ChunkZ
Definition: ChunkDef.h:60
bool ForEachLoadedChunk(cFunctionRef< bool(int, int)> a_Callback)
Calls the callback for each loaded chunk.
Definition: ChunkMap.cpp:1917
void SetLight(const cChunkDef::BlockNibbles &a_BlockLight, const cChunkDef::BlockNibbles &a_SkyLight)
Definition: Chunk.cpp:351
bool TryGetHeight(int a_BlockX, int a_BlockZ, int &a_Height)
Definition: ChunkMap.cpp:444
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback a_Callback)
Calls the callback for each dropspenser in the specified chunk.
Definition: ChunkMap.cpp:1433
int GetHeight(int a_X, int a_Z)
Definition: Chunk.cpp:1183
cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockInfo.h:159
static bool FullyOccupiesVoxel(BLOCKTYPE a_Type)
Definition: BlockInfo.h:50
bool ForEachDropper(cDropperCallback a_Callback)
Calls the callback for each dropper; returns true if all droppers processed, false if the callback ab...
Definition: Chunk.cpp:2000
void TakeDamage(cEntity &a_Attacker)
Makes this pawn take damage from an attack by a_Attacker.
Definition: Entity.cpp:269
int GetSizeY(void) const
Definition: BlockArea.h:345
int m_ChunkX
Definition: ChunkDef.h:59
std::string AString
Definition: StringUtils.h:13
void MarkChunkSaved(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:266
void TickBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
Ticks a single block.
Definition: ChunkMap.cpp:2081
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback)
Calls the callback for the mob head block at the specified coords; returns false if there&#39;s no mob he...
Definition: Chunk.cpp:2180
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback)
Calls the callback for the chest at the specified coords; returns false if there&#39;s no chest at those ...
Definition: Chunk.cpp:2100
void ReplaceTreeBlocks(const sSetBlockVector &a_Blocks)
Special function used for growing trees, replaces only blocks that tree may overwrite.
Definition: ChunkMap.cpp:714
std::unique_ptr< cAllocationPool< cChunkData::sChunkSection > > m_Pool
Definition: ChunkMap.h:470
int GetSizeZ(void) const
Definition: BlockArea.h:346
void QueueLoadChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback *a_Callback=nullptr)
Queues a chunk to be loaded, asynchronously.
cItems PickupsFromBlock(Vector3i a_BlockPos, const cEntity *a_Digger, const cItem *a_Tool)
Returns all the pickups that would result if the a_Digger dug up the block at a_BlockPos using a_Tool...
Definition: ChunkMap.cpp:876
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:177
bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
Sets the biome at the specified coords.
Definition: ChunkMap.cpp:770
cChunkGeneratorThread & GetGenerator(void)
Definition: World.h:1042
bool Read(cForEachChunkProvider &a_ForEachChunkProvider, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes=baTypes|baMetas|baBlockEntities)
Reads an area of blocks specified.
Definition: BlockArea.cpp:443
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta, bool a_ShouldMarkDirty, bool a_ShouldInformClients)
Sets the meta for the specified block, while keeping the blocktype.
Definition: ChunkMap.cpp:611
void Tick(std::chrono::milliseconds a_Dt)
Definition: ChunkMap.cpp:2064
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback a_Callback)
Calls the callback for each dropper in the specified chunk.
Definition: ChunkMap.cpp:1418
bool ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback a_Callback)
Calls the callback for brewingstand in the specified chunk.
Definition: ChunkMap.cpp:1373
bool ForEachEntityInBox(const cBoundingBox &a_Box, cEntityCallback a_Callback)
Calls the callback for each entity that has a nonempty intersection with the specified boundingbox...
Definition: ChunkMap.cpp:1111
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
Calls the callback for the noteblock at the specified coords.
Definition: ChunkMap.cpp:1625
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback a_Callback)
Calls the callback for each chest in the specified chunk.
Definition: ChunkMap.cpp:1388
cItems PickupsFromBlock(Vector3i a_AbsPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Returns the pickups that would result if the block at the specified position was mined by a_Digger...
Definition: BlockArea.cpp:2219
bool GetBlockInfo(Vector3i, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_Meta, NIBBLETYPE &a_SkyLight, NIBBLETYPE &a_BlockLight)
Definition: ChunkMap.cpp:672
cWorld * m_World
Definition: ChunkMap.h:465
Interface class used as a callback for operations that involve chunk coords.
Definition: ChunkDef.h:610
void WakeUpArea(const cCuboid &a_Area)
Does the same processing as WakeUp, but for all blocks within the specified area. ...
OwnedEntity RemoveEntity(cEntity &a_Entity)
Removes the entity from its appropriate chunk Returns an owning reference to the found entity...
Definition: ChunkMap.cpp:1061
bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback &a_Callback)
Calls the callback for each chunk in the coords specified (all cords are inclusive).
Definition: ChunkMap.cpp:1888
This class is used to collect information, for each Mob, what is the distance of the closest player i...
Definition: MobCensus.h:25
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback)
Calls the callback for the dispenser at the specified coords; returns false if there&#39;s no dispenser a...
Definition: Chunk.cpp:2112
Definition: Entity.h:73
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
UInt32 SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec=80, double a_InitialVelocityCoeff=1)
Definition: World.h:629
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:307
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle &a_Client)
Sends the block entity, if it is at the coords specified, to a_Client.
Definition: ChunkMap.cpp:160
NIBBLETYPE GetBlockBlockLight(Vector3i a_BlockPos)
Definition: ChunkMap.cpp:592
bool IsPickup(void) const
Definition: Entity.h:172
int GetChunkZ(void) const
Definition: SetChunkData.h:50
int GrowPlantAt(Vector3i a_BlockPos, int a_NumStages=1)
Grows the plant at the specified position by at most a_NumStages.
Definition: ChunkMap.cpp:1994
bool GetChunkData(cChunkCoords a_Coords, cChunkDataCallback &a_Callback)
Calls the callback with the chunk&#39;s data, if available (with ChunkCS locked).
Definition: ChunkMap.cpp:345
unsigned int UInt32
Definition: Globals.h:113
virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess)=0
Called with the chunk&#39;s coords, and an optional operation status flag for operations that support it...
void SaveAllChunks(void)
Definition: ChunkMap.cpp:2121
std::vector< cChunkCoords > cChunkCoordsVector
Definition: ChunkDef.h:567
double GetMaxX(void) const
Definition: BoundingBox.h:96
bool GetBlocks(sSetBlockVector &a_Blocks, bool a_ContinueOnFailure)
Retrieves block types and metas of the specified blocks.
Definition: ChunkMap.cpp:827
void SetPresence(ePresence a_Presence)
Sets the chunk&#39;s presence.
Definition: Chunk.cpp:159
std::unique_ptr< cEntity > OwnedEntity
Definition: ChunkDef.h:32
bool AddClient(cClientHandle *a_Client)
Adds a client to the chunk; returns true if added, false if already there.
Definition: Chunk.cpp:1719
Vector3< int > Vector3i
Definition: Vector3.h:447
void CollectPickupsByPlayer(cPlayer &a_Player)
Makes the specified player collect all the pickups around them.
Definition: ChunkMap.cpp:508
bool UseBlockEntity(cPlayer *a_Player, int a_X, int a_Y, int a_Z)
Use block entity on coordinate.
Definition: Chunk.cpp:1586
const cChunkCoordsVector & GetChunks(void) const
Returns all the chunks that should be kept.
Definition: ChunkStay.h:63
NIBBLETYPE BlockNibbles[NumBlocks/2]
The type used for block data in nibble format, AXIS_ORDER ordering.
Definition: ChunkDef.h:153
void SetNextBlockTick(int a_RelX, int a_RelY, int a_RelZ)
Sets the blockticking to start at the specified block.
Definition: Chunk.h:373
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback)
Calls the callback for the command block at the specified coords.
Definition: ChunkMap.cpp:1643
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback)
Calls the callback for the brewingstand at the specified coords; returns false if there&#39;s no brewings...
Definition: ChunkMap.cpp:1517
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback)
Calls the callback for the dispenser at the specified coords.
Definition: ChunkMap.cpp:1553
double GetPosZ(void) const
Definition: Entity.h:208
bool Write(cForEachChunkProvider &a_ForEachChunkProvider, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
Writes the area back into cWorld at the coords specified.
Definition: BlockArea.cpp:516
cChunk * FindChunk(int a_ChunkX, int a_ChunkZ)
Locates a chunk ptr in the chunkmap; doesn&#39;t create it when not found; assumes m_CSChunks is locked...
Definition: ChunkMap.cpp:148
void TickBlock(int a_RelX, int a_RelY, int a_RelZ)
Ticks a single block.
Definition: Chunk.cpp:719
cChunkClientHandles GetAllClients(void) const
Definition: Chunk.h:562
virtual void OnPlaced(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Called by cWorld::SetBlock() after the block has been set.
void WakeUpSimulators(Vector3i a_Block)
Wakes up simulators for the specified block.
Definition: ChunkMap.cpp:221
Definition: Globals.h:378
bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback a_Callback)
Calls the callback if the entity with the specified ID is found, with the entity object as the callba...
Definition: ChunkMap.cpp:1340
bool HasAnyClients(void) const
Returns true if theres any client in the chunk; false otherwise.
Definition: Chunk.cpp:1787
bool HasEntity(UInt32 a_EntityID)
Returns true if the entity with specified ID is present in the chunks.
Definition: ChunkMap.cpp:1044
virtual float GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower)
a lightweight calculation approach to get explosion exposure rate
Definition: Entity.cpp:2259
bool IsFallingBlock(void) const
Definition: Entity.h:175
std::enable_if< std::is_arithmetic< T >::value, C >::type FloorC(T a_Value)
Floors a value, then casts it to C (an int by default)
Definition: Globals.h:362
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:251
void GetAllData(cChunkDataCallback &a_Callback)
Gets all chunk data, calls the a_Callback&#39;s methods for each data type.
Definition: Chunk.cpp:274
bool ForEachBrewingstand(cBrewingstandCallback a_Callback)
Calls the callback for each brewingstand; returns true if all brewingstands processed, false if the callback aborted by returning true.
Definition: Chunk.cpp:1967
double GetMaxZ(void) const
Definition: BoundingBox.h:98
virtual float GetEnchantmentBlastKnockbackReduction()
Returns explosion knock back reduction percent from blast protection level.
Definition: Entity.cpp:686
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback)
Calls the callback for the flower pot at the specified coords.
Definition: ChunkMap.cpp:1679
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle *a_Client)
Removes the client from the chunk.
Definition: ChunkMap.cpp:977
Definition: Item.h:36
int GetHeight(int a_BlockX, int a_BlockZ)
Definition: ChunkMap.cpp:416
#define CASE_TREE_OVERWRITTEN_BLOCKS
Definition: Trees.h:38
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback)
Calls the callback for the bed at the specified coords.
Definition: ChunkMap.cpp:1499
void RemoveClientFromChunks(cClientHandle *a_Client)
Removes the client from all chunks it is present in.
Definition: ChunkMap.cpp:992
static bool IsBlockEntityBlockType(BLOCKTYPE a_BlockType)
Returns true if the specified blocktype is supposed to have an associated block entity.
Definition: BlockEntity.cpp:39
std::vector< sSetBlock > sSetBlockVector
Definition: ChunkDef.h:564
bool WriteBlockArea(cBlockArea &a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
Writes the block area into the specified coords.
Definition: ChunkMap.cpp:1937
void TouchChunk(int a_ChunkX, int a_ChunkZ)
Touches the chunk, causing it to be loaded or generated.
Definition: ChunkMap.cpp:1715
cClientHandle * GetClientHandle(void) const
Returns the raw client handle associated with the player.
Definition: Player.h:254
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:234
void MarkSaving(void)
Definition: Chunk.cpp:223
void Stay(bool a_Stay=true)
Sets or resets the internal flag that prevents chunk from being unloaded.
Definition: Chunk.cpp:488
void SetAllData(cSetChunkData &a_SetChunkData)
Sets all chunk data as either loaded from the storage or generated.
Definition: Chunk.cpp:300
std::enable_if< std::is_arithmetic< T >::value, C >::type CeilC(T a_Value)
Ceils a value, then casts it to C (an int by default)
Definition: Globals.h:369
void RemoveClient(cClientHandle *a_Client)
Removes the specified client from the chunk; ignored if client not in chunk.
Definition: Chunk.cpp:1748
void ChunkLighted(int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles &a_BlockLight, const cChunkDef::BlockNibbles &a_SkyLight)
Definition: ChunkMap.cpp:325