diff --git a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h index 27e5a965c..e7666f560 100644 --- a/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h +++ b/src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h @@ -42,20 +42,22 @@ public: cVector3iArray GetTerracingConnectionOffsets(cWorld & a_World, const Vector3i a_Position) const { - cVector3iArray RelativePositions; - auto YPTerraceBlock = a_World.GetBlock(a_Position + OffsetYP()); - bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock); + auto RelativePositions = GetRelativeLaterals(); + const auto YPTerraceBlock = a_World.GetBlock(a_Position + OffsetYP()); + const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock); for (const auto & Adjacent : GetRelativeLaterals()) { if ( + // A block above us blocks all YP terracing, so the check is static in the loop !IsYPTerracingBlocked && (a_World.GetBlock(a_Position + Adjacent + OffsetYP()) == E_BLOCK_REDSTONE_WIRE) - ) + ) { RelativePositions.emplace_back(Adjacent + OffsetYP()); } - auto YMTerraceBlock = a_World.GetBlock(a_Position + Adjacent); + + const auto YMTerraceBlock = a_World.GetBlock(a_Position + Adjacent); if ( // IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent) (!cBlockInfo::IsSolid(YMTerraceBlock) || cBlockInfo::IsTransparent(YMTerraceBlock)) && @@ -83,31 +85,55 @@ public: a_Meta++; } - if ((a_QueryPosition != (a_Position + OffsetYM())) && !IsDirectlyConnectingMechanism( a_QueryBlockType, a_Meta, a_QueryPosition - a_Position)) + // Wires always deliver power to the block underneath, and any directly connecting mechanisms + if ( + (a_QueryPosition != (a_Position + OffsetYM())) && + !IsDirectlyConnectingMechanism(a_QueryBlockType, a_World.GetBlockMeta(a_QueryPosition), a_QueryPosition - a_Position) + ) { + /* + Okay, we do not directly connect to the wire. + If there are no DC mechanisms at all, the wire powers all laterals. Great, we fall out the loop. + If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism. + The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing towards us. + If there is more than one DC, no non-DCs are powered. + */ + Vector3i PotentialOffset; bool FoundOneBorderingMechanism = false; - for (const auto & Offset : StaticAppend(GetRelativeLaterals(), GetTerracingConnectionOffsets(a_World, a_Position))) + for (const auto & Offset : GetTerracingConnectionOffsets(a_World, a_Position)) { - if (IsDirectlyConnectingMechanism(a_World.GetBlock(Offset + a_Position), a_Meta, Offset)) + BLOCKTYPE Block; + NIBBLETYPE Meta; + + if ( + !a_World.GetBlockTypeMeta(Offset + a_Position, Block, Meta) || + !IsDirectlyConnectingMechanism(Block, Meta, Offset) + ) { - if (FoundOneBorderingMechanism) - { - return 0; - } - else - { - FoundOneBorderingMechanism = true; - PotentialOffset = { -Offset.x, 0, -Offset.z }; - } + continue; } + + if (FoundOneBorderingMechanism) + { + // Case 3 + return 0; + } + + // Potential case 2 + FoundOneBorderingMechanism = true; + PotentialOffset = { -Offset.x, 0, -Offset.z }; } if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset))) { + // Case 2 fail return 0; } + + // Case 1 + // Case 2 success } return (a_Meta != 0) ? --a_Meta : a_Meta;