From 1d74b9756c7fd58657430dd8ec8bfa6f241bde0c Mon Sep 17 00:00:00 2001
From: haykam821 <24855774+haykam821@users.noreply.github.com>
Date: Sun, 17 Nov 2024 11:28:10 -0500
Subject: [PATCH] Add two-dimensional connectivities
---
.../plasmid/api/util/BlockTraversal.java | 62 +++++-
.../plasmid/test/BlockTraversalTests.java | 201 ++++++++++++++++++
2 files changed, 255 insertions(+), 8 deletions(-)
create mode 100644 src/test/java/xyz/nucleoid/plasmid/test/BlockTraversalTests.java
diff --git a/src/main/java/xyz/nucleoid/plasmid/api/util/BlockTraversal.java b/src/main/java/xyz/nucleoid/plasmid/api/util/BlockTraversal.java
index c91ac2eb..c016f435 100644
--- a/src/main/java/xyz/nucleoid/plasmid/api/util/BlockTraversal.java
+++ b/src/main/java/xyz/nucleoid/plasmid/api/util/BlockTraversal.java
@@ -141,9 +141,17 @@ boolean isComplete() {
* @see 3-dimensional pixel connectivity
*/
public static final class Connectivity {
- public static final Connectivity SIX = create(Connectivity::six);
- public static final Connectivity EIGHTEEN = create(Connectivity::eighteen);
- public static final Connectivity TWENTY_SIX = create(Connectivity::twentySix);
+ public static final Connectivity SIX = create(Connectivity::generateSix);
+ public static final Connectivity EIGHTEEN = create(Connectivity::generateEighteen);
+ public static final Connectivity TWENTY_SIX = create(Connectivity::generateTwentySix);
+
+ private static final Connectivity FOUR_X = create(consumer -> generateFour(Direction.Axis.X, consumer));
+ private static final Connectivity FOUR_Y = create(consumer -> generateFour(Direction.Axis.Y, consumer));
+ private static final Connectivity FOUR_Z = create(consumer -> generateFour(Direction.Axis.Z, consumer));
+
+ private static final Connectivity EIGHT_X = create(consumer -> generateEight(Direction.Axis.X, consumer));
+ private static final Connectivity EIGHT_Y = create(consumer -> generateEight(Direction.Axis.Y, consumer));
+ private static final Connectivity EIGHT_Z = create(consumer -> generateEight(Direction.Axis.Z, consumer));
final Vec3i[] offsets;
@@ -151,20 +159,36 @@ public static final class Connectivity {
this.offsets = offsets;
}
+ public static Connectivity four(Direction.Axis orthogonalAxis) {
+ return switch (orthogonalAxis) {
+ case X -> FOUR_X;
+ case Y -> FOUR_Y;
+ case Z -> FOUR_Z;
+ };
+ }
+
+ public static Connectivity eight(Direction.Axis orthogonalAxis) {
+ return switch (orthogonalAxis) {
+ case X -> EIGHT_X;
+ case Y -> EIGHT_Y;
+ case Z -> EIGHT_Z;
+ };
+ }
+
static Connectivity create(Consumer> generator) {
var offsets = new ArrayList();
generator.accept(offsets::add);
return new Connectivity(offsets.toArray(new Vec3i[0]));
}
- private static void six(Consumer consumer) {
+ private static void generateSix(Consumer consumer) {
for (var direction : Direction.values()) {
consumer.accept(direction.getVector());
}
}
- private static void eighteen(Consumer consumer) {
- six(consumer);
+ private static void generateEighteen(Consumer consumer) {
+ generateSix(consumer);
for (int x = -1; x <= 1; x += 2) {
for (int y = -1; y <= 1; y += 2) {
@@ -175,8 +199,8 @@ private static void eighteen(Consumer consumer) {
}
}
- private static void twentySix(Consumer consumer) {
- eighteen(consumer);
+ private static void generateTwentySix(Consumer consumer) {
+ generateEighteen(consumer);
for (int z = -1; z <= 1; z += 2) {
for (int x = -1; x <= 1; x += 2) {
@@ -186,6 +210,28 @@ private static void twentySix(Consumer consumer) {
}
}
}
+
+ private static void generateFour(Direction.Axis orthogonalAxis, Consumer consumer) {
+ for (var direction : Direction.values()) {
+ if (direction.getAxis() != orthogonalAxis) {
+ consumer.accept(direction.getVector());
+ }
+ }
+ }
+
+ private static void generateEight(Direction.Axis orthogonalAxis, Consumer consumer) {
+ generateFour(orthogonalAxis, consumer);
+
+ for (int x = -1; x <= 1; x += 2) {
+ for (int y = -1; y <= 1; y += 2) {
+ consumer.accept(switch (orthogonalAxis) {
+ case X -> new BlockPos(0, x, y);
+ case Y -> new BlockPos(y, 0, x);
+ case Z -> new BlockPos(x, y, 0);
+ });
+ }
+ }
+ }
}
/**
diff --git a/src/test/java/xyz/nucleoid/plasmid/test/BlockTraversalTests.java b/src/test/java/xyz/nucleoid/plasmid/test/BlockTraversalTests.java
new file mode 100644
index 00000000..436d4e6d
--- /dev/null
+++ b/src/test/java/xyz/nucleoid/plasmid/test/BlockTraversalTests.java
@@ -0,0 +1,201 @@
+package xyz.nucleoid.plasmid.test;
+
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Direction;
+import xyz.nucleoid.plasmid.api.util.BlockTraversal;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class BlockTraversalTests {
+ @Test
+ public void testSixConnectivity() {
+ var expected = Set.of(
+ new BlockPos(-1, 0, 0),
+ new BlockPos(0, -1, 0),
+ new BlockPos(0, 0, -1),
+ new BlockPos(1, 0, 0),
+ new BlockPos(0, 1, 0),
+ new BlockPos(0, 0, 1)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.SIX);
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testEighteenConnectivity() {
+ var expected = Set.of(
+ new BlockPos(-1, 0, 0),
+ new BlockPos(0, -1, 0),
+ new BlockPos(0, 0, -1),
+ new BlockPos(1, 0, 0),
+ new BlockPos(0, 1, 0),
+ new BlockPos(0, 0, 1),
+
+ new BlockPos(-1, -1, 0),
+ new BlockPos(-1, 0, -1),
+ new BlockPos(0, -1, -1),
+ new BlockPos(1, -1, 0),
+ new BlockPos(1, 0, -1),
+ new BlockPos(0, 1, -1),
+ new BlockPos(-1, 1, 0),
+ new BlockPos(-1, 0, 1),
+ new BlockPos(0, -1, 1),
+ new BlockPos(1, 1, 0),
+ new BlockPos(1, 0, 1),
+ new BlockPos(0, 1, 1)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.EIGHTEEN);
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testTwentySixConnectivity() {
+ var expected = Set.of(
+ new BlockPos(-1, 0, 0),
+ new BlockPos(0, -1, 0),
+ new BlockPos(0, 0, -1),
+ new BlockPos(1, 0, 0),
+ new BlockPos(0, 1, 0),
+ new BlockPos(0, 0, 1),
+
+ new BlockPos(-1, -1, 0),
+ new BlockPos(-1, 0, -1),
+ new BlockPos(0, -1, -1),
+ new BlockPos(1, -1, 0),
+ new BlockPos(1, 0, -1),
+ new BlockPos(0, 1, -1),
+ new BlockPos(-1, 1, 0),
+ new BlockPos(-1, 0, 1),
+ new BlockPos(0, -1, 1),
+ new BlockPos(1, 1, 0),
+ new BlockPos(1, 0, 1),
+ new BlockPos(0, 1, 1),
+
+ new BlockPos(-1, -1, -1),
+ new BlockPos(-1, -1, 1),
+ new BlockPos(-1, 1, -1),
+ new BlockPos(-1, 1, 1),
+ new BlockPos(1, -1, -1),
+ new BlockPos(1, -1, 1),
+ new BlockPos(1, 1, -1),
+ new BlockPos(1, 1, 1)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.TWENTY_SIX);
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testFourConnectivityAxisX() {
+ var expected = Set.of(
+ new BlockPos(0, -1, 0),
+ new BlockPos(0, 1, 0),
+ new BlockPos(0, 0, -1),
+ new BlockPos(0, 0, 1)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.four(Direction.Axis.X));
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testFourConnectivityAxisY() {
+ var expected = Set.of(
+ new BlockPos(0, 0, -1),
+ new BlockPos(0, 0, 1),
+ new BlockPos(-1, 0, 0),
+ new BlockPos(1, 0, 0)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.four(Direction.Axis.Y));
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testFourConnectivityAxisZ() {
+ var expected = Set.of(
+ new BlockPos(-1, 0, 0),
+ new BlockPos(1, 0, 0),
+ new BlockPos(0, -1, 0),
+ new BlockPos(0, 1, 0)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.four(Direction.Axis.Z));
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testEightConnectivityAxisX() {
+ var expected = Set.of(
+ new BlockPos(0, -1, 0),
+ new BlockPos(0, 1, 0),
+ new BlockPos(0, 0, -1),
+ new BlockPos(0, 0, 1),
+
+ new BlockPos(0, -1, -1),
+ new BlockPos(0, -1, 1),
+ new BlockPos(0, 1, -1),
+ new BlockPos(0, 1, 1)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.eight(Direction.Axis.X));
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testEightConnectivityAxisY() {
+ var expected = Set.of(
+ new BlockPos(0, 0, -1),
+ new BlockPos(0, 0, 1),
+ new BlockPos(-1, 0, 0),
+ new BlockPos(1, 0, 0),
+
+ new BlockPos(-1, 0, -1),
+ new BlockPos(-1, 0, 1),
+ new BlockPos(1, 0, -1),
+ new BlockPos(1, 0, 1)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.eight(Direction.Axis.Y));
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ @Test
+ public void testEightConnectivityAxisZ() {
+ var expected = Set.of(
+ new BlockPos(-1, 0, 0),
+ new BlockPos(1, 0, 0),
+ new BlockPos(0, -1, 0),
+ new BlockPos(0, 1, 0),
+
+ new BlockPos(-1, -1, 0),
+ new BlockPos(-1, 1, 0),
+ new BlockPos(1, -1, 0),
+ new BlockPos(1, 1, 0)
+ );
+
+ var traversal = BlockTraversal.create().connectivity(BlockTraversal.Connectivity.eight(Direction.Axis.Z));
+ assertSingleTraversalVisits(expected, BlockPos.ORIGIN, traversal);
+ }
+
+ private void assertSingleTraversalVisits(Set expected, BlockPos origin, BlockTraversal traversal) {
+ Set actual = new HashSet<>();
+
+ traversal.accept(origin, (pos, fromPos, depth) -> {
+ if (depth >= 1) {
+ actual.add(pos.toImmutable());
+ return BlockTraversal.Result.TERMINATE;
+ }
+
+ return BlockTraversal.Result.CONTINUE;
+ });
+
+ assertEquals(expected, actual);
+ }
+}