Cuberite
A lightweight, fast and extensible game server for Minecraft
World.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 "World.h"
5 #include "BlockInfo.h"
6 #include "ClientHandle.h"
7 #include "Physics/Explodinator.h"
8 #include "Server.h"
9 #include "Root.h"
10 #include "IniFile.h"
11 #include "Generating/ChunkDesc.h"
13 #include "SetChunkData.h"
14 #include "DeadlockDetect.h"
15 #include "LineBlockTracer.h"
16 #include "UUID.h"
18 
19 // Serializers
21 
22 // Entities (except mobs):
23 #include "Entities/EnderCrystal.h"
24 #include "Entities/ExpOrb.h"
25 #include "Entities/FallingBlock.h"
26 #include "Entities/Minecart.h"
27 #include "Entities/Pickup.h"
28 #include "Entities/Player.h"
29 #include "Entities/TNTEntity.h"
30 
33 
34 // Simulators:
44 
45 // Mobs:
47 #include "MobCensus.h"
48 #include "MobSpawner.h"
49 
50 #include "Generating/Trees.h"
51 #include "Bindings/PluginManager.h"
52 #include "Blocks/BlockHandler.h"
53 
54 #ifndef _WIN32
55  #include <stdlib.h>
56 #endif
57 
58 #include "SpawnPrepare.h"
59 #include "FastRandom.h"
60 #include "OpaqueWorld.h"
61 
62 
63 
64 
65 
66 namespace World
67 {
68  // Implement conversion functions from OpaqueWorld.h
69  cBroadcastInterface * GetBroadcastInterface(cWorld * a_World) { return a_World; }
70  cForEachChunkProvider * GetFECProvider (cWorld * a_World) { return a_World; }
71  cWorldInterface * GetWorldInterface (cWorld * a_World) { return a_World; }
72 
74  {
75  return { a_World.GetChunkMap() };
76  }
77 }
78 
79 
80 
81 
82 
84 // cWorld::cLock:
85 
86 cWorld::cLock::cLock(const cWorld & a_World) :
87  Super(&(a_World.m_ChunkMap.GetCS()))
88 {
89 }
90 
91 
92 
93 
94 
96 // cWorld::cTickThread:
97 
99  Super(Printf("World Ticker (%s)", a_World.GetName().c_str())),
100  m_World(a_World)
101 {
102 }
103 
104 
105 
106 
107 
109 {
110  auto LastTime = std::chrono::steady_clock::now();
111  auto TickTime = std::chrono::duration_cast<std::chrono::milliseconds>(1_tick);
112 
113  while (!m_ShouldTerminate)
114  {
115  auto NowTime = std::chrono::steady_clock::now();
116  auto WaitTime = std::chrono::duration_cast<std::chrono::milliseconds>(NowTime - LastTime);
117  m_World.Tick(WaitTime, TickTime);
118  TickTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - NowTime);
119 
120  if (TickTime < 1_tick)
121  {
122  // Stretch tick time until it's at least 1 tick:
123  std::this_thread::sleep_for(1_tick - TickTime);
124  }
125 
126  LastTime = NowTime;
127  }
128 }
129 
130 
131 
132 
133 
135 // cWorld:
136 
138  const AString & a_WorldName, const AString & a_DataPath,
139  cDeadlockDetect & a_DeadlockDetect, const AStringVector & a_WorldNames,
140  eDimension a_Dimension, const AString & a_LinkedOverworldName
141 ):
142  m_WorldName(a_WorldName),
143  m_DataPath(a_DataPath),
144  m_LinkedOverworldName(a_LinkedOverworldName),
145  m_IniFileName(m_DataPath + "/world.ini"),
146  m_StorageSchema("Default"),
147 #ifdef __arm__
149 #else
151 #endif
152  m_IsSavingEnabled(true),
153  m_Dimension(a_Dimension),
154  m_IsSpawnExplicitlySet(false),
155  m_SpawnX(0),
156  m_SpawnY(cChunkDef::Height),
157  m_SpawnZ(0),
161  m_WorldAge(0),
162  m_WorldDate(0),
163  m_WorldTickAge(0),
164  m_LastChunkCheck(0),
165  m_LastSave(0),
166  m_SkyDarkness(0),
168  m_bEnabledPVP(false),
170  m_IsDeepSnowEnabled(false),
171  m_ShouldLavaSpawnFire(true),
174  m_SandSimulator(),
175  m_WaterSimulator(nullptr),
176  m_LavaSimulator(nullptr),
177  m_FireSimulator(),
178  m_RedstoneSimulator(nullptr),
179  m_MaxPlayers(10),
180  m_ChunkMap(this),
181  m_bAnimals(true),
183  m_WeatherInterval(24000), // Guaranteed 1 game-day of sunshine at server start :)
184  m_MaxSunnyTicks(180000), // 150 real-world minutes -+
185  m_MinSunnyTicks(12000), // 10 real-world minutes |
186  m_MaxRainTicks(24000), // 20 real-world minutes +- all values adapted from Vanilla 1.7.2
187  m_MinRainTicks(12000), // 10 real-world minutes |
188  m_MaxThunderStormTicks(15600), // 13 real-world minutes |
189  m_MinThunderStormTicks(3600), // 3 real-world minutes -+
192  /* TODO: Enable when functionality exists again
193  m_IsBeetrootsBonemealable(true),
194  m_IsCactusBonemealable(false),
195  m_IsCarrotsBonemealable(true),
196  m_IsCropsBonemealable(true),
197  m_IsGrassBonemealable(true),
198  m_IsMelonStemBonemealable(true),
199  m_IsMelonBonemealable(true),
200  m_IsPotatoesBonemealable(true),
201  m_IsPumpkinStemBonemealable(true),
202  m_IsPumpkinBonemealable(true),
203  m_IsSaplingBonemealable(true),
204  m_IsSugarcaneBonemealable(false),
205  m_IsBigFlowerBonemealable(true),
206  m_IsTallGrassBonemealable(true),
207  */
209  m_bUseChatPrefixes(false),
211  m_MaxViewDistance(12),
212  m_Scoreboard(this),
213  m_MapManager(this),
214  m_GeneratorCallbacks(*this),
215  m_ChunkSender(*this),
216  m_Lighting(*this),
217  m_TickThread(*this)
218 {
219  LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str());
220 
222 
223  m_ChunkMap.TrackInDeadlockDetect(a_DeadlockDetect, m_WorldName);
224 
225  // Load the scoreboard
227  Serializer.Load();
228 
229  // Track the CSs used by this world in the deadlock detector:
230  a_DeadlockDetect.TrackCriticalSection(m_CSTasks, Printf("World %s tasks", m_WorldName.c_str()));
231 
232  // Load world settings from the ini file
233  cIniFile IniFile;
234  if (!IniFile.ReadFile(m_IniFileName))
235  {
236  LOGWARNING("Cannot read world settings from \"%s\", defaults will be used.", m_IniFileName.c_str());
237 
238  // TODO: More descriptions for each key
239  IniFile.AddHeaderComment(" This is the per-world configuration file, managing settings such as generators, simulators, and spawn points");
240  IniFile.AddKeyComment(" LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation");
241  }
242 
243  // The presence of a configuration value overrides everything
244  // If no configuration value is found, GetDimension() is written to file and the variable is written to again to ensure that cosmic rays haven't sneakily changed its value
245  m_Dimension = StringToDimension(IniFile.GetValueSet("General", "Dimension", DimensionToString(GetDimension())));
246  int UnusedDirtyChunksCap = IniFile.GetValueSetI("General", "UnusedChunkCap", 1000);
247  if (UnusedDirtyChunksCap < 0)
248  {
249  UnusedDirtyChunksCap *= -1;
250  IniFile.SetValueI("General", "UnusedChunkCap", UnusedDirtyChunksCap);
251  }
252  m_UnusedDirtyChunksCap = static_cast<size_t>(UnusedDirtyChunksCap);
253 
254  m_BroadcastDeathMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastDeathMessages", true);
255  m_BroadcastAchievementMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastAchievementMessages", true);
256 
257  SetMaxViewDistance(IniFile.GetValueSetI("SpawnPosition", "MaxViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE));
258 
259  // Try to find the "SpawnPosition" key and coord values in the world configuration, set the flag if found
260  int KeyNum = IniFile.FindKey("SpawnPosition");
262  (
263  (KeyNum >= 0) &&
264  (
265  (IniFile.FindValue(KeyNum, "X") >= 0) &&
266  (IniFile.FindValue(KeyNum, "Y") >= 0) &&
267  (IniFile.FindValue(KeyNum, "Z") >= 0)
268  )
269  );
270 
272  {
273  LOGD("Spawnpoint explicitly set!");
274  m_SpawnX = IniFile.GetValueI("SpawnPosition", "X", m_SpawnX);
275  m_SpawnY = IniFile.GetValueI("SpawnPosition", "Y", m_SpawnY);
276  m_SpawnZ = IniFile.GetValueI("SpawnPosition", "Z", m_SpawnZ);
277  }
278 
279  m_StorageSchema = IniFile.GetValueSet ("Storage", "Schema", m_StorageSchema);
280  m_StorageCompressionFactor = IniFile.GetValueSetI("Storage", "CompressionFactor", m_StorageCompressionFactor);
281  m_MaxCactusHeight = IniFile.GetValueSetI("Plants", "MaxCactusHeight", 3);
282  m_MaxSugarcaneHeight = IniFile.GetValueSetI("Plants", "MaxSugarcaneHeight", 3);
283  /* TODO: Enable when functionality exists again
284  m_IsBeetrootsBonemealable = IniFile.GetValueSetB("Plants", "IsBeetrootsBonemealable", true);
285  m_IsCactusBonemealable = IniFile.GetValueSetB("Plants", "IsCactusBonemealable", false);
286  m_IsCarrotsBonemealable = IniFile.GetValueSetB("Plants", "IsCarrotsBonemealable", true);
287  m_IsCropsBonemealable = IniFile.GetValueSetB("Plants", "IsCropsBonemealable", true);
288  m_IsGrassBonemealable = IniFile.GetValueSetB("Plants", "IsGrassBonemealable", true);
289  m_IsMelonStemBonemealable = IniFile.GetValueSetB("Plants", "IsMelonStemBonemealable", true);
290  m_IsMelonBonemealable = IniFile.GetValueSetB("Plants", "IsMelonBonemealable", false);
291  m_IsPotatoesBonemealable = IniFile.GetValueSetB("Plants", "IsPotatoesBonemealable", true);
292  m_IsPumpkinStemBonemealable = IniFile.GetValueSetB("Plants", "IsPumpkinStemBonemealable", true);
293  m_IsPumpkinBonemealable = IniFile.GetValueSetB("Plants", "IsPumpkinBonemealable", false);
294  m_IsSaplingBonemealable = IniFile.GetValueSetB("Plants", "IsSaplingBonemealable", true);
295  m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false);
296  m_IsBigFlowerBonemealable = IniFile.GetValueSetB("Plants", "IsBigFlowerBonemealable", true);
297  m_IsTallGrassBonemealable = IniFile.GetValueSetB("Plants", "IsTallGrassBonemealable", true);
298  */
299  m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", true);
300  m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true);
301  int TNTShrapnelLevel = IniFile.GetValueSetI("Physics", "TNTShrapnelLevel", static_cast<int>(slAll));
302  m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false);
303  m_bEnabledPVP = IniFile.GetValueSetB("Mechanics", "PVPEnabled", true);
304  m_bFarmlandTramplingEnabled = IniFile.GetValueSetB("Mechanics", "FarmlandTramplingEnabled", true);
305  m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true);
306  m_MinNetherPortalWidth = IniFile.GetValueSetI("Mechanics", "MinNetherPortalWidth", 2);
307  m_MaxNetherPortalWidth = IniFile.GetValueSetI("Mechanics", "MaxNetherPortalWidth", 21);
308  m_MinNetherPortalHeight = IniFile.GetValueSetI("Mechanics", "MinNetherPortalHeight", 3);
309  m_MaxNetherPortalHeight = IniFile.GetValueSetI("Mechanics", "MaxNetherPortalHeight", 21);
310  m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true);
311  m_IsDaylightCycleEnabled = IniFile.GetValueSetB("General", "IsDaylightCycleEnabled", true);
312  int GameMode = IniFile.GetValueSetI("General", "Gamemode", static_cast<int>(m_GameMode));
313  int Weather = IniFile.GetValueSetI("General", "Weather", static_cast<int>(m_Weather));
314 
315  m_WorldAge = std::chrono::milliseconds(IniFile.GetValueSetI("General", "WorldAgeMS", 0LL));
316 
317  // Load the weather frequency data:
318  if (m_Dimension == dimOverworld)
319  {
320  m_MaxSunnyTicks = IniFile.GetValueSetI("Weather", "MaxSunnyTicks", m_MaxSunnyTicks);
321  m_MinSunnyTicks = IniFile.GetValueSetI("Weather", "MinSunnyTicks", m_MinSunnyTicks);
322  m_MaxRainTicks = IniFile.GetValueSetI("Weather", "MaxRainTicks", m_MaxRainTicks);
323  m_MinRainTicks = IniFile.GetValueSetI("Weather", "MinRainTicks", m_MinRainTicks);
324  m_MaxThunderStormTicks = IniFile.GetValueSetI("Weather", "MaxThunderStormTicks", m_MaxThunderStormTicks);
325  m_MinThunderStormTicks = IniFile.GetValueSetI("Weather", "MinThunderStormTicks", m_MinThunderStormTicks);
327  {
328  std::swap(m_MaxSunnyTicks, m_MinSunnyTicks);
329  }
331  {
332  std::swap(m_MaxRainTicks, m_MinRainTicks);
333  }
335  {
337  }
338  }
339 
340  auto WorldExists = [&](const AString & a_CheckWorldName)
341  {
342  return (std::find(a_WorldNames.begin(), a_WorldNames.end(), a_CheckWorldName) != a_WorldNames.end());
343  };
344 
345  if (a_Dimension == dimOverworld)
346  {
347  AString MyNetherName = GetName() + "_nether";
348  AString MyEndName = GetName() + "_the_end";
349  if (!WorldExists(MyNetherName))
350  {
351  MyNetherName.clear();
352  }
353  if (!WorldExists(MyEndName))
354  {
355  MyEndName = GetName() + "_end";
356  if (!WorldExists(MyEndName))
357  {
358  MyEndName.clear();
359  }
360  }
361 
362  m_LinkedNetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", MyNetherName);
363  m_LinkedEndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", MyEndName);
364  }
365  else
366  {
367  m_LinkedOverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName());
368  }
369 
370  // If we are linked to one or more worlds that do not exist, unlink them
371  if (a_Dimension == dimOverworld)
372  {
373  if (!m_LinkedNetherWorldName.empty() && !WorldExists(m_LinkedNetherWorldName))
374  {
375  IniFile.SetValue("LinkedWorlds", "NetherWorldName", "");
376  LOG("%s Is linked to a nonexisting nether world called \"%s\". The server has modified \"%s/world.ini\" and removed this invalid link.",
377  GetName().c_str(), m_LinkedNetherWorldName.c_str(), GetName().c_str());
378  m_LinkedNetherWorldName.clear();
379  }
380  if (!m_LinkedEndWorldName.empty() && !WorldExists(m_LinkedEndWorldName))
381  {
382  IniFile.SetValue("LinkedWorlds", "EndWorldName", "");
383  LOG("%s Is linked to a nonexisting end world called \"%s\". The server has modified \"%s/world.ini\" and removed this invalid link.",
384  GetName().c_str(), m_LinkedEndWorldName.c_str(), GetName().c_str());
385  m_LinkedEndWorldName.clear();
386  }
387  }
388  else
389  {
390  if (!m_LinkedOverworldName.empty() && !WorldExists(m_LinkedOverworldName))
391  {
392  IniFile.SetValue("LinkedWorlds", "OverworldName", "");
393  LOG("%s Is linked to a nonexisting overworld called \"%s\". The server has modified \"%s/world.ini\" and removed this invalid link.",
394  GetName().c_str(), m_LinkedOverworldName.c_str(), GetName().c_str());
395  m_LinkedOverworldName.clear();
396  }
397  }
398 
399 
400 
401  // Adjust the enum-backed variables into their respective bounds:
402  m_GameMode = static_cast<eGameMode> (Clamp<int>(GameMode, gmSurvival, gmSpectator));
403  m_TNTShrapnelLevel = static_cast<eShrapnelLevel>(Clamp<int>(TNTShrapnelLevel, slNone, slAll));
404  m_Weather = static_cast<eWeather> (Clamp<int>(Weather, wSunny, wStorm));
405 
407 
409  m_WorldDate = cTickTime(IniFile.GetValueSetI("General", "TimeInTicks", GetWorldDate().count()));
410 
411  // preallocate some memory for ticking blocks so we don't need to allocate that often
412  m_BlockTickQueue.reserve(1000);
413  m_BlockTickQueueCopy.reserve(1000);
414 
415  // Simulators:
416  m_SimulatorManager = std::make_unique<cSimulatorManager>(*this);
419  m_SandSimulator = std::make_unique<cSandSimulator>(*this, IniFile);
420  m_FireSimulator = std::make_unique<cFireSimulator>(*this, IniFile);
422 
423  // Water, Lava and Redstone simulators get registered in their initialize function.
424  m_SimulatorManager->RegisterSimulator(m_SandSimulator.get(), 1);
425  m_SimulatorManager->RegisterSimulator(m_FireSimulator.get(), 1);
426 
429 
431 
432  // Save any changes that the defaults may have done to the ini file:
433  if (!IniFile.WriteFile(m_IniFileName))
434  {
435  LOGWARNING("Could not write world config to %s", m_IniFileName.c_str());
436  }
437 
438  // Init of the spawn monster time (as they are supposed to have different spawn rate)
439  m_LastSpawnMonster.emplace(cMonster::mfHostile, 0_tick);
440  m_LastSpawnMonster.emplace(cMonster::mfPassive, 0_tick);
441  m_LastSpawnMonster.emplace(cMonster::mfAmbient, 0_tick);
442  m_LastSpawnMonster.emplace(cMonster::mfWater, 0_tick);
443 }
444 
445 
446 
447 
448 
450 {
451  delete m_WaterSimulator; m_WaterSimulator = nullptr;
452  delete m_LavaSimulator; m_LavaSimulator = nullptr;
453  delete m_RedstoneSimulator; m_RedstoneSimulator = nullptr;
454 }
455 
456 
457 
458 
459 
460 void cWorld::CastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
461 {
462  LOG("CastThunderbolt(int, int, int) is deprecated, use CastThunderbolt(Vector3i) instead");
463  CastThunderbolt({a_BlockX, a_BlockY, a_BlockZ});
464 }
465 
466 
467 
468 
469 
471 {
472  BroadcastThunderbolt(a_Block);
473  BroadcastSoundEffect("entity.lightning.thunder", a_Block, 50, 1);
474 }
475 
476 
477 
478 
479 
481 {
482  using namespace std::chrono_literals;
483 
484  return std::chrono::duration_cast<cTickTime>(m_WorldDate % 20min);
485 }
486 
487 
488 
489 
490 
492 {
493  return std::chrono::duration_cast<cTickTimeLong>(m_WorldAge);
494 }
495 
496 
497 
498 
499 
501 {
502  return std::chrono::duration_cast<cTickTimeLong>(m_WorldDate);
503 }
504 
505 
506 
507 
508 
510 {
511  return m_WorldTickAge;
512 }
513 
514 
515 
516 
517 
518 void cWorld::SetTimeOfDay(const cTickTime a_TimeOfDay)
519 {
520  using namespace std::chrono_literals;
521 
522  m_WorldDate = (m_WorldDate / 20min) * 20min + a_TimeOfDay;
525 }
526 
527 
528 
529 
530 
532 {
533  auto & Random = GetRandomProvider();
534  switch (a_Weather)
535  {
536  case eWeather_Sunny:
537  {
538  return Random.RandInt(m_MinSunnyTicks, m_MaxSunnyTicks);
539  }
540  case eWeather_Rain:
541  {
542  return Random.RandInt(m_MinRainTicks, m_MaxRainTicks);
543  }
545  {
546  return Random.RandInt(m_MinThunderStormTicks, m_MaxThunderStormTicks);
547  }
548  }
549  UNREACHABLE("Unsupported weather");
550 }
551 
552 
553 
554 
555 
556 void cWorld::SetWeather(eWeather a_NewWeather)
557 {
558  // Do the plugins agree? Do they want a different weather?
559  if (cRoot::Get()->GetPluginManager()->CallHookWeatherChanging(*this, a_NewWeather))
560  {
562  return;
563  }
564 
565  // Set new period for the selected weather:
567 
568  // The weather can't be found:
569  if (m_WeatherInterval < 0)
570  {
571  return;
572  }
573 
574  m_Weather = a_NewWeather;
576 
577  // Let the plugins know about the change:
579 }
580 
581 
582 
583 
584 
586 {
587  // In the next tick the weather will be changed
588  m_WeatherInterval = 0;
589 }
590 
591 
592 
593 
594 
595 bool cWorld::IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const
596 {
597  return m_ChunkMap.IsWeatherSunnyAt(a_BlockX, a_BlockZ);
598 }
599 
600 
601 
602 
603 
604 bool cWorld::IsWeatherWetAt(int a_BlockX, int a_BlockZ)
605 {
606  return m_ChunkMap.IsWeatherWetAt(a_BlockX, a_BlockZ);
607 }
608 
609 
610 
611 
612 
613 bool cWorld::IsWeatherWetAtXYZ(const Vector3i a_Position)
614 {
615  return m_ChunkMap.IsWeatherWetAt(a_Position);
616 }
617 
618 
619 
620 
621 
622 void cWorld::SetNextBlockToTick(const Vector3i a_BlockPos)
623 {
624  return m_ChunkMap.SetNextBlockToTick(a_BlockPos);
625 }
626 
627 
628 
629 
630 
631 bool cWorld::SetSpawn(int a_X, int a_Y, int a_Z)
632 {
633  cIniFile IniFile;
634 
635  IniFile.ReadFile(m_IniFileName);
636  IniFile.SetValueI("SpawnPosition", "X", a_X);
637  IniFile.SetValueI("SpawnPosition", "Y", a_Y);
638  IniFile.SetValueI("SpawnPosition", "Z", a_Z);
639  if (IniFile.WriteFile(m_IniFileName))
640  {
641  m_SpawnX = a_X;
642  m_SpawnY = a_Y;
643  m_SpawnZ = a_Z;
644  FLOGD("Spawn set at {}", Vector3i{m_SpawnX, m_SpawnY, m_SpawnZ});
645  return true;
646  }
647  else
648  {
649  LOGWARNING("Couldn't write new spawn settings to \"%s\".", m_IniFileName.c_str());
650  }
651  return false;
652 }
653 
654 
655 
656 
657 
659 {
660  // For the debugging builds, don't make the server build too much world upon start:
661  #if !defined(NDEBUG) || defined(ANDROID)
662  const int DefaultViewDist = 9;
663  #else
664  const int DefaultViewDist = 20; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is
665  #endif // !NDEBUG
666 
668  {
669  // Spawn position wasn't already explicitly set, enumerate random solid-land coordinate and then write it to the world configuration:
670  GenerateRandomSpawn(DefaultViewDist);
671  }
672 
673  cIniFile IniFile;
674  IniFile.ReadFile(m_IniFileName);
675  int ViewDist = IniFile.GetValueSetI("SpawnPosition", "PregenerateDistance", DefaultViewDist);
676  IniFile.WriteFile(m_IniFileName);
677 
678  int ChunkX = 0, ChunkZ = 0;
679  cChunkDef::BlockToChunk(m_SpawnX, m_SpawnZ, ChunkX, ChunkZ);
680  cSpawnPrepare::PrepareChunks(*this, ChunkX, ChunkZ, ViewDist);
681 }
682 
683 
684 
685 
686 
688 {
689  m_Lighting.Start();
690  m_Storage.Start();
691  m_Generator.Start();
694 }
695 
696 
697 
698 
699 
700 void cWorld::GenerateRandomSpawn(int a_MaxSpawnRadius)
701 {
702  LOGD("Generating random spawnpoint...");
703 
704  // Number of checks to make sure we have a valid biome
705  // 100 checks will check across 400 chunks, we should have
706  // a valid biome by then.
707  static const int BiomeCheckCount = 100;
708 
709  // Make sure we are in a valid biome
710  Vector3i BiomeOffset = Vector3i(0, 0, 0);
711  for (int BiomeCheckIndex = 0; BiomeCheckIndex < BiomeCheckCount; ++BiomeCheckIndex)
712  {
713  EMCSBiome Biome = GetBiomeAt(BiomeOffset.x, BiomeOffset.z);
714  if ((Biome == EMCSBiome::biOcean) || (Biome == EMCSBiome::biFrozenOcean))
715  {
716  BiomeOffset += Vector3d(cChunkDef::Width * 4, 0, 0);
717  continue;
718  }
719 
720  // Found a usable biome
721  // Spawn chunks so we can find a nice spawn.
722  int ChunkX = 0, ChunkZ = 0;
723  cChunkDef::BlockToChunk(BiomeOffset.x, BiomeOffset.z, ChunkX, ChunkZ);
724  cSpawnPrepare::PrepareChunks(*this, ChunkX, ChunkZ, a_MaxSpawnRadius);
725  break;
726  }
727 
728  // Check 0, 0 first.
729  int SpawnY = 0;
730  if (CanSpawnAt(BiomeOffset.x, SpawnY, BiomeOffset.z))
731  {
732  SetSpawn(BiomeOffset.x, SpawnY, BiomeOffset.z);
733 
734  FLOGINFO("World \"{}\": Generated spawnpoint position at {}", m_WorldName, Vector3i{m_SpawnX, m_SpawnY, m_SpawnZ});
735  return;
736  }
737 
738  // A search grid (searches clockwise around the origin)
739  static const int HalfChunk = cChunkDef::Width / 2;
740  static const Vector3i ChunkOffset[] =
741  {
742  Vector3i(0, 0, HalfChunk),
743  Vector3i(HalfChunk, 0, HalfChunk),
744  Vector3i(HalfChunk, 0, 0),
745  Vector3i(HalfChunk, 0, -HalfChunk),
746  Vector3i(0, 0, -HalfChunk),
747  Vector3i(-HalfChunk, 0, -HalfChunk),
748  Vector3i(-HalfChunk, 0, 0),
749  Vector3i(-HalfChunk, 0, HalfChunk),
750  };
751 
752  static const int PerRadiSearchCount = ARRAYCOUNT(ChunkOffset);
753 
754  for (int RadiusOffset = 1; RadiusOffset < (a_MaxSpawnRadius * 2); ++RadiusOffset)
755  {
756  for (int SearchGridIndex = 0; SearchGridIndex < PerRadiSearchCount; ++SearchGridIndex)
757  {
758  const Vector3i PotentialSpawn = BiomeOffset + (ChunkOffset[SearchGridIndex] * RadiusOffset);
759 
760  if (CanSpawnAt(PotentialSpawn.x, SpawnY, PotentialSpawn.z))
761  {
762  SetSpawn(PotentialSpawn.x, SpawnY, PotentialSpawn.z);
763 
764  int ChunkX, ChunkZ;
765  cChunkDef::BlockToChunk(m_SpawnX, m_SpawnZ, ChunkX, ChunkZ);
766  cSpawnPrepare::PrepareChunks(*this, ChunkX, ChunkZ, a_MaxSpawnRadius);
767 
768  FLOGINFO("World \"{}\":Generated spawnpoint position at {}", m_WorldName, Vector3i{m_SpawnX, m_SpawnY, m_SpawnZ});
769  return;
770  }
771  }
772  }
773 
775  FLOGWARNING("World \"{}\": Did not find an acceptable spawnpoint. Generated a random spawnpoint position at {}", m_WorldName, Vector3i{m_SpawnX, m_SpawnY, m_SpawnZ});
776 }
777 
778 
779 
780 
781 
782 bool cWorld::CanSpawnAt(int a_X, int & a_Y, int a_Z)
783 {
784  // All this blocks can only be found above ground.
785  // Apart from netherrack (as the Nether is technically a massive cave)
786  static const BLOCKTYPE ValidSpawnBlocks[] =
787  {
789  E_BLOCK_SAND,
790  E_BLOCK_SNOW,
793  };
794 
795  static const int ValidSpawnBlocksCount = ARRAYCOUNT(ValidSpawnBlocks);
796 
797  // Increase this by two, because we need two more blocks for body and head
798  static const int HighestSpawnPoint = GetHeight(a_X, a_Z) + 2;
799  static const int LowestSpawnPoint = HighestSpawnPoint / 2;
800 
801  for (int PotentialY = HighestSpawnPoint; PotentialY > LowestSpawnPoint; --PotentialY)
802  {
803  BLOCKTYPE HeadBlock = GetBlock({ a_X, PotentialY, a_Z });
804 
805  // Is this block safe for spawning
806  if (HeadBlock != E_BLOCK_AIR)
807  {
808  continue;
809  }
810 
811  BLOCKTYPE BodyBlock = GetBlock({ a_X, PotentialY - 1, a_Z });
812 
813  // Is this block safe for spawning
814  if (BodyBlock != E_BLOCK_AIR)
815  {
816  continue;
817  }
818 
819  BLOCKTYPE FloorBlock = GetBlock({ a_X, PotentialY - 2, a_Z });
820 
821  // Early out - Is the floor block air
822  if (FloorBlock == E_BLOCK_AIR)
823  {
824  continue;
825  }
826 
827  // Is the floor block ok
828  bool ValidSpawnBlock = false;
829  for (int BlockIndex = 0; BlockIndex < ValidSpawnBlocksCount; ++BlockIndex)
830  {
831  ValidSpawnBlock |= (ValidSpawnBlocks[BlockIndex] == FloorBlock);
832  }
833 
834  if (!ValidSpawnBlock)
835  {
836  continue;
837  }
838 
839  if (!CheckPlayerSpawnPoint(a_X, PotentialY - 1, a_Z))
840  {
841  continue;
842  }
843 
844  a_Y = PotentialY - 1;
845  return true;
846  }
847 
848  return false;
849 }
850 
851 
852 
853 
854 
856 {
857  // Check height bounds
858  if (!cChunkDef::IsValidHeight(a_Pos))
859  {
860  return false;
861  }
862 
863  // Check that surrounding blocks are neither solid or liquid
864  constexpr std::array<Vector3i, 8> SurroundingCoords =
865  {
866  {
867  {0, 0, 1},
868  {1, 0, 1},
869  {1, 0, 0},
870  {1, 0, -1},
871  {0, 0, -1},
872  {-1, 0, -1},
873  {-1, 0, 0},
874  {-1, 0, 1},
875  }
876  };
877 
878  for (const auto & Offset : SurroundingCoords)
879  {
880  const BLOCKTYPE BlockType = GetBlock(a_Pos + Offset);
882  {
883  return true;
884  }
885  }
886 
887  return false;
888 }
889 
890 
891 
892 
893 
895 {
896  // Pick a new weather. Only reasonable transitions allowed:
897  switch (m_Weather)
898  {
899  case eWeather_Sunny:
901  {
902  return eWeather_Rain;
903  }
904  case eWeather_Rain:
905  {
906  // 1 / 8 chance of turning into a thunderstorm
908  }
909  }
910  UNREACHABLE("Unsupported weather");
911 }
912 
913 
914 
915 
916 
918 {
919  AString DefaultMonsters;
920  switch (m_Dimension)
921  {
922  case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, guardian, horse, mooshroom, ocelot, pig, rabbit, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; // TODO Re-add Enderman when bugs are fixed
923  case dimNether: DefaultMonsters = "blaze, ghast, magmacube, witherskeleton, zombiepigman"; break;
924  case dimEnd: DefaultMonsters = ""; break; // TODO Re-add Enderman when bugs are fixed
925  case dimNotSet: ASSERT(!"Dimension not set"); break;
926  }
927 
928  m_bAnimals = a_IniFile.GetValueSetB("Monsters", "AnimalsOn", true);
929  AString AllMonsters = a_IniFile.GetValueSet("Monsters", "Types", DefaultMonsters);
930 
931  if (!m_bAnimals)
932  {
933  return;
934  }
935 
936  AStringVector SplitList = StringSplitAndTrim(AllMonsters, ",");
937  for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr)
938  {
940  if (ToAdd != mtInvalidType)
941  {
942  m_AllowedMobs.insert(ToAdd);
943  LOGD("Allowed mob: %s", itr->c_str());
944  }
945  else
946  {
947  LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str());
948  }
949  }
950 }
951 
952 
953 
954 
955 
956 void cWorld::Stop(cDeadlockDetect & a_DeadlockDetect)
957 {
958  // Write settings to file; these are all plugin changeable values - keep updated!
959  cIniFile IniFile;
960  IniFile.ReadFile(m_IniFileName);
961  if (GetDimension() == dimOverworld)
962  {
963  IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_LinkedNetherWorldName);
964  IniFile.SetValue("LinkedWorlds", "EndWorldName", m_LinkedEndWorldName);
965  }
966  else
967  {
968  IniFile.SetValue("LinkedWorlds", "OverworldName", m_LinkedOverworldName);
969  }
970  IniFile.SetValueI("Physics", "TNTShrapnelLevel", static_cast<int>(m_TNTShrapnelLevel));
971  IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled);
972  IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes);
973  IniFile.SetValueB("General", "IsDaylightCycleEnabled", m_IsDaylightCycleEnabled);
974  IniFile.SetValueI("General", "Weather", static_cast<int>(m_Weather));
975  IniFile.SetValueI("General", "TimeInTicks", GetWorldDate().count());
976  IniFile.SetValueI("General", "WorldAgeMS", static_cast<Int64>(m_WorldAge.count()));
977  IniFile.WriteFile(m_IniFileName);
978 
979  m_TickThread.Stop();
980  m_Lighting.Stop();
981  m_Generator.Stop();
983  m_Storage.Stop(); // Waits for thread to finish
984 
985  a_DeadlockDetect.UntrackCriticalSection(m_CSTasks);
986  m_ChunkMap.UntrackInDeadlockDetect(a_DeadlockDetect);
987 
988  if (IsSavingEnabled())
989  {
990  // Unload the scoreboard
992  Serializer.Save();
993 
995  }
996 }
997 
998 
999 
1000 
1001 
1002 void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec)
1003 {
1004  // Notify the plugins:
1005  cPluginManager::Get()->CallHookWorldTick(*this, a_Dt, a_LastTickDurationMSec);
1006 
1007  m_WorldAge += a_Dt;
1008  m_WorldTickAge++;
1009 
1011  {
1012  m_WorldDate += a_Dt;
1013 
1014  // Updates the sky darkness based on current time of day:
1016 
1017  // Broadcast time update every 64 ticks (3.2 seconds):
1018  if ((m_WorldTickAge % 64_tick) == 0_tick)
1019  {
1021  }
1022  }
1023 
1024  // Broadcast player list pings every 256 ticks (12.8 seconds):
1025  if ((m_WorldTickAge % 256_tick) == 0_tick)
1026  {
1028  }
1029 
1030  // Process all clients' buffered actions:
1031  for (const auto Player : m_Players)
1032  {
1033  Player->GetClientHandle()->ProcessProtocolIn();
1034  }
1035 
1037  TickQueuedBlocks();
1038  m_ChunkMap.Tick(a_Dt);
1039  TickMobs(a_Dt);
1042  TickQueuedTasks();
1043  TickWeather(static_cast<float>(a_Dt.count()));
1044 
1045  GetSimulatorManager()->Simulate(static_cast<float>(a_Dt.count()));
1046 
1047  // Flush out all clients' buffered data:
1048  for (const auto Player : m_Players)
1049  {
1050  Player->GetClientHandle()->ProcessProtocolOut();
1051  }
1052 
1053  if (m_WorldAge - m_LastChunkCheck > std::chrono::seconds(10))
1054  {
1055  // Unload every 10 seconds
1057 
1058  if (m_WorldAge - m_LastSave > std::chrono::minutes(5))
1059  {
1060  // Save every 5 minutes
1061  SaveAllChunks();
1062  }
1064  {
1065  // Save if we have too many dirty unused chunks
1066  SaveAllChunks();
1067  }
1068  }
1069 }
1070 
1071 
1072 
1073 
1074 
1075 void cWorld::TickWeather(float a_Dt)
1076 {
1077  UNUSED(a_Dt);
1078  // There are no weather changes anywhere but in the Overworld:
1079  if (GetDimension() != dimOverworld)
1080  {
1081  return;
1082  }
1083 
1084  if (m_WeatherInterval > 0)
1085  {
1086  // Not yet, wait for the weather period to end
1088  }
1089  else
1090  {
1091  // Change weather:
1093  }
1094 
1096  {
1097  // 0.5% chance per tick of thunderbolt
1098  if (GetRandomProvider().RandBool(0.005))
1099  {
1100  CastThunderbolt({0, 0, 0}); // TODO: find random positions near players to cast thunderbolts.
1101  }
1102  }
1103 }
1104 
1105 
1106 
1107 
1108 
1109 void cWorld::TickMobs(std::chrono::milliseconds a_Dt)
1110 {
1111  // _X 2013_10_22: This is a quick fix for #283 - the world needs to be locked while ticking mobs
1112  cWorld::cLock Lock(*this);
1113 
1114  // before every Mob action, we have to count them depending on the distance to players, on their family ...
1115  cMobCensus MobCensus;
1116  m_ChunkMap.CollectMobCensus(MobCensus);
1117  if (m_bAnimals)
1118  {
1119  // Spawning is enabled, spawn now:
1120  static const cMonster::eFamily AllFamilies[] =
1121  {
1126  } ;
1127  for (size_t i = 0; i < ARRAYCOUNT(AllFamilies); i++)
1128  {
1129  cMonster::eFamily Family = AllFamilies[i];
1130  if (
1131  (m_LastSpawnMonster[Family] > (m_WorldTickAge - cMonster::GetSpawnDelay(Family))) || // Not reached the needed ticks before the next round
1132  MobCensus.IsCapped(Family)
1133  )
1134  {
1135  continue;
1136  }
1139  if (Spawner.CanSpawnAnything())
1140  {
1142  // do the spawn
1143  for (auto & Mob : Spawner.getSpawned())
1144  {
1145  SpawnMobFinalize(std::move(Mob));
1146  }
1147  }
1148  } // for i - AllFamilies[]
1149  } // if (Spawning enabled)
1150 
1151  ForEachEntity([=](cEntity & a_Entity)
1152  {
1153  if (!a_Entity.IsMob())
1154  {
1155  return false;
1156  }
1157  if (!a_Entity.IsTicking())
1158  {
1159  return false;
1160  }
1161 
1162  auto & Monster = static_cast<cMonster &>(a_Entity);
1163  ASSERT(Monster.GetParentChunk() != nullptr); // A ticking entity must have a valid parent chunk
1164 
1165  // Tick close mobs
1166  if (Monster.GetParentChunk()->HasAnyClients())
1167  {
1168  Monster.Tick(a_Dt, *(a_Entity.GetParentChunk()));
1169  }
1170  // Destroy far hostile mobs except if last target was a player
1171  else if ((Monster.GetMobFamily() == cMonster::eFamily::mfHostile) && !Monster.WasLastTargetAPlayer())
1172  {
1173  if (Monster.GetMobType() != eMonsterType::mtWolf)
1174  {
1175  Monster.Destroy();
1176  }
1177  else
1178  {
1179  auto & Wolf = static_cast<cWolf &>(Monster);
1180  if (!Wolf.IsAngry() && !Wolf.IsTame())
1181  {
1182  Monster.Destroy();
1183  }
1184  }
1185  }
1186  return false;
1187  }
1188  );
1189 }
1190 
1191 
1192 
1193 
1194 
1196 {
1197  decltype(m_SetChunkDataQueue) SetChunkDataQueue;
1198  {
1200  SetChunkDataQueue = std::move(m_SetChunkDataQueue);
1201  }
1202 
1203  // Set any chunk data that has been queued for setting:
1204  for (auto & Item : SetChunkDataQueue)
1205  {
1206  // A copy of the chunk coordinates since we're moving Item.
1207  const auto Chunk = Item.Chunk;
1208 
1209  // Set the data:
1210  m_ChunkMap.SetChunkData(std::move(Item));
1211 
1212  // If a client is requesting this chunk, send it to them:
1213  cChunkSender & ChunkSender = m_ChunkSender;
1214  DoWithChunk(
1215  Chunk.m_ChunkX, Chunk.m_ChunkZ,
1216  [&ChunkSender](cChunk & a_Chunk)
1217  {
1218  if (a_Chunk.HasAnyClients())
1219  {
1220  ChunkSender.QueueSendChunkTo(
1221  a_Chunk.GetPosX(),
1222  a_Chunk.GetPosZ(),
1223  cChunkSender::Priority::Medium,
1224  a_Chunk.GetAllClients()
1225  );
1226  }
1227  return true;
1228  }
1229  );
1230  } // for itr - SetChunkDataQueue[]
1231 }
1232 
1233 
1234 
1235 
1236 
1238 {
1239  decltype(m_EntitiesToAdd) EntitiesToAdd;
1240  {
1241  cCSLock Lock(m_CSEntitiesToAdd);
1242  std::swap(EntitiesToAdd, m_EntitiesToAdd);
1243  }
1244 
1245  // Ensures m_Players manipulation happens under the chunkmap lock.
1246  cLock Lock(*this);
1247 
1248  // Add entities waiting in the queue to be added:
1249  for (auto & Item: EntitiesToAdd)
1250  {
1251  const auto Entity = Item.first.get();
1252 
1253  if (Entity->IsPlayer())
1254  {
1255  const auto Player = static_cast<cPlayer *>(Entity);
1256 
1257  LOGD("Adding player %s to world \"%s\".", Player->GetName().c_str(), m_WorldName.c_str());
1258  ASSERT(std::find(m_Players.begin(), m_Players.end(), Player) == m_Players.end()); // Is it already in the list? HOW?
1259 
1260  m_Players.push_back(Player);
1261  }
1262 
1263  m_ChunkMap.AddEntity(std::move(Item.first));
1264 
1265  if (const auto OldWorld = Item.second; OldWorld != nullptr)
1266  {
1267  cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*Entity, *OldWorld);
1268  }
1269  }
1270 }
1271 
1272 
1273 
1274 
1275 
1277 {
1278  // Move the tasks to be executed to a seperate vector to avoid deadlocks on accessing m_Tasks
1279  decltype(m_Tasks) Tasks;
1280  {
1281  cCSLock Lock(m_CSTasks);
1282  if (m_Tasks.empty())
1283  {
1284  return;
1285  }
1286 
1287  // Partition everything to be executed by returning false to move to end of list if time reached
1288  auto MoveBeginIterator = std::partition(m_Tasks.begin(), m_Tasks.end(), [this](const decltype(m_Tasks)::value_type & a_Task)
1289  {
1290  return a_Task.first >= m_WorldAge;
1291  });
1292 
1293  // Cut all the due tasks from m_Tasks into Tasks:
1294  Tasks.insert(
1295  Tasks.end(),
1296  std::make_move_iterator(MoveBeginIterator),
1297  std::make_move_iterator(m_Tasks.end())
1298  );
1299  m_Tasks.erase(MoveBeginIterator, m_Tasks.end());
1300  }
1301 
1302  // Execute each task:
1303  for (const auto & Task : Tasks)
1304  {
1305  Task.second(*this);
1306  } // for itr - m_Tasks[]
1307 }
1308 
1309 
1310 
1311 
1312 
1314 {
1315  const auto TIME_SUNSET = 12000_tick;
1316  const auto TIME_NIGHT_START = 13187_tick;
1317  const auto TIME_NIGHT_END = 22812_tick;
1318  const auto TIME_SUNRISE = 23999_tick;
1319  const auto TIME_SPAWN_DIVISOR = 148_tick;
1320 
1321  const auto TempTime = GetTimeOfDay();
1322  if (TempTime <= TIME_SUNSET)
1323  {
1324  m_SkyDarkness = 0;
1325  }
1326  else if (TempTime <= TIME_NIGHT_START)
1327  {
1328  m_SkyDarkness = static_cast<NIBBLETYPE>((TIME_NIGHT_START - TempTime) / TIME_SPAWN_DIVISOR);
1329  }
1330  else if (TempTime <= TIME_NIGHT_END)
1331  {
1332  m_SkyDarkness = 8;
1333  }
1334  else
1335  {
1336  m_SkyDarkness = static_cast<NIBBLETYPE>((TIME_SUNRISE - TempTime) / TIME_SPAWN_DIVISOR);
1337  }
1338 }
1339 
1340 
1341 
1342 
1343 
1345 {
1346  return m_ChunkMap.WakeUpSimulators(a_Block);
1347 }
1348 
1349 
1350 
1351 
1352 
1354 {
1355  m_SimulatorManager->WakeUp(a_Area);
1356 }
1357 
1358 
1359 
1360 
1361 
1362 bool cWorld::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback)
1363 {
1364  return m_ChunkMap.ForEachBlockEntityInChunk(a_ChunkX, a_ChunkZ, a_Callback);
1365 }
1366 
1367 
1368 
1369 
1370 
1371 void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData)
1372 {
1373  cLock Lock(*this);
1374  if (!cPluginManager::Get()->CallHookExploding(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData) && (a_ExplosionSize > 0))
1375  {
1376  // TODO: CanCauseFire gets reset to false for some reason, (plugin has ability to change it, might be related)
1377 
1378  const cEntity * Entity;
1379  switch (a_Source)
1380  {
1387  {
1388  Entity = static_cast<const cEntity *>(a_SourceData);
1389  break;
1390  }
1391  default:
1392  {
1393  Entity = nullptr;
1394  }
1395  }
1396 
1397  Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC(a_ExplosionSize), a_CanCauseFire, Entity);
1398  cPluginManager::Get()->CallHookExploded(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData);
1399  }
1400 }
1401 
1402 
1403 
1404 
1405 
1407 {
1408  return m_ChunkMap.DoWithBlockEntityAt(a_Position, a_Callback);
1409 }
1410 
1411 
1412 
1413 
1414 
1415 bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
1416 {
1417  return DoWithBlockEntityAt({ a_BlockX, a_BlockY, a_BlockZ }, [&a_Line1, &a_Line2, &a_Line3, &a_Line4](cBlockEntity & a_BlockEntity)
1418  {
1419  if ((a_BlockEntity.GetBlockType() != E_BLOCK_WALLSIGN) && (a_BlockEntity.GetBlockType() != E_BLOCK_SIGN_POST))
1420  {
1421  return false; // Not a sign
1422  }
1423 
1424  const auto & Sign = static_cast<cSignEntity &>(a_BlockEntity);
1425  a_Line1 = Sign.GetLine(0);
1426  a_Line2 = Sign.GetLine(1);
1427  a_Line3 = Sign.GetLine(2);
1428  a_Line4 = Sign.GetLine(3);
1429  return true;
1430  });
1431 }
1432 
1433 
1434 
1435 
1436 
1437 bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback)
1438 {
1439  return m_ChunkMap.DoWithChunk(a_ChunkX, a_ChunkZ, a_Callback);
1440 }
1441 
1442 
1443 
1444 
1445 
1446 bool cWorld::DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback)
1447 {
1448  return m_ChunkMap.DoWithChunkAt(a_BlockPos, a_Callback);
1449 }
1450 
1451 
1452 
1453 
1454 
1455 bool cWorld::GrowTree(const Vector3i a_BlockPos)
1456 {
1457  if (GetBlock(a_BlockPos) == E_BLOCK_SAPLING)
1458  {
1459  // There is a sapling here, grow a tree according to its type:
1460  return GrowTreeFromSapling(a_BlockPos);
1461  }
1462  else
1463  {
1464  // There is nothing here, grow a tree based on the current biome here:
1465  return GrowTreeByBiome(a_BlockPos);
1466  }
1467 }
1468 
1469 
1470 
1471 
1472 
1474 {
1475  cNoise Noise(m_Generator.GetSeed());
1476  sSetBlockVector Logs, Other;
1477  auto WorldAge = static_cast<int>(m_WorldTickAge.count() & 0xffffffff);
1478  auto SaplingMeta = GetBlockMeta(a_BlockPos);
1479  switch (SaplingMeta & 0x07)
1480  {
1481  case E_META_SAPLING_APPLE: GetAppleTreeImage (a_BlockPos, Noise, WorldAge, Logs, Other); break;
1482  case E_META_SAPLING_BIRCH: GetBirchTreeImage (a_BlockPos, Noise, WorldAge, Logs, Other); break;
1484  {
1485  bool IsLarge = GetLargeTreeAdjustment(a_BlockPos, SaplingMeta);
1486  GetConiferTreeImage(a_BlockPos, Noise, WorldAge, Logs, Other, IsLarge);
1487  break;
1488  }
1489  case E_META_SAPLING_ACACIA: GetAcaciaTreeImage (a_BlockPos, Noise, WorldAge, Logs, Other); break;
1490  case E_META_SAPLING_JUNGLE:
1491  {
1492  bool IsLarge = GetLargeTreeAdjustment(a_BlockPos, SaplingMeta);
1493  GetJungleTreeImage(a_BlockPos, Noise, WorldAge, Logs, Other, IsLarge);
1494  break;
1495  }
1497  {
1498  if (!GetLargeTreeAdjustment(a_BlockPos, SaplingMeta))
1499  {
1500  return false;
1501  }
1502 
1503  GetDarkoakTreeImage(a_BlockPos, Noise, WorldAge, Logs, Other);
1504  break;
1505  }
1506  }
1507  Other.insert(Other.begin(), Logs.begin(), Logs.end());
1508  Logs.clear();
1509  return GrowTreeImage(Other);
1510 }
1511 
1512 
1513 
1514 
1515 
1517 {
1518  bool IsLarge = true;
1519  a_Meta = a_Meta & 0x07;
1520 
1521  // Check to see if we are the northwest corner
1522  for (int x = 0; x < 2; ++x)
1523  {
1524  for (int z = 0; z < 2; ++z)
1525  {
1526  NIBBLETYPE meta;
1527  BLOCKTYPE type;
1528  GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
1529  IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
1530  }
1531  }
1532 
1533  if (IsLarge)
1534  {
1535  return true;
1536  }
1537 
1538  IsLarge = true;
1539  // Check to see if we are the southwest corner
1540  for (int x = 0; x < 2; ++x)
1541  {
1542  for (int z = 0; z > -2; --z)
1543  {
1544  NIBBLETYPE meta;
1545  BLOCKTYPE type;
1546  GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
1547  IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
1548  }
1549  }
1550 
1551  if (IsLarge)
1552  {
1553  --a_BlockPos.z;
1554  return true;
1555  }
1556 
1557  IsLarge = true;
1558  // Check to see if we are the southeast corner
1559  for (int x = 0; x > -2; --x)
1560  {
1561  for (int z = 0; z > -2; --z)
1562  {
1563  NIBBLETYPE meta;
1564  BLOCKTYPE type;
1565  GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
1566  IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
1567  }
1568  }
1569 
1570  if (IsLarge)
1571  {
1572  --a_BlockPos.x;
1573  --a_BlockPos.z;
1574  return true;
1575  }
1576 
1577  IsLarge = true;
1578  // Check to see if we are the northeast corner
1579  for (int x = 0; x > -2; --x)
1580  {
1581  for (int z = 0; z < 2; ++z)
1582  {
1583  NIBBLETYPE meta;
1584  BLOCKTYPE type;
1585  GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
1586  IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
1587  }
1588  }
1589 
1590  if (IsLarge)
1591  {
1592  --a_BlockPos.x;
1593  }
1594 
1595  return IsLarge;
1596 }
1597 
1598 
1599 
1600 
1601 
1602 bool cWorld::GrowTreeByBiome(const Vector3i a_BlockPos)
1603 {
1604  cNoise Noise(m_Generator.GetSeed());
1605  sSetBlockVector Logs, Other;
1606  auto seq = static_cast<int>(m_WorldTickAge.count() & 0xffffffff);
1607  GetTreeImageByBiome(a_BlockPos, Noise, seq, GetBiomeAt(a_BlockPos.x, a_BlockPos.z), Logs, Other);
1608  Other.insert(Other.begin(), Logs.begin(), Logs.end());
1609  Logs.clear();
1610  return GrowTreeImage(Other);
1611 }
1612 
1613 
1614 
1615 
1616 
1618 {
1619  // Check that the tree has place to grow
1620 
1621  // Make a copy of the log blocks:
1622  sSetBlockVector b2;
1623  for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
1624  {
1625  if (itr->m_BlockType == E_BLOCK_LOG)
1626  {
1627  b2.push_back(*itr);
1628  }
1629  } // for itr - a_Blocks[]
1630 
1631  // Query blocktypes and metas at those log blocks:
1632  if (!GetBlocks(b2, false))
1633  {
1634  return false;
1635  }
1636 
1637  // Check that at each log's coord there's an block allowed to be overwritten:
1638  for (sSetBlockVector::const_iterator itr = b2.begin(); itr != b2.end(); ++itr)
1639  {
1640  switch (itr->m_BlockType)
1641  {
1643  {
1644  break;
1645  }
1646  default:
1647  {
1648  return false;
1649  }
1650  }
1651  } // for itr - b2[]
1652 
1653  // All ok, replace blocks with the tree image:
1654  m_ChunkMap.ReplaceTreeBlocks(a_Blocks);
1655  return true;
1656 }
1657 
1658 
1659 
1660 
1661 
1662 int cWorld::GrowPlantAt(Vector3i a_BlockPos, int a_NumStages)
1663 {
1664  return m_ChunkMap.GrowPlantAt(a_BlockPos, a_NumStages);
1665 }
1666 
1667 
1668 
1669 
1670 
1672 {
1673  return (GrowPlantAt(a_BlockPos, 16) > 0);
1674 }
1675 
1676 
1677 
1678 
1679 
1680 EMCSBiome cWorld::GetBiomeAt (int a_BlockX, int a_BlockZ)
1681 {
1682  return m_ChunkMap.GetBiomeAt(a_BlockX, a_BlockZ);
1683 }
1684 
1685 
1686 
1687 
1688 
1689 bool cWorld::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
1690 {
1691  return m_ChunkMap.SetBiomeAt(a_BlockX, a_BlockZ, a_Biome);
1692 }
1693 
1694 
1695 
1696 
1697 
1698 bool cWorld::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome)
1699 {
1700  return m_ChunkMap.SetAreaBiome(a_MinX, a_MaxX, a_MinZ, a_MaxZ, a_Biome);
1701 }
1702 
1703 
1704 
1705 
1706 
1707 bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome)
1708 {
1709  return SetAreaBiome(
1710  std::min(a_Area.p1.x, a_Area.p2.x), std::max(a_Area.p1.x, a_Area.p2.x),
1711  std::min(a_Area.p1.z, a_Area.p2.z), std::max(a_Area.p1.z, a_Area.p2.z),
1712  a_Biome
1713  );
1714 }
1715 
1716 
1717 
1718 
1719 
1720 void cWorld::SetMaxViewDistance(int a_MaxViewDistance)
1721 {
1723 }
1724 
1725 
1726 
1727 
1728 
1729 void cWorld::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
1730 {
1731  m_ChunkMap.SetBlock(a_BlockPos, a_BlockType, a_BlockMeta);
1732 }
1733 
1734 
1735 
1736 
1737 
1738 void cWorld::SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData)
1739 {
1740  m_ChunkMap.SetBlockMeta(a_BlockPos, a_MetaData);
1741 }
1742 
1743 
1744 
1745 
1746 
1748 {
1749  return m_ChunkMap.GetBlockSkyLight(a_BlockPos);
1750 }
1751 
1752 
1753 
1754 
1755 
1757 {
1758  return m_ChunkMap.GetBlockBlockLight(a_BlockPos);
1759 }
1760 
1761 
1762 
1763 
1764 
1765 bool cWorld::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const
1766 {
1767  return m_ChunkMap.GetBlockTypeMeta(a_BlockPos, a_BlockType, a_BlockMeta);
1768 }
1769 
1770 
1771 
1772 
1773 
1774 bool cWorld::GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const
1775 {
1776  return m_ChunkMap.GetBlockInfo(a_BlockPos, a_BlockType, a_Meta, a_SkyLight, a_BlockLight);
1777 }
1778 
1779 
1780 
1781 
1782 
1783 bool cWorld::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
1784 {
1785  return m_ChunkMap.WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes);
1786 }
1787 
1788 
1789 
1790 
1791 
1792 void cWorld::SpawnItemPickups(const cItems & a_Pickups, Vector3i a_BlockPos, double a_FlyAwaySpeed, bool a_IsPlayerCreated)
1793 {
1794  auto & random = GetRandomProvider();
1795  auto microX = random.RandReal<double>(0, 1);
1796  auto microZ = random.RandReal<double>(0, 1);
1797  return SpawnItemPickups(a_Pickups, Vector3d(microX, 0, microZ) + a_BlockPos, a_FlyAwaySpeed, a_IsPlayerCreated);
1798 }
1799 
1800 
1801 
1802 
1803 
1804 void cWorld::SpawnItemPickups(const cItems & a_Pickups, Vector3d a_Pos, double a_FlyAwaySpeed, bool a_IsPlayerCreated)
1805 {
1806  auto & Random = GetRandomProvider();
1807  a_FlyAwaySpeed /= 100; // Pre-divide, so that we don't have to divide each time inside the loop
1808  for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr)
1809  {
1810  if (!IsValidItem(itr->m_ItemType) || (itr->m_ItemType == E_BLOCK_AIR))
1811  {
1812  // Don't spawn pickup if item isn't even valid; should prevent client crashing too
1813  continue;
1814  }
1815 
1816  float SpeedX = static_cast<float>(a_FlyAwaySpeed * Random.RandInt(-10, 10));
1817  float SpeedY = static_cast<float>(a_FlyAwaySpeed * Random.RandInt(40, 50));
1818  float SpeedZ = static_cast<float>(a_FlyAwaySpeed * Random.RandInt(-10, 10));
1819 
1820  auto Pickup = std::make_unique<cPickup>(a_Pos, *itr, a_IsPlayerCreated, Vector3f{SpeedX, SpeedY, SpeedZ});
1821  auto PickupPtr = Pickup.get();
1822  PickupPtr->Initialize(std::move(Pickup), *this);
1823  }
1824 }
1825 
1826 
1827 
1828 
1829 
1830 void cWorld::SpawnItemPickups(const cItems & a_Pickups, Vector3d a_Pos, Vector3d a_Speed, bool a_IsPlayerCreated)
1831 {
1832  for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr)
1833  {
1834  if (!IsValidItem(itr->m_ItemType) || (itr->m_ItemType == E_BLOCK_AIR))
1835  {
1836  continue;
1837  }
1838 
1839  auto pickup = std::make_unique<cPickup>(a_Pos, *itr, a_IsPlayerCreated, a_Speed);
1840  auto pickupPtr = pickup.get();
1841  pickupPtr->Initialize(std::move(pickup), *this);
1842  }
1843 }
1844 
1845 
1846 
1847 
1848 
1849 UInt32 cWorld::SpawnItemPickup(Vector3d a_Pos, const cItem & a_Item, Vector3f a_Speed, int a_LifetimeTicks, bool a_CanCombine)
1850 {
1851  auto pickup = std::make_unique<cPickup>(a_Pos, a_Item, false, a_Speed, a_LifetimeTicks, a_CanCombine);
1852  auto pickupPtr = pickup.get();
1853  if (!pickupPtr->Initialize(std::move(pickup), *this))
1854  {
1855  return cEntity::INVALID_ID;
1856  }
1857  return pickupPtr->GetUniqueID();
1858 }
1859 
1860 
1861 
1862 
1863 
1865 {
1866  auto fallingBlock = std::make_unique<cFallingBlock>(a_Pos, a_BlockType, a_BlockMeta);
1867  auto fallingBlockPtr = fallingBlock.get();
1868  auto ID = fallingBlock->GetUniqueID();
1869  if (!fallingBlockPtr->Initialize(std::move(fallingBlock), *this))
1870  {
1871  return cEntity::INVALID_ID;
1872  }
1873  return ID;
1874 }
1875 
1876 
1877 
1878 
1879 
1881 {
1882  if (a_Reward < 1)
1883  {
1884  LOGWARNING("%s: Attempting to create an experience orb with non-positive reward!", __FUNCTION__);
1885  return cEntity::INVALID_ID;
1886  }
1887 
1888  auto expOrb = std::make_unique<cExpOrb>(a_Pos, a_Reward);
1889  auto expOrbPtr = expOrb.get();
1890  if (!expOrbPtr->Initialize(std::move(expOrb), *this))
1891  {
1892  return cEntity::INVALID_ID;
1893  }
1894  return expOrbPtr->GetUniqueID();
1895 }
1896 
1897 
1898 
1899 
1900 
1901 std::vector<UInt32> cWorld::SpawnSplitExperienceOrbs(Vector3d a_Pos, int a_Reward)
1902 {
1903  std::vector<UInt32> OrbsID;
1904 
1905  if (a_Reward < 1)
1906  {
1907  LOGWARNING("%s: Attempting to create an experience orb with non-positive reward!", __FUNCTION__);
1908  return OrbsID;
1909  }
1910 
1911  std::vector<int> Rewards = cExpOrb::Split(a_Reward);
1912 
1913  // Check generate number to decide speed limit (distribute range)
1914  float SpeedLimit = static_cast<float>((Rewards.size() / 2) + 5);
1915  if (SpeedLimit > 10)
1916  {
1917  SpeedLimit = 10;
1918  }
1919 
1920  auto & Random = GetRandomProvider();
1921  for (auto Reward : Rewards)
1922  {
1923  auto ExpOrb = std::make_unique<cExpOrb>(a_Pos, Reward);
1924  auto ExpOrbPtr = ExpOrb.get();
1925  double SpeedX = Random.RandReal(-SpeedLimit, SpeedLimit);
1926  double SpeedY = Random.RandReal(0.5);
1927  double SpeedZ = Random.RandReal(-SpeedLimit, SpeedLimit);
1928  ExpOrbPtr->SetSpeed(SpeedX, SpeedY, SpeedZ);
1929 
1930  UInt32 Id = ExpOrbPtr->GetUniqueID();
1931  if (ExpOrbPtr->Initialize(std::move(ExpOrb), *this))
1932  {
1933  OrbsID.push_back(Id);
1934  }
1935  }
1936 
1937  return OrbsID;
1938 }
1939 
1940 
1941 
1942 
1943 
1944 UInt32 cWorld::SpawnMinecart(Vector3d a_Pos, int a_MinecartType, const cItem & a_Content, int a_BlockHeight)
1945 {
1946  std::unique_ptr<cMinecart> Minecart;
1947  switch (a_MinecartType)
1948  {
1949  case E_ITEM_MINECART: Minecart = std::make_unique<cRideableMinecart> (a_Pos, a_Content, a_BlockHeight); break;
1950  case E_ITEM_CHEST_MINECART: Minecart = std::make_unique<cMinecartWithChest> (a_Pos); break;
1951  case E_ITEM_FURNACE_MINECART: Minecart = std::make_unique<cMinecartWithFurnace>(a_Pos); break;
1952  case E_ITEM_MINECART_WITH_TNT: Minecart = std::make_unique<cMinecartWithTNT> (a_Pos); break;
1953  case E_ITEM_MINECART_WITH_HOPPER: Minecart = std::make_unique<cMinecartWithHopper> (a_Pos); break;
1954  default:
1955  {
1956  return cEntity::INVALID_ID;
1957  }
1958  } // switch (a_MinecartType)
1959 
1960  auto MinecartPtr = Minecart.get();
1961  if (!MinecartPtr->Initialize(std::move(Minecart), *this))
1962  {
1963  return cEntity::INVALID_ID;
1964  }
1965  return MinecartPtr->GetUniqueID();
1966 }
1967 
1968 
1969 
1970 
1971 
1973 {
1974  auto Boat = std::make_unique<cBoat>(a_Pos, a_Material);
1975  auto BoatPtr = Boat.get();
1976  if (!BoatPtr->Initialize(std::move(Boat), *this))
1977  {
1978  return cEntity::INVALID_ID;
1979  }
1980  return BoatPtr->GetUniqueID();
1981 }
1982 
1983 
1984 
1985 
1986 
1987 UInt32 cWorld::SpawnPrimedTNT(Vector3d a_Pos, int a_FuseTicks, double a_InitialVelocityCoeff, bool a_ShouldPlayFuseSound)
1988 {
1989  auto TNT = std::make_unique<cTNTEntity>(a_Pos, a_FuseTicks);
1990  auto TNTPtr = TNT.get();
1991  if (!TNTPtr->Initialize(std::move(TNT), *this))
1992  {
1993  return cEntity::INVALID_ID;
1994  }
1995 
1996  if (a_ShouldPlayFuseSound)
1997  {
1998  BroadcastSoundEffect("entity.tnt.primed", a_Pos, 1.0f, 1.0f);
1999  }
2000 
2001  auto & Random = GetRandomProvider();
2002  TNTPtr->SetSpeed(
2003  a_InitialVelocityCoeff * Random.RandReal(-0.5f, 0.5f),
2004  a_InitialVelocityCoeff * 2,
2005  a_InitialVelocityCoeff * Random.RandReal(-0.5f, 0.5f)
2006  );
2007  return TNTPtr->GetUniqueID();
2008 }
2009 
2010 
2011 
2012 
2013 
2014 UInt32 cWorld::SpawnEnderCrystal(Vector3d a_Pos, bool a_ShowBottom)
2015 {
2016  auto EnderCrystal = std::make_unique<cEnderCrystal>(a_Pos, a_ShowBottom);
2017  auto EnderCrystalPtr = EnderCrystal.get();
2018  if (!EnderCrystalPtr->Initialize(std::move(EnderCrystal), *this))
2019  {
2020  return cEntity::INVALID_ID;
2021  }
2022  return EnderCrystalPtr->GetUniqueID();
2023 }
2024 
2025 
2026 
2027 
2028 
2029 void cWorld::PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta)
2030 {
2032  NIBBLETYPE BlockMeta;
2033  GetBlockTypeMeta(a_Position, BlockType, BlockMeta);
2034 
2035  SetBlock(a_Position, a_BlockType, a_BlockMeta);
2036 
2037  cChunkInterface ChunkInterface(GetChunkMap());
2038  cBlockHandler::For(BlockType).OnBroken(ChunkInterface, *this, a_Position, BlockType, BlockMeta, nullptr);
2039  cBlockHandler::For(a_BlockType).OnPlaced(ChunkInterface, *this, a_Position, a_BlockType, a_BlockMeta);
2040 }
2041 
2042 
2043 
2044 
2045 
2046 bool cWorld::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
2047 {
2048  return m_ChunkMap.GetBlocks(a_Blocks, a_ContinueOnFailure);
2049 }
2050 
2051 
2052 
2053 
2054 
2055 bool cWorld::DigBlock(Vector3i a_BlockPos, const cEntity * a_Digger)
2056 {
2058  NIBBLETYPE BlockMeta;
2059  GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta);
2060 
2061  if (!m_ChunkMap.DigBlock(a_BlockPos))
2062  {
2063  return false;
2064  }
2065 
2066  cChunkInterface ChunkInterface(GetChunkMap());
2067  cBlockHandler::For(BlockType).OnBroken(ChunkInterface, *this, a_BlockPos, BlockType, BlockMeta, a_Digger);
2068 
2069  return true;
2070 }
2071 
2072 
2073 
2074 
2075 
2076 bool cWorld::DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool)
2077 {
2078  auto pickups = PickupsFromBlock(a_BlockPos, a_Digger, a_Tool);
2079  if (!DigBlock(a_BlockPos, a_Digger))
2080  {
2081  return false;
2082  }
2083  SpawnItemPickups(pickups, Vector3d(0.5, 0.5, 0.5) + a_BlockPos, 10);
2084  return true;
2085 }
2086 
2087 
2088 
2089 
2090 
2091 cItems cWorld::PickupsFromBlock(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool)
2092 {
2093  return m_ChunkMap.PickupsFromBlock(a_BlockPos, a_Digger, a_Tool);
2094 }
2095 
2096 
2097 
2098 
2099 
2100 void cWorld::SendBlockTo(int a_X, int a_Y, int a_Z, const cPlayer & a_Player)
2101 {
2102  m_ChunkMap.SendBlockTo(a_X, a_Y, a_Z, a_Player);
2103 }
2104 
2105 
2106 
2107 
2108 
2109 int cWorld::GetHeight(int a_X, int a_Z)
2110 {
2111  return m_ChunkMap.GetHeight(a_X, a_Z);
2112 }
2113 
2114 
2115 
2116 
2117 
2118 bool cWorld::TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height)
2119 {
2120  return m_ChunkMap.TryGetHeight(a_BlockX, a_BlockZ, a_Height);
2121 }
2122 
2123 
2124 
2125 
2126 
2127 void cWorld::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client)
2128 {
2129  m_ChunkMap.SendBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Client);
2130 }
2131 
2132 
2133 
2134 
2135 
2136 void cWorld::MarkChunkDirty(int a_ChunkX, int a_ChunkZ)
2137 {
2138  m_ChunkMap.MarkChunkDirty(a_ChunkX, a_ChunkZ);
2139 }
2140 
2141 
2142 
2143 
2144 
2145 void cWorld::MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
2146 {
2147  m_ChunkMap.MarkChunkSaving(a_ChunkX, a_ChunkZ);
2148 }
2149 
2150 
2151 
2152 
2153 
2154 void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
2155 {
2156  m_ChunkMap.MarkChunkSaved (a_ChunkX, a_ChunkZ);
2157 }
2158 
2159 
2160 
2161 
2162 
2163 void cWorld::QueueSetChunkData(struct SetChunkData && a_SetChunkData)
2164 {
2165  // Store a copy of the data in the queue:
2166  // TODO: If the queue is too large, wait for it to get processed. Not likely, though.
2168  m_SetChunkDataQueue.emplace_back(std::move(a_SetChunkData));
2169 }
2170 
2171 
2172 
2173 
2174 
2176  int a_ChunkX, int a_ChunkZ,
2177  const cChunkDef::BlockNibbles & a_BlockLight,
2178  const cChunkDef::BlockNibbles & a_SkyLight
2179 )
2180 {
2181  m_ChunkMap.ChunkLighted(a_ChunkX, a_ChunkZ, a_BlockLight, a_SkyLight);
2182 }
2183 
2184 
2185 
2186 
2187 
2188 bool cWorld::GetChunkData(cChunkCoords a_Coords, cChunkDataCallback & a_Callback) const
2189 {
2190  return m_ChunkMap.GetChunkData(a_Coords, a_Callback);
2191 }
2192 
2193 
2194 
2195 
2196 
2197 bool cWorld::IsChunkQueued(int a_ChunkX, int a_ChunkZ) const
2198 {
2199  return m_ChunkMap.IsChunkQueued(a_ChunkX, a_ChunkZ);
2200 }
2201 
2202 
2203 
2204 
2205 
2206 bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
2207 {
2208  return m_ChunkMap.IsChunkValid(a_ChunkX, a_ChunkZ);
2209 }
2210 
2211 
2212 
2213 
2214 
2215 bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const
2216 {
2217  return m_ChunkMap.HasChunkAnyClients(a_ChunkX, a_ChunkZ);
2218 }
2219 
2220 
2221 
2222 
2223 
2225 {
2228 }
2229 
2230 
2231 
2232 
2233 
2235 {
2236  QueueTask([](cWorld & a_World) { a_World.UnloadUnusedChunks(); });
2237 }
2238 
2239 
2240 
2241 
2242 
2244 {
2246 }
2247 
2248 
2249 
2250 
2251 
2253 {
2254  // Calls the callback for each player in the list
2255  cLock Lock(*this);
2256  for (auto & Player : m_Players)
2257  {
2258  if (Player->IsTicking() && a_Callback(*Player))
2259  {
2260  return false;
2261  }
2262  } // for itr - m_Players[]
2263  return true;
2264 }
2265 
2266 
2267 
2268 
2269 
2270 bool cWorld::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback)
2271 {
2272  // Calls the callback for the specified player in the list
2273  cLock Lock(*this);
2274  for (auto & Player : m_Players)
2275  {
2276  if (Player->IsTicking() && (NoCaseCompare(Player->GetName(), a_PlayerName) == 0))
2277  {
2278  a_Callback(*Player);
2279  return true;
2280  }
2281  } // for itr - m_Players[]
2282  return false;
2283 }
2284 
2285 
2286 
2287 
2288 
2289 bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback a_Callback)
2290 {
2291  cPlayer * BestMatch = nullptr;
2292  size_t BestRating = 0;
2293  size_t NameLength = a_PlayerNameHint.length();
2294 
2295  cLock Lock(*this);
2296  for (const auto Player : m_Players)
2297  {
2298  if (!Player->IsTicking())
2299  {
2300  continue;
2301  }
2302  size_t Rating = RateCompareString (a_PlayerNameHint, Player->GetName());
2303  if (Rating >= BestRating)
2304  {
2305  BestMatch = Player;
2306  BestRating = Rating;
2307  }
2308  if (Rating == NameLength) // Perfect match
2309  {
2310  break;
2311  }
2312  } // for itr - m_Players[]
2313 
2314  if (BestMatch != nullptr)
2315  {
2316  return a_Callback(*BestMatch);
2317  }
2318  return false;
2319 }
2320 
2321 
2322 
2323 
2324 
2325 bool cWorld::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a_Callback)
2326 {
2327  cLock Lock(*this);
2328  for (auto & Player : m_Players)
2329  {
2330  if (Player->IsTicking() && (Player->GetUUID() == a_PlayerUUID))
2331  {
2332  return a_Callback(*Player);
2333  }
2334  }
2335  return false;
2336 }
2337 
2338 
2339 
2340 
2341 
2342 bool cWorld::DoWithNearestPlayer(Vector3d a_Pos, double a_RangeLimit, cPlayerListCallback a_Callback, bool a_CheckLineOfSight, bool a_IgnoreSpectator)
2343 {
2344  double ClosestDistance = a_RangeLimit;
2345  cPlayer * ClosestPlayer = nullptr;
2346 
2347  cLock Lock(*this);
2348  for (const auto Player : m_Players)
2349  {
2350  if (!Player->IsTicking())
2351  {
2352  continue;
2353  }
2354 
2355  if (a_IgnoreSpectator && Player->IsGameModeSpectator())
2356  {
2357  continue;
2358  }
2359 
2360  Vector3f Pos = Player->GetPosition();
2361  double Distance = (Pos - a_Pos).Length();
2362 
2363  // If the player is too far, skip them:
2364  if (Distance > ClosestDistance)
2365  {
2366  continue;
2367  }
2368 
2369  // Check LineOfSight, if requested:
2370  if (
2371  a_CheckLineOfSight &&
2373  )
2374  {
2375  continue;
2376  }
2377 
2378  ClosestDistance = Distance;
2379  ClosestPlayer = Player;
2380  }
2381 
2382  if (ClosestPlayer)
2383  {
2384  return a_Callback(*ClosestPlayer);
2385  }
2386  else
2387  {
2388  return false;
2389  }
2390 }
2391 
2392 
2393 
2394 
2395 
2396 void cWorld::SendPlayerList(cPlayer * a_DestPlayer)
2397 {
2398  // Sends the playerlist to a_DestPlayer
2399  cLock Lock(*this);
2400  for (const auto & Player : m_Players)
2401  {
2402  if (!Player->GetClientHandle()->IsDestroyed())
2403  {
2404  a_DestPlayer->GetClientHandle()->SendPlayerListAddPlayer(*Player);
2405  }
2406  }
2407 }
2408 
2409 
2410 
2411 
2412 
2414 {
2415  return m_ChunkMap.ForEachEntity(a_Callback);
2416 }
2417 
2418 
2419 
2420 
2421 
2422 bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback)
2423 {
2424  return m_ChunkMap.ForEachEntityInChunk(a_ChunkX, a_ChunkZ, a_Callback);
2425 }
2426 
2427 
2428 
2429 
2430 
2432 {
2433  return m_ChunkMap.ForEachEntityInBox(a_Box, a_Callback);
2434 }
2435 
2436 
2437 
2438 
2439 
2441 {
2442  cLock Lock(*this);
2443  return m_Players.size();
2444 }
2445 
2446 
2447 
2448 
2449 
2451 {
2452  // First check the entities-to-add:
2453  {
2454  cCSLock Lock(m_CSEntitiesToAdd);
2455  for (const auto & Item : m_EntitiesToAdd)
2456  {
2457  if (Item.first->GetUniqueID() == a_UniqueID)
2458  {
2459  a_Callback(*Item.first);
2460  return true;
2461  }
2462  } // for ent - m_EntitiesToAdd[]
2463  }
2464 
2465  // Then check the chunkmap:
2466  return m_ChunkMap.DoWithEntityByID(a_UniqueID, a_Callback);
2467 }
2468 
2469 
2470 
2471 
2472 
2473 void cWorld::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
2474 {
2475  m_ChunkMap.CompareChunkClients(a_ChunkX1, a_ChunkZ1, a_ChunkX2, a_ChunkZ2, a_Callback);
2476 }
2477 
2478 
2479 
2480 
2481 
2482 bool cWorld::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
2483 {
2484  return m_ChunkMap.AddChunkClient(a_ChunkX, a_ChunkZ, a_Client);
2485 }
2486 
2487 
2488 
2489 
2490 
2491 void cWorld::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
2492 {
2493  m_ChunkMap.RemoveChunkClient(a_ChunkX, a_ChunkZ, a_Client);
2494 }
2495 
2496 
2497 
2498 
2499 
2501 {
2503 }
2504 
2505 
2506 
2507 
2508 
2509 void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle * a_Client)
2510 {
2511  m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client);
2512 }
2513 
2514 
2515 
2516 
2517 
2518 void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle * a_Client)
2519 {
2520  a_Client->AddWantedChunk(a_ChunkX, a_ChunkZ);
2521  m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client);
2522 }
2523 
2524 
2525 
2526 
2527 
2528 void cWorld::PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_CallAfter)
2529 {
2530  m_ChunkMap.PrepareChunk(a_ChunkX, a_ChunkZ, std::move(a_CallAfter));
2531 }
2532 
2533 
2534 
2535 
2536 
2537 void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
2538 {
2539  m_ChunkMap.ChunkLoadFailed(a_ChunkX, a_ChunkZ);
2540 }
2541 
2542 
2543 
2544 
2545 
2546 bool cWorld::SetSignLines(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player)
2547 {
2548  // TODO: rvalue these strings
2549 
2550  AString Line1(a_Line1);
2551  AString Line2(a_Line2);
2552  AString Line3(a_Line3);
2553  AString Line4(a_Line4);
2554 
2555  if (cRoot::Get()->GetPluginManager()->CallHookUpdatingSign(*this, a_BlockPos, Line1, Line2, Line3, Line4, a_Player))
2556  {
2557  return false;
2558  }
2559 
2560  if (
2561  DoWithBlockEntityAt(a_BlockPos, [&Line1, &Line2, &Line3, &Line4](cBlockEntity & a_BlockEntity)
2562  {
2563  if ((a_BlockEntity.GetBlockType() != E_BLOCK_WALLSIGN) && (a_BlockEntity.GetBlockType() != E_BLOCK_SIGN_POST))
2564  {
2565  return false; // Not a sign
2566  }
2567 
2568  static_cast<cSignEntity &>(a_BlockEntity).SetLines(Line1, Line2, Line3, Line4);
2569  return true;
2570  })
2571  )
2572  {
2573  cRoot::Get()->GetPluginManager()->CallHookUpdatedSign(*this, a_BlockPos, Line1, Line2, Line3, Line4, a_Player);
2574  return true;
2575  }
2576 
2577  return false;
2578 }
2579 
2580 
2581 
2582 
2583 
2584 bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command)
2585 {
2586  return DoWithBlockEntityAt({ a_BlockX, a_BlockY, a_BlockZ }, [&](cBlockEntity & a_BlockEntity)
2587  {
2588  if (a_BlockEntity.GetBlockType() != E_BLOCK_COMMAND_BLOCK)
2589  {
2590  return false;
2591  }
2592 
2593  static_cast<cCommandBlockEntity &>(a_BlockEntity).SetCommand(a_Command);
2594  return true;
2595  });
2596 }
2597 
2598 
2599 
2600 
2601 
2602 bool cWorld::IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ)
2603 {
2604  BLOCKTYPE Block;
2605  NIBBLETYPE Meta;
2606  GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta);
2608  {
2609  return false;
2610  }
2611 
2612  return (Meta & 0x4) > 0;
2613 }
2614 
2615 
2616 
2617 
2618 
2619 bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open)
2620 {
2621  BLOCKTYPE Block;
2622  NIBBLETYPE Meta;
2623  GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta);
2625  {
2626  return false;
2627  }
2628 
2629  bool IsOpen = (Meta & 0x4) != 0;
2630  if (a_Open != IsOpen)
2631  {
2632  SetBlockMeta({ a_BlockX, a_BlockY, a_BlockZ }, Meta ^ 0x4);
2633  BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_TRAPDOOR_OPEN, { a_BlockX, a_BlockY, a_BlockZ }, 0);
2634  return true;
2635  }
2636  return false;
2637 }
2638 
2639 
2640 
2641 
2642 
2643 void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ)
2644 {
2645  m_ChunkMap.MarkChunkRegenerating(a_ChunkX, a_ChunkZ);
2646  m_Generator.QueueGenerateChunk({a_ChunkX, a_ChunkZ}, true);
2647 }
2648 
2649 
2650 
2651 
2652 
2653 void cWorld::GenerateChunk(int a_ChunkX, int a_ChunkZ)
2654 {
2655  m_ChunkMap.GenerateChunk(a_ChunkX, a_ChunkZ);
2656 }
2657 
2658 
2659 
2660 
2661 
2662 void cWorld::QueueLightChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_Callback)
2663 {
2664  m_Lighting.QueueChunk(a_ChunkX, a_ChunkZ, std::move(a_Callback));
2665 }
2666 
2667 
2668 
2669 
2670 
2671 bool cWorld::IsChunkLighted(int a_ChunkX, int a_ChunkZ)
2672 {
2673  return m_ChunkMap.IsChunkLighted(a_ChunkX, a_ChunkZ);
2674 }
2675 
2676 
2677 
2678 
2679 
2680 bool cWorld::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback)
2681 {
2682  return m_ChunkMap.ForEachChunkInRect(a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ, a_Callback);
2683 }
2684 
2685 
2686 
2687 
2688 
2689 bool cWorld::ForEachLoadedChunk(cFunctionRef<bool(int, int)> a_Callback)
2690 {
2691  return m_ChunkMap.ForEachLoadedChunk(a_Callback);
2692 }
2693 
2694 
2695 
2696 
2697 
2699 {
2700  if (IsSavingEnabled())
2701  {
2704  }
2705 }
2706 
2707 
2708 
2709 
2710 
2712 {
2713  QueueTask([](cWorld & a_World) { a_World.SaveAllChunks(); });
2714 }
2715 
2716 
2717 
2718 
2719 
2720 void cWorld::QueueTask(std::function<void(cWorld &)> a_Task)
2721 {
2722  cCSLock Lock(m_CSTasks);
2723  m_Tasks.emplace_back(0, std::move(a_Task));
2724 }
2725 
2726 
2727 
2728 
2729 
2730 void cWorld::ScheduleTask(const cTickTime a_DelayTicks, std::function<void (cWorld &)> a_Task)
2731 {
2732  const auto TargetTick = a_DelayTicks + m_WorldAge;
2733 
2734  // Insert the task into the list of scheduled tasks
2735  {
2736  cCSLock Lock(m_CSTasks);
2737  m_Tasks.emplace_back(TargetTick, std::move(a_Task));
2738  }
2739 }
2740 
2741 
2742 
2743 
2744 
2745 void cWorld::AddEntity(OwnedEntity a_Entity, cWorld * a_OldWorld)
2746 {
2747  cCSLock Lock(m_CSEntitiesToAdd);
2748  m_EntitiesToAdd.emplace_back(std::move(a_Entity), a_OldWorld);
2749 }
2750 
2751 
2752 
2753 
2754 
2756 {
2757  // Remove players from the player list:
2758  if (a_Entity.IsPlayer())
2759  {
2760  cLock Lock(*this);
2761  const auto Player = static_cast<cPlayer *>(&a_Entity);
2762  LOGD("Removing player %s from world \"%s\"", Player->GetName().c_str(), m_WorldName.c_str());
2763  m_Players.erase(std::remove(m_Players.begin(), m_Players.end(), Player), m_Players.end());
2764  }
2765 
2766  // Check if the entity is in the chunkmap:
2767  auto Entity = m_ChunkMap.RemoveEntity(a_Entity);
2768  if (Entity != nullptr)
2769  {
2770  Entity->OnRemoveFromWorld(*this);
2771  return Entity;
2772  }
2773 
2774  // Check if the entity is in the queue to be added to the world:
2775  cCSLock Lock(m_CSEntitiesToAdd);
2776  auto itr = std::find_if(m_EntitiesToAdd.begin(), m_EntitiesToAdd.end(),
2777  [&a_Entity](const auto & Item)
2778  {
2779  return (Item.first.get() == &a_Entity);
2780  }
2781  );
2782 
2783  if (itr != m_EntitiesToAdd.end())
2784  {
2785  Entity = std::move(itr->first);
2786  m_EntitiesToAdd.erase(itr);
2787  }
2788 
2789  return Entity;
2790 }
2791 
2792 
2793 
2794 
2795 
2796 size_t cWorld::GetNumChunks(void) const
2797 {
2798  return m_ChunkMap.GetNumChunks();
2799 }
2800 
2801 
2802 
2803 
2804 
2806 {
2808 }
2809 
2810 
2811 
2812 
2813 
2814 void cWorld::GetChunkStats(int & a_NumValid, int & a_NumDirty, int & a_NumInLightingQueue)
2815 {
2816  m_ChunkMap.GetChunkStats(a_NumValid, a_NumDirty);
2817  a_NumInLightingQueue = static_cast<int>(m_Lighting.GetQueueLength());
2818 }
2819 
2820 
2821 
2822 
2823 
2825 {
2826  if (m_BlockTickQueue.empty())
2827  {
2828  return;
2829  }
2830  m_BlockTickQueueCopy.clear();
2832 
2833  for (std::vector<BlockTickQueueItem *>::iterator itr = m_BlockTickQueueCopy.begin(); itr != m_BlockTickQueueCopy.end(); ++itr)
2834  {
2835  BlockTickQueueItem * Block = (*itr);
2836  Block->TicksToWait -= 1;
2837  if (Block->TicksToWait <= 0)
2838  {
2839  // TODO: Handle the case when the chunk is already unloaded
2840  m_ChunkMap.TickBlock({Block->X, Block->Y, Block->Z});
2841  delete Block; // We don't have to remove it from the vector, this will happen automatically on the next tick
2842  }
2843  else
2844  {
2845  m_BlockTickQueue.push_back(Block); // Keep the block in the queue
2846  }
2847  } // for itr - m_BlockTickQueueCopy[]
2848 }
2849 
2850 
2851 
2852 
2853 
2854 void cWorld::QueueBlockForTick(int a_BlockX, int a_BlockY, int a_BlockZ, int a_TicksToWait)
2855 {
2857  Block->X = a_BlockX;
2858  Block->Y = a_BlockY;
2859  Block->Z = a_BlockZ;
2860  Block->TicksToWait = a_TicksToWait;
2861 
2862  m_BlockTickQueue.push_back(Block);
2863 }
2864 
2865 
2866 
2867 
2868 
2869 bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ)
2870 {
2871  return (
2872  IsBlockWater(GetBlock({ a_BlockX - 1, a_BlockY, a_BlockZ })) ||
2873  IsBlockWater(GetBlock({ a_BlockX + 1, a_BlockY, a_BlockZ })) ||
2874  IsBlockWater(GetBlock({ a_BlockX, a_BlockY, a_BlockZ - 1 })) ||
2875  IsBlockWater(GetBlock({ a_BlockX, a_BlockY, a_BlockZ + 1 }))
2876  );
2877 }
2878 
2879 
2880 
2881 
2882 
2883 UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby)
2884 {
2885  auto Monster = cMonster::NewMonsterFromType(a_MonsterType);
2886  if (Monster == nullptr)
2887  {
2888  return cEntity::INVALID_ID;
2889  }
2890  Monster->SetPosition(a_PosX, a_PosY, a_PosZ);
2891 
2892  if (a_Baby)
2893  {
2894  Monster->SetAge(-1);
2895  }
2896 
2897  return SpawnMobFinalize(std::move(Monster));
2898 }
2899 
2900 
2901 
2902 
2903 
2904 UInt32 cWorld::SpawnMobFinalize(std::unique_ptr<cMonster> a_Monster)
2905 {
2906  ASSERT(a_Monster != nullptr);
2907 
2908  // Give the mob full health.
2909  a_Monster->SetHealth(a_Monster->GetMaxHealth());
2910 
2911  // A plugin doesn't agree with the spawn. bail out.
2912  if (cPluginManager::Get()->CallHookSpawningMonster(*this, *a_Monster))
2913  {
2914  return cEntity::INVALID_ID;
2915  }
2916 
2917  auto & Monster = *a_Monster;
2918 
2919  // Initialize the monster into the current world.
2920  if (!Monster.Initialize(std::move(a_Monster), *this))
2921  {
2922  return cEntity::INVALID_ID;
2923  }
2924 
2925  cPluginManager::Get()->CallHookSpawnedMonster(*this, Monster);
2926 
2927  return Monster.GetUniqueID();
2928 }
2929 
2930 
2931 
2932 
2933 
2934 UInt32 cWorld::CreateProjectile(Vector3d a_Pos, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed)
2935 {
2936  auto Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_Pos, a_Item, a_Speed);
2937  if (Projectile == nullptr)
2938  {
2939  return cEntity::INVALID_ID;
2940  }
2941 
2942  auto ProjectilePtr = Projectile.get();
2943  if (!ProjectilePtr->Initialize(std::move(Projectile), *this))
2944  {
2945  return cEntity::INVALID_ID;
2946  }
2947 
2948  return ProjectilePtr->GetUniqueID();
2949 }
2950 
2951 
2952 
2953 
2954 
2955 UInt32 cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed)
2956 {
2957  return CreateProjectile({a_PosX, a_PosY, a_PosZ}, a_Kind, a_Creator, a_Item, a_Speed);
2958 }
2959 
2960 
2961 
2962 
2963 
2965 {
2966  return GetRandomProvider().RandInt(a_Range);
2967 }
2968 
2969 
2970 
2971 
2972 
2973 void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Results)
2974 {
2975  typedef std::pair<AString::size_type, AString> pair_t;
2976  size_t LastSpace = a_Text.find_last_of(" "); // Find the position of the last space
2977  AString LastWord = a_Text.substr(LastSpace + 1, a_Text.length()); // Find the last word
2978 
2979  if (LastWord.empty())
2980  {
2981  return;
2982  }
2983 
2984  std::vector<pair_t> UsernamesByWeight;
2985 
2986  cLock Lock(*this);
2987  for (const auto Player : m_Players)
2988  {
2989  AString PlayerName = Player->HasCustomName() ? Player->GetCustomName() : Player->GetName();
2990 
2991  AString::size_type Found = StrToLower(PlayerName).find(StrToLower(LastWord)); // Try to find last word in playername
2992  if (Found == AString::npos)
2993  {
2994  continue; // No match
2995  }
2996 
2997  UsernamesByWeight.push_back(std::make_pair(Found, PlayerName)); // Match! Store it with the position of the match as a weight
2998  }
2999  Lock.Unlock();
3000 
3001  std::sort(UsernamesByWeight.begin(), UsernamesByWeight.end()); // Sort lexicographically (by the first value, then second), so higher weights (usernames with match closer to start) come first (#1274)
3002 
3003  /* TODO: Uncomment once migrated to C++11
3004  std::transform(
3005  UsernamesByWeight.begin(),
3006  UsernamesByWeight.end(),
3007  std::back_inserter(a_Results),
3008  [](const pair_t & p) { return p.first; }
3009  );
3010  */
3011 
3012  a_Results.reserve(UsernamesByWeight.size());
3013  for (std::vector<pair_t>::const_iterator itr = UsernamesByWeight.begin(); itr != UsernamesByWeight.end(); ++itr)
3014  {
3015  a_Results.push_back(itr->second);
3016  }
3017 }
3018 
3019 
3020 
3021 
3022 
3023 void cWorld::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked)
3024 {
3025  m_ChunkMap.SetChunkAlwaysTicked(a_ChunkX, a_ChunkZ, a_AlwaysTicked);
3026 }
3027 
3028 
3029 
3030 
3031 
3033 {
3034  AString SimulatorName = a_IniFile.GetValueSet("Physics", "RedstoneSimulator", "Incremental");
3035 
3036  if (SimulatorName.empty())
3037  {
3038  LOGWARNING("[Physics] RedstoneSimulator not present or empty in %s, using the default of \"Incremental\".", GetIniFileName().c_str());
3039  SimulatorName = "Incremental";
3040  }
3041 
3042  cRedstoneSimulator * res = nullptr;
3043 
3044  if (NoCaseCompare(SimulatorName, "Incremental") == 0)
3045  {
3046  res = new cIncrementalRedstoneSimulator(*this);
3047  }
3048  else if (NoCaseCompare(SimulatorName, "noop") == 0)
3049  {
3050  res = new cRedstoneNoopSimulator(*this);
3051  }
3052  else
3053  {
3054  LOGWARNING("[Physics] Unknown RedstoneSimulator \"%s\" in %s, using the default of \"Incremental\".", SimulatorName.c_str(), GetIniFileName().c_str());
3055  res = new cIncrementalRedstoneSimulator(*this);
3056  }
3057 
3058  m_SimulatorManager->RegisterSimulator(res, 2 /* Two game ticks is a redstone tick */);
3059 
3060  return res;
3061 }
3062 
3063 
3064 
3065 
3066 
3067 cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const char * a_FluidName, BLOCKTYPE a_SimulateBlock, BLOCKTYPE a_StationaryBlock)
3068 {
3069  AString SimulatorNameKey;
3070  Printf(SimulatorNameKey, "%sSimulator", a_FluidName);
3071  AString SimulatorSectionName;
3072  Printf(SimulatorSectionName, "%sSimulator", a_FluidName);
3073 
3074  bool IsWater = (strcmp(a_FluidName, "Water") == 0); // Used for defaults
3075  AString DefaultSimulatorName = ((GetDimension() == dimNether) && IsWater) ? "Vaporise" : "Vanilla";
3076  AString SimulatorName = a_IniFile.GetValueSet("Physics", SimulatorNameKey, DefaultSimulatorName);
3077  if (SimulatorName.empty())
3078  {
3079  LOGWARNING("[Physics] %s not present or empty in %s, using the default of \"%s\".", SimulatorNameKey.c_str(), GetIniFileName().c_str(), DefaultSimulatorName.c_str());
3080  SimulatorName = DefaultSimulatorName;
3081  }
3082  cFluidSimulator * res = nullptr;
3083  int Rate = 1;
3084  if (
3085  (NoCaseCompare(SimulatorName, "vaporize") == 0) ||
3086  (NoCaseCompare(SimulatorName, "vaporise") == 0)
3087  )
3088  {
3089  res = new cVaporizeFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock);
3090  }
3091  else if (
3092  (NoCaseCompare(SimulatorName, "noop") == 0) ||
3093  (NoCaseCompare(SimulatorName, "nop") == 0) ||
3094  (NoCaseCompare(SimulatorName, "null") == 0) ||
3095  (NoCaseCompare(SimulatorName, "nil") == 0)
3096  )
3097  {
3098  res = new cNoopFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock);
3099  }
3100  else
3101  {
3102  int Falloff = a_IniFile.GetValueSetI(SimulatorSectionName, "Falloff", IsWater ? 1 : 2);
3103  int TickDelay = a_IniFile.GetValueSetI(SimulatorSectionName, "TickDelay", IsWater ? 5 : 30);
3104  int NumNeighborsForSource = a_IniFile.GetValueSetI(SimulatorSectionName, "NumNeighborsForSource", IsWater ? 2 : -1);
3105 
3106  if ((Falloff > 15) || (Falloff < 0))
3107  {
3108  LOGWARNING("Falloff for %s simulator is out of range, assuming default of %d", a_FluidName, IsWater ? 1 : 2);
3109  Falloff = IsWater ? 1 : 2;
3110  }
3111 
3112  if (NoCaseCompare(SimulatorName, "floody") == 0)
3113  {
3114  res = new cFloodyFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast<NIBBLETYPE>(Falloff), TickDelay, NumNeighborsForSource);
3115  }
3116  else if (NoCaseCompare(SimulatorName, "vanilla") == 0)
3117  {
3118  res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast<NIBBLETYPE>(Falloff), TickDelay, NumNeighborsForSource);
3119  }
3120  else
3121  {
3122  // The simulator name doesn't match anything we have, issue a warning:
3123  LOGWARNING("%s [Physics]:%s specifies an unknown simulator, using the default \"Vanilla\".", GetIniFileName().c_str(), SimulatorNameKey.c_str());
3124  res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast<NIBBLETYPE>(Falloff), TickDelay, NumNeighborsForSource);
3125  }
3126  }
3127 
3128  m_SimulatorManager->RegisterSimulator(res, Rate);
3129 
3130  return res;
3131 }
3132 
3133 
3134 
3135 
3136 
3138 // cWorld::cChunkGeneratorCallbacks:
3139 
3141  m_World(&a_World)
3142 {
3143 }
3144 
3145 
3146 
3147 
3148 
3150 {
3151  cChunkDef::BlockNibbles BlockMetas;
3152  a_ChunkDesc.CompressBlockMetas(BlockMetas);
3153 
3154  struct SetChunkData Data({ a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ() });
3155  {
3156  Data.BlockData.SetAll(a_ChunkDesc.GetBlockTypes(), BlockMetas);
3157 
3158  std::copy(a_ChunkDesc.GetBiomeMap(), a_ChunkDesc.GetBiomeMap() + std::size(a_ChunkDesc.GetBiomeMap()), Data.BiomeMap);
3159  std::copy(a_ChunkDesc.GetHeightMap(), a_ChunkDesc.GetHeightMap() + std::size(a_ChunkDesc.GetHeightMap()), Data.HeightMap);
3160 
3161  Data.Entities = std::move(a_ChunkDesc.GetEntities());
3162  Data.BlockEntities = std::move(a_ChunkDesc.GetBlockEntities());
3163 
3164  Data.IsLightValid = false;
3165  }
3166 
3167  m_World->QueueSetChunkData(std::move(Data));
3168 }
3169 
3170 
3171 
3172 
3173 
3175 {
3176  return m_World->IsChunkValid(a_Coords.m_ChunkX, a_Coords.m_ChunkZ);
3177 }
3178 
3179 
3180 
3181 
3182 
3184 {
3185  return m_World->IsChunkQueued(a_Coords.m_ChunkX, a_Coords.m_ChunkZ);
3186 }
3187 
3188 
3189 
3190 
3191 
3193 {
3194  return m_World->HasChunkAnyClients(a_Coords.m_ChunkX, a_Coords.m_ChunkZ);
3195 }
3196 
3197 
3198 
3199 
3200 
3202 {
3204  *m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
3205  );
3206 }
3207 
3208 
3209 
3210 
3211 
3213 {
3215  *m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc
3216  );
3217 }
FloorC
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:344
cCommandBlockEntity
Definition: CommandBlockEntity.h:20
cChunkMap::ForEachBlockEntityInChunk
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:1064
IncrementalRedstoneSimulator.h
cChunkGeneratorThread::Stop
void Stop(void)
Definition: ChunkGeneratorThread.cpp:59
cWorld::GetIniFileName
const AString & GetIniFileName(void) const
Returns the name of the world.ini file used by this world.
Definition: World.h:697
cWorldStorage::Initialize
void Initialize(cWorld &a_World, const AString &a_StorageSchemaName, int a_StorageCompressionFactor)
Initializes the storage schemas, ready to be started.
Definition: WorldStorage.cpp:63
cChunkMap::SetChunkAlwaysTicked
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:1464
cChunkMap::TryGetHeight
bool TryGetHeight(int a_BlockX, int a_BlockZ, int &a_Height)
Definition: ChunkMap.cpp:406
cWorld::cChunkGeneratorCallbacks::IsChunkValid
virtual bool IsChunkValid(cChunkCoords a_Coords) override
Called just before the chunk generation is started, to verify that it hasn't been generated in the me...
Definition: World.cpp:3174
cChunkMap::MarkChunkRegenerating
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:1141
cWorld::RemoveClientFromChunks
void RemoveClientFromChunks(cClientHandle *a_Client)
Removes the client from all chunks it is present in.
Definition: World.cpp:2500
eShrapnelLevel
eShrapnelLevel
Definition: Defines.h:326
cClientHandle
Definition: ClientHandle.h:49
cWorld::m_WorldAge
std::chrono::milliseconds m_WorldAge
The age of the world.
Definition: World.h:983
cWorld::m_BlockTickQueue
std::vector< BlockTickQueueItem * > m_BlockTickQueue
Definition: World.h:1008
eWeather_Sunny
@ eWeather_Sunny
Definition: Defines.h:161
cWorld::BroadcastWeather
virtual void BroadcastWeather(eWeather a_Weather, const cClientHandle *a_Exclude=nullptr) override
Definition: Broadcaster.cpp:621
cChunkDesc
Definition: ChunkDesc.h:27
cDeadlockDetect::UntrackCriticalSection
void UntrackCriticalSection(cCriticalSection &a_CS)
Removes the CS from the tracking.
Definition: DeadlockDetect.cpp:82
cForEachChunkProvider
Definition: ForEachChunkProvider.h:24
cMapManager::SaveMapData
void SaveMapData(void)
Saves the map data to the disk.
Definition: MapManager.cpp:129
cNoise
Definition: Noise.h:19
cWorld::SpawnMobFinalize
UInt32 SpawnMobFinalize(std::unique_ptr< cMonster > a_Monster)
Wraps cEntity::Initialize, doing Monster-specific things before spawning the monster.
Definition: World.cpp:2904
BlockHandler.h
cWorld::m_bCommandBlocksEnabled
bool m_bCommandBlocksEnabled
Whether command blocks are enabled or not.
Definition: World.h:1056
cRedstoneSimulator
Definition: RedstoneSimulator.h:23
cWorld::GetChunkStats
void GetChunkStats(int &a_NumValid, int &a_NumDirty, int &a_NumInLightingQueue)
Returns the number of chunks loaded and dirty, and in the lighting queue.
Definition: World.cpp:2814
cChunkDef::Width
static const int Width
Definition: ChunkDef.h:107
E_ITEM_FURNACE_MINECART
@ E_ITEM_FURNACE_MINECART
Definition: BlockType.h:388
cUUID
Definition: UUID.h:10
cWorld::IsBlockDirectlyWatered
bool IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ)
Definition: World.cpp:2869
cCuboid::p2
Vector3i p2
Definition: Cuboid.h:13
FastRandom.h
SandSimulator.h
Vector3::x
T x
Definition: Vector3.h:17
sSetBlockVector
std::vector< sSetBlock > sSetBlockVector
Definition: ChunkDef.h:424
cEntity::IsPlayer
bool IsPlayer(void) const
Definition: Entity.h:160
cRandomWrapper::RandInt
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
cChunkMap::AddChunkClient
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:873
cWorld::GenerateRandomSpawn
void GenerateRandomSpawn(int a_MaxSpawnRadius)
Generates a random spawnpoint on solid land by walking chunks and finding their biomes.
Definition: World.cpp:700
cIniFile::GetValueSetI
int GetValueSetI(const AString &keyname, const AString &valuename, const int defValue=0) override
Definition: IniFile.cpp:558
E_BLOCK_WATER
@ E_BLOCK_WATER
Definition: BlockType.h:18
cWorld::m_EntitiesToAdd
std::vector< std::pair< OwnedEntity, cWorld * > > m_EntitiesToAdd
List of entities that are scheduled for adding, waiting for the Tick thread to add them.
Definition: World.h:1100
cChunkMap::SetBlockMeta
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta)
Sets the meta for the specified block, while keeping the blocktype.
Definition: ChunkMap.cpp:551
Vector3i
Vector3< int > Vector3i
Definition: Vector3.h:487
cChunkDef
Constants used throughout the code, useful typedefs and utility functions.
Definition: ChunkDef.h:102
IncludeAllMonsters.h
cLineBlockTracer::losAirWater
@ losAirWater
Definition: LineBlockTracer.h:41
NoopFluidSimulator.h
eExplosionSource
eExplosionSource
The source of an explosion.
Definition: Defines.h:308
cWorld::GetNumUnusedDirtyChunks
size_t GetNumUnusedDirtyChunks(void) const
Returns the number of unused dirty chunks.
Definition: World.cpp:2805
cWorld::CastThunderbolt
void CastThunderbolt(Vector3i a_Block)
Casts a thunderbolt at the specified coords.
Definition: World.cpp:470
cWorld::SpawnSplitExperienceOrbs
virtual std::vector< UInt32 > SpawnSplitExperienceOrbs(Vector3d a_Pos, int a_Reward) override
Spawns experience orbs of the specified total value at the given location.
Definition: World.cpp:1901
SpawnPrepare.h
cWorld::PlaceBlock
void PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta)
Replaces the specified block with another, and calls the OnPlaced block handler.
Definition: World.cpp:2029
cWorld::m_FireSimulator
std::unique_ptr< cFireSimulator > m_FireSimulator
Definition: World.h:1015
Trees.h
cWorld::QueueLightChunk
void QueueLightChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_Callback={})
Queues a chunk for lighting; a_Callback is called after the chunk is lighted.
Definition: World.cpp:2662
cFloodyFluidSimulator
Definition: FloodyFluidSimulator.h:19
E_META_SAPLING_CONIFER
@ E_META_SAPLING_CONIFER
Definition: BlockType.h:815
cWorld::SpawnEnderCrystal
UInt32 SpawnEnderCrystal(Vector3d a_Pos, bool a_ShowBottom)
Spawns a new ender crystal at the specified block coords.
Definition: World.cpp:2014
cWorld::m_MaxRainTicks
int m_MaxRainTicks
Definition: World.h:1033
cChunkDesc::GetChunkZ
int GetChunkZ() const
Definition: ChunkDesc.h:50
cWorld::ForEachEntity
bool ForEachEntity(cEntityCallback a_Callback)
Calls the callback for each entity in the entire world; returns true if all entities processed,...
Definition: World.cpp:2413
cWorld::m_AllowedMobs
std::set< eMonsterType > m_AllowedMobs
Definition: World.h:1028
cWorld::ChunkLoadFailed
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
Marks the chunk as failed-to-load:
Definition: World.cpp:2537
cRedstoneNoopSimulator
Definition: NoopRedstoneSimulator.h:10
E_META_SAPLING_ACACIA
@ E_META_SAPLING_ACACIA
Definition: BlockType.h:818
cChunkMap::SetAreaBiome
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:697
EnderCrystal.h
cChunkMap::HasChunkAnyClients
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const
Definition: ChunkMap.cpp:372
cWorld::m_Players
std::vector< cPlayer * > m_Players
Definition: World.h:1019
cWorld::CollectPickupsByEntity
void CollectPickupsByEntity(cEntity &a_Entity)
Definition: World.cpp:2243
E_BLOCK_TRAPDOOR
@ E_BLOCK_TRAPDOOR
Definition: BlockType.h:111
MobCensus.h
cChunkMap::GetBlockInfo
bool GetBlockInfo(Vector3i, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_Meta, NIBBLETYPE &a_SkyLight, NIBBLETYPE &a_BlockLight) const
Definition: ChunkMap.cpp:605
cIncrementalRedstoneSimulator
Definition: IncrementalRedstoneSimulator.h:10
cChunkMap::GetNumUnusedDirtyChunks
size_t GetNumUnusedDirtyChunks(void) const
Returns the number of unused dirty chunks.
Definition: ChunkMap.cpp:1437
cWorld::BlockTickQueueItem
Definition: World.h:785
cWorld::m_GameMode
eGameMode m_GameMode
Definition: World.h:1001
UUID.h
cWorld::cTickThread::Execute
virtual void Execute(void) override
This function, overloaded by the descendants, is called in the new thread.
Definition: World.cpp:108
cWorld::ForEachChunkInRect
virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback &a_Callback) override
Calls the callback for each chunk in the coords specified (all cords are inclusive).
Definition: World.cpp:2680
cChunkMap::WakeUpSimulators
void WakeUpSimulators(Vector3i a_Block)
Wakes up simulators for the specified block.
Definition: ChunkMap.cpp:153
cWorld::GetSignLines
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's no sign at those coo...
Definition: World.cpp:1415
E_META_SAPLING_BIRCH
@ E_META_SAPLING_BIRCH
Definition: BlockType.h:816
cPluginManager::CallHookChunkGenerated
bool CallHookChunkGenerated(cWorld &a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc *a_ChunkDesc)
Definition: PluginManager.cpp:390
cWorld::QueueSaveAllChunks
void QueueSaveAllChunks(void)
Queues a task to save all chunks onto the tick thread.
Definition: World.cpp:2711
cWorld::GetTickRandomNumber
int GetTickRandomNumber(int a_Range)
Returns a random number in range [0 .
Definition: World.cpp:2964
cChunkMap::MarkChunkSaving
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:185
cPluginManager::CallHookUpdatedSign
bool CallHookUpdatedSign(cWorld &a_World, Vector3i a_BlockPos, const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4, cPlayer *a_Player)
Definition: PluginManager.cpp:1191
FallingBlock.h
cWorld::m_IsDeepSnowEnabled
bool m_IsDeepSnowEnabled
Definition: World.h:1004
cChunkSender
Definition: ChunkSender.h:50
cChunkMap::SetNextBlockToTick
void SetNextBlockToTick(const Vector3i a_BlockPos)
Causes the specified block to be ticked on the next Tick() call.
Definition: ChunkMap.cpp:1290
cBoundingBox
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:23
World::GetFECProvider
cForEachChunkProvider * GetFECProvider(cWorld *a_World)
Definition: World.cpp:70
cWorld::Stop
void Stop(cDeadlockDetect &a_DeadlockDetect)
Stops threads that belong to this world (part of deinit).
Definition: World.cpp:956
cWorld::m_SpawnZ
int m_SpawnZ
Definition: World.h:967
OpaqueWorld.h
SignEntity.h
esEnderCrystal
@ esEnderCrystal
Definition: Defines.h:311
OwnedEntity
std::unique_ptr< cEntity > OwnedEntity
Definition: ChunkDef.h:32
cWorld::m_SkyDarkness
NIBBLETYPE m_SkyDarkness
Definition: World.h:999
cWorld::SetAreaBiome
bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome)
Sets the biome at the area.
Definition: World.cpp:1698
Server.h
cWorld::InitializeRedstoneSimulator
cRedstoneSimulator * InitializeRedstoneSimulator(cIniFile &a_IniFile)
Creates a new redstone simulator.
Definition: World.cpp:3032
cWorld::m_TNTShrapnelLevel
eShrapnelLevel m_TNTShrapnelLevel
The level of DoExplosionAt() projecting random affected blocks as FallingBlock entities See the eShra...
Definition: World.h:1064
StrToLower
AString StrToLower(const AString &s)
Returns a lower-cased copy of the string.
Definition: StringUtils.cpp:280
cWorld::m_IniFileName
AString m_IniFileName
Definition: World.h:951
LineBlockTracer.h
cChunkMap::GetChunkStats
void GetChunkStats(int &a_NumChunksValid, int &a_NumChunksDirty) const
Returns the number of valid chunks and the number of dirty chunks.
Definition: ChunkMap.cpp:1254
cWorld::InitializeAndLoadMobSpawningValues
void InitializeAndLoadMobSpawningValues(cIniFile &a_IniFile)
Sets mob spawning values if nonexistant to their dimension specific defaults.
Definition: World.cpp:917
MobSpawner.h
cWorld::GetWorldAge
virtual cTickTimeLong GetWorldAge(void) const override
Definition: World.cpp:491
cWorld::IsChunkQueued
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const
Returns true iff the chunk is in the loader / generator queue.
Definition: World.cpp:2197
cWorld::GetDefaultWeatherInterval
int GetDefaultWeatherInterval(eWeather a_Weather) const
Returns the default weather interval for the specific weather type.
Definition: World.cpp:531
cWorld::m_MinSunnyTicks
int m_MinSunnyTicks
Definition: World.h:1032
cWorld::CanSpawnAt
bool CanSpawnAt(int a_X, int &a_Y, int a_Z)
Can the specified coordinates be used as a spawn point? Returns true if spawn position is valid and s...
Definition: World.cpp:782
cWorld::SendBlockTo
virtual void SendBlockTo(int a_X, int a_Y, int a_Z, const cPlayer &a_Player) override
Sends the block at the specified coords to the player.
Definition: World.cpp:2100
cWorld::BroadcastSoundParticleEffect
virtual void BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle *a_Exclude=nullptr) override
Definition: Broadcaster.cpp:556
E_BLOCK_COMMAND_BLOCK
@ E_BLOCK_COMMAND_BLOCK
Definition: BlockType.h:152
E_BLOCK_SAND
@ E_BLOCK_SAND
Definition: BlockType.h:22
cWorld::SpawnMob
virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby=false) override
Spawns a mob of the specified type.
Definition: World.cpp:2883
cChunkMap::IsChunkQueued
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const
Returns true iff the chunk is in the loader / generator queue.
Definition: ChunkMap.cpp:293
cProjectileEntity::Create
static std::unique_ptr< cProjectileEntity > Create(eKind a_Kind, cEntity *a_Creator, Vector3d a_Pos, const cItem *a_Item, const Vector3d *a_Speed=nullptr)
Creates a new instance of the specified projectile entity.
Definition: ProjectileEntity.cpp:252
cWorld::AddChunkClient
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: World.cpp:2482
Explodinator.h
gmSpectator
@ gmSpectator
Definition: Defines.h:137
cFluidSimulator
Definition: FluidSimulator.h:37
cChunkDesc::GetHeightMap
cChunkDef::HeightMap & GetHeightMap(void)
Definition: ChunkDesc.h:221
World
Utilities to allow casting a cWorld to one of its interfaces without including World....
Definition: OpaqueWorld.h:12
cWorld::TickQueuedBlocks
void TickQueuedBlocks(void)
Processes the blocks queued for ticking with a delay (m_BlockTickQueue[])
Definition: World.cpp:2824
cWorld::SetBlockMeta
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData)
Sets the meta for the specified block, while keeping the blocktype.
Definition: World.cpp:1738
cWorld::GetTimeOfDay
virtual cTickTime GetTimeOfDay(void) const override
Definition: World.cpp:480
cWorld::TickWeather
void TickWeather(float a_Dt)
Handles the weather in each tick.
Definition: World.cpp:1075
cWorld::DoExplosionAt
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void *a_SourceData) override
Does an explosion with the specified strength at the specified coordinates.
Definition: World.cpp:1371
cClientHandle::DEFAULT_VIEW_DISTANCE
static const int DEFAULT_VIEW_DISTANCE
Definition: ClientHandle.h:57
cWorld::SetChunkAlwaysTicked
void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked=true)
Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter for the specifie...
Definition: World.cpp:3023
cIsThread
Definition: IsThread.h:23
cRandomWrapper::RandBool
bool RandBool(double a_TrueProbability=0.5)
Return a random bool with the given probability of being true.
Definition: FastRandom.h:158
cWorld::IsSavingEnabled
bool IsSavingEnabled(void) const
Get whether saving chunks is enabled.
Definition: World.h:81
mtInvalidType
@ mtInvalidType
Definition: MonsterTypes.h:12
dimNotSet
@ dimNotSet
Definition: Defines.h:235
cWorld::m_BlockTickQueueCopy
std::vector< BlockTickQueueItem * > m_BlockTickQueueCopy
Definition: World.h:1009
cMobCensus
This class is used to collect information, for each Mob, what is the distance of the closest player i...
Definition: MobCensus.h:25
cSignEntity
Definition: SignEntity.h:19
cWorld::m_CSTasks
cCriticalSection m_CSTasks
Guards the m_Tasks.
Definition: World.h:1091
cWorld::m_MaxNetherPortalHeight
int m_MaxNetherPortalHeight
Definition: World.h:973
cChunkDesc::GetBlockEntities
cBlockEntities & GetBlockEntities(void)
Definition: ChunkDesc.h:223
cChunkMap::SpawnMobs
void SpawnMobs(cMobSpawner &a_MobSpawner)
Try to Spawn Monsters inside all Chunks.
Definition: ChunkMap.cpp:1326
BlockType::Spawner
@ Spawner
cWorld::WakeUpSimulators
virtual void WakeUpSimulators(Vector3i a_Block) override
Wakes up the simulators for the specified block.
Definition: World.cpp:1344
VaporizeFluidSimulator.h
cChunkSender::QueueSendChunkTo
void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, cClientHandle *a_Client)
Queues a chunk to be sent to a specific client.
Definition: ChunkSender.cpp:92
cChunkMap::IsChunkLighted
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:1151
cVanillaFluidSimulator
Definition: VanillaFluidSimulator.h:16
cWorld::GetPlayerCount
size_t GetPlayerCount() const
Returns the number of players currently in this world.
Definition: World.cpp:2440
cWorld::~cWorld
virtual ~cWorld() override
Definition: World.cpp:449
cWorld::m_bAnimals
bool m_bAnimals
Definition: World.h:1027
gmSurvival
@ gmSurvival
Definition: Defines.h:134
World::GetBroadcastInterface
cBroadcastInterface * GetBroadcastInterface(cWorld *a_World)
Definition: World.cpp:69
cWorldInterface
Definition: WorldInterface.h:19
cBoat::eMaterial
eMaterial
Definition: Boat.h:28
cWorld::SpawnPrimedTNT
UInt32 SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec=80, double a_InitialVelocityCoeff=1, bool a_ShouldPlayFuseSound=true)
Definition: World.h:519
cNoopFluidSimulator
Definition: NoopFluidSimulator.h:18
Pickup.h
cIniFile::SetValueI
bool SetValueI(const AString &a_KeyName, const AString &a_ValueName, const int a_Value, const bool a_CreateIfNotExists=true) override
Definition: IniFile.cpp:441
cWorld::m_VillagersShouldHarvestCrops
bool m_VillagersShouldHarvestCrops
Definition: World.h:1006
IsValidItem
bool IsValidItem(int a_ItemType)
Returns true if the specified item type is valid (known).
Definition: Defines.cpp:172
cWorld::cChunkGeneratorCallbacks::cChunkGeneratorCallbacks
cChunkGeneratorCallbacks(cWorld &a_World)
Definition: World.cpp:3140
Globals.h
FLOGD
#define FLOGD
Definition: LoggerSimple.h:91
Item
Item
Definition: Items.h:3
cWorld::GrowPlantAt
int GrowPlantAt(Vector3i a_BlockPos, int a_NumStages=1)
Grows the plant at the specified position by at most a_NumStages.
Definition: World.cpp:1662
TNTEntity.h
cWorld::SendPlayerList
void SendPlayerList(cPlayer *a_DestPlayer)
Definition: World.cpp:2396
NoCaseCompare
int NoCaseCompare(const AString &s1, const AString &s2)
Case-insensitive string comparison.
Definition: StringUtils.cpp:304
UInt32
unsigned int UInt32
Definition: Globals.h:154
cIniFile::AddHeaderComment
void AddHeaderComment(const AString &comment)
Adds a header comment.
Definition: IniFile.cpp:675
cWorld::BroadcastTimeUpdate
virtual void BroadcastTimeUpdate(const cClientHandle *a_Exclude=nullptr) override
Definition: Broadcaster.cpp:595
cChunkMap::CollectPickupsByEntity
void CollectPickupsByEntity(cEntity &a_Entity)
Makes the specified entity collect all the pickups around them.
Definition: ChunkMap.cpp:442
cClientHandle::SendPlayerListAddPlayer
void SendPlayerListAddPlayer(const cPlayer &a_Player)
Definition: ClientHandle.cpp:2804
E_BLOCK_WALLSIGN
@ E_BLOCK_WALLSIGN
Definition: BlockType.h:82
cPluginManager::CallHookWeatherChanged
bool CallHookWeatherChanged(cWorld &a_World)
Definition: PluginManager.cpp:1204
Vector3::addedXZ
Vector3< T > addedXZ(T a_AddX, T a_AddZ) const
Returns a copy of this vector moved by the specified amount on the X and Z axes.
Definition: Vector3.h:326
cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients
virtual bool HasChunkAnyClients(cChunkCoords a_Coords) override
Called when the generator is overloaded to skip chunks that are no longer needed.
Definition: World.cpp:3192
dimNether
@ dimNether
Definition: Defines.h:232
cChunkMap::GetNumChunks
size_t GetNumChunks(void) const
Definition: ChunkMap.cpp:1427
cChunkCoords::m_ChunkX
int m_ChunkX
Definition: ChunkDef.h:58
cWorld::RegenerateChunk
void RegenerateChunk(int a_ChunkX, int a_ChunkZ)
Regenerate the given chunk.
Definition: World.cpp:2643
cWorld::PickupsFromBlock
cItems PickupsFromBlock(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Returns all the pickups that would result if the a_Digger dug up the block at a_BlockPos using a_Tool...
Definition: World.cpp:2091
cMapManager::TickMaps
void TickMaps(void)
Ticks each registered map.
Definition: MapManager.cpp:45
cChunkDef::BlockToChunk
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:193
cWorld::WriteBlockArea
virtual bool WriteBlockArea(cBlockArea &a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override
Writes the block area into the specified coords.
Definition: World.cpp:1783
cChunkMap::GrowPlantAt
int GrowPlantAt(Vector3i a_BlockPos, int a_NumStages=1)
Grows the plant at the specified position by at most a_NumStages.
Definition: ChunkMap.cpp:1273
CASE_TREE_ALLOWED_BLOCKS
#define CASE_TREE_ALLOWED_BLOCKS
Definition: Trees.h:27
esMonster
@ esMonster
Definition: Defines.h:313
VanillaFluidSimulator.h
cWorld::m_SimulatorManager
std::unique_ptr< cSimulatorManager > m_SimulatorManager
Definition: World.h:1011
StringToDimension
eDimension StringToDimension(const AString &a_DimensionString)
Translates a dimension string to dimension enum.
Definition: Defines.cpp:194
BlockInfo.h
cWorld::m_MaxPlayers
unsigned int m_MaxPlayers
Definition: World.h:1023
cWorld::GetWorldTickAge
cTickTimeLong GetWorldTickAge() const
Definition: World.cpp:509
cWorld::IsChunkValid
bool IsChunkValid(int a_ChunkX, int a_ChunkZ) const
Returns true iff the chunk is present and valid.
Definition: World.cpp:2206
ASSERT
#define ASSERT(x)
Definition: Globals.h:273
E_BLOCK_SIGN_POST
@ E_BLOCK_SIGN_POST
Definition: BlockType.h:76
NIBBLETYPE
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
cChunkMap::CompareChunkClients
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:822
cMonster::mfPassive
@ mfPassive
Definition: Monster.h:31
cWorld::m_WorldDate
std::chrono::milliseconds m_WorldDate
The fully controllable age of the world.
Definition: World.h:988
cIniFile::FindKey
int FindKey(const AString &keyname) const
Returns index of specified key, or noID if not found.
Definition: IniFile.cpp:239
cWorld::cTickThread::cTickThread
cTickThread(cWorld &a_World)
Definition: World.cpp:98
cWorld::SetMaxViewDistance
void SetMaxViewDistance(int a_MaxViewDistance)
Definition: World.cpp:1720
cWorld::ChooseNewWeather
eWeather ChooseNewWeather(void)
Chooses a reasonable transition from the current weather to a new weather.
Definition: World.cpp:894
esWitherBirth
@ esWitherBirth
Definition: Defines.h:317
cWorld::m_SpawnY
int m_SpawnY
Definition: World.h:966
E_BLOCK_SNOW_BLOCK
@ E_BLOCK_SNOW_BLOCK
Definition: BlockType.h:94
eGameMode
eGameMode
Definition: Defines.h:124
cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerating
virtual void CallHookChunkGenerating(cChunkDesc &a_ChunkDesc) override
Called when the chunk is about to be generated.
Definition: World.cpp:3201
cLightingThread::QueueChunk
void QueueChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallbackAfter)
Queues the entire chunk for lighting.
Definition: LightingThread.cpp:150
cPluginManager::CallHookEntityChangedWorld
bool CallHookEntityChangedWorld(cEntity &a_Entity, cWorld &a_World)
Definition: PluginManager.cpp:520
cWorld::SendChunkTo
void SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle *a_Client)
Sends the chunk to the client specified, if the client doesn't have the chunk yet.
Definition: World.cpp:2509
Vector3::z
T z
Definition: Vector3.h:17
cBlockArea
Definition: BlockArea.h:37
cChunkMap::IsWeatherSunnyAt
bool IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const
Definition: ChunkMap.cpp:304
cWorld::m_BroadcastDeathMessages
bool m_BroadcastDeathMessages
Definition: World.h:975
cWorld::GetDimension
virtual eDimension GetDimension(void) const override
Definition: World.h:133
cMonster::GetSpawnDelay
static cTickTime GetSpawnDelay(cMonster::eFamily a_MobFamily)
Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family.
Definition: Monster.cpp:1180
LOGD
#define LOGD
Definition: LoggerSimple.h:83
cChunkDesc::GetEntities
cEntityList & GetEntities(void)
Definition: ChunkDesc.h:222
cRoot::Get
static cRoot * Get()
Definition: Root.h:52
cWorld::m_bUseChatPrefixes
bool m_bUseChatPrefixes
Whether prefixes such as [INFO] are prepended to SendMessageXXX() / BroadcastChatXXX() functions.
Definition: World.h:1059
cWorld::cChunkGeneratorCallbacks::IsChunkQueued
virtual bool IsChunkQueued(cChunkCoords a_Coords) override
Called to check whether the specified chunk is in the queued state.
Definition: World.cpp:3183
cWorld::m_MaxNetherPortalWidth
int m_MaxNetherPortalWidth
Definition: World.h:971
cClientHandle::MIN_VIEW_DISTANCE
static const int MIN_VIEW_DISTANCE
Definition: ClientHandle.h:60
cBlockHandler::For
static const cBlockHandler & For(BLOCKTYPE a_BlockType)
Definition: BlockHandler.cpp:631
cWorld::m_bEnabledPVP
bool m_bEnabledPVP
Definition: World.h:1002
DeadlockDetect.h
slAll
@ slAll
Definition: Defines.h:330
E_BLOCK_LOG
@ E_BLOCK_LOG
Definition: BlockType.h:27
cChunkDesc::GetBiomeMap
cChunkDef::BiomeMap & GetBiomeMap(void)
Definition: ChunkDesc.h:216
cWorld::GetChunkData
bool GetChunkData(cChunkCoords a_Coords, cChunkDataCallback &a_Callback) const
Calls the callback with the chunk's data, if available (with ChunkCS locked).
Definition: World.cpp:2188
IniFile.h
cWorld::m_bFarmlandTramplingEnabled
bool m_bFarmlandTramplingEnabled
Definition: World.h:1003
cChunkMap::AddEntity
void AddEntity(OwnedEntity a_Entity)
Adds the entity to its appropriate chunk, takes ownership of the entity pointer.
Definition: ChunkMap.cpp:908
cChunkMap::ChunkLighted
void ChunkLighted(int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles &a_BlockLight, const cChunkDef::BlockNibbles &a_SkyLight)
Definition: ChunkMap.cpp:251
Root.h
cWorld::m_StorageCompressionFactor
int m_StorageCompressionFactor
Definition: World.h:956
cWorld::m_WaterSimulator
cFluidSimulator * m_WaterSimulator
Definition: World.h:1013
cWorld::GetLinkedOverworldName
AString GetLinkedOverworldName(void) const
Definition: World.h:727
cWorld::m_LastChunkCheck
std::chrono::milliseconds m_LastChunkCheck
Definition: World.h:995
IsWater
static bool IsWater(BLOCKTYPE a_BlockType)
Definition: FinishGen.cpp:36
cChunkMap::WriteBlockArea
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:1216
cChunkInterface
Definition: ChunkInterface.h:21
cWorld::TickQueuedTasks
void TickQueuedTasks(void)
Executes all tasks queued onto the tick thread.
Definition: World.cpp:1276
cWorld::m_IsDaylightCycleEnabled
bool m_IsDaylightCycleEnabled
Definition: World.h:978
cWorld::m_RedstoneSimulator
cRedstoneSimulator * m_RedstoneSimulator
Definition: World.h:1016
cWorld::BroadcastSoundEffect
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override
Definition: Broadcaster.cpp:543
cWorld::m_GeneratorCallbacks
cChunkGeneratorCallbacks m_GeneratorCallbacks
The callbacks that the ChunkGenerator uses to store new chunks and interface to plugins.
Definition: World.h:1084
cWorld::GenerateChunk
void GenerateChunk(int a_ChunkX, int a_ChunkZ)
Generates the given chunk.
Definition: World.cpp:2653
cWorld::BroadcastPlayerListUpdatePing
virtual void BroadcastPlayerListUpdatePing() override
Definition: Broadcaster.cpp:491
cWorld::CompareChunkClients
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: World.cpp:2473
cWorld::MarkChunkDirty
void MarkChunkDirty(int a_ChunkX, int a_ChunkZ)
Definition: World.cpp:2136
cWorld::m_WeatherInterval
int m_WeatherInterval
Definition: World.h:1031
cWorldStorage::Stop
void Stop(void)
Definition: WorldStorage.cpp:74
cChunkMap::GetBiomeAt
EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ) const
Returns the biome at the specified coords.
Definition: ChunkMap.cpp:660
cSimulatorManager::Simulate
void Simulate(float a_Dt)
Called in each tick, a_Dt is the time passed since the last tick, in msec.
Definition: SimulatorManager.cpp:31
cIsThread::Start
void Start(void)
Starts the thread; returns without waiting for the actual start.
Definition: IsThread.cpp:35
eWeather_Rain
@ eWeather_Rain
Definition: Defines.h:162
cWorld::SetWeather
void SetWeather(eWeather a_NewWeather)
Sets the specified weather; resets weather interval; asks and notifies plugins of the change.
Definition: World.cpp:556
ARRAYCOUNT
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:228
cChunkMap::ForEachEntityInChunk
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:999
eMonsterType
eMonsterType
Identifies individual monster type.
Definition: MonsterTypes.h:10
cChunkDesc::GetBlockTypes
cChunkDef::BlockTypes & GetBlockTypes(void)
Definition: ChunkDesc.h:217
cWorld::m_DataPath
AString m_DataPath
The path to the root directory for the world files.
Definition: World.h:945
E_META_SAPLING_DARK_OAK
@ E_META_SAPLING_DARK_OAK
Definition: BlockType.h:819
cChunkMap::IsWeatherWetAt
bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) const
Definition: ChunkMap.cpp:323
cChunkGeneratorThread::Initialize
bool Initialize(cPluginInterface &a_PluginInterface, cChunkSink &a_ChunkSink, cIniFile &a_IniFile)
Read settings from the ini file and initialize in preperation for being started.
Definition: ChunkGeneratorThread.cpp:41
cWorld
Definition: World.h:47
cChunkMap::GetBlockTypeMeta
bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Definition: ChunkMap.cpp:586
cWorld::ChangeWeather
void ChangeWeather(void)
Forces a weather change in the next game tick.
Definition: World.cpp:585
biOcean
@ biOcean
Definition: BiomeDef.h:22
Clamp
T Clamp(T a_Value, T a_Min, T a_Max)
Clamp X to the specified range.
Definition: Globals.h:333
cWorld::Start
void Start()
Starts threads that belong to this world.
Definition: World.cpp:687
BlockType
BlockType
Definition: BlockTypes.h:3
cChunkMap::TickBlock
void TickBlock(const Vector3i a_BlockPos)
Ticks a single block.
Definition: ChunkMap.cpp:1364
cWorld::PrepareChunk
void PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallAfter={})
Queues the chunk for preparing - making sure that it's generated and lit.
Definition: World.cpp:2528
cWorld::m_Dimension
eDimension m_Dimension
The dimension of the world, used by the client to provide correct lighting scheme.
Definition: World.h:962
cWorld::m_SandSimulator
std::unique_ptr< cSandSimulator > m_SandSimulator
Definition: World.h:1012
cWorld::UnloadUnusedChunks
void UnloadUnusedChunks(void)
Unloads all chunks immediately.
Definition: World.cpp:2224
cChunkMap::GetBlocks
bool GetBlocks(sSetBlockVector &a_Blocks, bool a_ContinueOnFailure)
Retrieves block types and metas of the specified blocks.
Definition: ChunkMap.cpp:735
cWorld::SpawnExperienceOrb
UInt32 SpawnExperienceOrb(Vector3d a_Pos, int a_Reward)
Spawns an experience orb at the given location with the given reward.
Definition: World.cpp:1880
cClientDiffCallback
Interface class used for comparing clients of two chunks.
Definition: ChunkDef.h:352
cIniFile::GetValueSet
AString GetValueSet(const AString &keyname, const AString &valuename, const AString &defValue="") override
Gets the value; if not found, write the default to the repository.
Definition: IniFile.cpp:524
cWorld::m_MaxSunnyTicks
int m_MaxSunnyTicks
Definition: World.h:1032
E_BLOCK_STATIONARY_WATER
@ E_BLOCK_STATIONARY_WATER
Definition: BlockType.h:19
cDeadlockDetect
Definition: DeadlockDetect.h:23
cWorld::m_UnusedDirtyChunksCap
size_t m_UnusedDirtyChunksCap
The maximum number of allowed unused dirty chunks for this world.
Definition: World.h:940
cWorld::InitializeFluidSimulator
cFluidSimulator * InitializeFluidSimulator(cIniFile &a_IniFile, const char *a_FluidName, BLOCKTYPE a_SimulateBlock, BLOCKTYPE a_StationaryBlock)
Creates a new fluid simulator, loads its settings from the inifile (a_FluidName section)
Definition: World.cpp:3067
cWorld::m_WorldTickAge
cTickTimeLong m_WorldTickAge
The time since this world began, in ticks.
Definition: World.h:993
StringSplitAndTrim
AStringVector StringSplitAndTrim(const AString &str, const AString &delim)
Split the string at any of the listed delimiters and trim each value.
Definition: StringUtils.cpp:205
cDeadlockDetect::TrackCriticalSection
void TrackCriticalSection(cCriticalSection &a_CS, const AString &a_Name)
Adds the critical section for tracking.
Definition: DeadlockDetect.cpp:72
FLOGWARNING
void FLOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:41
GetJungleTreeImage
void GetJungleTreeImage(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks, bool a_Large)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random jungle ...
Definition: Trees.cpp:1287
cMapManager::LoadMapData
void LoadMapData(void)
Loads the map data from the disk.
Definition: MapManager.cpp:95
Item::Minecart
@ Minecart
cWorld::m_SpawnX
int m_SpawnX
Definition: World.h:965
cChunkMap::GenerateChunk
void GenerateChunk(int a_ChunkX, int a_ChunkZ)
Queues the chunk for generating.
Definition: ChunkMap.cpp:1119
cWorld::cWorld
cWorld(const AString &a_WorldName, const AString &a_DataPath, cDeadlockDetect &a_DeadlockDetect, const AStringVector &a_WorldNames, eDimension a_Dimension=dimOverworld, const AString &a_LinkedOverworldName={})
Construct the world and read settings from its ini file.
Definition: World.cpp:137
cPluginManager::CallHookSpawnedMonster
bool CallHookSpawnedMonster(cWorld &a_World, cMonster &a_Monster)
Definition: PluginManager.cpp:1126
cWorld::DigBlock
bool DigBlock(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr)
Replaces the specified block with air, and calls the OnBroken block handler.
Definition: World.cpp:2055
Explodinator::Kaboom
void Kaboom(cWorld &a_World, const Vector3f a_Position, const int a_Power, const bool a_Fiery, const cEntity *const a_ExplodingEntity)
Creates an explosion of Power, centred at Position, with ability to set fires as provided.
Definition: Explodinator.cpp:432
cWorld::SetSignLines
bool SetSignLines(Vector3i a_BlockPos, const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4, cPlayer *a_Player=nullptr)
Sets the sign text, asking plugins for permission first.
Definition: World.cpp:2546
cWorld::DoWithPlayerByUUID
bool DoWithPlayerByUUID(const cUUID &a_PlayerUUID, cPlayerListCallback a_Callback)
Finds the player over his uuid and calls the callback.
Definition: World.cpp:2325
cChunkDef::IsValidHeight
static bool IsValidHeight(Vector3i a_BlockPosition)
Validates a height-coordinate.
Definition: ChunkDef.h:168
cWorld::InitializeSpawn
void InitializeSpawn(void)
Definition: World.cpp:658
cWorld::SetTrapdoorOpen
bool SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open)
Set the state of a trapdoor.
Definition: World.cpp:2619
ChunkDesc.h
cPluginManager::Get
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
Definition: PluginManager.cpp:19
GetRandomProvider
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
cChunkMap::SetBiomeAt
bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
Sets the biome at the specified coords.
Definition: ChunkMap.cpp:678
cLightingThread::GetQueueLength
size_t GetQueueLength(void)
Definition: LightingThread.cpp:180
cChunkMap::RemoveEntity
OwnedEntity RemoveEntity(cEntity &a_Entity)
Removes the entity from its appropriate chunk Returns an owning reference to the found entity.
Definition: ChunkMap.cpp:964
cChunkMap::ForEachLoadedChunk
bool ForEachLoadedChunk(cFunctionRef< bool(int, int)> a_Callback) const
Calls the callback for each loaded chunk.
Definition: ChunkMap.cpp:1196
cMonster
Definition: Monster.h:16
World.h
cItem
Definition: Item.h:36
cChunkMap::SetBlock
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: ChunkMap.cpp:569
cMonster::eFamily
eFamily
Definition: Monster.h:28
cChunkMap::Tick
void Tick(std::chrono::milliseconds a_Dt)
Definition: ChunkMap.cpp:1343
cWorld::GetChunkMap
cChunkMap * GetChunkMap(void)
Definition: World.h:852
E_BLOCK_IRON_TRAPDOOR
@ E_BLOCK_IRON_TRAPDOOR
Definition: BlockType.h:186
cWorld::GrowTreeByBiome
bool GrowTreeByBiome(Vector3i a_BlockPos)
Grows a tree at the specified coords, based on the biome in the place.
Definition: World.cpp:1602
IsBlockLiquid
bool IsBlockLiquid(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:58
IsBlockWater
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:10
cWorld::m_LastSave
std::chrono::milliseconds m_LastSave
Definition: World.h:996
cWorld::QueueSetChunkData
void QueueSetChunkData(SetChunkData &&a_SetChunkData)
Puts the chunk data into a queue to be set into the chunkmap in the tick thread.
Definition: World.cpp:2163
cChunkMap::ForEachEntity
bool ForEachEntity(cEntityCallback a_Callback) const
Calls the callback for each entity in the entire world; returns true if all entities processed,...
Definition: ChunkMap.cpp:982
cMonster::mfWater
@ mfWater
Definition: Monster.h:33
Vector3d
Vector3< double > Vector3d
Definition: Vector3.h:485
wSunny
@ wSunny
Definition: Defines.h:166
SetChunkData
Definition: SetChunkData.h:15
cWorld::SetNextBlockToTick
void SetNextBlockToTick(const Vector3i a_BlockPos)
Causes the specified block to be ticked on the next Tick() call.
Definition: World.cpp:622
cChunkMap::MarkChunkSaved
void MarkChunkSaved(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:200
eWeather
eWeather
Definition: Defines.h:159
cChunkMap::PrepareChunk
void PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallAfter={})
Queues the chunk for preparing - making sure that it's generated and lit.
Definition: ChunkMap.cpp:1096
cWorld::m_MaxSugarcaneHeight
int m_MaxSugarcaneHeight
Definition: World.h:1037
cIniFile::GetValueI
int GetValueI(const AString &keyname, const AString &valuename, const int defValue=0) const
Definition: IniFile.cpp:502
cWorld::RemoveChunkClient
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle *a_Client)
Removes client from the chunk specified.
Definition: World.cpp:2491
E_META_SAPLING_JUNGLE
@ E_META_SAPLING_JUNGLE
Definition: BlockType.h:817
cScoreboardSerializer
Definition: ScoreboardSerializer.h:24
esGhastFireball
@ esGhastFireball
Definition: Defines.h:312
cEntity::IsMob
bool IsMob(void) const
Definition: Entity.h:162
cChunkGeneratorThread::QueueGenerateChunk
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 ...
Definition: ChunkGeneratorThread.cpp:72
cWorld::ForEachEntityInChunk
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: World.cpp:2422
cMonster::NewMonsterFromType
static std::unique_ptr< cMonster > NewMonsterFromType(eMonsterType a_MobType)
Creates a new object of the specified mob.
Definition: Monster.cpp:1246
cWorld::GetBlock
BLOCKTYPE GetBlock(Vector3i a_BlockPos) const
Returns the block type at the specified position.
Definition: World.h:363
EMCSBiome
EMCSBiome
Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft.
Definition: BiomeDef.h:17
DimensionToString
AString DimensionToString(eDimension a_Dimension)
Translates a dimension enum to dimension string.
Definition: Defines.cpp:236
cWorld::HasChunkAnyClients
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const
Definition: World.cpp:2215
cMonster::StringToMobType
static eMonsterType StringToMobType(const AString &a_MobTypeName)
Translates MobType string to the enum, mtInvalidType if not recognized.
Definition: Monster.cpp:1057
cChunkMap::IsChunkValid
bool IsChunkValid(int a_ChunkX, int a_ChunkZ) const
Definition: ChunkMap.cpp:361
cChunkMap::GetBlockSkyLight
NIBBLETYPE GetBlockSkyLight(Vector3i a_BlockPos) const
Definition: ChunkMap.cpp:513
cWorld::m_MinThunderStormTicks
int m_MinThunderStormTicks
Definition: World.h:1034
cWorld::SpawnItemPickups
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:1792
cWorld::ForEachBlockEntityInChunk
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback)
Calls the callback for each block entity in the specified chunk; returns true if all block entities p...
Definition: World.cpp:1362
cRoot::GetPluginManager
cPluginManager * GetPluginManager(void)
Definition: Root.h:111
cWorld::m_BroadcastAchievementMessages
bool m_BroadcastAchievementMessages
Definition: World.h:976
E_ITEM_MINECART
@ E_ITEM_MINECART
Definition: BlockType.h:372
cWorld::m_MaxViewDistance
int m_MaxViewDistance
The maximum view distance that a player can have in this world.
Definition: World.h:1067
cWorld::SendBlockEntity
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle &a_Client)
If there is a block entity at the specified coords, sends it to the client specified.
Definition: World.cpp:2127
ComposableGenerator.h
cChunkMap::UnloadUnusedChunks
void UnloadUnusedChunks(void)
Definition: ChunkMap.cpp:1381
E_BLOCK_GRASS
@ E_BLOCK_GRASS
Definition: BlockType.h:12
cWorld::m_IsSpawnExplicitlySet
bool m_IsSpawnExplicitlySet
Definition: World.h:964
cCuboid::p1
Vector3i p1
Definition: Cuboid.h:13
GetConiferTreeImage
void GetConiferTreeImage(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks, bool a_Large)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random conifer...
Definition: Trees.cpp:878
cWorld::FindAndDoWithPlayer
bool FindAndDoWithPlayer(const AString &a_PlayerNameHint, cPlayerListCallback a_Callback)
Finds a player from a partial or complete player name and calls the callback - case-insensitive.
Definition: World.cpp:2289
cWorld::m_LinkedNetherWorldName
AString m_LinkedNetherWorldName
Name of the nether world - where Nether portals should teleport.
Definition: World.h:1071
FluidSimulator.h
cWorld::GetBiomeAt
EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ)
Returns the biome at the specified coords.
Definition: World.cpp:1680
cWorld::m_ChunkSender
cChunkSender m_ChunkSender
Definition: World.h:1086
RateCompareString
size_t RateCompareString(const AString &s1, const AString &s2)
Case-insensitive string comparison that returns a rating of equal-ness between [0 - s1....
Definition: StringUtils.cpp:317
cWorld::DoWithPlayer
bool DoWithPlayer(const AString &a_PlayerName, cPlayerListCallback a_Callback)
Calls the callback for the player of the given name; returns true if the player was found and the cal...
Definition: World.cpp:2270
cCSLock
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
Definition: CriticalSection.h:52
cChunkDesc::CompressBlockMetas
void CompressBlockMetas(cChunkDef::BlockNibbles &a_DestMetas)
Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byt...
Definition: ChunkDesc.cpp:637
cComposableGenerator::InitializeGeneratorDefaults
static void InitializeGeneratorDefaults(cIniFile &a_IniFile, eDimension a_Dimension)
If there's no particular sub-generator set in the INI file, adds the default one, based on the dimens...
Definition: ComposableGenerator.cpp:202
biFrozenOcean
@ biFrozenOcean
Definition: BiomeDef.h:34
cWorld::SetCommandBlockCommand
bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString &a_Command)
Sets the command block command.
Definition: World.cpp:2584
cWorld::GrowRipePlant
bool GrowRipePlant(Vector3i a_BlockPos)
Grows the plant at the specified block to its ripe stage.
Definition: World.cpp:1671
cWorld::m_StorageSchema
AString m_StorageSchema
Name of the storage schema used to load and save chunks.
Definition: World.h:954
cClientHandle::MAX_VIEW_DISTANCE
static const int MAX_VIEW_DISTANCE
Definition: ClientHandle.h:59
cTickTime
std::chrono::duration< signed int, std::ratio_multiply< std::chrono::milliseconds::period, std::ratio< 50 > >> cTickTime
Definition: Globals.h:361
cBlockHandler::OnBroken
virtual void OnBroken(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity *a_Digger) const
Called after a block gets broken (replaced with air), by natural means.
Definition: BlockHandler.h:60
wStorm
@ wStorm
Definition: Defines.h:169
cBlockHandler::OnPlaced
virtual void OnPlaced(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const
Called by cWorld::SetBlock() after the block has been set.
Definition: BlockHandler.h:50
cWorld::SpawnBoat
UInt32 SpawnBoat(double a_X, double a_Y, double a_Z, cBoat::eMaterial a_Material)
Definition: World.h:480
FireSimulator.h
cSignEntity::GetLine
AString GetLine(int a_Index) const
Retrieves individual line (zero-based index)
Definition: SignEntity.cpp:76
cChunkMap::PickupsFromBlock
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:787
GetAppleTreeImage
void GetAppleTreeImage(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random apple t...
Definition: Trees.cpp:522
World::GetWorldInterface
cWorldInterface * GetWorldInterface(cWorld *a_World)
Definition: World.cpp:71
cWorld::m_Generator
cChunkGeneratorThread m_Generator
The thread responsible for generating chunks.
Definition: World.h:1078
cWorld::m_SetChunkDataQueue
std::vector< SetChunkData > m_SetChunkDataQueue
Queue for the chunk data to be set into m_ChunkMap by the tick thread.
Definition: World.h:1106
cIniFile::ReadFile
bool ReadFile(const AString &a_FileName, bool a_AllowExampleRedirect=true)
Reads the contents of the specified ini file If the file doesn't exist and a_AllowExampleRedirect is ...
Definition: IniFile.cpp:50
cItems
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:213
cWorld::GetBlockMeta
NIBBLETYPE GetBlockMeta(Vector3i a_BlockPos) const
Returns the block meta at the specified position.
Definition: World.h:370
cWorld::GetSimulatorManager
cSimulatorManager * GetSimulatorManager(void)
Definition: World.h:597
cChunkMap::DoWithEntityByID
bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback a_Callback) const
Calls the callback if the entity with the specified ID is found, with the entity object as the callba...
Definition: ChunkMap.cpp:1046
cVaporizeFluidSimulator
Definition: VaporizeFluidSimulator.h:19
cClientHandle::AddWantedChunk
void AddWantedChunk(int a_ChunkX, int a_ChunkZ)
Adds the chunk specified to the list of chunks wanted for sending (m_ChunksToSend)
Definition: ClientHandle.cpp:3342
cWorld::TickQueuedEntityAdditions
void TickQueuedEntityAdditions(void)
Adds the entities queued in the m_EntitiesToAdd queue into their chunk.
Definition: World.cpp:1237
cIniFile::AddKeyComment
bool AddKeyComment(const int keyID, const AString &comment)
Add a key comment.
Definition: IniFile.cpp:740
cLightingThread::Stop
void Stop(void)
Definition: LightingThread.cpp:123
cWorld::IsTrapdoorOpen
bool IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ)
Is the trapdoor open? Returns false if there is no trapdoor at the specified coords.
Definition: World.cpp:2602
CommandBlockEntity.h
cChunkMap::ReplaceTreeBlocks
void ReplaceTreeBlocks(const sSetBlockVector &a_Blocks)
Special function used for growing trees, replaces only blocks that tree may overwrite.
Definition: ChunkMap.cpp:625
esPrimedTNT
@ esPrimedTNT
Definition: Defines.h:316
UNREACHABLE
#define UNREACHABLE(x)
Definition: Globals.h:285
E_META_SAPLING_APPLE
@ E_META_SAPLING_APPLE
Definition: BlockType.h:814
cWorld::DoWithChunkAt
bool DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback)
Calls the callback for the chunk at the block position specified, with ChunkMapCS locked.
Definition: World.cpp:1446
cEntity::INVALID_ID
static const UInt32 INVALID_ID
Special ID that is considered an "invalid value", signifying no entity.
Definition: Entity.h:128
cChunkMap::ChunkLoadFailed
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
Marks the chunk as failed-to-load.
Definition: ChunkMap.cpp:1129
cWorld::cLock::cLock
cLock(const cWorld &a_World)
Definition: World.cpp:86
EffectID::SFX_RANDOM_WOODEN_TRAPDOOR_OPEN
@ SFX_RANDOM_WOODEN_TRAPDOOR_OPEN
cWorld::GetBlockTypeMeta
bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Retrieves the block type and meta at the specified coords.
Definition: World.cpp:1765
cChunkMap::SaveAllChunks
void SaveAllChunks(void) const
Definition: ChunkMap.cpp:1411
dimOverworld
@ dimOverworld
Definition: Defines.h:233
cWorld::GetBlockInfo
bool GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_Meta, NIBBLETYPE &a_SkyLight, NIBBLETYPE &a_BlockLight) const
Queries the whole block specification from the world.
Definition: World.cpp:1774
cWorld::GetWorldDate
cTickTimeLong GetWorldDate() const
Definition: World.cpp:500
cWorld::TabCompleteUserName
void TabCompleteUserName(const AString &a_Text, AStringVector &a_Results)
Appends all usernames starting with a_Text (case-insensitive) into Results.
Definition: World.cpp:2973
cWorld::DoWithChunk
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback)
Calls the callback for the chunk specified, with ChunkMapCS locked.
Definition: World.cpp:1437
ScoreboardSerializer.h
cWorld::m_Storage
cWorldStorage m_Storage
Definition: World.h:1021
cChunkMap::SetChunkData
void SetChunkData(SetChunkData &&a_SetChunkData)
Sets the chunk data as either loaded from the storage or generated.
Definition: ChunkMap.cpp:215
cChunkMap::TrackInDeadlockDetect
void TrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect, const AString &a_WorldName)
Adds this chunkmap's CS to the DeadlockDetect's tracked CSs.
Definition: ChunkMap.cpp:1474
cMonster::mfAmbient
@ mfAmbient
Definition: Monster.h:32
cScoreboardSerializer::Save
bool Save(void)
Try to save the scoreboard.
Definition: ScoreboardSerializer.cpp:57
cWorld::m_MaxThunderStormTicks
int m_MaxThunderStormTicks
Definition: World.h:1034
BLOCKTYPE
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
cWorld::MarkChunkSaving
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
Definition: World.cpp:2145
cWorld::DoWithNearestPlayer
bool DoWithNearestPlayer(Vector3d a_Pos, double a_RangeLimit, cPlayerListCallback a_Callback, bool a_CheckLineOfSight=true, bool a_IgnoreSpectator=true)
Calls the callback for nearest player for given position, Returns false if player not found,...
Definition: World.cpp:2342
cWorld::GetBlocks
bool GetBlocks(sSetBlockVector &a_Blocks, bool a_ContinueOnFailure)
Retrieves block types of the specified blocks.
Definition: World.cpp:2046
cWorld::GetBlockBlockLight
NIBBLETYPE GetBlockBlockLight(Vector3i a_BlockPos) const
Returns the block-light value at the specified block position.
Definition: World.cpp:1756
cWorld::QueueUnloadUnusedChunks
void QueueUnloadUnusedChunks(void)
Queues a task to unload unused chunks onto the tick thread.
Definition: World.cpp:2234
cIniFile::FindValue
int FindValue(const int keyID, const AString &valuename) const
Returns index of specified value, in the specified key, or noID if not found.
Definition: IniFile.cpp:256
cWorld::Tick
void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec)
Definition: World.cpp:1002
cChunkMap::DoWithChunkAt
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:143
cPluginManager::CallHookExploded
bool CallHookExploded(cWorld &a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void *a_SourceData)
Definition: PluginManager.cpp:570
cWorld::IsWeatherSunnyAt
bool IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const
Returns true if it is sunny at the specified location.
Definition: World.cpp:595
LOGWARNING
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
cExpOrb::Split
static std::vector< int > Split(int a_Reward)
Split reward into small values according to regular Minecraft rules.
Definition: ExpOrb.cpp:110
cWorld::RemoveEntity
OwnedEntity RemoveEntity(cEntity &a_Entity)
Removes the entity from the world.
Definition: World.cpp:2755
cChunkMap::GetBlockBlockLight
NIBBLETYPE GetBlockBlockLight(Vector3i a_BlockPos) const
Definition: ChunkMap.cpp:532
cWorld::m_LinkedEndWorldName
AString m_LinkedEndWorldName
Name of the End world - where End portals should teleport.
Definition: World.h:1075
cWorld::ScheduleTask
void ScheduleTask(cTickTime a_DelayTicks, std::function< void(cWorld &)> a_Task)
Queues a lambda task onto the tick thread, with the specified delay.
Definition: World.cpp:2730
cWorld::cChunkGeneratorCallbacks::OnChunkGenerated
virtual void OnChunkGenerated(cChunkDesc &a_ChunkDesc) override
Called after the chunk has been generated The interface may store the chunk, send it over network,...
Definition: World.cpp:3149
ClientHandle.h
NoopRedstoneSimulator.h
eDimension
eDimension
Dimension of a world.
Definition: Defines.h:230
cChunkMap::DoWithChunk
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'...
Definition: ChunkMap.cpp:128
Printf
AString & Printf(AString &a_Dst, const char *a_Format, const Args &... a_Args)
Definition: StringUtils.h:26
BlockInServerPluginInterface.h
cWorld::cLock
A simple RAII locker for the chunkmap - locks the chunkmap in its constructor, unlocks it in the dest...
Definition: World.h:58
cWorld::GrowTree
bool GrowTree(Vector3i a_BlockPos)
Grows a tree at the specified coords.
Definition: World.cpp:1455
cWorld::TickQueuedChunkDataSets
void TickQueuedChunkDataSets()
Sets the chunk data queued in the m_SetChunkDataQueue queue into their chunk.
Definition: World.cpp:1195
cProjectileEntity::eKind
eKind
The kind of the projectile.
Definition: ProjectileEntity.h:33
cWorld::AddEntity
void AddEntity(OwnedEntity a_Entity, cWorld *a_OldWorld=nullptr)
Adds the entity into its appropriate chunk; takes ownership of the entity ptr.
Definition: World.cpp:2745
cChunkMap::ForEachEntityInBox
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:1014
E_BLOCK_STATIONARY_LAVA
@ E_BLOCK_STATIONARY_LAVA
Definition: BlockType.h:21
cPlayer::GetClientHandle
cClientHandle * GetClientHandle(void) const
Definition: Player.h:276
cWorld::SpawnFallingBlock
UInt32 SpawnFallingBlock(Vector3d a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Spawns an falling block entity at the given position.
Definition: World.cpp:1864
cChunkSender::Stop
void Stop(void)
Definition: ChunkSender.cpp:81
cIniFile
Definition: IniFile.h:33
cWorld::TickMobs
void TickMobs(std::chrono::milliseconds a_Dt)
Handles the mob spawning / moving / destroying each tick.
Definition: World.cpp:1109
E_ITEM_MINECART_WITH_TNT
@ E_ITEM_MINECART_WITH_TNT
Definition: BlockType.h:453
Int64
signed long long Int64
Definition: Globals.h:148
cIsThread::Stop
void Stop(void)
Signals the thread to terminate and waits until it's finished.
Definition: IsThread.cpp:48
cChunkSender::Priority
Priority
Tag indicating urgency of chunk to be sent.
Definition: ChunkSender.h:63
cEntity::IsTicking
bool IsTicking(void) const
Returns true if the entity is valid and ticking.
Definition: Entity.cpp:2259
cWorld::GrowTreeFromSapling
bool GrowTreeFromSapling(Vector3i a_BlockPos)
Grows a tree from the sapling at the specified coords.
Definition: World.cpp:1473
Block::AcaciaLeaves::Distance
unsigned char Distance(const BlockState Block)
Definition: BlockStates.cpp:174
cFile::CreateFolderRecursive
static bool CreateFolderRecursive(const AString &a_FolderPath)
Creates a new folder with the specified name, creating its parents if needed.
Definition: File.cpp:467
cChunkGeneratorThread::GetSeed
int GetSeed() const
Definition: ChunkGeneratorThread.cpp:134
cWorld::DoWithBlockEntityAt
virtual bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) override
Calls the callback for the block entity at the specified coords; returns false if there's no block en...
Definition: World.cpp:1406
cChunk
Definition: Chunk.h:35
cWorld::GetName
const AString & GetName(void) const
Returns the name of the world.
Definition: World.h:691
cWorld::m_CSEntitiesToAdd
cCriticalSection m_CSEntitiesToAdd
Guards m_EntitiesToAdd.
Definition: World.h:1097
esWitherSkull
@ esWitherSkull
Definition: Defines.h:318
FloodyFluidSimulator.h
cWorld::SaveAllChunks
void SaveAllChunks(void)
Saves all chunks immediately.
Definition: World.cpp:2698
cEntity
Definition: Entity.h:75
Minecart.h
cWorld::IsWeatherWetAtXYZ
virtual bool IsWeatherWetAtXYZ(Vector3i a_Position) override
Returns true if it is raining or storming at the specified location, and the rain reaches (the bottom...
Definition: World.cpp:613
cChunkCoords
Definition: ChunkDef.h:55
cChunkMap::SendBlockTo
void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, const cPlayer &a_Player)
Sends the block at the specified coords to the specified player.
Definition: ChunkMap.cpp:805
cChunkDesc::GetChunkX
int GetChunkX() const
Definition: ChunkDesc.h:49
cCSLock::Unlock
void Unlock(void)
Definition: CriticalSection.cpp:112
cWorld::m_Weather
eWeather m_Weather
Definition: World.h:1030
cIniFile::GetValueSetB
bool GetValueSetB(const AString &keyname, const AString &valuename, const bool defValue=false) override
Definition: IniFile.h:150
cPlayer
Definition: Player.h:27
E_ITEM_CHEST_MINECART
@ E_ITEM_CHEST_MINECART
Definition: BlockType.h:387
cWorld::UpdateSkyDarkness
void UpdateSkyDarkness(void)
Definition: World.cpp:1313
cWorld::m_MinNetherPortalWidth
int m_MinNetherPortalWidth
Definition: World.h:970
cBlockInfo::IsSolid
static bool IsSolid(BLOCKTYPE Block)
Is this block solid (player cannot walk through)?
Definition: BlockInfo.cpp:892
E_BLOCK_NETHERRACK
@ E_BLOCK_NETHERRACK
Definition: BlockType.h:102
cSignEntity::SetLines
void SetLines(const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4)
Sets all the sign's lines.
Definition: SignEntity.cpp:50
E_ITEM_MINECART_WITH_HOPPER
@ E_ITEM_MINECART_WITH_HOPPER
Definition: BlockType.h:454
cWorld::m_Lighting
cLightingThread m_Lighting
Definition: World.h:1087
cMobSpawner
This class is used to determine which monster can be spawned in which place it is essentially static ...
Definition: MobSpawner.h:15
cPluginManager::CallHookWorldTick
bool CallHookWorldTick(cWorld &a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec)
Definition: PluginManager.cpp:1243
cWorld::ChunkLighted
void ChunkLighted(int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles &a_BlockLight, const cChunkDef::BlockNibbles &a_SkyLight)
Definition: World.cpp:2175
cTickTimeLong
std::chrono::duration< signed long long int, cTickTime::period > cTickTimeLong
Definition: Globals.h:364
E_BLOCK_AIR
@ E_BLOCK_AIR
Definition: BlockType.h:10
cWorld::CreateProjectile
UInt32 CreateProjectile(Vector3d a_Pos, cProjectileEntity::eKind a_Kind, cEntity *a_Creator, const cItem *a_Item, const Vector3d *a_Speed=nullptr)
Creates a projectile of the specified type.
Definition: World.cpp:2934
SetChunkData.h
cWorld::SpawnMinecart
UInt32 SpawnMinecart(Vector3d a_Pos, int a_MinecartType, const cItem &a_Content=cItem(), int a_BlockHeight=1)
Spawns an minecart at the given coordinates.
Definition: World.cpp:1944
cWorld::GetNumChunks
size_t GetNumChunks() const
Returns the number of chunks loaded
Definition: World.cpp:2796
cScoreboardSerializer::Load
bool Load(void)
Try to load the scoreboard.
Definition: ScoreboardSerializer.cpp:31
cWorld::ForEachLoadedChunk
bool ForEachLoadedChunk(cFunctionRef< bool(int, int)> a_Callback)
Calls the callback for each loaded chunk.
Definition: World.cpp:2689
cWorld::m_IsSavingEnabled
std::atomic< bool > m_IsSavingEnabled
Whether or not writing chunks to disk is currently enabled.
Definition: World.h:959
cWorld::QueueBlockForTick
void QueueBlockForTick(int a_BlockX, int a_BlockY, int a_BlockZ, int a_TicksToWait)
Queues the block to be ticked after the specified number of game ticks.
Definition: World.cpp:2854
UNUSED
#define UNUSED
Definition: Globals.h:72
cChunkMap::DigBlock
bool DigBlock(Vector3i a_BlockPos)
Removes the block at the specified coords and wakes up simulators.
Definition: ChunkMap.cpp:765
cChunkMap::DoWithBlockEntityAt
bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback)
Calls the callback for the block entity at the specified coords.
Definition: ChunkMap.cpp:1079
cWorld::GetBlockSkyLight
NIBBLETYPE GetBlockSkyLight(Vector3i a_BlockPos) const
Returns the sky light value at the specified block position.
Definition: World.cpp:1747
cWorld::m_WorldName
AString m_WorldName
Definition: World.h:942
cWorld::m_LastSpawnMonster
std::map< cMonster::eFamily, cTickTimeLong > m_LastSpawnMonster
Definition: World.h:997
cMobCensus::IsCapped
bool IsCapped(cMonster::eFamily a_MobFamily)
Returns true if the family is capped (i.e.
Definition: MobCensus.cpp:20
cWorld::m_ChunkMap
cChunkMap m_ChunkMap
Definition: World.h:1025
cWorld::m_MaxCactusHeight
int m_MaxCactusHeight
Definition: World.h:1036
cWorld::m_CSSetChunkDataQueue
cCriticalSection m_CSSetChunkDataQueue
CS protecting m_SetChunkDataQueue.
Definition: World.h:1103
cWorld::DoWithEntityByID
bool DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback)
Calls the callback if the entity with the specified ID is found, with the entity object as the callba...
Definition: World.cpp:2450
cPluginManager::CallHookChunkGenerating
bool CallHookChunkGenerating(cWorld &a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc *a_ChunkDesc)
Definition: PluginManager.cpp:403
cWorld::SetSpawn
bool SetSpawn(int a_X, int a_Y, int a_Z)
Set default spawn at the given coordinates.
Definition: World.cpp:631
cLineBlockTracer::LineOfSightTrace
static bool LineOfSightTrace(cWorld &a_World, const Vector3d &a_Start, const Vector3d &a_End, int a_Sight)
Returns true if the two positions are within line of sight (not obscured by blocks).
Definition: LineBlockTracer.cpp:42
ExpOrb.h
cChunkMap::RemoveClientFromChunks
void RemoveClientFromChunks(cClientHandle *a_Client)
Removes the client from all chunks it is present in.
Definition: ChunkMap.cpp:895
cWorld::IsWeatherWetAt
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) override
Returns true if it is raining or storming at the specified location.
Definition: World.cpp:604
cBlockEntity::GetBlockType
BLOCKTYPE GetBlockType() const
Definition: BlockEntity.h:97
GetBirchTreeImage
void GetBirchTreeImage(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random birch t...
Definition: Trees.cpp:673
cChunkMap::GetHeight
int GetHeight(int a_BlockX, int a_BlockZ)
Definition: ChunkMap.cpp:383
PluginManager.h
cChunkDef::BlockNibbles
NIBBLETYPE BlockNibbles[NumBlocks/2]
The type used for block data in nibble format, AXIS_ORDER ordering.
Definition: ChunkDef.h:126
cWorld::m_LinkedOverworldName
AString m_LinkedOverworldName
The name of the overworld that portals in this world should link to.
Definition: World.h:949
E_BLOCK_SNOW
@ E_BLOCK_SNOW
Definition: BlockType.h:92
Block
Definition: BlockStates.cpp:3
cBroadcastInterface
Definition: BroadcastInterface.h:16
World::GetChunkInterface
cChunkInterface GetChunkInterface(cWorld &a_World)
Definition: World.cpp:73
cFunctionRef
Definition: FunctionRef.h:6
cWorld::m_ShouldLavaSpawnFire
bool m_ShouldLavaSpawnFire
Definition: World.h:1005
cWorld::m_MinRainTicks
int m_MinRainTicks
Definition: World.h:1033
cWorld::m_MinNetherPortalHeight
int m_MinNetherPortalHeight
Definition: World.h:972
cWorld::DropBlockAsPickups
bool DropBlockAsPickups(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Digs the specified block, and spawns the appropriate pickups for it.
Definition: World.cpp:2076
cWorld::m_Scoreboard
cScoreboard m_Scoreboard
Definition: World.h:1080
GetDarkoakTreeImage
void GetDarkoakTreeImage(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random darkoak...
Definition: Trees.cpp:769
cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated
virtual void CallHookChunkGenerated(cChunkDesc &a_ChunkDesc) override
Called after the chunk is generated, before it is handed to the chunk sink.
Definition: World.cpp:3212
BlockType::TNT
@ TNT
cWorld::IsChunkLighted
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ)
Definition: World.cpp:2671
AString
std::string AString
Definition: StringUtils.h:11
cSpawnPrepare::PrepareChunks
static void PrepareChunks(cWorld &a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance)
Definition: SpawnPrepare.cpp:51
cWorld::ForEachPlayer
virtual bool ForEachPlayer(cPlayerListCallback a_Callback) override
Calls the callback for each player in the list; returns true if all players processed,...
Definition: World.cpp:2252
Vector3< int >
cChunkMap::ForEachChunkInRect
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:1167
E_BLOCK_LAVA
@ E_BLOCK_LAVA
Definition: BlockType.h:20
cWorld::SpawnItemPickup
UInt32 SpawnItemPickup(Vector3d a_Pos, const cItem &a_Item, Vector3f a_Speed, int a_LifetimeTicks=6000, bool a_CanCombine=true)
Spawns a single pickup containing the specified item.
Definition: World.cpp:1849
GetTreeImageByBiome
void GetTreeImageByBiome(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, EMCSBiome a_Biome, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a tree at the sp...
Definition: Trees.cpp:310
cChunkMap::CollectMobCensus
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:1307
cWorld::CheckPlayerSpawnPoint
bool CheckPlayerSpawnPoint(int a_PosX, int a_PosY, int a_PosZ)
Check if player starting point is acceptable.
Definition: World.h:1139
cWorld::ForEachEntityInBox
virtual bool ForEachEntityInBox(const cBoundingBox &a_Box, cEntityCallback a_Callback) override
Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
Definition: World.cpp:2431
cWorld::ForceSendChunkTo
void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle *a_Client)
Sends the chunk to the client specified, even if the client already has the chunk.
Definition: World.cpp:2518
cWorld::m_MapManager
cMapManager m_MapManager
Definition: World.h:1081
cChunkMap::MarkChunkDirty
void MarkChunkDirty(int a_ChunkX, int a_ChunkZ)
Definition: ChunkMap.cpp:170
E_BLOCK_SAPLING
@ E_BLOCK_SAPLING
Definition: BlockType.h:16
cChunkCoords::m_ChunkZ
int m_ChunkZ
Definition: ChunkDef.h:59
cWorld::SetBlock
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
Definition: World.cpp:1729
cIniFile::SetValue
bool SetValue(const int keyID, const int valueID, const AString &value)
Definition: IniFile.cpp:393
cWorld::TryGetHeight
bool TryGetHeight(int a_BlockX, int a_BlockZ, int &a_Height)
Retrieves the world height at the specified coords; returns false if chunk not loaded / generated.
Definition: World.cpp:2118
cChunkMap::GetChunkData
bool GetChunkData(cChunkCoords a_Coords, cChunkDataCallback &a_Callback) const
Calls the callback with the chunk's data, if available (with ChunkCS locked).
Definition: ChunkMap.cpp:271
cWorld::m_TickThread
cTickThread m_TickThread
Definition: World.h:1088
cIniFile::SetValueB
bool SetValueB(const AString &a_KeyName, const AString &a_ValueName, const bool a_Value, const bool a_CreateIfNotExists=true)
Definition: IniFile.h:173
cWorld::SetBiomeAt
bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
Sets the biome at the specified coords.
Definition: World.cpp:1689
LOG
void LOG(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:55
eWeather_ThunderStorm
@ eWeather_ThunderStorm
Definition: Defines.h:163
FLOGINFO
void FLOGINFO(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:35
cBlockEntity
Definition: BlockEntity.h:24
cWorld::MarkChunkSaved
void MarkChunkSaved(int a_ChunkX, int a_ChunkZ)
Definition: World.cpp:2154
cWorld::m_LavaSimulator
cFluidSimulator * m_LavaSimulator
Definition: World.h:1014
cChunkMap::SendBlockEntity
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:93
slNone
@ slNone
Definition: Defines.h:328
dimEnd
@ dimEnd
Definition: Defines.h:234
cWorld::GetLargeTreeAdjustment
bool GetLargeTreeAdjustment(Vector3i &a_BlockPos, NIBBLETYPE a_SaplingMeta)
Checks if the sapling at the specified block coord is a part of a large-tree sapling (2x2).
Definition: World.cpp:1516
Player.h
cWorld::QueueTask
void QueueTask(std::function< void(cWorld &)> a_Task)
Queues a task onto the tick thread.
Definition: World.cpp:2720
cChunkMap::UntrackInDeadlockDetect
void UntrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect)
Removes this chunkmap's CS from the DeadlockDetect's tracked CSs.
Definition: ChunkMap.cpp:1483
cIniFile::WriteFile
bool WriteFile(const AString &a_FileName) const
Writes data stored in class to the specified ini file.
Definition: IniFile.cpp:189
cChunkMap::RemoveChunkClient
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle *a_Client)
Removes the client from the chunk.
Definition: ChunkMap.cpp:883
cWorld::WakeUpSimulatorsInArea
void WakeUpSimulatorsInArea(const cCuboid &a_Area)
Wakes up the simulators for the specified area of blocks.
Definition: World.cpp:1353
cCuboid
Definition: Cuboid.h:9
cWorld::GetHeight
virtual int GetHeight(int a_BlockX, int a_BlockZ) override
Returns the world height at the specified coords; waits for the chunk to get loaded / generated.
Definition: World.cpp:2109
cWorld::SetTimeOfDay
virtual void SetTimeOfDay(cTickTime a_TimeOfDay) override
Definition: World.cpp:518
cWorld::m_Tasks
std::vector< std::pair< std::chrono::milliseconds, std::function< void(cWorld &)> > > m_Tasks
Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the futur...
Definition: World.h:1094
cWorld::BroadcastThunderbolt
virtual void BroadcastThunderbolt(Vector3i a_BlockPos, const cClientHandle *a_Exclude=nullptr) override
Definition: Broadcaster.cpp:582
cMonster::mfHostile
@ mfHostile
Definition: Monster.h:30
GetAcaciaTreeImage
void GetAcaciaTreeImage(Vector3i a_BlockPos, cNoise &a_Noise, int a_Seq, sSetBlockVector &a_LogBlocks, sSetBlockVector &a_OtherBlocks)
Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random acacia ...
Definition: Trees.cpp:711
cWorld::GrowTreeImage
bool GrowTreeImage(const sSetBlockVector &a_Blocks)
Imprints the specified blocks into the world, as long as each log block replaces only allowed blocks.
Definition: World.cpp:1617
AStringVector
std::vector< AString > AStringVector
Definition: StringUtils.h:12