From 19ad96561c255fcc1e54ea3717a7d6afd50f5c92 Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Sun, 5 Apr 2020 20:20:52 +0100 Subject: Filter blocks to add to redstone sim's wake queue (#4621) --- src/Chunk.h | 1 + .../IncrementalRedstoneSimulator.cpp | 63 +++++++++++++++++++++- .../IncrementalRedstoneSimulator.h | 5 +- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/Chunk.h b/src/Chunk.h index 39dc07a9f..7ba12f5ef 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -151,6 +151,7 @@ public: int GetPosX(void) const { return m_PosX; } int GetPosZ(void) const { return m_PosZ; } + cChunkCoords GetPos() const { return {m_PosX, m_PosZ}; } cWorld * GetWorld(void) const { return m_World; } diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp index ddd682288..6be03c947 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp @@ -157,8 +157,7 @@ void cIncrementalRedstoneSimulator::Simulate(float a_dt) if (CurrentHandler == nullptr) // Block at CurrentPosition doesn't have a corresponding redstone handler { // Clean up cached PowerData for CurrentPosition - static_cast(m_World.GetRedstoneSimulator())->GetChunkData()->ErasePowerData(CurrentLocation); - + GetChunkData()->ErasePowerData(CurrentLocation); continue; } @@ -193,3 +192,63 @@ void cIncrementalRedstoneSimulator::Simulate(float a_dt) } } } + + + + + +void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk) +{ + // Can't inspect block, so queue update anyway + if (a_Chunk == nullptr) + { + m_Data.WakeUp(a_Block); + return; + } + + const auto RelPos = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos()); + const auto CurBlock = a_Chunk->GetBlock(RelPos); + + // Always update redstone devices + if (IsRedstone(CurBlock)) + { + m_Data.WakeUp(a_Block); + return; + } + + // Never update blocks without a handler + if (GetComponentHandler(CurBlock) == nullptr) + { + GetChunkData()->ErasePowerData(a_Block); + return; + } + + // Only update others if there is a redstone device nearby + for (int x = -1; x < 2; ++x) + { + for (int y = -1; y < 2; ++y) + { + if (!cChunkDef::IsValidHeight(RelPos.y + y)) + { + continue; + } + + for (int z = -1; z < 2; ++z) + { + auto CheckPos = RelPos + Vector3i{x, y, z}; + BLOCKTYPE Block; + NIBBLETYPE Meta; + + // If we can't read the block, assume it is a mechanism + if ( + !a_Chunk->UnboundedRelGetBlock(CheckPos, Block, Meta) || + IsRedstone(Block) + ) + { + m_Data.WakeUp(a_Block); + return; + } + } + } + } +} diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h index e00db39b5..850bb30c4 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h @@ -31,10 +31,7 @@ public: return IsRedstone(a_BlockType); } - virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override - { - m_Data.WakeUp(a_Block); - } + virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override; /** Returns if a block is a mechanism (something that accepts power and does something) Used by torches to determine if they will power a block -- cgit v1.2.3