diff options
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h')
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h | 319 |
1 files changed, 172 insertions, 147 deletions
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 |