summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp')
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp113
1 files changed, 113 insertions, 0 deletions
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;
+}