From f089103c2b121f8128abfd6cdf0bd3cfbeca4465 Mon Sep 17 00:00:00 2001 From: Debucquoy Anthony tonitch Date: Sat, 18 Jun 2022 02:09:58 +0200 Subject: Additional Y height checks (#5405) For redstone wire, block area bindings, and fire simulator. Co-authored-by: Tiger Wang --- .../RedstoneWireHandler.h | 48 ++++++++++++---------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h') diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h index 5f2026842..b40491820 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h @@ -100,19 +100,32 @@ namespace RedstoneWireHandler } } + static bool IsYPTerracingBlocked(const cChunk & a_Chunk, const Vector3i a_Position) + { + const auto Position = a_Position + OffsetYP; + + 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); + } + /** 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 & Chunk, const Vector3i Position) + static void SetWireState(const cChunk & a_Chunk, const Vector3i a_Position) { auto Block = Block::RedstoneWire::RedstoneWire(); - const auto YPTerraceBlock = Chunk.GetBlock(Position + OffsetYP); - const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock); + const bool IsYPTerracingBlocked = RedstoneWireHandler::IsYPTerracingBlocked(a_Chunk, a_Position); // Loop through laterals, discovering terracing connections: for (const auto & Offset : RelativeLaterals) { - auto Adjacent = Position + Offset; - auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(Adjacent); + auto Adjacent = a_Position + Offset; + auto NeighbourChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Adjacent); if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid()) { @@ -131,7 +144,7 @@ namespace RedstoneWireHandler // 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 != &Chunk) && (LateralBlock == E_BLOCK_REDSTONE_WIRE)) + if ((NeighbourChunk != &a_Chunk) && (LateralBlock == E_BLOCK_REDSTONE_WIRE)) { auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent)->second; SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); @@ -148,7 +161,7 @@ namespace RedstoneWireHandler { SetDirectionState(Offset, Block, cBlockInfo::IsTransparent(LateralBlock) ? TemporaryDirection::Side : TemporaryDirection::Up); - if (NeighbourChunk != &Chunk) + if (NeighbourChunk != &a_Chunk) { auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYP)->second; SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); @@ -166,7 +179,7 @@ namespace RedstoneWireHandler { SetDirectionState(Offset, Block, TemporaryDirection::Side); - if (NeighbourChunk != &Chunk) + if (NeighbourChunk != &a_Chunk) { auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYM)->second; SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Up); @@ -174,8 +187,8 @@ namespace RedstoneWireHandler } } - auto & States = DataForChunk(Chunk).WireStates; - const auto FindResult = States.find(Position); + auto & States = DataForChunk(a_Chunk).WireStates; + const auto FindResult = States.find(a_Position); if (FindResult != States.end()) { if (Block != FindResult->second) @@ -184,13 +197,13 @@ namespace RedstoneWireHandler // 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: - Chunk.GetWorld()->WakeUpSimulators(cChunkDef::RelativeToAbsolute(Position, Chunk.GetPos())); + a_Chunk.GetWorld()->WakeUpSimulators(cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); } return; } - DataForChunk(Chunk).WireStates.emplace(Position, Block); + 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) @@ -269,15 +282,8 @@ namespace RedstoneWireHandler a_Chunk.SetMeta(a_Position, Power); // Notify all positions, sans YP, to update: - for (const auto & Offset : RelativeAdjacents) - { - if (Offset == OffsetYP) - { - continue; - } - - UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Offset); - } + 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) -- cgit v1.2.3