diff options
author | DrButcher <JoBad@online.de> | 2020-04-14 00:23:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-14 00:23:43 +0200 |
commit | 35299b8509c1acc66ccbddfd08a94a9b189737d8 (patch) | |
tree | 97de440879cd4d98f59c04177fd3e30d57940c56 /src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h | |
parent | Acquire chunk map CS when accessing player entities (diff) | |
download | cuberite-35299b8509c1acc66ccbddfd08a94a9b189737d8.tar cuberite-35299b8509c1acc66ccbddfd08a94a9b189737d8.tar.gz cuberite-35299b8509c1acc66ccbddfd08a94a9b189737d8.tar.bz2 cuberite-35299b8509c1acc66ccbddfd08a94a9b189737d8.tar.lz cuberite-35299b8509c1acc66ccbddfd08a94a9b189737d8.tar.xz cuberite-35299b8509c1acc66ccbddfd08a94a9b189737d8.tar.zst cuberite-35299b8509c1acc66ccbddfd08a94a9b189737d8.zip |
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h')
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h | 148 |
1 files changed, 141 insertions, 7 deletions
diff --git a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h index 8c37c629e..1eeaf2afa 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h @@ -3,6 +3,7 @@ #include "RedstoneHandler.h" #include "../../BoundingBox.h" +#include "../../Entities/Pickup.h" @@ -27,7 +28,7 @@ public: { UNUSED(a_Meta); - unsigned int NumberOfEntities = 0; + int NumberOfEntities = 0; bool FoundPlayer = false; a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + a_Position, 0.5, 0.5), [&](cEntity & a_Entity) { @@ -36,6 +37,11 @@ public: FoundPlayer = true; } + if (a_Entity.IsPickup()) + { + NumberOfEntities += static_cast<cPickup &>(a_Entity).GetItem().m_ItemCount; + return false; + } NumberOfEntities++; return false; } @@ -72,16 +78,103 @@ public: UNUSED(a_PoweringData.PowerLevel); // LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); - auto PreviousPower = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power)); + auto ChunkData = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData(); + + const auto PreviousPower = ChunkData->GetCachedPowerData(a_Position); + auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); // Get the current power of the platey + + const auto PlateUpdates = GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeLaterals(), cVector3iArray{ OffsetYM() })); + auto DelayInfo = ChunkData->GetMechanismDelayInfo(a_Position); - if (Power != PreviousPower.PowerLevel) + // Resting state? + if (DelayInfo == nullptr) { - a_World.SetBlockMeta(a_Position, (Power == 0) ? E_META_PRESSURE_PLATE_RAISED : E_META_PRESSURE_PLATE_DEPRESSED); - return GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeLaterals(), cVector3iArray{ OffsetYM() })); + if (Power == 0) + { + // Nothing happened, back to rest + return {}; + } + + // 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); + + auto soundToPlay = GetClickOnSound(a_BlockType); + a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.6f); + + // Update power + ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + + // Immediately depress plate + a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED); + return PlateUpdates; } - 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) + { + // Nothing changes, if there is nothing on it anymore, because the state is locked. + if (Power == 0) + { + return {}; + } + + // 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 (Power != PreviousPower.PowerLevel) + { + // Yes. Update power + ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + return PlateUpdates; + } + + return {}; + } + + // Not waiting for anything. Has the initial delay elapsed? + if (HasExitedMinimumOnDelayPhase) + { + // Yep, initial delay elapsed. Has the player gotten off? + if (Power == 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 (Power != PreviousPower.PowerLevel) + { + // Yes. Update power + ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + return PlateUpdates; + } + + // Yes, but player's still on the plate, do nothing + return {}; + } + + // Just got out of the subsequent release phase, reset everything and raise the plate + ChunkData->m_MechanismDelays.erase(a_Position); + + auto soundToPlay = GetClickOffSound(a_BlockType); + a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.5f); + ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + + a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_RAISED); + return PlateUpdates; } virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override @@ -92,4 +185,45 @@ public: UNUSED(a_Meta); return {}; } + +private: + static AString GetClickOnSound(BLOCKTYPE a_BlockType) + { + // manage on-sound + switch (a_BlockType) + { + case E_BLOCK_STONE_PRESSURE_PLATE: + return "block.wood_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 ""; + } + } + } + + static AString GetClickOffSound(BLOCKTYPE a_BlockType) + { + // manage on-sound + switch (a_BlockType) + { + case E_BLOCK_STONE_PRESSURE_PLATE: + return "block.wood_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 ""; + } + } + } }; |