summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator
diff options
context:
space:
mode:
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator')
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp4
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h1
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h30
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h48
4 files changed, 52 insertions, 31 deletions
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<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
}
-template <typename... ArrayTypes>
-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 <typename ArrayType>
-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)