River bed padding and feature search rings

- surface.bed: falling blocks under and beside river water are replaced by a padding palette unless allowed
- Ring order helper for bounded feature searches
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-01 23:08:47 -04:00
1 parent 1ad3a25cb6
commit 639786537b
9 files changed
+238 -11

No files matched your search

@@ -113,6 +113,49 @@ public class PackHydrologyValidatorTest {
assertTrue(result.errors().toString(), result.errors().isEmpty());
}
@Test
public void bedRulesRejectBadPaddingAndFluidPaddingBlocks() throws Exception {
File pack = pack(riversDimension("""
{
"enabled": true,
"routing": {"tileSize": 1024, "sampleSpacing": 64, "oceanOutlets": true},
"surface": {
"bed": {
"allowGravityBlocks": false,
"padding": 9,
"paddingPalette": {"palette": [{"block": "minecraft:water"}]}
}
}
}
""", ""));
PackHydrologyValidator.Validation result = validate(pack);
assertContains(result.errors(), "padding must be at most 8");
assertContains(result.errors(), "paddingPalette.palette[0].block must not be a fluid");
}
@Test
public void bedRulesAcceptSolidPaddingBlocks() throws Exception {
File pack = pack(riversDimension("""
{
"enabled": true,
"routing": {"tileSize": 1024, "sampleSpacing": 64, "oceanOutlets": true},
"surface": {
"bed": {
"allowGravityBlocks": true,
"padding": 0,
"paddingPalette": {"palette": [{"block": "minecraft:clay"}, {"block": "minecraft:dirt", "weight": 2}]}
}
}
}
""", ""));
PackHydrologyValidator.Validation result = validate(pack);
assertTrue(result.errors().toString(), result.errors().stream().noneMatch((String error) -> error.contains(".bed")));
}
@Test
public void rejectsMouthLevelingDistanceBeyondTheRouteLength() throws Exception {
File pack = pack(riversDimension("""
@@ -0,0 +1,47 @@
package art.arcane.iris.engine.hydrology.runtime;
import art.arcane.iris.engine.hydrology.HydrologyTileKey;
import org.junit.Test;
import java.util.HashSet;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class HydrologyFeatureSearchTest {
@Test
public void ringZeroIsTheOriginTile() {
assertEquals(List.of(new HydrologyTileKey(3, -2)), HydrologyFeatureSearch.ring(3, -2, 0));
}
@Test
public void ringsCoverEveryTileAtExactlyTheirChebyshevDistance() {
HashSet<HydrologyTileKey> seen = new HashSet<>();
for (int radius = 0; radius <= 3; radius++) {
List<HydrologyTileKey> ring = HydrologyFeatureSearch.ring(1, 1, radius);
assertEquals(radius == 0 ? 1 : radius * 8, ring.size());
for (HydrologyTileKey key : ring) {
int distance = Math.max(Math.abs(key.tileX() - 1), Math.abs(key.tileZ() - 1));
assertEquals(radius, distance);
assertTrue(seen.add(key));
}
}
assertEquals(49, seen.size());
}
@Test
public void ringLimitCoversTheRequestedDistancePlusPublication() {
assertEquals(9, HydrologyFeatureSearch.ringLimit(8192, 1024, 358));
assertEquals(1, HydrologyFeatureSearch.ringLimit(0, 1024, 358));
assertEquals(0, HydrologyFeatureSearch.ringLimit(0, 1024, 0));
}
@Test
public void lowerBoundGrowsWithTheRingAndNeverGoesNegative() {
assertEquals(0L, HydrologyFeatureSearch.lowerBound(0, 1024, 358));
assertEquals(0L, HydrologyFeatureSearch.lowerBound(1, 1024, 358));
assertEquals(666L, HydrologyFeatureSearch.lowerBound(2, 1024, 358));
assertEquals(1690L, HydrologyFeatureSearch.lowerBound(3, 1024, 358));
}
}