summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2015-03-20 23:30:20 +0100
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2015-06-06 13:21:18 +0200
commitbd484750856586bd2354be2aa6852a63fd102c1b (patch)
treea5df764903451c430ad32fde29df42effad5c4b5
parentComparators (diff)
downloadcuberite-bd484750856586bd2354be2aa6852a63fd102c1b.tar
cuberite-bd484750856586bd2354be2aa6852a63fd102c1b.tar.gz
cuberite-bd484750856586bd2354be2aa6852a63fd102c1b.tar.bz2
cuberite-bd484750856586bd2354be2aa6852a63fd102c1b.tar.lz
cuberite-bd484750856586bd2354be2aa6852a63fd102c1b.tar.xz
cuberite-bd484750856586bd2354be2aa6852a63fd102c1b.tar.zst
cuberite-bd484750856586bd2354be2aa6852a63fd102c1b.zip
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp145
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.h19
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<std::pair<Vector3i, cChunk *>> 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<Vector3i> 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)