Modded structure state key

- Modded biome policy supplies the structure state key from the generator
- History worlds key structure state by the active epoch
- Studio worlds get a fresh transient key
- Tests cover the key binding and the structure state codec
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-30 22:50:49 -04:00
1 parent 618bb28591
commit b61d2f305b
4 files changed
+94 -6

No files matched your search

@@ -105,6 +105,7 @@ import java.util.Objects;
import java.util.OptionalLong; import java.util.OptionalLong;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.IntConsumer; import java.util.function.IntConsumer;
@@ -946,6 +947,14 @@ public final class IrisModdedChunkGenerator implements NativeGeneratorOwner, Nat
+ " requires an attached generation-history runtime router.")); + " requires an attached generation-history runtime router."));
} }
private String structureStateKey() {
Engine current = boundEngineOrNull();
if (current == null || allowsGenerationHistoryBypass(current)) {
return "transient:" + UUID.randomUUID();
}
return "epoch:" + requireHistoryRouter(current, "structure state key").history().activeEpoch().epochId();
}
boolean allowsGenerationHistoryBypass(Engine current) { boolean allowsGenerationHistoryBypass(Engine current) {
if (generationMode != ModdedGenerationMode.TRANSIENT_STUDIO) { if (generationMode != ModdedGenerationMode.TRANSIENT_STUDIO) {
return false; return false;
@@ -985,7 +994,7 @@ public final class IrisModdedChunkGenerator implements NativeGeneratorOwner, Nat
ModdedBiomePolicy<H, S> policy = new ModdedBiomePolicy<>(source); ModdedBiomePolicy<H, S> policy = new ModdedBiomePolicy<>(source);
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(this::boundEngineOrNull, this::awaitStructureEngine, policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(this::boundEngineOrNull, this::awaitStructureEngine,
this::allowsGenerationHistoryBypass, this::configuredStructureBiomeKeys, this::allowsGenerationHistoryBypass, this::configuredStructureBiomeKeys,
IrisModdedChunkGenerator::retainedBiomeKeys, this::visibleBiomeSeed)); IrisModdedChunkGenerator::retainedBiomeKeys, this::visibleBiomeSeed, this::structureStateKey));
return policy; return policy;
} }
@@ -1395,6 +1395,11 @@ final class ModdedBiomePolicy<H, S> implements NativeModdedBiomePolicy<H, S> {
return requireConfiguredStructureBiomeKeys(exactStructureBiomeKeys()); return requireConfiguredStructureBiomeKeys(exactStructureBiomeKeys());
} }
@Override
public String structureStateKey() {
return Objects.requireNonNull(runtime, "runtime").structureStateKey().get();
}
@Override @Override
public int horizontalSearchStep(int blockY, int searchRadius) { public int horizontalSearchStep(int blockY, int searchRadius) {
return horizontalBiomeSearchQuartStep(blockY, searchRadius); return horizontalBiomeSearchQuartStep(blockY, searchRadius);
@@ -1402,6 +1407,7 @@ final class ModdedBiomePolicy<H, S> implements NativeModdedBiomePolicy<H, S> {
record RuntimeCallbacks(Supplier<Engine> currentEngine, Supplier<Engine> awaitEngine, record RuntimeCallbacks(Supplier<Engine> currentEngine, Supplier<Engine> awaitEngine,
Predicate<Engine> historyBypass, Supplier<Set<String>> configuredStructureKeys, Predicate<Engine> historyBypass, Supplier<Set<String>> configuredStructureKeys,
Function<Engine, Set<String>> retainedBiomeKeys, LongSupplier visibleBiomeSeed) { Function<Engine, Set<String>> retainedBiomeKeys, LongSupplier visibleBiomeSeed,
Supplier<String> structureStateKey) {
} }
} }
@@ -102,6 +102,15 @@ public class ModdedBiomePolicyTest {
assertSame(desert, policy.orderedPossibleBiomes().getFirst()); assertSame(desert, policy.orderedPossibleBiomes().getFirst());
} }
@Test
public void structureStateKeyComesFromTheBoundRuntime() {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(new ArrayList<>()));
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> null, () -> null, engine -> false,
Set::of, engine -> Set.of(), () -> 0L, () -> "epoch:example"));
assertEquals("epoch:example", policy.structureStateKey());
}
@Test @Test
public void missingRequiredStructureBiomesFailBeforePublishingAPartialSet() { public void missingRequiredStructureBiomesFailBeforePublishingAPartialSet() {
AtomicReference<Set<String>> configured = new AtomicReference<>(Set.of("example:missing")); AtomicReference<Set<String>> configured = new AtomicReference<>(Set.of("example:missing"));
@@ -130,7 +139,7 @@ public class ModdedBiomePolicyTest {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>( ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(
new Access(new ArrayList<>(List.of(forest)))); new Access(new ArrayList<>(List.of(forest))));
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> engine, () -> engine, bound -> true, policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> engine, () -> engine, bound -> true,
() -> Set.of(forest.key()), bound -> Set.of(), () -> 0L)); () -> Set.of(forest.key()), bound -> Set.of(), () -> 0L, () -> "transient:test"));
assertSame(forest, policy.requiredStructureBiome(6000, 0, -6000, null)); assertSame(forest, policy.requiredStructureBiome(6000, 0, -6000, null));
assertSame(forest, policy.requiredStructureBiome(6000, -30, -6000, null)); assertSame(forest, policy.requiredStructureBiome(6000, -30, -6000, null));
@@ -212,7 +221,7 @@ public class ModdedBiomePolicyTest {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>( ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(
new Access(new ArrayList<>(List.of(plains, mirage)))); new Access(new ArrayList<>(List.of(plains, mirage))));
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> engine, () -> engine, bound -> false, policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> engine, () -> engine, bound -> false,
() -> Set.of(plains.key(), mirage.key()), bound -> Set.of(), () -> 0L)); () -> Set.of(plains.key(), mirage.key()), bound -> Set.of(), () -> 0L, () -> "transient:test"));
int[] columns = {0, 1024, 2048, 3072, 4096, 5120}; int[] columns = {0, 1024, 2048, 3072, 4096, 5120};
NativeBiomeSourcePolicy.BiomeLocation<BiomeToken> found = policy.findClosestBiome3d( NativeBiomeSourcePolicy.BiomeLocation<BiomeToken> found = policy.findClosestBiome3d(
@@ -241,7 +250,7 @@ public class ModdedBiomePolicyTest {
private static ModdedBiomePolicy<BiomeToken, Object> boundTo(Engine engine) { private static ModdedBiomePolicy<BiomeToken, Object> boundTo(Engine engine) {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(new ArrayList<>())); ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(new ArrayList<>()));
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> engine, () -> engine, bound -> true, policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> engine, () -> engine, bound -> true,
Set::of, bound -> Set.of(), () -> 0L)); Set::of, bound -> Set.of(), () -> 0L, () -> "transient:test"));
return policy; return policy;
} }
@@ -249,7 +258,7 @@ public class ModdedBiomePolicyTest {
AtomicReference<Set<String>> configured) { AtomicReference<Set<String>> configured) {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(entries)); ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(entries));
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> null, () -> null, engine -> false, policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(() -> null, () -> null, engine -> false,
configured::get, engine -> Set.of(), () -> 0L)); configured::get, engine -> Set.of(), () -> 0L, () -> "transient:test"));
return policy; return policy;
} }
@@ -0,0 +1,64 @@
package art.arcane.volmlib.nativelib.minecraft26_2.modded;
import art.arcane.volmlib.nativelib.terrain.NativeModdedBiomePolicy;
import com.google.gson.JsonElement;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import net.minecraft.SharedConstants;
import net.minecraft.core.Holder;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate;
import org.junit.BeforeClass;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class NativeModdedBiomeSourceCodecTest {
@BeforeClass
public static void bootstrap() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
public void runtimeSourceEncodeReportsErrorInsteadOfThrowing() {
DataResult<JsonElement> result = BiomeSource.CODEC.encodeStart(JsonOps.INSTANCE, runtimeSource("epoch:unused"));
assertTrue(result.isError());
}
@Test
@SuppressWarnings("unchecked")
public void structureStateSourceEncodesItsGenerationKey() throws ReflectiveOperationException {
BiomeSource structureState = structureState(runtimeSource("epoch:example"));
MapCodec<BiomeSource> codec = (MapCodec<BiomeSource>) NativeModdedBiomeSource.STRUCTURE_STATE_CODEC;
JsonElement encoded = codec.codec().encodeStart(JsonOps.INSTANCE, structureState).getOrThrow();
assertEquals("epoch:example", encoded.getAsJsonObject().get("generation").getAsString());
assertTrue(codec.codec().parse(JsonOps.INSTANCE, encoded).isError());
}
private static BiomeSource structureState(NativeModdedBiomeSource<?> source) throws ReflectiveOperationException {
Class<?> type = Class.forName(NativeModdedBiomeSource.class.getName() + "$StructureStateBiomeSource");
Constructor<?> constructor = type.getDeclaredConstructor(NativeModdedBiomeSource.class, Set.class);
constructor.setAccessible(true);
return (BiomeSource) constructor.newInstance(source, Set.<Holder<Biome>>of());
}
@SuppressWarnings("unchecked")
private static NativeModdedBiomeSource<NativeModdedBiomePolicy<Holder<Biome>, Climate.Sampler>> runtimeSource(String key) {
NativeModdedBiomePolicy<Holder<Biome>, Climate.Sampler> policy = mock(NativeModdedBiomePolicy.class);
when(policy.structureStateKey()).thenReturn(key);
return new NativeModdedBiomeSource<>(new NativeModdedBiomeSource.Options<>(
mock(BiomeSource.class), () -> null, access -> policy));
}
}