Semantic registry validation

- Generated registry validation always re-renders recorded semantics with the current fixer
- Validation canonicalizes the rendering like the installer
- Renderer changes need no version bump
- The renderer identity SPI, both identity strings and the identity-based source preference are gone
- New captures record the fixer class as an informational renderer identity
- The v1 history format is unchanged
- The modded forced datapack, world check and datapack command use the runtime data version
- That is the same data version validation uses
- Tests cover a renderer change under an unchanged identity
- Tests cover 26.3 bare natural_mob_spawns history against the overlay rendering
- Tests cover semantic round trips for every supported fixer
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-29 05:41:18 -04:00
1 parent aa428c0383
commit 3e4a2432bc
16 files changed
+409 -207

No files matched your search

@@ -314,12 +314,13 @@ public final class ModdedForcedDatapack {
} catch (NoSuchAlgorithmException missing) {
throw new IllegalStateException("SHA-256 is unavailable", missing);
}
DataVersion dataVersion = DataVersion.getRuntime();
digest.update((HASH_SALT + '|' + ModdedEngineBootstrap.loader().platformName()
+ '|' + DataVersion.V26_3.getPackFormat() + '\n').getBytes(StandardCharsets.UTF_8));
+ '|' + dataVersion.getPackFormat() + '\n').getBytes(StandardCharsets.UTF_8));
String inputFingerprint = IrisDatapackCompiler.computeInputFingerprint(
compilationPackRoots(),
List.of(),
DataVersion.V26_3.get(),
dataVersion.get(),
false
);
digest.update(inputFingerprint.getBytes(StandardCharsets.UTF_8));
@@ -328,7 +329,7 @@ public final class ModdedForcedDatapack {
private static void writeStagedPack(Path stagingDirectory) throws IOException {
Map<String, KSet<String>> seenBiomes = new LinkedHashMap<>();
IDataFixer fixer = DataVersion.V26_3.get();
IDataFixer fixer = DataVersion.getRuntime().get();
int packCount = 0;
KList<String> presetIds = new KList<>();
@@ -679,7 +680,7 @@ public final class ModdedForcedDatapack {
}
static void writePackMeta(Path packDirectory) throws IOException {
int packFormat = DataVersion.V26_3.getPackFormat();
int packFormat = DataVersion.getRuntime().getPackFormat();
String json = "{\n"
+ " \"pack\": {\n"
+ " \"description\": \"Iris world generation biomes and dimension types for installed packs.\",\n"
@@ -9,12 +9,10 @@ import java.util.Objects;
final class ModdedGenerationRegistry implements PlatformGenerationRegistry {
private final NativeGenerationRegistry nativeRegistry;
private final String runtimeIdentity;
private final String rendererIdentity;
ModdedGenerationRegistry(NativeGenerationRegistry nativeRegistry, Identity identity) {
ModdedGenerationRegistry(NativeGenerationRegistry nativeRegistry, String runtimeIdentity) {
this.nativeRegistry = Objects.requireNonNull(nativeRegistry, "nativeRegistry");
this.runtimeIdentity = requireText(identity.runtime(), "runtimeIdentity");
this.rendererIdentity = requireText(identity.renderer(), "rendererIdentity");
this.runtimeIdentity = requireText(runtimeIdentity, "runtimeIdentity");
}
@Override
@@ -22,11 +20,6 @@ final class ModdedGenerationRegistry implements PlatformGenerationRegistry {
return runtimeIdentity;
}
@Override
public String generatedDefinitionRendererIdentity() {
return rendererIdentity;
}
@Override
public String customBiomeResourceKey(String identitySha256) {
return PlatformGenerationRegistry.contentAddressedCustomBiomeResourceKey(identitySha256);
@@ -75,7 +68,4 @@ final class ModdedGenerationRegistry implements PlatformGenerationRegistry {
}
return required;
}
record Identity(String runtime, String renderer) {
}
}
@@ -357,8 +357,7 @@ public final class ModdedPlatform implements IrisPlatform {
throw new IllegalStateException("Minecraft server is not ready for generation registry capture.");
}
return new ModdedGenerationRegistry(NativeModdedServer.registryDefinitions(ModdedEngineBootstrap::currentServer),
new ModdedGenerationRegistry.Identity("modded-generation-registry-v1",
"modded-generated-registry-json-v1|minecraft:" + BuildConstants.MINECRAFT_VERSION));
"modded-generation-registry-v1");
}
}
@@ -55,7 +55,7 @@ final class WorldCheckDimensionContract {
}
static Dimension expectedDimensionContract(IrisDimension dimension) {
JSONObject json = new JSONObject(dimension.getDimensionType().toJson(DataVersion.V26_3.get()));
JSONObject json = new JSONObject(dimension.getDimensionType().toJson(DataVersion.getRuntime().get()));
return new Dimension(
json.getInt("min_y"),
json.getInt("height"),
@@ -165,7 +165,7 @@ public final class ModdedDatapackCommands {
IrisDimension dimension = engine.getDimension();
String json;
try {
json = dimension.getDimensionType().toJson(DataVersion.V26_3.get());
json = dimension.getDimensionType().toJson(DataVersion.getRuntime().get());
} catch (Throwable e) {
ModdedIrisLog.error("Iris dimension type generation failed for {}", dimension.getLoadKey(), e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_DIMENSION_TYPE_GENERATION_FAILED, MessageArgument.untrusted("value", level.name()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage()))));
@@ -187,7 +187,7 @@ public final class ModdedDatapackCommands {
}
File mcmeta = new File(worldDatapacksFolder(server), WORLD_PACK_NAME + "/pack.mcmeta");
int packFormat = DataVersion.V26_3.getPackFormat();
int packFormat = DataVersion.getRuntime().getPackFormat();
String meta = "{\n"
+ " \"pack\": {\n"
+ " \"description\": \"Iris dimension types derived from the installed Iris packs.\",\n"