summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2015-04-26 01:38:41 +0200
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2015-06-06 13:21:19 +0200
commit84534dfeb288dd12d998f3f192ee162a1def5367 (patch)
treea8debc1723cafc6066d46edfc02888218ba7cb4d
parentProvides improvements to redstone wire (diff)
downloadcuberite-84534dfeb288dd12d998f3f192ee162a1def5367.tar
cuberite-84534dfeb288dd12d998f3f192ee162a1def5367.tar.gz
cuberite-84534dfeb288dd12d998f3f192ee162a1def5367.tar.bz2
cuberite-84534dfeb288dd12d998f3f192ee162a1def5367.tar.lz
cuberite-84534dfeb288dd12d998f3f192ee162a1def5367.tar.xz
cuberite-84534dfeb288dd12d998f3f192ee162a1def5367.tar.zst
cuberite-84534dfeb288dd12d998f3f192ee162a1def5367.zip
-rw-r--r--src/ChunkDef.h13
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp550
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.h69
-rw-r--r--src/World.cpp2
4 files changed, 323 insertions, 311 deletions
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index fb3451db1..a1273bd23 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -96,6 +96,19 @@ public:
a_Z = a_Z - a_ChunkZ * Width;
}
+ inline static Vector3i AbsoluteToRelative(Vector3i a_BlockPosition)
+ {
+ int ChunkX, ChunkZ;
+ BlockToChunk(a_BlockPosition.x, a_BlockPosition.z, ChunkX, ChunkZ);
+
+ return {a_BlockPosition.x - ChunkX * Width, a_BlockPosition.y, a_BlockPosition.z - ChunkZ * Width};
+ }
+
+ inline static Vector3i AbsoluteToRelative(Vector3i a_BlockPosition, int a_ChunkX, int a_ChunkZ)
+ {
+ return {a_BlockPosition.x - a_ChunkX * Width, a_BlockPosition.y, a_BlockPosition.z - a_ChunkZ * Width};
+ }
+
/** Converts relative block coordinates into absolute coordinates with a known chunk location */
inline static Vector3i RelativeToAbsolute(const Vector3i & a_RelBlockPosition, int a_ChunkX, int a_ChunkZ)
{
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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<std::pair<Vector3i, cChunk *>> 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<std::pair<Vector3i, cChunk *>> & a_PotentialWireList, const std::pair<Vector3i, cChunk *> & a_Entry)
+{
+ std::vector<std::pair<Vector3i, cChunk *>> 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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<cIncrementalRedstoneSimulatorChunkData *>(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<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 == 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<cIncrementalRedstoneSimulatorChunkData *>(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<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)
@@ -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<Vector3i> BlocksPotentiallyUnpowered;
- auto Data = (cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)a_Chunk->GetRedstoneSimulatorData();
+ auto Data = static_cast<cIncrementalRedstoneSimulatorChunkData *>(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<cChunk *> cIncrementalRedstoneSimulator::GetAdjacentChunks(const Vector3i & a_RelBlockPosition, cChunk * a_Chunk)
{
- int Dir = REDSTONE_NONE;
+ std::vector<cChunk *> 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;
}
diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h
index 903dbe82a..c383b6a0b 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.h
+++ b/src/Simulator/IncrementalRedstoneSimulator.h
@@ -3,6 +3,7 @@
#include "RedstoneSimulator.h"
#include "BlockEntities/RedstonePoweredEntity.h"
+#include <bitset>
class cWorld;
class cChunk;
@@ -37,15 +38,14 @@ public:
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); }
virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
- enum eRedstoneDirection
+ enum eRedstoneWireDirectionBitfieldPositions
{
- REDSTONE_NONE = 0,
- REDSTONE_X_POS = 0x1,
- REDSTONE_X_NEG = 0x2,
- REDSTONE_Z_POS = 0x4,
- REDSTONE_Z_NEG = 0x8,
+ eWbpXP = 0,
+ eWbpXN = 1,
+ eWbpZP = 2,
+ eWbpZN = 3,
};
- eRedstoneDirection GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ);
+ std::bitset<4> GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ);
private:
@@ -108,8 +108,9 @@ private:
SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks;
RepeatersDelayList * m_RepeatersDelayList;
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override { RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk); }
- void RedstoneAddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk, cChunk * a_OtherChunk = nullptr);
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
+
+ void AddBlock(const Vector3i & a_BlockPosition, cChunk * a_Chunk, cChunk * a_OtherChunk = nullptr);
cChunk * m_Chunk;
// We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly
@@ -192,6 +193,9 @@ private:
void SetBlockPowered(Vector3i a_RelBlockPosition, Vector3i a_RelSourcePosition, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL) { SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ), a_PowerLevel); }
+ /** Recursively searches for a wire path and powers everything that should be powered */
+ void FindAndPowerBorderingWires(std::vector<std::pair<Vector3i, cChunk *>> & a_PotentialWireList, const std::pair<Vector3i, cChunk *> & a_Entry);
+
/** Marks a block as being powered through another block */
void SetBlockLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
@@ -214,13 +218,13 @@ private:
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 */
- bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
+ bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk); }
/** Returns if a coordinate is in the directly powered blocks list */
- bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk);
+ static bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk);
/** Returns if a coordinate is in the indirectly powered blocks list */
- bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ static bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk);
/** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered);
@@ -236,7 +240,7 @@ private:
/** Returns if a wire is powered
The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
- unsigned char IsWirePowered(Vector3i a_RelBlockPosition);
+ static unsigned char IsWirePowered(Vector3i a_RelBlockPosition, cChunk * a_Chunk);
/** Handles delayed updates to repeaters **/
void HandleRedstoneRepeaterDelays(void);
@@ -249,14 +253,14 @@ private:
/** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
- inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); }
+ inline static bool IsViableMiddleBlock(BLOCKTYPE a_Block) { return cBlockInfo::FullyOccupiesVoxel(a_Block); }
/** Returns if a block is a mechanism (something that accepts power and does something)
Used by torches to determine if they power a block whilst not standing on the ground
*/
- inline static bool IsMechanism(BLOCKTYPE Block)
+ inline static bool IsMechanism(BLOCKTYPE a_Block)
{
- switch (Block)
+ switch (a_Block)
{
case E_BLOCK_ACACIA_DOOR:
case E_BLOCK_ACACIA_FENCE_GATE:
@@ -298,9 +302,9 @@ private:
}
/** Returns if a block has the potential to output power */
- inline static bool IsPotentialSource(BLOCKTYPE Block)
+ inline static bool IsPotentialSource(BLOCKTYPE a_Block)
{
- switch (Block)
+ switch (a_Block)
{
case E_BLOCK_DETECTOR_RAIL:
case E_BLOCK_DAYLIGHT_SENSOR:
@@ -326,9 +330,9 @@ private:
}
/** Returns if a block is any sort of redstone device */
- inline static bool IsRedstone(BLOCKTYPE Block)
+ inline static bool IsRedstone(BLOCKTYPE a_Block)
{
- switch (Block)
+ switch (a_Block)
{
// All redstone devices, please alpha sort
case E_BLOCK_ACACIA_DOOR:
@@ -385,16 +389,27 @@ private:
}
}
- inline static Vector3i GetCoordinateAdjacentChunk(const Vector3i & a_BlockPos)
+ inline static bool DoesIgnorePlayerToggle(BLOCKTYPE a_Block)
{
- // 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 };
+ switch (a_Block)
+ {
+ case E_BLOCK_ACACIA_FENCE_GATE:
+ case E_BLOCK_BIRCH_FENCE_GATE:
+ case E_BLOCK_DARK_OAK_FENCE_GATE:
+ case E_BLOCK_FENCE_GATE:
+ case E_BLOCK_JUNGLE_FENCE_GATE:
+ case E_BLOCK_SPRUCE_FENCE_GATE:
+ case E_BLOCK_IRON_TRAPDOOR:
+ case E_BLOCK_TRAPDOOR:
+ {
+ return true;
+ }
+ default: return false;
+ }
}
+ inline static std::vector<cChunk *> GetAdjacentChunks(const Vector3i & a_RelBlockPosition, cChunk * a_Chunk);
+
inline static Vector3i AdjustRelativeCoords(const Vector3i & a_RelPosition)
{
if (
diff --git a/src/World.cpp b/src/World.cpp
index f7d2165c7..cf2c35816 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2964,7 +2964,7 @@ bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Op
return false;
}
- bool IsOpen = (Meta & 0x4) > 0;
+ bool IsOpen = (Meta & 0x4) != 0;
if (a_Open != IsOpen)
{
SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta ^ 0x4);