From de5b1401f813985300c33c6b3166b115f9a10dd3 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 8 Feb 2015 16:35:10 +0000 Subject: Comparators --- src/Simulator/IncrementalRedstoneSimulator.cpp | 200 ++++++++++++++++--------- 1 file changed, 133 insertions(+), 67 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 7f320af0d..c1a66243d 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -3,11 +3,10 @@ #include "BlockEntities/ChestEntity.h" -typedef cItemCallback cChestCallback; - #include "Chunk.h" #include "World.h" #include "Blocks/GetHandlerCompileTimeTemplate.h" +#include "Blocks/BlockComparator.h" #include "Blocks/BlockTorch.h" #include "Blocks/BlockLever.h" #include "Blocks/BlockButton.h" @@ -286,6 +285,12 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z); break; } + case E_BLOCK_ACTIVE_COMPARATOR: + case E_BLOCK_INACTIVE_COMPARATOR: + { + HandleRedstoneComparator(dataitr->x, dataitr->y, dataitr->z); + break; + } default: break; } } @@ -535,20 +540,16 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re }; // Check to see if directly beside a power source - unsigned char MyPower; - if (!IsWirePowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower)) + unsigned char MyPower = IsWirePowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); + if (MyPower == 0) { + SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk); m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0); return; } m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - if (MyPower < 1) - { - return; - } - MyPower--; for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power @@ -656,6 +657,67 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re +void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +{ + auto Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + auto HighestSidePower = std::max(IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, false))), IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, true)))); + auto FrontCoordinate = AdjustRelativeCoords(cBlockComparatorHandler::GetFrontCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3)); + unsigned char Power = 0; + + class cContainerCallback : public cBlockEntityCallback + { + public: + cContainerCallback() : m_SignalStrength(0) + { + } + + virtual bool Item(cBlockEntity * a_BlockEntity) override + { + auto & Contents = static_cast(a_BlockEntity)->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 += Contents.GetSlot(Slot).m_ItemCount / Contents.GetSlot(Slot).GetMaxStackSize(); + } + + m_SignalStrength = static_cast(1 + (Fullness / Contents.GetNumSlots()) * 14); + return false; + } + + unsigned char m_SignalStrength; + } CCB; + + auto AbsoluteComparatorCoords = cChunkDef::RelativeToAbsolute(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), m_Chunk->GetPosX(), m_Chunk->GetPosZ()); + auto AbsoluteRearCoords = cBlockComparatorHandler::GetRearCoordinate(AbsoluteComparatorCoords.x, AbsoluteComparatorCoords.y, AbsoluteComparatorCoords.z, Meta & 0x3); + + m_Chunk->DoWithBlockEntityAt(AbsoluteRearCoords.x, AbsoluteRearCoords.y, AbsoluteRearCoords.z, CCB); + auto RearPower = std::max(CCB.m_SignalStrength, IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetRearCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3)))); + + if ((Meta & 0x4) == 0x4) + { // Subtraction mode + Power = RearPower - HighestSidePower; + } + else + { // Comparison mode + Power = std::max(HighestSidePower, RearPower); + } + + if (Power > 0) + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0x8); + SetBlockPowered(FrontCoordinate, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), Power); + } + else + { + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7); + SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk); + } +} + + + + + void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState) { /* Repeater Orientation Mini Guide: @@ -1017,19 +1079,19 @@ void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_ int ChunkX, ChunkZ; cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); - if (!this->m_World.IsChunkLighted(ChunkX, ChunkZ)) + if (!m_World.IsChunkLighted(ChunkX, ChunkZ)) { - this->m_World.QueueLightChunk(ChunkX, ChunkZ); + m_World.QueueLightChunk(ChunkX, ChunkZ); } else { - if (m_Chunk->GetTimeAlteredLight(this->m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8) + if (m_Chunk->GetTimeAlteredLight(m_Chunk->GetSkyLight(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ)) > 8) { SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); } else { - WakeUp(BlockX, a_RelBlockY, BlockZ, m_Chunk); + SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk); } } } @@ -1702,22 +1764,22 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl -bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel) +unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPosition) { - a_PowerLevel = 0; + unsigned char PowerLevel = 0; for (const auto & itr : *m_PoweredBlocks) // Check powered list { - if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + if (itr.a_BlockPos != a_RelBlockPosition) { continue; } - a_PowerLevel = std::max(itr.a_PowerLevel, a_PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block) + PowerLevel = std::max(itr.a_PowerLevel, PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block) } for (const auto & itr : *m_LinkedPoweredBlocks) // Check linked powered list { - if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + if (itr.a_BlockPos != a_RelBlockPosition) { continue; } @@ -1727,10 +1789,10 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBloc { continue; } - a_PowerLevel = std::max(itr.a_PowerLevel, a_PowerLevel); + PowerLevel = std::max(itr.a_PowerLevel, PowerLevel); } - return (a_PowerLevel != 0); // Answer the inital question: is the wire powered? + return PowerLevel; } @@ -1871,20 +1933,20 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_R { static const struct { - int x, y, z; + Vector3i Offset; } gCrossCoords[] = { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, - { 0, 1, 0 }, - { 0, -1, 0 } + Vector3i(1, 0, 0), + Vector3i(-1, 0, 0), + Vector3i(0, 0, 1), + Vector3i(0, 0, -1), + Vector3i(0, 1, 0), + Vector3i(0, -1, 0) }; for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions { - SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_PowerLevel); + SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ) + gCrossCoords[i].Offset, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), a_PowerLevel); } } @@ -1892,60 +1954,64 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_R -void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel) +void cIncrementalRedstoneSimulator::SetBlockPowered(Vector3i a_RelBlockPosition, Vector3i a_RelSourcePosition, unsigned char a_PowerLevel) { - cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values + cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockPosition.x, a_RelBlockPosition.z); // Adjust coordinates for the later call using these values if ((Neighbour == nullptr) || !Neighbour->IsValid()) { return; } + a_RelSourcePosition.x += (m_Chunk->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width; + a_RelSourcePosition.z += (m_Chunk->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width; auto & Powered = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position for (auto itr = Powered.begin(); itr != Powered.end(); ++itr) { - if ( - itr->a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) && - itr->a_SourcePos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ)) - ) + if ((itr->a_BlockPos == a_RelBlockPosition) && (itr->a_SourcePos == a_RelSourcePosition)) { - // Check for duplicates, update power level, don't add a new listing - itr->a_PowerLevel = a_PowerLevel; - return; - } - } - - // No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk - for (auto itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) - { - if ( - itr->a_BlockPos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ)) && - itr->a_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) && - (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE) - ) - { - BLOCKTYPE Block; - NIBBLETYPE Meta; - Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block, Meta); - - if (Block == E_BLOCK_REDSTONE_WIRE) + if (itr->a_PowerLevel != a_PowerLevel) { - if (Meta < a_PowerLevel) - { - m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it - break; - } - else - { - // Powered wires try to power their source - don't let them! - return; - } + // Update power level, don't add a new listing + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); + itr->a_PowerLevel = a_PowerLevel; } + return; } } + //// No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk + //for (auto itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) + //{ + // if ( + // (itr->a_BlockPos == a_RelBlockPosition) && + // (itr->a_SourcePos == a_RelSourcePosition) && + // (m_Chunk->GetBlock(a_RelSourcePosition) == E_BLOCK_REDSTONE_WIRE) + // ) + // { + // BLOCKTYPE Block; + // NIBBLETYPE Meta; + // Neighbour->GetBlockTypeMeta(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, Meta); + + // if (Block == E_BLOCK_REDSTONE_WIRE) + // { + // if (Meta < a_PowerLevel) + // { + // m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it + // break; + // } + // else + // { + // // Powered wires try to power their source - don't let them! + // return; + // } + // } + // } + //} + sPoweredBlocks RC; - RC.a_BlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - RC.a_SourcePos = Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ); + RC.a_BlockPos = a_RelBlockPosition; + RC.a_SourcePos = a_RelSourcePosition; RC.a_PowerLevel = a_PowerLevel; Powered.emplace_back(RC); Neighbour->SetIsRedstoneDirty(true); @@ -2123,7 +2189,7 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R for (const auto & itr : BlocksPotentiallyUnpowered) { auto Neighbour = a_Chunk->GetRelNeighborChunk(itr.x, itr.z); - if (!AreCoordsPowered(itr.x, itr.y, itr.z) && (Neighbour->GetBlock(itr) != E_BLOCK_REDSTONE_REPEATER_ON)) + if (Neighbour->GetBlock(itr) != E_BLOCK_REDSTONE_REPEATER_ON) { // Repeaters time themselves with regards to unpowering; ensure we don't do it for them SetSourceUnpowered(itr.x, itr.y, itr.z, Neighbour); -- cgit v1.2.3 From bd484750856586bd2354be2aa6852a63fd102c1b Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 20 Mar 2015 22:30:20 +0000 Subject: Provides improvements to redstone wire Intermediary commit that fixes #1763. --- src/Simulator/IncrementalRedstoneSimulator.cpp | 145 ++++++++++--------------- 1 file changed, 60 insertions(+), 85 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index c1a66243d..ff813a2c0 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -304,7 +304,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) { - if (AreCoordsOnChunkBoundary(a_BlockX, a_BlockY, a_BlockZ)) + if (GetCoordinateAdjacentChunk({ a_BlockX, a_BlockY, a_BlockZ }).Equals({ 0, 0, 0 })) { // On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk) AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); @@ -1980,35 +1980,6 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(Vector3i a_RelBlockPosition, } } - //// No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk - //for (auto itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) - //{ - // if ( - // (itr->a_BlockPos == a_RelBlockPosition) && - // (itr->a_SourcePos == a_RelSourcePosition) && - // (m_Chunk->GetBlock(a_RelSourcePosition) == E_BLOCK_REDSTONE_WIRE) - // ) - // { - // BLOCKTYPE Block; - // NIBBLETYPE Meta; - // Neighbour->GetBlockTypeMeta(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, Meta); - - // if (Block == E_BLOCK_REDSTONE_WIRE) - // { - // if (Meta < a_PowerLevel) - // { - // m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it - // break; - // } - // else - // { - // // Powered wires try to power their source - don't let them! - // return; - // } - // } - // } - //} - sPoweredBlocks RC; RC.a_BlockPos = a_RelBlockPosition; RC.a_SourcePos = a_RelSourcePosition; @@ -2079,20 +2050,12 @@ void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_Re continue; } - if (itr->WasLastStatePowered != WasLastStatePowered) - { - // If power states different, update listing - itr->WasLastStatePowered = WasLastStatePowered; - return; - } - else - { - // If states the same, just ignore - return; - } + // Update listing + itr->WasLastStatePowered = WasLastStatePowered; + return; } - // We have arrive here; no block must be in list - add one + // We have arrived here; no block must be in list - add one sSimulatedPlayerToggleableList RC; RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); RC.WasLastStatePowered = WasLastStatePowered; @@ -2140,60 +2103,72 @@ bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in -void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk, bool a_IsFirstCall) +void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk) { - if (!a_IsFirstCall) // The neighbouring chunks passed when this parameter is false may be invalid + std::vector> BlocksPotentiallyUnpowered = { std::make_pair(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ), a_Chunk) }; + + auto UnpoweringFunction = [&BlocksPotentiallyUnpowered](cChunk * a_Chunk, const Vector3i & a_RelSource) { - if ((a_Chunk == nullptr) || !a_Chunk->IsValid()) - { - return; - } - } + auto Data = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData(); + Data->m_PoweredBlocks.erase(std::remove_if(Data->m_PoweredBlocks.begin(), Data->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sPoweredBlocks & itr) + { + if (itr.a_SourcePos != a_RelSource) + { + return false; + } - std::vector BlocksPotentiallyUnpowered; + auto ChunkBoundaryTestCoords = a_RelSource + GetCoordinateAdjacentChunk(a_RelSource); + auto BoundaryChunk = a_Chunk->GetRelNeighborChunk(ChunkBoundaryTestCoords.x, ChunkBoundaryTestCoords.z); + if (BoundaryChunk != a_Chunk) + { + Vector3i ChunkAdjustedSource = a_RelSource; + ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; + ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; + + auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); + BoundaryData->m_PoweredBlocks.erase(std::remove_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sPoweredBlocks & itr) + { + if (itr.a_SourcePos != ChunkAdjustedSource) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); + BoundaryChunk->SetIsRedstoneDirty(true); + return true; + } + ), BoundaryData->m_PoweredBlocks.end()); + } - auto Data = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData(); - Data->m_PoweredBlocks.erase(std::remove_if(Data->m_PoweredBlocks.begin(), Data->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSourceX, a_RelSourceY, a_RelSourceZ](const sPoweredBlocks & itr) - { - if (itr.a_SourcePos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ))) - { - BlocksPotentiallyUnpowered.emplace_back(itr.a_BlockPos); + if (a_Chunk->GetBlock(a_RelSource) == E_BLOCK_REDSTONE_REPEATER_ON) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); a_Chunk->SetIsRedstoneDirty(true); return true; } - return false; - } - ), Data->m_PoweredBlocks.end()); + ), Data->m_PoweredBlocks.end()); - Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSourceX, a_RelSourceY, a_RelSourceZ](const sLinkedPoweredBlocks & itr) - { - if (itr.a_SourcePos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ))) + /*Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sLinkedPoweredBlocks & itr) { - BlocksPotentiallyUnpowered.emplace_back(itr.a_BlockPos); - a_Chunk->SetIsRedstoneDirty(true); - return true; + if (itr.a_SourcePos == a_RelSource) + { + BlocksPotentiallyUnpowered.emplace_back(itr.a_BlockPos); + a_Chunk->SetIsRedstoneDirty(true); + return true; + } + return false; } - return false; - } - ), Data->m_LinkedBlocks.end()); - - if (a_IsFirstCall && AreCoordsOnChunkBoundary(a_RelSourceX, a_RelSourceY, a_RelSourceZ)) - { - // +- 2 to accomodate linked powered blocks - SetSourceUnpowered(a_RelSourceX, a_RelSourceY, a_RelSourceZ, a_Chunk->GetRelNeighborChunk(a_RelSourceX - 2, a_RelSourceZ), false); - SetSourceUnpowered(a_RelSourceX, a_RelSourceY, a_RelSourceZ, a_Chunk->GetRelNeighborChunk(a_RelSourceX + 2, a_RelSourceZ), false); - SetSourceUnpowered(a_RelSourceX, a_RelSourceY, a_RelSourceZ, a_Chunk->GetRelNeighborChunk(a_RelSourceX, a_RelSourceZ - 2), false); - SetSourceUnpowered(a_RelSourceX, a_RelSourceY, a_RelSourceZ, a_Chunk->GetRelNeighborChunk(a_RelSourceX, a_RelSourceZ + 2), false); - } + ), Data->m_LinkedBlocks.end());*/ + }; - for (const auto & itr : BlocksPotentiallyUnpowered) + while (!BlocksPotentiallyUnpowered.empty()) { - auto Neighbour = a_Chunk->GetRelNeighborChunk(itr.x, itr.z); - if (Neighbour->GetBlock(itr) != E_BLOCK_REDSTONE_REPEATER_ON) - { - // Repeaters time themselves with regards to unpowering; ensure we don't do it for them - SetSourceUnpowered(itr.x, itr.y, itr.z, Neighbour); - } + auto End = BlocksPotentiallyUnpowered.back(); + BlocksPotentiallyUnpowered.pop_back(); + UnpoweringFunction(End.second, End.first); } } @@ -2226,7 +2201,7 @@ void cIncrementalRedstoneSimulator::SetInvalidMiddleBlock(int a_RelMiddleX, int } ), Data->m_LinkedBlocks.end()); - if (a_IsFirstCall && AreCoordsOnChunkBoundary(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ)) + if (a_IsFirstCall && /*AreCoordsOnChunkBoundary(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ)*/1) { // +- 2 to accomodate linked powered blocks SetInvalidMiddleBlock(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, a_Chunk->GetRelNeighborChunk(a_RelMiddleX - 2, a_RelMiddleZ), false); -- cgit v1.2.3 From 84534dfeb288dd12d998f3f192ee162a1def5367 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 26 Apr 2015 00:38:41 +0100 Subject: Redstone wire and trapdoor fixes * Fixes #1887 * Fixes #1763 * Fixes #1083 --- src/Simulator/IncrementalRedstoneSimulator.cpp | 550 ++++++++++++------------- 1 file changed, 267 insertions(+), 283 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index ff813a2c0..40829757d 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -24,41 +24,42 @@ -void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk, cChunk * a_OtherChunk) +void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) { - if ((a_Chunk == nullptr) || !a_Chunk->IsValid()) + AddBlock(cChunkDef::AbsoluteToRelative({ a_BlockX, a_BlockY, a_BlockZ }, a_Chunk->GetPosX(), a_Chunk->GetPosZ()), a_Chunk, nullptr); +} + + + + + +void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition, cChunk * a_OriginalChunk, cChunk * a_NeighborChunk) +{ + if ((a_OriginalChunk == nullptr) || !a_OriginalChunk->IsValid()) { return; } - else if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) + else if ((a_RelBlockPosition.y < 0) || (a_RelBlockPosition.y >= cChunkDef::Height)) { return; } - // We may be called with coordinates in a chunk that is not the first chunk parameter - // In that case, the actual chunk (which the coordinates are in), will be passed as the second parameter - // Use that Chunk pointer to get a relative position + // The relative block position is relative to the neighboring chunk should it be passed as an argument - int RelX = 0; - int RelZ = 0; BLOCKTYPE Block; NIBBLETYPE Meta; - if (a_OtherChunk != nullptr) + if (a_NeighborChunk != nullptr) { - RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width; - RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width; - a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + a_NeighborChunk->UnboundedRelGetBlock(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, Meta); - // If a_OtherChunk is passed (not nullptr), it is the chunk that had a block change, and a_Chunk will be the neighbouring chunk of that block + // If a_OtherChunk is passed (not nullptr), it is the neighbouring chunk of a_Chunk, which itself is the chunk with the block change // Because said neighbouring chunk does not know of this change but still needs to update its redstone, we set it to dirty - a_Chunk->SetIsRedstoneDirty(true); + a_NeighborChunk->SetIsRedstoneDirty(true); } else { - RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width; - RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width; - a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta); + a_OriginalChunk->GetBlockTypeMeta(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, Meta); } // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid @@ -76,39 +77,53 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, ) ) { - SetSourceUnpowered(RelX, a_BlockY, RelZ, a_OtherChunk != nullptr ? a_OtherChunk : a_Chunk); + SetSourceUnpowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_NeighborChunk != nullptr ? a_NeighborChunk : a_OriginalChunk); } if (!IsViableMiddleBlock(Block)) { - SetInvalidMiddleBlock(RelX, a_BlockY, RelZ, a_OtherChunk != nullptr ? a_OtherChunk : a_Chunk); + SetInvalidMiddleBlock(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_NeighborChunk != nullptr ? a_NeighborChunk : a_OriginalChunk); } - auto & SimulatedPlayerToggleableBlocks = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks; - SimulatedPlayerToggleableBlocks.erase(std::remove_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), [RelX, a_BlockY, RelZ, Block, this](const sSimulatedPlayerToggleableList & itr) + if (a_NeighborChunk != nullptr) + { + // DO NOT touch our chunk's data structure if we are being called with coordinates from another chunk - this one caused me massive grief :P + return; + } + + auto & SimulatedPlayerToggleableBlocks = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks; + if ( + DoesIgnorePlayerToggle(Block) && + std::find_if(SimulatedPlayerToggleableBlocks.begin(),SimulatedPlayerToggleableBlocks.end(), + [a_RelBlockPosition](const sSimulatedPlayerToggleableList & itr){ return itr.a_RelBlockPos == a_RelBlockPosition; }) == SimulatedPlayerToggleableBlocks.end() + ) + { + // We have arrived here; no block must be in list - add one + sSimulatedPlayerToggleableList RC; + RC.a_RelBlockPos = a_RelBlockPosition; + RC.WasLastStatePowered = AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk); + + // Initialise the toggleable blocks list so that trapdoors etc. aren't reset on restart (#1887) + SimulatedPlayerToggleableBlocks.emplace_back(RC); + } + + SimulatedPlayerToggleableBlocks.erase(std::remove_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), [a_RelBlockPosition, Block, this](const sSimulatedPlayerToggleableList & itr) { - return itr.a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ)) && !IsAllowedBlock(Block); + return (itr.a_RelBlockPos == a_RelBlockPosition) && !DoesIgnorePlayerToggle(Block); } ), SimulatedPlayerToggleableBlocks.end()); - - auto & RepeatersDelayList = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_RepeatersDelayList; - RepeatersDelayList.erase(std::remove_if(RepeatersDelayList.begin(), RepeatersDelayList.end(), [RelX, a_BlockY, RelZ, Block](const sRepeatersDelayList & itr) + auto & RepeatersDelayList = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList; + RepeatersDelayList.erase(std::remove_if(RepeatersDelayList.begin(), RepeatersDelayList.end(), [a_RelBlockPosition, Block](const sRepeatersDelayList & itr) { - return itr.a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ)) && (Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF); + return (itr.a_RelBlockPos == a_RelBlockPosition) && (Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF); } ), RepeatersDelayList.end()); - if (a_OtherChunk != nullptr) - { - // DO NOT touch our chunk's data structure if we are being called with coordinates from another chunk - this one caused me massive grief :P - return; - } - - cCoordWithBlockAndBoolVector & RedstoneSimulatorChunkData = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_ChunkData; + auto & RedstoneSimulatorChunkData = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData; for (auto & itr : RedstoneSimulatorChunkData) { - if ((itr.x == RelX) && (itr.y == a_BlockY) && (itr.z == RelZ)) // We are at an entry matching the current (changed) block + if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z)) // We are at an entry matching the current (changed) block { if (!IsAllowedBlock(Block)) { @@ -128,16 +143,16 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, return; } - cCoordWithBlockAndBoolVector & QueuedData = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData; + auto & QueuedData = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_QueuedChunkData; for (const auto & itr : QueuedData) { - if ((itr.x == RelX) && (itr.y == a_BlockY) && (itr.z == RelZ)) + if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z)) { // Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data return; } } - QueuedData.emplace_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false)); + QueuedData.emplace_back(cCoordWithBlockAndBool(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, false)); } @@ -146,13 +161,13 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY, void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { - m_RedstoneSimulatorChunkData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData(); + m_RedstoneSimulatorChunkData = static_cast(a_Chunk->GetRedstoneSimulatorData()); if (m_RedstoneSimulatorChunkData == nullptr) { m_RedstoneSimulatorChunkData = new cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData(); a_Chunk->SetRedstoneSimulatorData(m_RedstoneSimulatorChunkData); } - if (m_RedstoneSimulatorChunkData->m_ChunkData.empty() && ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData.empty()) + if (m_RedstoneSimulatorChunkData->m_ChunkData.empty() && static_cast(a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData.empty()) { return; } @@ -304,23 +319,14 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) { - if (GetCoordinateAdjacentChunk({ a_BlockX, a_BlockY, a_BlockZ }).Equals({ 0, 0, 0 })) - { - // On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk) - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); - - // Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position - // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordinates are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 2, a_BlockZ), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 2, a_BlockZ), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 2), a_Chunk); - RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 2), a_Chunk); + auto CurrentChunkRelative = cChunkDef::AbsoluteToRelative({a_BlockX, a_BlockY, a_BlockZ}, a_Chunk->GetPosX(), a_Chunk->GetPosZ()); + AddBlock(CurrentChunkRelative, a_Chunk); // Alert the current chunk which the block is present in - return; + for (const auto & BoundaryChunk : GetAdjacentChunks(CurrentChunkRelative, a_Chunk)) + { + // On a chunk boundary, alert all neighbouring chunks which may have a connection with this block + AddBlock(cChunkDef::AbsoluteToRelative({a_BlockX, a_BlockY, a_BlockZ}, BoundaryChunk->GetPosX(), BoundaryChunk->GetPosZ()), a_Chunk, BoundaryChunk); } - - // Not on boundary, just alert this chunk for speed - AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); } @@ -508,147 +514,145 @@ void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_RelBlockX, int a_ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { - static const struct // Define which directions the wire can receive power from + static const eBlockFace BlockFaceOffsets[] = { - int x, y, z; - } gCrossCoords[] = - { - { 1, 0, 0 }, /* Wires on same level start */ - { -1, 0, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 }, /* Wires on same level stop */ - { 1, 1, 0 }, /* Wires one higher, surrounding self start */ - { -1, 1, 0 }, - { 0, 1, 1 }, - { 0, 1, -1 }, /* Wires one higher, surrounding self stop */ - { 1, -1, 0 }, /* Wires one lower, surrounding self start */ - { -1, -1, 0 }, - { 0, -1, 1 }, - { 0, -1, -1 }, /* Wires one lower, surrounding self stop */ + BLOCK_FACE_XM, + BLOCK_FACE_XP, + BLOCK_FACE_ZM, + BLOCK_FACE_ZP }; - static const struct // Define which directions the wire will check for repeater prescence - { - int x, y, z; - } gSideCoords[] = + static const Vector3i VectorOffsets[] = { - { 1, 0, 0 }, { -1, 0, 0 }, - { 0, 0, 1 }, + { 1, 0, 0 }, { 0, 0, -1 }, - { 0, 1, 0 }, + { 0, 0, 1 } }; + auto RelBlock = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + // Check to see if directly beside a power source - unsigned char MyPower = IsWirePowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)); + unsigned char MyPower = IsWirePowered(RelBlock, m_Chunk); + m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); if (MyPower == 0) { SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk); - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0); return; } - m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + if (MyPower == MAX_POWER_LEVEL) + { + std::vector> PotentialWireList = { std::make_pair(RelBlock, m_Chunk) }; + while (!PotentialWireList.empty()) + { + auto Current = PotentialWireList.back(); + PotentialWireList.pop_back(); + FindAndPowerBorderingWires(PotentialWireList, Current); + } + } + else if (MyPower == 1) + { + return; + } MyPower--; - for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power + // Wire still powered, power blocks beneath + SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, MyPower); + + int BorderingMechanismCount = 0; + bool RepeaterPresent = false; + Vector3i VectorOffset; + + for (auto OffsetIdx = 0; OffsetIdx != ARRAYCOUNT(VectorOffsets); ++OffsetIdx) { - if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above... - { - BLOCKTYPE Type = 0; - if (a_RelBlockY >= cChunkDef::Height - 1) - { - continue; - } - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, Type)) - { - continue; - } - if (cBlockInfo::IsSolid(Type)) // If there is something solid above us (wire cut off)... - { - continue; // We don't receive power from that wire - } - } - else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us + BLOCKTYPE Block; + auto Offset = RelBlock + VectorOffsets[OffsetIdx]; + if (m_Chunk->UnboundedRelGetBlockType(Offset.x, Offset.y, Offset.z, Block)) { - BLOCKTYPE Type = 0; - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY, a_RelBlockZ + gCrossCoords[i].z, Type)) - { - continue; - } - if (cBlockInfo::IsSolid(Type)) + switch (Block) { - continue; + case E_BLOCK_REDSTONE_REPEATER_OFF: + { + BorderingMechanismCount++; + if (!RepeaterPresent) + { + // TODO: only if wire is actually connected to repeater (repeater facing right way) + RepeaterPresent = true; + VectorOffset = { -VectorOffsets[OffsetIdx].x, VectorOffsets[OffsetIdx].y, -VectorOffsets[OffsetIdx].z }; + } + SetBlockPowered(Offset, RelBlock, MyPower); + } + case E_BLOCK_REDSTONE_TORCH_ON: + case E_BLOCK_REDSTONE_WIRE: + { + BorderingMechanismCount++; + if (!RepeaterPresent) + { + VectorOffset = { -VectorOffsets[OffsetIdx].x, VectorOffsets[OffsetIdx].y, -VectorOffsets[OffsetIdx].z }; + } + } + default: break; } } - - BLOCKTYPE Type = 0; - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, Type)) - { - continue; - } - if (Type == E_BLOCK_REDSTONE_WIRE) - { - SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - } } - for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them + if (BorderingMechanismCount == 0) { - BLOCKTYPE Type = 0; - if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, Type)) - { - continue; - } - if (Type == E_BLOCK_REDSTONE_REPEATER_OFF) - { - SetBlockPowered(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - } + SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); } + else if (BorderingMechanismCount == 1) + { + eBlockFace Face = BlockFaceOffsets[std::distance(VectorOffsets, std::find(VectorOffsets, VectorOffsets + ARRAYCOUNT(VectorOffsets), VectorOffset))]; + SetBlockPowered(RelBlock + VectorOffset, RelBlock, MyPower); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Face, MyPower); + } +} + - // Wire still powered, power blocks beneath - SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, MyPower); - switch (GetWireDirection(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) + + +void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vector> & a_PotentialWireList, const std::pair & a_Entry) +{ + std::vector> NewAdditions; + const Vector3i Offsets[] = { - case REDSTONE_NONE: - { - SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); + { 1, 0, 0 }, /* Wires on same level start */ + { -1, 0, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 }, /* Wires on same level stop */ + { 1, 1, 0 }, /* Wires one higher, surrounding self start */ + { -1, 1, 0 }, + { 0, 1, 1 }, + { 0, 1, -1 }, /* Wires one higher, surrounding self stop */ + { 1, -1, 0 }, /* Wires one lower, surrounding self start */ + { -1, -1, 0 }, + { 0, -1, 1 }, + { 0, -1, -1 }, /* Wires one lower, surrounding self stop */ + }; + + for (auto Offset : Offsets) + { + auto AdjustedPos = a_Entry.first + Offset; + auto Neighbour = a_Entry.second->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); + auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower); - break; - } - case REDSTONE_X_POS: - { - SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower); - break; - } - case REDSTONE_X_NEG: + if ((Neighbour->GetBlock(AdjustedPos) == E_BLOCK_REDSTONE_WIRE) && (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) { - SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower); - break; - } - case REDSTONE_Z_POS: - { - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower); - break; - } - case REDSTONE_Z_NEG: - { - SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); - SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower); - break; + sPoweredBlocks RC; + RC.a_BlockPos = AdjustedPos; + RC.a_SourcePos = a_Entry.first + Vector3i((a_Entry.second->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width, 0, (a_Entry.second->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width); + RC.a_PowerLevel = MyPower - 1; + ((cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks.emplace_back(RC); // We need to insert the value into the chunk who owns the block position + + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); + + Neighbour->SetMeta(AdjustedPos.x, AdjustedPos.y, AdjustedPos.z, MyPower - 1); + a_PotentialWireList.emplace_back(std::make_pair(AdjustedPos, Neighbour)); } } } @@ -660,7 +664,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { auto Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - auto HighestSidePower = std::max(IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, false))), IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, true)))); + auto HighestSidePower = std::max(IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, false)), m_Chunk), IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, true)), m_Chunk)); auto FrontCoordinate = AdjustRelativeCoords(cBlockComparatorHandler::GetFrontCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3)); unsigned char Power = 0; @@ -691,7 +695,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, in auto AbsoluteRearCoords = cBlockComparatorHandler::GetRearCoordinate(AbsoluteComparatorCoords.x, AbsoluteComparatorCoords.y, AbsoluteComparatorCoords.z, Meta & 0x3); m_Chunk->DoWithBlockEntityAt(AbsoluteRearCoords.x, AbsoluteRearCoords.y, AbsoluteRearCoords.z, CCB); - auto RearPower = std::max(CCB.m_SignalStrength, IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetRearCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3)))); + auto RearPower = std::max(CCB.m_SignalStrength, IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetRearCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3)), m_Chunk)); if ((Meta & 0x4) == 0x4) { // Subtraction mode @@ -1514,30 +1518,18 @@ bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, in { // Torches want to access neighbour's data when on a wall, hence the extra chunk parameter - for (const auto & itr : ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks) // Check powered list - { - if (itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - return true; - } - } - return false; + const auto & Data = static_cast(a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks; + return std::find_if(Data.begin(), Data.end(), [a_RelBlockX, a_RelBlockY, a_RelBlockZ](const sPoweredBlocks & itr) { return itr.a_BlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }) != Data.end(); } -bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk) { - for (const auto & itr : *m_LinkedPoweredBlocks) // Check linked powered list - { - if (itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - return true; - } - } - return false; + const auto & Data = static_cast(a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks; + return std::find_if(Data.begin(), Data.end(), [a_RelBlockX, a_RelBlockY, a_RelBlockZ](const sLinkedPoweredBlocks & itr) { return itr.a_BlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }) != Data.end(); } @@ -1764,11 +1756,11 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl -unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPosition) +unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPosition, cChunk * a_Chunk) { unsigned char PowerLevel = 0; - for (const auto & itr : *m_PoweredBlocks) // Check powered list + for (const auto & itr : static_cast(a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks) // Check powered list { if (itr.a_BlockPos != a_RelBlockPosition) { @@ -1777,7 +1769,7 @@ unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPo PowerLevel = std::max(itr.a_PowerLevel, PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block) } - for (const auto & itr : *m_LinkedPoweredBlocks) // Check linked powered list + for (const auto & itr : static_cast(a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks) // Check linked powered list { if (itr.a_BlockPos != a_RelBlockPosition) { @@ -1785,7 +1777,7 @@ unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPo } BLOCKTYPE Type = E_BLOCK_AIR; - if (!m_Chunk->UnboundedRelGetBlockType(itr.a_SourcePos.x, itr.a_SourcePos.y, itr.a_SourcePos.z, Type) || (Type == E_BLOCK_REDSTONE_WIRE)) + if (!a_Chunk->UnboundedRelGetBlockType(itr.a_SourcePos.x, itr.a_SourcePos.y, itr.a_SourcePos.z, Type) || (Type == E_BLOCK_REDSTONE_WIRE)) { continue; } @@ -1931,22 +1923,19 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_RelBlockX, i void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel) { - static const struct - { - Vector3i Offset; - } gCrossCoords[] = - { - Vector3i(1, 0, 0), - Vector3i(-1, 0, 0), - Vector3i(0, 0, 1), - Vector3i(0, 0, -1), - Vector3i(0, 1, 0), - Vector3i(0, -1, 0) + static const Vector3i Offsets[] = + { + {1, 0, 0}, + { -1, 0, 0}, + {0, 0, 1}, + {0, 0, -1}, + {0, 1, 0}, + {0, -1, 0} }; - for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions + for (auto Offset : Offsets) // Loop through struct to power all directions { - SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ) + gCrossCoords[i].Offset, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), a_PowerLevel); + SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ) + Offset, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), a_PowerLevel); } } @@ -1964,7 +1953,7 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(Vector3i a_RelBlockPosition, a_RelSourcePosition.x += (m_Chunk->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width; a_RelSourcePosition.z += (m_Chunk->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width; - auto & Powered = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position + auto & Powered = static_cast(Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position for (auto itr = Powered.begin(); itr != Powered.end(); ++itr) { if ((itr->a_BlockPos == a_RelBlockPosition) && (itr->a_SourcePos == a_RelSourcePosition)) @@ -2012,7 +2001,7 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( return; } - auto & Linked = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_LinkedBlocks; + auto & Linked = static_cast(Neighbour->GetRedstoneSimulatorData())->m_LinkedBlocks; for (auto & itr : Linked) // Check linked powered list { if ( @@ -2041,24 +2030,24 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( -void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered) +void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool a_WasLastStatePowered) { - for (auto itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr) + for (auto & itr : *m_SimulatedPlayerToggleableBlocks) { - if (!itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + if (!itr.a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) { continue; } // Update listing - itr->WasLastStatePowered = WasLastStatePowered; + itr.WasLastStatePowered = a_WasLastStatePowered; return; } // We have arrived here; no block must be in list - add one sSimulatedPlayerToggleableList RC; RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - RC.WasLastStatePowered = WasLastStatePowered; + RC.WasLastStatePowered = a_WasLastStatePowered; m_SimulatedPlayerToggleableBlocks->emplace_back(RC); } @@ -2109,7 +2098,7 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R auto UnpoweringFunction = [&BlocksPotentiallyUnpowered](cChunk * a_Chunk, const Vector3i & a_RelSource) { - auto Data = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData(); + auto Data = static_cast(a_Chunk->GetRedstoneSimulatorData()); Data->m_PoweredBlocks.erase(std::remove_if(Data->m_PoweredBlocks.begin(), Data->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sPoweredBlocks & itr) { if (itr.a_SourcePos != a_RelSource) @@ -2117,16 +2106,16 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R return false; } - auto ChunkBoundaryTestCoords = a_RelSource + GetCoordinateAdjacentChunk(a_RelSource); - auto BoundaryChunk = a_Chunk->GetRelNeighborChunk(ChunkBoundaryTestCoords.x, ChunkBoundaryTestCoords.z); - if (BoundaryChunk != a_Chunk) + for (const auto & BoundaryChunk : GetAdjacentChunks(a_RelSource, a_Chunk)) { - Vector3i ChunkAdjustedSource = a_RelSource; - ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; - ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; + if (BoundaryChunk != a_Chunk) + { + Vector3i ChunkAdjustedSource = a_RelSource; + ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; + ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; - auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); - BoundaryData->m_PoweredBlocks.erase(std::remove_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sPoweredBlocks & itr) + auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); + BoundaryData->m_PoweredBlocks.erase(std::remove_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sPoweredBlocks & itr) { if (itr.a_SourcePos != ChunkAdjustedSource) { @@ -2137,7 +2126,8 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R BoundaryChunk->SetIsRedstoneDirty(true); return true; } - ), BoundaryData->m_PoweredBlocks.end()); + ), BoundaryData->m_PoweredBlocks.end()); + } } if (a_Chunk->GetBlock(a_RelSource) == E_BLOCK_REDSTONE_REPEATER_ON) @@ -2151,17 +2141,47 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R } ), Data->m_PoweredBlocks.end()); - /*Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sLinkedPoweredBlocks & itr) + Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sLinkedPoweredBlocks & itr) { - if (itr.a_SourcePos == a_RelSource) + if (itr.a_SourcePos != a_RelSource) { - BlocksPotentiallyUnpowered.emplace_back(itr.a_BlockPos); - a_Chunk->SetIsRedstoneDirty(true); - return true; + return false; } - return false; + + for (const auto & BoundaryChunk : GetAdjacentChunks(a_RelSource, a_Chunk)) + { + if (BoundaryChunk != a_Chunk) + { + Vector3i ChunkAdjustedSource = a_RelSource; + ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; + ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; + + auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); + BoundaryData->m_LinkedBlocks.erase(std::remove_if(BoundaryData->m_LinkedBlocks.begin(), BoundaryData->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sLinkedPoweredBlocks & itr) + { + if (itr.a_SourcePos != ChunkAdjustedSource) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); + BoundaryChunk->SetIsRedstoneDirty(true); + return true; + } + ), BoundaryData->m_LinkedBlocks.end()); + } + } + + if (a_Chunk->GetBlock(a_RelSource) == E_BLOCK_REDSTONE_REPEATER_ON) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); + a_Chunk->SetIsRedstoneDirty(true); + return true; } - ), Data->m_LinkedBlocks.end());*/ + ), Data->m_LinkedBlocks.end()); }; while (!BlocksPotentiallyUnpowered.empty()) @@ -2187,7 +2207,7 @@ void cIncrementalRedstoneSimulator::SetInvalidMiddleBlock(int a_RelMiddleX, int } std::vector BlocksPotentiallyUnpowered; - auto Data = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData(); + auto Data = static_cast(a_Chunk->GetRedstoneSimulatorData()); Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ](const sLinkedPoweredBlocks & itr) { @@ -2223,76 +2243,40 @@ void cIncrementalRedstoneSimulator::SetInvalidMiddleBlock(int a_RelMiddleX, int -cIncrementalRedstoneSimulator::eRedstoneDirection cIncrementalRedstoneSimulator::GetWireDirection(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) +bool cIncrementalRedstoneSimulator::IsLeverOn(NIBBLETYPE a_BlockMeta) +{ + // Extract the ON bit from metadata and return if true if it is set: + return ((a_BlockMeta & 0x8) == 0x8); +} + + + + + +std::vector cIncrementalRedstoneSimulator::GetAdjacentChunks(const Vector3i & a_RelBlockPosition, cChunk * a_Chunk) { - int Dir = REDSTONE_NONE; + std::vector AdjacentChunks; + AdjacentChunks.reserve(2); // At most bordering two chunks; reserve that many - BLOCKTYPE NegX = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, NegX)) + // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks + if ((a_RelBlockPosition.x % cChunkDef::Width) <= 1) { - if (IsPotentialSource(NegX)) - { - Dir |= (REDSTONE_X_POS); - } + AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x - 2, a_RelBlockPosition.z)); } - - BLOCKTYPE PosX = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, PosX)) + if ((a_RelBlockPosition.x % cChunkDef::Width) >= 14) { - if (IsPotentialSource(PosX)) - { - Dir |= (REDSTONE_X_NEG); - } + AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x + 2, a_RelBlockPosition.z)); } - - BLOCKTYPE NegZ = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, NegZ)) + if ((a_RelBlockPosition.z % cChunkDef::Width) <= 1) { - if (IsPotentialSource(NegZ)) - { - if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner - { - Dir ^= REDSTONE_X_POS; - Dir |= REDSTONE_X_NEG; - } - if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner - { - Dir ^= REDSTONE_X_NEG; - Dir |= REDSTONE_X_POS; - } - Dir |= REDSTONE_Z_POS; - } + AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z - 2)); } - - BLOCKTYPE PosZ = 0; - if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, PosZ)) + if ((a_RelBlockPosition.z % cChunkDef::Width) >= 14) { - if (IsPotentialSource(PosZ)) - { - if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner - { - Dir ^= REDSTONE_X_POS; - Dir |= REDSTONE_X_NEG; - } - if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner - { - Dir ^= REDSTONE_X_NEG; - Dir |= REDSTONE_X_POS; - } - Dir |= REDSTONE_Z_NEG; - } + AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z + 2)); } - return (eRedstoneDirection)Dir; -} - - - - -bool cIncrementalRedstoneSimulator::IsLeverOn(NIBBLETYPE a_BlockMeta) -{ - // Extract the ON bit from metadata and return if true if it is set: - return ((a_BlockMeta & 0x8) == 0x8); + return AdjacentChunks; } -- cgit v1.2.3 From 151fe0fc595d580264fdb0d394c74ed9fa6df514 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 26 Apr 2015 01:16:23 +0100 Subject: Fixed wire consuming much resources --- src/Simulator/IncrementalRedstoneSimulator.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 40829757d..f297f7701 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -640,16 +640,26 @@ void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vectorGetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); + auto & PoweredBlocks = ((cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position + sPoweredBlocks RC; + RC.a_BlockPos = AdjustedPos; + RC.a_SourcePos = a_Entry.first + Vector3i((a_Entry.second->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width, 0, (a_Entry.second->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width); + RC.a_PowerLevel = MyPower - 1; + if ((Neighbour->GetBlock(AdjustedPos) == E_BLOCK_REDSTONE_WIRE) && (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) { - sPoweredBlocks RC; - RC.a_BlockPos = AdjustedPos; - RC.a_SourcePos = a_Entry.first + Vector3i((a_Entry.second->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width, 0, (a_Entry.second->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width); - RC.a_PowerLevel = MyPower - 1; - ((cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks.emplace_back(RC); // We need to insert the value into the chunk who owns the block position + auto Position = std::find_if(PoweredBlocks.begin(), PoweredBlocks.end(), [RC](const sPoweredBlocks & itr) { return itr.a_BlockPos == RC.a_BlockPos && itr.a_SourcePos == RC.a_SourcePos; }); + if (Position != PoweredBlocks.end()) + { + Position->a_PowerLevel = RC.a_PowerLevel; + } + else + { + PoweredBlocks.emplace_back(RC); - Neighbour->SetIsRedstoneDirty(true); - m_Chunk->SetIsRedstoneDirty(true); + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); + } Neighbour->SetMeta(AdjustedPos.x, AdjustedPos.y, AdjustedPos.z, MyPower - 1); a_PotentialWireList.emplace_back(std::make_pair(AdjustedPos, Neighbour)); -- cgit v1.2.3 From bef7cce5ede018a4b0bc0f03cbd7a3a87f066d4c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 1 May 2015 22:55:43 +0100 Subject: Improved wires and repeaters * Fixed repeater cross-chunk power detection + Re-implemented horizontal wire cut-off checking --- src/Simulator/IncrementalRedstoneSimulator.cpp | 223 +++++++++++++++++-------- 1 file changed, 150 insertions(+), 73 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index f297f7701..095fefe7b 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -94,7 +94,7 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition auto & SimulatedPlayerToggleableBlocks = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks; if ( DoesIgnorePlayerToggle(Block) && - std::find_if(SimulatedPlayerToggleableBlocks.begin(),SimulatedPlayerToggleableBlocks.end(), + std::find_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), [a_RelBlockPosition](const sSimulatedPlayerToggleableList & itr){ return itr.a_RelBlockPos == a_RelBlockPosition; }) == SimulatedPlayerToggleableBlocks.end() ) { @@ -549,28 +549,28 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re auto Current = PotentialWireList.back(); PotentialWireList.pop_back(); FindAndPowerBorderingWires(PotentialWireList, Current); - } + } } else if (MyPower == 1) { return; } + // Wire still powered, power blocks beneath and in direction of facing MyPower--; - // Wire still powered, power blocks beneath SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower); SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, MyPower); int BorderingMechanismCount = 0; bool RepeaterPresent = false; - Vector3i VectorOffset; + Vector3i OffsetToPower; - for (auto OffsetIdx = 0; OffsetIdx != ARRAYCOUNT(VectorOffsets); ++OffsetIdx) + for (const auto & Offset : VectorOffsets) { BLOCKTYPE Block; - auto Offset = RelBlock + VectorOffsets[OffsetIdx]; - if (m_Chunk->UnboundedRelGetBlockType(Offset.x, Offset.y, Offset.z, Block)) + Vector3i AdjustedOffset = RelBlock + Offset; + if (m_Chunk->UnboundedRelGetBlockType(AdjustedOffset.x, AdjustedOffset.y, AdjustedOffset.z, Block)) { switch (Block) { @@ -581,9 +581,9 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re { // TODO: only if wire is actually connected to repeater (repeater facing right way) RepeaterPresent = true; - VectorOffset = { -VectorOffsets[OffsetIdx].x, VectorOffsets[OffsetIdx].y, -VectorOffsets[OffsetIdx].z }; + OffsetToPower = { -Offset.x, Offset.y, -Offset.z }; // Negate to obtain offset in opposite direction since wire powers that way } - SetBlockPowered(Offset, RelBlock, MyPower); + SetBlockPowered(AdjustedOffset, RelBlock, MyPower); } case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: @@ -591,7 +591,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re BorderingMechanismCount++; if (!RepeaterPresent) { - VectorOffset = { -VectorOffsets[OffsetIdx].x, VectorOffsets[OffsetIdx].y, -VectorOffsets[OffsetIdx].z }; + OffsetToPower = { -Offset.x, Offset.y, -Offset.z }; } } default: break; @@ -602,11 +602,15 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re if (BorderingMechanismCount == 0) { SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + for (const auto & BlockFaceOffset : BlockFaceOffsets) + { + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BlockFaceOffset, MyPower); + } } else if (BorderingMechanismCount == 1) { - eBlockFace Face = BlockFaceOffsets[std::distance(VectorOffsets, std::find(VectorOffsets, VectorOffsets + ARRAYCOUNT(VectorOffsets), VectorOffset))]; - SetBlockPowered(RelBlock + VectorOffset, RelBlock, MyPower); + eBlockFace Face = BlockFaceOffsets[std::distance(VectorOffsets, std::find(VectorOffsets, VectorOffsets + ARRAYCOUNT(VectorOffsets), OffsetToPower))]; + SetBlockPowered(RelBlock + OffsetToPower, RelBlock, MyPower); SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Face, MyPower); } } @@ -617,52 +621,82 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vector> & a_PotentialWireList, const std::pair & a_Entry) { - std::vector> NewAdditions; - const Vector3i Offsets[] = + static const Vector3i LevelOffsets[] = // Wires on same level { - { 1, 0, 0 }, /* Wires on same level start */ + { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, - { 0, 0, -1 }, /* Wires on same level stop */ - { 1, 1, 0 }, /* Wires one higher, surrounding self start */ + { 0, 0, -1 }, + }; + static const Vector3i HigherOffsets[] = // Wires one higher, surrounding self + { + { 1, 1, 0 }, { -1, 1, 0 }, { 0, 1, 1 }, - { 0, 1, -1 }, /* Wires one higher, surrounding self stop */ - { 1, -1, 0 }, /* Wires one lower, surrounding self start */ + { 0, 1, -1 }, + }; + static const Vector3i LowerOffsets[] = // Wires one lower, surrounding self + { + { 1, -1, 0 }, { -1, -1, 0 }, { 0, -1, 1 }, - { 0, -1, -1 }, /* Wires one lower, surrounding self stop */ + { 0, -1, -1 }, }; - for (auto Offset : Offsets) + for (auto Offset : LevelOffsets) { auto AdjustedPos = a_Entry.first + Offset; auto Neighbour = a_Entry.second->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); - auto & PoweredBlocks = ((cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position - sPoweredBlocks RC; - RC.a_BlockPos = AdjustedPos; - RC.a_SourcePos = a_Entry.first + Vector3i((a_Entry.second->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width, 0, (a_Entry.second->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width); - RC.a_PowerLevel = MyPower - 1; + if ((Neighbour == nullptr) || !Neighbour->IsValid()) + { + return; + } if ((Neighbour->GetBlock(AdjustedPos) == E_BLOCK_REDSTONE_WIRE) && (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) { - auto Position = std::find_if(PoweredBlocks.begin(), PoweredBlocks.end(), [RC](const sPoweredBlocks & itr) { return itr.a_BlockPos == RC.a_BlockPos && itr.a_SourcePos == RC.a_SourcePos; }); - if (Position != PoweredBlocks.end()) - { - Position->a_PowerLevel = RC.a_PowerLevel; - } - else - { - PoweredBlocks.emplace_back(RC); + PowerBorderingWires(a_PotentialWireList, a_Entry, AdjustedPos, Neighbour, MyPower); + } + } - Neighbour->SetIsRedstoneDirty(true); - m_Chunk->SetIsRedstoneDirty(true); - } + for (auto Offset : HigherOffsets) + { + auto AdjustedPos = a_Entry.first + Offset; + auto Neighbour = a_Entry.second->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); + auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); + + if ((Neighbour == nullptr) || !Neighbour->IsValid()) + { + return; + } + + if ( + (Neighbour->GetBlock(AdjustedPos) == E_BLOCK_REDSTONE_WIRE) && + (!cBlockInfo::FullyOccupiesVoxel(a_Entry.second->GetBlock(a_Entry.first.x, a_Entry.first.y + 1, a_Entry.first.z))) && + (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) + { + PowerBorderingWires(a_PotentialWireList, a_Entry, AdjustedPos, Neighbour, MyPower); + } + } + + for (auto Offset : LowerOffsets) + { + auto AdjustedPos = a_Entry.first + Offset; + auto Neighbour = a_Entry.second->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); + auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); - Neighbour->SetMeta(AdjustedPos.x, AdjustedPos.y, AdjustedPos.z, MyPower - 1); - a_PotentialWireList.emplace_back(std::make_pair(AdjustedPos, Neighbour)); + if ((Neighbour == nullptr) || !Neighbour->IsValid()) + { + return; + } + + if ( + (Neighbour->GetBlock(AdjustedPos) == E_BLOCK_REDSTONE_WIRE) && + (!cBlockInfo::FullyOccupiesVoxel(Neighbour->GetBlock(AdjustedPos.x, AdjustedPos.y + 1, AdjustedPos.z))) && + (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) + { + PowerBorderingWires(a_PotentialWireList, a_Entry, AdjustedPos, Neighbour, MyPower); } } } @@ -671,6 +705,35 @@ void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vector> & a_PotentialWireList, const std::pair & a_Entry, const Vector3i & a_AdjustedPos, cChunk * a_NeighbourChunk, unsigned char a_MyPower) +{ + sPoweredBlocks RC; + RC.a_BlockPos = a_AdjustedPos; + RC.a_SourcePos = a_Entry.first + Vector3i((a_Entry.second->GetPosX() - a_NeighbourChunk->GetPosX()) * cChunkDef::Width, 0, (a_Entry.second->GetPosZ() - a_NeighbourChunk->GetPosZ()) * cChunkDef::Width); + RC.a_PowerLevel = a_MyPower - 1; + + auto & PoweredBlocks = static_cast(a_NeighbourChunk->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position + auto Position = std::find_if(PoweredBlocks.begin(), PoweredBlocks.end(), [RC](const sPoweredBlocks & itr) { return itr.a_BlockPos == RC.a_BlockPos && itr.a_SourcePos == RC.a_SourcePos; }); + if (Position != PoweredBlocks.end()) + { + Position->a_PowerLevel = RC.a_PowerLevel; + } + else + { + PoweredBlocks.emplace_back(RC); + + a_NeighbourChunk->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); + } + + a_NeighbourChunk->SetMeta(RC.a_BlockPos.x, RC.a_BlockPos.y, RC.a_BlockPos.z, RC.a_PowerLevel); + a_PotentialWireList.emplace_back(std::make_pair(RC.a_BlockPos, a_NeighbourChunk)); +} + + + + + void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { auto Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); @@ -708,12 +771,12 @@ void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, in auto RearPower = std::max(CCB.m_SignalStrength, IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetRearCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3)), m_Chunk)); if ((Meta & 0x4) == 0x4) - { // Subtraction mode - Power = RearPower - HighestSidePower; + { // Subtraction mode + Power = std::max(static_cast(RearPower - HighestSidePower), std::numeric_limits::min()); } else - { // Comparison mode - Power = std::max(HighestSidePower, RearPower); + { // Comparison mode + Power = (std::max(HighestSidePower, RearPower) == HighestSidePower) ? 0 : RearPower; } if (Power > 0) @@ -1562,7 +1625,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel case 0x0: { // Flip the coords to check the back of the repeater - if (itr.a_SourcePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1)))) + if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1))) { return true; } @@ -1570,7 +1633,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x1: { - if (itr.a_SourcePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ)))) + if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ))) { return true; } @@ -1578,7 +1641,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x2: { - if (itr.a_SourcePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1)))) + if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1))) { return true; } @@ -1586,7 +1649,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x3: { - if (itr.a_SourcePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ)))) + if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ))) { return true; } @@ -1606,7 +1669,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel { case 0x0: { - if (itr.a_MiddlePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1)))) + if (itr.a_MiddlePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1))) { return true; } @@ -1614,7 +1677,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x1: { - if (itr.a_MiddlePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ)))) + if (itr.a_MiddlePos.Equals(Vector3i(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ))) { return true; } @@ -1622,7 +1685,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x2: { - if (itr.a_MiddlePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1)))) + if (itr.a_MiddlePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1))) { return true; } @@ -1630,7 +1693,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x3: { - if (itr.a_MiddlePos.Equals(AdjustRelativeCoords(Vector3i(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ)))) + if (itr.a_MiddlePos.Equals(Vector3i(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ))) { return true; } @@ -2104,6 +2167,10 @@ bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk) { + if ((a_Chunk == nullptr) || !a_Chunk->IsValid()) + { + return; + } std::vector> BlocksPotentiallyUnpowered = { std::make_pair(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ), a_Chunk) }; auto UnpoweringFunction = [&BlocksPotentiallyUnpowered](cChunk * a_Chunk, const Vector3i & a_RelSource) @@ -2126,21 +2193,22 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); BoundaryData->m_PoweredBlocks.erase(std::remove_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sPoweredBlocks & itr) - { - if (itr.a_SourcePos != ChunkAdjustedSource) { - return false; + if (itr.a_SourcePos != ChunkAdjustedSource) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); + BoundaryChunk->SetIsRedstoneDirty(true); + return true; } - - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); - BoundaryChunk->SetIsRedstoneDirty(true); - return true; - } ), BoundaryData->m_PoweredBlocks.end()); } } - if (a_Chunk->GetBlock(a_RelSource) == E_BLOCK_REDSTONE_REPEATER_ON) + BLOCKTYPE RepeaterType; + if (a_Chunk->UnboundedRelGetBlockType(a_RelSource.x, a_RelSource.y, a_RelSource.z, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) { return false; } @@ -2168,21 +2236,22 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); BoundaryData->m_LinkedBlocks.erase(std::remove_if(BoundaryData->m_LinkedBlocks.begin(), BoundaryData->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sLinkedPoweredBlocks & itr) - { - if (itr.a_SourcePos != ChunkAdjustedSource) { - return false; + if (itr.a_SourcePos != ChunkAdjustedSource) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); + BoundaryChunk->SetIsRedstoneDirty(true); + return true; } - - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); - BoundaryChunk->SetIsRedstoneDirty(true); - return true; - } ), BoundaryData->m_LinkedBlocks.end()); } } - if (a_Chunk->GetBlock(a_RelSource) == E_BLOCK_REDSTONE_REPEATER_ON) + BLOCKTYPE RepeaterType; + if (a_Chunk->UnboundedRelGetBlockType(a_RelSource.x, a_RelSource.y, a_RelSource.z, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) { return false; } @@ -2268,22 +2337,30 @@ std::vector cIncrementalRedstoneSimulator::GetAdjacentChunks(const Vec std::vector AdjacentChunks; AdjacentChunks.reserve(2); // At most bordering two chunks; reserve that many + auto CheckAndEmplace = [&AdjacentChunks](cChunk * a_Chunk) + { + if ((a_Chunk != nullptr) && a_Chunk->IsValid()) + { + AdjacentChunks.emplace_back(a_Chunk); + } + }; + // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks if ((a_RelBlockPosition.x % cChunkDef::Width) <= 1) { - AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x - 2, a_RelBlockPosition.z)); + CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x - 2, a_RelBlockPosition.z)); } if ((a_RelBlockPosition.x % cChunkDef::Width) >= 14) { - AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x + 2, a_RelBlockPosition.z)); + CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x + 2, a_RelBlockPosition.z)); } if ((a_RelBlockPosition.z % cChunkDef::Width) <= 1) { - AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z - 2)); + CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z - 2)); } if ((a_RelBlockPosition.z % cChunkDef::Width) >= 14) { - AdjacentChunks.emplace_back(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z + 2)); + CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z + 2)); } return AdjacentChunks; -- cgit v1.2.3 From 6a831c0b6fdf984f0cdf1d30995c9e602bdd41a5 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 26 May 2015 23:30:50 +0100 Subject: Improved link power behaviour --- src/Simulator/IncrementalRedstoneSimulator.cpp | 248 ++++++++++++------------- 1 file changed, 116 insertions(+), 132 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 095fefe7b..29ea65407 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -713,7 +713,7 @@ void cIncrementalRedstoneSimulator::PowerBorderingWires(std::vector(a_NeighbourChunk->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position - auto Position = std::find_if(PoweredBlocks.begin(), PoweredBlocks.end(), [RC](const sPoweredBlocks & itr) { return itr.a_BlockPos == RC.a_BlockPos && itr.a_SourcePos == RC.a_SourcePos; }); + auto Position = std::find_if(PoweredBlocks.begin(), PoweredBlocks.end(), [RC](const sPoweredBlocks & itr) { return ((itr.a_BlockPos == RC.a_BlockPos) && (itr.a_SourcePos == RC.a_SourcePos)); }); if (Position != PoweredBlocks.end()) { Position->a_PowerLevel = RC.a_PowerLevel; @@ -819,19 +819,50 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int */ // Create a variable holding my meta to avoid multiple lookups. - NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); + NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ); bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON); - if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta)) // If we're locked, change nothing. Otherwise: + if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta)) // If we're locked, change nothing. Otherwise: { - bool IsSelfPowered = IsRepeaterPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta); + bool IsSelfPowered = IsRepeaterPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta); if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked. { - QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true); + QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta, true); } else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked. { - QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false); + QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta, false); + } + } + + if (IsOn) + { + switch (Meta & 0x3) // We only want the direction (bottom) bits + { + case 0x0: + { + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM); + break; + } + case 0x1: + { + SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP); + break; + } + case 0x2: + { + SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP); + break; + } + case 0x3: + { + SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); + SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM); + break; + } } } } @@ -855,34 +886,6 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays() { m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); } - - switch (Meta & 0x3) // We only want the direction (bottom) bits - { - case 0x0: - { - SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ - 1, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZM); - break; - } - case 0x1: - { - SetBlockPowered(RelBlockX + 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XP); - break; - } - case 0x2: - { - SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ + 1, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZP); - break; - } - case 0x3: - { - SetBlockPowered(RelBlockX - 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ); - SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XM); - break; - } - } } else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF) { @@ -2027,16 +2030,16 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(Vector3i a_RelBlockPosition, a_RelSourcePosition.z += (m_Chunk->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width; auto & Powered = static_cast(Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position - for (auto itr = Powered.begin(); itr != Powered.end(); ++itr) + for (auto & itr : Powered) { - if ((itr->a_BlockPos == a_RelBlockPosition) && (itr->a_SourcePos == a_RelSourcePosition)) + if ((itr.a_BlockPos == a_RelBlockPosition) && (itr.a_SourcePos == a_RelSourcePosition)) { - if (itr->a_PowerLevel != a_PowerLevel) + if (itr.a_PowerLevel != a_PowerLevel) { // Update power level, don't add a new listing Neighbour->SetIsRedstoneDirty(true); m_Chunk->SetIsRedstoneDirty(true); - itr->a_PowerLevel = a_PowerLevel; + itr.a_PowerLevel = a_PowerLevel; } return; } @@ -2068,11 +2071,14 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( } cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); - m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelMiddleX, a_RelMiddleZ); if ((Neighbour == nullptr) || !Neighbour->IsValid()) { return; } + a_RelMiddleX += (m_Chunk->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width; + a_RelMiddleZ += (m_Chunk->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width; + a_RelSourceX += (m_Chunk->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width; + a_RelSourceZ += (m_Chunk->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width; auto & Linked = static_cast(Neighbour->GetRedstoneSimulatorData())->m_LinkedBlocks; for (auto & itr : Linked) // Check linked powered list @@ -2083,8 +2089,13 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( itr.a_SourcePos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ)) ) { - // Check for duplicates, update power level, don't add a new listing - itr.a_PowerLevel = a_PowerLevel; + if (itr.a_PowerLevel != a_PowerLevel) + { + // Update power level, don't add a new listing + Neighbour->SetIsRedstoneDirty(true); + m_Chunk->SetIsRedstoneDirty(true); + itr.a_PowerLevel = a_PowerLevel; + } return; } } @@ -2175,6 +2186,12 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R auto UnpoweringFunction = [&BlocksPotentiallyUnpowered](cChunk * a_Chunk, const Vector3i & a_RelSource) { + BLOCKTYPE RepeaterType; + if (a_Chunk->UnboundedRelGetBlockType(a_RelSource.x, a_RelSource.y, a_RelSource.z, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) + { + return; + } + auto Data = static_cast(a_Chunk->GetRedstoneSimulatorData()); Data->m_PoweredBlocks.erase(std::remove_if(Data->m_PoweredBlocks.begin(), Data->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sPoweredBlocks & itr) { @@ -2183,42 +2200,12 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R return false; } - for (const auto & BoundaryChunk : GetAdjacentChunks(a_RelSource, a_Chunk)) - { - if (BoundaryChunk != a_Chunk) - { - Vector3i ChunkAdjustedSource = a_RelSource; - ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; - ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; - - auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); - BoundaryData->m_PoweredBlocks.erase(std::remove_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sPoweredBlocks & itr) - { - if (itr.a_SourcePos != ChunkAdjustedSource) - { - return false; - } - - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); - BoundaryChunk->SetIsRedstoneDirty(true); - return true; - } - ), BoundaryData->m_PoweredBlocks.end()); - } - } - - BLOCKTYPE RepeaterType; - if (a_Chunk->UnboundedRelGetBlockType(a_RelSource.x, a_RelSource.y, a_RelSource.z, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) - { - return false; - } - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); a_Chunk->SetIsRedstoneDirty(true); return true; } ), Data->m_PoweredBlocks.end()); - + Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sLinkedPoweredBlocks & itr) { if (itr.a_SourcePos != a_RelSource) @@ -2226,41 +2213,27 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R return false; } - for (const auto & BoundaryChunk : GetAdjacentChunks(a_RelSource, a_Chunk)) - { - if (BoundaryChunk != a_Chunk) - { - Vector3i ChunkAdjustedSource = a_RelSource; - ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; - ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; - - auto BoundaryData = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)BoundaryChunk->GetRedstoneSimulatorData(); - BoundaryData->m_LinkedBlocks.erase(std::remove_if(BoundaryData->m_LinkedBlocks.begin(), BoundaryData->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedSource](const sLinkedPoweredBlocks & itr) - { - if (itr.a_SourcePos != ChunkAdjustedSource) - { - return false; - } - - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); - BoundaryChunk->SetIsRedstoneDirty(true); - return true; - } - ), BoundaryData->m_LinkedBlocks.end()); - } - } - - BLOCKTYPE RepeaterType; - if (a_Chunk->UnboundedRelGetBlockType(a_RelSource.x, a_RelSource.y, a_RelSource.z, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) - { - return false; - } - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); a_Chunk->SetIsRedstoneDirty(true); return true; } ), Data->m_LinkedBlocks.end()); + + for (const auto & BoundaryChunk : GetAdjacentChunks(a_RelSource, a_Chunk)) + { + auto BoundaryData = static_cast(BoundaryChunk->GetRedstoneSimulatorData()); + Vector3i ChunkAdjustedSource = a_RelSource; + ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; + ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; + + if ( + (std::find_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [ChunkAdjustedSource](const sPoweredBlocks & itr) { return (itr.a_SourcePos == ChunkAdjustedSource); }) != BoundaryData->m_PoweredBlocks.end()) || + (std::find_if(BoundaryData->m_LinkedBlocks.begin(), BoundaryData->m_LinkedBlocks.end(), [ChunkAdjustedSource](const sLinkedPoweredBlocks & itr) { return (itr.a_SourcePos == ChunkAdjustedSource); }) != BoundaryData->m_LinkedBlocks.end()) + ) + { + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(ChunkAdjustedSource, BoundaryChunk)); + } + } }; while (!BlocksPotentiallyUnpowered.empty()) @@ -2275,45 +2248,56 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R -void cIncrementalRedstoneSimulator::SetInvalidMiddleBlock(int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, cChunk * a_Chunk, bool a_IsFirstCall) +void cIncrementalRedstoneSimulator::SetInvalidMiddleBlock(int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, cChunk * a_Chunk) { - if (!a_IsFirstCall) // The neighbouring chunks passed when this parameter is false may be invalid - { - if ((a_Chunk == nullptr) || !a_Chunk->IsValid()) - { - return; - } - } - - std::vector BlocksPotentiallyUnpowered; + std::vector> BlocksPotentiallyUnpowered; auto Data = static_cast(a_Chunk->GetRedstoneSimulatorData()); Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ](const sLinkedPoweredBlocks & itr) { - if (itr.a_MiddlePos.Equals(Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ))) + if (!itr.a_MiddlePos.Equals(Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ))) { - BlocksPotentiallyUnpowered.emplace_back(itr.a_BlockPos); - a_Chunk->SetIsRedstoneDirty(true); - return true; + return false; } - return false; + + for (const auto & BoundaryChunk : GetAdjacentChunks(Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ), a_Chunk)) + { + Vector3i ChunkAdjustedMiddlePos = Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ); + ChunkAdjustedMiddlePos.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; + ChunkAdjustedMiddlePos.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; + + auto BoundaryData = static_cast(BoundaryChunk->GetRedstoneSimulatorData()); + BoundaryData->m_LinkedBlocks.erase(std::remove_if(BoundaryData->m_LinkedBlocks.begin(), BoundaryData->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedMiddlePos](const sLinkedPoweredBlocks & itr) + { + if (itr.a_MiddlePos != ChunkAdjustedMiddlePos) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); + BoundaryChunk->SetIsRedstoneDirty(true); + return true; + } + ), BoundaryData->m_LinkedBlocks.end()); + } + + BLOCKTYPE RepeaterType; + if (a_Chunk->UnboundedRelGetBlockType(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) + { + return false; + } + + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); + a_Chunk->SetIsRedstoneDirty(true); + return true; } ), Data->m_LinkedBlocks.end()); - if (a_IsFirstCall && /*AreCoordsOnChunkBoundary(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ)*/1) - { - // +- 2 to accomodate linked powered blocks - SetInvalidMiddleBlock(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, a_Chunk->GetRelNeighborChunk(a_RelMiddleX - 2, a_RelMiddleZ), false); - SetInvalidMiddleBlock(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, a_Chunk->GetRelNeighborChunk(a_RelMiddleX + 2, a_RelMiddleZ), false); - SetInvalidMiddleBlock(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, a_Chunk->GetRelNeighborChunk(a_RelMiddleX, a_RelMiddleZ - 2), false); - SetInvalidMiddleBlock(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, a_Chunk->GetRelNeighborChunk(a_RelMiddleX, a_RelMiddleZ + 2), false); - } - for (const auto & itr : BlocksPotentiallyUnpowered) { - if (!AreCoordsPowered(itr.x, itr.y, itr.z)) + if (!AreCoordsPowered(itr.first.x, itr.first.y, itr.first.z)) { - SetSourceUnpowered(itr.x, itr.y, itr.z, a_Chunk->GetRelNeighborChunk(itr.x, itr.z)); + SetSourceUnpowered(itr.first.x, itr.first.y, itr.first.z, itr.second); } } } @@ -2346,19 +2330,19 @@ std::vector cIncrementalRedstoneSimulator::GetAdjacentChunks(const Vec }; // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks - if ((a_RelBlockPosition.x % cChunkDef::Width) <= 1) + if (a_RelBlockPosition.x <= 1) { CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x - 2, a_RelBlockPosition.z)); } - if ((a_RelBlockPosition.x % cChunkDef::Width) >= 14) + if (a_RelBlockPosition.x >= 14) { CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x + 2, a_RelBlockPosition.z)); } - if ((a_RelBlockPosition.z % cChunkDef::Width) <= 1) + if (a_RelBlockPosition.z <= 1) { CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z - 2)); } - if ((a_RelBlockPosition.z % cChunkDef::Width) >= 14) + if (a_RelBlockPosition.z >= 14) { CheckAndEmplace(a_Chunk->GetRelNeighborChunk(a_RelBlockPosition.x, a_RelBlockPosition.z + 2)); } -- cgit v1.2.3 From 171c59a01b07b7513cf7a281bbcb141e8182d274 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 2 Jun 2015 13:29:52 +0100 Subject: Changed appropriate containers to unordered_map Thanks to @worktycho for guidance! * Potential speed improvements --- src/Simulator/IncrementalRedstoneSimulator.cpp | 212 +++++++++---------------- 1 file changed, 78 insertions(+), 134 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 29ea65407..f60106fac 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -92,67 +92,45 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition } auto & SimulatedPlayerToggleableBlocks = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks; - if ( - DoesIgnorePlayerToggle(Block) && - std::find_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), - [a_RelBlockPosition](const sSimulatedPlayerToggleableList & itr){ return itr.a_RelBlockPos == a_RelBlockPosition; }) == SimulatedPlayerToggleableBlocks.end() - ) + if (DoesIgnorePlayerToggle(Block)) { - // We have arrived here; no block must be in list - add one - sSimulatedPlayerToggleableList RC; - RC.a_RelBlockPos = a_RelBlockPosition; - RC.WasLastStatePowered = AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk); - // Initialise the toggleable blocks list so that trapdoors etc. aren't reset on restart (#1887) - SimulatedPlayerToggleableBlocks.emplace_back(RC); + SimulatedPlayerToggleableBlocks.emplace( + a_RelBlockPosition, + AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) + ); // This map won't insert if key already present, so no need to check + } + else + { + SimulatedPlayerToggleableBlocks.erase(a_RelBlockPosition); } - SimulatedPlayerToggleableBlocks.erase(std::remove_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), [a_RelBlockPosition, Block, this](const sSimulatedPlayerToggleableList & itr) - { - return (itr.a_RelBlockPos == a_RelBlockPosition) && !DoesIgnorePlayerToggle(Block); - } - ), SimulatedPlayerToggleableBlocks.end()); - - auto & RepeatersDelayList = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList; - RepeatersDelayList.erase(std::remove_if(RepeatersDelayList.begin(), RepeatersDelayList.end(), [a_RelBlockPosition, Block](const sRepeatersDelayList & itr) - { - return (itr.a_RelBlockPos == a_RelBlockPosition) && (Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF); - } - ), RepeatersDelayList.end()); - - auto & RedstoneSimulatorChunkData = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData; - for (auto & itr : RedstoneSimulatorChunkData) + if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { - if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z)) // We are at an entry matching the current (changed) block - { - if (!IsAllowedBlock(Block)) - { - itr.DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list - } - else - { - itr.DataTwo = false; - itr.Data = Block; // Update block information - } - return; - } + static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList.erase(a_RelBlockPosition); } + auto & RedstoneSimulatorChunkData = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData; + auto Iterator = RedstoneSimulatorChunkData.find(a_RelBlockPosition); if (!IsAllowedBlock(Block)) { + if (Iterator != RedstoneSimulatorChunkData.end()) + { + Iterator->second.second = true; // The new blocktype is not redstone; it must be queued to be removed from this list + } return; } - - auto & QueuedData = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_QueuedChunkData; - for (const auto & itr : QueuedData) + else { - if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z)) + if (Iterator != RedstoneSimulatorChunkData.end()) { - // Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data + Iterator->second.second = false; + Iterator->second.first = Block; // Update block information return; } } - QueuedData.emplace_back(cCoordWithBlockAndBool(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, false)); + + RedstoneSimulatorChunkData.emplace(a_RelBlockPosition, std::make_pair(Block, false)); } @@ -167,19 +145,11 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt m_RedstoneSimulatorChunkData = new cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData(); a_Chunk->SetRedstoneSimulatorData(m_RedstoneSimulatorChunkData); } - if (m_RedstoneSimulatorChunkData->m_ChunkData.empty() && static_cast(a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData.empty()) + if (m_RedstoneSimulatorChunkData->m_ChunkData.empty()) { return; } - m_RedstoneSimulatorChunkData->m_ChunkData.insert( - m_RedstoneSimulatorChunkData->m_ChunkData.end(), - m_RedstoneSimulatorChunkData->m_QueuedChunkData.begin(), - m_RedstoneSimulatorChunkData->m_QueuedChunkData.end() - ); - - m_RedstoneSimulatorChunkData->m_QueuedChunkData.clear(); - m_PoweredBlocks = &m_RedstoneSimulatorChunkData->m_PoweredBlocks; m_RepeatersDelayList = &m_RedstoneSimulatorChunkData->m_RepeatersDelayList; m_SimulatedPlayerToggleableBlocks = &m_RedstoneSimulatorChunkData->m_SimulatedPlayerToggleableBlocks; @@ -199,24 +169,24 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt for (auto dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.begin(); dataitr != m_RedstoneSimulatorChunkData->m_ChunkData.end();) { - if (dataitr->DataTwo) + if (dataitr->second.second) { dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr); continue; } - switch (dataitr->Data) + switch (dataitr->second.first) { - case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: { - HandlePressurePlate(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandlePressurePlate(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } default: break; @@ -224,23 +194,23 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt if (ShouldUpdateSimulateOnceBlocks) { - switch (dataitr->Data) + switch (dataitr->second.first) { - case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break; - case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break; + case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TNT: HandleTNT(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; + case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_POWERED_RAIL: { - HandleRail(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRail(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_ACACIA_DOOR: @@ -251,7 +221,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt case E_BLOCK_WOODEN_DOOR: case E_BLOCK_IRON_DOOR: { - HandleDoor(dataitr->x, dataitr->y, dataitr->z); + HandleDoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_ACACIA_FENCE_GATE: @@ -261,49 +231,49 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_SPRUCE_FENCE_GATE: { - HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); + HandleFenceGate(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: { - HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRedstoneLamp(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: { - HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z); + HandleDropSpenser(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_PISTON: case E_BLOCK_STICKY_PISTON: { - HandlePiston(dataitr->x, dataitr->y, dataitr->z); + HandlePiston(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: { - HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRedstoneRepeater(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: { - HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data); + HandleRedstoneTorch(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first); break; } case E_BLOCK_STONE_BUTTON: case E_BLOCK_WOODEN_BUTTON: { - HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z); + HandleRedstoneButton(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_INACTIVE_COMPARATOR: { - HandleRedstoneComparator(dataitr->x, dataitr->y, dataitr->z); + HandleRedstoneComparator(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; } default: break; @@ -872,32 +842,29 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays() { for (auto itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();) { - if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks? + if (itr->second.a_ElapsedTicks >= itr->second.a_DelayTicks) // Has the elapsed ticks reached the target ticks? { - int RelBlockX = itr->a_RelBlockPos.x; - int RelBlockY = itr->a_RelBlockPos.y; - int RelBlockZ = itr->a_RelBlockPos.z; BLOCKTYPE Block; NIBBLETYPE Meta; - m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta); - if (itr->ShouldPowerOn) + m_Chunk->GetBlockTypeMeta(itr->first.x, itr->first.y, itr->first.z, Block, Meta); + if (itr->second.ShouldPowerOn) { if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance { - m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); + m_Chunk->SetBlock(itr->first, E_BLOCK_REDSTONE_REPEATER_ON, Meta); } } else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF) { - m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta); + m_Chunk->SetBlock(itr->first.x, itr->first.y, itr->first.z, E_BLOCK_REDSTONE_REPEATER_OFF, Meta); } itr = m_RepeatersDelayList->erase(itr); } else { - LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); - itr->a_ElapsedTicks++; - itr++; + LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->first.x, itr->first.y, itr->first.z, itr->second.a_ElapsedTicks, itr->second.a_DelayTicks); + itr->second.a_ElapsedTicks++; + ++itr; } } } @@ -1871,9 +1838,9 @@ bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_Re { for (const auto & itr : *m_SimulatedPlayerToggleableBlocks) { - if (itr.a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + if (itr.first.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) { - if (itr.WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current? + if (itr.second != IsCurrentStatePowered) // Was the last power state different to the current? { return false; // It was, coordinates are no longer simulated } @@ -2116,60 +2083,37 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered( void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool a_WasLastStatePowered) { - for (auto & itr : *m_SimulatedPlayerToggleableBlocks) - { - if (!itr.a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - continue; - } - - // Update listing - itr.WasLastStatePowered = a_WasLastStatePowered; - return; - } - - // We have arrived here; no block must be in list - add one - sSimulatedPlayerToggleableList RC; - RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); - RC.WasLastStatePowered = a_WasLastStatePowered; - m_SimulatedPlayerToggleableBlocks->emplace_back(RC); + m_SimulatedPlayerToggleableBlocks->operator[](Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) = a_WasLastStatePowered; } -bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn) +void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool a_ShouldPowerOn) { - for (auto itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr) - { - if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) - { - if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry - { - return false; - } - - // Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit - itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description - itr->a_ElapsedTicks = 0; - itr->ShouldPowerOn = ShouldPowerOn; - return false; - } - } - - // Self not in list, add self to list sRepeatersDelayList RC; - RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.) // Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; - RC.a_ElapsedTicks = 0; - RC.ShouldPowerOn = ShouldPowerOn; - m_RepeatersDelayList->emplace_back(RC); - return true; + RC.ShouldPowerOn = a_ShouldPowerOn; + + auto Result = m_RepeatersDelayList->emplace(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), RC); + if (!Result.second) + { + // Key exists + if (a_ShouldPowerOn == Result.first->second.ShouldPowerOn) + { + // We are queued already for the same thing, don't replace entry + return; + } + + Result.first->second.a_DelayTicks = RC.a_DelayTicks; + Result.first->second.a_ElapsedTicks = 0; + Result.first->second.ShouldPowerOn = a_ShouldPowerOn; + } } -- cgit v1.2.3 From a6983ec3c9cfef029c5f86f06b7737f2bce45203 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 3 Jun 2015 21:42:09 +0100 Subject: Improved link unpowering speed Also fixed compile errors --- src/Simulator/IncrementalRedstoneSimulator.cpp | 89 ++++++++++++-------------- 1 file changed, 41 insertions(+), 48 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index f60106fac..dd4386814 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -2128,47 +2128,47 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R } std::vector> BlocksPotentiallyUnpowered = { std::make_pair(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ), a_Chunk) }; - auto UnpoweringFunction = [&BlocksPotentiallyUnpowered](cChunk * a_Chunk, const Vector3i & a_RelSource) + auto UnpoweringFunction = [&BlocksPotentiallyUnpowered](cChunk * a_LambdaChunk, const Vector3i & a_RelSource) { BLOCKTYPE RepeaterType; - if (a_Chunk->UnboundedRelGetBlockType(a_RelSource.x, a_RelSource.y, a_RelSource.z, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) + if (a_LambdaChunk->UnboundedRelGetBlockType(a_RelSource.x, a_RelSource.y, a_RelSource.z, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) { return; } - auto Data = static_cast(a_Chunk->GetRedstoneSimulatorData()); - Data->m_PoweredBlocks.erase(std::remove_if(Data->m_PoweredBlocks.begin(), Data->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sPoweredBlocks & itr) + auto Data = static_cast(a_LambdaChunk->GetRedstoneSimulatorData()); + Data->m_PoweredBlocks.erase(std::remove_if(Data->m_PoweredBlocks.begin(), Data->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, a_LambdaChunk, a_RelSource](const sPoweredBlocks & itr) { if (itr.a_SourcePos != a_RelSource) { return false; } - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); - a_Chunk->SetIsRedstoneDirty(true); + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_LambdaChunk)); + a_LambdaChunk->SetIsRedstoneDirty(true); return true; } ), Data->m_PoweredBlocks.end()); - Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelSource](const sLinkedPoweredBlocks & itr) + Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_LambdaChunk, a_RelSource](const sLinkedPoweredBlocks & itr) { if (itr.a_SourcePos != a_RelSource) { return false; } - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); - a_Chunk->SetIsRedstoneDirty(true); + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_LambdaChunk)); + a_LambdaChunk->SetIsRedstoneDirty(true); return true; } ), Data->m_LinkedBlocks.end()); - for (const auto & BoundaryChunk : GetAdjacentChunks(a_RelSource, a_Chunk)) + for (const auto & BoundaryChunk : GetAdjacentChunks(a_RelSource, a_LambdaChunk)) { auto BoundaryData = static_cast(BoundaryChunk->GetRedstoneSimulatorData()); Vector3i ChunkAdjustedSource = a_RelSource; - ChunkAdjustedSource.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; - ChunkAdjustedSource.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; + ChunkAdjustedSource.x += (a_LambdaChunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; + ChunkAdjustedSource.z += (a_LambdaChunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; if ( (std::find_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [ChunkAdjustedSource](const sPoweredBlocks & itr) { return (itr.a_SourcePos == ChunkAdjustedSource); }) != BoundaryData->m_PoweredBlocks.end()) || @@ -2197,45 +2197,38 @@ void cIncrementalRedstoneSimulator::SetInvalidMiddleBlock(int a_RelMiddleX, int std::vector> BlocksPotentiallyUnpowered; auto Data = static_cast(a_Chunk->GetRedstoneSimulatorData()); - Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_Chunk, a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ](const sLinkedPoweredBlocks & itr) - { - if (!itr.a_MiddlePos.Equals(Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ))) - { - return false; - } + BLOCKTYPE RepeaterType; + if (a_Chunk->UnboundedRelGetBlockType(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) + { + return; + } - for (const auto & BoundaryChunk : GetAdjacentChunks(Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ), a_Chunk)) + auto MiddleBlockUnpoweringFunction = [&BlocksPotentiallyUnpowered](cChunk * a_LambdaChunk, const Vector3i & a_RelMiddle) + { + auto Data = static_cast(a_LambdaChunk->GetRedstoneSimulatorData()); + Data->m_LinkedBlocks.erase(std::remove_if(Data->m_LinkedBlocks.begin(), Data->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, a_LambdaChunk, a_RelMiddle](const sLinkedPoweredBlocks & itr) { - Vector3i ChunkAdjustedMiddlePos = Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ); - ChunkAdjustedMiddlePos.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; - ChunkAdjustedMiddlePos.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; + if (itr.a_MiddlePos != a_RelMiddle) + { + return false; + } - auto BoundaryData = static_cast(BoundaryChunk->GetRedstoneSimulatorData()); - BoundaryData->m_LinkedBlocks.erase(std::remove_if(BoundaryData->m_LinkedBlocks.begin(), BoundaryData->m_LinkedBlocks.end(), [&BlocksPotentiallyUnpowered, BoundaryChunk, ChunkAdjustedMiddlePos](const sLinkedPoweredBlocks & itr) - { - if (itr.a_MiddlePos != ChunkAdjustedMiddlePos) - { - return false; - } - - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, BoundaryChunk)); - BoundaryChunk->SetIsRedstoneDirty(true); - return true; - } - ), BoundaryData->m_LinkedBlocks.end()); + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_LambdaChunk)); + a_LambdaChunk->SetIsRedstoneDirty(true); + return true; } + ), Data->m_LinkedBlocks.end()); + }; - BLOCKTYPE RepeaterType; - if (a_Chunk->UnboundedRelGetBlockType(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) - { - return false; - } + MiddleBlockUnpoweringFunction(a_Chunk, Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ)); + for (const auto & BoundaryChunk : GetAdjacentChunks(Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ), a_Chunk)) + { + Vector3i ChunkAdjustedMiddlePos = Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ); + ChunkAdjustedMiddlePos.x += (a_Chunk->GetPosX() - BoundaryChunk->GetPosX()) * cChunkDef::Width; + ChunkAdjustedMiddlePos.z += (a_Chunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_Chunk)); - a_Chunk->SetIsRedstoneDirty(true); - return true; - } - ), Data->m_LinkedBlocks.end()); + MiddleBlockUnpoweringFunction(a_Chunk, Vector3i(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ)); + } for (const auto & itr : BlocksPotentiallyUnpowered) { @@ -2265,11 +2258,11 @@ std::vector cIncrementalRedstoneSimulator::GetAdjacentChunks(const Vec std::vector AdjacentChunks; AdjacentChunks.reserve(2); // At most bordering two chunks; reserve that many - auto CheckAndEmplace = [&AdjacentChunks](cChunk * a_Chunk) + auto CheckAndEmplace = [&AdjacentChunks](cChunk * a_LambdaChunk) { - if ((a_Chunk != nullptr) && a_Chunk->IsValid()) + if ((a_LambdaChunk != nullptr) && a_LambdaChunk->IsValid()) { - AdjacentChunks.emplace_back(a_Chunk); + AdjacentChunks.emplace_back(a_LambdaChunk); } }; -- cgit v1.2.3 From ed6c37febc3e5f6bd491317946aae11db73c2d04 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 6 Jun 2015 12:30:08 +0100 Subject: Use emplace to construct structures --- src/Simulator/IncrementalRedstoneSimulator.cpp | 87 ++++++++++++-------------- 1 file changed, 39 insertions(+), 48 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index dd4386814..75fb314dc 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -518,7 +518,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re { auto Current = PotentialWireList.back(); PotentialWireList.pop_back(); - FindAndPowerBorderingWires(PotentialWireList, Current); + FindAndPowerBorderingWires(PotentialWireList, Current.first, Current.second); } } else if (MyPower == 1) @@ -589,7 +589,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re -void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vector> & a_PotentialWireList, const std::pair & a_Entry) +void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vector> & a_PotentialWireList, const Vector3i & a_EntryRelBlockPosition, cChunk * a_EntryChunk) { static const Vector3i LevelOffsets[] = // Wires on same level { @@ -615,9 +615,9 @@ void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vectorGetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); - auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); + auto AdjustedPos = a_EntryRelBlockPosition + Offset; + auto Neighbour = a_EntryChunk->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); + auto MyPower = IsWirePowered(a_EntryRelBlockPosition, a_EntryChunk); if ((Neighbour == nullptr) || !Neighbour->IsValid()) { @@ -626,15 +626,15 @@ void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vectorGetBlock(AdjustedPos) == E_BLOCK_REDSTONE_WIRE) && (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) { - PowerBorderingWires(a_PotentialWireList, a_Entry, AdjustedPos, Neighbour, MyPower); + PowerBorderingWires(a_PotentialWireList, a_EntryRelBlockPosition, a_EntryChunk, AdjustedPos, Neighbour, MyPower); } } for (auto Offset : HigherOffsets) { - auto AdjustedPos = a_Entry.first + Offset; - auto Neighbour = a_Entry.second->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); - auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); + auto AdjustedPos = a_EntryRelBlockPosition + Offset; + auto Neighbour = a_EntryChunk->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); + auto MyPower = IsWirePowered(a_EntryRelBlockPosition, a_EntryChunk); if ((Neighbour == nullptr) || !Neighbour->IsValid()) { @@ -643,18 +643,18 @@ void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vectorGetBlock(AdjustedPos) == E_BLOCK_REDSTONE_WIRE) && - (!cBlockInfo::FullyOccupiesVoxel(a_Entry.second->GetBlock(a_Entry.first.x, a_Entry.first.y + 1, a_Entry.first.z))) && + (!cBlockInfo::FullyOccupiesVoxel(a_EntryChunk->GetBlock(a_EntryRelBlockPosition.x, a_EntryRelBlockPosition.y + 1, a_EntryRelBlockPosition.z))) && (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) { - PowerBorderingWires(a_PotentialWireList, a_Entry, AdjustedPos, Neighbour, MyPower); + PowerBorderingWires(a_PotentialWireList, a_EntryRelBlockPosition, a_EntryChunk, AdjustedPos, Neighbour, MyPower); } } for (auto Offset : LowerOffsets) { - auto AdjustedPos = a_Entry.first + Offset; - auto Neighbour = a_Entry.second->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); - auto MyPower = IsWirePowered(a_Entry.first, a_Entry.second); + auto AdjustedPos = a_EntryRelBlockPosition + Offset; + auto Neighbour = a_EntryChunk->GetRelNeighborChunkAdjustCoords(AdjustedPos.x, AdjustedPos.z); + auto MyPower = IsWirePowered(a_EntryRelBlockPosition, a_EntryChunk); if ((Neighbour == nullptr) || !Neighbour->IsValid()) { @@ -666,7 +666,7 @@ void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vectorGetBlock(AdjustedPos.x, AdjustedPos.y + 1, AdjustedPos.z))) && (MyPower > 1) && (MyPower > IsWirePowered(AdjustedPos, Neighbour))) { - PowerBorderingWires(a_PotentialWireList, a_Entry, AdjustedPos, Neighbour, MyPower); + PowerBorderingWires(a_PotentialWireList, a_EntryRelBlockPosition, a_EntryChunk, AdjustedPos, Neighbour, MyPower); } } } @@ -675,29 +675,25 @@ void cIncrementalRedstoneSimulator::FindAndPowerBorderingWires(std::vector> & a_PotentialWireList, const std::pair & a_Entry, const Vector3i & a_AdjustedPos, cChunk * a_NeighbourChunk, unsigned char a_MyPower) +void cIncrementalRedstoneSimulator::PowerBorderingWires(std::vector> & a_PotentialWireList, const Vector3i & a_EntryRelSourcePosition, cChunk * a_EntryChunk, const Vector3i & a_AdjustedPos, cChunk * a_NeighbourChunk, unsigned char a_MyPower) { - sPoweredBlocks RC; - RC.a_BlockPos = a_AdjustedPos; - RC.a_SourcePos = a_Entry.first + Vector3i((a_Entry.second->GetPosX() - a_NeighbourChunk->GetPosX()) * cChunkDef::Width, 0, (a_Entry.second->GetPosZ() - a_NeighbourChunk->GetPosZ()) * cChunkDef::Width); - RC.a_PowerLevel = a_MyPower - 1; - + auto SourcePos = a_EntryRelSourcePosition + Vector3i((a_EntryChunk->GetPosX() - a_NeighbourChunk->GetPosX()) * cChunkDef::Width, 0, (a_EntryChunk->GetPosZ() - a_NeighbourChunk->GetPosZ()) * cChunkDef::Width); auto & PoweredBlocks = static_cast(a_NeighbourChunk->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position - auto Position = std::find_if(PoweredBlocks.begin(), PoweredBlocks.end(), [RC](const sPoweredBlocks & itr) { return ((itr.a_BlockPos == RC.a_BlockPos) && (itr.a_SourcePos == RC.a_SourcePos)); }); + auto Position = std::find_if(PoweredBlocks.begin(), PoweredBlocks.end(), [a_AdjustedPos, SourcePos, a_MyPower](const sPoweredBlocks & itr) { return ((itr.m_BlockPos == a_AdjustedPos) && (itr.m_SourcePos == SourcePos)); }); if (Position != PoweredBlocks.end()) { - Position->a_PowerLevel = RC.a_PowerLevel; + Position->m_PowerLevel = a_MyPower - 1; } else { - PoweredBlocks.emplace_back(RC); + PoweredBlocks.emplace_back(a_AdjustedPos, SourcePos, a_MyPower - 1); a_NeighbourChunk->SetIsRedstoneDirty(true); m_Chunk->SetIsRedstoneDirty(true); } - a_NeighbourChunk->SetMeta(RC.a_BlockPos.x, RC.a_BlockPos.y, RC.a_BlockPos.z, RC.a_PowerLevel); - a_PotentialWireList.emplace_back(std::make_pair(RC.a_BlockPos, a_NeighbourChunk)); + a_NeighbourChunk->SetMeta(a_AdjustedPos.x, a_AdjustedPos.y, a_AdjustedPos.z, a_MyPower - 1); + a_PotentialWireList.emplace_back(std::make_pair(a_AdjustedPos, a_NeighbourChunk)); } @@ -1562,7 +1558,7 @@ bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, in // Torches want to access neighbour's data when on a wall, hence the extra chunk parameter const auto & Data = static_cast(a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks; - return std::find_if(Data.begin(), Data.end(), [a_RelBlockX, a_RelBlockY, a_RelBlockZ](const sPoweredBlocks & itr) { return itr.a_BlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }) != Data.end(); + return std::find_if(Data.begin(), Data.end(), [a_RelBlockX, a_RelBlockY, a_RelBlockZ](const sPoweredBlocks & itr) { return itr.m_BlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }) != Data.end(); } @@ -1585,7 +1581,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel for (const auto & itr : *m_PoweredBlocks) { - if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + if (!itr.m_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) { continue; } @@ -1595,7 +1591,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel case 0x0: { // Flip the coords to check the back of the repeater - if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1))) + if (itr.m_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1))) { return true; } @@ -1603,7 +1599,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x1: { - if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ))) + if (itr.m_SourcePos.Equals(Vector3i(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ))) { return true; } @@ -1611,7 +1607,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x2: { - if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1))) + if (itr.m_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1))) { return true; } @@ -1619,7 +1615,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel } case 0x3: { - if (itr.a_SourcePos.Equals(Vector3i(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ))) + if (itr.m_SourcePos.Equals(Vector3i(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ))) { return true; } @@ -1764,7 +1760,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl for (const auto & itr : *m_PoweredBlocks) { - if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) + if (!itr.m_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))) { continue; } @@ -1772,7 +1768,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl int X = a_RelBlockX, Z = a_RelBlockZ; AddFaceDirection(X, a_RelBlockY, Z, Face); - if (!itr.a_SourcePos.Equals(AdjustRelativeCoords(Vector3i(X, a_RelBlockY, Z)))) + if (!itr.m_SourcePos.Equals(AdjustRelativeCoords(Vector3i(X, a_RelBlockY, Z)))) { return true; } @@ -1805,11 +1801,11 @@ unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPo for (const auto & itr : static_cast(a_Chunk->GetRedstoneSimulatorData())->m_PoweredBlocks) // Check powered list { - if (itr.a_BlockPos != a_RelBlockPosition) + if (itr.m_BlockPos != a_RelBlockPosition) { continue; } - PowerLevel = std::max(itr.a_PowerLevel, PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block) + PowerLevel = std::max(itr.m_PowerLevel, PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block) } for (const auto & itr : static_cast(a_Chunk->GetRedstoneSimulatorData())->m_LinkedBlocks) // Check linked powered list @@ -1999,24 +1995,20 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(Vector3i a_RelBlockPosition, auto & Powered = static_cast(Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position for (auto & itr : Powered) { - if ((itr.a_BlockPos == a_RelBlockPosition) && (itr.a_SourcePos == a_RelSourcePosition)) + if ((itr.m_BlockPos == a_RelBlockPosition) && (itr.m_SourcePos == a_RelSourcePosition)) { - if (itr.a_PowerLevel != a_PowerLevel) + if (itr.m_PowerLevel != a_PowerLevel) { // Update power level, don't add a new listing Neighbour->SetIsRedstoneDirty(true); m_Chunk->SetIsRedstoneDirty(true); - itr.a_PowerLevel = a_PowerLevel; + itr.m_PowerLevel = a_PowerLevel; } return; } } - sPoweredBlocks RC; - RC.a_BlockPos = a_RelBlockPosition; - RC.a_SourcePos = a_RelSourcePosition; - RC.a_PowerLevel = a_PowerLevel; - Powered.emplace_back(RC); + Powered.emplace_back(a_RelBlockPosition, a_RelSourcePosition, a_PowerLevel); Neighbour->SetIsRedstoneDirty(true); m_Chunk->SetIsRedstoneDirty(true); } @@ -2139,12 +2131,12 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R auto Data = static_cast(a_LambdaChunk->GetRedstoneSimulatorData()); Data->m_PoweredBlocks.erase(std::remove_if(Data->m_PoweredBlocks.begin(), Data->m_PoweredBlocks.end(), [&BlocksPotentiallyUnpowered, a_LambdaChunk, a_RelSource](const sPoweredBlocks & itr) { - if (itr.a_SourcePos != a_RelSource) + if (itr.m_SourcePos != a_RelSource) { return false; } - BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.a_BlockPos, a_LambdaChunk)); + BlocksPotentiallyUnpowered.emplace_back(std::make_pair(itr.m_BlockPos, a_LambdaChunk)); a_LambdaChunk->SetIsRedstoneDirty(true); return true; } @@ -2171,7 +2163,7 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R ChunkAdjustedSource.z += (a_LambdaChunk->GetPosZ() - BoundaryChunk->GetPosZ()) * cChunkDef::Width; if ( - (std::find_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [ChunkAdjustedSource](const sPoweredBlocks & itr) { return (itr.a_SourcePos == ChunkAdjustedSource); }) != BoundaryData->m_PoweredBlocks.end()) || + (std::find_if(BoundaryData->m_PoweredBlocks.begin(), BoundaryData->m_PoweredBlocks.end(), [ChunkAdjustedSource](const sPoweredBlocks & itr) { return (itr.m_SourcePos == ChunkAdjustedSource); }) != BoundaryData->m_PoweredBlocks.end()) || (std::find_if(BoundaryData->m_LinkedBlocks.begin(), BoundaryData->m_LinkedBlocks.end(), [ChunkAdjustedSource](const sLinkedPoweredBlocks & itr) { return (itr.a_SourcePos == ChunkAdjustedSource); }) != BoundaryData->m_LinkedBlocks.end()) ) { @@ -2195,7 +2187,6 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R void cIncrementalRedstoneSimulator::SetInvalidMiddleBlock(int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, cChunk * a_Chunk) { std::vector> BlocksPotentiallyUnpowered; - auto Data = static_cast(a_Chunk->GetRedstoneSimulatorData()); BLOCKTYPE RepeaterType; if (a_Chunk->UnboundedRelGetBlockType(a_RelMiddleX, a_RelMiddleY, a_RelMiddleZ, RepeaterType) && (RepeaterType == E_BLOCK_REDSTONE_REPEATER_ON)) -- cgit v1.2.3 From 061866616d44c127871e95eb8dd6c713bcd3a2c8 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 7 Jun 2015 12:03:28 +0100 Subject: Added moar comments --- src/Simulator/IncrementalRedstoneSimulator.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp') diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index 75fb314dc..7d9cc93b2 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -90,15 +90,16 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition // DO NOT touch our chunk's data structure if we are being called with coordinates from another chunk - this one caused me massive grief :P return; } + auto RedstoneSimulatorData = static_cast(a_OriginalChunk->GetRedstoneSimulatorData()); - auto & SimulatedPlayerToggleableBlocks = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks; + auto & SimulatedPlayerToggleableBlocks = RedstoneSimulatorData->m_SimulatedPlayerToggleableBlocks; if (DoesIgnorePlayerToggle(Block)) { // Initialise the toggleable blocks list so that trapdoors etc. aren't reset on restart (#1887) SimulatedPlayerToggleableBlocks.emplace( a_RelBlockPosition, AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) - ); // This map won't insert if key already present, so no need to check + ); // This map won't insert if key already present, so no need to check } else { @@ -107,10 +108,10 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF)) { - static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList.erase(a_RelBlockPosition); + RedstoneSimulatorData->m_RepeatersDelayList.erase(a_RelBlockPosition); } - auto & RedstoneSimulatorChunkData = static_cast(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData; + auto & RedstoneSimulatorChunkData = RedstoneSimulatorData->m_ChunkData; auto Iterator = RedstoneSimulatorChunkData.find(a_RelBlockPosition); if (!IsAllowedBlock(Block)) { @@ -124,7 +125,7 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition { if (Iterator != RedstoneSimulatorChunkData.end()) { - Iterator->second.second = false; + Iterator->second.second = false; // De-schedule removal from list Iterator->second.first = Block; // Update block information return; } @@ -171,11 +172,12 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt { if (dataitr->second.second) { + // Removal was scheduled - do so dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr); continue; } - switch (dataitr->second.first) + switch (dataitr->second.first) // Call the appropriate simulator for the entry's block type { case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->first.x, dataitr->first.y, dataitr->first.z); break; @@ -737,11 +739,13 @@ void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, in auto RearPower = std::max(CCB.m_SignalStrength, IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetRearCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3)), m_Chunk)); if ((Meta & 0x4) == 0x4) - { // Subtraction mode + { + // Subtraction mode Power = std::max(static_cast(RearPower - HighestSidePower), std::numeric_limits::min()); } else - { // Comparison mode + { + // Comparison mode Power = (std::max(HighestSidePower, RearPower) == HighestSidePower) ? 0 : RearPower; } -- cgit v1.2.3