diff --git a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h index 2d0eb959d..fb0671fdc 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h @@ -65,6 +65,11 @@ namespace DropSpenserHandler UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); + + // Consider indirect power: + Callback.CheckIndirectPower(); + + // Consider normal adjacents: InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp index 178ee00a0..4c676b405 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp @@ -23,25 +23,6 @@ ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3 -bool ForEachSourceCallback::ShouldQueryLinkedPosition(const Vector3i Location, const BLOCKTYPE Block) -{ - switch (Block) - { - // Normally we don't ask solid blocks for power because they don't have any (store, dirt, etc.) - // However, these are mechanisms that are IsSolid, but still give power. Don't ignore them: - case E_BLOCK_BLOCK_OF_REDSTONE: - case E_BLOCK_OBSERVER: - case E_BLOCK_TRAPPED_CHEST: return false; - - // If a mechanism asks for power from a block, redirect the query to linked positions if: - default: return cBlockInfo::IsSolid(Block); - } -} - - - - - void ForEachSourceCallback::operator()(Vector3i Location) { if (!cChunk::IsValidHeight(Location.y)) @@ -58,7 +39,7 @@ void ForEachSourceCallback::operator()(Vector3i Location) const auto PotentialSourceBlock = NeighbourChunk->GetBlock(Location); const auto NeighbourRelativeQueryPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position); - if (ShouldQueryLinkedPosition(Location, PotentialSourceBlock)) + if (ShouldQueryLinkedPosition(PotentialSourceBlock)) { Power = std::max(Power, QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location)); } @@ -78,6 +59,58 @@ void ForEachSourceCallback::operator()(Vector3i Location) +void ForEachSourceCallback::CheckIndirectPower() +{ + const Vector3i OffsetYP(0, 1, 0); + const auto Above = m_Position + OffsetYP; + + if (Above.y == cChunkDef::Height) + { + return; + } + + // Object representing restarted power calculation where the + // block above this piston, dropspenser is requesting a power level. + ForEachSourceCallback QuasiQueryCallback(m_Chunk, Above, m_Chunk.GetBlock(Above)); + + // Manually feed the callback object all positions that may deliver power to Above: + for (const auto QuasiPowerOffset : cSimulator::GetLinkedOffsets(OffsetYP)) + { + QuasiQueryCallback(m_Position + QuasiPowerOffset); + } + + // Get the results: + Power = std::max(Power, QuasiQueryCallback.Power); +} + + + + + +bool ForEachSourceCallback::ShouldQueryLinkedPosition(const BLOCKTYPE Block) +{ + switch (Block) + { + // Normally we don't ask solid blocks for power because they don't have any (store, dirt, etc.) + // However, these are mechanisms that are IsSolid, but still give power. Don't ignore them: + case E_BLOCK_BLOCK_OF_REDSTONE: + case E_BLOCK_OBSERVER: + case E_BLOCK_TRAPPED_CHEST: return false; + + // Pistons are solid but don't participate in link powering: + case E_BLOCK_PISTON: + case E_BLOCK_PISTON_EXTENSION: + case E_BLOCK_STICKY_PISTON: return false; + + // If a mechanism asks for power from a block, redirect the query to linked positions if: + default: return cBlockInfo::IsSolid(Block); + } +} + + + + + PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition) { PowerLevel Power = 0; diff --git a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h index 6d49291cb..66b56aa5a 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h +++ b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h @@ -13,20 +13,24 @@ public: ForEachSourceCallback(const cChunk & Chunk, Vector3i Position, BLOCKTYPE CurrentBlock); - /** Returns whether a potential source position should be treated as linked. */ - bool ShouldQueryLinkedPosition(Vector3i Location, BLOCKTYPE Block); - /** Callback invoked for each potential source position of the redstone component. */ void operator()(Vector3i Location); + /** Callback invoked for blocks supporting quasiconnectivity. */ + void CheckIndirectPower(); + + // The maximum power level of all source locations. + PowerLevel Power; + +private: + + /** Returns whether a potential source position that's occupied by Block should be treated as linked. */ + static bool ShouldQueryLinkedPosition(BLOCKTYPE Block); + /** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block. Both QueryPosition and SolidBlockPosition are relative to Chunk. */ static PowerLevel QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition); - PowerLevel Power; - -private: - const cChunk & m_Chunk; const Vector3i m_Position; const BLOCKTYPE m_CurrentBlock; diff --git a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h index f0cdda3f8..851b32498 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h @@ -60,5 +60,8 @@ namespace PistonHandler Callback(a_Position + Offset); } } + + // Consider indirect power: + Callback.CheckIndirectPower(); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h index 2e04b4b75..0bf3d58f3 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h @@ -88,11 +88,14 @@ namespace RedstoneWireHandler return a_Offset.z != 0; } case E_BLOCK_ACTIVE_COMPARATOR: - case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_BLOCK_OF_REDSTONE: + case E_BLOCK_INACTIVE_COMPARATOR: + case E_BLOCK_LEVER: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: - case E_BLOCK_REDSTONE_WIRE: return true; + case E_BLOCK_REDSTONE_WIRE: + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_WOODEN_BUTTON: return true; default: return false; } }