diff options
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h')
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h | 221 |
1 files changed, 132 insertions, 89 deletions
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h index df8f697a2..b90c4b693 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h @@ -9,44 +9,60 @@ namespace RedstoneComparatorHandler { - static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel) +static unsigned char GetFrontPowerLevel( + NIBBLETYPE a_Meta, + unsigned char a_HighestSidePowerLevel, + unsigned char a_HighestRearPowerLevel +) +{ + if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta)) { - if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta)) - { - // Subtraction mode - return static_cast<unsigned char>(std::max(static_cast<char>(a_HighestRearPowerLevel) - a_HighestSidePowerLevel, 0)); - } - else - { - // Comparison mode - return (a_HighestRearPowerLevel < a_HighestSidePowerLevel) ? 0 : a_HighestRearPowerLevel; - } + // Subtraction mode + return static_cast<unsigned char>( + std::max(static_cast<char>(a_HighestRearPowerLevel) - a_HighestSidePowerLevel, 0) + ); } - - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) + else { - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - - const auto Meta = a_Chunk.GetMeta(a_Position); - return ( - (cBlockComparatorHandler::GetFrontCoordinate(a_Position, Meta & 0x3) == a_QueryPosition) ? - DataForChunk(a_Chunk).GetCachedPowerData(a_Position) : 0 - ); + // Comparison mode + return (a_HighestRearPowerLevel < a_HighestSidePowerLevel) ? 0 : a_HighestRearPowerLevel; } +} + +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + + const auto Meta = a_Chunk.GetMeta(a_Position); + return ( + (cBlockComparatorHandler::GetFrontCoordinate(a_Position, Meta & 0x3) == a_QueryPosition) + ? DataForChunk(a_Chunk).GetCachedPowerData(a_Position) + : 0 + ); +} + +static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta) +{ + UInt8 SignalStrength = 0; + auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(Position, Meta & 0x3); - static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta) + auto RearChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RearCoordinate); + if ((RearChunk == nullptr) || !RearChunk->IsValid()) { - UInt8 SignalStrength = 0; - auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(Position, Meta & 0x3); - - auto RearChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RearCoordinate); - if ((RearChunk == nullptr) || !RearChunk->IsValid()) - { - return SignalStrength; - } + return SignalStrength; + } - RearChunk->DoWithBlockEntityAt(RearCoordinate, [&](cBlockEntity & a_BlockEntity) + RearChunk->DoWithBlockEntityAt( + RearCoordinate, + [&](cBlockEntity & a_BlockEntity) { // Skip BlockEntities that don't have slots auto BlockEntityWithItems = dynamic_cast<cBlockEntityWithItems *>(&a_BlockEntity); @@ -62,75 +78,102 @@ namespace RedstoneComparatorHandler for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot) { - Fullness += static_cast<float>(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize(); + Fullness += + static_cast<float>(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize(); } - SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast<UInt8>(1 + (Fullness / Contents.GetNumSlots()) * 14); + SignalStrength = (Fullness < 0.001 /* container empty? */) + ? 0 + : static_cast<UInt8>(1 + (Fullness / Contents.GetNumSlots()) * 14); return false; - }); - - const auto RearType = RearChunk->GetBlock(RearCoordinate); - return std::max( - SignalStrength, - RedstoneHandler::GetPowerDeliveredToPosition( - *RearChunk, RearCoordinate, RearType, - cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType, false - ) - ); - } - - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // Note that Power here contains the maximum * side * power level, as specified by GetValidSourcePositions - // LOGD("Evaluating ALU the comparator (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - auto & Data = DataForChunk(a_Chunk); - auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); - - // Delay is used here to prevent an infinite loop (#3168) - if (DelayInfo == nullptr) - { - const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); - const auto FrontPower = GetFrontPowerLevel(a_Meta, Power, RearPower); - const auto PreviousFrontPower = Data.GetCachedPowerData(a_Position); - const bool ShouldUpdate = (FrontPower != PreviousFrontPower); // "Business logic" (:P) - determined by side and rear power levels - - if (ShouldUpdate) - { - Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool()); - } - - return; } + ); + + const auto RearType = RearChunk->GetBlock(RearCoordinate); + return std::max( + SignalStrength, + RedstoneHandler::GetPowerDeliveredToPosition( + *RearChunk, + RearCoordinate, + RearType, + cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), + BlockType, + false + ) + ); +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // Note that Power here contains the maximum * side * power level, as specified by GetValidSourcePositions + // LOGD("Evaluating ALU the comparator (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - int DelayTicks; - std::tie(DelayTicks, std::ignore) = *DelayInfo; - - if (DelayTicks != 0) - { - return; - } + auto & Data = DataForChunk(a_Chunk); + auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); + // Delay is used here to prevent an infinite loop (#3168) + if (DelayInfo == nullptr) + { const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); const auto FrontPower = GetFrontPowerLevel(a_Meta, Power, RearPower); - const NIBBLETYPE NewMeta = (FrontPower > 0) ? (a_Meta | 0x08u) : (a_Meta & 0x07u); - - // Don't care about the previous power level so return value ignored - Data.ExchangeUpdateOncePowerData(a_Position, FrontPower); + const auto PreviousFrontPower = Data.GetCachedPowerData(a_Position); + const bool ShouldUpdate = + (FrontPower != PreviousFrontPower); // "Business logic" (:P) - determined by side and rear power levels - a_Chunk.SetMeta(a_Position, NewMeta); - Data.m_MechanismDelays.erase(a_Position); + if (ShouldUpdate) + { + Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool()); + } - // Assume that an update (to front power) is needed: - UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) - a_Position); + return; } - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_BlockType); + int DelayTicks; + std::tie(DelayTicks, std::ignore) = *DelayInfo; - Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, false)); - Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, true)); + if (DelayTicks != 0) + { + return; } -}; + + const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); + const auto FrontPower = GetFrontPowerLevel(a_Meta, Power, RearPower); + const NIBBLETYPE NewMeta = (FrontPower > 0) ? (a_Meta | 0x08u) : (a_Meta & 0x07u); + + // Don't care about the previous power level so return value ignored + Data.ExchangeUpdateOncePowerData(a_Position, FrontPower); + + a_Chunk.SetMeta(a_Position, NewMeta); + Data.m_MechanismDelays.erase(a_Position); + + // Assume that an update (to front power) is needed: + UpdateAdjustedRelative( + a_Chunk, + CurrentlyTicking, + a_Position, + cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) - a_Position + ); +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + + Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, false)); + Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, true)); +} +}; // namespace RedstoneComparatorHandler |