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.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.IntConsumer;
@@ -946,6 +947,14 @@ public final class IrisModdedChunkGenerator implements NativeGeneratorOwner, Nat
+ " 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) {
if (generationMode != ModdedGenerationMode.TRANSIENT_STUDIO) {
return false;
@@ -985,7 +994,7 @@ public final class IrisModdedChunkGenerator implements NativeGeneratorOwner, Nat
ModdedBiomePolicy<H, S> policy = new ModdedBiomePolicy<>(source);
policy.bind(new ModdedBiomePolicy.RuntimeCallbacks(this::boundEngineOrNull, this::awaitStructureEngine,
this::allowsGenerationHistoryBypass, this::configuredStructureBiomeKeys,
IrisModdedChunkGenerator::retainedBiomeKeys, this::visibleBiomeSeed));
IrisModdedChunkGenerator::retainedBiomeKeys, this::visibleBiomeSeed, this::structureStateKey));
return policy;
}
@@ -1395,6 +1395,11 @@ final class ModdedBiomePolicy<H, S> implements NativeModdedBiomePolicy<H, S> {
return requireConfiguredStructureBiomeKeys(exactStructureBiomeKeys());
}
@Override
public String structureStateKey() {
return Objects.requireNonNull(runtime, "runtime").structureStateKey().get();
}
@Override
public int horizontalSearchStep(int blockY, int 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,
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());
}
@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
public void missingRequiredStructureBiomesFailBeforePublishingAPartialSet() {
AtomicReference<Set<String>> configured = new AtomicReference<>(Set.of("example:missing"));
@@ -130,7 +139,7 @@ public class ModdedBiomePolicyTest {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(
new Access(new ArrayList<>(List.of(forest))));
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, -30, -6000, null));
@@ -212,7 +221,7 @@ public class ModdedBiomePolicyTest {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(
new Access(new ArrayList<>(List.of(plains, mirage))));
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};
NativeBiomeSourcePolicy.BiomeLocation<BiomeToken> found = policy.findClosestBiome3d(
@@ -241,7 +250,7 @@ public class ModdedBiomePolicyTest {
private static ModdedBiomePolicy<BiomeToken, Object> boundTo(Engine engine) {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(new ArrayList<>()));
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;
}
@@ -249,7 +258,7 @@ public class ModdedBiomePolicyTest {
AtomicReference<Set<String>> configured) {
ModdedBiomePolicy<BiomeToken, Object> policy = new ModdedBiomePolicy<>(new Access(entries));
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;
}
@@ -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));
}
}