diff options
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator')
29 files changed, 2084 insertions, 1517 deletions
diff --git a/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h index 50ea6dcb6..4966d6859 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h @@ -9,42 +9,65 @@ namespace CommandBlockHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; - } +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); - if ((Previous != 0) || (Power == 0)) - { - // If we're already powered or received an update of no power, don't activate - return; - } + const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); + if ((Previous != 0) || (Power == 0)) + { + // If we're already powered or received an update of no power, don't activate + return; + } - a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity) + a_Chunk.DoWithBlockEntityAt( + a_Position, + [](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_COMMAND_BLOCK); static_cast<cCommandBlockEntity &>(a_BlockEntity).Activate(); return false; - }); - } + } + ); +} - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); - } -}; +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} +}; // namespace CommandBlockHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/DaylightSensorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DaylightSensorHandler.h index 75e6651da..a520960dc 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DaylightSensorHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DaylightSensorHandler.h @@ -9,55 +9,75 @@ namespace DaylightSensorHandler { - static PowerLevel GetPowerLevel(const cChunk & a_Chunk, const Vector3i a_Position) +static PowerLevel GetPowerLevel(const cChunk & a_Chunk, const Vector3i a_Position) +{ + if (a_Chunk.GetBlock(a_Position) == E_BLOCK_INVERTED_DAYLIGHT_SENSOR) { - if (a_Chunk.GetBlock(a_Position) == E_BLOCK_INVERTED_DAYLIGHT_SENSOR) - { - // Inverted sensor directly returns darkened skylight, no fancy tricks: - return 15 - a_Chunk.GetSkyLightAltered(a_Position); - } - - // The [0, 1) proportion of the current day that has elapsed. - const auto ProportionOfDay = a_Chunk.GetWorld()->GetTimeOfDay().count() * (static_cast<float>(M_PI) / 12000.f); - - // The curved value of darkened skylight, with outputs somewhat similar to Vanilla. - const auto RawOutput = a_Chunk.GetSkyLightAltered(a_Position) * (0.6f * std::sin(ProportionOfDay) + 0.5f); - - // Saturate the amplified sine curve at 0 and 15: - return static_cast<PowerLevel>(std::clamp(RawOutput, 0.f, 15.f)); + // Inverted sensor directly returns darkened skylight, no fancy tricks: + return 15 - a_Chunk.GetSkyLightAltered(a_Position); } - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); + // The [0, 1) proportion of the current day that has elapsed. + const auto ProportionOfDay = a_Chunk.GetWorld()->GetTimeOfDay().count() * (static_cast<float>(M_PI) / 12000.f); - // Daylight sensors only output to immediately surrounding blocks: - return IsLinked ? 0 : a_Chunk.GetMeta(a_Position); - } + // The curved value of darkened skylight, with outputs somewhat similar to Vanilla. + const auto RawOutput = a_Chunk.GetSkyLightAltered(a_Position) * (0.6f * std::sin(ProportionOfDay) + 0.5f); - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating Darryl the daylight sensor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); + // Saturate the amplified sine curve at 0 and 15: + return static_cast<PowerLevel>(std::clamp(RawOutput, 0.f, 15.f)); +} - // What the sensor should output according to the time-power function. - const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position); +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + + // Daylight sensors only output to immediately surrounding blocks: + return IsLinked ? 0 : a_Chunk.GetMeta(a_Position); +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating Darryl the daylight sensor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - // Only update the output if the power level has changed: - if (PowerLevel != a_Meta) - { - a_Chunk.SetMeta(a_Position, PowerLevel); - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); - } - } + // What the sensor should output according to the time-power function. + const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position); - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + // Only update the output if the power level has changed: + if (PowerLevel != a_Meta) { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - UNUSED(Callback); + a_Chunk.SetMeta(a_Position, PowerLevel); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } -}; +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_Meta); + UNUSED(Callback); +} +}; // namespace DaylightSensorHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h index cb772bb5b..9e3a2b6d4 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h @@ -9,90 +9,110 @@ namespace DoorHandler { - // "Doormammu, I've come to bargain" +// "Doormammu, I've come to bargain" + +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} + +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + PowerLevel Power +) +{ + // LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; - } + NIBBLETYPE TopMeta; + const bool IsTop = (a_Meta & 0x8) == 0x8; + const auto TopPosition = IsTop ? a_Position : a_Position.addedY(1); - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + // Figure out the metadata of the top half, which stores the previous redstone power state: + if (IsTop) { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); + TopMeta = a_Meta; } - - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PowerLevel Power) + else { - // LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - NIBBLETYPE TopMeta; - const bool IsTop = (a_Meta & 0x8) == 0x8; - const auto TopPosition = IsTop ? a_Position : a_Position.addedY(1); - - // Figure out the metadata of the top half, which stores the previous redstone power state: - if (IsTop) + if (TopPosition.y == cChunkDef::Height) { - TopMeta = a_Meta; + return; } - else + + BLOCKTYPE AboveType; + a_Chunk.GetBlockTypeMeta(TopPosition, AboveType, TopMeta); + if (!cBlockDoorHandler::IsDoorBlockType(AboveType)) { - if (TopPosition.y == cChunkDef::Height) - { - return; - } - - BLOCKTYPE AboveType; - a_Chunk.GetBlockTypeMeta(TopPosition, AboveType, TopMeta); - if (!cBlockDoorHandler::IsDoorBlockType(AboveType)) - { - return; - } + return; } + } - const auto OppositeHalfPosition = a_Position + (IsTop ? OffsetYM : OffsetYP); - ForEachSourceCallback Callback(a_Chunk, OppositeHalfPosition, a_BlockType); - ForValidSourcePositions(a_Chunk, OppositeHalfPosition, a_BlockType, a_Meta, Callback); + const auto OppositeHalfPosition = a_Position + (IsTop ? OffsetYM : OffsetYP); + ForEachSourceCallback Callback(a_Chunk, OppositeHalfPosition, a_BlockType); + ForValidSourcePositions(a_Chunk, OppositeHalfPosition, a_BlockType, a_Meta, Callback); - // Factor in what the other half is getting: - Power = std::max(Power, Callback.Power); + // Factor in what the other half is getting: + Power = std::max(Power, Callback.Power); - const bool ShouldBeOpen = Power != 0; - const bool PreviouslyPowered = (TopMeta & 0x2) == 0x2; + const bool ShouldBeOpen = Power != 0; + const bool PreviouslyPowered = (TopMeta & 0x2) == 0x2; - // Allow players to override redstone control - // don't update if redstone power hasn't changed since we last saw it: - if (ShouldBeOpen == PreviouslyPowered) - { - return; - } + // Allow players to override redstone control + // don't update if redstone power hasn't changed since we last saw it: + if (ShouldBeOpen == PreviouslyPowered) + { + return; + } - // Update the previous redstone power: - if (ShouldBeOpen) - { - a_Chunk.SetMeta(TopPosition, TopMeta | 0x2); - } - else - { - a_Chunk.SetMeta(TopPosition, TopMeta & ~0x2); - } + // Update the previous redstone power: + if (ShouldBeOpen) + { + a_Chunk.SetMeta(TopPosition, TopMeta | 0x2); + } + else + { + a_Chunk.SetMeta(TopPosition, TopMeta & ~0x2); + } - cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap()); - const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); + cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap()); + const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); - // Toggle the door, if it needs to be changed: - if (ShouldBeOpen != cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition)) - { - cBlockDoorHandler::SetOpen(ChunkInterface, AbsolutePosition, ShouldBeOpen); - a_Chunk.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, AbsolutePosition, 0); - } + // Toggle the door, if it needs to be changed: + if (ShouldBeOpen != cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition)) + { + cBlockDoorHandler::SetOpen(ChunkInterface, AbsolutePosition, ShouldBeOpen); + a_Chunk.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, AbsolutePosition, 0); } -}; +} +}; // namespace DoorHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h index 5f92c3868..ba2589fac 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h @@ -9,69 +9,95 @@ namespace DropSpenserHandler { - static bool IsActivated(NIBBLETYPE a_Meta) - { - return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0; - } +static bool IsActivated(NIBBLETYPE a_Meta) +{ + return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0; +} - static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn) +static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn) +{ + if (IsOn) { - if (IsOn) - { - return a_Meta | E_META_DROPSPENSER_ACTIVATED; // set the bit - } - else - { - return a_Meta & ~E_META_DROPSPENSER_ACTIVATED; // clear the bit - } + return a_Meta | E_META_DROPSPENSER_ACTIVATED; // set the bit } - - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) + else { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; + return a_Meta & ~E_META_DROPSPENSER_ACTIVATED; // clear the bit } +} + +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} + +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating spencer the dropspenser (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating spencer the dropspenser (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - const bool IsPoweredNow = (Power > 0); - const bool WasPoweredPreviously = IsActivated(a_Meta); + const bool IsPoweredNow = (Power > 0); + const bool WasPoweredPreviously = IsActivated(a_Meta); - if (IsPoweredNow && !WasPoweredPreviously) - { - a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity) + if (IsPoweredNow && !WasPoweredPreviously) + { + a_Chunk.DoWithBlockEntityAt( + a_Position, + [](cBlockEntity & a_BlockEntity) { - ASSERT((a_BlockEntity.GetBlockType() == E_BLOCK_DISPENSER) || (a_BlockEntity.GetBlockType() == E_BLOCK_DROPPER)); + ASSERT( + (a_BlockEntity.GetBlockType() == E_BLOCK_DISPENSER) || + (a_BlockEntity.GetBlockType() == E_BLOCK_DROPPER) + ); static_cast<cDropSpenserEntity &>(a_BlockEntity).Activate(); return false; - }); - } - - // Update the internal dropspenser state if necessary - if (IsPoweredNow != WasPoweredPreviously) - { - a_Chunk.SetMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow)); - } + } + ); } - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + // Update the internal dropspenser state if necessary + if (IsPoweredNow != WasPoweredPreviously) { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); + a_Chunk.SetMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow)); + } +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); - // Consider indirect power: - Callback.CheckIndirectPower(); + // Consider indirect power: + Callback.CheckIndirectPower(); - // Consider normal adjacents: - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); - } -}; + // Consider normal adjacents: + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} +}; // namespace DropSpenserHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp index 9c7560a6c..3b0df14e7 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp @@ -12,11 +12,12 @@ -ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE CurrentBlock) : - Power(0), - m_Chunk(Chunk), - m_Position(Position), - m_CurrentBlock(CurrentBlock) +ForEachSourceCallback::ForEachSourceCallback( + const cChunk & Chunk, + const Vector3i Position, + const BLOCKTYPE CurrentBlock +) : + Power(0), m_Chunk(Chunk), m_Position(Position), m_CurrentBlock(CurrentBlock) { } @@ -38,19 +39,27 @@ void ForEachSourceCallback::operator()(Vector3i Location) } const auto PotentialSourceBlock = NeighbourChunk->GetBlock(Location); - const auto NeighbourRelativeQueryPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position); + const auto NeighbourRelativeQueryPosition = + cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position); if (!cBlockInfo::IsTransparent(PotentialSourceBlock)) { - Power = std::max(Power, QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location)); + Power = std::max( + Power, + QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location) + ); } else { Power = std::max( Power, RedstoneHandler::GetPowerDeliveredToPosition( - *NeighbourChunk, Location, PotentialSourceBlock, - NeighbourRelativeQueryPosition, m_CurrentBlock, false + *NeighbourChunk, + Location, + PotentialSourceBlock, + NeighbourRelativeQueryPosition, + m_CurrentBlock, + false ) ); } @@ -88,7 +97,12 @@ void ForEachSourceCallback::CheckIndirectPower() -PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition) +PowerLevel ForEachSourceCallback::QueryLinkedPower( + const cChunk & Chunk, + const Vector3i QueryPosition, + const BLOCKTYPE QueryBlock, + const Vector3i SolidBlockPosition +) { PowerLevel Power = 0; @@ -108,14 +122,19 @@ PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const V } // Conduit block's position, relative to NeighbourChunk. - const auto NeighbourRelativeSolidBlockPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, SolidBlockPosition); + const auto NeighbourRelativeSolidBlockPosition = + cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, SolidBlockPosition); // Do a standard power query, but the requester's position is actually the solid block that will conduct power: Power = std::max( Power, RedstoneHandler::GetPowerDeliveredToPosition( - *NeighbourChunk, SourcePosition, NeighbourChunk->GetBlock(SourcePosition), - NeighbourRelativeSolidBlockPosition, QueryBlock, true + *NeighbourChunk, + SourcePosition, + NeighbourChunk->GetBlock(SourcePosition), + NeighbourRelativeSolidBlockPosition, + QueryBlock, + true ) ); } diff --git a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h index 16c10fd5e..9dcc982c8 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h +++ b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h @@ -9,8 +9,7 @@ class ForEachSourceCallback { -public: - + public: ForEachSourceCallback(const cChunk & Chunk, Vector3i Position, BLOCKTYPE CurrentBlock); /** Callback invoked for each potential source position of the redstone component. */ @@ -22,11 +21,15 @@ public: // The maximum power level of all source locations. PowerLevel Power; -private: - - /** 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); + private: + /** 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; diff --git a/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h b/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h index 95ef6ae62..006bda455 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h @@ -9,52 +9,75 @@ namespace HopperHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; - } +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - const bool ShouldBeLocked = Power != 0; - const bool PreviouslyLocked = (a_Meta & 0x8) == 0x8; + const bool ShouldBeLocked = Power != 0; + const bool PreviouslyLocked = (a_Meta & 0x8) == 0x8; - if (ShouldBeLocked == PreviouslyLocked) - { - return; - } + if (ShouldBeLocked == PreviouslyLocked) + { + return; + } - if (ShouldBeLocked) - { - a_Chunk.SetMeta(a_Position, a_Meta | 0x8); - } - else - { - a_Chunk.SetMeta(a_Position, a_Meta & ~0x8); - } + if (ShouldBeLocked) + { + a_Chunk.SetMeta(a_Position, a_Meta | 0x8); + } + else + { + a_Chunk.SetMeta(a_Position, a_Meta & ~0x8); + } - a_Chunk.DoWithBlockEntityAt(a_Position, [ShouldBeLocked](cBlockEntity & a_BlockEntity) + a_Chunk.DoWithBlockEntityAt( + a_Position, + [ShouldBeLocked](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_HOPPER); static_cast<cHopperEntity &>(a_BlockEntity).SetLocked(ShouldBeLocked); return false; - }); - } + } + ); +} - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); - } -}; +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} +}; // namespace HopperHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp index 8063e72a4..cf652b509 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp @@ -22,7 +22,7 @@ bool cIncrementalRedstoneSimulator::IsAlwaysTicked(BLOCKTYPE a_Block) case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return true; - default: return false; + default: return false; } } @@ -112,7 +112,12 @@ void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & Tic -void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) +void cIncrementalRedstoneSimulator::SimulateChunk( + std::chrono::milliseconds a_Dt, + int a_ChunkX, + int a_ChunkZ, + cChunk * a_Chunk +) { auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData()); for (auto & DelayInfo : ChunkData.m_MechanismDelays) @@ -194,7 +199,8 @@ void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position { // Having WakeUp called on us directly means someone called SetBlock (or WakeUp) // Since the simulator never does this, something external changed. Clear cached data: - static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData())->ErasePowerData(a_Position); + static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData()) + ->ErasePowerData(a_Position); // Queue the block, in case the set block was redstone: AddBlock(a_Chunk, a_Position, a_Block); diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h index 365f0176e..4f2028ff1 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h @@ -7,17 +7,14 @@ -class cIncrementalRedstoneSimulator final : - public cRedstoneSimulator +class cIncrementalRedstoneSimulator final : public cRedstoneSimulator { using Super = cRedstoneSimulator; -public: - + public: using Super::Super; -private: - + private: /** Returns if a redstone device is always ticked due to influence by its environment */ static bool IsAlwaysTicked(BLOCKTYPE a_Block); @@ -31,4 +28,4 @@ private: virtual cRedstoneSimulatorChunkData * CreateChunkData() override; virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block) override; -} ; +}; diff --git a/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h index fd96d8721..21008cd89 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h @@ -9,42 +9,65 @@ namespace NoteBlockHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; - } +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating sparky the magical note block (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, Power); +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating sparky the magical note block (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, Power); - const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); - if ((Previous != 0) || (Power == 0)) - { - // If we're already powered or received an update of no power, don't make a sound - return; - } + const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); + if ((Previous != 0) || (Power == 0)) + { + // If we're already powered or received an update of no power, don't make a sound + return; + } - a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity) + a_Chunk.DoWithBlockEntityAt( + a_Position, + [](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_NOTE_BLOCK); static_cast<cNoteEntity &>(a_BlockEntity).MakeSound(); return false; - }); - } + } + ); +} - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); - } -}; +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} +}; // namespace NoteBlockHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h b/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h index 802b9307c..4cac17b72 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h @@ -9,100 +9,130 @@ namespace ObserverHandler { - static bool IsOn(NIBBLETYPE a_Meta) +static bool IsOn(NIBBLETYPE a_Meta) +{ + return (a_Meta & 0x8) == 0x8; +} + +static bool ShouldPowerOn( + cChunk & Chunk, + const Vector3i a_Position, + NIBBLETYPE a_Meta, + cIncrementalRedstoneSimulatorChunkData & a_Data +) +{ + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + if (!Chunk.UnboundedRelGetBlock( + a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), + BlockType, + BlockMeta + )) { - return (a_Meta & 0x8) == 0x8; + return false; } - static bool ShouldPowerOn(cChunk & Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData & a_Data) - { - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if (!Chunk.UnboundedRelGetBlock(a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), BlockType, BlockMeta)) - { - return false; - } + auto & ObserverCache = a_Data.ObserverCache; + const auto FindResult = ObserverCache.find(a_Position); + const auto Observed = std::make_pair(BlockType, BlockMeta); - auto & ObserverCache = a_Data.ObserverCache; - const auto FindResult = ObserverCache.find(a_Position); - const auto Observed = std::make_pair(BlockType, BlockMeta); + if (FindResult == ObserverCache.end()) + { + // Cache the last seen block for this position: + ObserverCache.emplace(a_Position, Observed); - if (FindResult == ObserverCache.end()) - { - // Cache the last seen block for this position: - ObserverCache.emplace(a_Position, Observed); + // Definitely should signal update: + return true; + } - // Definitely should signal update: - return true; - } + // The block this observer previously saw. + const auto Previous = FindResult->second; - // The block this observer previously saw. - const auto Previous = FindResult->second; + // Update the last seen block: + FindResult->second = Observed; - // Update the last seen block: - FindResult->second = Observed; + // Determine if to signal an update based on the block previously observed changed + return Previous != Observed; +} - // Determine if to signal an update based on the block previously observed changed - return Previous != Observed; - } +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + const auto Meta = a_Chunk.GetMeta(a_Position); + return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 + : 0; +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating Lenny the observer (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - const auto Meta = a_Chunk.GetMeta(a_Position); - return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0; - } + auto & Data = DataForChunk(a_Chunk); + auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) + if (DelayInfo == nullptr) { - // LOGD("Evaluating Lenny the observer (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); - - auto & Data = DataForChunk(a_Chunk); - auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); - - if (DelayInfo == nullptr) + if (!ShouldPowerOn(a_Chunk, a_Position, a_Meta, Data)) { - if (!ShouldPowerOn(a_Chunk, a_Position, a_Meta, Data)) - { - return; - } - - // From rest, we've determined there was a block update - // Schedule power-on 1 tick in the future - Data.m_MechanismDelays[a_Position] = std::make_pair(1, true); - return; } - int DelayTicks; - bool ShouldPowerOn; - std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; + // From rest, we've determined there was a block update + // Schedule power-on 1 tick in the future + Data.m_MechanismDelays[a_Position] = std::make_pair(1, true); - if (DelayTicks != 0) - { - return; - } + return; + } - if (ShouldPowerOn) - { - // Remain on for 1 tick before resetting - *DelayInfo = std::make_pair(1, false); - a_Chunk.SetMeta(a_Position, a_Meta | 0x8); - } - else - { - // We've reset. Erase delay data in preparation for detecting further updates - Data.m_MechanismDelays.erase(a_Position); - a_Chunk.SetMeta(a_Position, a_Meta & ~0x8); - } + int DelayTicks; + bool ShouldPowerOn; + std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; - UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockObserverHandler::GetSignalOutputOffset(a_Meta)); + if (DelayTicks != 0) + { + return; } - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + if (ShouldPowerOn) + { + // Remain on for 1 tick before resetting + *DelayInfo = std::make_pair(1, false); + a_Chunk.SetMeta(a_Position, a_Meta | 0x8); + } + else { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_BlockType); + // We've reset. Erase delay data in preparation for detecting further updates + Data.m_MechanismDelays.erase(a_Position); + a_Chunk.SetMeta(a_Position, a_Meta & ~0x8); } -}; + + UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockObserverHandler::GetSignalOutputOffset(a_Meta)); +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_BlockType); +} +}; // namespace ObserverHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h index 9713bc0a6..16334808d 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h @@ -9,59 +9,80 @@ namespace PistonHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; - } +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} + +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating pisty the piston (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) + const bool ShouldBeExtended = Power != 0; + if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta)) { - // LOGD("Evaluating pisty the piston (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - const bool ShouldBeExtended = Power != 0; - if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta)) - { - return; - } + return; + } - a_Position = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); + a_Position = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); - if (ShouldBeExtended) - { - cBlockPistonHandler::ExtendPiston(a_Position, *a_Chunk.GetWorld()); - } - else - { - cBlockPistonHandler::RetractPiston(a_Position, *a_Chunk.GetWorld()); - } - - // It is necessary to delay after a signal to prevent an infinite loop (#3168) - // However, this delay is already present: as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp + if (ShouldBeExtended) + { + cBlockPistonHandler::ExtendPiston(a_Position, *a_Chunk.GetWorld()); } - - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + else { - UNUSED(a_Chunk); - UNUSED(a_BlockType); + cBlockPistonHandler::RetractPiston(a_Position, *a_Chunk.GetWorld()); + } - const auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); - const auto FrontOffset = AddFaceDirection(Vector3i(), Face); + // It is necessary to delay after a signal to prevent an infinite loop (#3168) + // However, this delay is already present: as a side effect of the implementation of piston animation in + // Blocks\BlockPiston.cpp +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + + const auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); + const auto FrontOffset = AddFaceDirection(Vector3i(), Face); - for (const auto & Offset : RelativeAdjacents) + for (const auto & Offset : RelativeAdjacents) + { + if (Offset != FrontOffset) { - if (Offset != FrontOffset) - { - Callback(a_Position + Offset); - } + Callback(a_Position + Offset); } - - // Consider indirect power: - Callback.CheckIndirectPower(); } -}; + + // Consider indirect power: + Callback.CheckIndirectPower(); +} +}; // namespace PistonHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h index 28eeb4b04..8220f14a7 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h @@ -7,85 +7,105 @@ namespace PoweredRailHandler { - /** Get the offset along which the rail faces. - Not in cBlockRailHandler since specific to powered rails. */ - static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) +/** Get the offset along which the rail faces. +Not in cBlockRailHandler since specific to powered rails. */ +static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) +{ + switch (a_Meta & 0x7) { - switch (a_Meta & 0x7) + case E_META_RAIL_ZM_ZP: return {0, 0, 1}; + case E_META_RAIL_XM_XP: return {1, 0, 0}; + case E_META_RAIL_ASCEND_XP: return {1, 1, 0}; + case E_META_RAIL_ASCEND_XM: return {1, 1, 0}; + case E_META_RAIL_ASCEND_ZM: return {0, 1, 1}; + case E_META_RAIL_ASCEND_ZP: return {0, 1, 1}; + default: { - case E_META_RAIL_ZM_ZP: return { 0, 0, 1 }; - case E_META_RAIL_XM_XP: return { 1, 0, 0 }; - case E_META_RAIL_ASCEND_XP: return { 1, 1, 0 }; - case E_META_RAIL_ASCEND_XM: return { 1, 1, 0 }; - case E_META_RAIL_ASCEND_ZM: return { 0, 1, 1 }; - case E_META_RAIL_ASCEND_ZP: return { 0, 1, 1 }; - default: - { - ASSERT(!"Impossible rail meta! wat wat wat"); - return { 0, 0, 0 }; - } + ASSERT(!"Impossible rail meta! wat wat wat"); + return {0, 0, 0}; } } +} - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_QueryBlockType); +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_QueryBlockType); - const auto Meta = a_Chunk.GetMeta(a_Position); - const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(Meta); - if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition)) - { - const auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position); - return (Power <= 7) ? 0 : (Power - 1); - } - return 0; + const auto Meta = a_Chunk.GetMeta(a_Position); + const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(Meta); + if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition)) + { + const auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position); + return (Power <= 7) ? 0 : (Power - 1); } + return 0; +} - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTickingChunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating tracky the rail (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTickingChunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating tracky the rail (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - switch (a_BlockType) + switch (a_BlockType) + { + case E_BLOCK_DETECTOR_RAIL: { - case E_BLOCK_DETECTOR_RAIL: + /* + if ((m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x08) == 0x08) { - /* - if ((m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x08) == 0x08) - { - SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType); - } - */ - return; + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType); } - case E_BLOCK_ACTIVATOR_RAIL: - case E_BLOCK_POWERED_RAIL: + */ + return; + } + case E_BLOCK_ACTIVATOR_RAIL: + case E_BLOCK_POWERED_RAIL: + { + const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta); + if (Power != DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power)) { - const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta); - if (Power != DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power)) - { - a_Chunk.SetMeta(a_Position, (Power == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08)); - - UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, Offset); - UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, -Offset); - } + a_Chunk.SetMeta(a_Position, (Power == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08)); - return; - } - default: - { - ASSERT(!"Unhandled type of rail in passed to rail handler!"); + UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, Offset); + UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, -Offset); } + + return; + } + default: + { + ASSERT(!"Unhandled type of rail in passed to rail handler!"); } } +} - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_Meta); +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Meta); - if ((a_BlockType == E_BLOCK_POWERED_RAIL) || (a_BlockType == E_BLOCK_ACTIVATOR_RAIL)) - { - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); - } + if ((a_BlockType == E_BLOCK_POWERED_RAIL) || (a_BlockType == E_BLOCK_ACTIVATOR_RAIL)) + { + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } -}; +} +}; // namespace PoweredRailHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h index 003b5b253..dda3e2d57 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h @@ -10,12 +10,14 @@ namespace PressurePlateHandler { - static unsigned char GetPowerLevel(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType) - { - size_t NumberOfEntities = 0; - bool FoundPlayer = false; +static unsigned char GetPowerLevel(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType) +{ + size_t NumberOfEntities = 0; + bool FoundPlayer = false; - Chunk.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [&](cEntity & Entity) + Chunk.ForEachEntityInBox( + cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), + [&](cEntity & Entity) { if (Entity.GetHealth() <= 0) { @@ -42,187 +44,210 @@ namespace PressurePlateHandler NumberOfEntities++; return false; - }); + } + ); - switch (BlockType) + switch (BlockType) + { + case E_BLOCK_STONE_PRESSURE_PLATE: { - case E_BLOCK_STONE_PRESSURE_PLATE: - { - return FoundPlayer ? 15 : 0; - } - case E_BLOCK_WOODEN_PRESSURE_PLATE: - { - return (NumberOfEntities != 0) ? 15 : 0; - } - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - { - return std::min(static_cast<unsigned char>(CeilC(NumberOfEntities / 10.f)), static_cast<unsigned char>(15)); - } - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: - { - return std::min(static_cast<unsigned char>(NumberOfEntities), static_cast<unsigned char>(15)); - } - default: - { - ASSERT(!"Unhandled/unimplemented block in pressure plate handler!"); - return 0; - } + return FoundPlayer ? 15 : 0; + } + case E_BLOCK_WOODEN_PRESSURE_PLATE: + { + return (NumberOfEntities != 0) ? 15 : 0; + } + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + { + return std::min(static_cast<unsigned char>(CeilC(NumberOfEntities / 10.f)), static_cast<unsigned char>(15)); + } + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: + { + return std::min(static_cast<unsigned char>(NumberOfEntities), static_cast<unsigned char>(15)); + } + default: + { + ASSERT(!"Unhandled/unimplemented block in pressure plate handler!"); + return 0; } } +} - static const char * GetClickOnSound(BLOCKTYPE a_BlockType) +static const char * GetClickOnSound(BLOCKTYPE a_BlockType) +{ + // manage on-sound + switch (a_BlockType) { - // manage on-sound - switch (a_BlockType) + case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_on"; + case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_on"; + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_on"; + default: { - case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_on"; - case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_on"; - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_on"; - default: - { - ASSERT(!"No on sound for this one!"); - return ""; - } + ASSERT(!"No on sound for this one!"); + return ""; } } +} - static const char * GetClickOffSound(BLOCKTYPE a_BlockType) +static const char * GetClickOffSound(BLOCKTYPE a_BlockType) +{ + // manage off-sound + switch (a_BlockType) { - // manage off-sound - switch (a_BlockType) + case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_off"; + case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_off"; + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_off"; + default: { - case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_off"; - case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_off"; - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_off"; - default: - { - ASSERT(!"No off sound for this one!"); - return ""; - } + ASSERT(!"No off sound for this one!"); + return ""; } } +} + +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + + // Plates only link power blocks below + // Retrieve and return the cached power calculated by Update for performance: + return (IsLinked && (a_QueryPosition != (a_Position + OffsetYM))) + ? 0 + : DataForChunk(a_Chunk).GetCachedPowerData(a_Position); +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); + auto & ChunkData = DataForChunk(a_Chunk); - // Plates only link power blocks below - // Retrieve and return the cached power calculated by Update for performance: - return (IsLinked && (a_QueryPosition != (a_Position + OffsetYM))) ? 0 : DataForChunk(a_Chunk).GetCachedPowerData(a_Position); - } + const auto PreviousPower = ChunkData.GetCachedPowerData(a_Position); + const auto Absolute = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); + const auto PowerLevel = GetPowerLevel(a_Chunk, Absolute, a_BlockType); // Get the current power of the platey + const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position); - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) + // Resting state? + if (DelayInfo == nullptr) { - // LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); + if (PowerLevel == 0) + { + // Nothing happened, back to rest + return; + } - auto & ChunkData = DataForChunk(a_Chunk); + // From rest, a player stepped on us + // Schedule a minimum 0.5 second delay before even thinking about releasing + ChunkData.m_MechanismDelays[a_Position] = std::make_pair(5, true); - const auto PreviousPower = ChunkData.GetCachedPowerData(a_Position); - const auto Absolute = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); - const auto PowerLevel = GetPowerLevel(a_Chunk, Absolute, a_BlockType); // Get the current power of the platey - const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position); + a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f); - // Resting state? - if (DelayInfo == nullptr) - { - if (PowerLevel == 0) - { - // Nothing happened, back to rest - return; - } + // Update power + ChunkData.SetCachedPowerData(a_Position, PowerLevel); - // From rest, a player stepped on us - // Schedule a minimum 0.5 second delay before even thinking about releasing - ChunkData.m_MechanismDelays[a_Position] = std::make_pair(5, true); + // Immediately depress plate + a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED); - a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); + return; + } - // Update power - ChunkData.SetCachedPowerData(a_Position, PowerLevel); + // Not a resting state - // Immediately depress plate - a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED); + int DelayTicks; + bool HasExitedMinimumOnDelayPhase; + std::tie(DelayTicks, HasExitedMinimumOnDelayPhase) = *DelayInfo; - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); + // Are we waiting for the initial delay or subsequent release delay? + if (DelayTicks > 0) + { + // Nothing changes, if there is nothing on it anymore, because the state is locked. + if (PowerLevel == 0) + { return; } - // Not a resting state - - int DelayTicks; - bool HasExitedMinimumOnDelayPhase; - std::tie(DelayTicks, HasExitedMinimumOnDelayPhase) = *DelayInfo; - - // Are we waiting for the initial delay or subsequent release delay? - if (DelayTicks > 0) + // Yes. Are we waiting to release, and found that the player stepped on it again? + if (!HasExitedMinimumOnDelayPhase) { - // Nothing changes, if there is nothing on it anymore, because the state is locked. - if (PowerLevel == 0) - { - return; - } + // Reset delay + *DelayInfo = std::make_pair(0, true); + } - // Yes. Are we waiting to release, and found that the player stepped on it again? - if (!HasExitedMinimumOnDelayPhase) - { - // Reset delay - *DelayInfo = std::make_pair(0, true); - } + // Did the power level change and is still above zero? + if (PowerLevel != PreviousPower) + { + // Yes. Update power + ChunkData.SetCachedPowerData(a_Position, PowerLevel); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); + } - // Did the power level change and is still above zero? - if (PowerLevel != PreviousPower) - { - // Yes. Update power - ChunkData.SetCachedPowerData(a_Position, PowerLevel); - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); - } + return; + } + // Not waiting for anything. Has the initial delay elapsed? + if (HasExitedMinimumOnDelayPhase) + { + // Yep, initial delay elapsed. Has the player gotten off? + if (PowerLevel == 0) + { + // Yes. Go into subsequent release delay, for a further 0.5 seconds + *DelayInfo = std::make_pair(5, false); return; } - // Not waiting for anything. Has the initial delay elapsed? - if (HasExitedMinimumOnDelayPhase) + // Did the power level change and is still above zero? + if (PowerLevel != PreviousPower) { - // Yep, initial delay elapsed. Has the player gotten off? - if (PowerLevel == 0) - { - // Yes. Go into subsequent release delay, for a further 0.5 seconds - *DelayInfo = std::make_pair(5, false); - return; - } - - // Did the power level change and is still above zero? - if (PowerLevel != PreviousPower) - { - // Yes. Update power - ChunkData.SetCachedPowerData(a_Position, PowerLevel); - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); - } - - // Yes, but player's still on the plate, do nothing - return; + // Yes. Update power + ChunkData.SetCachedPowerData(a_Position, PowerLevel); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } - // Just got out of the subsequent release phase, reset everything and raise the plate - ChunkData.m_MechanismDelays.erase(a_Position); + // Yes, but player's still on the plate, do nothing + return; + } - a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f); - ChunkData.SetCachedPowerData(a_Position, PowerLevel); + // Just got out of the subsequent release phase, reset everything and raise the plate + ChunkData.m_MechanismDelays.erase(a_Position); - a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED); - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); - } + a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f); + ChunkData.SetCachedPowerData(a_Position, PowerLevel); - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - UNUSED(Callback); - } -}; + a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_Meta); + UNUSED(Callback); +} +}; // namespace PressurePlateHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h index 25e44f3d7..d80c53303 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h @@ -7,27 +7,47 @@ namespace RedstoneBlockHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(IsLinked); - return IsLinked ? 0 : 15; - } - - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating crimson the redstone block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - } - - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - UNUSED(Callback); - } -}; +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(IsLinked); + return IsLinked ? 0 : 15; +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating crimson the redstone block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_Meta); + UNUSED(Callback); +} +}; // namespace RedstoneBlockHandler 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 diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h index 3942f803c..e10c6027f 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h @@ -7,7 +7,12 @@ inline auto & DataForChunk(const cChunk & a_Chunk) return *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData()); } -inline void UpdateAdjustedRelative(const cChunk & a_Chunk, const cChunk & a_TickingChunk, const Vector3i a_Position, const Vector3i a_Offset) +inline void UpdateAdjustedRelative( + const cChunk & a_Chunk, + const cChunk & a_TickingChunk, + const Vector3i a_Position, + const Vector3i a_Offset +) { const auto PositionToWake = a_Position + a_Offset; @@ -20,20 +25,31 @@ inline void UpdateAdjustedRelative(const cChunk & a_Chunk, const cChunk & a_Tick auto & ChunkData = DataForChunk(a_TickingChunk); // Schedule the block in the requested direction to update: - ChunkData.WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, a_TickingChunk, PositionToWake)); + ChunkData.WakeUp( + cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, a_TickingChunk, PositionToWake) + ); // To follow Vanilla behaviour, update all linked positions: for (const auto & LinkedOffset : cSimulator::GetLinkedOffsets(a_Offset)) { if (const auto LinkedPositionToWake = a_Position + LinkedOffset; cChunkDef::IsValidHeight(LinkedPositionToWake)) { - ChunkData.WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, a_TickingChunk, LinkedPositionToWake)); + ChunkData.WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition( + a_Chunk, + a_TickingChunk, + LinkedPositionToWake + )); } } } template <typename ArrayType> -inline void UpdateAdjustedRelatives(const cChunk & a_Chunk, const cChunk & a_TickingChunk, const Vector3i a_Position, const ArrayType & a_Relative) +inline void UpdateAdjustedRelatives( + const cChunk & a_Chunk, + const cChunk & a_TickingChunk, + const Vector3i a_Position, + const ArrayType & a_Relative +) { for (const auto & Offset : a_Relative) { @@ -42,7 +58,11 @@ inline void UpdateAdjustedRelatives(const cChunk & a_Chunk, const cChunk & a_Tic } template <typename ArrayType> -inline void InvokeForAdjustedRelatives(ForEachSourceCallback & Callback, const Vector3i Position, const ArrayType & Relative) +inline void InvokeForAdjustedRelatives( + ForEachSourceCallback & Callback, + const Vector3i Position, + const ArrayType & Relative +) { for (const auto & Offset : Relative) { @@ -50,28 +70,22 @@ inline void InvokeForAdjustedRelatives(ForEachSourceCallback & Callback, const V } } -inline constexpr Vector3i OffsetYP{ 0, 1, 0 }; +inline constexpr Vector3i OffsetYP {0, 1, 0}; -inline constexpr Vector3i OffsetYM{ 0, -1, 0 }; +inline constexpr Vector3i OffsetYM {0, -1, 0}; -inline constexpr std::array<Vector3i, 6> RelativeAdjacents -{ - { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 1, 0 }, - { 0, -1, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, - } -}; +inline constexpr std::array<Vector3i, 6> RelativeAdjacents {{ + {1, 0, 0}, + {-1, 0, 0}, + {0, 1, 0}, + {0, -1, 0}, + {0, 0, 1}, + {0, 0, -1}, +}}; -inline constexpr std::array<Vector3i, 4> RelativeLaterals -{ - { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, - } -}; +inline constexpr std::array<Vector3i, 4> RelativeLaterals {{ + {1, 0, 0}, + {-1, 0, 0}, + {0, 0, 1}, + {0, 0, -1}, +}}; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.cpp b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.cpp index ab6b35c0b..cfe9a03ea 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.cpp @@ -32,61 +32,62 @@ -#define INVOKE_FOR_HANDLERS(Callback) \ - do \ - { \ - switch (BlockType) \ - { \ - case E_BLOCK_ACTIVATOR_RAIL: \ - case E_BLOCK_DETECTOR_RAIL: \ - case E_BLOCK_POWERED_RAIL: return PoweredRailHandler::Callback; \ - case E_BLOCK_ACTIVE_COMPARATOR: \ - case E_BLOCK_INACTIVE_COMPARATOR: return RedstoneComparatorHandler::Callback; \ - case E_BLOCK_DISPENSER: \ - case E_BLOCK_DROPPER: return DropSpenserHandler::Callback; \ - case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: \ - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: \ - case E_BLOCK_STONE_PRESSURE_PLATE: \ - case E_BLOCK_WOODEN_PRESSURE_PLATE: return PressurePlateHandler::Callback; \ - case E_BLOCK_ACACIA_FENCE_GATE: \ - case E_BLOCK_BIRCH_FENCE_GATE: \ - case E_BLOCK_DARK_OAK_FENCE_GATE: \ - case E_BLOCK_FENCE_GATE: \ - case E_BLOCK_IRON_TRAPDOOR: \ - case E_BLOCK_JUNGLE_FENCE_GATE: \ - case E_BLOCK_SPRUCE_FENCE_GATE: \ - case E_BLOCK_TRAPDOOR: return SmallGateHandler::Callback; \ - case E_BLOCK_REDSTONE_LAMP_OFF: \ - case E_BLOCK_REDSTONE_LAMP_ON: return RedstoneLampHandler::Callback; \ - case E_BLOCK_REDSTONE_REPEATER_OFF: \ - case E_BLOCK_REDSTONE_REPEATER_ON: return RedstoneRepeaterHandler::Callback; \ - case E_BLOCK_REDSTONE_TORCH_OFF: \ - case E_BLOCK_REDSTONE_TORCH_ON: return RedstoneTorchHandler::Callback; \ - case E_BLOCK_OBSERVER: return ObserverHandler::Callback; \ - case E_BLOCK_PISTON: \ - case E_BLOCK_STICKY_PISTON: return PistonHandler::Callback; \ - case E_BLOCK_DAYLIGHT_SENSOR: \ - case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: return DaylightSensorHandler::Callback; \ - case E_BLOCK_LEVER: \ - case E_BLOCK_STONE_BUTTON: \ - case E_BLOCK_WOODEN_BUTTON: return RedstoneToggleHandler::Callback; \ - case E_BLOCK_BLOCK_OF_REDSTONE: return RedstoneBlockHandler::Callback; \ - case E_BLOCK_COMMAND_BLOCK: return CommandBlockHandler::Callback; \ - case E_BLOCK_HOPPER: return HopperHandler::Callback; \ - case E_BLOCK_NOTE_BLOCK: return NoteBlockHandler::Callback; \ - case E_BLOCK_REDSTONE_WIRE: return RedstoneWireHandler::Callback; \ - case E_BLOCK_TNT: return TNTHandler::Callback; \ - case E_BLOCK_TRAPPED_CHEST: return TrappedChestHandler::Callback; \ - case E_BLOCK_TRIPWIRE_HOOK: return TripwireHookHandler::Callback; \ - default: \ - { \ - if (cBlockDoorHandler::IsDoorBlockType(BlockType)) \ - { \ - return DoorHandler::Callback; \ - } \ - } \ - } \ - } while (false) +#define INVOKE_FOR_HANDLERS(Callback) \ + do \ + { \ + switch (BlockType) \ + { \ + case E_BLOCK_ACTIVATOR_RAIL: \ + case E_BLOCK_DETECTOR_RAIL: \ + case E_BLOCK_POWERED_RAIL: return PoweredRailHandler::Callback; \ + case E_BLOCK_ACTIVE_COMPARATOR: \ + case E_BLOCK_INACTIVE_COMPARATOR: return RedstoneComparatorHandler::Callback; \ + case E_BLOCK_DISPENSER: \ + case E_BLOCK_DROPPER: return DropSpenserHandler::Callback; \ + case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: \ + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: \ + case E_BLOCK_STONE_PRESSURE_PLATE: \ + case E_BLOCK_WOODEN_PRESSURE_PLATE: return PressurePlateHandler::Callback; \ + case E_BLOCK_ACACIA_FENCE_GATE: \ + case E_BLOCK_BIRCH_FENCE_GATE: \ + case E_BLOCK_DARK_OAK_FENCE_GATE: \ + case E_BLOCK_FENCE_GATE: \ + case E_BLOCK_IRON_TRAPDOOR: \ + case E_BLOCK_JUNGLE_FENCE_GATE: \ + case E_BLOCK_SPRUCE_FENCE_GATE: \ + case E_BLOCK_TRAPDOOR: return SmallGateHandler::Callback; \ + case E_BLOCK_REDSTONE_LAMP_OFF: \ + case E_BLOCK_REDSTONE_LAMP_ON: return RedstoneLampHandler::Callback; \ + case E_BLOCK_REDSTONE_REPEATER_OFF: \ + case E_BLOCK_REDSTONE_REPEATER_ON: return RedstoneRepeaterHandler::Callback; \ + case E_BLOCK_REDSTONE_TORCH_OFF: \ + case E_BLOCK_REDSTONE_TORCH_ON: return RedstoneTorchHandler::Callback; \ + case E_BLOCK_OBSERVER: return ObserverHandler::Callback; \ + case E_BLOCK_PISTON: \ + case E_BLOCK_STICKY_PISTON: return PistonHandler::Callback; \ + case E_BLOCK_DAYLIGHT_SENSOR: \ + case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: return DaylightSensorHandler::Callback; \ + case E_BLOCK_LEVER: \ + case E_BLOCK_STONE_BUTTON: \ + case E_BLOCK_WOODEN_BUTTON: return RedstoneToggleHandler::Callback; \ + case E_BLOCK_BLOCK_OF_REDSTONE: return RedstoneBlockHandler::Callback; \ + case E_BLOCK_COMMAND_BLOCK: return CommandBlockHandler::Callback; \ + case E_BLOCK_HOPPER: return HopperHandler::Callback; \ + case E_BLOCK_NOTE_BLOCK: return NoteBlockHandler::Callback; \ + case E_BLOCK_REDSTONE_WIRE: return RedstoneWireHandler::Callback; \ + case E_BLOCK_TNT: return TNTHandler::Callback; \ + case E_BLOCK_TRAPPED_CHEST: return TrappedChestHandler::Callback; \ + case E_BLOCK_TRIPWIRE_HOOK: return TripwireHookHandler::Callback; \ + default: \ + { \ + if (cBlockDoorHandler::IsDoorBlockType(BlockType)) \ + { \ + return DoorHandler::Callback; \ + } \ + } \ + } \ + } \ + while (false) @@ -94,30 +95,51 @@ namespace RedstoneHandler { - PowerLevel GetPowerDeliveredToPosition(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const Vector3i QueryPosition, const BLOCKTYPE QueryBlockType, const bool IsLinked) - { - INVOKE_FOR_HANDLERS(GetPowerDeliveredToPosition(Chunk, Position, BlockType, QueryPosition, QueryBlockType, IsLinked)); - - // Fell through the switch statement - // Block at Position doesn't have a corresponding redstone handler - // ErasePowerData will have been called in AddBlock - - // Default: - return 0; - } - - void Update(cChunk & Chunk, cChunk & CurrentlyTicking, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, const PowerLevel PowerLevel) - { - INVOKE_FOR_HANDLERS(Update(Chunk, CurrentlyTicking, Position, BlockType, Meta, PowerLevel)); - } - - void ForValidSourcePositions(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, ForEachSourceCallback & Callback) - { - INVOKE_FOR_HANDLERS(ForValidSourcePositions(Chunk, Position, BlockType, Meta, Callback)); - } - - void SetWireState(const cChunk & Chunk, const Vector3i Position) - { - RedstoneWireHandler::SetWireState(Chunk, Position); - } +PowerLevel GetPowerDeliveredToPosition( + const cChunk & Chunk, + const Vector3i Position, + const BLOCKTYPE BlockType, + const Vector3i QueryPosition, + const BLOCKTYPE QueryBlockType, + const bool IsLinked +) +{ + INVOKE_FOR_HANDLERS(GetPowerDeliveredToPosition(Chunk, Position, BlockType, QueryPosition, QueryBlockType, IsLinked) + ); + + // Fell through the switch statement + // Block at Position doesn't have a corresponding redstone handler + // ErasePowerData will have been called in AddBlock + + // Default: + return 0; +} + +void Update( + cChunk & Chunk, + cChunk & CurrentlyTicking, + const Vector3i Position, + const BLOCKTYPE BlockType, + const NIBBLETYPE Meta, + const PowerLevel PowerLevel +) +{ + INVOKE_FOR_HANDLERS(Update(Chunk, CurrentlyTicking, Position, BlockType, Meta, PowerLevel)); +} + +void ForValidSourcePositions( + const cChunk & Chunk, + const Vector3i Position, + const BLOCKTYPE BlockType, + const NIBBLETYPE Meta, + ForEachSourceCallback & Callback +) +{ + INVOKE_FOR_HANDLERS(ForValidSourcePositions(Chunk, Position, BlockType, Meta, Callback)); +} + +void SetWireState(const cChunk & Chunk, const Vector3i Position) +{ + RedstoneWireHandler::SetWireState(Chunk, Position); } +} // namespace RedstoneHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h index fdac7901f..42334e58b 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h @@ -16,19 +16,40 @@ class ForEachSourceCallback; namespace RedstoneHandler { - /** Asks a redstone component at the source position how much power it will deliver to the querying position. - If IsLinked is true, QueryPosition should point to the intermediate conduit block. - The Position and QueryPosition are both relative to Chunk. */ - PowerLevel GetPowerDeliveredToPosition(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, Vector3i QueryPosition, BLOCKTYPE QueryBlockType, bool IsLinked); - - /** Tells a redstone component at this position to update itself. - PowerLevel represents the maximum power level all of its source positions gave to it. - Position is relative to Chunk, but if the component needs to queue neighbour updates, they are queued to CurrentlyTicking. */ - void Update(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, PowerLevel PowerLevel); - - /** Invokes Callback for each position this component can accept power from. */ - void ForValidSourcePositions(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, ForEachSourceCallback & Callback); - - /** Temporary: compute and set the block state of a redstone wire. */ - void SetWireState(const cChunk & Chunk, Vector3i Position); -} +/** Asks a redstone component at the source position how much power it will deliver to the querying position. +If IsLinked is true, QueryPosition should point to the intermediate conduit block. +The Position and QueryPosition are both relative to Chunk. */ +PowerLevel GetPowerDeliveredToPosition( + const cChunk & Chunk, + Vector3i Position, + BLOCKTYPE BlockType, + Vector3i QueryPosition, + BLOCKTYPE QueryBlockType, + bool IsLinked +); + +/** Tells a redstone component at this position to update itself. +PowerLevel represents the maximum power level all of its source positions gave to it. +Position is relative to Chunk, but if the component needs to queue neighbour updates, they are queued to +CurrentlyTicking. */ +void Update( + cChunk & Chunk, + cChunk & CurrentlyTicking, + Vector3i Position, + BLOCKTYPE BlockType, + NIBBLETYPE Meta, + PowerLevel PowerLevel +); + +/** Invokes Callback for each position this component can accept power from. */ +void ForValidSourcePositions( + const cChunk & Chunk, + Vector3i Position, + BLOCKTYPE BlockType, + NIBBLETYPE Meta, + ForEachSourceCallback & Callback +); + +/** Temporary: compute and set the block state of a redstone wire. */ +void SetWireState(const cChunk & Chunk, Vector3i Position); +} // namespace RedstoneHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h index 3b37783f6..e65e10fb7 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h @@ -7,41 +7,61 @@ namespace RedstoneLampHandler { - static bool IsOn(BLOCKTYPE a_BlockType) - { - return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON); - } +static bool IsOn(BLOCKTYPE a_BlockType) +{ + return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON); +} - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - return 0; - } +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + return 0; +} - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating lamp (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating lamp (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); - if (Power > 0) + if (Power > 0) + { + if (!IsOn(a_BlockType)) { - if (!IsOn(a_BlockType)) - { - a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_ON, 0); - } + a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_ON, 0); } - else + } + else + { + if (IsOn(a_BlockType)) { - if (IsOn(a_BlockType)) - { - a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_OFF, 0); - } + a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_OFF, 0); } } +} - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_Chunk); - UNUSED(a_Meta); - UNUSED(a_BlockType); - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); - } -}; +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Meta); + UNUSED(a_BlockType); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} +}; // namespace RedstoneLampHandler 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 diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h index f9545d997..9a31d1872 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h @@ -19,17 +19,10 @@ using PowerLevel = unsigned char; class cIncrementalRedstoneSimulatorChunkData final : public cRedstoneSimulatorChunkData { -public: + public: + void WakeUp(const Vector3i & a_Position) { m_ActiveBlocks.push(a_Position); } - void WakeUp(const Vector3i & a_Position) - { - m_ActiveBlocks.push(a_Position); - } - - auto & GetActiveBlocks() - { - return m_ActiveBlocks; - } + auto & GetActiveBlocks() { return m_ActiveBlocks; } PowerLevel GetCachedPowerData(const Vector3i Position) const { @@ -74,8 +67,7 @@ public: /** Adjust From-relative coordinates into To-relative coordinates. */ inline static Vector3i RebaseRelativePosition(const cChunk & From, const cChunk & To, const Vector3i Position) { - return - { + return { Position.x + (From.GetPosX() - To.GetPosX()) * cChunkDef::Width, Position.y, Position.z + (From.GetPosZ() - To.GetPosZ()) * cChunkDef::Width @@ -93,8 +85,7 @@ public: /** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on. */ std::unordered_map<Vector3i, std::pair<int, bool>, VectorHasher<int>> m_MechanismDelays; -private: - + private: std::stack<Vector3i, std::vector<Vector3i>> m_ActiveBlocks; // TODO: map<Vector3i, int> -> Position of torch + it's heat level diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h index 45682406d..cd8a4d45c 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h @@ -10,96 +10,116 @@ namespace RedstoneToggleHandler { - static Vector3i GetOffsetAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +static Vector3i GetOffsetAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +{ + switch (a_BlockType) { - switch (a_BlockType) + case E_BLOCK_LEVER: { - case E_BLOCK_LEVER: + switch (a_Meta & 0x7) { - switch (a_Meta & 0x7) + case 0x0: + case 0x7: return {0, 1, 0}; + case 0x1: return {-1, 0, 0}; + case 0x2: return {1, 0, 0}; + case 0x3: return {0, 0, -1}; + case 0x4: return {0, 0, 1}; + case 0x5: + case 0x6: return {0, -1, 0}; + default: { - case 0x0: - case 0x7: return { 0, 1, 0 }; - case 0x1: return { -1, 0, 0 }; - case 0x2: return { 1, 0, 0 }; - case 0x3: return { 0, 0, -1 }; - case 0x4: return { 0, 0, 1 }; - case 0x5: - case 0x6: return { 0, -1, 0 }; - default: - { - ASSERT(!"Unhandled lever metadata!"); - return { 0, 0, 0 }; - } + ASSERT(!"Unhandled lever metadata!"); + return {0, 0, 0}; } } - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_WOODEN_BUTTON: + } + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_WOODEN_BUTTON: + { + switch (a_Meta & 0x7) { - switch (a_Meta & 0x7) + case 0x0: return {0, 1, 0}; + case 0x1: return {-1, 0, 0}; + case 0x2: return {1, 0, 0}; + case 0x3: return {0, 0, -1}; + case 0x4: return {0, 0, 1}; + case 0x5: return {0, -1, 0}; + default: { - case 0x0: return { 0, 1, 0 }; - case 0x1: return { -1, 0, 0 }; - case 0x2: return { 1, 0, 0 }; - case 0x3: return { 0, 0, -1 }; - case 0x4: return { 0, 0, 1 }; - case 0x5: return { 0, -1, 0 }; - default: - { - ASSERT(!"Unhandled button metadata!"); - return { 0, 0, 0 }; - } + ASSERT(!"Unhandled button metadata!"); + return {0, 0, 0}; } } - default: - { - ASSERT(!"Unexpected block passed to button/lever handler"); - return { 0, 0, 0 }; - } } - } - - static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) - { - switch (a_BlockType) + default: { - case E_BLOCK_LEVER: return cBlockLeverHandler::IsLeverOn(a_Meta) ? 15 : 0; - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_WOODEN_BUTTON: return cBlockButtonHandler::IsButtonOn(a_Meta) ? 15 : 0; - default: - { - ASSERT(!"Unexpected block passed to button/lever handler"); - return 0; - } + ASSERT(!"Unexpected block passed to button/lever handler"); + return {0, 0, 0}; } } +} - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) +static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) +{ + switch (a_BlockType) { - UNUSED(a_QueryBlockType); - - const auto Meta = a_Chunk.GetMeta(a_Position); - const auto QueryOffset = a_QueryPosition - a_Position; - - if (IsLinked && (QueryOffset != GetOffsetAttachedTo(a_Position, a_BlockType, Meta))) + case E_BLOCK_LEVER: return cBlockLeverHandler::IsLeverOn(a_Meta) ? 15 : 0; + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_WOODEN_BUTTON: return cBlockButtonHandler::IsButtonOn(a_Meta) ? 15 : 0; + default: { + ASSERT(!"Unexpected block passed to button/lever handler"); return 0; } - - return GetPowerLevel(a_BlockType, Meta); } +} - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - } +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_QueryBlockType); + + const auto Meta = a_Chunk.GetMeta(a_Position); + const auto QueryOffset = a_QueryPosition - a_Position; - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + if (IsLinked && (QueryOffset != GetOffsetAttachedTo(a_Position, a_BlockType, Meta))) { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - UNUSED(Callback); + return 0; } -}; + + return GetPowerLevel(a_BlockType, Meta); +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_Meta); + UNUSED(Callback); +} +}; // namespace RedstoneToggleHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h index 8acaecc8d..ef9279602 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h @@ -7,89 +7,106 @@ namespace RedstoneTorchHandler { - static bool IsOn(BLOCKTYPE a_Block) - { - return (a_Block == E_BLOCK_REDSTONE_TORCH_ON); - } +static bool IsOn(BLOCKTYPE a_Block) +{ + return (a_Block == E_BLOCK_REDSTONE_TORCH_ON); +} - static Vector3i GetOffsetAttachedTo(const NIBBLETYPE a_Meta) +static Vector3i GetOffsetAttachedTo(const NIBBLETYPE a_Meta) +{ + switch (a_Meta) { - switch (a_Meta) + case E_META_TORCH_FLOOR: return {0, -1, 0}; + case E_META_TORCH_EAST: return {-1, 0, 0}; + case E_META_TORCH_WEST: return {1, 0, 0}; + case E_META_TORCH_NORTH: return {0, 0, 1}; + case E_META_TORCH_SOUTH: return {0, 0, -1}; + default: { - case E_META_TORCH_FLOOR: return { 0, -1, 0 }; - case E_META_TORCH_EAST: return { -1, 0, 0 }; - case E_META_TORCH_WEST: return { 1, 0, 0 }; - case E_META_TORCH_NORTH: return { 0, 0, 1 }; - case E_META_TORCH_SOUTH: return { 0, 0, -1 }; - default: - { - ASSERT(!"Unhandled torch metadata"); - return { 0, 0, 0 }; - } + ASSERT(!"Unhandled torch metadata"); + return {0, 0, 0}; } } +} + +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + const auto QueryOffset = a_QueryPosition - a_Position; - 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) || (QueryOffset == GetOffsetAttachedTo(a_Chunk.GetMeta(a_Position))) || + (IsLinked && (QueryOffset != OffsetYP))) { - const auto QueryOffset = a_QueryPosition - a_Position; - - if ( - !IsOn(a_BlockType) || - (QueryOffset == GetOffsetAttachedTo(a_Chunk.GetMeta(a_Position))) || - (IsLinked && (QueryOffset != OffsetYP)) - ) - { - return 0; - } - - return 15; + return 0; } - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); + return 15; +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); - auto & Data = DataForChunk(a_Chunk); - auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); + auto & Data = DataForChunk(a_Chunk); + auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); - if (DelayInfo == nullptr) + if (DelayInfo == nullptr) + { + const bool ShouldBeOn = (Power == 0); + if (ShouldBeOn != IsOn(a_BlockType)) { - const bool ShouldBeOn = (Power == 0); - if (ShouldBeOn != IsOn(a_BlockType)) - { - Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn); - } - - return; + Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn); } - int DelayTicks; - bool ShouldPowerOn; - std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; - - if (DelayTicks != 0) - { - return; - } + return; + } - a_Chunk.FastSetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta); - Data.m_MechanismDelays.erase(a_Position); + int DelayTicks; + bool ShouldPowerOn; + std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; - for (const auto & Adjacent : RelativeAdjacents) - { - // Update all adjacents (including linked power positions) - // apart from our attachment, which can't possibly need an update: - if (Adjacent != GetOffsetAttachedTo(a_Meta)) - { - UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Adjacent); - } - } + if (DelayTicks != 0) + { + return; } - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + a_Chunk.FastSetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta); + Data.m_MechanismDelays.erase(a_Position); + + for (const auto & Adjacent : RelativeAdjacents) { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - Callback(a_Position + GetOffsetAttachedTo(a_Meta)); + // Update all adjacents (including linked power positions) + // apart from our attachment, which can't possibly need an update: + if (Adjacent != GetOffsetAttachedTo(a_Meta)) + { + UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Adjacent); + } } -}; +} + +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(a_Position + GetOffsetAttachedTo(a_Meta)); +} +}; // namespace RedstoneTorchHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h index b40491820..6706e4078 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h @@ -10,48 +10,51 @@ namespace RedstoneWireHandler { - /** A unified representation of wire direction. */ - enum class TemporaryDirection - { - Up, - Side - }; - - /** Invokes Callback with the wire's left, front, and right direction state corresponding to Offset. - Returns a new block constructed from the directions that the callback may have modified. */ - template <class OffsetCallback> - static BlockState DoWithDirectionState(const Vector3i Offset, BlockState Block, OffsetCallback Callback) - { - auto North = Block::RedstoneWire::North(Block); - auto South = Block::RedstoneWire::South(Block); - auto West = Block::RedstoneWire::West(Block); - auto East = Block::RedstoneWire::East(Block); - - if (Offset.x == -1) - { - Callback(South, West, North); - } - else if (Offset.x == 1) - { - Callback(North, East, South); - } +/** A unified representation of wire direction. */ +enum class TemporaryDirection +{ + Up, + Side +}; - if (Offset.z == -1) - { - Callback(West, North, East); - } - else if (Offset.z == 1) - { - Callback(East, South, West); - } +/** Invokes Callback with the wire's left, front, and right direction state corresponding to Offset. +Returns a new block constructed from the directions that the callback may have modified. */ +template <class OffsetCallback> +static BlockState DoWithDirectionState(const Vector3i Offset, BlockState Block, OffsetCallback Callback) +{ + auto North = Block::RedstoneWire::North(Block); + auto South = Block::RedstoneWire::South(Block); + auto West = Block::RedstoneWire::West(Block); + auto East = Block::RedstoneWire::East(Block); - return Block::RedstoneWire::RedstoneWire(East, North, 0, South, West); + if (Offset.x == -1) + { + Callback(South, West, North); + } + else if (Offset.x == 1) + { + Callback(North, East, South); } - /** Adjusts a given wire block so that the direction represented by Offset has state Direction. */ - static void SetDirectionState(const Vector3i Offset, BlockState & Block, TemporaryDirection Direction) + if (Offset.z == -1) + { + Callback(West, North, East); + } + else if (Offset.z == 1) { - Block = DoWithDirectionState(Offset, Block, [Direction](auto, auto & Front, auto) + Callback(East, South, West); + } + + return Block::RedstoneWire::RedstoneWire(East, North, 0, South, West); +} + +/** Adjusts a given wire block so that the direction represented by Offset has state Direction. */ +static void SetDirectionState(const Vector3i Offset, BlockState & Block, TemporaryDirection Direction) +{ + Block = DoWithDirectionState( + Offset, + Block, + [Direction](auto, auto & Front, auto) { using FrontState = std::remove_reference_t<decltype(Front)>; switch (Direction) @@ -67,169 +70,184 @@ namespace RedstoneWireHandler return; } } - }); - } + } + ); +} - static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset) +static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset) +{ + switch (a_Block) { - switch (a_Block) + case E_BLOCK_REDSTONE_REPEATER_ON: + case E_BLOCK_REDSTONE_REPEATER_OFF: { - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: + a_BlockMeta &= E_META_REDSTONE_REPEATER_FACING_MASK; + if ((a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XP) || + (a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XM)) { - a_BlockMeta &= E_META_REDSTONE_REPEATER_FACING_MASK; - if ((a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XP) || (a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XM)) - { - // Wire connects to repeater if repeater is aligned along X - // and wire is in front or behind it (#4639) - return a_Offset.x != 0; - } - - return a_Offset.z != 0; + // Wire connects to repeater if repeater is aligned along X + // and wire is in front or behind it (#4639) + return a_Offset.x != 0; } - case E_BLOCK_ACTIVE_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: - case E_BLOCK_STONE_BUTTON: - case E_BLOCK_WOODEN_BUTTON: return true; - default: return false; + + return a_Offset.z != 0; } + case E_BLOCK_ACTIVE_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: + case E_BLOCK_STONE_BUTTON: + case E_BLOCK_WOODEN_BUTTON: return true; + default: return false; } +} - static bool IsYPTerracingBlocked(const cChunk & a_Chunk, const Vector3i a_Position) +static bool IsYPTerracingBlocked(const cChunk & a_Chunk, const Vector3i a_Position) +{ + const auto Position = a_Position + OffsetYP; + + if (!cChunkDef::IsValidHeight(Position)) { - const auto Position = a_Position + OffsetYP; + // Certainly cannot terrace at the top of the world: + return true; + } - if (!cChunkDef::IsValidHeight(Position)) - { - // Certainly cannot terrace at the top of the world: - return true; - } + const auto YPTerraceBlock = a_Chunk.GetBlock(Position); + return cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock); +} - const auto YPTerraceBlock = a_Chunk.GetBlock(Position); - return cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock); - } +/** Temporary. Discovers a wire's connection state, including terracing, storing the block inside redstone chunk data. +TODO: once the server supports block states this should go in the block handler, with data saved in the world. */ +static void SetWireState(const cChunk & a_Chunk, const Vector3i a_Position) +{ + auto Block = Block::RedstoneWire::RedstoneWire(); + const bool IsYPTerracingBlocked = RedstoneWireHandler::IsYPTerracingBlocked(a_Chunk, a_Position); - /** Temporary. Discovers a wire's connection state, including terracing, storing the block inside redstone chunk data. - TODO: once the server supports block states this should go in the block handler, with data saved in the world. */ - static void SetWireState(const cChunk & a_Chunk, const Vector3i a_Position) + // Loop through laterals, discovering terracing connections: + for (const auto & Offset : RelativeLaterals) { - auto Block = Block::RedstoneWire::RedstoneWire(); - const bool IsYPTerracingBlocked = RedstoneWireHandler::IsYPTerracingBlocked(a_Chunk, a_Position); + auto Adjacent = a_Position + Offset; + auto NeighbourChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Adjacent); - // Loop through laterals, discovering terracing connections: - for (const auto & Offset : RelativeLaterals) + if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid()) { - auto Adjacent = a_Position + Offset; - auto NeighbourChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Adjacent); + continue; + } - if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid()) - { - continue; - } + BLOCKTYPE LateralBlock; + NIBBLETYPE LateralMeta; + NeighbourChunk->GetBlockTypeMeta(Adjacent, LateralBlock, LateralMeta); - BLOCKTYPE LateralBlock; - NIBBLETYPE LateralMeta; - NeighbourChunk->GetBlockTypeMeta(Adjacent, LateralBlock, LateralMeta); + if (IsDirectlyConnectingMechanism(LateralBlock, LateralMeta, Offset)) + { + // Any direct connections on a lateral means the wire has side connection in that direction: + SetDirectionState(Offset, Block, TemporaryDirection::Side); - if (IsDirectlyConnectingMechanism(LateralBlock, LateralMeta, Offset)) + // Temporary: this case will eventually be handled when wires are placed, with the state saved as blocks + // When a neighbour wire was loaded into its chunk, its neighbour chunks may not have loaded yet + // This function is called during chunk load (through AddBlock). Attempt to tell it its new state: + if ((NeighbourChunk != &a_Chunk) && (LateralBlock == E_BLOCK_REDSTONE_WIRE)) { - // Any direct connections on a lateral means the wire has side connection in that direction: - SetDirectionState(Offset, Block, TemporaryDirection::Side); + auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent)->second; + SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); + } - // Temporary: this case will eventually be handled when wires are placed, with the state saved as blocks - // When a neighbour wire was loaded into its chunk, its neighbour chunks may not have loaded yet - // This function is called during chunk load (through AddBlock). Attempt to tell it its new state: - if ((NeighbourChunk != &a_Chunk) && (LateralBlock == E_BLOCK_REDSTONE_WIRE)) - { - auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent)->second; - SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); - } + continue; + } - continue; - } + if (!IsYPTerracingBlocked && // A block above us blocks all YP terracing, so the check is static in the loop + (Adjacent.y < (cChunkDef::Height - 1)) && + (NeighbourChunk->GetBlock(Adjacent + OffsetYP) == E_BLOCK_REDSTONE_WIRE + ) // Only terrace YP with another wire + ) + { + SetDirectionState( + Offset, + Block, + cBlockInfo::IsTransparent(LateralBlock) ? TemporaryDirection::Side : TemporaryDirection::Up + ); - if ( - !IsYPTerracingBlocked && // A block above us blocks all YP terracing, so the check is static in the loop - (Adjacent.y < (cChunkDef::Height - 1)) && - (NeighbourChunk->GetBlock(Adjacent + OffsetYP) == E_BLOCK_REDSTONE_WIRE) // Only terrace YP with another wire - ) + if (NeighbourChunk != &a_Chunk) { - SetDirectionState(Offset, Block, cBlockInfo::IsTransparent(LateralBlock) ? TemporaryDirection::Side : TemporaryDirection::Up); + auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYP)->second; + SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); + } - if (NeighbourChunk != &a_Chunk) - { - auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYP)->second; - SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); - } + continue; + } - continue; - } + if ( + // IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent) + (!cBlockInfo::IsSolid(LateralBlock) || cBlockInfo::IsTransparent(LateralBlock)) && (Adjacent.y > 0) && + (NeighbourChunk->GetBlock(Adjacent + OffsetYM) == E_BLOCK_REDSTONE_WIRE + ) // Only terrace YM with another wire + ) + { + SetDirectionState(Offset, Block, TemporaryDirection::Side); - if ( - // IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent) - (!cBlockInfo::IsSolid(LateralBlock) || cBlockInfo::IsTransparent(LateralBlock)) && - (Adjacent.y > 0) && - (NeighbourChunk->GetBlock(Adjacent + OffsetYM) == E_BLOCK_REDSTONE_WIRE) // Only terrace YM with another wire - ) + if (NeighbourChunk != &a_Chunk) { - SetDirectionState(Offset, Block, TemporaryDirection::Side); - - if (NeighbourChunk != &a_Chunk) - { - auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYM)->second; - SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Up); - } + auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYM)->second; + SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Up); } } + } - auto & States = DataForChunk(a_Chunk).WireStates; - const auto FindResult = States.find(a_Position); - if (FindResult != States.end()) + auto & States = DataForChunk(a_Chunk).WireStates; + const auto FindResult = States.find(a_Position); + if (FindResult != States.end()) + { + if (Block != FindResult->second) { - if (Block != FindResult->second) - { - FindResult->second = Block; + FindResult->second = Block; - // TODO: when state is stored as the block, the block handler updating via SetBlock will do this automatically - // When a wire changes connection state, it needs to update its neighbours: - a_Chunk.GetWorld()->WakeUpSimulators(cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); - } - - return; + // TODO: when state is stored as the block, the block handler updating via SetBlock will do this + // automatically When a wire changes connection state, it needs to update its neighbours: + a_Chunk.GetWorld()->WakeUpSimulators(cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); } - DataForChunk(a_Chunk).WireStates.emplace(a_Position, Block); + return; } - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - // Starts off as the wire's meta value, modified appropriately and returned - auto Power = a_Chunk.GetMeta(a_Position); - const auto QueryOffset = a_QueryPosition - a_Position; + DataForChunk(a_Chunk).WireStates.emplace(a_Position, Block); +} + +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + // Starts off as the wire's meta value, modified appropriately and returned + auto Power = a_Chunk.GetMeta(a_Position); + const auto QueryOffset = a_QueryPosition - a_Position; - if ( - (QueryOffset == OffsetYP) || // Wires do not power things above them - (IsLinked && (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)) // Nor do they link power other wires - ) - { - return 0; - } + if ((QueryOffset == OffsetYP) || // Wires do not power things above them + (IsLinked && (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)) // Nor do they link power other wires + ) + { + return 0; + } - if (QueryOffset == OffsetYM) - { - // Wires always deliver power to the block underneath - return Power; - } + if (QueryOffset == OffsetYM) + { + // Wires always deliver power to the block underneath + return Power; + } - const auto & Data = DataForChunk(a_Chunk); - const auto Block = Data.WireStates.find(a_Position)->second; + const auto & Data = DataForChunk(a_Chunk); + const auto Block = Data.WireStates.find(a_Position)->second; - DoWithDirectionState(QueryOffset, Block, [a_QueryBlockType, &Power](const auto Left, const auto Front, const auto Right) + DoWithDirectionState( + QueryOffset, + Block, + [a_QueryBlockType, &Power](const auto Left, const auto Front, const auto Right) { using LeftState = std::remove_reference_t<decltype(Left)>; using FrontState = std::remove_reference_t<decltype(Front)>; @@ -252,8 +270,8 @@ namespace RedstoneWireHandler Okay, we do not directly connect to the wire. 1. If there are no DC mechanisms at all, the wire powers all laterals. Great, left and right are both None. 2. If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism. - The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing towards us. - Check that left and right are both None. + The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing + towards us. Check that left and right are both None. 3. If there is more than one DC, no non-DCs are powered. Left, right, cannot both be None. */ if ((Left == LeftState::None) && (Right == RightState::None)) @@ -265,45 +283,62 @@ namespace RedstoneWireHandler // Case 3 Power = 0; - }); - - return Power; - } + } + ); + + return Power; +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating dusty the wire (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, Power); - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) + if (a_Meta == Power) { - // LOGD("Evaluating dusty the wire (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, Power); - - if (a_Meta == Power) - { - return; - } + return; + } - a_Chunk.SetMeta(a_Position, Power); + a_Chunk.SetMeta(a_Position, Power); - // Notify all positions, sans YP, to update: - UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, OffsetYM); - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals); - } + // Notify all positions, sans YP, to update: + UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, OffsetYM); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals); +} - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) - { - UNUSED(a_BlockType); - UNUSED(a_Meta); +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_BlockType); + UNUSED(a_Meta); - Callback(a_Position + OffsetYP); - Callback(a_Position + OffsetYM); + Callback(a_Position + OffsetYP); + Callback(a_Position + OffsetYM); - const auto & Data = DataForChunk(a_Chunk); - const auto Block = Data.WireStates.find(a_Position)->second; + const auto & Data = DataForChunk(a_Chunk); + const auto Block = Data.WireStates.find(a_Position)->second; - // Figure out, based on our pre-computed block, where we connect to: - for (const auto & Offset : RelativeLaterals) - { - const auto Relative = a_Position + Offset; - Callback(Relative); + // Figure out, based on our pre-computed block, where we connect to: + for (const auto & Offset : RelativeLaterals) + { + const auto Relative = a_Position + Offset; + Callback(Relative); - DoWithDirectionState(Offset, Block, [&a_Chunk, &Callback, Relative](auto, const auto Front, auto) + DoWithDirectionState( + Offset, + Block, + [&a_Chunk, &Callback, Relative](auto, const auto Front, auto) { using FrontState = std::remove_reference_t<decltype(Front)>; @@ -317,17 +352,15 @@ namespace RedstoneWireHandler // Have to do a manual check to only accept power from YM diagonal if there's a wire there const auto YMDiagonalPosition = Relative + OffsetYM; - if ( - BLOCKTYPE QueryBlock; - cChunkDef::IsValidHeight(YMDiagonalPosition) && + if (BLOCKTYPE QueryBlock; cChunkDef::IsValidHeight(YMDiagonalPosition) && a_Chunk.UnboundedRelGetBlockType(YMDiagonalPosition, QueryBlock) && - (QueryBlock == E_BLOCK_REDSTONE_WIRE) - ) + (QueryBlock == E_BLOCK_REDSTONE_WIRE)) { Callback(YMDiagonalPosition); } } - }); - } + } + ); } -}; +} +}; // namespace RedstoneWireHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h b/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h index aed9d98ee..55eb7917c 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h @@ -7,37 +7,57 @@ namespace SmallGateHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; - } - - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating gateydory the fence gate/trapdoor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - // Use redstone data rather than block state so players can override redstone control - const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); - const bool IsOpen = (Previous != 0); - const bool ShouldBeOpen = Power != 0; +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} + +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating gateydory the fence gate/trapdoor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - if (ShouldBeOpen != IsOpen) - { - a_Chunk.SetMeta(a_Position, ShouldBeOpen ? (a_Meta | 0x4) : (a_Meta & ~0x04)); - } - } + // Use redstone data rather than block state so players can override redstone control + const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); + const bool IsOpen = (Previous != 0); + const bool ShouldBeOpen = Power != 0; - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + if (ShouldBeOpen != IsOpen) { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); + a_Chunk.SetMeta(a_Position, ShouldBeOpen ? (a_Meta | 0x4) : (a_Meta & ~0x04)); } -}; +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} +}; // namespace SmallGateHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h index cae538418..7b9a32972 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h @@ -7,32 +7,54 @@ namespace TNTHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); - return 0; - } - - static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating explodinator the trinitrotoluene (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - if (Power != 0) - { - a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0); - a_Chunk.GetWorld()->SpawnPrimedTNT(Vector3d(0.5, 0.5, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); // 80 ticks to boom - } - } - - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); + return 0; +} + +static void Update( + cChunk & a_Chunk, + cChunk &, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating explodinator the trinitrotoluene (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); + if (Power != 0) { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); - InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); + a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0); + a_Chunk.GetWorld()->SpawnPrimedTNT( + Vector3d(0.5, 0.5, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()) + ); // 80 ticks to boom } -}; +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); +} +}; // namespace TNTHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h index d68e48997..9b604f8ef 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h @@ -9,49 +9,72 @@ namespace TrappedChestHandler { - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_BlockType); - UNUSED(a_QueryPosition); - UNUSED(a_QueryBlockType); - UNUSED(IsLinked); +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_BlockType); + UNUSED(a_QueryPosition); + UNUSED(a_QueryBlockType); + UNUSED(IsLinked); - return DataForChunk(a_Chunk).GetCachedPowerData(a_Position); - } + return DataForChunk(a_Chunk).GetCachedPowerData(a_Position); +} - static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position) - { - int NumberOfPlayers = 0; - a_Chunk.DoWithBlockEntityAt(a_Position, [&NumberOfPlayers](cBlockEntity & a_BlockEntity) +static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position) +{ + int NumberOfPlayers = 0; + a_Chunk.DoWithBlockEntityAt( + a_Position, + [&NumberOfPlayers](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_TRAPPED_CHEST); NumberOfPlayers = static_cast<cChestEntity &>(a_BlockEntity).GetNumberOfPlayers(); return false; - }); + } + ); - return static_cast<unsigned char>(std::min(NumberOfPlayers, 15)); - } + return static_cast<unsigned char>(std::min(NumberOfPlayers, 15)); +} - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) - { - // LOGD("Evaluating tricky the trapped chest (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating tricky the trapped chest (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position); - const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PowerLevel); + const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position); + const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PowerLevel); - if (PowerLevel != PreviousPower) - { - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); - } - } - - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + if (PowerLevel != PreviousPower) { - UNUSED(a_Chunk); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - UNUSED(Callback); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } -}; +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_Position); + UNUSED(a_BlockType); + UNUSED(a_Meta); + UNUSED(Callback); +} +}; // namespace TrappedChestHandler diff --git a/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h index 578831db5..9fcadb0b3 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h @@ -9,104 +9,126 @@ namespace TripwireHookHandler { - static unsigned char GetPowerLevel(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta) +static unsigned char GetPowerLevel(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta) +{ + bool FoundActivated = false; + const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta); + + for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks { - bool FoundActivated = false; - const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta); + BLOCKTYPE Type; + NIBBLETYPE Meta; - for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks + a_Position = AddFaceDirection(a_Position, FaceToGoTowards); + if (!a_Chunk.UnboundedRelGetBlock(a_Position, Type, Meta)) { - BLOCKTYPE Type; - NIBBLETYPE Meta; + return 0; + } - a_Position = AddFaceDirection(a_Position, FaceToGoTowards); - if (!a_Chunk.UnboundedRelGetBlock(a_Position, Type, Meta)) + if (Type == E_BLOCK_TRIPWIRE) + { + if (FoundActivated) { - return 0; + continue; } - if (Type == E_BLOCK_TRIPWIRE) + if (!a_Chunk.ForEachEntityInBox( + cBoundingBox( + Vector3d(0.5, 0, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()), + 0.5, + 0.5 + ), + [](cEntity &) { return true; } + )) { - if (FoundActivated) - { - continue; - } - - if ( - !a_Chunk.ForEachEntityInBox( - cBoundingBox(Vector3d(0.5, 0, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()), 0.5, 0.5), - [](cEntity &) { return true; } - ) - ) - { - FoundActivated = true; - } - - continue; + FoundActivated = true; } - else if (Type == E_BLOCK_TRIPWIRE_HOOK) + + continue; + } + else if (Type == E_BLOCK_TRIPWIRE_HOOK) + { + if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards) { - if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards) - { - // Other hook facing in opposite direction - circuit completed! - return FoundActivated ? 15 : 1; - } + // Other hook facing in opposite direction - circuit completed! + return FoundActivated ? 15 : 1; } - - // Tripwire hook not connected at all - return 0; } + // Tripwire hook not connected at all return 0; } - static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) - { - UNUSED(a_BlockType); - UNUSED(a_QueryBlockType); - UNUSED(a_QueryPosition); + return 0; +} + +static PowerLevel GetPowerDeliveredToPosition( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + Vector3i a_QueryPosition, + BLOCKTYPE a_QueryBlockType, + bool IsLinked +) +{ + UNUSED(a_BlockType); + UNUSED(a_QueryBlockType); + UNUSED(a_QueryPosition); + + return (GetPowerLevel(a_Chunk, a_Position, a_Chunk.GetMeta(a_Position)) == 15) ? 15 : 0; +} + +static void Update( + cChunk & a_Chunk, + cChunk & CurrentlyTicking, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + const PowerLevel Power +) +{ + // LOGD("Evaluating hooky the tripwire hook (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - return (GetPowerLevel(a_Chunk, a_Position, a_Chunk.GetMeta(a_Position)) == 15) ? 15 : 0; + const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position, a_Meta); + NIBBLETYPE Meta; + if (PowerLevel == 0) + { + Meta = (a_Meta & 0x3); } - - static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) + else if (PowerLevel == 1) { - // LOGD("Evaluating hooky the tripwire hook (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position, a_Meta); - NIBBLETYPE Meta; - if (PowerLevel == 0) - { - Meta = (a_Meta & 0x3); - } - else if (PowerLevel == 1) - { - // Connected but not activated, AND away the highest bit - Meta = (a_Meta & 0x7) | 0x4; - } - else if (PowerLevel == 15) - { - // Connected and activated, set the 3rd and 4th highest bits - Meta = (a_Meta | 0xC); - } - else - { - UNREACHABLE("Unexpected tripwire hook power level!"); - } - - if (Meta != a_Meta) - { - a_Chunk.SetMeta(a_Position, Meta); - UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); - } + // Connected but not activated, AND away the highest bit + Meta = (a_Meta & 0x7) | 0x4; + } + else if (PowerLevel == 15) + { + // Connected and activated, set the 3rd and 4th highest bits + Meta = (a_Meta | 0xC); + } + else + { + UNREACHABLE("Unexpected tripwire hook power level!"); } - static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) + if (Meta != a_Meta) { - UNUSED(a_Chunk); - UNUSED(a_BlockType); - UNUSED(a_Meta); - UNUSED(a_Position); - UNUSED(Callback); + a_Chunk.SetMeta(a_Position, Meta); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } -}; +} + +static void ForValidSourcePositions( + const cChunk & a_Chunk, + Vector3i a_Position, + BLOCKTYPE a_BlockType, + NIBBLETYPE a_Meta, + ForEachSourceCallback & Callback +) +{ + UNUSED(a_Chunk); + UNUSED(a_BlockType); + UNUSED(a_Meta); + UNUSED(a_Position); + UNUSED(Callback); +} +}; // namespace TripwireHookHandler |