summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h')
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h75
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);
- }
};