From 4e5ab02a589582e2fa908909e3ee30360dd08be5 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 26 Jul 2020 14:15:00 +0100 Subject: [PATCH] Use SimulateChunk in redstone simulator + Improved performance, reduces bottleneck in chunkmap lookup * Stop allocating and throwing away lots of small vectors in Update/GetValidSourcePositions return values - Remove unused GetPowerLevel virtual --- src/Blocks/BlockComparator.h | 19 +- .../CommandBlockHandler.h | 42 ++--- .../DoorHandler.h | 54 ++---- .../DropSpenserHandler.h | 49 ++---- .../HopperHandler.h | 46 ++--- .../IncrementalRedstoneSimulator.cpp | 158 ++++++++++------- .../IncrementalRedstoneSimulator.h | 19 +- .../NoteBlockHandler.h | 44 ++--- .../ObserverHandler.h | 44 ++--- .../PistonHandler.h | 54 +++--- .../PoweredRailHandler.h | 42 ++--- .../PressurePlateHandler.h | 132 +++++++------- .../RedstoneBlockHandler.h | 27 +-- .../RedstoneComparatorHandler.h | 142 ++++++++------- .../RedstoneHandler.h | 139 +++++++-------- .../RedstoneLampHandler.h | 23 +-- .../RedstoneRepeaterHandler.h | 59 +++---- .../RedstoneSimulatorChunkData.h | 105 +++++++++--- .../RedstoneToggleHandler.h | 23 +-- .../RedstoneTorchHandler.h | 45 +++-- .../RedstoneWireHandler.h | 162 +++++++++++------- .../SmallGateHandler.h | 39 ++--- .../SolidBlockHandler.h | 27 ++- .../IncrementalRedstoneSimulator/TNTHandler.h | 31 +--- .../TrappedChestHandler.h | 35 ++-- .../TripwireHookHandler.h | 70 ++++---- src/Simulator/NoopRedstoneSimulator.h | 2 +- 27 files changed, 785 insertions(+), 847 deletions(-) diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h index a2f2d430d..ba939b41f 100644 --- a/src/Blocks/BlockComparator.h +++ b/src/Blocks/BlockComparator.h @@ -34,10 +34,13 @@ public: const Vector3i a_CursorPos ) override { + const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); + // Toggle the 3rd bit (addition / subtraction): - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); - Meta ^= 0x04; - a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta); + a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta ^ 0x04); + + // Update simulators: + a_WorldInterface.WakeUpSimulators(a_BlockPos); return true; } @@ -56,6 +59,7 @@ public: UNUSED(a_ChunkInterface); UNUSED(a_BlockFace); + a_WorldInterface.WakeUpSimulators(a_BlockPos); a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } @@ -120,15 +124,6 @@ public: - inline static bool IsOn(NIBBLETYPE a_Meta) - { - return ((a_Meta & 0x8) == 0x8); - } - - - - - inline static Vector3i GetSideCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta, bool a_bInverse) { if (!a_bInverse) diff --git a/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h index 6bdd580a9..31a34236c 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h @@ -8,16 +8,13 @@ -class cCommandBlockHandler: - public cRedstoneHandler +class cCommandBlockHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -26,40 +23,29 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto Previous = static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData); + auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData); if ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0)) { // If we're already powered or received an update of no power, don't activate - return {}; + return; } - a_World.DoWithCommandBlockAt(a_Position.x, a_Position.y, a_Position.z, [](cCommandBlockEntity & a_CommandBlock) - { - a_CommandBlock.Activate(); - return false; - } - ); - return {}; + a_Chunk.DoWithCommandBlockAt(a_Position, [](cCommandBlockEntity & a_CommandBlock) + { + a_CommandBlock.Activate(); + return false; + }); } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h index a22a6ff50..c91886f4e 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h @@ -8,16 +8,13 @@ -class cDoorHandler: - public cRedstoneHandler +class cDoorHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -26,46 +23,27 @@ public: return 0; } - - - - - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } - - - - - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - if (a_PoweringData != static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData)) - { - cChunkInterface ChunkInterface(a_World.GetChunkMap()); - cBlockDoorHandler::SetOpen(ChunkInterface, a_Position, (a_PoweringData.PowerLevel != 0)); - a_World.BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, a_Position, 0); - } + cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap()); + const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0; + const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); + const bool IsOpen = cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition); - return {}; + if (ShouldBeOpen != IsOpen) + { + cBlockDoorHandler::SetOpen(ChunkInterface, AbsolutePosition, ShouldBeOpen); + a_Chunk.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, AbsolutePosition, 0); + } } - - - - - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h index 131d2eb6c..cee8133d8 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h @@ -8,17 +8,15 @@ -class cDropSpenserHandler: - public cRedstoneHandler +class cDropSpenserHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: inline static bool IsActivated(NIBBLETYPE a_Meta) { return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0; } + inline static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn) { if (IsOn) @@ -31,9 +29,9 @@ public: } } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -42,45 +40,34 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating spencer the dropspenser (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - bool IsPoweredNow = (a_PoweringData.PowerLevel > 0); - bool WasPoweredPreviously = IsActivated(a_Meta); + + const bool IsPoweredNow = (a_PoweringData.PowerLevel > 0); + const bool WasPoweredPreviously = IsActivated(a_Meta); + if (IsPoweredNow && !WasPoweredPreviously) { - a_World.DoWithDropSpenserAt(a_Position.x, a_Position.y, a_Position.z, [](cDropSpenserEntity & a_DropSpenser) - { - a_DropSpenser.Activate(); - return false; - } - ); + a_Chunk.DoWithDropSpenserAt(a_Position, [](cDropSpenserEntity & a_DropSpenser) + { + a_DropSpenser.Activate(); + return false; + }); } // Update the internal dropspenser state if necessary if (IsPoweredNow != WasPoweredPreviously) { - a_World.SetBlockMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow)); + a_Chunk.SetMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow)); } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h b/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h index 32b615ffa..2f2e5b129 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h @@ -8,16 +8,13 @@ -class cHopperHandler: - public cRedstoneHandler +class cHopperHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -26,39 +23,28 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } + // LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override - { - // LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - - auto Previous = static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData); - if (Previous.PowerLevel != a_PoweringData.PowerLevel) + auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData); + if (Previous.PowerLevel == a_PoweringData.PowerLevel) { - return {}; + return; } - a_World.DoWithHopperAt(a_Position.x, a_Position.y, a_Position.z, [a_PoweringData](cHopperEntity & a_Hopper) - { - a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0); - return false; - } - ); - return {}; + a_Chunk.DoWithHopperAt(a_Position, [a_PoweringData](cHopperEntity & a_Hopper) + { + a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0); + return false; + }); } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; 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, 256> { sComponents() @@ -128,76 +128,98 @@ std::unique_ptr 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(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; - } - - 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); - } - - // Inform the handler to update - cVector3iArray Updates = CurrentHandler->Update(m_World, CurrentLocation, CurrentBlock, CurrentMeta, Power); - WorkQueue.insert(WorkQueue.end(), Updates.begin(), Updates.end()); - - if (IsAlwaysTicked(CurrentBlock)) - { - m_Data.GetActiveBlocks().emplace_back(CurrentLocation); - } + ProcessWorkItem(*NeighbourChunk, *a_Chunk, CurrentLocation); } + + for (const auto Position : ChunkData.AlwaysTickedPositions) + { + ChunkData.WakeUp(Position); + } +} + + + + + +void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position) +{ + auto & ChunkData = *static_cast(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; + } + + 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); + }); + + // 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(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; } } diff --git a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h index 8213eddae..3523463bd 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h @@ -2,26 +2,29 @@ #pragma once #include "../RedstoneSimulator.h" +#include "RedstoneHandler.h" #include "RedstoneSimulatorChunkData.h" -class cIncrementalRedstoneSimulator: +class cIncrementalRedstoneSimulator final : public cRedstoneSimulator { using Super = cRedstoneSimulator; public: - cIncrementalRedstoneSimulator(cWorld & a_World): + cIncrementalRedstoneSimulator(cWorld & a_World) : Super(a_World) { } - virtual void Simulate(float a_dt) override; - virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override {} + virtual void Simulate(float Dt) override {}; + virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override; + + void ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position); virtual cIncrementalRedstoneSimulatorChunkData * CreateChunkData() override { @@ -36,8 +39,7 @@ public: virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override; /** 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 - */ + Used by torches to determine if they will power a block */ inline static bool IsMechanism(BLOCKTYPE Block) { switch (Block) @@ -158,14 +160,9 @@ public: } } - cIncrementalRedstoneSimulatorChunkData * GetChunkData() { return &m_Data; } - static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType); private: static std::unique_ptr CreateComponent(BLOCKTYPE a_BlockType); - - // oh yea its crazy time - cIncrementalRedstoneSimulatorChunkData m_Data; } ; diff --git a/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h index f6dfc7c97..7d3ec2f30 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h @@ -8,17 +8,13 @@ -class cNoteBlockHandler: - public cRedstoneHandler +class cNoteBlockHandler: public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -27,41 +23,29 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating sparky the magical note block (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, a_PoweringData.PowerLevel); - auto Previous = static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData); + auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData); if ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0)) { // If we're already powered or received an update of no power, don't make a sound - return {}; + return; } - a_World.DoWithNoteBlockAt(a_Position.x, a_Position.y, a_Position.z, [](cNoteEntity & a_NoteBlock) - { - a_NoteBlock.MakeSound(); - return false; - } - ); - - return {}; + a_Chunk.DoWithNoteBlockAt(a_Position, [](cNoteEntity & a_NoteBlock) + { + a_NoteBlock.MakeSound(); + return false; + }); } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h b/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h index b4af66aff..a3c055844 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h @@ -8,7 +8,7 @@ -class cObserverHandler : public cRedstoneHandler +class cObserverHandler final : public cRedstoneHandler { public: @@ -17,24 +17,24 @@ public: return (a_Meta & 0x8) == 0x8; } - static bool ShouldPowerOn(cWorld & a_World, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData * a_Data) + static bool ShouldPowerOn(cChunk & Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData & a_Data) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - if (!a_World.GetBlockTypeMeta(a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), BlockType, BlockMeta)) + if (!Chunk.UnboundedRelGetBlock(a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), BlockType, BlockMeta)) { return false; } // Cache the last seen block type and meta in the power data for this position auto Observed = PoweringData(BlockType, BlockMeta); - auto Previous = a_Data->ExchangeUpdateOncePowerData(a_Position, Observed); + auto Previous = a_Data.ExchangeUpdateOncePowerData(a_Position, Observed); // Determine if to signal an update based on the block previously observed changed return (Previous.PoweringBlock != Observed.PoweringBlock) || (Previous.PowerLevel != Observed.PowerLevel); } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + 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 (IsOn(a_Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta)))) { @@ -44,30 +44,25 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - return IsOn(a_BlockType) ? 15 : 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating Lenny the observer (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); - auto Data = static_cast(a_World.GetRedstoneSimulator())->GetChunkData(); - auto DelayInfo = Data->GetMechanismDelayInfo(a_Position); + auto & Data = DataForChunk(a_Chunk); + auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); if (DelayInfo == nullptr) { - if (!ShouldPowerOn(a_World, a_Position, a_Meta, Data)) + if (!ShouldPowerOn(a_Chunk, a_Position, a_Meta, Data)) { - return {}; + return; } // From rest, we've determined there was a block update // Schedule power-on 1 tick in the future - Data->m_MechanismDelays[a_Position] = std::make_pair(1, true); + Data.m_MechanismDelays[a_Position] = std::make_pair(1, true); - return {}; + return; } int DelayTicks; @@ -76,31 +71,30 @@ public: if (DelayTicks != 0) { - return {}; + return; } if (ShouldPowerOn) { // Remain on for 1 tick before resetting *DelayInfo = std::make_pair(1, false); - a_World.SetBlockMeta(a_Position, a_Meta | 0x8); + a_Chunk.SetMeta(a_Position, a_Meta | 0x8); } else { // We've reset. Erase delay data in preparation for detecting further updates - Data->m_MechanismDelays.erase(a_Position); - a_World.SetBlockMeta(a_Position, a_Meta & ~0x8); + Data.m_MechanismDelays.erase(a_Position); + a_Chunk.SetMeta(a_Position, a_Meta & ~0x8); } - return { a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta) }; + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta)); } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_BlockType); - return {}; } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h index 0929951d5..b3860a778 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h @@ -8,16 +8,13 @@ -class cPistonHandler: - public cRedstoneHandler +class cPistonHandler final: public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -26,52 +23,45 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating pisty the piston (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - bool ShouldBeExtended = (a_PoweringData.PowerLevel != 0); + const bool ShouldBeExtended = a_PoweringData.PowerLevel != 0; if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta)) { - return {}; + return; } + a_Position = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); + if (ShouldBeExtended) { - cBlockPistonHandler::ExtendPiston(a_Position, a_World); + cBlockPistonHandler::ExtendPiston(a_Position, *a_Chunk.GetWorld()); } else { - cBlockPistonHandler::RetractPiston(a_Position, a_World); + cBlockPistonHandler::RetractPiston(a_Position, *a_Chunk.GetWorld()); } // It is necessary to delay after a signal to prevent an infinite loop (#3168) - // However, that is present as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp - - return {}; + // However, this delay is already present: as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); - auto PositionsOffset = GetRelativeAdjacents(); - auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); - int OffsetX = 0, OffsetY = 0, OffsetZ = 0; + const auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); + const auto FrontOffset = AddFaceDirection(Vector3i(), Face); - AddFaceDirection(OffsetX, OffsetY, OffsetZ, Face); - PositionsOffset.erase(std::remove(PositionsOffset.begin(), PositionsOffset.end(), Vector3i(OffsetX, OffsetY, OffsetZ)), PositionsOffset.end()); - - return GetAdjustedRelatives(a_Position, PositionsOffset); + for (const auto Offset : RelativeAdjacents) + { + if (Offset != FrontOffset) + { + Callback(a_Position + Offset); + } + } } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h index d1d44a270..38fbf8d98 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h @@ -7,11 +7,8 @@ -class cPoweredRailHandler: - public cRedstoneHandler +class cPoweredRailHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) // Not in cBlockRailHandler since specific to powered rails @@ -32,27 +29,20 @@ public: } } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { UNUSED(a_QueryBlockType); auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta); if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition)) { - auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); + auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel; return (Power <= 7) ? 0 : --Power; } return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_BlockType); - UNUSED(a_Meta); - return static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTickingChunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating tracky the rail (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); @@ -66,33 +56,37 @@ public: SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType); } */ - return {}; + return; } case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_POWERED_RAIL: { auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta); - if (a_PoweringData != static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData)) + if (a_PoweringData != DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData)) { - a_World.SetBlockMeta(a_Position, (a_PoweringData.PowerLevel == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08)); - return cVector3iArray{ { Offset + a_Position }, { -Offset + a_Position } }; + a_Chunk.SetMeta(a_Position, (a_PoweringData.PowerLevel == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08)); + + UpdateAdjustedRelatives(a_Chunk, CurrentlyTickingChunk, a_Position + Offset); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTickingChunk, a_Position + -Offset); } - return {}; + return; } default: { ASSERT(!"Unhandled type of rail in passed to rail handler!"); - return {}; } } } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); - UNUSED(a_BlockType); + UNUSED(a_Chunk); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + + if ((a_BlockType == E_BLOCK_POWERED_RAIL) || (a_BlockType == E_BLOCK_ACTIVATOR_RAIL)) + { + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); + } } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h index 9f490b458..c2791e45c 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h @@ -9,47 +9,42 @@ -class cPressurePlateHandler: - public cRedstoneHandler +class cPressurePlateHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); - return static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel; + return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + static unsigned char GetPowerLevel(cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType) { - UNUSED(a_Meta); - - int NumberOfEntities = 0; + unsigned NumberOfEntities = 0; bool FoundPlayer = false; - a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + a_Position, 0.5, 0.5), [&](cEntity & a_Entity) - { - if (a_Entity.IsPlayer()) - { - FoundPlayer = true; - } - if (a_Entity.IsPickup()) - { - NumberOfEntities += static_cast(a_Entity).GetItem().m_ItemCount; - return false; - } - NumberOfEntities++; + Chunk.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [&](cEntity & Entity) + { + if (Entity.IsPlayer()) + { + FoundPlayer = true; + } + + if (Entity.IsPickup()) + { + NumberOfEntities += static_cast(Entity).GetItem().m_ItemCount; return false; } - ); + NumberOfEntities++; + return false; + }); - switch (a_BlockType) + switch (BlockType) { case E_BLOCK_STONE_PRESSURE_PLATE: { @@ -75,18 +70,22 @@ public: } } - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + static void UpdatePlate(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position) + { + UpdateAdjustedRelatives(Chunk, CurrentlyTicking, Position, RelativeLaterals); + UpdateAdjustedRelatives(Chunk, CurrentlyTicking, Position + OffsetYM); + } + + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { - UNUSED(a_PoweringData.PowerLevel); // LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto ChunkData = static_cast(a_World.GetRedstoneSimulator())->GetChunkData(); + auto & ChunkData = DataForChunk(a_Chunk); - const auto PreviousPower = ChunkData->GetCachedPowerData(a_Position); - auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); // Get the current power of the platey - - const auto PlateUpdates = GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeLaterals(), cVector3iArray{ OffsetYM() })); - auto DelayInfo = ChunkData->GetMechanismDelayInfo(a_Position); + const auto PreviousPower = ChunkData.GetCachedPowerData(a_Position); + const auto Absolute = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); + const auto Power = GetPowerLevel(a_Chunk, Absolute, a_BlockType); // Get the current power of the platey + const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position); // Resting state? if (DelayInfo == nullptr) @@ -94,22 +93,21 @@ public: if (Power == 0) { // Nothing happened, back to rest - return {}; + return; } // From rest, a player stepped on us // Schedule a minimum 0.5 second delay before even thinking about releasing - ChunkData->m_MechanismDelays[a_Position] = std::make_pair(5, true); + ChunkData.m_MechanismDelays[a_Position] = std::make_pair(5, true); - auto soundToPlay = GetClickOnSound(a_BlockType); - a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.6f); + a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f); // Update power - ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); // Immediately depress plate - a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED); - return PlateUpdates; + a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED); + return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position); } // Not a resting state @@ -124,7 +122,7 @@ public: // Nothing changes, if there is nothing on it anymore, because the state is locked. if (Power == 0) { - return {}; + return; } // Yes. Are we waiting to release, and found that the player stepped on it again? @@ -138,11 +136,11 @@ public: if (Power != PreviousPower.PowerLevel) { // Yes. Update power - ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); - return PlateUpdates; + ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position); } - return {}; + return; } // Not waiting for anything. Has the initial delay elapsed? @@ -153,54 +151,51 @@ public: { // Yes. Go into subsequent release delay, for a further 0.5 seconds *DelayInfo = std::make_pair(5, false); - return {}; + return; } // Did the power level change and is still above zero? if (Power != PreviousPower.PowerLevel) { // Yes. Update power - ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); - return PlateUpdates; + ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position); } // Yes, but player's still on the plate, do nothing - return {}; + return; } // Just got out of the subsequent release phase, reset everything and raise the plate - ChunkData->m_MechanismDelays.erase(a_Position); + ChunkData.m_MechanismDelays.erase(a_Position); - auto soundToPlay = GetClickOffSound(a_BlockType); - a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.5f); - ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); + a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f); + ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); - a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_RAISED); - return PlateUpdates; + a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED); + return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position); } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); - return {}; + UNUSED(Callback); } private: - static AString GetClickOnSound(BLOCKTYPE a_BlockType) + + static const char * GetClickOnSound(BLOCKTYPE a_BlockType) { // manage on-sound switch (a_BlockType) { - case E_BLOCK_STONE_PRESSURE_PLATE: - return "block.stone_pressureplate.click_on"; - case E_BLOCK_WOODEN_PRESSURE_PLATE: - return "block.wood_pressureplate.click_on"; + case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_on"; + case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_on"; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: - return "block.metal_pressureplate.click_on"; + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_on"; default: { ASSERT(!"No on sound for this one!"); @@ -209,18 +204,15 @@ private: } } - static AString GetClickOffSound(BLOCKTYPE a_BlockType) + static const char * GetClickOffSound(BLOCKTYPE a_BlockType) { // manage off-sound switch (a_BlockType) { - case E_BLOCK_STONE_PRESSURE_PLATE: - return "block.stone_pressureplate.click_off"; - case E_BLOCK_WOODEN_PRESSURE_PLATE: - return "block.wood_pressureplate.click_off"; + case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_off"; + case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_off"; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: - case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: - return "block.metal_pressureplate.click_off"; + case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_off"; default: { ASSERT(!"No off sound for this one!"); diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h index 98d373002..150723944 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h @@ -7,16 +7,13 @@ -class cRedstoneBlockHandler: - public cRedstoneHandler +class cRedstoneBlockHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -24,27 +21,17 @@ public: return cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) ? 15 : 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 15; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating crimson the redstone block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); - return {}; + UNUSED(Callback); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h index 3c5dae98f..5827c806b 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h @@ -8,14 +8,11 @@ -class cRedstoneComparatorHandler: - public cRedstoneHandler +class cRedstoneComparatorHandler : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - unsigned char GetFrontPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel) const + static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel) { if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta)) { @@ -29,107 +26,120 @@ public: } } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); - auto ChunkData = static_cast(a_World.GetRedstoneSimulator())->GetChunkData(); return ( (cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) == a_QueryPosition) ? - ChunkData->GetCachedPowerData(a_Position).PowerLevel : 0 + DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel : 0 ); } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta) { - UNUSED(a_Position); - UNUSED(a_BlockType); - UInt8 SignalStrength = 0; - auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(a_Position, a_Meta & 0x3); - a_World.DoWithBlockEntityAt(RearCoordinate.x, RearCoordinate.y, RearCoordinate.z, [&](cBlockEntity & a_BlockEntity) - { - // Skip BlockEntities that don't have slots - auto BlockEntityWithItems = dynamic_cast(&a_BlockEntity); - if (BlockEntityWithItems == nullptr) - { - return false; - } + auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(Position, Meta & 0x3); - auto & Contents = BlockEntityWithItems->GetContents(); - float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value - - for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot) - { - Fullness += static_cast(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize(); - } - - SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast(1 + (Fullness / Contents.GetNumSlots()) * 14); - return false; - } - ); - auto RearPower = SignalStrength; - auto RearType = a_World.GetBlock(RearCoordinate); - - auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType); - if (PotentialSourceHandler != nullptr) + auto RearChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RearCoordinate); + if ((RearChunk == nullptr) || !RearChunk->IsValid()) { - NIBBLETYPE RearMeta = a_World.GetBlockMeta(RearCoordinate); - RearPower = std::max(SignalStrength, PotentialSourceHandler->GetPowerDeliveredToPosition(a_World, RearCoordinate, RearType, RearMeta, a_Position, a_BlockType)); + return SignalStrength; } - return RearPower; + RearChunk->DoWithBlockEntityAt(RearCoordinate, [&](cBlockEntity & a_BlockEntity) + { + // Skip BlockEntities that don't have slots + auto BlockEntityWithItems = dynamic_cast(&a_BlockEntity); + if (BlockEntityWithItems == nullptr) + { + return false; + } + + // TODO: handle double chests + + auto & Contents = BlockEntityWithItems->GetContents(); + float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value + + for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot) + { + Fullness += static_cast(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize(); + } + + SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast(1 + (Fullness / Contents.GetNumSlots()) * 14); + return false; + }); + + BLOCKTYPE RearType; + NIBBLETYPE RearMeta; + RearChunk->GetBlockTypeMeta(RearCoordinate, RearType, RearMeta); + + auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType); + if (PotentialSourceHandler == nullptr) + { + return SignalStrength; + } + + return std::max( + SignalStrength, + PotentialSourceHandler->GetPowerDeliveredToPosition( + *RearChunk, RearCoordinate, RearType, RearMeta, + cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType + ) + ); } - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // Note that a_PoweringData here contains the maximum * side * power level, as specified by GetValidSourcePositions // LOGD("Evaluating ALU the comparator (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto Data = static_cast(a_World.GetRedstoneSimulator())->GetChunkData(); - auto DelayInfo = Data->GetMechanismDelayInfo(a_Position); + + auto & Data = DataForChunk(a_Chunk); + auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); // Delay is used here to prevent an infinite loop (#3168) if (DelayInfo == nullptr) { - auto RearPower = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); - auto FrontPower = GetFrontPowerLevel(a_World, a_Position, a_BlockType, a_Meta, a_PoweringData.PowerLevel, RearPower); - auto PreviousFrontPower = Data->ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower)); + const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); + const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower); + const auto PreviousFrontPower = Data.GetCachedPowerData(a_Position); + const bool ShouldUpdate = (FrontPower != PreviousFrontPower.PowerLevel); // "Business logic" (:P) - determined by side and rear power levels - bool ShouldBeOn = (RearPower > 0); // Provide visual indication by examining * rear * power level - bool ShouldUpdate = (FrontPower != PreviousFrontPower.PowerLevel); // "Business logic" (:P) - determine by examining *side* power levels - - if (ShouldUpdate || (ShouldBeOn != cBlockComparatorHandler::IsOn(a_Meta))) + if (ShouldUpdate) { - Data->m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn); + Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool()); } } else { int DelayTicks; - bool ShouldPowerOn; - std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; + std::tie(DelayTicks, std::ignore) = *DelayInfo; if (DelayTicks == 0) { - a_World.SetBlockMeta(a_Position, ShouldPowerOn ? (a_Meta | 0x8) : (a_Meta & 0x7)); - Data->m_MechanismDelays.erase(a_Position); + 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); - // Assume that an update (to front power) is needed. - // Note: potential inconsistencies will arise as power data is updated before-delay due to limitations of the power data caching functionality (only stores one bool) - // This means that other mechanisms like wires may get our new power data before our delay has finished - // This also means that we have to manually update ourselves to be aware of any changes that happened in the previous redstone tick - return StaticAppend(GetAdjustedRelatives(a_Position, GetRelativeLaterals()), cVector3iArray{ a_Position }); + // 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); + + // Assume that an update (to front power) is needed: + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3)); } } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); - return cVector3iArray {cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, false), cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, true)}; + + Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, false)); + Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, true)); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h index 2d0ac97b9..fec38b14d 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h @@ -1,7 +1,8 @@ #pragma once -#include "../../World.h" +#include "../../Chunk.h" +#include "RedstoneSimulatorChunkData.h" @@ -14,50 +15,11 @@ public: cRedstoneHandler() = default; DISALLOW_COPY_AND_ASSIGN(cRedstoneHandler); - struct PoweringData - { - public: - PoweringData(BLOCKTYPE a_PoweringBlock, unsigned char a_PowerLevel) : - PoweringBlock(a_PoweringBlock), - PowerLevel(a_PowerLevel) - { - } + using SourceCallback = cFunctionRef; - PoweringData(void) : - PoweringBlock(E_BLOCK_AIR), - PowerLevel(0) - { - } - - BLOCKTYPE PoweringBlock; - unsigned char PowerLevel; - - inline friend bool operator < (const PoweringData & a_Lhs, const PoweringData & a_Rhs) - { - return ( - (a_Lhs.PowerLevel < a_Rhs.PowerLevel) || - ( - (a_Lhs.PowerLevel == a_Rhs.PowerLevel) && - ((a_Lhs.PoweringBlock == E_BLOCK_REDSTONE_WIRE) && (a_Rhs.PoweringBlock != E_BLOCK_REDSTONE_WIRE)) - ) - ); - } - - inline friend bool operator == (const PoweringData & a_Lhs, const PoweringData & a_Rhs) - { - return (a_Lhs.PowerLevel == a_Rhs.PowerLevel); - } - - inline friend bool operator != (const PoweringData & a_Lhs, const PoweringData & a_Rhs) - { - return !operator ==(a_Lhs, a_Rhs); - } - }; - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const = 0; - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const = 0; - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const = 0; - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const = 0; + 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 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; // Force a virtual destructor virtual ~cRedstoneHandler() {} @@ -72,15 +34,9 @@ protected: return ToReturn; } - inline static Vector3i OffsetYP() - { - return Vector3i(0, 1, 0); - } + inline static Vector3i OffsetYP{ 0, 1, 0 }; - inline static Vector3i OffsetYM() - { - return Vector3i(0, -1, 0); - } + inline static Vector3i OffsetYM{ 0, -1, 0 }; static cVector3iArray GetAdjustedRelatives(Vector3i a_Position, cVector3iArray a_Relatives) { @@ -91,31 +47,68 @@ protected: return a_Relatives; } - inline static cVector3iArray GetRelativeAdjacents() + inline static cIncrementalRedstoneSimulatorChunkData & DataForChunk(cChunk & a_Chunk) { - return - { - { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 1, 0 }, - { 0, -1, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, - } - }; + return *static_cast(a_Chunk.GetRedstoneSimulatorData()); } - inline static cVector3iArray GetRelativeLaterals() + template + static void UpdateAdjustedRelatives(cChunk & From, cChunk & To, const Vector3i Position) { - return + DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position)); + } + + template + static void UpdateAdjustedRelatives(cChunk & From, cChunk & To, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives) + { + for (const auto Offset : Relative) { - { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, - } - }; + DataForChunk(To).GetActiveBlocks().push(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset)); + } + + UpdateAdjustedRelatives(From, To, Position, Relatives...); + } + + template + static void InvokeForAdjustedRelatives(SourceCallback Callback, Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives) + { + for (const auto Offset : Relative) + { + Callback(Position + Offset); + } + + InvokeForAdjustedRelatives(Callback, Position, Relatives...); + } + + inline static std::array RelativeAdjacents + { + { + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 }, + } + }; + + inline static std::array RelativeLaterals + { + { + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 }, + } + }; + +private: + + static void UpdateAdjustedRelatives(cVector3iArray &, Vector3i) + { + } + + static void InvokeForAdjustedRelatives(SourceCallback, Vector3i) + { } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h index 7c967af9c..85aa1d743 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h @@ -5,7 +5,7 @@ -class cRedstoneLampHandler : public cRedstoneHandler +class cRedstoneLampHandler final : public cRedstoneHandler { public: @@ -14,17 +14,12 @@ public: return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON); } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + 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 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - return 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating lamp (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); @@ -32,25 +27,23 @@ public: { if (!IsOn(a_BlockType)) { - a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, E_BLOCK_REDSTONE_LAMP_ON, 0); + a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_ON, 0); } } else { if (IsOn(a_BlockType)) { - a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, E_BLOCK_REDSTONE_LAMP_OFF, 0); + a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_OFF, 0); } } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Meta); UNUSED(a_BlockType); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h index 0cd65be53..4174ac930 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h @@ -15,37 +15,27 @@ class cRedstoneRepeaterHandler: public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + 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))) ? - GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta) : 0 - ); + return ((a_QueryPosition == (a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta))) && IsOn(a_BlockType)) ? 15 : 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_Meta); - return IsOn(a_BlockType) ? 15 : 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating loopy the repeater (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto Data = static_cast(a_World.GetRedstoneSimulator())->GetChunkData(); - auto DelayInfo = Data->GetMechanismDelayInfo(a_Position); + + auto & Data = DataForChunk(a_Chunk); + const auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); // If the repeater is locked by another, ignore and forget all power changes: - if (IsLocked(a_World, a_Position, a_Meta)) + if (IsLocked(a_Chunk, a_Position, a_Meta)) { if (DelayInfo != nullptr) { - Data->m_MechanismDelays.erase(a_Position); + Data.m_MechanismDelays.erase(a_Position); } - return {}; + return; } if (DelayInfo == nullptr) @@ -53,7 +43,7 @@ public: bool ShouldBeOn = (a_PoweringData.PowerLevel != 0); if (ShouldBeOn != IsOn(a_BlockType)) { - Data->m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn); + Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn); } } else @@ -64,18 +54,23 @@ public: if (DelayTicks == 0) { - a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta); - Data->m_MechanismDelays.erase(a_Position); - return cVector3iArray{ cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta) + 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); + + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta)); } } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - return { cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position }; + Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position); } private: @@ -87,12 +82,12 @@ private: /** Returns a pair with first element indicating if the block at the given position is an activated repeater. If it is activated, the second element is the repeater metadata. */ - static std::pair IsOnRepeater(cWorld & a_World, const Vector3i a_Position) + static std::pair IsOnRepeater(cChunk & Chunk, const Vector3i a_Position) { BLOCKTYPE Type; NIBBLETYPE Meta; - if (!a_World.GetBlockTypeMeta(a_Position, Type, Meta)) + if (!Chunk.UnboundedRelGetBlock(a_Position, Type, Meta)) { return std::make_pair(false, 0); } @@ -103,20 +98,20 @@ private: /** Determine if a repeater is locked. A locked repeater is one with another powered repeater facing them, to their immediate left or right sides. "Left" is relative to the direction the repeater output faces, naturally. */ - inline static bool IsLocked(cWorld & a_World, const Vector3i a_Position, const NIBBLETYPE a_Meta) + inline static bool IsLocked(cChunk & Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) { // The left hand side offset. Will be negated to get the rhs offset const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta); // Test the block to the left of us - const auto Lhs = IsOnRepeater(a_World, LhsOffset + a_Position); + const auto Lhs = IsOnRepeater(Chunk, LhsOffset + a_Position); if (Lhs.first && DoesLhsLockMe(Lhs.second, a_Meta)) { return true; } // Test the right side, flipping the argument order to DoesLhsLockMe - const auto Rhs = IsOnRepeater(a_World, -LhsOffset + a_Position); + const auto Rhs = IsOnRepeater(Chunk, -LhsOffset + a_Position); return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second); } diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h index a842770a5..71d43d00e 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h @@ -1,73 +1,132 @@ #pragma once -#include "RedstoneHandler.h" +#include + #include "../RedstoneSimulator.h" +struct PoweringData +{ +public: + PoweringData(BLOCKTYPE a_PoweringBlock, unsigned char a_PowerLevel) : + PoweringBlock(a_PoweringBlock), + PowerLevel(a_PowerLevel) + { + } + + PoweringData(void) : + PoweringBlock(E_BLOCK_AIR), + PowerLevel(0) + { + } + + BLOCKTYPE PoweringBlock; + unsigned char PowerLevel; + + inline friend bool operator < (const PoweringData & Lhs, const PoweringData & Rhs) + { + return ( + (Lhs.PowerLevel < Rhs.PowerLevel) || + ( + (Lhs.PowerLevel == Rhs.PowerLevel) && + ((Lhs.PoweringBlock == E_BLOCK_REDSTONE_WIRE) && (Rhs.PoweringBlock != E_BLOCK_REDSTONE_WIRE)) + ) + ); + } + + inline friend bool operator == (const PoweringData & Lhs, const PoweringData & Rhs) + { + return (Lhs.PowerLevel == Rhs.PowerLevel); + } + + inline friend bool operator != (const PoweringData & Lhs, const PoweringData & Rhs) + { + return !operator ==(Lhs, Rhs); + } +}; + + + + + class cIncrementalRedstoneSimulatorChunkData : public cRedstoneSimulatorChunkData { - public: + void WakeUp(const Vector3i & a_Position) { - m_ActiveBlocks.push_back(a_Position); + ActiveBlocks.push(a_Position); } - cVector3iArray & GetActiveBlocks() + auto & GetActiveBlocks() { - return m_ActiveBlocks; + return ActiveBlocks; } - const cRedstoneHandler::PoweringData GetCachedPowerData(const Vector3i & a_Position) const + const PoweringData GetCachedPowerData(const Vector3i Position) const { - auto Result = m_CachedPowerLevels.find(a_Position); - return (Result == m_CachedPowerLevels.end()) ? cRedstoneHandler::PoweringData() : Result->second; + auto Result = CachedPowerLevels.find(Position); + return (Result == CachedPowerLevels.end()) ? PoweringData() : Result->second; } - void SetCachedPowerData(const Vector3i & a_Position, cRedstoneHandler::PoweringData a_PoweringData) + void SetCachedPowerData(const Vector3i Position, PoweringData PoweringData) { - m_CachedPowerLevels[a_Position] = a_PoweringData; + CachedPowerLevels[Position] = PoweringData; } - std::pair * GetMechanismDelayInfo(const Vector3i & a_Position) + std::pair * GetMechanismDelayInfo(const Vector3i Position) { - auto Result = m_MechanismDelays.find(a_Position); + auto Result = m_MechanismDelays.find(Position); return (Result == m_MechanismDelays.end()) ? nullptr : &Result->second; } - /** Erase cached PowerData for position */ - void ErasePowerData(const Vector3i & a_Position) + /** Erase all cached redstone data for position. */ + void ErasePowerData(const Vector3i Position) { - m_CachedPowerLevels.erase(a_Position); - m_MechanismDelays.erase(a_Position); + CachedPowerLevels.erase(Position); + m_MechanismDelays.erase(Position); + AlwaysTickedPositions.erase(Position); } - cRedstoneHandler::PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, cRedstoneHandler::PoweringData a_PoweringData) + PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData) { - auto Result = m_CachedPowerLevels.find(a_Position); - if (Result == m_CachedPowerLevels.end()) + auto Result = CachedPowerLevels.find(a_Position); + if (Result == CachedPowerLevels.end()) { - m_CachedPowerLevels[a_Position] = a_PoweringData; - return cRedstoneHandler::PoweringData(); + CachedPowerLevels[a_Position] = a_PoweringData; + return PoweringData(); } std::swap(Result->second, a_PoweringData); return a_PoweringData; } + /** Adjust From-relative coordinates into To-relative coordinates. */ + inline static Vector3i RebaseRelativePosition(cChunk & From, cChunk & To, const Vector3i Position) + { + return + { + Position.x + (From.GetPosX() - To.GetPosX()) * cChunkDef::Width, + Position.y, + Position.z + (From.GetPosZ() - To.GetPosZ()) * cChunkDef::Width + }; + } + + std::unordered_set> AlwaysTickedPositions; + /** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on */ std::unordered_map, VectorHasher> m_MechanismDelays; private: - cVector3iArray m_ActiveBlocks; + std::stack> ActiveBlocks; // TODO: map -> Position of torch + it's heat level - std::unordered_map> m_CachedPowerLevels; + std::unordered_map> CachedPowerLevels; friend class cRedstoneHandlerFactory; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h index c56b09c7b..bf9c639b1 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h @@ -9,11 +9,8 @@ -class cRedstoneToggleHandler: - public cRedstoneHandler +class cRedstoneToggleHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: inline static Vector3i GetPositionAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) @@ -65,21 +62,18 @@ public: } } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { UNUSED(a_QueryBlockType); if ((GetPositionAttachedTo(a_Position, a_BlockType, a_Meta) == a_QueryPosition) || cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType)) { - return GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); + return GetPowerLevel(a_BlockType, a_Meta); } return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) { - UNUSED(a_World); - UNUSED(a_Position); - switch (a_BlockType) { case E_BLOCK_LEVER: return cBlockLeverHandler::IsLeverOn(a_Meta) ? 15 : 0; @@ -93,18 +87,17 @@ public: } } - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); - return {}; + UNUSED(Callback); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h index 16f060939..c935e1f1b 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h @@ -7,7 +7,7 @@ -class cRedstoneTorchHandler : public cRedstoneHandler +class cRedstoneTorchHandler final : public cRedstoneHandler { public: @@ -33,12 +33,12 @@ public: } } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + 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 ( 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())))) + (cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) || (cBlockInfo::FullyOccupiesVoxel(a_QueryBlockType) && (a_QueryPosition == (a_Position + OffsetYP)))) ) { return 15; @@ -46,24 +46,19 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - return IsOn(a_BlockType) ? 15 : 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); - auto Data = static_cast(a_World.GetRedstoneSimulator())->GetChunkData(); - auto DelayInfo = Data->GetMechanismDelayInfo(a_Position); + auto & Data = DataForChunk(a_Chunk); + auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); if (DelayInfo == nullptr) { bool ShouldBeOn = (a_PoweringData.PowerLevel == 0); if (ShouldBeOn != IsOn(a_BlockType)) { - Data->m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn); + Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn); } } else @@ -72,24 +67,28 @@ public: bool ShouldPowerOn; std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; - if (DelayTicks == 0) + if (DelayTicks != 0) { - a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta); - Data->m_MechanismDelays.erase(a_Position); + return; + } - cVector3iArray RelativePositions = GetRelativeAdjacents(); - RelativePositions.erase(std::remove(RelativePositions.begin(), RelativePositions.end(), GetOffsetAttachedTo(a_Position, a_Meta)), RelativePositions.end()); - return GetAdjustedRelatives(a_Position, RelativePositions); + a_Chunk.SetBlock(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) + { + if (Adjacent != GetOffsetAttachedTo(a_Position, a_Meta)) + { + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + Adjacent); + } } } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); - return { (a_Position + GetOffsetAttachedTo(a_Position, a_Meta)) }; + Callback(a_Position + GetOffsetAttachedTo(a_Position, a_Meta)); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h index e7666f560..3a782d1d3 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h @@ -7,11 +7,8 @@ -class cRedstoneWireHandler: - public cRedstoneHandler +class cRedstoneWireHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: inline static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset) @@ -40,133 +37,170 @@ public: } } - cVector3iArray GetTerracingConnectionOffsets(cWorld & a_World, const Vector3i a_Position) const + template + static bool ForTerracingConnectionOffsets(cChunk & a_Chunk, const Vector3i a_Position, OffsetCallback Callback) { - auto RelativePositions = GetRelativeLaterals(); - const auto YPTerraceBlock = a_World.GetBlock(a_Position + OffsetYP()); + const auto YPTerraceBlock = a_Chunk.GetBlock(a_Position + OffsetYP); const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock); - for (const auto & Adjacent : GetRelativeLaterals()) + for (const auto Adjacent : RelativeLaterals) { - if ( - // A block above us blocks all YP terracing, so the check is static in the loop - !IsYPTerracingBlocked && - (a_World.GetBlock(a_Position + Adjacent + OffsetYP()) == E_BLOCK_REDSTONE_WIRE) - ) + // All laterals are counted as terracing, duh + if (Callback(Adjacent)) { - RelativePositions.emplace_back(Adjacent + OffsetYP()); + return true; } - const auto YMTerraceBlock = a_World.GetBlock(a_Position + Adjacent); if ( - // IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent) - (!cBlockInfo::IsSolid(YMTerraceBlock) || cBlockInfo::IsTransparent(YMTerraceBlock)) && - (a_World.GetBlock(a_Position + Adjacent + OffsetYM()) == E_BLOCK_REDSTONE_WIRE) + BLOCKTYPE YPBlock; + + // 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) ) { - RelativePositions.emplace_back(Adjacent + OffsetYM()); + if (Callback(Adjacent + OffsetYP)) + { + return true; + } + } + + 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) + ) + { + if (Callback(Adjacent + OffsetYM)) + { + return true; + } } } - return RelativePositions; + return false; } - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + 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())) + if (a_QueryPosition == (a_Position + OffsetYP)) { // Wires do not power things above them return 0; } - if (a_QueryBlockType != E_BLOCK_REDSTONE_WIRE) + if (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) { // For mechanisms, wire of power one will still power them - a_Meta++; + // But for wire-to-wire connections, power level decreases by 1 + return (a_Meta != 0) ? --a_Meta : a_Meta; } // Wires always deliver power to the block underneath, and any directly connecting mechanisms if ( - (a_QueryPosition != (a_Position + OffsetYM())) && - !IsDirectlyConnectingMechanism(a_QueryBlockType, a_World.GetBlockMeta(a_QueryPosition), a_QueryPosition - a_Position) + NIBBLETYPE QueryMeta; + + (a_QueryPosition == (a_Position + OffsetYM)) || + (a_Chunk.UnboundedRelGetBlockMeta(a_QueryPosition, QueryMeta) && IsDirectlyConnectingMechanism(a_QueryBlockType, QueryMeta, a_QueryPosition - a_Position)) ) { - /* - 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. - */ + return a_Meta; + } - Vector3i PotentialOffset; - bool FoundOneBorderingMechanism = false; + /* + 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. + */ - for (const auto & Offset : GetTerracingConnectionOffsets(a_World, a_Position)) + Vector3i PotentialOffset; + bool FoundOneBorderingMechanism = false; + + if ( + ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, a_Position, &FoundOneBorderingMechanism, &PotentialOffset](const Vector3i Offset) { BLOCKTYPE Block; NIBBLETYPE Meta; if ( - !a_World.GetBlockTypeMeta(Offset + a_Position, Block, Meta) || + !a_Chunk.UnboundedRelGetBlock(Offset + a_Position, Block, Meta) || !IsDirectlyConnectingMechanism(Block, Meta, Offset) ) { - continue; + return false; } if (FoundOneBorderingMechanism) { // Case 3 - return 0; + return true; } // Potential case 2 FoundOneBorderingMechanism = true; PotentialOffset = { -Offset.x, 0, -Offset.z }; - } - if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset))) - { - // Case 2 fail - return 0; - } - - // Case 1 - // Case 2 success + return false; + }) + ) + { + // Case 3 + return 0; } - return (a_Meta != 0) ? --a_Meta : a_Meta; - } + if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset))) + { + // Case 2 fail + return 0; + } + + // Case 1 + // Case 2 success - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); return a_Meta; } - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + 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); // 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) { - a_World.SetBlockMeta(a_Position, a_PoweringData.PowerLevel); - return GetAdjustedRelatives(a_Position, StaticAppend(StaticAppend(GetRelativeLaterals(), GetTerracingConnectionOffsets(a_World, a_Position)), cVector3iArray{ OffsetYM() })); - } + a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel); - return {}; + // Notify block below us to update: + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + OffsetYM); + + // Notify all terracing positions: + ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, &CurrentlyTicking, a_Position](const Vector3i Offset) + { + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + Offset); + return false; + }); + } } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeAdjacents(), GetTerracingConnectionOffsets(a_World, a_Position))); + Callback(a_Position + OffsetYP); + Callback(a_Position + OffsetYM); + + ForTerracingConnectionOffsets(a_Chunk, a_Position, [&Callback, a_Position](const Vector3i Offset) + { + Callback(a_Position + Offset); + return false; + }); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h b/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h index 48238f4eb..0bf2faacd 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h @@ -7,16 +7,13 @@ -class cSmallGateHandler: - public cRedstoneHandler +class cSmallGateHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -25,32 +22,24 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating gateydory the fence gate/trapdoor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto Data = static_cast(a_World.GetRedstoneSimulator())->GetChunkData(); - if (a_PoweringData != Data->ExchangeUpdateOncePowerData(a_Position, a_PoweringData)) - { - a_World.SetBlockMeta(a_Position, (a_PoweringData.PowerLevel > 0) ? (a_Meta | 0x4) : (a_Meta & ~0x04)); - } - return {}; + const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0; + const bool IsOpen = (a_Meta & 0x4) == 0x4; + + if (ShouldBeOpen != IsOpen) + { + a_Chunk.SetMeta(a_Position, ShouldBeOpen ? (a_Meta | 0x4) : (a_Meta & ~0x04)); + } } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h b/src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h index 5b6bafaa3..abf8dc63b 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/SolidBlockHandler.h @@ -14,41 +14,34 @@ class cSolidBlockHandler: public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - // TODO: wire isn't linked powered only if the source was a wire, not just because it is a wire + const auto SolidBlock = DataForChunk(a_Chunk).GetCachedPowerData(a_Position); return ( !cIncrementalRedstoneSimulator::IsRedstone(a_QueryBlockType) || ( (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) && - (static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PoweringBlock == E_BLOCK_REDSTONE_WIRE) + (SolidBlock.PoweringBlock == E_BLOCK_REDSTONE_WIRE) ) - ) ? 0 : GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); + ) ? 0 : SolidBlock.PowerLevel; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - return static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + 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 = static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData); + auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData); if ((a_PoweringData != PreviousPower) || (a_PoweringData.PoweringBlock != PreviousPower.PoweringBlock)) { - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -64,6 +57,6 @@ public: } } */ - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h index 1ded2a733..4b048e5c2 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h @@ -7,16 +7,13 @@ -class cTNTHandler: - public cRedstoneHandler +class cTNTHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); @@ -25,31 +22,21 @@ public: return 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override - { - UNUSED(a_World); - UNUSED(a_Position); - UNUSED(a_BlockType); - UNUSED(a_Meta); - return 0; - } - - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating explodinator the trinitrotoluene (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); if (a_PoweringData.PowerLevel != 0) { - a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, E_BLOCK_AIR, 0); - a_World.SpawnPrimedTNT(Vector3d(a_Position) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom + a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0); + a_Chunk.GetWorld()->SpawnPrimedTNT(Vector3d(0.5, 0.5, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); // 80 ticks to boom } - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h index e8483a73a..707c239e9 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h @@ -15,54 +15,51 @@ class cTrappedChestHandler: public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); - return static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel; + return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position) { - UNUSED(a_BlockType); - UNUSED(a_Meta); - int NumberOfPlayers = 0; - VERIFY(!a_World.DoWithChestAt(a_Position.x, a_Position.y, a_Position.z, [&](cChestEntity & a_Chest) + VERIFY( + !a_Chunk.DoWithChestAt(a_Position, [&](cChestEntity & a_Chest) { ASSERT(a_Chest.GetBlockType() == E_BLOCK_TRAPPED_CHEST); NumberOfPlayers = a_Chest.GetNumberOfPlayers(); return true; - } - )); + }) + ); + return static_cast(std::min(NumberOfPlayers, 15)); } - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating tricky the trapped chest (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); - auto PreviousPower = static_cast(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power)); + const auto Power = GetPowerLevel(a_Chunk, a_Position); + const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power)); if (Power != PreviousPower.PowerLevel) { - return GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeLaterals(), cVector3iArray{ OffsetYM() })); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, OffsetYM); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals); } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); - - return {}; + UNUSED(Callback); } }; diff --git a/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h b/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h index 6a857cd7c..7c00c4e2f 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h @@ -8,43 +8,53 @@ -class cTripwireHookHandler: - public cRedstoneHandler +class cTripwireHookHandler final : public cRedstoneHandler { - using Super = cRedstoneHandler; - public: - virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override + virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override { + UNUSED(a_BlockType); UNUSED(a_QueryBlockType); UNUSED(a_QueryPosition); - return (GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta) == 15) ? 15 : 0; + return (GetPowerLevel(a_Chunk, a_Position, a_Meta) == 15) ? 15 : 0; } - virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta) { - UNUSED(a_BlockType); - bool FoundActivated = false; - auto Position = a_Position; - eBlockFace FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta); + const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta); for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks { BLOCKTYPE Type; NIBBLETYPE Meta; - AddFaceDirection(Position.x, Position.y, Position.z, FaceToGoTowards); - a_World.GetBlockTypeMeta(Position.x, Position.y, Position.z, Type, Meta); + a_Position = AddFaceDirection(a_Position, FaceToGoTowards); + if (!a_Chunk.UnboundedRelGetBlock(a_Position, Type, Meta)) + { + return 0; + } if (Type == E_BLOCK_TRIPWIRE) { - if (!a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [](cEntity &) { return true; })) + if (FoundActivated) + { + continue; + } + + if ( + !a_Chunk.ForEachEntityInBox( + cBoundingBox(Vector3d(0.5, 0, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()), 0.5, 0.5), + [](cEntity &) { return true; } + ) + ) { FoundActivated = true; } + + continue; } else if (Type == E_BLOCK_TRIPWIRE_HOOK) { @@ -53,27 +63,20 @@ public: // Other hook facing in opposite direction - circuit completed! return FoundActivated ? 15 : 1; } - else - { - // Tripwire hook not connected at all - return 0; - } - } - else - { - // Tripwire hook not connected at all - return 0; } + + // Tripwire hook not connected at all + return 0; } return 0; } - virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override + virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override { // LOGD("Evaluating hooky the tripwire hook (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); - auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); + const auto Power = GetPowerLevel(a_Chunk, a_Position, a_Meta); NIBBLETYPE Meta; if (Power == 0) { @@ -91,25 +94,22 @@ public: } else { - ASSERT(!"Unexpected tripwire hook power level!"); - return {}; + UNREACHABLE("Unexpected tripwire hook power level!"); } if (Meta != a_Meta) { - a_World.SetBlockMeta(a_Position, Meta); - return GetAdjustedRelatives(a_Position, GetRelativeAdjacents()); + a_Chunk.SetMeta(a_Position, Meta); + UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } - - return {}; } - virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override + virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override { - UNUSED(a_World); + UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(a_Position); - return {}; + UNUSED(Callback); } }; diff --git a/src/Simulator/NoopRedstoneSimulator.h b/src/Simulator/NoopRedstoneSimulator.h index 4959882fa..91436ce7e 100644 --- a/src/Simulator/NoopRedstoneSimulator.h +++ b/src/Simulator/NoopRedstoneSimulator.h @@ -7,7 +7,7 @@ -class cRedstoneNoopSimulator: +class cRedstoneNoopSimulator final : public cRedstoneSimulator { using Super = cRedstoneSimulator;