Terminal carving roots

- Roots without selectable children resolve to themselves before the per-column child cache
- Selection plans build through one shared helper for root checks and child selection
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-22 07:19:57 -04:00
1 parent 67fd9046ba
commit e38f956d66
2 files changed
+47 -10

No files matched your search

@@ -120,7 +120,7 @@ public final class IrisDimensionCarvingResolver {
} }
int remainingDepth = clampDepth(rootEntry.getChildRecursionDepth()); int remainingDepth = clampDepth(rootEntry.getChildRecursionDepth());
if (remainingDepth <= 0) { if (remainingDepth <= 0 || terminal(engine, data, rootEntry, rootBiome, resolvedState)) {
return rootEntry; return rootEntry;
} }
@@ -131,13 +131,12 @@ public final class IrisDimensionCarvingResolver {
return columns.entries[slot]; return columns.entries[slot];
} }
Map<String, IrisDimensionCarvingEntry> entryIndex = resolveEntryIndex(engine, resolvedState);
IrisDimensionCarvingEntry current = rootEntry; IrisDimensionCarvingEntry current = rootEntry;
int depth = remainingDepth; int depth = remainingDepth;
boolean cacheable = true; boolean cacheable = true;
while (depth > 0) { while (depth > 0) {
cacheable &= fixedChildStyle(current); cacheable &= fixedChildStyle(current);
IrisDimensionCarvingEntry selected = selectChild(engine, data, current, worldX, worldZ, entryIndex, resolvedState); IrisDimensionCarvingEntry selected = selectChild(engine, data, current, worldX, worldZ, resolvedState);
if (selected == null || selected == current || selected.getWorldYRange() != null if (selected == null || selected == current || selected.getWorldYRange() != null
&& !selected.getWorldYRange().contains(worldY)) { && !selected.getWorldYRange().contains(worldY)) {
break; break;
@@ -164,6 +163,24 @@ public final class IrisDimensionCarvingResolver {
return current; return current;
} }
private static boolean terminal(Engine engine, IrisData data, IrisDimensionCarvingEntry entry, IrisBiome biome, State state) {
KList<String> children = entry.getChildren();
if (children == null || children.isEmpty()) {
return true;
}
return selectionPlan(engine, data, entry, biome, state).size() <= 1L;
}
private static IrisRaritySelection<CarvingChoice> selectionPlan(Engine engine, IrisData data, IrisDimensionCarvingEntry parent,
IrisBiome parentBiome, State state) {
IrisRaritySelection<CarvingChoice> selectionPlan = state.selectionPlans.get(parent);
if (selectionPlan == null) {
selectionPlan = buildSelectionPlan(data, parent, parentBiome, resolveEntryIndex(engine, state), state);
state.selectionPlans.put(parent, selectionPlan);
}
return selectionPlan;
}
private static boolean fixedChildStyle(IrisDimensionCarvingEntry entry) { private static boolean fixedChildStyle(IrisDimensionCarvingEntry entry) {
for (IrisGeneratorStyle style = entry.getChildStyle(); style != null; style = style.getFracture()) { for (IrisGeneratorStyle style = entry.getChildStyle(); style != null; style = style.getFracture()) {
if (style.getExpression() != null) { if (style.getExpression() != null) {
@@ -202,7 +219,6 @@ public final class IrisDimensionCarvingResolver {
IrisDimensionCarvingEntry parent, IrisDimensionCarvingEntry parent,
int worldX, int worldX,
int worldZ, int worldZ,
Map<String, IrisDimensionCarvingEntry> entryIndex,
State state State state
) { ) {
KList<String> children = parent.getChildren(); KList<String> children = parent.getChildren();
@@ -215,12 +231,7 @@ public final class IrisDimensionCarvingResolver {
return parent; return parent;
} }
IrisRaritySelection<CarvingChoice> selectionPlan = state.selectionPlans.get(parent); IrisRaritySelection<CarvingChoice> selectionPlan = selectionPlan(engine, data, parent, parentBiome, state);
if (selectionPlan == null) {
selectionPlan = buildSelectionPlan(data, parent, parentBiome, entryIndex, state);
state.selectionPlans.put(parent, selectionPlan);
}
if (selectionPlan.size() <= 1L) { if (selectionPlan.size() <= 1L) {
return parent; return parent;
} }
@@ -166,6 +166,32 @@ public class IrisDimensionCarvingResolverParityTest {
assertSame(child, IrisDimensionCarvingResolver.resolveFromRoot(fixture.engine, parent, 7, 0, 9, state)); assertSame(child, IrisDimensionCarvingResolver.resolveFromRoot(fixture.engine, parent, 7, 0, 9, state));
} }
@Test
public void rootsWithoutSelectableChildrenResolveToThemselvesWithoutSampling() {
for (List<String> children : List.of(List.<String>of(), List.of("missing-child"))) {
Fixture fixture = createFixture();
IrisDimensionCarvingEntry parent = spy(fixture.engine.getDimension().getCarvingEntryIndex().get("root-low"));
parent.setChildRecursionDepth(3);
parent.setChildren(new KList<>(children));
CNG generator = mock(CNG.class);
doReturn(0.5D).when(generator).noiseFast2D(anyDouble(), anyDouble());
doReturn(generator).when(parent).getChildrenGenerator(anyLong(), any(IrisData.class));
IrisDimensionCarvingResolver.State state = new IrisDimensionCarvingResolver.State();
for (int worldY = -80; worldY < 140; worldY += 13) {
for (int x = -20; x < 20; x += 3) {
for (int z = -20; z < 20; z += 7) {
assertSame(legacyResolveFromRoot(fixture.engine, parent, x, worldY, z),
IrisDimensionCarvingResolver.resolveFromRoot(fixture.engine, parent, x, worldY, z, state));
assertSame(parent, IrisDimensionCarvingResolver.resolveFromRoot(fixture.engine, parent, x, worldY, z, state));
}
}
}
verify(generator, never()).noiseFast2D(anyDouble(), anyDouble());
}
}
@Test @Test
public void repeatedColumnResolutionSamplesChildrenOnceAcrossHeights() { public void repeatedColumnResolutionSamplesChildrenOnceAcrossHeights() {
Fixture fixture = createFixture(); Fixture fixture = createFixture();