Wip floaters

This commit is contained in:
Brian Neumann-Fopiano
2026-04-23 21:29:23 -04:00
parent ce29b70618
commit 1968ef2f2c
13 changed files with 639 additions and 342 deletions
@@ -1,11 +1,43 @@
package art.arcane.iris.engine.mantle.components;
import art.arcane.iris.engine.object.FloatingObjectFootprint;
import art.arcane.iris.engine.object.IrisObjectRotation;
import org.junit.Test;
import java.lang.reflect.Constructor;
import static org.junit.Assert.assertEquals;
public class MantleFloatingObjectComponentInvertedCountersTest {
private FloatingObjectFootprint footprint(int lowestSolidKeyY, int highestSolidKeyY, int tallestKx, int tallestKz) throws Exception {
Constructor<FloatingObjectFootprint> constructor = FloatingObjectFootprint.class.getDeclaredConstructor(
int.class,
int.class,
int.class,
int.class,
int.class,
int.class,
int.class,
int.class,
int.class,
long[].class
);
constructor.setAccessible(true);
return constructor.newInstance(
lowestSolidKeyY,
highestSolidKeyY,
0,
0,
0,
tallestKx,
tallestKz,
99,
99,
new long[0]
);
}
@Test
public void resetObjectCounters_resetsAllInvertedCountersToZero() {
MantleFloatingObjectComponent.objectsInvertedAttempted.set(5);
@@ -39,4 +71,49 @@ public class MantleFloatingObjectComponentInvertedCountersTest {
assertEquals(0, MantleFloatingObjectComponent.objectsAttempted.get());
assertEquals(0, MantleFloatingObjectComponent.objectsPlaced.get());
}
@Test
public void invertedBaseY_anchorsOriginalLowestSolidBelowBottomFace() throws Exception {
FloatingObjectFootprint footprint = footprint(5, 30, 2, 3);
assertEquals(104, MantleFloatingObjectComponent.invertedBaseY(100, footprint));
}
@Test
public void invertedBaseX_usesTopFootprintAnchor() throws Exception {
FloatingObjectFootprint footprint = footprint(5, 30, 2, 3);
assertEquals(106, MantleFloatingObjectComponent.invertedBaseX(100, 8, footprint));
}
@Test
public void invertedBaseZ_mirrorsTopFootprintAnchor() throws Exception {
FloatingObjectFootprint footprint = footprint(5, 30, 2, 3);
assertEquals(111, MantleFloatingObjectComponent.invertedBaseZ(100, 8, footprint));
}
@Test
public void invertedBaseX_usesFixedYRotationAnchor() throws Exception {
FloatingObjectFootprint footprint = footprint(5, 30, 2, 3);
IrisObjectRotation rotation = IrisObjectRotation.xFlip180WithY(90);
assertEquals(111, MantleFloatingObjectComponent.invertedBaseX(100, 8, footprint, rotation));
}
@Test
public void invertedBaseZ_usesFixedYRotationAnchor() throws Exception {
FloatingObjectFootprint footprint = footprint(5, 30, 2, 3);
IrisObjectRotation rotation = IrisObjectRotation.xFlip180WithY(90);
assertEquals(110, MantleFloatingObjectComponent.invertedBaseZ(100, 8, footprint, rotation));
}
@Test
public void invertedBaseY_isStableAcrossFixedYRotation() throws Exception {
FloatingObjectFootprint footprint = footprint(5, 30, 2, 3);
IrisObjectRotation rotation = IrisObjectRotation.xFlip180WithY(270);
assertEquals(104, MantleFloatingObjectComponent.invertedBaseY(100, footprint, rotation));
}
}
@@ -1,5 +1,8 @@
package art.arcane.iris.engine.object;
import art.arcane.iris.util.project.noise.CNG;
import art.arcane.iris.util.project.noise.NoiseGenerator;
import art.arcane.volmlib.util.math.RNG;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -15,7 +18,9 @@ public class FloatingIslandSampleBottomYTest {
}
}
for (boolean b : solidMask) {
if (b) solidCount++;
if (b) {
solidCount++;
}
}
return FloatingIslandSample.constructForTest(islandBaseY, solidMask.length, topIdx, solidCount, solidMask);
}
@@ -72,4 +77,84 @@ public class FloatingIslandSampleBottomYTest {
assertEquals(false, mask[1]);
assertEquals(false, mask[2]);
}
@Test
public void roundedEdgeHeight_zeroFade_removesEdgeWall() {
assertEquals(0, FloatingIslandSample.roundedEdgeHeight(18, 0.0));
}
@Test
public void roundedEdgeDepth_zeroFade_removesMinimumTailAtEdge() {
assertEquals(0, FloatingIslandSample.roundedEdgeDepth(10, 20, 1.0, 0.0));
}
@Test
public void roundedEdgeDepth_fullFade_keepsConfiguredDepth() {
assertEquals(15, FloatingIslandSample.roundedEdgeDepth(10, 20, 0.5, 1.0));
}
@Test
public void carveSolidInterior_preservesOuterShell() {
boolean[] mask = {false, true, true, true, true, false};
CNG carve = new CNG(new RNG(1), new NoiseGenerator() {
@Override
public double noise(double x) {
return 1.0;
}
@Override
public double noise(double x, double z) {
return 1.0;
}
@Override
public double noise(double x, double y, double z) {
return 1.0;
}
}, 1.0, 1);
int count = FloatingIslandSample.carveSolidInterior(mask, 100, 0, 0, carve, 0.5);
assertEquals(2, count);
assertEquals(false, mask[0]);
assertEquals(true, mask[1]);
assertEquals(false, mask[2]);
assertEquals(false, mask[3]);
assertEquals(true, mask[4]);
assertEquals(false, mask[5]);
}
@Test
public void hasFootprintNeighborSupport_rejectsSingleIsolatedColumn() {
CNG footprint = new CNG(new RNG(2)) {
@Override
public double noise(double x, double z) {
return x == 0 && z == 0 ? 1.0 : 0.0;
}
@Override
public double noise(double x, double y, double z) {
return noise(x, z);
}
};
assertEquals(false, FloatingIslandSample.hasFootprintNeighborSupport(footprint, 0, 0, 0.0));
}
@Test
public void hasFootprintNeighborSupport_acceptsCardinalNeighbor() {
CNG footprint = new CNG(new RNG(3)) {
@Override
public double noise(double x, double z) {
return (x == 0 && z == 0) || (x == 1 && z == 0) ? 1.0 : 0.0;
}
@Override
public double noise(double x, double y, double z) {
return noise(x, z);
}
};
assertEquals(true, FloatingIslandSample.hasFootprintNeighborSupport(footprint, 0, 0, 0.0));
}
}
@@ -19,6 +19,33 @@ public class IrisObjectRotationFlipTest {
assertTrue(!rot.canRotateY());
}
@Test
public void xFlip180RandomY_canRotateY_returnsTrue() {
IrisObjectRotation rot = IrisObjectRotation.xFlip180RandomY();
assertTrue(rot.canRotateY());
}
@Test
public void xFlip180WithY_zeroYaw_stillUsesFixedYRotation() {
IrisObjectRotation rot = IrisObjectRotation.xFlip180WithY(0);
BlockVector v = new BlockVector(1, 2, 3);
BlockVector result = rot.rotate(v, 117, 253, 91);
assertTrue(rot.canRotateY());
assertEquals(1, result.getBlockX());
assertEquals(-2, result.getBlockY());
assertEquals(-3, result.getBlockZ());
}
@Test
public void xFlip180WithY_ninetyYaw_rotatesMirroredFootprint() {
IrisObjectRotation rot = IrisObjectRotation.xFlip180WithY(90);
BlockVector v = new BlockVector(2, 5, 3);
BlockVector result = rot.rotate(v, 0, 0, 0);
assertEquals(-3, result.getBlockX());
assertEquals(-5, result.getBlockY());
assertEquals(-2, result.getBlockZ());
}
@Test
public void xFlip180_rotateVector_negatesYandZ() {
IrisObjectRotation rot = IrisObjectRotation.xFlip180();
@@ -51,6 +51,31 @@ public class IslandObjectPlacerAnchorFaceTest {
assertEquals(1, placer.getWritesDroppedAboveBottom());
}
@Test
public void bottomFace_canWriteObjectBlock_allowsBelowAnchorWithoutCounting() {
FloatingIslandSample[] samples = new FloatingIslandSample[256];
samples[0] = sampleWithBottomAt(100, 0);
IslandObjectPlacer placer = new IslandObjectPlacer(null, samples, 0, 0, 100, IslandObjectPlacer.AnchorFace.BOTTOM);
assertEquals(true, placer.canWriteObjectBlock(0, 99, 0));
assertEquals(0, placer.getWritesAttempted());
assertEquals(0, placer.getWritesDroppedAboveBottom());
}
@Test
public void bottomFace_canWriteObjectBlock_blocksAnchorAndAboveWithoutCounting() {
FloatingIslandSample[] samples = new FloatingIslandSample[256];
samples[0] = sampleWithBottomAt(100, 0);
IslandObjectPlacer placer = new IslandObjectPlacer(null, samples, 0, 0, 100, IslandObjectPlacer.AnchorFace.BOTTOM);
assertEquals(false, placer.canWriteObjectBlock(0, 100, 0));
assertEquals(false, placer.canWriteObjectBlock(0, 101, 0));
assertEquals(0, placer.getWritesAttempted());
assertEquals(0, placer.getWritesDroppedAboveBottom());
}
@Test
public void topFace_existingConstructor_dropsBelowAnchor_noRegression() {
FloatingIslandSample[] samples = new FloatingIslandSample[256];