summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2020-08-08 19:22:16 +0200
committerTiger Wang <ziwei.tiger@outlook.com>2020-08-08 19:22:16 +0200
commit40eba5244ddd7045a9c3539c5f46c9921301ed90 (patch)
tree9edf40e2e5033ad19ce8a0739668500e30de653e
parentconst-ify some Chunk functions (diff)
downloadcuberite-40eba5244ddd7045a9c3539c5f46c9921301ed90.tar
cuberite-40eba5244ddd7045a9c3539c5f46c9921301ed90.tar.gz
cuberite-40eba5244ddd7045a9c3539c5f46c9921301ed90.tar.bz2
cuberite-40eba5244ddd7045a9c3539c5f46c9921301ed90.tar.lz
cuberite-40eba5244ddd7045a9c3539c5f46c9921301ed90.tar.xz
cuberite-40eba5244ddd7045a9c3539c5f46c9921301ed90.tar.zst
cuberite-40eba5244ddd7045a9c3539c5f46c9921301ed90.zip
-rw-r--r--src/BlockEntities/BlockEntityWithItems.cpp5
-rw-r--r--src/BlockEntities/ChestEntity.cpp5
-rw-r--r--src/Blocks/BlockButton.h27
-rw-r--r--src/Blocks/BlockLever.h3
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/CMakeLists.txt3
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h21
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp113
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h32
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp69
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h54
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h16
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h13
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h29
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h54
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h67
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h6
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h60
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h11
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h43
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h59
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h355
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h62
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h8
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h16
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h10
-rw-r--r--src/Simulator/RedstoneSimulator.h13
-rw-r--r--src/Simulator/Simulator.cpp84
-rw-r--r--src/Simulator/Simulator.h5
35 files changed, 731 insertions, 568 deletions
diff --git a/src/BlockEntities/BlockEntityWithItems.cpp b/src/BlockEntities/BlockEntityWithItems.cpp
index b2f225aa7..d7ffc960e 100644
--- a/src/BlockEntities/BlockEntityWithItems.cpp
+++ b/src/BlockEntities/BlockEntityWithItems.cpp
@@ -58,10 +58,7 @@ void cBlockEntityWithItems::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
auto & Simulator = *m_World->GetRedstoneSimulator();
// Notify comparators:
- m_World->WakeUpSimulators(m_Pos + Vector3i(1, 0, 0));
- m_World->WakeUpSimulators(m_Pos + Vector3i(-1, 0, 0));
- m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, 1));
- m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, -1));
+ m_World->WakeUpSimulators(m_Pos);
return true;
});
}
diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp
index cb26f4d08..b5d281fec 100644
--- a/src/BlockEntities/ChestEntity.cpp
+++ b/src/BlockEntities/ChestEntity.cpp
@@ -248,10 +248,7 @@ void cChestEntity::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
auto & Simulator = *m_World->GetRedstoneSimulator();
// Notify comparators:
- m_World->WakeUpSimulators(m_Pos + Vector3i(1, 0, 0));
- m_World->WakeUpSimulators(m_Pos + Vector3i(-1, 0, 0));
- m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, 1));
- m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, -1));
+ m_World->WakeUpSimulators(m_Pos);
return true;
});
}
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index 9d8bf3da1..f4994f193 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -48,7 +48,7 @@ public:
const auto SoundToPlay = (m_BlockType == E_BLOCK_STONE_BUTTON) ? "block.stone_button.click_on" : "block.wood_button.click_on";
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta, false);
- WakeUpSimulators(a_WorldInterface, a_BlockPos);
+ a_WorldInterface.WakeUpSimulators(a_BlockPos);
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect(SoundToPlay, a_BlockPos, 0.5f, 0.6f, a_Player.GetClientHandle());
// Queue a button reset (unpress)
@@ -186,7 +186,7 @@ public:
}
a_World.SetBlockMeta(Pos, Meta | 0x08, false);
- WakeUpSimulators(a_World, Pos);
+ a_World.WakeUpSimulators(Pos);
// sound name is ok to be wood, because only wood gets triggered by arrow
a_World.GetBroadcastManager().BroadcastSoundEffect("block.wood_button.click_on", Pos, 0.5f, 0.6f);
@@ -195,27 +195,6 @@ public:
QueueButtonRelease(a_World, Pos, Type);
}
- /** Notify, mainly the redstone simulator, that this toggle component has updated. */
- template <class WorldType>
- static void WakeUpSimulators(WorldType & a_World, const Vector3i a_Position)
- {
- // Contains our direct adjacents
- static const Vector3i Offsets[] =
- {
- { 1, 0, 0 },
- { -1, 0, 0 },
- { 0, 1, 0 },
- { 0, -1, 0 },
- { 0, 0, 1 },
- { 0, 0, -1 }
- };
-
- for (const auto & Offset : Offsets)
- {
- a_World.WakeUpSimulators(a_Position + Offset);
- }
- }
-
private:
/** Schedules a recurring event at appropriate intervals to release a button at a given position.
@@ -250,7 +229,7 @@ private:
const auto SoundToPlayOnRelease = (Type == E_BLOCK_STONE_BUTTON) ? "block.stone_button.click_off" : "block.wood_button.click_off";
a_World.SetBlockMeta(a_Position, Meta & 0x07, false);
- WakeUpSimulators(a_World, a_Position);
+ a_World.WakeUpSimulators(a_Position);
a_World.BroadcastSoundEffect(SoundToPlayOnRelease, a_Position, 0.5f, 0.5f);
}
);
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 7f028b61f..4a682322d 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -3,7 +3,6 @@
#include "BlockHandler.h"
#include "../Chunk.h"
#include "Mixins.h"
-#include "BlockButton.h"
#include "BlockSlab.h"
@@ -36,7 +35,7 @@ public:
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x08);
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta);
- cBlockButtonHandler::WakeUpSimulators(a_WorldInterface, a_BlockPos);
+ a_WorldInterface.WakeUpSimulators(a_BlockPos);
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.lever.click", a_BlockPos, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
return true;
}
diff --git a/src/Simulator/IncrementalRedstoneSimulator/CMakeLists.txt b/src/Simulator/IncrementalRedstoneSimulator/CMakeLists.txt
index 1857a115a..3f64d6e4e 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/CMakeLists.txt
+++ b/src/Simulator/IncrementalRedstoneSimulator/CMakeLists.txt
@@ -1,16 +1,17 @@
target_sources(
${CMAKE_PROJECT_NAME} PRIVATE
+ ForEachSourceCallback.cpp
IncrementalRedstoneSimulator.cpp
CommandBlockHandler.h
DoorHandler.h
DropSpenserHandler.h
+ ForEachSourceCallback.h
HopperHandler.h
IncrementalRedstoneSimulator.h
RedstoneHandler.h
RedstoneSimulatorChunkData.h
- SolidBlockHandler.h
RedstoneComparatorHandler.h
RedstoneRepeaterHandler.h
RedstoneBlockHandler.h
diff --git a/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h
index 31a34236c..89dc55ecd 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h
@@ -10,16 +10,14 @@
class cCommandBlockHandler final : public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -41,7 +39,7 @@ public:
});
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h
index c91886f4e..7011b852b 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h
@@ -10,16 +10,16 @@
class cDoorHandler final : public cRedstoneHandler
{
-public:
+ // "Doormammu, I've come to bargain"
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -27,6 +27,19 @@ public:
{
// LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
+ if ((a_Meta & 0x8) == 0x8)
+ {
+ // We're treating the bottom half as the source of truth, so ignore updates to the top:
+ return;
+ }
+
+ const auto TopPosition = a_Position + OffsetYP;
+ ForEachSourceCallback Callback(a_Chunk, TopPosition, a_BlockType);
+ ForValidSourcePositions(a_Chunk, TopPosition, a_BlockType, a_Meta, Callback);
+
+ // Factor in what the upper half is getting:
+ a_PoweringData = std::max(a_PoweringData, Callback.Power);
+
cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap());
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0;
const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
@@ -39,7 +52,7 @@ public:
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h
index cee8133d8..d953be8c0 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h
@@ -10,8 +10,6 @@
class cDropSpenserHandler final : public cRedstoneHandler
{
-public:
-
inline static bool IsActivated(NIBBLETYPE a_Meta)
{
return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0;
@@ -29,14 +27,14 @@ public:
}
}
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -63,7 +61,7 @@ public:
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp
new file mode 100644
index 000000000..3bf0fc371
--- /dev/null
+++ b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp
@@ -0,0 +1,113 @@
+
+#include "Globals.h"
+
+#include "ForEachSourceCallback.h"
+#include "IncrementalRedstoneSimulator.h"
+#include "../../BlockInfo.h"
+#include "../../Chunk.h"
+
+
+
+
+
+ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE CurrentBlock) :
+ m_Chunk(Chunk),
+ m_Position(Position),
+ m_CurrentBlock(CurrentBlock)
+{
+}
+
+
+
+
+
+bool ForEachSourceCallback::ShouldQueryLinkedPosition(const Vector3i Location, const BLOCKTYPE Block)
+{
+ switch (Block)
+ {
+ case E_BLOCK_BLOCK_OF_REDSTONE:
+ case E_BLOCK_TRAPPED_CHEST: return false;
+ default: return cBlockInfo::IsSolid(Block);
+ }
+}
+
+
+
+
+
+void ForEachSourceCallback::operator()(Vector3i Location)
+{
+ if (!cChunk::IsValidHeight(Location.y))
+ {
+ return;
+ }
+
+ const auto NeighbourChunk = m_Chunk.GetRelNeighborChunkAdjustCoords(Location);
+ if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
+ {
+ return;
+ }
+
+ const auto PotentialSourceBlock = NeighbourChunk->GetBlock(Location);
+ const auto NeighbourRelativeQueryPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position);
+
+ if (ShouldQueryLinkedPosition(Location, PotentialSourceBlock))
+ {
+ Power = std::max(Power, QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location));
+ }
+ else
+ {
+ Power = std::max(Power, QueryPower(*NeighbourChunk, Location, PotentialSourceBlock, NeighbourRelativeQueryPosition, m_CurrentBlock, false));
+ }
+}
+
+
+
+
+
+PoweringData ForEachSourceCallback::QueryPower(const cChunk & Chunk, const Vector3i SourcePosition, const BLOCKTYPE SourceBlock, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const bool IsLinked)
+{
+ const auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(SourceBlock);
+ if (PotentialSourceHandler == nullptr)
+ {
+ return {};
+ }
+
+ return
+ {
+ SourceBlock,
+ PotentialSourceHandler->GetPowerDeliveredToPosition(
+ Chunk, SourcePosition, SourceBlock,
+ QueryPosition, QueryBlock, IsLinked
+ )
+ };
+}
+
+
+
+
+
+PoweringData ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition)
+{
+ PoweringData Power;
+
+ for (const auto Offset : cSimulator::GetLinkedOffsets(SolidBlockPosition - QueryPosition))
+ {
+ auto SourcePosition = QueryPosition + Offset;
+ if (!cChunk::IsValidHeight(SourcePosition.y))
+ {
+ continue;
+ }
+
+ const auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(SourcePosition);
+ if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
+ {
+ continue;
+ }
+
+ const auto NeighbourRelativeSolidBlockPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, SolidBlockPosition);
+ Power = std::max(Power, QueryPower(*NeighbourChunk, SourcePosition, NeighbourChunk->GetBlock(SourcePosition), NeighbourRelativeSolidBlockPosition, QueryBlock, true));
+ }
+
+ return Power;
+}
diff --git a/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h
new file mode 100644
index 000000000..4ab3866d3
--- /dev/null
+++ b/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h
@@ -0,0 +1,32 @@
+
+#pragma once
+
+#include "ForEachSourceCallback.h"
+#include "RedstoneSimulatorChunkData.h"
+
+class ForEachSourceCallback
+{
+public:
+
+ ForEachSourceCallback(const cChunk & Chunk, Vector3i Position, BLOCKTYPE CurrentBlock);
+
+ /** Returns whether a potential source position should be treated as linked. */
+ bool ShouldQueryLinkedPosition(Vector3i Location, BLOCKTYPE Block);
+
+ /** Callback invoked for each potential source position of the redstone component. */
+ void operator()(Vector3i Location);
+
+ /** Asks a redstone component at the source position how much power it will deliver to the querying position. */
+ static PoweringData QueryPower(const cChunk & Chunk, Vector3i SourcePosition, BLOCKTYPE SourceBlock, Vector3i QueryPosition, BLOCKTYPE QueryBlock, bool IsLinked);
+
+ /** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block. */
+ static PoweringData QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition);
+
+ PoweringData Power;
+
+private:
+
+ const cChunk & m_Chunk;
+ const Vector3i m_Position;
+ const BLOCKTYPE m_CurrentBlock;
+};
diff --git a/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h b/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h
index 2f2e5b129..24685e287 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h
@@ -10,16 +10,14 @@
class cHopperHandler final : public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -40,7 +38,7 @@ public:
});
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
index e3177e420..056bfb368 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
@@ -1,9 +1,8 @@
-
#include "Globals.h"
#include "IncrementalRedstoneSimulator.h"
-#include "../../Chunk.h"
+#include "ForEachSourceCallback.h"
#include "CommandBlockHandler.h"
#include "DoorHandler.h"
@@ -11,7 +10,6 @@
#include "RedstoneWireHandler.h"
#include "RedstoneRepeaterHandler.h"
#include "RedstoneToggleHandler.h"
-#include "SolidBlockHandler.h"
#include "RedstoneLampHandler.h"
#include "RedstoneBlockHandler.h"
#include "PistonHandler.h"
@@ -115,10 +113,6 @@ std::unique_ptr<cRedstoneHandler> cIncrementalRedstoneSimulator::CreateComponent
return std::make_unique<cDoorHandler>();
}
- if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))
- {
- return std::make_unique<cSolidBlockHandler>();
- }
return nullptr;
}
}
@@ -182,42 +176,11 @@ void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & Tic
return;
}
- PoweringData Power;
- CurrentHandler->ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, [&Chunk, Position, CurrentBlock, &Power](Vector3i Location)
- {
- if (!cChunk::IsValidHeight(Location.y))
- {
- return;
- }
-
- const auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(Location);
- if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
- {
- return;
- }
-
- BLOCKTYPE PotentialBlock;
- NIBBLETYPE PotentialMeta;
- NeighbourChunk->GetBlockTypeMeta(Location, PotentialBlock, PotentialMeta);
-
- auto PotentialSourceHandler = GetComponentHandler(PotentialBlock);
- if (PotentialSourceHandler == nullptr)
- {
- return;
- }
-
- const PoweringData PotentialPower(
- PotentialBlock,
- PotentialSourceHandler->GetPowerDeliveredToPosition(
- *NeighbourChunk, Location, PotentialBlock, PotentialMeta,
- cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, Position), CurrentBlock
- )
- );
- Power = std::max(Power, PotentialPower);
- });
+ ForEachSourceCallback Callback(Chunk, Position, CurrentBlock);
+ CurrentHandler->ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, Callback);
// Inform the handler to update
- CurrentHandler->Update(Chunk, TickingSource, Position, CurrentBlock, CurrentMeta, Power);
+ CurrentHandler->Update(Chunk, TickingSource, Position, CurrentBlock, CurrentMeta, Callback.Power);
}
@@ -241,6 +204,12 @@ void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Positi
ChunkData.AlwaysTickedPositions.emplace(a_Position);
}
+ // Temporary: in the absence of block state support calculate our own:
+ if (a_Block == E_BLOCK_REDSTONE_WIRE)
+ {
+ static_cast<const cRedstoneWireHandler *>(GetComponentHandler(a_Block))->SetWireState(a_Chunk, a_Position);
+ }
+
// Always update redstone devices:
ChunkData.WakeUp(a_Position);
}
@@ -273,5 +242,21 @@ void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position
// The only thing to do go one block farther than this cross-coord, in the direction of Offset
// in order to notify linked-powered positions that there was a change
- // TODO: use a_Offset, exclude a_Position and a_Position - a_Offset
+ for (const auto Offset : cSimulator::GetLinkedOffsets(a_Offset))
+ {
+ auto Relative = a_Position - a_Offset + Offset;
+ if (!cChunkDef::IsValidHeight(Relative.y))
+ {
+ continue;
+ }
+
+ auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Relative);
+ if ((Chunk == nullptr) || !Chunk->IsValid())
+ {
+ continue;
+ }
+
+ const auto Block = Chunk->GetBlock(Relative);
+ AddBlock(*Chunk, Relative, Block);
+ }
}
diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h
index e20880b7a..a940b8920 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h
@@ -16,58 +16,11 @@ class cIncrementalRedstoneSimulator final :
public:
- cIncrementalRedstoneSimulator(cWorld & a_World) :
- Super(a_World)
- {
- }
+ using Super::cRedstoneSimulator;
static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType);
- /** Returns if a block is a mechanism (something that accepts power and does something)
- Used by torches to determine if they will power a block */
- inline static bool IsMechanism(BLOCKTYPE Block)
- {
- switch (Block)
- {
- case E_BLOCK_ACACIA_DOOR:
- case E_BLOCK_ACACIA_FENCE_GATE:
- case E_BLOCK_ACTIVATOR_RAIL:
- case E_BLOCK_ACTIVE_COMPARATOR:
- case E_BLOCK_BIRCH_DOOR:
- case E_BLOCK_BIRCH_FENCE_GATE:
- case E_BLOCK_COMMAND_BLOCK:
- case E_BLOCK_DARK_OAK_DOOR:
- case E_BLOCK_DARK_OAK_FENCE_GATE:
- case E_BLOCK_DISPENSER:
- case E_BLOCK_DROPPER:
- case E_BLOCK_FENCE_GATE:
- case E_BLOCK_HOPPER:
- case E_BLOCK_INACTIVE_COMPARATOR:
- case E_BLOCK_IRON_DOOR:
- case E_BLOCK_IRON_TRAPDOOR:
- case E_BLOCK_JUNGLE_DOOR:
- case E_BLOCK_JUNGLE_FENCE_GATE:
- case E_BLOCK_NOTE_BLOCK:
- case E_BLOCK_OBSERVER:
- case E_BLOCK_PISTON:
- case E_BLOCK_POWERED_RAIL:
- case E_BLOCK_REDSTONE_LAMP_OFF:
- case E_BLOCK_REDSTONE_LAMP_ON:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_WIRE:
- case E_BLOCK_SPRUCE_DOOR:
- case E_BLOCK_SPRUCE_FENCE_GATE:
- case E_BLOCK_STICKY_PISTON:
- case E_BLOCK_TNT:
- case E_BLOCK_TRAPDOOR:
- case E_BLOCK_WOODEN_DOOR:
- {
- return true;
- }
- default: return false;
- }
- }
+private:
/** Returns if a redstone device is always ticked due to influence by its environment */
inline static bool IsAlwaysTicked(BLOCKTYPE a_Block)
@@ -133,7 +86,6 @@ public:
case E_BLOCK_TRAPDOOR:
case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_TRIPWIRE_HOOK:
- case E_BLOCK_TRIPWIRE:
case E_BLOCK_WOODEN_BUTTON:
case E_BLOCK_WOODEN_DOOR:
case E_BLOCK_WOODEN_PRESSURE_PLATE:
@@ -145,8 +97,6 @@ public:
}
}
-private:
-
virtual void Simulate(float Dt) override {};
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override;
diff --git a/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h
index 7d3ec2f30..e610e6bdf 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h
@@ -10,16 +10,14 @@
class cNoteBlockHandler: public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -41,7 +39,7 @@ public:
});
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h b/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h
index 211e3c64a..c0866824b 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h
@@ -10,8 +10,6 @@
class cObserverHandler final : public cRedstoneHandler
{
-public:
-
inline static bool IsOn(NIBBLETYPE a_Meta)
{
return (a_Meta & 0x8) == 0x8;
@@ -34,14 +32,10 @@ public:
return (Previous.PoweringBlock != Observed.PoweringBlock) || (Previous.PowerLevel != Observed.PowerLevel);
}
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
- if (IsOn(a_Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta))))
- {
- return 15;
- }
-
- return 0;
+ const auto Meta = a_Chunk.GetMeta(a_Position);
+ return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0;
}
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
@@ -87,10 +81,10 @@ public:
a_Chunk.SetMeta(a_Position, a_Meta & ~0x8);
}
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta));
+ UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockObserverHandler::GetSignalOutputOffset(a_Meta));
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h
index b3860a778..14932b95b 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h
@@ -10,16 +10,14 @@
class cPistonHandler final: public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -48,7 +46,7 @@ public:
// However, this delay is already present: as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h
index 9e58e09ad..6f8dbc196 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h
@@ -9,8 +9,6 @@
class cPoweredRailHandler final : public cRedstoneHandler
{
-public:
-
static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) // Not in cBlockRailHandler since specific to powered rails
{
switch (a_Meta & 0x7)
@@ -29,11 +27,12 @@ public:
}
}
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_QueryBlockType);
- auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
+ const auto Meta = a_Chunk.GetMeta(a_Position);
+ const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(Meta);
if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition))
{
auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
@@ -66,8 +65,8 @@ public:
{
a_Chunk.SetMeta(a_Position, (a_PoweringData.PowerLevel == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08));
- UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position + Offset);
- UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position + -Offset);
+ UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, Offset);
+ UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, -Offset);
}
return;
@@ -79,7 +78,7 @@ public:
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_Meta);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h
index f6969e15a..979d1ef96 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h
@@ -11,19 +11,18 @@
class cPressurePlateHandler final : public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
- return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
+ // Plates only link power blocks below
+ // Retrieve and return the cached power calculated by Update for performance:
+ return (IsLinked && (a_QueryPosition != (a_Position + OffsetYM))) ? 0 : DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
}
- static unsigned char GetPowerLevel(cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType)
+ static unsigned char GetPowerLevel(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType)
{
unsigned NumberOfEntities = 0;
bool FoundPlayer = false;
@@ -70,12 +69,6 @@ public:
}
}
- static void UpdatePlate(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position)
- {
- UpdateAdjustedRelative(Chunk, CurrentlyTicking, Position + OffsetYM);
- UpdateAdjustedRelatives(Chunk, CurrentlyTicking, Position, RelativeLaterals);
- }
-
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
{
// LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
@@ -107,7 +100,9 @@ public:
// Immediately depress plate
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
- return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
+
+ UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
+ return;
}
// Not a resting state
@@ -137,7 +132,7 @@ public:
{
// Yes. Update power
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
- return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
+ UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
}
return;
@@ -159,7 +154,7 @@ public:
{
// Yes. Update power
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
- return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
+ UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
}
// Yes, but player's still on the plate, do nothing
@@ -173,10 +168,10 @@ public:
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
- return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
+ UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h
index 150723944..51e2162d1 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h
@@ -11,14 +11,14 @@ class cRedstoneBlockHandler final : public cRedstoneHandler
{
public:
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
- return cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) ? 15 : 0;
+ UNUSED(IsLinked);
+ return IsLinked ? 0 : 15;
}
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
@@ -26,7 +26,7 @@ public:
// LOGD("Evaluating crimson the redstone block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h
index 4ccb6838e..bf781eb7a 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h
@@ -10,8 +10,6 @@
class cRedstoneComparatorHandler : public cRedstoneHandler
{
-public:
-
static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel)
{
if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta))
@@ -26,13 +24,14 @@ public:
}
}
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ const auto Meta = a_Chunk.GetMeta(a_Position);
return (
- (cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) == a_QueryPosition) ?
+ (cBlockComparatorHandler::GetFrontCoordinate(a_Position, Meta & 0x3) == a_QueryPosition) ?
DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel : 0
);
}
@@ -71,11 +70,8 @@ public:
return false;
});
- BLOCKTYPE RearType;
- NIBBLETYPE RearMeta;
- RearChunk->GetBlockTypeMeta(RearCoordinate, RearType, RearMeta);
-
- auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
+ const auto RearType = RearChunk->GetBlock(RearCoordinate);
+ const auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
if (PotentialSourceHandler == nullptr)
{
return SignalStrength;
@@ -84,8 +80,8 @@ public:
return std::max(
SignalStrength,
PotentialSourceHandler->GetPowerDeliveredToPosition(
- *RearChunk, RearCoordinate, RearType, RearMeta,
- cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType
+ *RearChunk, RearCoordinate, RearType,
+ cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType, false
)
);
}
@@ -110,31 +106,33 @@ public:
{
Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool());
}
+
+ return;
}
- else
+
+ int DelayTicks;
+ std::tie(DelayTicks, std::ignore) = *DelayInfo;
+
+ if (DelayTicks != 0)
{
- int DelayTicks;
- std::tie(DelayTicks, std::ignore) = *DelayInfo;
+ return;
+ }
- if (DelayTicks == 0)
- {
- const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
- const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
- const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
+ const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
+ const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
+ const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
- // Don't care about the previous power level so return value ignored
- Data.ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
+ // Don't care about the previous power level so return value ignored
+ Data.ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
- a_Chunk.SetMeta(a_Position, NewMeta);
- Data.m_MechanismDelays.erase(a_Position);
+ a_Chunk.SetMeta(a_Position, NewMeta);
+ Data.m_MechanismDelays.erase(a_Position);
- // Assume that an update (to front power) is needed:
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3));
- }
- }
+ // Assume that an update (to front power) is needed:
+ UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) - a_Position);
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h
index 79c410265..9b131ece2 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h
@@ -2,6 +2,7 @@
#pragma once
#include "../../Chunk.h"
+#include "ForEachSourceCallback.h"
#include "RedstoneSimulatorChunkData.h"
@@ -15,71 +16,55 @@ public:
cRedstoneHandler() = default;
DISALLOW_COPY_AND_ASSIGN(cRedstoneHandler);
- using SourceCallback = cFunctionRef<void(Vector3i)>;
+ using SourceCallback = ForEachSourceCallback &;
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const = 0;
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const = 0;
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const = 0;
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const = 0;
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const = 0;
// Force a virtual destructor
virtual ~cRedstoneHandler() {}
protected:
- template <class Container>
- static Container StaticAppend(const Container & a_Lhs, const Container & a_Rhs)
- {
- Container ToReturn = a_Lhs;
- std::copy(a_Rhs.begin(), a_Rhs.end(), std::back_inserter(ToReturn));
- return ToReturn;
- }
-
- inline static Vector3i OffsetYP{ 0, 1, 0 };
-
- inline static Vector3i OffsetYM{ 0, -1, 0 };
-
- static cVector3iArray GetAdjustedRelatives(Vector3i a_Position, cVector3iArray a_Relatives)
- {
- for (auto & Entry : a_Relatives)
- {
- Entry += a_Position;
- }
- return a_Relatives;
- }
-
- inline static cIncrementalRedstoneSimulatorChunkData & DataForChunk(cChunk & a_Chunk)
+ inline static auto & DataForChunk(const cChunk & a_Chunk)
{
return *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
}
template <typename... ArrayTypes>
- static void UpdateAdjustedRelative(cChunk & From, cChunk & To, const Vector3i Position)
+ static void UpdateAdjustedRelative(const cChunk & From, const cChunk & To, const Vector3i Position, const Vector3i Offset)
{
- DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position));
+ DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset));
+
+ for (const auto LinkedOffset : cSimulator::GetLinkedOffsets(Offset))
+ {
+ DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + LinkedOffset));
+ }
}
- template <typename ArrayType, typename... ArrayTypes>
- static void UpdateAdjustedRelatives(cChunk & From, cChunk & To, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
+ template <typename ArrayType>
+ static void UpdateAdjustedRelatives(const cChunk & From, const cChunk & To, const Vector3i Position, const ArrayType & Relative)
{
for (const auto Offset : Relative)
{
- DataForChunk(To).GetActiveBlocks().push(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset));
+ UpdateAdjustedRelative(From, To, Position, Offset);
}
-
- UpdateAdjustedRelatives(From, To, Position, Relatives...);
}
- template <typename ArrayType, typename... ArrayTypes>
- static void InvokeForAdjustedRelatives(SourceCallback Callback, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
+ template <typename ArrayType>
+ static void InvokeForAdjustedRelatives(SourceCallback Callback, const Vector3i Position, const ArrayType & Relative)
{
for (const auto Offset : Relative)
{
Callback(Position + Offset);
}
-
- InvokeForAdjustedRelatives(Callback, Position, Relatives...);
}
+ inline static Vector3i OffsetYP{ 0, 1, 0 };
+
+ inline static Vector3i OffsetYM{ 0, -1, 0 };
+
inline static std::array<Vector3i, 6> RelativeAdjacents
{
{
@@ -101,14 +86,4 @@ protected:
{ 0, 0, -1 },
}
};
-
-private:
-
- static void UpdateAdjustedRelatives(cChunk &, cChunk &, const Vector3i)
- {
- }
-
- static void InvokeForAdjustedRelatives(SourceCallback, const Vector3i)
- {
- }
};
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h
index 85aa1d743..eb47e2367 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h
@@ -7,14 +7,12 @@
class cRedstoneLampHandler final : public cRedstoneHandler
{
-public:
-
inline static bool IsOn(BLOCKTYPE a_BlockType)
{
return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON);
}
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
return 0;
}
@@ -39,7 +37,7 @@ public:
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_Meta);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h
index 711d1762d..ce42e0163 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h
@@ -8,16 +8,23 @@
-class cRedstoneRepeaterHandler:
- public cRedstoneHandler
+class cRedstoneRepeaterHandler final : public cRedstoneHandler
{
- using Super = cRedstoneHandler;
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
+ {
+ if (!IsOn(a_BlockType))
+ {
+ return 0;
+ }
-public:
+ const auto FrontOffset = cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Chunk.GetMeta(a_Position));
+ const auto FrontPosition = a_Position + FrontOffset;
+ if (a_QueryPosition == FrontPosition)
+ {
+ return 15;
+ }
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
- {
- return ((a_QueryPosition == (a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta))) && IsOn(a_BlockType)) ? 15 : 0;
+ return 0;
}
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
@@ -45,37 +52,36 @@ public:
{
Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
}
+
+ return;
}
- else
+
+ int DelayTicks;
+ bool ShouldPowerOn;
+ std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
+
+ if (DelayTicks != 0)
{
- int DelayTicks;
- bool ShouldPowerOn;
- std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
+ return;
+ }
- if (DelayTicks == 0)
- {
- const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
- a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
- Data.m_MechanismDelays.erase(a_Position);
+ const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
+ a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
+ Data.m_MechanismDelays.erase(a_Position);
- // While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
- // Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
- // FastSetBlock doesn't wake simulators, so manually update ourselves:
- Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData);
+ // While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
+ // Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
+ // FastSetBlock doesn't wake simulators, so manually update ourselves:
+ Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData);
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
- UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta), RelativeAdjacents);
- }
- }
+ UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
}
-private:
-
inline static bool IsOn(BLOCKTYPE a_Block)
{
return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h
index eb5dfc92d..f8e7eb466 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h
@@ -4,6 +4,7 @@
#include <stack>
#include "../RedstoneSimulator.h"
+#include "../../Chunk.h"
@@ -53,7 +54,7 @@ public:
-class cIncrementalRedstoneSimulatorChunkData : public cRedstoneSimulatorChunkData
+class cIncrementalRedstoneSimulatorChunkData final : public cRedstoneSimulatorChunkData
{
public:
@@ -90,6 +91,7 @@ public:
m_CachedPowerLevels.erase(Position);
m_MechanismDelays.erase(Position);
AlwaysTickedPositions.erase(Position);
+ WireStates.erase(Position);
}
PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData)
@@ -105,7 +107,7 @@ public:
}
/** Adjust From-relative coordinates into To-relative coordinates. */
- inline static Vector3i RebaseRelativePosition(cChunk & From, cChunk & To, const Vector3i Position)
+ inline static Vector3i RebaseRelativePosition(const cChunk & From, const cChunk & To, const Vector3i Position)
{
return
{
@@ -115,9 +117,12 @@ public:
};
}
+ /** Temporary, should be chunk data: wire block store, to avoid recomputing states every time. */
+ std::unordered_map<Vector3i, short, VectorHasher<int>> WireStates;
+
std::unordered_set<Vector3i, VectorHasher<int>> AlwaysTickedPositions;
- /** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on */
+ /** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on. */
std::unordered_map<Vector3i, std::pair<int, bool>, VectorHasher<int>> m_MechanismDelays;
private:
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h
index bf9c639b1..b66ce47fd 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h
@@ -11,9 +11,7 @@
class cRedstoneToggleHandler final : public cRedstoneHandler
{
-public:
-
- inline static Vector3i GetPositionAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
+ inline static Vector3i GetOffsetAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
{
switch (a_BlockType)
{
@@ -22,13 +20,13 @@ public:
switch (a_Meta & 0x7)
{
case 0x0:
- case 0x7: return { a_Position + Vector3i(0, 1, 0) };
- case 0x1: return { a_Position + Vector3i(-1, 0, 0) };
- case 0x2: return { a_Position + Vector3i(1, 0, 0) };
- case 0x3: return { a_Position + Vector3i(0, 0, -1) };
- case 0x4: return { a_Position + Vector3i(0, 0, 1) };
+ case 0x7: return { 0, 1, 0 };
+ case 0x1: return { -1, 0, 0 };
+ case 0x2: return { 1, 0, 0 };
+ case 0x3: return { 0, 0, -1 };
+ case 0x4: return { 0, 0, 1 };
case 0x5:
- case 0x6: return { a_Position + Vector3i(0, -1, 0) };
+ case 0x6: return { 0, -1, 0 };
default:
{
ASSERT(!"Unhandled lever metadata!");
@@ -41,12 +39,12 @@ public:
{
switch (a_Meta & 0x7)
{
- case 0x0: return { a_Position + Vector3i(0, 1, 0) };
- case 0x1: return { a_Position + Vector3i(-1, 0, 0) };
- case 0x2: return { a_Position + Vector3i(1, 0, 0) };
- case 0x3: return { a_Position + Vector3i(0, 0, -1) };
- case 0x4: return { a_Position + Vector3i(0, 0, 1) };
- case 0x5: return { a_Position + Vector3i(0, -1, 0) };
+ case 0x0: return { 0, 1, 0 };
+ case 0x1: return { -1, 0, 0 };
+ case 0x2: return { 1, 0, 0 };
+ case 0x3: return { 0, 0, -1 };
+ case 0x4: return { 0, 0, 1 };
+ case 0x5: return { 0, -1, 0 };
default:
{
ASSERT(!"Unhandled button metadata!");
@@ -62,14 +60,19 @@ public:
}
}
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_QueryBlockType);
- if ((GetPositionAttachedTo(a_Position, a_BlockType, a_Meta) == a_QueryPosition) || cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType))
+
+ const auto Meta = a_Chunk.GetMeta(a_Position);
+ const auto QueryOffset = a_QueryPosition - a_Position;
+
+ if (IsLinked && (QueryOffset != GetOffsetAttachedTo(a_Position, a_BlockType, Meta)))
{
- return GetPowerLevel(a_BlockType, a_Meta);
+ return 0;
}
- return 0;
+
+ return GetPowerLevel(a_BlockType, Meta);
}
static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
@@ -92,7 +95,7 @@ public:
// LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h
index 65cf32204..77c889aa9 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h
@@ -9,14 +9,12 @@
class cRedstoneTorchHandler final : public cRedstoneHandler
{
-public:
-
inline static bool IsOn(BLOCKTYPE a_Block)
{
return (a_Block == E_BLOCK_REDSTONE_TORCH_ON);
}
- inline static Vector3i GetOffsetAttachedTo(Vector3i a_Position, NIBBLETYPE a_Meta)
+ inline static Vector3i GetOffsetAttachedTo(const NIBBLETYPE a_Meta)
{
switch (a_Meta)
{
@@ -33,17 +31,20 @@ public:
}
}
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
+ const auto QueryOffset = a_QueryPosition - a_Position;
+
if (
- IsOn(a_BlockType) &&
- (a_QueryPosition != (a_Position + GetOffsetAttachedTo(a_Position, a_Meta))) &&
- (cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) || (cBlockInfo::FullyOccupiesVoxel(a_QueryBlockType) && (a_QueryPosition == (a_Position + OffsetYP))))
+ !IsOn(a_BlockType) ||
+ (QueryOffset == GetOffsetAttachedTo(a_Chunk.GetMeta(a_Position))) ||
+ (IsLinked && (QueryOffset != OffsetYP))
)
{
- return 15;
+ return 0;
}
- return 0;
+
+ return 15;
}
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
@@ -55,40 +56,42 @@ public:
if (DelayInfo == nullptr)
{
- bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
+ const bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
if (ShouldBeOn != IsOn(a_BlockType))
{
Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
}
+
+ return;
}
- else
- {
- int DelayTicks;
- bool ShouldPowerOn;
- std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
- if (DelayTicks != 0)
- {
- return;
- }
+ int DelayTicks;
+ bool ShouldPowerOn;
+ std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
- a_Chunk.SetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
- Data.m_MechanismDelays.erase(a_Position);
+ if (DelayTicks != 0)
+ {
+ return;
+ }
- for (const auto Adjacent : RelativeAdjacents)
+ a_Chunk.FastSetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
+ Data.m_MechanismDelays.erase(a_Position);
+
+ for (const auto Adjacent : RelativeAdjacents)
+ {
+ // Update all adjacents (including linked power positions)
+ // apart from our attachment, which can't possibly need an update:
+ if (Adjacent != GetOffsetAttachedTo(a_Meta))
{
- if (Adjacent != GetOffsetAttachedTo(a_Position, a_Meta))
- {
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + Adjacent);
- }
+ UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Adjacent);
}
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
- Callback(a_Position + GetOffsetAttachedTo(a_Position, a_Meta));
+ Callback(a_Position + GetOffsetAttachedTo(a_Meta));
}
};
diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h
index 5bf4afcd3..2772441bd 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h
@@ -2,6 +2,7 @@
#pragma once
#include "RedstoneHandler.h"
+#include "../../Registries/Blocks.h"
@@ -9,198 +10,318 @@
class cRedstoneWireHandler final : public cRedstoneHandler
{
-public:
+ /** A unified representation of wire direction. */
+ enum class TemporaryDirection
+ {
+ Up,
+ Side
+ };
- inline static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset)
+ /** Adjusts a given wire block so that the direction represented by Offset has state Direction. */
+ inline static void SetDirectionState(const Vector3i Offset, short & Block, TemporaryDirection Direction)
{
- switch (a_Block)
+ Block = DoWithDirectionState(Offset, Block, [Direction](auto, auto & Front, auto)
{
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
+ using FrontState = std::remove_reference_t<decltype(Front)>;
+ switch (Direction)
{
- a_BlockMeta &= E_META_REDSTONE_REPEATER_FACING_MASK;
- if ((a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XP) || (a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XM))
+ case TemporaryDirection::Up:
{
- // Wire connects to repeater if repeater is aligned along X
- // and wire is in front or behind it (#4639)
- return a_Offset.x != 0;
+ Front = FrontState::Up;
+ return;
+ }
+ case TemporaryDirection::Side:
+ {
+ Front = FrontState::Side;
+ return;
}
-
- return a_Offset.z != 0;
}
- case E_BLOCK_ACTIVE_COMPARATOR:
- case E_BLOCK_INACTIVE_COMPARATOR:
- case E_BLOCK_REDSTONE_TORCH_OFF:
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_REDSTONE_WIRE: return true;
- default: return false;
- }
+ });
}
+ /** Invokes Callback with the wire's left, front, and right direction state corresponding to Offset.
+ Returns a new block constructed from the directions that the callback may have modified. */
template <class OffsetCallback>
- static bool ForTerracingConnectionOffsets(cChunk & a_Chunk, const Vector3i a_Position, OffsetCallback Callback)
+ inline static short DoWithDirectionState(const Vector3i Offset, short Block, OffsetCallback Callback)
+ {
+ auto North = Block::RedstoneWire::North(Block);
+ auto South = Block::RedstoneWire::South(Block);
+ auto West = Block::RedstoneWire::West(Block);
+ auto East = Block::RedstoneWire::East(Block);
+
+ if (Offset.x == -1)
+ {
+ Callback(South, West, North);
+ }
+ else if (Offset.x == 1)
+ {
+ Callback(North, East, South);
+ }
+
+ if (Offset.z == -1)
+ {
+ Callback(West, North, East);
+ }
+ else if (Offset.z == 1)
+ {
+ Callback(East, South, West);
+ }
+
+ return Block::RedstoneWire::RedstoneWire(East, North, 0, South, West);
+ }
+
+public:
+
+ /** 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. */
+ void SetWireState(const cChunk & Chunk, const Vector3i Position) const
{
- const auto YPTerraceBlock = a_Chunk.GetBlock(a_Position + OffsetYP);
+ auto Block = Block::RedstoneWire::RedstoneWire();
+ const auto YPTerraceBlock = Chunk.GetBlock(Position + OffsetYP);
const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock);
- for (const auto Adjacent : RelativeLaterals)
+ // Loop through laterals, discovering terracing connections:
+ for (const auto Offset : RelativeLaterals)
{
- // All laterals are counted as terracing, duh
- if (Callback(Adjacent))
+ auto Adjacent = Position + Offset;
+ auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(Adjacent);
+
+ if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
{
- return true;
+ continue;
}
- if (
- BLOCKTYPE YPBlock;
+ BLOCKTYPE LateralBlock;
+ NIBBLETYPE LateralMeta;
+ NeighbourChunk->GetBlockTypeMeta(Adjacent, LateralBlock, LateralMeta);
- // A block above us blocks all YP terracing, so the check is static in the loop
- !IsYPTerracingBlocked &&
- a_Chunk.UnboundedRelGetBlockType(a_Position + Adjacent + OffsetYP, YPBlock) &&
- (YPBlock == E_BLOCK_REDSTONE_WIRE)
- )
+ if (IsDirectlyConnectingMechanism(LateralBlock, LateralMeta, Offset))
{
- if (Callback(Adjacent + OffsetYP))
+ // Any direct connections on a lateral means the wire has side connection in that direction:
+ SetDirectionState(Offset, Block, TemporaryDirection::Side);
+
+ // 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))
{
- return true;
+ auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent)->second;
+ SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side);
}
+
+ continue;
}
if (
- BLOCKTYPE YMTerraceBlock, YMDiagonalBlock;
-
- // IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent)
- a_Chunk.UnboundedRelGetBlockType(a_Position + Adjacent, YMTerraceBlock) &&
- (!cBlockInfo::IsSolid(YMTerraceBlock) || cBlockInfo::IsTransparent(YMTerraceBlock)) &&
-
- a_Chunk.UnboundedRelGetBlockType(a_Position + Adjacent + OffsetYM, YMDiagonalBlock) &&
- (YMDiagonalBlock == E_BLOCK_REDSTONE_WIRE)
+ !IsYPTerracingBlocked && // A block above us blocks all YP terracing, so the check is static in the loop
+ (Adjacent.y < (cChunkDef::Height - 1)) &&
+ (NeighbourChunk->GetBlock(Adjacent + OffsetYP) == E_BLOCK_REDSTONE_WIRE) // Only terrace YP with another wire
)
{
- if (Callback(Adjacent + OffsetYM))
+ SetDirectionState(Offset, Block, TemporaryDirection::Up);
+
+ if (NeighbourChunk != &Chunk)
{
- return true;
+ auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYP)->second;
+ SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side);
}
+
+ continue;
}
- }
- return false;
- }
+ if (
+ // IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent)
+ (!cBlockInfo::IsSolid(LateralBlock) || cBlockInfo::IsTransparent(LateralBlock)) &&
+ (NeighbourChunk->GetBlock(Adjacent + OffsetYM) == E_BLOCK_REDSTONE_WIRE) // Only terrace YM with another wire
+ )
+ {
+ SetDirectionState(Offset, Block, TemporaryDirection::Side);
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
- {
- if (a_QueryPosition == (a_Position + OffsetYP))
- {
- // Wires do not power things above them
- return 0;
+ if (NeighbourChunk != &Chunk)
+ {
+ auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYM)->second;
+ SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Up);
+ }
+ }
}
- if (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)
+ auto & States = DataForChunk(Chunk).WireStates;
+ const auto FindResult = States.find(Position);
+ if (FindResult != States.end())
{
- // For mechanisms, wire of power one will still power them
- // But for wire-to-wire connections, power level decreases by 1
- return (a_Meta != 0) ? --a_Meta : a_Meta;
- }
+ if (Block != FindResult->second)
+ {
+ FindResult->second = Block;
- // Wires always deliver power to the block underneath, and any directly connecting mechanisms
- if (
- NIBBLETYPE QueryMeta;
+ // 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_QueryPosition == (a_Position + OffsetYM)) ||
- (a_Chunk.UnboundedRelGetBlockMeta(a_QueryPosition, QueryMeta) && IsDirectlyConnectingMechanism(a_QueryBlockType, QueryMeta, a_QueryPosition - a_Position))
- )
- {
- return a_Meta;
+ return;
}
- /*
- Okay, we do not directly connect to the wire.
- If there are no DC mechanisms at all, the wire powers all laterals. Great, we fall out the loop.
- If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism.
- The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing towards us.
- If there is more than one DC, no non-DCs are powered.
- */
+ DataForChunk(Chunk).WireStates[Position] = Block;
+ }
- Vector3i PotentialOffset;
- bool FoundOneBorderingMechanism = false;
+private:
- if (
- ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, a_Position, &FoundOneBorderingMechanism, &PotentialOffset](const Vector3i Offset)
+ inline static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset)
+ {
+ switch (a_Block)
+ {
+ case E_BLOCK_REDSTONE_REPEATER_ON:
+ case E_BLOCK_REDSTONE_REPEATER_OFF:
{
- BLOCKTYPE Block;
- NIBBLETYPE Meta;
-
- if (
- !a_Chunk.UnboundedRelGetBlock(Offset + a_Position, Block, Meta) ||
- !IsDirectlyConnectingMechanism(Block, Meta, Offset)
- )
+ a_BlockMeta &= E_META_REDSTONE_REPEATER_FACING_MASK;
+ if ((a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XP) || (a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XM))
{
- return false;
+ // Wire connects to repeater if repeater is aligned along X
+ // and wire is in front or behind it (#4639)
+ return a_Offset.x != 0;
}
- if (FoundOneBorderingMechanism)
- {
- // Case 3
- return true;
- }
+ return a_Offset.z != 0;
+ }
+ case E_BLOCK_ACTIVE_COMPARATOR:
+ case E_BLOCK_INACTIVE_COMPARATOR:
+ case E_BLOCK_BLOCK_OF_REDSTONE:
+ case E_BLOCK_REDSTONE_TORCH_OFF:
+ case E_BLOCK_REDSTONE_TORCH_ON:
+ case E_BLOCK_REDSTONE_WIRE: return true;
+ default: return false;
+ }
+ }
- // Potential case 2
- FoundOneBorderingMechanism = true;
- PotentialOffset = { -Offset.x, 0, -Offset.z };
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
+ {
+ // Starts off as the wire's meta value, modified appropriately and returned
+ auto Power = a_Chunk.GetMeta(a_Position);
+ const auto QueryOffset = a_QueryPosition - a_Position;
- return false;
- })
+ if (
+ (QueryOffset == OffsetYP) || // Wires do not power things above them
+ (IsLinked && (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)) // Nor do they link power other wires
)
{
- // Case 3
return 0;
}
- if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset)))
+ if (QueryOffset == OffsetYM)
{
- // Case 2 fail
- return 0;
+ // Wires always deliver power to the block underneath
+ return Power;
}
- // Case 1
- // Case 2 success
+ const auto & Data = DataForChunk(a_Chunk);
+ const auto Block = Data.WireStates.find(a_Position)->second;
+
+ DoWithDirectionState(QueryOffset, Block, [a_QueryBlockType, &Power](const auto Left, const auto Front, const auto Right)
+ {
+ using LeftState = std::remove_reference_t<decltype(Left)>;
+ using FrontState = std::remove_reference_t<decltype(Front)>;
+ using RightState = std::remove_reference_t<decltype(Right)>;
+
+ // Wires always deliver power to any directly connecting mechanisms:
+ if (Front != FrontState::None)
+ {
+ if ((a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) && (Power != 0))
+ {
+ // For mechanisms, wire of power one will still power them
+ // But for wire-to-wire connections, power level decreases by 1:
+ Power--;
+ }
+
+ return;
+ }
+
+ /*
+ Okay, we do not directly connect to the wire.
+ 1. If there are no DC mechanisms at all, the wire powers all laterals. Great, left and right are both None.
+ 2. If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism.
+ The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing towards us.
+ Check that left and right are both None.
+ 3. If there is more than one DC, no non-DCs are powered. Left, right, cannot both be None.
+ */
+ if ((Left == LeftState::None) && (Right == RightState::None))
+ {
+ // Case 1
+ // Case 2
+ return;
+ }
- return a_Meta;
+ // Case 3
+ Power = 0;
+ });
+
+ return Power;
}
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
{
// LOGD("Evaluating dusty the wire (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, a_PoweringData.PowerLevel);
- if (a_Meta != a_PoweringData.PowerLevel)
+ if (a_Meta == a_PoweringData.PowerLevel)
{
- a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
+ return;
+ }
- // Notify block below us to update:
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + OffsetYM);
+ a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
- // Notify all terracing positions:
- ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, &CurrentlyTicking, a_Position](const Vector3i Offset)
+ // Notify all positions, sans YP, to update:
+ for (const auto Offset : RelativeAdjacents)
+ {
+ if (Offset == OffsetYP)
{
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + Offset);
- return false;
- });
+ continue;
+ }
+
+ UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Offset);
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
- UNUSED(a_Chunk);
UNUSED(a_BlockType);
UNUSED(a_Meta);
Callback(a_Position + OffsetYP);
Callback(a_Position + OffsetYM);
- ForTerracingConnectionOffsets(a_Chunk, a_Position, [&Callback, a_Position](const Vector3i Offset)
+ const auto & Data = DataForChunk(a_Chunk);
+ const auto Block = Data.WireStates.find(a_Position)->second;
+
+ // Figure out, based on our pre-computed block, where we connect to:
+ for (const auto Offset : RelativeLaterals)
{
- Callback(a_Position + Offset);
- return false;
- });
+ const auto Relative = a_Position + Offset;
+ Callback(Relative);
+
+ DoWithDirectionState(Offset, Block, [&a_Chunk, &Callback, Relative](auto, const auto Front, auto)
+ {
+ using FrontState = std::remove_reference_t<decltype(Front)>;
+
+ if (Front == FrontState::Up)
+ {
+ Callback(Relative + OffsetYP);
+ }
+ else if (Front == FrontState::Side)
+ {
+ // Alas, no way to distinguish side lateral and side diagonal
+ // Have to do a manual check to only accept power from YM diagonal if there's a wire there
+
+ const auto YMDiagonalPosition = Relative + OffsetYM;
+ if (
+ BLOCKTYPE Block;
+ cChunkDef::IsValidHeight(YMDiagonalPosition.y) &&
+ a_Chunk.UnboundedRelGetBlockType(YMDiagonalPosition, Block) &&
+ (Block == E_BLOCK_REDSTONE_WIRE)
+ )
+ {
+ Callback(YMDiagonalPosition);
+ }
+ }
+ });
+ }
}
};
diff --git a/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h b/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h
index 0bf2faacd..68727284d 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h
@@ -9,16 +9,14 @@
class cSmallGateHandler final : public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -35,7 +33,7 @@ public:
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h
deleted file mode 100644
index abf8dc63b..000000000
--- a/src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h
+++ /dev/null
@@ -1,62 +0,0 @@
-
-#pragma once
-
-#include "RedstoneHandler.h"
-
-
-
-
-
-class cSolidBlockHandler:
- public cRedstoneHandler
-{
- using Super = cRedstoneHandler;
-
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
- {
- const auto SolidBlock = DataForChunk(a_Chunk).GetCachedPowerData(a_Position);
- return (
- !cIncrementalRedstoneSimulator::IsRedstone(a_QueryBlockType) ||
- (
- (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) &&
- (SolidBlock.PoweringBlock == E_BLOCK_REDSTONE_WIRE)
- )
- ) ? 0 : SolidBlock.PowerLevel;
- }
-
- virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
- {
- UNUSED(a_BlockType);
- UNUSED(a_Meta);
- // LOGD("Evaluating blocky the generic block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
-
- auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
- if ((a_PoweringData != PreviousPower) || (a_PoweringData.PoweringBlock != PreviousPower.PoweringBlock))
- {
- UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
- }
- }
-
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
- {
- UNUSED(a_Chunk);
- UNUSED(a_BlockType);
- UNUSED(a_Meta);
-
- /* TODO: is this more performant?
- cVector3iArray Adjacents;
- for (const auto Offset : GetRelativeAdjacents())
- {
- auto Position = Offset + a_Position;
- auto Block = m_World.GetBlock(Position);
- if ((Block == E_BLOCK_REDSTONE_REPEATER_ON) || (Block == E_BLOCK_REDSTONE_WIRE) || (Block == E_BLOCK_TRIPWIRE_HOOK))
- {
- Adjacents.emplace_back(Position);
- }
- }
- */
- InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
- }
-};
diff --git a/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h
index 4b048e5c2..2396660a8 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h
@@ -9,16 +9,14 @@
class cTNTHandler final : public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return 0;
}
@@ -32,7 +30,7 @@ public:
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h
index e3deea5e9..45014d637 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h
@@ -8,19 +8,14 @@
-class cTrappedChestHandler:
- public cRedstoneHandler
+class cTrappedChestHandler final : public cRedstoneHandler
{
- using Super = cRedstoneHandler;
-
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_BlockType);
- UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
+ UNUSED(IsLinked);
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
}
@@ -49,12 +44,11 @@ public:
if (Power != PreviousPower.PowerLevel)
{
- UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, OffsetYM);
- UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals);
+ UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_Position);
diff --git a/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h
index 7c00c4e2f..6ae3c2e3c 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h
+++ b/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h
@@ -10,18 +10,16 @@
class cTripwireHookHandler final : public cRedstoneHandler
{
-public:
-
- virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
+ virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
{
UNUSED(a_BlockType);
UNUSED(a_QueryBlockType);
UNUSED(a_QueryPosition);
- return (GetPowerLevel(a_Chunk, a_Position, a_Meta) == 15) ? 15 : 0;
+ return (GetPowerLevel(a_Chunk, a_Position, a_Chunk.GetMeta(a_Position)) == 15) ? 15 : 0;
}
- static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta)
+ static unsigned char GetPowerLevel(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta)
{
bool FoundActivated = false;
const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta);
@@ -104,7 +102,7 @@ public:
}
}
- virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
+ virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
{
UNUSED(a_Chunk);
UNUSED(a_BlockType);
diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h
index 6d60b91a2..0ef0dd6af 100644
--- a/src/Simulator/RedstoneSimulator.h
+++ b/src/Simulator/RedstoneSimulator.h
@@ -10,10 +10,11 @@
class cRedstoneSimulatorChunkData
{
public:
- virtual ~cRedstoneSimulatorChunkData() = 0;
-};
-inline cRedstoneSimulatorChunkData::~cRedstoneSimulatorChunkData() {}
+ virtual ~cRedstoneSimulatorChunkData()
+ {
+ }
+};
@@ -26,11 +27,7 @@ class cRedstoneSimulator:
public:
- cRedstoneSimulator(cWorld & a_World):
- Super(a_World)
- {
- }
+ using Super::cSimulator;
virtual cRedstoneSimulatorChunkData * CreateChunkData() = 0;
-
};
diff --git a/src/Simulator/Simulator.cpp b/src/Simulator/Simulator.cpp
index e55b77f0f..6b39b81d5 100644
--- a/src/Simulator/Simulator.cpp
+++ b/src/Simulator/Simulator.cpp
@@ -10,6 +10,90 @@
+std::array<Vector3i, 5> cSimulator::GetLinkedOffsets(const Vector3i Offset)
+{
+ if (Offset.x == -1)
+ {
+ return
+ {
+ {
+ { -2, 0, 0 },
+ { -1, -1, 0 },
+ { -1, 1, 0 },
+ { -1, 0, -1 },
+ { -1, 0, 1 }
+ }
+ };
+ }
+ else if (Offset.x == 1)
+ {
+ return
+ {
+ {
+ { 2, 0, 0 },
+ { 1, -1, 0 },
+ { 1, 1, 0 },
+ { 1, 0, -1 },
+ { 1, 0, 1 }
+ }
+ };
+ }
+ else if (Offset.y == -1)
+ {
+ return
+ {
+ {
+ { 0, -2, 0 },
+ { -1, -1, 0 },
+ { 1, -1, 0 },
+ { 0, -1, -1 },
+ { 0, -1, 1 }
+ }
+ };
+ }
+ else if (Offset.y == 1)
+ {
+ return
+ {
+ {
+ { 0, 2, 0 },
+ { -1, 1, 0 },
+ { 1, 1, 0 },
+ { 0, 1, -1 },
+ { 0, 1, 1 }
+ }
+ };
+ }
+ else if (Offset.z == -1)
+ {
+ return
+ {
+ {
+ { 0, 0, -2 },
+ { -1, 0, -1 },
+ { 1, 0, -1 },
+ { 0, -1, -1 },
+ { 0, 1, -1 }
+ }
+ };
+ }
+
+ return
+ {
+ {
+ { 0, 0, 2 },
+ { -1, 0, 1 },
+ { 1, 0, 1 },
+ { 0, -1, 1 },
+ { 0, 1, 1 }
+ }
+ };
+}
+
+
+
+
+
void cSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
{
ASSERT(a_Chunk.IsValid());
diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h
index e18465bee..32a36213b 100644
--- a/src/Simulator/Simulator.h
+++ b/src/Simulator/Simulator.h
@@ -27,7 +27,7 @@ public:
virtual ~cSimulator() {}
- // Contains our direct adjacents
+ /** Contains offsets for direct adjacents of any position. */
static constexpr std::array<Vector3i, 6> AdjacentOffsets
{
{
@@ -40,6 +40,9 @@ public:
}
};
+ /** For a given offset from a position, return the offsets that represent the adjacents of the newly offset position, excluding the old position. */
+ static std::array<Vector3i, 5> GetLinkedOffsets(Vector3i Offset);
+
protected:
friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up