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 --- .../IncrementalRedstoneSimulator.cpp | 4 +- .../IncrementalRedstoneSimulator.h | 1 - .../RedstoneDataHelper.h | 30 ++++++++++---- .../RedstoneWireHandler.h | 48 ++++++++++++---------- 4 files changed, 52 insertions(+), 31 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator') diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp index c23af9f75..8063e72a4 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp @@ -217,12 +217,14 @@ void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position for (const auto & Offset : cSimulator::GetLinkedOffsets(a_Offset)) { auto Relative = a_Position - a_Offset + Offset; + if (!cChunkDef::IsValidHeight(Relative)) { continue; } - auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Relative); + const auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Relative); + if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h index 7f08c50af..365f0176e 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h @@ -26,7 +26,6 @@ private: void ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position); - virtual void Simulate(float Dt) override {} virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override; virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; virtual cRedstoneSimulatorChunkData * CreateChunkData() override; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h index dc97a34d4..3942f803c 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h @@ -7,23 +7,37 @@ inline auto & DataForChunk(const cChunk & a_Chunk) return *static_cast(a_Chunk.GetRedstoneSimulatorData()); } -template -inline void UpdateAdjustedRelative(const cChunk & From, const cChunk & To, const Vector3i Position, const Vector3i Offset) +inline void UpdateAdjustedRelative(const cChunk & a_Chunk, const cChunk & a_TickingChunk, const Vector3i a_Position, const Vector3i a_Offset) { - DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset)); + const auto PositionToWake = a_Position + a_Offset; - for (const auto & LinkedOffset : cSimulator::GetLinkedOffsets(Offset)) + if (!cChunkDef::IsValidHeight(PositionToWake)) { - DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + LinkedOffset)); + // If an offset position is not a valid height, its linked offset positions won't be either. + return; + } + + auto & ChunkData = DataForChunk(a_TickingChunk); + + // Schedule the block in the requested direction to update: + ChunkData.WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, a_TickingChunk, PositionToWake)); + + // To follow Vanilla behaviour, update all linked positions: + for (const auto & LinkedOffset : cSimulator::GetLinkedOffsets(a_Offset)) + { + if (const auto LinkedPositionToWake = a_Position + LinkedOffset; cChunkDef::IsValidHeight(LinkedPositionToWake)) + { + ChunkData.WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, a_TickingChunk, LinkedPositionToWake)); + } } } template -inline void UpdateAdjustedRelatives(const cChunk & From, const cChunk & To, const Vector3i Position, const ArrayType & Relative) +inline void UpdateAdjustedRelatives(const cChunk & a_Chunk, const cChunk & a_TickingChunk, const Vector3i a_Position, const ArrayType & a_Relative) { - for (const auto & Offset : Relative) + for (const auto & Offset : a_Relative) { - UpdateAdjustedRelative(From, To, Position, Offset); + UpdateAdjustedRelative(a_Chunk, a_TickingChunk, a_Position, Offset); } } 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