summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/Blocks/BlockHandler.cpp4
-rw-r--r--source/Chunk.cpp166
-rw-r--r--source/Chunk.h22
-rw-r--r--source/ChunkMap.cpp25
-rw-r--r--source/ChunkMap.h7
-rw-r--r--source/Simulator/ClassicFluidSimulator.cpp27
-rw-r--r--source/Simulator/ClassicFluidSimulator.h2
-rw-r--r--source/Simulator/DelayedFluidSimulator.cpp3
-rw-r--r--source/Simulator/DelayedFluidSimulator.h2
-rw-r--r--source/Simulator/FireSimulator.cpp3
-rw-r--r--source/Simulator/FireSimulator.h2
-rw-r--r--source/Simulator/RedstoneSimulator.cpp5
-rw-r--r--source/Simulator/RedstoneSimulator.h5
-rw-r--r--source/Simulator/SandSimulator.cpp28
-rw-r--r--source/Simulator/SandSimulator.h2
-rw-r--r--source/Simulator/Simulator.cpp17
-rw-r--r--source/Simulator/Simulator.h9
-rw-r--r--source/Simulator/SimulatorManager.cpp4
-rw-r--r--source/Simulator/SimulatorManager.h9
-rw-r--r--source/World.cpp10
-rw-r--r--source/World.h3
21 files changed, 230 insertions, 125 deletions
diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp
index cde85fce8..71d56f94d 100644
--- a/source/Blocks/BlockHandler.cpp
+++ b/source/Blocks/BlockHandler.cpp
@@ -436,8 +436,8 @@ void cBlockHandler::Check(cWorld * a_World, int a_BlockX, int a_BlockY, int a_Bl
}
else
{
- // Wake up the simulators:
- a_World->GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ);
+ // Wake up the simulators for this block:
+ a_World->WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
}
}
diff --git a/source/Chunk.cpp b/source/Chunk.cpp
index 41cc0e7f6..3616f6b8e 100644
--- a/source/Chunk.cpp
+++ b/source/Chunk.cpp
@@ -492,15 +492,10 @@ void cChunk::BroadcastPendingBlockChanges(void)
void cChunk::CheckBlocks(void)
{
cCSLock Lock2(m_CSBlockLists);
- unsigned int NumTickBlocks = m_ToTickBlocks.size();
- Lock2.Unlock();
-
- if (NumTickBlocks == 0)
+ if (m_ToTickBlocks.size() == 0)
{
return;
}
-
- Lock2.Lock();
std::deque< unsigned int > ToTickBlocks = m_ToTickBlocks;
m_ToTickBlocks.clear();
Lock2.Unlock();
@@ -1131,17 +1126,18 @@ void cChunk::SetBlock( int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType
}
m_ToTickBlocks.push_back(index);
- CheckNeighbors(a_RelX, a_RelY, a_RelZ);
+ QueueTickBlockNeighbors(a_RelX, a_RelY, a_RelZ);
- Vector3i WorldPos = PositionToWorldPosition( a_RelX, a_RelY, a_RelZ );
- cBlockEntity* BlockEntity = GetBlockEntity( WorldPos );
- if( BlockEntity )
+ Vector3i WorldPos = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ);
+ cBlockEntity * BlockEntity = GetBlockEntity(WorldPos);
+ if (BlockEntity != NULL)
{
BlockEntity->Destroy();
- RemoveBlockEntity( BlockEntity );
+ RemoveBlockEntity(BlockEntity);
delete BlockEntity;
}
- switch( a_BlockType )
+
+ switch (a_BlockType)
{
case E_BLOCK_CHEST:
{
@@ -1181,76 +1177,52 @@ void cChunk::SetBlock( int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType
-void cChunk::CheckNeighbors(int a_RelX, int a_RelY, int a_RelZ)
+void cChunk::QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ)
{
- int BlockX = m_PosX * cChunkDef::Width + a_RelX;
- int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
- if (a_RelX < cChunkDef::Width - 1)
- {
- m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX + 1, a_RelY, a_RelZ));
- }
- else
- {
- m_ChunkMap->CheckBlock(BlockX + 1, a_RelY, BlockZ);
- }
-
- if (a_RelX > 0)
- {
- m_ToTickBlocks.push_back( MakeIndexNoCheck(a_RelX - 1, a_RelY, a_RelZ));
- }
- else
- {
- m_ChunkMap->CheckBlock(BlockX - 1, a_RelY, BlockZ);
- }
-
- if (a_RelY < cChunkDef::Height - 1)
- {
- m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY + 1, a_RelZ));
- }
-
- if (a_RelY > 0)
- {
- m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY - 1, a_RelZ));
- }
-
- if (a_RelZ < cChunkDef::Width - 1)
- {
- m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ + 1));
- }
- else
+ if (!IsValid())
{
- m_ChunkMap->CheckBlock(BlockX, a_RelY, BlockZ + 1);
+ return;
}
- if (a_RelZ > 0)
- {
- m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ - 1));
- }
- else
- {
- m_ChunkMap->CheckBlock(BlockX, a_RelY, BlockZ - 1);
- }
+ m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ));
}
-void cChunk::CheckBlock(int a_RelX, int a_RelY, int a_RelZ)
+void cChunk::QueueTickBlockNeighbors(int a_RelX, int a_RelY, int a_RelZ)
{
- if (!IsValid())
+ int BlockX = m_PosX * cChunkDef::Width + a_RelX;
+ int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
+ struct
{
- return;
+ int x, y, z;
}
-
- m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ));
+ Coords[] =
+ {
+ { 1, 0, 0},
+ {-1, 0, 0},
+ { 0, 1, 0},
+ { 0, -1, 0},
+ { 0, 0, 1},
+ { 0, 0, -1},
+ } ;
+ for (int i = 0; i < ARRAYCOUNT(Coords); i++)
+ {
+ cChunk * ch = GetNeighborChunk(BlockX + Coords[i].x, a_RelY, BlockZ + Coords[i].z);
+ if (ch != NULL)
+ {
+ ch->QueueTickBlock(a_RelX + Coords[i].x, a_RelY + Coords[i].y, a_RelZ + Coords[i].z);
+ }
+ } // for i - Coords[]
}
-void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta)
+void cChunk::FastSetBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta)
{
ASSERT(!((a_X < 0 || a_X >= Width || a_Y < 0 || a_Y >= Height || a_Z < 0 || a_Z >= Width)));
@@ -1833,6 +1805,74 @@ void cChunk::GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_Bloc
+cChunk * cChunk::GetNeighborChunk(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ // Convert coords to relative, then call the relative version:
+ a_BlockX -= m_PosX * cChunkDef::Width;
+ a_BlockZ -= m_PosZ * cChunkDef::Width;
+ return GetRelNeighborChunk(a_BlockX, a_BlockY, a_BlockZ);
+}
+
+
+
+
+
+cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelY, int a_RelZ)
+{
+ bool ReturnThis = true;
+ if (a_RelX < 0)
+ {
+ if (m_NeighborXM != NULL)
+ {
+ cChunk * Candidate = m_NeighborXM->GetRelNeighborChunk(a_RelX + cChunkDef::Width, a_RelY, a_RelZ);
+ if (Candidate != NULL)
+ {
+ return Candidate;
+ }
+ }
+ // Going X first failed, but if the request is crossing Z as well, let's try the Z first later on.
+ ReturnThis = false;
+ }
+ else if (a_RelX >= cChunkDef::Width)
+ {
+ if (m_NeighborXP != NULL)
+ {
+ cChunk * Candidate = m_NeighborXP->GetRelNeighborChunk(a_RelX - cChunkDef::Width, a_RelY, a_RelZ);
+ if (Candidate != NULL)
+ {
+ return Candidate;
+ }
+ }
+ // Going X first failed, but if the request is crossing Z as well, let's try the Z first later on.
+ ReturnThis = false;
+ }
+
+ if (a_RelZ < 0)
+ {
+ if (m_NeighborZM != NULL)
+ {
+ return m_NeighborZM->GetRelNeighborChunk(a_RelX, a_RelY, a_RelZ + cChunkDef::Width);
+ // For requests crossing both X and Z, the X-first way has been already tried
+ }
+ return NULL;
+ }
+ else if (a_RelZ >= cChunkDef::Width)
+ {
+ if (m_NeighborZP != NULL)
+ {
+ return m_NeighborZP->GetRelNeighborChunk(a_RelX, a_RelY, a_RelZ - cChunkDef::Width);
+ // For requests crossing both X and Z, the X-first way has been already tried
+ }
+ return NULL;
+ }
+
+ return (ReturnThis ? this : NULL);
+}
+
+
+
+
+
void cChunk::BroadcastPlayerAnimation(const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude)
{
for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
diff --git a/source/Chunk.h b/source/Chunk.h
index 7985bbff0..324929cac 100644
--- a/source/Chunk.h
+++ b/source/Chunk.h
@@ -131,16 +131,30 @@ public:
void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta );
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); }
- void CheckBlock(int a_RelX, int a_RelY, int a_RelZ);
+
+ /// Queues block for ticking (m_ToTickQueue)
+ void QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ);
+
+ /// Queues all 6 neighbors of the specified block for ticking (m_ToTickQueue). If any are outside the chunk, relays the checking to the proper neighboring chunk
+ void QueueTickBlockNeighbors(int a_RelX, int a_RelY, int a_RelZ);
+
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
BLOCKTYPE GetBlock( int a_X, int a_Y, int a_Z );
BLOCKTYPE GetBlock( int a_BlockIdx );
void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
void GetBlockInfo (int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
- /// Queues all 6 neighbors of the specified block for checking. If outside the chunk, relays the checking to the neighboring chunk
- void CheckNeighbors(int a_RelX, int a_RelY, int a_RelZ);
-
+ /** Returns the chunk into which the specified block belongs, by walking the neighbors.
+ Will return self if appropriate. Returns NULL if not reachable through neighbors.
+ */
+ cChunk * GetNeighborChunk(int a_BlockX, int a_BlockY, int a_BlockZ);
+
+ /**
+ Returns the chunk into which the relatively-specified block belongs, by walking the neighbors.
+ Will return self if appropriate. Returns NULL if not reachable through neighbors.
+ */
+ cChunk * GetRelNeighborChunk(int a_RelX, int a_RelY, int a_RelZ);
+
EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); }
void CollectPickupsByPlayer(cPlayer * a_Player);
diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp
index 5ccdf35ca..824c7cbfe 100644
--- a/source/ChunkMap.cpp
+++ b/source/ChunkMap.cpp
@@ -641,6 +641,23 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
+void cChunkMap::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ cCSLock Lock(m_CSLayers);
+ int ChunkX, ChunkZ;
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
+ {
+ return;
+ }
+ m_World->GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ, Chunk);
+}
+
+
+
+
+
void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
@@ -1002,6 +1019,7 @@ void cChunkMap::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_B
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->SetBlock(X, Y, Z, a_BlockType, a_BlockMeta );
+ m_World->GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ, Chunk);
}
}
@@ -1164,10 +1182,9 @@ bool cChunkMap::DigBlock(int a_X, int a_Y, int a_Z)
}
DestChunk->SetBlock(PosX, PosY, PosZ, E_BLOCK_AIR, 0 );
+ m_World->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z, DestChunk);
}
- m_World->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z);
-
return true;
}
@@ -1810,7 +1827,7 @@ void cChunkMap::ChunkValidated(void)
-void cChunkMap::CheckBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cChunkMap::QueueTickBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
{
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
@@ -1820,7 +1837,7 @@ void cChunkMap::CheckBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if (Chunk != NULL)
{
- Chunk->CheckBlock(a_BlockX, a_BlockY, a_BlockZ);
+ Chunk->QueueTickBlock(a_BlockX, a_BlockY, a_BlockZ);
}
}
diff --git a/source/ChunkMap.h b/source/ChunkMap.h
index 12c6e7275..86cbf35a2 100644
--- a/source/ChunkMap.h
+++ b/source/ChunkMap.h
@@ -96,6 +96,9 @@ public:
/// a_Player rclked block entity at the coords specified, handle it
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z);
+
+ /// Wakes up simulators for the specified block
+ void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
@@ -256,8 +259,8 @@ public:
void ChunkValidated(void); // Called by chunks that have become valid
- /// Schedules the specified block for checking (block update)
- void CheckBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
+ /// Queues the specified block for ticking (block update)
+ void QueueTickBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
private:
diff --git a/source/Simulator/ClassicFluidSimulator.cpp b/source/Simulator/ClassicFluidSimulator.cpp
index e195ffdc5..e005e7381 100644
--- a/source/Simulator/ClassicFluidSimulator.cpp
+++ b/source/Simulator/ClassicFluidSimulator.cpp
@@ -284,8 +284,9 @@ cClassicFluidSimulator::~cClassicFluidSimulator()
-void cClassicFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cClassicFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
+ // TODO: This can be optimized
BLOCKTYPE BlockType = m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (!IsAllowedBlock(BlockType)) // This should save very much time because it doesn´t have to iterate through all blocks
{
@@ -389,17 +390,15 @@ void cClassicFluidSimulator::Simulate(float a_Dt)
}
if (pos.y > 0)
{
- m_World->FastSetBlock( pos.x, pos.y-1, pos.z, m_FluidBlock, 8 ); // falling
- AddBlock( pos.x, pos.y-1, pos.z );
+ m_World->SetBlock(pos.x, pos.y - 1, pos.z, m_FluidBlock, 8); // falling
ApplyUniqueToNearest(pos - Vector3i(0, 1, 0));
}
}
- if (IsSolidBlock(DownID)||( BlockID == m_StationaryFluidBlock)) // Not falling
+ if (IsSolidBlock(DownID) || (BlockID == m_StationaryFluidBlock)) // Not falling
{
if (Feed + m_Falloff < Meta)
{
- m_World->FastSetBlock( pos.x, pos.y, pos.z, m_FluidBlock, Feed + m_Falloff);
- AddBlock( pos.x, pos.y, pos.z );
+ m_World->SetBlock(pos.x, pos.y, pos.z, m_FluidBlock, Feed + m_Falloff);
ApplyUniqueToNearest(pos);
}
else if ((Meta < m_MaxHeight ) || (BlockID == m_StationaryFluidBlock)) // max is the lowest, so it cannot spread
@@ -426,21 +425,20 @@ void cClassicFluidSimulator::Simulate(float a_Dt)
if (p.y == pos.y)
{
- m_World->FastSetBlock(p.x, p.y, p.z, m_FluidBlock, Meta + m_Falloff);
+ m_World->SetBlock(p.x, p.y, p.z, m_FluidBlock, Meta + m_Falloff);
}
else
{
- m_World->FastSetBlock(p.x, p.y, p.z, m_FluidBlock, 8);
+ m_World->SetBlock(p.x, p.y, p.z, m_FluidBlock, 8);
}
- AddBlock( p.x, p.y, p.z );
ApplyUniqueToNearest(p);
}
else // it's fluid
{
- char PointMeta = m_World->GetBlockMeta( p.x, p.y, p.z );
- if( PointMeta > Meta + m_Falloff)
+ NIBBLETYPE PointMeta = m_World->GetBlockMeta(p.x, p.y, p.z);
+ if (PointMeta > Meta + m_Falloff)
{
- AddBlock( p.x, p.y, p.z );
+ // TODO: AddBlock(p.x, p.y, p.z);
ApplyUniqueToNearest(p);
}
}
@@ -448,10 +446,9 @@ void cClassicFluidSimulator::Simulate(float a_Dt)
}
}
}
- else// not fed
+ else // not fed
{
- m_World->FastSetBlock( pos.x, pos.y, pos.z, E_BLOCK_AIR, 0 );
- WakeUp( pos.x, pos.y, pos.z );
+ m_World->SetBlock(pos.x, pos.y, pos.z, E_BLOCK_AIR, 0);
}
}
}
diff --git a/source/Simulator/ClassicFluidSimulator.h b/source/Simulator/ClassicFluidSimulator.h
index 4198f16de..95dfd9e4a 100644
--- a/source/Simulator/ClassicFluidSimulator.h
+++ b/source/Simulator/ClassicFluidSimulator.h
@@ -24,7 +24,7 @@ public:
// cSimulator overrides:
virtual void Simulate(float a_Dt) override;
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) override;
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
protected:
NIBBLETYPE GetHighestLevelAround(int a_BlockX, int a_BlockY, int a_BlockZ);
diff --git a/source/Simulator/DelayedFluidSimulator.cpp b/source/Simulator/DelayedFluidSimulator.cpp
index 317452c57..e0faf5b18 100644
--- a/source/Simulator/DelayedFluidSimulator.cpp
+++ b/source/Simulator/DelayedFluidSimulator.cpp
@@ -36,7 +36,7 @@ cDelayedFluidSimulator::~cDelayedFluidSimulator()
-void cDelayedFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cDelayedFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
{
@@ -44,6 +44,7 @@ void cDelayedFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
return;
}
+ // TODO: This can be optimized:
BLOCKTYPE BlockType = m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (BlockType != m_FluidBlock)
{
diff --git a/source/Simulator/DelayedFluidSimulator.h b/source/Simulator/DelayedFluidSimulator.h
index 51fe2a514..d8ba3f858 100644
--- a/source/Simulator/DelayedFluidSimulator.h
+++ b/source/Simulator/DelayedFluidSimulator.h
@@ -25,7 +25,7 @@ public:
virtual ~cDelayedFluidSimulator();
// cSimulator overrides:
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) override;
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
virtual void Simulate(float a_Dt) override;
protected:
diff --git a/source/Simulator/FireSimulator.cpp b/source/Simulator/FireSimulator.cpp
index 8579c2c17..0ebac74b3 100644
--- a/source/Simulator/FireSimulator.cpp
+++ b/source/Simulator/FireSimulator.cpp
@@ -72,8 +72,9 @@ bool cFireSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
-void cFireSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cFireSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
+ // TODO: This can be optimized
BLOCKTYPE BlockType = m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (!IsAllowedBlock(BlockType))
{
diff --git a/source/Simulator/FireSimulator.h b/source/Simulator/FireSimulator.h
index 826d24340..d95ecf4f0 100644
--- a/source/Simulator/FireSimulator.h
+++ b/source/Simulator/FireSimulator.h
@@ -23,7 +23,7 @@ public:
virtual bool FiresForever( BLOCKTYPE a_BlockType );
protected:
- virtual void AddBlock(int a_X, int a_Y, int a_Z) override;
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
virtual bool BurnBlockAround(int a_X, int a_Y, int a_Z);
virtual bool BurnBlock(int a_X, int a_Y, int a_Z);
diff --git a/source/Simulator/RedstoneSimulator.cpp b/source/Simulator/RedstoneSimulator.cpp
index 1862537e0..d6afda413 100644
--- a/source/Simulator/RedstoneSimulator.cpp
+++ b/source/Simulator/RedstoneSimulator.cpp
@@ -29,10 +29,9 @@ cRedstoneSimulator::~cRedstoneSimulator()
-void cRedstoneSimulator::WakeUp( int a_X, int a_Y, int a_Z )
+void cRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
- cCSLock Lock( m_CS );
- m_Blocks.push_back( Vector3i( a_X, a_Y, a_Z ) );
+ m_Blocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
}
diff --git a/source/Simulator/RedstoneSimulator.h b/source/Simulator/RedstoneSimulator.h
index 0b0333164..df5874d07 100644
--- a/source/Simulator/RedstoneSimulator.h
+++ b/source/Simulator/RedstoneSimulator.h
@@ -18,7 +18,7 @@ public:
virtual void Simulate( float a_Dt ) override;
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return true; }
- virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ) override;
+ virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
enum eRedstoneDirection
{
@@ -56,7 +56,7 @@ private:
void SetRepeater(const Vector3i & a_Position, int a_Ticks, bool a_bPowerOn);
- virtual void AddBlock(int a_X, int a_Y, int a_Z) {}
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override {}
void HandleChange( const Vector3i & a_BlockPos );
BlockList RemoveCurrent( const Vector3i & a_BlockPos );
@@ -77,6 +77,7 @@ private:
void RefreshTorchesAround( const Vector3i & a_BlockPos );
+ // TODO: The entire simulator is synchronized, no need to lock data structures; remove this
cCriticalSection m_CS;
};
diff --git a/source/Simulator/SandSimulator.cpp b/source/Simulator/SandSimulator.cpp
index 69513afef..f9d58f030 100644
--- a/source/Simulator/SandSimulator.cpp
+++ b/source/Simulator/SandSimulator.cpp
@@ -6,6 +6,8 @@
#include "../BlockID.h"
#include "../Defines.h"
#include "../FallingBlock.h"
+#include "../Chunk.h"
+
@@ -70,19 +72,29 @@ bool cSandSimulator::IsAllowedBlock( BLOCKTYPE a_BlockType )
-void cSandSimulator::AddBlock(int a_X, int a_Y, int a_Z)
+void cSandSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
- if(!IsAllowedBlock(m_World->GetBlock(a_X, a_Y, a_Z)))
+ // TODO: Optimize this by passing the block type along
+ int RelX = a_BlockX;
+ int RelY = a_BlockY;
+ int RelZ = a_BlockZ;
+ int ChunkX, ChunkZ;
+ cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
+ if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, RelY, RelZ)))
+ {
return;
+ }
- Vector3i Block(a_X, a_Y, a_Z);
+ Vector3i Block(a_BlockX, a_BlockY, a_BlockZ);
//check for duplicates
- for( BlockList::iterator itr = m_Blocks->begin(); itr != m_Blocks->end(); ++itr )
+ for (BlockList::iterator itr = m_Blocks->begin(); itr != m_Blocks->end(); ++itr)
{
Vector3i Pos = *itr;
- if( Pos.x == a_X && Pos.y == a_Y && Pos.z == a_Z )
+ if ((Pos.x == a_BlockX) && (Pos.y == a_BlockY) && (Pos.z == a_BlockZ))
+ {
return;
+ }
}
m_Blocks->push_back(Block);
@@ -92,10 +104,10 @@ void cSandSimulator::AddBlock(int a_X, int a_Y, int a_Z)
-bool cSandSimulator::IsPassable( BLOCKTYPE a_BlockType )
+bool cSandSimulator::IsPassable(BLOCKTYPE a_BlockType)
{
- return a_BlockType == E_BLOCK_AIR
+ return (a_BlockType == E_BLOCK_AIR)
|| IsBlockWater(a_BlockType)
|| IsBlockLava(a_BlockType)
- || a_BlockType == E_BLOCK_FIRE;
+ || (a_BlockType == E_BLOCK_FIRE);
}
diff --git a/source/Simulator/SandSimulator.h b/source/Simulator/SandSimulator.h
index 928ea63fc..4b786678c 100644
--- a/source/Simulator/SandSimulator.h
+++ b/source/Simulator/SandSimulator.h
@@ -21,7 +21,7 @@ public:
virtual bool IsPassable( BLOCKTYPE a_BlockType );
protected:
- virtual void AddBlock(int a_X, int a_Y, int a_Z) override;
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
typedef std::list <Vector3i> BlockList;
BlockList * m_Blocks;
diff --git a/source/Simulator/Simulator.cpp b/source/Simulator/Simulator.cpp
index 86b37e989..8560163c5 100644
--- a/source/Simulator/Simulator.cpp
+++ b/source/Simulator/Simulator.cpp
@@ -6,6 +6,7 @@
#include "../Vector3i.h"
#include "../BlockID.h"
#include "../Defines.h"
+#include "../Chunk.h"
@@ -28,15 +29,15 @@ cSimulator::~cSimulator()
-void cSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
- AddBlock(a_BlockX, a_BlockY, a_BlockZ);
- AddBlock(a_BlockX - 1, a_BlockY, a_BlockZ);
- AddBlock(a_BlockX + 1, a_BlockY, a_BlockZ);
- AddBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
- AddBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
- AddBlock(a_BlockX, a_BlockY, a_BlockZ - 1);
- AddBlock(a_BlockX, a_BlockY, a_BlockZ + 1);
+ AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
+ AddBlock(a_BlockX, a_BlockY - 1, a_BlockZ, a_Chunk);
+ AddBlock(a_BlockX, a_BlockY + 1, a_BlockZ, a_Chunk);
+ AddBlock(a_BlockX - 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockY, a_BlockZ));
+ AddBlock(a_BlockX + 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockY, a_BlockZ));
+ AddBlock(a_BlockX, a_BlockY, a_BlockZ - 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockY, a_BlockZ - 1));
+ AddBlock(a_BlockX, a_BlockY, a_BlockZ + 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockY, a_BlockZ + 1));
}
diff --git a/source/Simulator/Simulator.h b/source/Simulator/Simulator.h
index 1fecb0c96..ee3489b02 100644
--- a/source/Simulator/Simulator.h
+++ b/source/Simulator/Simulator.h
@@ -8,6 +8,7 @@
class cWorld;
+class cChunk;
@@ -19,17 +20,17 @@ public:
cSimulator(cWorld * a_World);
virtual ~cSimulator();
- /// Called in each tick, a_Dt is the time passed since the last tick
+ /// Called in each tick, a_Dt is the time passed since the last tick, in msec
virtual void Simulate(float a_Dt) = 0;
- /// Called when a block changes via cWorld::SetBlock()
- virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ);
+ /// Called when a block changes
+ virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk);
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) = 0;
protected:
/// Called to simulate a new block
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) = 0;
cWorld * m_World;
} ;
diff --git a/source/Simulator/SimulatorManager.cpp b/source/Simulator/SimulatorManager.cpp
index c74b273f7..ceebc2d8f 100644
--- a/source/Simulator/SimulatorManager.cpp
+++ b/source/Simulator/SimulatorManager.cpp
@@ -40,11 +40,11 @@ void cSimulatorManager::Simulate( float a_Dt )
-void cSimulatorManager::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cSimulatorManager::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr )
{
- itr->first->WakeUp(a_BlockX, a_BlockY, a_BlockZ);
+ itr->first->WakeUp(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
}
}
diff --git a/source/Simulator/SimulatorManager.h b/source/Simulator/SimulatorManager.h
index fbd97b8fa..989831b03 100644
--- a/source/Simulator/SimulatorManager.h
+++ b/source/Simulator/SimulatorManager.h
@@ -15,6 +15,13 @@
+// fwd: Chunk.h
+class cChunk;
+
+
+
+
+
class cSimulatorManager
{
public:
@@ -22,7 +29,7 @@ public:
~cSimulatorManager();
void Simulate(float a_Dt);
- void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ);
+ void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk);
void RegisterSimulator(cSimulator * a_Simulator, int a_Rate); // Takes ownership of the simulator object!
diff --git a/source/World.cpp b/source/World.cpp
index 2c31371d2..0236a456b 100644
--- a/source/World.cpp
+++ b/source/World.cpp
@@ -687,6 +687,15 @@ void cWorld::TickSpawnMobs(float a_Dt)
+void cWorld::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ return m_ChunkMap->WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
+}
+
+
+
+
+
bool cWorld::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback)
{
return m_ChunkMap->ForEachChestInChunk(a_ChunkX, a_ChunkZ, a_Callback);
@@ -1030,7 +1039,6 @@ void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_Bloc
}
m_ChunkMap->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
- GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ);
BlockHandler(a_BlockType)->OnPlaced(this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
}
diff --git a/source/World.h b/source/World.h
index b744a66c1..6fc3fa088 100644
--- a/source/World.h
+++ b/source/World.h
@@ -312,6 +312,9 @@ public:
inline cFluidSimulator * GetWaterSimulator(void) { return m_WaterSimulator; }
inline cFluidSimulator * GetLavaSimulator (void) { return m_LavaSimulator; }
+
+ /// Wakes up the simulators for the specified block
+ void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);
/// Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true
bool ForEachChestInChunk (int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp