summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h')
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h255
1 files changed, 139 insertions, 116 deletions
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h
index 8f5e8c1b7..ea10e004e 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h
@@ -9,147 +9,170 @@
namespace RedstoneRepeaterHandler
{
- static bool IsOn(BLOCKTYPE a_Block)
- {
- return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON);
- }
-
- /** Returns a pair with first element indicating if the block at the given position is an activated repeater.
- If it is activated, the second element is the repeater metadata. */
- static std::pair<bool, NIBBLETYPE> IsOnRepeater(cChunk & Chunk, const Vector3i a_Position)
- {
- BLOCKTYPE Type;
- NIBBLETYPE Meta;
-
- if (!Chunk.UnboundedRelGetBlock(a_Position, Type, Meta))
- {
- return std::make_pair(false, static_cast<NIBBLETYPE>(0));
- }
+static bool IsOn(BLOCKTYPE a_Block)
+{
+ return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON);
+}
- return std::make_pair(IsOn(Type), Meta);
- }
+/** Returns a pair with first element indicating if the block at the given position is an activated repeater.
+If it is activated, the second element is the repeater metadata. */
+static std::pair<bool, NIBBLETYPE> IsOnRepeater(cChunk & Chunk, const Vector3i a_Position)
+{
+ BLOCKTYPE Type;
+ NIBBLETYPE Meta;
- /** Determine, from the metadata of a repeater on our left side, if they lock us.
- To test a repeater on our right, simply invert the order of arguments provided.
- "Left" is relative to the direction the repeater output faces, naturally. */
- static bool DoesLhsLockMe(NIBBLETYPE a_MetaLhs, NIBBLETYPE a_MyMeta)
+ if (!Chunk.UnboundedRelGetBlock(a_Position, Type, Meta))
{
- // Get the direction bits
- a_MetaLhs &= E_META_REDSTONE_REPEATER_FACING_MASK;
- a_MyMeta &= E_META_REDSTONE_REPEATER_FACING_MASK;
-
- /*
- Check for a valid locking configuration, where they are perpendicular and one snuggles into the other.
-
- Order of comparisons:
- XP >^ ZM
- ZP |_ XP
- XM <| ZP
- ZP ^< xM
-
- Key:
- ^ Facing up
- _ Facing right
- | Facing down
- < Facing left
- */
- return
- ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_XP) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_ZM)) ||
- ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_ZP) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_XP)) ||
- ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_XM) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_ZP)) ||
- ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_ZM) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_XM))
- ;
+ return std::make_pair(false, static_cast<NIBBLETYPE>(0));
}
- /** Determine if a repeater is locked.
- A locked repeater is one with another powered repeater facing them, to their immediate left or right sides.
- "Left" is relative to the direction the repeater output faces, naturally. */
- static bool IsLocked(cChunk & Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta)
- {
- // The left hand side offset. Will be negated to get the rhs offset
- const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta);
+ return std::make_pair(IsOn(Type), Meta);
+}
- // Test the block to the left of us
- const auto Lhs = IsOnRepeater(Chunk, LhsOffset + a_Position);
- if (Lhs.first && DoesLhsLockMe(Lhs.second, a_Meta))
- {
- return true;
- }
+/** Determine, from the metadata of a repeater on our left side, if they lock us.
+To test a repeater on our right, simply invert the order of arguments provided.
+"Left" is relative to the direction the repeater output faces, naturally. */
+static bool DoesLhsLockMe(NIBBLETYPE a_MetaLhs, NIBBLETYPE a_MyMeta)
+{
+ // Get the direction bits
+ a_MetaLhs &= E_META_REDSTONE_REPEATER_FACING_MASK;
+ a_MyMeta &= E_META_REDSTONE_REPEATER_FACING_MASK;
+
+ /*
+ Check for a valid locking configuration, where they are perpendicular and one snuggles into the other.
+
+ Order of comparisons:
+ XP >^ ZM
+ ZP |_ XP
+ XM <| ZP
+ ZP ^< xM
+
+ Key:
+ ^ Facing up
+ _ Facing right
+ | Facing down
+ < Facing left
+ */
+ return ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_XP) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_ZM)) ||
+ ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_ZP) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_XP)) ||
+ ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_XM) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_ZP)) ||
+ ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_ZM) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_XM));
+}
+
+/** Determine if a repeater is locked.
+A locked repeater is one with another powered repeater facing them, to their immediate left or right sides.
+"Left" is relative to the direction the repeater output faces, naturally. */
+static bool IsLocked(cChunk & Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta)
+{
+ // The left hand side offset. Will be negated to get the rhs offset
+ const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta);
- // Test the right side, flipping the argument order to DoesLhsLockMe
- const auto Rhs = IsOnRepeater(Chunk, -LhsOffset + a_Position);
- return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second);
+ // Test the block to the left of us
+ const auto Lhs = IsOnRepeater(Chunk, LhsOffset + a_Position);
+ if (Lhs.first && DoesLhsLockMe(Lhs.second, a_Meta))
+ {
+ return true;
}
- static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
+ // Test the right side, flipping the argument order to DoesLhsLockMe
+ const auto Rhs = IsOnRepeater(Chunk, -LhsOffset + a_Position);
+ return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second);
+}
+
+static PowerLevel GetPowerDeliveredToPosition(
+ const cChunk & a_Chunk,
+ Vector3i a_Position,
+ BLOCKTYPE a_BlockType,
+ Vector3i a_QueryPosition,
+ BLOCKTYPE a_QueryBlockType,
+ bool IsLinked
+)
+{
+ if (!IsOn(a_BlockType))
{
- if (!IsOn(a_BlockType))
- {
- return 0;
- }
-
- const auto FrontOffset = cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Chunk.GetMeta(a_Position));
- const auto FrontPosition = a_Position + FrontOffset;
- if (a_QueryPosition == FrontPosition)
- {
- return 15;
- }
-
return 0;
}
- static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
+ const auto FrontOffset = cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Chunk.GetMeta(a_Position));
+ const auto FrontPosition = a_Position + FrontOffset;
+ if (a_QueryPosition == FrontPosition)
{
- // LOGD("Evaluating loopy the repeater (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
-
- auto & Data = DataForChunk(a_Chunk);
- const auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
+ return 15;
+ }
- // If the repeater is locked by another, ignore and forget all power changes:
- if (IsLocked(a_Chunk, a_Position, a_Meta))
- {
- if (DelayInfo != nullptr)
- {
- Data.m_MechanismDelays.erase(a_Position);
- }
+ return 0;
+}
+
+static void Update(
+ cChunk & a_Chunk,
+ cChunk & CurrentlyTicking,
+ Vector3i a_Position,
+ BLOCKTYPE a_BlockType,
+ NIBBLETYPE a_Meta,
+ const PowerLevel Power
+)
+{
+ // LOGD("Evaluating loopy the repeater (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
- return;
- }
+ auto & Data = DataForChunk(a_Chunk);
+ const auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
- if (DelayInfo == nullptr)
+ // If the repeater is locked by another, ignore and forget all power changes:
+ if (IsLocked(a_Chunk, a_Position, a_Meta))
+ {
+ if (DelayInfo != nullptr)
{
- bool ShouldBeOn = (Power != 0);
- if (ShouldBeOn != IsOn(a_BlockType))
- {
- Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
- }
-
- return;
+ Data.m_MechanismDelays.erase(a_Position);
}
- int DelayTicks;
- bool ShouldPowerOn;
- std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
+ return;
+ }
- if (DelayTicks != 0)
+ if (DelayInfo == nullptr)
+ {
+ bool ShouldBeOn = (Power != 0);
+ if (ShouldBeOn != IsOn(a_BlockType))
{
- return;
+ Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
}
- const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
- a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
- Data.m_MechanismDelays.erase(a_Position);
-
- // While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
- // Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
- // FastSetBlock doesn't wake simulators, so manually update ourselves:
- Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, Power);
-
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
+ return;
}
- static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback)
+ int DelayTicks;
+ bool ShouldPowerOn;
+ std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
+
+ if (DelayTicks != 0)
{
- Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
+ return;
}
-};
+
+ const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
+ a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
+ Data.m_MechanismDelays.erase(a_Position);
+
+ // While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
+ // Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
+ // FastSetBlock doesn't wake simulators, so manually update ourselves:
+ Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, Power);
+
+ UpdateAdjustedRelative(
+ a_Chunk,
+ CurrentlyTicking,
+ a_Position,
+ cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta)
+ );
+}
+
+static void ForValidSourcePositions(
+ const cChunk & a_Chunk,
+ Vector3i a_Position,
+ BLOCKTYPE a_BlockType,
+ NIBBLETYPE a_Meta,
+ ForEachSourceCallback & Callback
+)
+{
+ Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
+}
+}; // namespace RedstoneRepeaterHandler