summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h5
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp73
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h16
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h3
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h7
5 files changed, 76 insertions, 28 deletions
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);
- /** 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);
+ /** 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);
+
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;
}
}