Fix frame flood-fill to follow diagonal (stepped) ring connections
Round/octagonal rings built the normal Minecraft way step diagonally at the corners - two frame blocks touching only edge-to-edge, not face-to-face. The scanner only checked the 6 face-adjacent neighbours, so those blocks were treated as disconnected fragments and the whole ring failed to register (or only a fraction of it did). Frame discovery now flood-fills using all 26 surrounding offsets instead of just the 6 faces. The geometric chevron walk needed the same fix - its in-plane adjacency now checks 8 directions (orthogonal + diagonal) instead of 4, so stepped rings still produce a clean single-loop walk instead of falling back to evenly-spaced chevrons. Interior/iris flood-fill is intentionally left orthogonal-only: since it only ever moves face-to-face, a diagonal-only frame corner already blocks it from slipping past, so enclosure detection didn't need to change.
This commit is contained in:
@@ -19,6 +19,9 @@ Build everything with `./gradlew build`. Jars land in each module's `build/libs/
|
||||
There's no fixed size or shape - build any single connected ring out of
|
||||
`gate.frame-materials` (default: obsidian, gold block, gilded blackstone, birch/oak
|
||||
planks) with a fully sealed hollow interior. No gaps; the interior must be enclosed.
|
||||
"Connected" includes the usual diagonal stepping a round/octagonal ring needs at its
|
||||
corners (blocks touching only edge-to-edge or corner-to-corner still count), so a
|
||||
circular build doesn't need every block to share a full face with the next.
|
||||
|
||||
Chevrons aren't a separate material you place. When the gate is linked, the plugin
|
||||
flood-fills the ring, walks it in geometric order, and picks out the blocks that stick
|
||||
|
||||
+27
-4
@@ -25,6 +25,25 @@ public class GateStructureScanner {
|
||||
BlockFace.UP, BlockFace.DOWN, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST
|
||||
};
|
||||
|
||||
// Round/octagonal rings built the usual Minecraft way step diagonally at the corners - two
|
||||
// frame blocks touching only edge-to-edge (or even just corner-to-corner), not face-to-face.
|
||||
// The frame search has to follow those too, or a stepped ring gets treated as several
|
||||
// disconnected fragments instead of one structure.
|
||||
private static final int[][] ALL_26_OFFSETS = buildAll26Offsets();
|
||||
|
||||
private static int[][] buildAll26Offsets() {
|
||||
List<int[]> offsets = new ArrayList<>();
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
if (dx == 0 && dy == 0 && dz == 0) continue;
|
||||
offsets.add(new int[]{dx, dy, dz});
|
||||
}
|
||||
}
|
||||
}
|
||||
return offsets.toArray(new int[0][]);
|
||||
}
|
||||
|
||||
public static final class ScanResult {
|
||||
public final GateStructure structure; // null on failure
|
||||
public final String failureReason; // null on success
|
||||
@@ -84,8 +103,8 @@ public class GateStructureScanner {
|
||||
+ "Raise max-frame-blocks or make the frame materials more specific.");
|
||||
}
|
||||
|
||||
for (BlockFace face : NEIGHBORS) {
|
||||
Block next = cur.getRelative(face);
|
||||
for (int[] d : ALL_26_OFFSETS) {
|
||||
Block next = cur.getRelative(d[0], d[1], d[2]);
|
||||
long k = key(next);
|
||||
if (frameKeys.contains(k)) continue;
|
||||
if (isFrameMaterial(next.getType())) {
|
||||
@@ -224,14 +243,18 @@ public class GateStructureScanner {
|
||||
return chevrons.isEmpty() ? fallbackEvenlySpaced(frameBlocks) : chevrons;
|
||||
}
|
||||
|
||||
/** Walks the ring in geometric order assuming each frame block has exactly two in-plane neighbours; null if that assumption fails. */
|
||||
private static final int[][] PLANE_8_OFFSETS = {
|
||||
{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}
|
||||
};
|
||||
|
||||
/** Walks the ring in geometric order assuming each frame block has exactly two in-plane neighbours (orthogonal or diagonal, for stepped rings); null if that assumption fails. */
|
||||
private List<Block> walkRing(List<Block> frameBlocks, Map<Long, Block> plane, boolean horizontalIsX) {
|
||||
Map<Block, List<Block>> adjacency = new HashMap<>();
|
||||
for (Block b : frameBlocks) {
|
||||
int col = horizontalIsX ? b.getX() : b.getZ();
|
||||
int row = b.getY();
|
||||
List<Block> neighbors = new ArrayList<>();
|
||||
for (int[] d : new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}) {
|
||||
for (int[] d : PLANE_8_OFFSETS) {
|
||||
long k = (((long) (row + d[0])) << 32) ^ ((col + d[1]) & 0xFFFFFFFFL);
|
||||
Block n = plane.get(k);
|
||||
if (n != null && n != b) neighbors.add(n);
|
||||
|
||||
Reference in New Issue
Block a user