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 ++++++++++--------------- src/Simulator/IncrementalRedstoneSimulator.h | 19 ++-- 2 files changed, 70 insertions(+), 94 deletions(-) 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); diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h index 65e3ff4af..903dbe82a 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.h +++ b/src/Simulator/IncrementalRedstoneSimulator.h @@ -22,7 +22,8 @@ class cIncrementalRedstoneSimulator : public: cIncrementalRedstoneSimulator(cWorld & a_World) - : cRedstoneSimulator(a_World) + : cRedstoneSimulator(a_World), + m_Chunk(nullptr) { } @@ -209,7 +210,7 @@ private: /** Removes a block from the Powered and LinkedPowered lists Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests */ - void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk, bool a_IsFirstCall = true); + void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk); void SetInvalidMiddleBlock(int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, cChunk * a_Chunk, bool a_IsFirstCall = true); /** Returns if a coordinate is powered or linked powered */ @@ -384,14 +385,14 @@ private: } } - inline static bool AreCoordsOnChunkBoundary(int a_BlockX, int a_BlockY, int a_BlockZ) + inline static Vector3i GetCoordinateAdjacentChunk(const Vector3i & a_BlockPos) { - return ( // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks - ((a_BlockX % cChunkDef::Width) <= 1) || - ((a_BlockX % cChunkDef::Width) >= 14) || - ((a_BlockZ % cChunkDef::Width) <= 1) || - ((a_BlockZ % cChunkDef::Width) >= 14) - ); + // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks + if ((a_BlockPos.x % cChunkDef::Width) <= 1) { return{ -2, 0, 0 }; } + if ((a_BlockPos.x % cChunkDef::Width) >= 14) { return{ 2, 0, 0 }; } + if ((a_BlockPos.z % cChunkDef::Width) <= 1) { return{ 0, 0, -2 }; } + if ((a_BlockPos.z % cChunkDef::Width) >= 14) { return{ 0, 0, 2 }; } + return { 0, 0, 0 }; } inline static Vector3i AdjustRelativeCoords(const Vector3i & a_RelPosition) -- cgit v1.2.3