From 2588f5a605d135bc01996f3a685444dfb37978f8 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Thu, 28 Feb 2013 07:42:45 +0000 Subject: [PATCH] Simulators now have direct access to the cChunk object in the WakeUp() call git-svn-id: http://mc-server.googlecode.com/svn/trunk@1227 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Blocks/BlockHandler.cpp | 4 +- source/Chunk.cpp | 178 +++++++++++++-------- source/Chunk.h | 22 ++- source/ChunkMap.cpp | 25 ++- source/ChunkMap.h | 7 +- source/Simulator/ClassicFluidSimulator.cpp | 27 ++-- source/Simulator/ClassicFluidSimulator.h | 2 +- source/Simulator/DelayedFluidSimulator.cpp | 3 +- source/Simulator/DelayedFluidSimulator.h | 2 +- source/Simulator/FireSimulator.cpp | 3 +- source/Simulator/FireSimulator.h | 2 +- source/Simulator/RedstoneSimulator.cpp | 5 +- source/Simulator/RedstoneSimulator.h | 5 +- source/Simulator/SandSimulator.cpp | 28 +++- source/Simulator/SandSimulator.h | 2 +- source/Simulator/Simulator.cpp | 17 +- source/Simulator/Simulator.h | 9 +- source/Simulator/SimulatorManager.cpp | 4 +- source/Simulator/SimulatorManager.h | 9 +- source/World.cpp | 10 +- source/World.h | 3 + 21 files changed, 236 insertions(+), 131 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,62 +1177,7 @@ 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) -{ - 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 - { - m_ChunkMap->CheckBlock(BlockX, a_RelY, BlockZ + 1); - } - - 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); - } -} - - - - - -void cChunk::CheckBlock(int a_RelX, int a_RelY, int a_RelZ) +void cChunk::QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ) { if (!IsValid()) { @@ -1250,7 +1191,38 @@ void cChunk::CheckBlock(int a_RelX, int a_RelY, int a_RelZ) -void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta) +void cChunk::QueueTickBlockNeighbors(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; + struct + { + int x, y, z; + } + 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) { 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 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