mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-25 13:30:08 +00:00
f
This commit is contained in:
1 parent
ad41b6795c
commit
1d194e880b
12 files changed
+1208
-128
No files matched your search
@@ -153,9 +153,20 @@ public class SchemaBuilderParityTest {
|
||||
.getJSONObject(stilt.getString("$ref").substring("#/definitions/".length()));
|
||||
JSONObject stiltProperties = stiltDefinition.getJSONObject("properties");
|
||||
JSONObject maxDepth = stiltProperties.getJSONObject("maxDepth");
|
||||
JSONObject overboreShape = properties.getJSONObject("overboreShape");
|
||||
JSONObject overboreErosionStrength = properties.getJSONObject("overboreErosionStrength");
|
||||
JSONObject overboreErosionFrequency = properties.getJSONObject("overboreErosionFrequency");
|
||||
String overboreShapeDefinition = overboreShape.getString("$ref")
|
||||
.substring("#/definitions/".length());
|
||||
|
||||
assertTrue(properties.has("structures"));
|
||||
assertTrue(properties.has("distribution"));
|
||||
assertEquals(List.of("BOX", "ROUNDED", "ERODED"), oneOfValues(
|
||||
schema.getJSONObject("definitions"), overboreShapeDefinition));
|
||||
assertEquals(0D, overboreErosionStrength.getDouble("minimum"), 0D);
|
||||
assertEquals(1D, overboreErosionStrength.getDouble("maximum"), 0D);
|
||||
assertEquals(0.001D, overboreErosionFrequency.getDouble("minimum"), 0D);
|
||||
assertEquals(1D, overboreErosionFrequency.getDouble("maximum"), 0D);
|
||||
assertEquals("object", stilt.getString("type"));
|
||||
assertTrue(stiltProperties.has("palette"));
|
||||
assertTrue(stiltProperties.has("supportNonOccluding"));
|
||||
@@ -190,6 +201,15 @@ public class SchemaBuilderParityTest {
|
||||
return values;
|
||||
}
|
||||
|
||||
private static List<String> oneOfValues(JSONObject definitions, String key) {
|
||||
JSONArray array = definitions.getJSONObject(key).getJSONArray("oneOf");
|
||||
List<String> values = new ArrayList<>(array.length());
|
||||
for (int index = 0; index < array.length(); index++) {
|
||||
values.add(array.getJSONObject(index).getString("const"));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@Desc("Registry dependent model.")
|
||||
public static class RegistryModel {
|
||||
@Desc("Potion field.")
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package art.arcane.iris.core.tools;
|
||||
|
||||
import art.arcane.iris.core.runtime.WorldRuntimeControlService;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class IrisCreatorTeleportTest {
|
||||
@Test
|
||||
public void createTeleportTarget_onlySelectsProductionPlayerSender() {
|
||||
Player player = mock(Player.class);
|
||||
VolmitSender playerSender = mock(VolmitSender.class);
|
||||
VolmitSender consoleSender = mock(VolmitSender.class);
|
||||
doReturn(true).when(playerSender).isPlayer();
|
||||
doReturn(player).when(playerSender).player();
|
||||
doReturn(false).when(consoleSender).isPlayer();
|
||||
|
||||
assertSame(player, IrisCreator.createTeleportTarget(playerSender, false, false));
|
||||
assertNull(IrisCreator.createTeleportTarget(consoleSender, false, false));
|
||||
assertNull(IrisCreator.createTeleportTarget(playerSender, true, false));
|
||||
assertNull(IrisCreator.createTeleportTarget(playerSender, false, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void teleportSenderToCreatedWorld_loadsAndResolvesSafeEntryBeforeTeleport() {
|
||||
Player player = mock(Player.class);
|
||||
World world = mock(World.class);
|
||||
Chunk chunk = mock(Chunk.class);
|
||||
WorldRuntimeControlService runtimeControl = mock(WorldRuntimeControlService.class);
|
||||
Location anchor = new Location(world, 32.5D, 80D, -15.5D);
|
||||
Location safeEntry = new Location(world, 32.5D, 94D, -15.5D);
|
||||
doReturn(anchor).when(runtimeControl).resolveEntryAnchor(world);
|
||||
doReturn(CompletableFuture.completedFuture(chunk))
|
||||
.when(runtimeControl).requestChunkAsync(world, 2, -1, true);
|
||||
doReturn(CompletableFuture.completedFuture(safeEntry))
|
||||
.when(runtimeControl).resolveSafeEntry(world, anchor);
|
||||
doReturn(CompletableFuture.completedFuture(true))
|
||||
.when(runtimeControl).teleport(player, safeEntry);
|
||||
|
||||
CompletableFuture<Boolean> result = IrisCreator.teleportSenderToCreatedWorld(player, world, runtimeControl);
|
||||
|
||||
assertTrue(result.join());
|
||||
InOrder order = inOrder(runtimeControl);
|
||||
order.verify(runtimeControl).resolveEntryAnchor(world);
|
||||
order.verify(runtimeControl).requestChunkAsync(world, 2, -1, true);
|
||||
order.verify(runtimeControl).resolveSafeEntry(world, anchor);
|
||||
order.verify(runtimeControl).teleport(player, safeEntry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void teleportSenderToCreatedWorld_preservesFalseTeleportResult() {
|
||||
Player player = mock(Player.class);
|
||||
World world = mock(World.class);
|
||||
WorldRuntimeControlService runtimeControl = mock(WorldRuntimeControlService.class);
|
||||
Location anchor = new Location(world, 0.5D, 80D, 0.5D);
|
||||
doReturn(anchor).when(runtimeControl).resolveEntryAnchor(world);
|
||||
doReturn(CompletableFuture.completedFuture(mock(Chunk.class)))
|
||||
.when(runtimeControl).requestChunkAsync(world, 0, 0, true);
|
||||
doReturn(CompletableFuture.completedFuture(anchor))
|
||||
.when(runtimeControl).resolveSafeEntry(world, anchor);
|
||||
doReturn(CompletableFuture.completedFuture(false))
|
||||
.when(runtimeControl).teleport(player, anchor);
|
||||
|
||||
CompletableFuture<Boolean> result = IrisCreator.teleportSenderToCreatedWorld(player, world, runtimeControl);
|
||||
|
||||
assertFalse(result.join());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void teleportSenderToCreatedWorld_failsWhenSafeEntryCannotResolve() {
|
||||
Player player = mock(Player.class);
|
||||
World world = mock(World.class);
|
||||
WorldRuntimeControlService runtimeControl = mock(WorldRuntimeControlService.class);
|
||||
Location anchor = new Location(world, 0.5D, 80D, 0.5D);
|
||||
doReturn("irisworld").when(world).getName();
|
||||
doReturn(anchor).when(runtimeControl).resolveEntryAnchor(world);
|
||||
doReturn(CompletableFuture.completedFuture(mock(Chunk.class)))
|
||||
.when(runtimeControl).requestChunkAsync(world, 0, 0, true);
|
||||
doReturn(CompletableFuture.completedFuture(null))
|
||||
.when(runtimeControl).resolveSafeEntry(world, anchor);
|
||||
|
||||
CompletableFuture<Boolean> result = IrisCreator.teleportSenderToCreatedWorld(player, world, runtimeControl);
|
||||
|
||||
assertThrows(CompletionException.class, result::join);
|
||||
}
|
||||
}
|
||||
+35
-1
@@ -30,6 +30,7 @@ import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisPosition;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisStructure;
|
||||
import art.arcane.iris.engine.object.IrisStructureCarveShape;
|
||||
import art.arcane.iris.engine.object.IrisStructurePlacement;
|
||||
import art.arcane.iris.engine.object.NativeStructureSuppression;
|
||||
import art.arcane.iris.engine.object.ObjectPlaceMode;
|
||||
@@ -469,8 +470,41 @@ public class IrisStructureLocatorContractTest {
|
||||
KList<PlacedStructurePiece> pieces = new KList<>();
|
||||
pieces.add(piece(0, 60, 0, 1, 80, 1));
|
||||
|
||||
assertEquals(Integer.valueOf(-17), IrisStructureLocator.resolveUndergroundBurialShift(
|
||||
assertEquals(Integer.valueOf(-14), IrisStructureLocator.resolveUndergroundBurialShift(
|
||||
engine, pieces, placement, 60, -63, 319));
|
||||
|
||||
placement.setOverboreErosionStrength(0D);
|
||||
assertEquals(Integer.valueOf(-1), IrisStructureLocator.resolveUndergroundBurialShift(
|
||||
engine, pieces, placement, 60, -63, 319));
|
||||
|
||||
placement.setOverboreShape(IrisStructureCarveShape.ROUNDED);
|
||||
assertEquals(Integer.valueOf(-1), IrisStructureLocator.resolveUndergroundBurialShift(
|
||||
engine, pieces, placement, 60, -63, 319));
|
||||
|
||||
placement.setOverboreHeight(0);
|
||||
assertEquals(Integer.valueOf(0), IrisStructureLocator.resolveUndergroundBurialShift(
|
||||
engine, pieces, placement, 60, -63, 319));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zeroOverboreRadiusDoesNotExpandTheBurialEnvelope() {
|
||||
Engine engine = mock(Engine.class);
|
||||
when(engine.getMinHeight()).thenReturn(-64);
|
||||
when(engine.getHeight(anyInt(), anyInt(), eq(true))).thenReturn(164);
|
||||
IrisStructurePlacement placement = new IrisStructurePlacement()
|
||||
.setUnderground(true)
|
||||
.setMinHeight(-64)
|
||||
.setMaxHeight(100)
|
||||
.setOverbore(true)
|
||||
.setOverboreShape(IrisStructureCarveShape.ROUNDED)
|
||||
.setOverboreRadius(0)
|
||||
.setOverboreHeight(0);
|
||||
KList<PlacedStructurePiece> pieces = new KList<>();
|
||||
pieces.add(piece(4, 60, 7, 4, 80, 7));
|
||||
|
||||
assertEquals(Integer.valueOf(0), IrisStructureLocator.resolveUndergroundBurialShift(
|
||||
engine, pieces, placement, 60, -63, 319));
|
||||
verify(engine, times(1)).getHeight(4, 7, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+37
-27
@@ -1,5 +1,6 @@
|
||||
package art.arcane.iris.engine.mantle.components;
|
||||
|
||||
import art.arcane.iris.engine.object.IrisStructureCarveShape;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -8,47 +9,56 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisStructureComponentOverboreTest {
|
||||
@Test
|
||||
public void exactPieceInteriorAlwaysCarves() {
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(0.0, 0.0));
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(0.0, 1.0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lowNoiseRemovesTheFormerFlatShell() {
|
||||
double oneBlockAtRadiusSix = 1.0 / 6.0;
|
||||
public void exactStructureFootprintAlwaysCarves() {
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
oneBlockAtRadiusSix * oneBlockAtRadiusSix, 0.0));
|
||||
assertFalse(IrisStructureComponent.shouldCarveOverboreCell(0.25 * 0.25, 0.0));
|
||||
IrisStructureCarveShape.ERODED, 0D, 0D, 1D));
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
IrisStructureCarveShape.ROUNDED, 0D, 0D, 1D));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maximumNoiseStopsAtConfiguredReach() {
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(1.0, 1.0));
|
||||
assertFalse(IrisStructureComponent.shouldCarveOverboreCell(1.000001, 1.0));
|
||||
public void boxModeKeepsStraightCandidateVolume() {
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
IrisStructureCarveShape.BOX, 100D, 0D, 1D));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void diagonalCornersUseEuclideanFalloff() {
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(1.0, 1.0));
|
||||
assertFalse(IrisStructureComponent.shouldCarveOverboreCell(0.8 * 0.8 + 0.8 * 0.8, 1.0));
|
||||
public void roundedModeStopsAtConfiguredReach() {
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
IrisStructureCarveShape.ROUNDED, 1D, 0D, 1D));
|
||||
assertFalse(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
IrisStructureCarveShape.ROUNDED, 1.000001D, 1D, 0D));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void boundaryNoiseIsClampedAndDeterministic() {
|
||||
assertEquals(0.2, IrisStructureComponent.overboreBoundaryLimit(-10.0), 0.0);
|
||||
assertEquals(1.0, IrisStructureComponent.overboreBoundaryLimit(10.0), 0.0);
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(0.36, 0.5));
|
||||
assertFalse(IrisStructureComponent.shouldCarveOverboreCell(0.360001, 0.5));
|
||||
public void zeroErosionStrengthMatchesRoundedMode() {
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
IrisStructureCarveShape.ERODED, 1D, 0D, 0D));
|
||||
assertFalse(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
IrisStructureCarveShape.ERODED, 1.000001D, 1D, 0D));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void candidateExtensionsDoNotScanImpossibleOuterShell() {
|
||||
assertEquals(6, IrisStructureComponent.overboreSideExtension(6));
|
||||
assertEquals(18, IrisStructureComponent.overboreUpExtension(10.0));
|
||||
public void zeroConfiguredCeilingHasNoErodedExtension() {
|
||||
assertEquals(0D, IrisStructureComponent.erodedUpReach(null, 0.16D, 1D, 0, 0, 0), 0D);
|
||||
}
|
||||
|
||||
long oldVolume = (41L + 18L) * (31L + 27L) * (35L + 18L);
|
||||
long newVolume = (41L + 12L) * (31L + 18L) * (35L + 12L);
|
||||
assertTrue(newVolume < oldVolume);
|
||||
@Test
|
||||
public void zeroErosionStrengthKeepsTheRoundedCeiling() {
|
||||
assertEquals(10D, IrisStructureComponent.erodedUpReach(null, 0.16D, 0D, 0, 0, 10), 0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void erosionStrengthAndNoiseAreClampedDeterministically() {
|
||||
assertEquals(0.2D, IrisStructureComponent.overboreBoundaryLimit(-10D, 0.8D), 1.0E-12D);
|
||||
assertEquals(1D, IrisStructureComponent.overboreBoundaryLimit(10D, 0.8D), 0D);
|
||||
assertEquals(0.5D, IrisStructureComponent.overboreBoundaryLimit(0.5D, 1D), 0D);
|
||||
assertEquals(1D, IrisStructureComponent.overboreBoundaryLimit(0D, -1D), 0D);
|
||||
assertEquals(0D, IrisStructureComponent.overboreBoundaryLimit(0D, 10D), 0D);
|
||||
assertTrue(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
null, 0.25D, 0.5D, 1D));
|
||||
assertFalse(IrisStructureComponent.shouldCarveOverboreCell(
|
||||
null, 0.250001D, 0.5D, 1D));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
package art.arcane.iris.engine.mantle.components;
|
||||
|
||||
import art.arcane.iris.engine.framework.PlacedStructurePiece;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisObjectRotation;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.iris.util.common.math.IrisBlockVector;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class StructureCarvingFootprintTest {
|
||||
@Test
|
||||
public void preservesIrregularFootprintInsteadOfFillingItsBoundingBox() {
|
||||
PlacedStructurePiece piece = piece(10, 40, 20, IrisObjectRotation.of(0, 0, 0),
|
||||
block(0, 0, 0), block(1, 0, 0), block(2, 0, 0),
|
||||
block(0, 0, 1), block(0, 0, 2));
|
||||
|
||||
StructureCarvingFootprint footprint = StructureCarvingFootprint.from(pieces(piece), 0);
|
||||
|
||||
assertNotNull(footprint);
|
||||
assertEquals(10, footprint.minX());
|
||||
assertEquals(12, footprint.maxX());
|
||||
assertEquals(20, footprint.minZ());
|
||||
assertEquals(22, footprint.maxZ());
|
||||
assertEquals(3, footprint.width());
|
||||
assertEquals(3, footprint.depth());
|
||||
assertEquals(0L, footprint.distanceSquaredAt(12, 20));
|
||||
assertEquals(4L, footprint.distanceSquaredAt(12, 22));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reportsExactDistanceAndNearestColumnHeights() {
|
||||
PlacedStructurePiece piece = piece(0, 0, 0, IrisObjectRotation.of(0, 0, 0),
|
||||
block(0, 10, 0), block(0, 12, 0),
|
||||
block(4, 30, 0), block(4, 35, 0));
|
||||
|
||||
StructureCarvingFootprint footprint = StructureCarvingFootprint.from(pieces(piece), 2);
|
||||
StructureCarvingFootprint.Column nearestRight = footprint.sample(3, 2);
|
||||
StructureCarvingFootprint.Column tied = footprint.sample(2, 0);
|
||||
|
||||
assertNotNull(nearestRight);
|
||||
assertEquals(5L, nearestRight.distanceSquared());
|
||||
assertEquals(30, nearestRight.sourceMinY());
|
||||
assertEquals(35, nearestRight.sourceMaxY());
|
||||
assertNotNull(tied);
|
||||
assertEquals(4L, tied.distanceSquared());
|
||||
assertEquals(10, tied.sourceMinY());
|
||||
assertEquals(12, tied.sourceMaxY());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rotatesAndMergesOverlappingColumns() {
|
||||
PlacedStructurePiece rotated = piece(10, 20, 30, IrisObjectRotation.of(0, 90, 0),
|
||||
block(2, 1, 0));
|
||||
PlacedStructurePiece overlapping = piece(10, 5, 28, IrisObjectRotation.of(0, 0, 0),
|
||||
block(0, 3, 0), block(0, 9, 0));
|
||||
|
||||
StructureCarvingFootprint footprint = StructureCarvingFootprint.from(
|
||||
pieces(rotated, overlapping), 0);
|
||||
|
||||
assertNotNull(footprint);
|
||||
assertEquals(10, footprint.minX());
|
||||
assertEquals(10, footprint.maxX());
|
||||
assertEquals(28, footprint.minZ());
|
||||
assertEquals(28, footprint.maxZ());
|
||||
assertEquals(0L, footprint.distanceSquaredAt(10, 28));
|
||||
assertEquals(8, footprint.sourceMinYAt(10, 28));
|
||||
assertEquals(21, footprint.sourceMaxYAt(10, 28));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesBruteForceSquaredDistancesAcrossSparseColumns() {
|
||||
int[][] sourceBlocks = new int[][]{
|
||||
block(0, 2, 0), block(3, 4, 1), block(1, 6, 4), block(5, 8, 5)
|
||||
};
|
||||
PlacedStructurePiece piece = piece(
|
||||
-8, 30, 11, IrisObjectRotation.of(0, 0, 0), sourceBlocks);
|
||||
|
||||
StructureCarvingFootprint footprint = StructureCarvingFootprint.from(pieces(piece), 3);
|
||||
|
||||
assertNotNull(footprint);
|
||||
for (int z = footprint.minZ(); z <= footprint.maxZ(); z++) {
|
||||
for (int x = footprint.minX(); x <= footprint.maxX(); x++) {
|
||||
long expected = Long.MAX_VALUE;
|
||||
for (int[] source : sourceBlocks) {
|
||||
long deltaX = (long) x - (piece.getX() + source[0]);
|
||||
long deltaZ = (long) z - (piece.getZ() + source[2]);
|
||||
expected = Math.min(expected, deltaX * deltaX + deltaZ * deltaZ);
|
||||
}
|
||||
assertEquals(expected, footprint.distanceSquaredAt(x, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullForEmptyInvalidOrOversizedInputs() {
|
||||
assertNull(StructureCarvingFootprint.from(null, 0));
|
||||
assertNull(StructureCarvingFootprint.from(new KList<>(), 0));
|
||||
|
||||
KList<PlacedStructurePiece> invalidPieces = new KList<>();
|
||||
invalidPieces.add((PlacedStructurePiece) null);
|
||||
invalidPieces.add(new PlacedStructurePiece(
|
||||
null, null, 0, 0, 0, null, 0, 0, 0, 0, 0, 0));
|
||||
assertNull(StructureCarvingFootprint.from(invalidPieces, 0));
|
||||
|
||||
PlacedStructurePiece piece = piece(0, 0, 0, IrisObjectRotation.of(0, 0, 0), block(0, 0, 0));
|
||||
assertNull(StructureCarvingFootprint.from(pieces(piece), 2, 24));
|
||||
PlacedStructurePiece overflowing = piece(
|
||||
Integer.MAX_VALUE, 0, 0, IrisObjectRotation.of(0, 0, 0), block(1, 0, 0));
|
||||
assertNull(StructureCarvingFootprint.from(pieces(overflowing), 0));
|
||||
|
||||
try {
|
||||
StructureCarvingFootprint.from(pieces(piece), -1);
|
||||
fail("Expected negative padding to fail");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("padding must be non-negative", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includesTheEntirePaddingBoundary() {
|
||||
PlacedStructurePiece piece = piece(7, 14, -4, IrisObjectRotation.of(0, 0, 0), block(0, 0, 0));
|
||||
|
||||
StructureCarvingFootprint footprint = StructureCarvingFootprint.from(pieces(piece), 2, 25);
|
||||
|
||||
assertNotNull(footprint);
|
||||
assertEquals(5, footprint.minX());
|
||||
assertEquals(9, footprint.maxX());
|
||||
assertEquals(-6, footprint.minZ());
|
||||
assertEquals(-2, footprint.maxZ());
|
||||
assertEquals(5, footprint.width());
|
||||
assertEquals(5, footprint.depth());
|
||||
assertTrue(footprint.contains(5, -6));
|
||||
assertTrue(footprint.contains(9, -2));
|
||||
assertFalse(footprint.contains(4, -6));
|
||||
assertEquals(8L, footprint.distanceSquaredAt(5, -6));
|
||||
assertNull(footprint.sample(4, -6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void explicitAirDoesNotExpandTheExteriorFootprint() {
|
||||
IrisObject object = new IrisObject(1, 1, 1);
|
||||
PlatformBlockState solid = mock(PlatformBlockState.class);
|
||||
PlatformBlockState air = mock(PlatformBlockState.class);
|
||||
when(air.isAir()).thenReturn(true);
|
||||
object.getBlocks().put(new IrisBlockVector(0, 0, 0), solid);
|
||||
object.getBlocks().put(new IrisBlockVector(8, 4, 8), air);
|
||||
PlacedStructurePiece piece = new PlacedStructurePiece(
|
||||
null, object, 10, 20, 30, IrisObjectRotation.of(0, 0, 0),
|
||||
10, 20, 30, 18, 24, 38);
|
||||
|
||||
StructureCarvingFootprint footprint = StructureCarvingFootprint.from(pieces(piece), 0);
|
||||
|
||||
assertNotNull(footprint);
|
||||
assertEquals(10, footprint.minX());
|
||||
assertEquals(10, footprint.maxX());
|
||||
assertEquals(30, footprint.minZ());
|
||||
assertEquals(30, footprint.maxZ());
|
||||
}
|
||||
|
||||
private static PlacedStructurePiece piece(int x, int y, int z, IrisObjectRotation rotation,
|
||||
int[]... blocks) {
|
||||
IrisObject object = new IrisObject(1, 1, 1);
|
||||
PlatformBlockState state = mock(PlatformBlockState.class);
|
||||
for (int[] block : blocks) {
|
||||
object.getBlocks().put(new IrisBlockVector(block[0], block[1], block[2]), state);
|
||||
}
|
||||
return new PlacedStructurePiece(
|
||||
null, object, x, y, z, rotation, x, y, z, x, y, z);
|
||||
}
|
||||
|
||||
private static KList<PlacedStructurePiece> pieces(PlacedStructurePiece... pieces) {
|
||||
KList<PlacedStructurePiece> result = new KList<>();
|
||||
for (PlacedStructurePiece piece : pieces) {
|
||||
result.add(piece);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[] block(int x, int y, int z) {
|
||||
return new int[]{x, y, z};
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class IrisStructurePlacementCarveSettingsTest {
|
||||
@Test
|
||||
public void defaultsSelectErodedOverbore() {
|
||||
IrisStructurePlacement placement = new IrisStructurePlacement();
|
||||
|
||||
assertEquals(IrisStructureCarveShape.ERODED, placement.getOverboreShape());
|
||||
assertEquals(IrisStructureCarveShape.ERODED, placement.resolvedOverboreShape());
|
||||
assertEquals(0.8D, placement.getOverboreErosionStrength(), 0D);
|
||||
assertEquals(0.8D, placement.resolvedOverboreErosionStrength(), 0D);
|
||||
assertEquals(0.07D, placement.getOverboreErosionFrequency(), 0D);
|
||||
assertEquals(0.07D, placement.resolvedOverboreErosionFrequency(), 0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void carveShapesExposeTheirMaximumCeilingScale() {
|
||||
assertEquals(1D, IrisStructureCarveShape.BOX.maximumCeilingScale(), 0D);
|
||||
assertEquals(1D, IrisStructureCarveShape.ROUNDED.maximumCeilingScale(), 0D);
|
||||
assertEquals(1.8D, IrisStructureCarveShape.ERODED.maximumCeilingScale(), 0D);
|
||||
assertEquals(10, IrisStructureCarveShape.BOX.maximumCeilingExtension(10));
|
||||
assertEquals(10, IrisStructureCarveShape.ROUNDED.maximumCeilingExtension(10));
|
||||
assertEquals(18, IrisStructureCarveShape.ERODED.maximumCeilingExtension(10));
|
||||
assertEquals(10, IrisStructureCarveShape.ERODED.maximumCeilingExtension(10, 0D));
|
||||
assertEquals(14, IrisStructureCarveShape.ERODED.maximumCeilingExtension(10, 0.5D));
|
||||
assertEquals(0, IrisStructureCarveShape.ERODED.maximumCeilingExtension(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullAndNonFiniteValuesResolveToDefaults() {
|
||||
IrisStructurePlacement placement = new IrisStructurePlacement()
|
||||
.setOverboreShape(null)
|
||||
.setOverboreErosionStrength(Double.NaN)
|
||||
.setOverboreErosionFrequency(Double.POSITIVE_INFINITY);
|
||||
|
||||
assertEquals(IrisStructureCarveShape.ERODED, placement.resolvedOverboreShape());
|
||||
assertEquals(0.8D, placement.resolvedOverboreErosionStrength(), 0D);
|
||||
assertEquals(0.07D, placement.resolvedOverboreErosionFrequency(), 0D);
|
||||
|
||||
placement.setOverboreErosionStrength(Double.NEGATIVE_INFINITY);
|
||||
placement.setOverboreErosionFrequency(Double.NaN);
|
||||
|
||||
assertEquals(0.8D, placement.resolvedOverboreErosionStrength(), 0D);
|
||||
assertEquals(0.07D, placement.resolvedOverboreErosionFrequency(), 0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void finiteValuesClampToAuthoredBounds() {
|
||||
IrisStructurePlacement placement = new IrisStructurePlacement()
|
||||
.setOverboreErosionStrength(-1D)
|
||||
.setOverboreErosionFrequency(0D);
|
||||
|
||||
assertEquals(0D, placement.resolvedOverboreErosionStrength(), 0D);
|
||||
assertEquals(0.001D, placement.resolvedOverboreErosionFrequency(), 0D);
|
||||
|
||||
placement.setOverboreErosionStrength(2D);
|
||||
placement.setOverboreErosionFrequency(2D);
|
||||
|
||||
assertEquals(1D, placement.resolvedOverboreErosionStrength(), 0D);
|
||||
assertEquals(1D, placement.resolvedOverboreErosionFrequency(), 0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numericSchemaBoundsMatchRuntimeBounds() throws NoSuchFieldException {
|
||||
assertBounds("overboreErosionStrength", 0D, 1D);
|
||||
assertBounds("overboreErosionFrequency", 0.001D, 1D);
|
||||
}
|
||||
|
||||
private void assertBounds(String fieldName, double expectedMinimum,
|
||||
double expectedMaximum) throws NoSuchFieldException {
|
||||
Field field = IrisStructurePlacement.class.getDeclaredField(fieldName);
|
||||
MinNumber minimum = field.getAnnotation(MinNumber.class);
|
||||
MaxNumber maximum = field.getAnnotation(MaxNumber.class);
|
||||
|
||||
assertNotNull(minimum);
|
||||
assertNotNull(maximum);
|
||||
assertEquals(expectedMinimum, minimum.value(), 0D);
|
||||
assertEquals(expectedMaximum, maximum.value(), 0D);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user