summaryrefslogtreecommitdiffstats
path: root/src/World.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/World.cpp')
-rw-r--r--src/World.cpp352
1 files changed, 172 insertions, 180 deletions
diff --git a/src/World.cpp b/src/World.cpp
index c0a79b9d0..123e4a8da 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -58,6 +58,8 @@
#endif
#include "Broadcaster.h"
+#include "SpawnPrepare.h"
+#include "FastRandom.h"
@@ -72,140 +74,6 @@ const int TIME_SPAWN_DIVISOR = 148;
////////////////////////////////////////////////////////////////////////////////
-// cSpawnPrepare:
-
-/** Generates and lights the spawn area of the world. Runs as a separate thread. */
-class cSpawnPrepare:
- public cIsThread,
- public cChunkCoordCallback
-{
- typedef cIsThread super;
-
-public:
- cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance):
- super("SpawnPrepare"),
- m_World(a_World),
- m_SpawnChunkX(a_SpawnChunkX),
- m_SpawnChunkZ(a_SpawnChunkZ),
- m_PrepareDistance(a_PrepareDistance),
- m_MaxIdx(a_PrepareDistance * a_PrepareDistance),
- m_NumPrepared(0),
- m_LastReportChunkCount(0)
- {
- // Start the thread:
- Start();
-
- // Wait for start confirmation, so that the thread can be waited-upon after the constructor returns:
- m_EvtStarted.Wait();
- }
-
-
- // cIsThread override:
- virtual void Execute(void) override
- {
- // Confirm thread start:
- m_EvtStarted.Set();
-
- // Queue the initial chunks:
- m_MaxIdx = m_PrepareDistance * m_PrepareDistance;
- int maxQueue = std::min(m_MaxIdx - 1, 100); // Number of chunks to queue at once
- m_NextIdx = maxQueue;
- m_LastReportTime = std::chrono::steady_clock::now();
- for (int i = 0; i < maxQueue; i++)
- {
- int chunkX, chunkZ;
- DecodeChunkCoords(i, chunkX, chunkZ);
- m_World.PrepareChunk(chunkX, chunkZ, this);
- } // for i
-
- // Wait for the lighting thread to prepare everything. Event is set in the Call() callback:
- m_EvtFinished.Wait();
- }
-
-protected:
- cWorld & m_World;
- int m_SpawnChunkX;
- int m_SpawnChunkZ;
- int m_PrepareDistance;
-
- /** The index of the next chunk to be queued in the lighting thread. */
- int m_NextIdx;
-
- /** The maximum index of the prepared chunks. Queueing stops when m_NextIdx reaches this number. */
- int m_MaxIdx;
-
- /** Total number of chunks already finished preparing. Preparation finishes when this number reaches m_MaxIdx. */
- int m_NumPrepared;
-
- /** Event used to signal that the thread has started. */
- cEvent m_EvtStarted;
-
- /** Event used to signal that the preparation is finished. */
- cEvent m_EvtFinished;
-
- /** The timestamp of the last progress report emitted. */
- std::chrono::steady_clock::time_point m_LastReportTime;
-
- /** Number of chunks prepared when the last progress report was emitted. */
- int m_LastReportChunkCount;
-
- // cChunkCoordCallback override:
- virtual void Call(int a_ChunkX, int a_ChunkZ)
- {
- // Check if this was the last chunk:
- m_NumPrepared += 1;
- if (m_NumPrepared >= m_MaxIdx)
- {
- m_EvtFinished.Set();
- // Must return here, because "this" may have gotten deleted by the previous line
- return;
- }
-
- // Queue another chunk, if appropriate:
- if (m_NextIdx < m_MaxIdx)
- {
- int chunkX, chunkZ;
- DecodeChunkCoords(m_NextIdx, chunkX, chunkZ);
- m_World.GetLightingThread().QueueChunk(chunkX, chunkZ, this);
- m_NextIdx += 1;
- }
-
- // Report progress every 1 second:
- auto Now = std::chrono::steady_clock::now();
- if (Now - m_LastReportTime > std::chrono::seconds(1))
- {
- float PercentDone = static_cast<float>(m_NumPrepared * 100) / m_MaxIdx;
- float ChunkSpeed = static_cast<float>((m_NumPrepared - m_LastReportChunkCount) * 1000) / std::chrono::duration_cast<std::chrono::milliseconds>(Now - m_LastReportTime).count();
- LOG("Preparing spawn (%s): %.02f%% (%d/%d; %.02f chunks / sec)",
- m_World.GetName().c_str(), PercentDone, m_NumPrepared, m_MaxIdx, ChunkSpeed
- );
- m_LastReportTime = Now;
- m_LastReportChunkCount = m_NumPrepared;
- }
- }
-
-
- /** Decodes the index into chunk coords. Provides the specific chunk ordering. */
- void DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ)
- {
- // A zigzag pattern from the top to bottom, each row alternating between forward-x and backward-x:
- int z = a_Idx / m_PrepareDistance;
- int x = a_Idx % m_PrepareDistance;
- if ((z & 1) == 0)
- {
- // Reverse every second row:
- x = m_PrepareDistance - 1 - x;
- }
- a_ChunkZ = m_SpawnChunkZ + z - m_PrepareDistance / 2;
- a_ChunkX = m_SpawnChunkX + x - m_PrepareDistance / 2;
- }
-};
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
// cWorld::cLock:
cWorld::cLock::cLock(cWorld & a_World) :
@@ -319,6 +187,7 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin
m_Scoreboard(this),
m_MapManager(this),
m_GeneratorCallbacks(*this),
+ m_ChunkSender(*this),
m_TickThread(*this)
{
LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str());
@@ -362,6 +231,7 @@ cWorld::~cWorld()
void cWorld::CastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ)
{
BroadcastThunderbolt(a_BlockX, a_BlockY, a_BlockZ);
+ BroadcastSoundEffect("ambient.weather.thunder", a_BlockX, a_BlockY, a_BlockZ, 50, 1);
}
@@ -469,8 +339,7 @@ void cWorld::InitializeSpawn(void)
int ViewDist = IniFile.GetValueSetI("SpawnPosition", "PregenerateDistance", DefaultViewDist);
IniFile.WriteFile(m_IniFileName);
- cSpawnPrepare prep(*this, ChunkX, ChunkZ, ViewDist);
- prep.Wait();
+ cSpawnPrepare::PrepareChunks(*this, ChunkX, ChunkZ, ViewDist);
#ifdef TEST_LINEBLOCKTRACER
// DEBUG: Test out the cLineBlockTracer class by tracing a few lines:
@@ -597,6 +466,10 @@ void cWorld::Start(void)
m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false);
m_bEnabledPVP = IniFile.GetValueSetB("Mechanics", "PVPEnabled", true);
m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true);
+ m_MinNetherPortalWidth = IniFile.GetValueSetI("Mechanics", "MinNetherPortalWidth", 2);
+ m_MaxNetherPortalWidth = IniFile.GetValueSetI("Mechanics", "MaxNetherPortalWidth", 21);
+ m_MinNetherPortalHeight = IniFile.GetValueSetI("Mechanics", "MinNetherPortalHeight", 3);
+ m_MaxNetherPortalHeight = IniFile.GetValueSetI("Mechanics", "MaxNetherPortalHeight", 21);
m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true);
m_IsDaylightCycleEnabled = IniFile.GetValueSetB("General", "IsDaylightCycleEnabled", true);
int GameMode = IniFile.GetValueSetI("General", "Gamemode", (int)m_GameMode);
@@ -621,18 +494,18 @@ void cWorld::Start(void)
InitialiseAndLoadMobSpawningValues(IniFile);
SetTimeOfDay(IniFile.GetValueSetI("General", "TimeInTicks", GetTimeOfDay()));
- m_ChunkMap = make_unique<cChunkMap>(this);
+ m_ChunkMap = cpp14::make_unique<cChunkMap>(this);
// preallocate some memory for ticking blocks so we don't need to allocate that often
m_BlockTickQueue.reserve(1000);
m_BlockTickQueueCopy.reserve(1000);
// Simulators:
- m_SimulatorManager = make_unique<cSimulatorManager>(*this);
+ m_SimulatorManager = cpp14::make_unique<cSimulatorManager>(*this);
m_WaterSimulator = InitializeFluidSimulator(IniFile, "Water", E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
m_LavaSimulator = InitializeFluidSimulator(IniFile, "Lava", E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
- m_SandSimulator = make_unique<cSandSimulator>(*this, IniFile);
- m_FireSimulator = make_unique<cFireSimulator>(*this, IniFile);
+ m_SandSimulator = cpp14::make_unique<cSandSimulator>(*this, IniFile);
+ m_FireSimulator = cpp14::make_unique<cFireSimulator>(*this, IniFile);
m_RedstoneSimulator = InitializeRedstoneSimulator(IniFile);
// Water, Lava and Redstone simulators get registered in their initialize function.
@@ -642,7 +515,7 @@ void cWorld::Start(void)
m_Lighting.Start(this);
m_Storage.Start(this, m_StorageSchema, m_StorageCompressionFactor);
m_Generator.Start(m_GeneratorCallbacks, m_GeneratorCallbacks, IniFile);
- m_ChunkSender.Start(this);
+ m_ChunkSender.Start();
m_TickThread.Start();
// Init of the spawn monster time (as they are supposed to have different spawn rate)
@@ -800,7 +673,7 @@ void cWorld::InitialiseGeneratorDefaults(cIniFile & a_IniFile)
a_IniFile.GetValueSet("Generator", "BiomeGen", "Grown");
a_IniFile.GetValueSet("Generator", "ShapeGen", "BiomalNoise3D");
a_IniFile.GetValueSet("Generator", "CompositionGen", "Biomal");
- a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, WaterSprings, LavaLakes, LavaSprings, OreNests, Mineshafts, Trees, Villages, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, NaturalPatches, PreSimulator, Animals");
+ a_IniFile.GetValueSet("Generator", "Finishers", "RoughRavines, WormNestCaves, WaterLakes, WaterSprings, LavaLakes, LavaSprings, OreNests, Mineshafts, Trees, Villages, TallGrass, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, NaturalPatches, PreSimulator, Animals");
break;
}
case dimNether:
@@ -1459,6 +1332,30 @@ bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback
+bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, std::function<bool(cChunk &)> a_Callback)
+{
+ struct cCallBackWrapper : cChunkCallback
+ {
+ cCallBackWrapper(std::function<bool(cChunk &)> a_InnerCallback) :
+ m_Callback(a_InnerCallback)
+ {
+ }
+
+ virtual bool Item(cChunk * a_Chunk)
+ {
+ return m_Callback(*a_Chunk);
+ }
+
+ private:
+ std::function<bool(cChunk &)> m_Callback;
+ } callback(a_Callback);
+ return m_ChunkMap->DoWithChunk(a_ChunkX, a_ChunkZ, callback);
+}
+
+
+
+
+
bool cWorld::DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback)
{
return m_ChunkMap->DoWithChunkAt(a_BlockPos, a_Callback);
@@ -1496,9 +1393,23 @@ void cWorld::GrowTreeFromSapling(int a_X, int a_Y, int a_Z, NIBBLETYPE a_Sapling
case E_META_SAPLING_APPLE: GetAppleTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
case E_META_SAPLING_BIRCH: GetBirchTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
case E_META_SAPLING_CONIFER: GetConiferTreeImage(a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
- case E_META_SAPLING_JUNGLE: GetJungleTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
case E_META_SAPLING_ACACIA: GetAcaciaTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
- case E_META_SAPLING_DARK_OAK: GetDarkoakTreeImage(a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
+ case E_META_SAPLING_JUNGLE:
+ {
+ bool IsLarge = GetLargeTreeAdjustment(*this, a_X, a_Y, a_Z, a_SaplingMeta);
+ GetJungleTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other, IsLarge);
+ break;
+ }
+ case E_META_SAPLING_DARK_OAK:
+ {
+ if (!GetLargeTreeAdjustment(*this, a_X, a_Y, a_Z, a_SaplingMeta))
+ {
+ return;
+ }
+
+ GetDarkoakTreeImage(a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other);
+ break;
+ }
}
Other.insert(Other.begin(), Logs.begin(), Logs.end());
Logs.clear();
@@ -1569,6 +1480,7 @@ void cWorld::GrowTreeImage(const sSetBlockVector & a_Blocks)
bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsByBonemeal)
{
+ cFastRandom random;
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
@@ -1582,10 +1494,19 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
}
if (BlockMeta < 7)
{
- FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, 7);
+ if (!a_IsByBonemeal)
+ {
+ ++BlockMeta;
+ }
+ else
+ {
+ BlockMeta += random.NextInt(4) + 2;
+ BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
+ }
+ FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
BroadcastSoundParticleEffect(2005, a_BlockX, a_BlockY, a_BlockZ, 0);
}
- return true;
+ return BlockMeta == 7;
}
case E_BLOCK_COCOA_POD:
@@ -1599,7 +1520,7 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, (NIBBLETYPE) (GrowState << 2 | TypeMeta));
BroadcastSoundParticleEffect(2005, a_BlockX, a_BlockY, a_BlockZ, 0);
}
- return true;
+ return GrowState == 2;
}
case E_BLOCK_CROPS:
@@ -1610,10 +1531,19 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
}
if (BlockMeta < 7)
{
- FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, 7);
+ if (!a_IsByBonemeal)
+ {
+ ++BlockMeta;
+ }
+ else
+ {
+ BlockMeta += random.NextInt(4) + 2;
+ BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
+ }
+ FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
BroadcastSoundParticleEffect(2005, a_BlockX, a_BlockY, a_BlockZ, 0);
}
- return true;
+ return BlockMeta == 7;
}
case E_BLOCK_MELON_STEM:
@@ -1624,7 +1554,17 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
{
return false;
}
- FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, 7);
+
+ if (!a_IsByBonemeal)
+ {
+ ++BlockMeta;
+ }
+ else
+ {
+ BlockMeta += random.NextInt(4) + 2;
+ BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
+ }
+ FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
BroadcastSoundParticleEffect(2005, a_BlockX, a_BlockY, a_BlockZ, 0);
}
else
@@ -1635,7 +1575,7 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
}
GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, BlockType);
}
- return true;
+ return BlockMeta == 7;
}
case E_BLOCK_POTATOES:
@@ -1646,10 +1586,19 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
}
if (BlockMeta < 7)
{
- FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, 7);
+ if (!a_IsByBonemeal)
+ {
+ ++BlockMeta;
+ }
+ else
+ {
+ BlockMeta += random.NextInt(4) + 2;
+ BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
+ }
+ FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
BroadcastSoundParticleEffect(2005, a_BlockX, a_BlockY, a_BlockZ, 0);
}
- return true;
+ return BlockMeta == 7;
}
case E_BLOCK_PUMPKIN_STEM:
@@ -1660,7 +1609,17 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
{
return false;
}
- FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, 7);
+
+ if (!a_IsByBonemeal)
+ {
+ ++BlockMeta;
+ }
+ else
+ {
+ BlockMeta += random.NextInt(4) + 2;
+ BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
+ }
+ FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
BroadcastSoundParticleEffect(2005, a_BlockX, a_BlockY, a_BlockZ, 0);
}
else
@@ -1671,7 +1630,7 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
}
GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, BlockType);
}
- return true;
+ return BlockMeta == 7;
}
case E_BLOCK_SAPLING:
@@ -1680,8 +1639,31 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
{
return false;
}
- GrowTreeFromSapling(a_BlockX, a_BlockY, a_BlockZ, BlockMeta);
- return true;
+ NIBBLETYPE TypeMeta = BlockMeta & 0x07;
+ int GrowState = BlockMeta >> 3;
+
+ if (GrowState < 1)
+ {
+ // Non-bonemeal forces a growth, while bonemeal only has a chance of growing it
+ if (!a_IsByBonemeal)
+ {
+ ++GrowState;
+ }
+ else if (random.NextInt(99) < 45)
+ {
+ ++GrowState;
+ }
+
+ FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, static_cast<NIBBLETYPE>(GrowState << 3 | TypeMeta));
+ BroadcastSoundParticleEffect(2005, a_BlockX, a_BlockY, a_BlockZ, 0);
+ }
+ else if (random.NextInt(99) < 45)
+ {
+
+ GrowTreeFromSapling(a_BlockX, a_BlockY, a_BlockZ, BlockMeta);
+ return true;
+ }
+ return false;
}
case E_BLOCK_GRASS:
@@ -2071,7 +2053,7 @@ void cWorld::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_V
-void cWorld::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude)
+void cWorld::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude)
{
m_ChunkMap->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, a_Byte1, a_Byte2, a_BlockType, a_Exclude);
}
@@ -2134,15 +2116,6 @@ void cWorld::BroadcastChat(const cCompositeChat & a_Message, const cClientHandle
-void cWorld::BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude)
-{
- m_ChunkMap->BroadcastChunkData(a_ChunkX, a_ChunkZ, a_Serializer, a_Exclude);
-}
-
-
-
-
-
void cWorld::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
m_ChunkMap->BroadcastCollectEntity(a_Entity, a_Player, a_Exclude);
@@ -2594,10 +2567,23 @@ void cWorld::SetChunkData(cSetChunkData & a_SetChunkData)
// If a client is requesting this chunk, send it to them:
int ChunkX = a_SetChunkData.GetChunkX();
int ChunkZ = a_SetChunkData.GetChunkZ();
- if (m_ChunkMap->HasChunkAnyClients(ChunkX, ChunkZ))
- {
- m_ChunkSender.ChunkReady(ChunkX, ChunkZ);
- }
+ cChunkSender & ChunkSender = m_ChunkSender;
+ DoWithChunk(
+ ChunkX, ChunkZ,
+ [&ChunkSender] (cChunk & a_Chunk) -> bool
+ {
+ if (a_Chunk.HasAnyClients())
+ {
+ ChunkSender.QueueSendChunkTo(
+ a_Chunk.GetPosX(),
+ a_Chunk.GetPosZ(),
+ cChunkSender::E_CHUNK_PRIORITY_MEDIUM,
+ a_Chunk.GetAllClients()
+ );
+ }
+ return true;
+ }
+ );
// Save the chunk right after generating, so that we don't have to generate it again on next run
if (a_SetChunkData.ShouldMarkDirty())
@@ -2680,7 +2666,7 @@ void cWorld::UnloadUnusedChunks(void)
void cWorld::QueueUnloadUnusedChunks(void)
{
- QueueTask(make_unique<cWorld::cTaskUnloadUnusedChunks>());
+ QueueTask(cpp14::make_unique<cWorld::cTaskUnloadUnusedChunks>());
}
@@ -3005,9 +2991,9 @@ void cWorld::TouchChunk(int a_ChunkX, int a_ChunkZ)
-void cWorld::PrepareChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallAfter)
+void cWorld::PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_CallAfter)
{
- m_ChunkMap->PrepareChunk(a_ChunkX, a_ChunkZ, a_CallAfter);
+ m_ChunkMap->PrepareChunk(a_ChunkX, a_ChunkZ, std::move(a_CallAfter));
}
@@ -3097,7 +3083,7 @@ bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Op
return false;
}
- bool IsOpen = (Meta & 0x4) > 0;
+ bool IsOpen = (Meta & 0x4) != 0;
if (a_Open != IsOpen)
{
SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta ^ 0x4);
@@ -3131,9 +3117,9 @@ void cWorld::GenerateChunk(int a_ChunkX, int a_ChunkZ)
-void cWorld::QueueLightChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback)
+void cWorld::QueueLightChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_Callback)
{
- m_Lighting.QueueChunk(a_ChunkX, a_ChunkZ, a_Callback);
+ m_Lighting.QueueChunk(a_ChunkX, a_ChunkZ, std::move(a_Callback));
}
@@ -3184,7 +3170,11 @@ void cWorld::QueueTask(cTaskPtr a_Task)
}
-
+void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld&)> a_Func)
+{
+ cTaskLambda task(a_Func);
+ ScheduleTask(a_DelayTicks, static_cast<cTaskPtr>(std::make_shared<cTaskLambda>(task)));
+}
void cWorld::ScheduleTask(int a_DelayTicks, cTaskPtr a_Task)
@@ -3687,8 +3677,10 @@ void cWorld::cTaskSendBlockToAllPlayers::Run(cWorld & a_World)
a_World.ForEachPlayer(PlayerCallback);
}
-
-
+void cWorld::cTaskLambda::Run(cWorld & a_World)
+{
+ m_func(a_World);
+}
////////////////////////////////////////////////////////////////////////////////