summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp142
1 files changed, 84 insertions, 58 deletions
diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
index 109ee4adc..2eb515604 100644
--- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp
@@ -7,7 +7,6 @@
#include "CommandBlockHandler.h"
#include "DoorHandler.h"
-#include "RedstoneHandler.h"
#include "RedstoneTorchHandler.h"
#include "RedstoneWireHandler.h"
#include "RedstoneRepeaterHandler.h"
@@ -31,9 +30,10 @@
+
const cRedstoneHandler * cIncrementalRedstoneSimulator::GetComponentHandler(BLOCKTYPE a_BlockType)
{
- struct sComponents:
+ struct sComponents :
public std::array<std::unique_ptr<cRedstoneHandler>, 256>
{
sComponents()
@@ -128,76 +128,98 @@ std::unique_ptr<cRedstoneHandler> cIncrementalRedstoneSimulator::CreateComponent
-void cIncrementalRedstoneSimulator::Simulate(float a_dt)
+void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
- for (auto & DelayInfo : m_Data.m_MechanismDelays)
+ auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData());
+ for (auto & DelayInfo : ChunkData.m_MechanismDelays)
{
if ((--DelayInfo.second.first) == 0)
{
- m_Data.GetActiveBlocks().emplace_back(DelayInfo.first);
+ ChunkData.WakeUp(DelayInfo.first);
}
}
// Build our work queue
- cVector3iArray WorkQueue;
- std::swap(WorkQueue, m_Data.GetActiveBlocks());
+ auto & WorkQueue = ChunkData.GetActiveBlocks();
// Process the work queue
while (!WorkQueue.empty())
{
// Grab the first element and remove it from the list
- Vector3i CurrentLocation = WorkQueue.back();
- WorkQueue.pop_back();
+ Vector3i CurrentLocation = WorkQueue.top();
+ WorkQueue.pop();
- BLOCKTYPE CurrentBlock;
- NIBBLETYPE CurrentMeta;
- if (!m_World.GetBlockTypeMeta(CurrentLocation.x, CurrentLocation.y, CurrentLocation.z, CurrentBlock, CurrentMeta))
+ const auto NeighbourChunk = a_Chunk->GetRelNeighborChunkAdjustCoords(CurrentLocation);
+ if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
{
- continue;
+ return;
}
- auto CurrentHandler = GetComponentHandler(CurrentBlock);
- if (CurrentHandler == nullptr) // Block at CurrentPosition doesn't have a corresponding redstone handler
- {
- // Clean up cached PowerData for CurrentPosition
- GetChunkData()->ErasePowerData(CurrentLocation);
- continue;
- }
+ ProcessWorkItem(*NeighbourChunk, *a_Chunk, CurrentLocation);
+ }
+
+ for (const auto Position : ChunkData.AlwaysTickedPositions)
+ {
+ ChunkData.WakeUp(Position);
+ }
+}
+
- cRedstoneHandler::PoweringData Power;
- for (const auto & Location : CurrentHandler->GetValidSourcePositions(m_World, CurrentLocation, CurrentBlock, CurrentMeta))
- {
- if (!cChunk::IsValidHeight(Location.y))
- {
- continue;
- }
- BLOCKTYPE PotentialBlock;
- NIBBLETYPE PotentialMeta;
- if (!m_World.GetBlockTypeMeta(Location.x, Location.y, Location.z, PotentialBlock, PotentialMeta))
- {
- continue;
- }
- auto PotentialSourceHandler = GetComponentHandler(PotentialBlock);
- if (PotentialSourceHandler == nullptr)
- {
- continue;
- }
- decltype(Power) PotentialPower(PotentialBlock, PotentialSourceHandler->GetPowerDeliveredToPosition(m_World, Location, PotentialBlock, PotentialMeta, CurrentLocation, CurrentBlock));
- Power = std::max(Power, PotentialPower);
+void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position)
+{
+ auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(Chunk.GetRedstoneSimulatorData());
+
+ BLOCKTYPE CurrentBlock;
+ NIBBLETYPE CurrentMeta;
+ Chunk.GetBlockTypeMeta(Position, CurrentBlock, CurrentMeta);
+
+ auto CurrentHandler = GetComponentHandler(CurrentBlock);
+ if (CurrentHandler == nullptr) // Block at CurrentPosition doesn't have a corresponding redstone handler
+ {
+ // Clean up cached PowerData for CurrentPosition
+ ChunkData.ErasePowerData(Position);
+ return;
+ }
+
+ PoweringData Power;
+ CurrentHandler->ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, [&Chunk, Position, CurrentBlock, &Power](Vector3i Location)
+ {
+ if (!cChunk::IsValidHeight(Location.y))
+ {
+ return;
}
- // Inform the handler to update
- cVector3iArray Updates = CurrentHandler->Update(m_World, CurrentLocation, CurrentBlock, CurrentMeta, Power);
- WorkQueue.insert(WorkQueue.end(), Updates.begin(), Updates.end());
+ const auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(Location);
+ if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
+ {
+ return;
+ }
- if (IsAlwaysTicked(CurrentBlock))
+ BLOCKTYPE PotentialBlock;
+ NIBBLETYPE PotentialMeta;
+ NeighbourChunk->GetBlockTypeMeta(Location, PotentialBlock, PotentialMeta);
+
+ auto PotentialSourceHandler = GetComponentHandler(PotentialBlock);
+ if (PotentialSourceHandler == nullptr)
{
- m_Data.GetActiveBlocks().emplace_back(CurrentLocation);
+ return;
}
- }
+
+ const PoweringData PotentialPower(
+ PotentialBlock,
+ PotentialSourceHandler->GetPowerDeliveredToPosition(
+ *NeighbourChunk, Location, PotentialBlock, PotentialMeta,
+ cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, Position), CurrentBlock
+ )
+ );
+ Power = std::max(Power, PotentialPower);
+ });
+
+ // Inform the handler to update
+ CurrentHandler->Update(Chunk, TickingSource, Position, CurrentBlock, CurrentMeta, Power);
}
@@ -206,27 +228,31 @@ void cIncrementalRedstoneSimulator::Simulate(float a_dt)
void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
{
- // Can't inspect block, so queue update anyway
- if (a_Chunk == nullptr)
+ // Can't inspect block, ignore:
+ if ((a_Chunk == nullptr) || (!a_Chunk->IsValid()))
{
- m_Data.WakeUp(a_Block);
return;
}
- const auto RelPos = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
- const auto CurBlock = a_Chunk->GetBlock(RelPos);
+ auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData());
+ const auto Relative = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
+ const auto CurrentBlock = a_Chunk->GetBlock(Relative);
// Always update redstone devices
- if (IsRedstone(CurBlock))
+ if (IsRedstone(CurrentBlock))
{
- m_Data.WakeUp(a_Block);
+ if (IsAlwaysTicked(CurrentBlock))
+ {
+ ChunkData.AlwaysTickedPositions.emplace(Relative);
+ }
+ ChunkData.WakeUp(Relative);
return;
}
// Never update blocks without a handler
- if (GetComponentHandler(CurBlock) == nullptr)
+ if (GetComponentHandler(CurrentBlock) == nullptr)
{
- GetChunkData()->ErasePowerData(a_Block);
+ ChunkData.ErasePowerData(Relative);
return;
}
@@ -235,14 +261,14 @@ void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
{
for (int y = -1; y < 2; ++y)
{
- if (!cChunkDef::IsValidHeight(RelPos.y + y))
+ if (!cChunkDef::IsValidHeight(Relative.y + y))
{
continue;
}
for (int z = -1; z < 2; ++z)
{
- auto CheckPos = RelPos + Vector3i{x, y, z};
+ auto CheckPos = Relative + Vector3i{x, y, z};
BLOCKTYPE Block;
NIBBLETYPE Meta;
@@ -252,7 +278,7 @@ void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
IsRedstone(Block)
)
{
- m_Data.WakeUp(a_Block);
+ ChunkData.WakeUp(Relative);
return;
}
}