diff options
author | Tiger Wang <ziwei.tiger@outlook.com> | 2020-09-28 23:04:57 +0200 |
---|---|---|
committer | Tiger Wang <ziwei.tiger@outlook.com> | 2020-09-29 00:40:19 +0200 |
commit | 429117c1f6131df407246a46bc75a724eca0da54 (patch) | |
tree | 9d5f027063fa52b981a129c4b5b402409714391c /src/Simulator/IncrementalRedstoneSimulator | |
parent | HandleEnchantItem: use a lambda (#4944) (diff) | |
download | cuberite-429117c1f6131df407246a46bc75a724eca0da54.tar cuberite-429117c1f6131df407246a46bc75a724eca0da54.tar.gz cuberite-429117c1f6131df407246a46bc75a724eca0da54.tar.bz2 cuberite-429117c1f6131df407246a46bc75a724eca0da54.tar.lz cuberite-429117c1f6131df407246a46bc75a724eca0da54.tar.xz cuberite-429117c1f6131df407246a46bc75a724eca0da54.tar.zst cuberite-429117c1f6131df407246a46bc75a724eca0da54.zip |
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator')
-rw-r--r-- | src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h | 75 |
1 files changed, 55 insertions, 20 deletions
diff --git a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h index fa5debbbf..00fd8c7eb 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h @@ -22,42 +22,77 @@ namespace DoorHandler return 0; } + inline 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); + } + inline 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); - if ((a_Meta & 0x8) == 0x8) + 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) { - // We're treating the bottom half as the source of truth, so ignore updates to the top: - return; + TopMeta = a_Meta; + } + else + { + if (TopPosition.y == cChunkDef::Height) + { + return; + } + + BLOCKTYPE AboveType; + a_Chunk.GetBlockTypeMeta(TopPosition, AboveType, TopMeta); + if (!cBlockDoorHandler::IsDoorBlockType(AboveType)) + { + return; + } } - const auto TopPosition = a_Position + OffsetYP; - ForEachSourceCallback Callback(a_Chunk, TopPosition, a_BlockType); - RedstoneHandler::ForValidSourcePositions(a_Chunk, TopPosition, 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 upper half is getting: + // Factor in what the other half is getting: Power = std::max(Power, Callback.Power); - cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap()); - // 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; + 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; + } + + // 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()); - if (ShouldBeOpen != IsOpen) + // 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); } } - - inline 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); - } }; |