mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-12 03:24:14 +00:00
Merge branch 'render-drift' into review
This commit is contained in:
+1
-2
@@ -15,7 +15,6 @@ import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedBlockState;
|
||||
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeBlockResolver;
|
||||
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeRegistryAccess;
|
||||
import art.arcane.volmlib.nativelib.v26_3_R1.terrain.NativeGenerationRegistryImpl;
|
||||
import art.arcane.volmlib.nativelib.v26_3_R1.terrain.NativeWorldGenerationImpl;
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeBiome;
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeBlockProperty;
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
|
||||
@@ -49,7 +48,7 @@ final class HeadlessNativePlatform implements IrisPlatform, PlatformRegistries,
|
||||
return access;
|
||||
}
|
||||
throw new IllegalStateException("Generation registry contract requires loaded native registries");
|
||||
}), "bukkit-generation-registry-v1", new NativeWorldGenerationImpl().generationRendererIdentity());
|
||||
}), "bukkit-generation-registry-v1");
|
||||
nativeAccess = new NativeRegistryAccess(new NativeRegistryAccess.Configuration(registries,
|
||||
() -> { throw new UnsupportedOperationException("Headless reloadable registries are not loaded"); },
|
||||
message -> { throw new IllegalStateException("Unavailable native registry: " + message); }));
|
||||
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
package art.arcane.iris.probe;
|
||||
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustom;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustomSpawn;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustomSpawnType;
|
||||
import art.arcane.iris.pack.datapack.v263.DataFixerV263;
|
||||
import art.arcane.iris.spi.PlatformGenerationRegistry;
|
||||
import art.arcane.iris.world.history.GenerationRegistryContract;
|
||||
import art.arcane.iris.world.history.GenerationRegistryContractFactory;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
public final class BareMobSpawnHistoryTest {
|
||||
private static final String LEGACY_RENDERER_IDENTITY = "bukkit-v26_3_R1-generated-registry-json-v1";
|
||||
private static final String NATURAL_MOB_SPAWNS = "minecraft:gameplay/natural_mob_spawns";
|
||||
private static final GenerationRegistryContract.PhysicalResourceKey INSTALLED =
|
||||
new GenerationRegistryContract.PhysicalResourceKey(
|
||||
GenerationRegistryContractFactory.BIOME_REGISTRY,
|
||||
"iris:biomes/" + "c".repeat(64)
|
||||
);
|
||||
private static HeadlessNativeRegistries loaded;
|
||||
private static PlatformGenerationRegistry registry;
|
||||
|
||||
@BeforeClass
|
||||
public static void installOverlayRendering() throws IOException {
|
||||
assertNull(Bukkit.getServer());
|
||||
loaded = HeadlessNativeRegistries.load(Map.of(
|
||||
"data/iris/worldgen/biome/biomes/" + "c".repeat(64) + ".json",
|
||||
spawningBiome().generateJson(new DataFixerV263())
|
||||
));
|
||||
registry = new HeadlessNativePlatform(new File("unused-native-platform"), loaded::registries)
|
||||
.generationRegistry();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void closeRegistries() throws IOException {
|
||||
if (loaded != null) {
|
||||
loaded.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bareMobSpawnHistoryValidatesAgainstTheInstalledOverlayRendering() throws IOException {
|
||||
GenerationRegistryContract legacy = legacyContract(INSTALLED, spawningBiome());
|
||||
GenerationRegistryContract.GeneratedSource source = legacy.generatedSources().get(INSTALLED);
|
||||
assertEquals(GenerationRegistryContract.FINGERPRINT_SCHEMA_VERSION_ONE, legacy.fingerprintSchema());
|
||||
assertEquals(LEGACY_RENDERER_IDENTITY, source.rendererIdentity());
|
||||
assertNotEquals(
|
||||
JsonParser.parseString(source.sourceJson()),
|
||||
JsonParser.parseString(registry.generatedDefinition(
|
||||
INSTALLED.registryKey(),
|
||||
INSTALLED.resourceKey()
|
||||
).value())
|
||||
);
|
||||
|
||||
GenerationRegistryContract available = GenerationRegistryContractFactory.captureRequiredDefinitions(
|
||||
Set.of(legacy),
|
||||
new DataFixerV263(),
|
||||
registry
|
||||
);
|
||||
|
||||
legacy.requireDefinitionsAvailableIn(available);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bareMobSpawnHistoryStillRejectsDifferentSemantics() throws IOException {
|
||||
GenerationRegistryContract changed = legacyContract(INSTALLED, spawningBiome().setTemperature(0.2D));
|
||||
|
||||
IOException failure = assertThrows(IOException.class,
|
||||
() -> GenerationRegistryContractFactory.captureRequiredDefinitions(
|
||||
Set.of(changed),
|
||||
new DataFixerV263(),
|
||||
registry
|
||||
));
|
||||
|
||||
assertEquals("Historical generated registry definition changed for minecraft:worldgen/biome / "
|
||||
+ INSTALLED.resourceKey() + ".", failure.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bareMobSpawnHistoryStillRejectsAMissingDefinition() throws IOException {
|
||||
GenerationRegistryContract missing = legacyContract(new GenerationRegistryContract.PhysicalResourceKey(
|
||||
GenerationRegistryContractFactory.BIOME_REGISTRY,
|
||||
"iris:biomes/" + "d".repeat(64)
|
||||
), spawningBiome());
|
||||
|
||||
assertThrows(IOException.class, () -> GenerationRegistryContractFactory.captureRequiredDefinitions(
|
||||
Set.of(missing),
|
||||
new DataFixerV263(),
|
||||
registry
|
||||
));
|
||||
}
|
||||
|
||||
private static GenerationRegistryContract legacyContract(
|
||||
GenerationRegistryContract.PhysicalResourceKey key,
|
||||
IrisBiomeCustom biome
|
||||
) {
|
||||
JsonObject rendered = JsonParser.parseString(biome.generateJson(new DataFixerV263())).getAsJsonObject();
|
||||
JsonObject attributes = rendered.getAsJsonObject("attributes");
|
||||
attributes.add(NATURAL_MOB_SPAWNS, attributes.getAsJsonObject(NATURAL_MOB_SPAWNS).get("argument"));
|
||||
String captured = registry.canonicalDefinition(key.registryKey(), key.resourceKey(), rendered.toString())
|
||||
.value();
|
||||
String semantic = GenerationRegistryContractFactory.customBiomeEffectiveSemanticJson(biome, null);
|
||||
GenerationRegistryContract.GeneratedSource source = new GenerationRegistryContract.GeneratedSource(
|
||||
GenerationRegistryContractFactory.CUSTOM_BIOME_EFFECTIVE_SOURCE_SCHEMA,
|
||||
GenerationRegistryContractFactory.fingerprintCustomBiomeAuthoredDefinition(semantic),
|
||||
semantic,
|
||||
LEGACY_RENDERER_IDENTITY,
|
||||
GenerationRegistryContractFactory.fingerprintDefinition(
|
||||
key,
|
||||
PlatformGenerationRegistry.Definition.exactJson(captured),
|
||||
"generated"
|
||||
),
|
||||
captured
|
||||
);
|
||||
return GenerationRegistryContract.fromDefinitionsAndGeneratedSources(
|
||||
Map.of(key, GenerationRegistryContractFactory.fingerprintGeneratedSemantic(key, source)),
|
||||
Map.of(key, source)
|
||||
);
|
||||
}
|
||||
|
||||
private static IrisBiomeCustom spawningBiome() {
|
||||
return new IrisBiomeCustom()
|
||||
.setId("tester")
|
||||
.setSpawnRarity(2)
|
||||
.setSpawns(new KList<>(
|
||||
new IrisBiomeCustomSpawn()
|
||||
.setType("minecraft:zombie")
|
||||
.setGroup(IrisBiomeCustomSpawnType.MONSTER)
|
||||
.setMinCount(2)
|
||||
.setMaxCount(4)
|
||||
.setWeight(7),
|
||||
new IrisBiomeCustomSpawn()
|
||||
.setType("minecraft:cow")
|
||||
.setGroup(IrisBiomeCustomSpawnType.CREATURE)
|
||||
.setMinCount(3)
|
||||
.setMaxCount(3)
|
||||
.setWeight(5)
|
||||
));
|
||||
}
|
||||
}
|
||||
-3
@@ -1,7 +1,6 @@
|
||||
package art.arcane.iris.probe;
|
||||
|
||||
import art.arcane.iris.spi.PlatformGenerationRegistry;
|
||||
import art.arcane.volmlib.nativelib.v26_3_R1.terrain.NativeWorldGenerationImpl;
|
||||
import net.minecraft.data.registries.VanillaRegistries;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.junit.Test;
|
||||
@@ -22,8 +21,6 @@ public final class HeadlessGenerationRegistryTest {
|
||||
HeadlessNativeTestRegistries::get);
|
||||
PlatformGenerationRegistry registry = platform.generationRegistry();
|
||||
assertEquals("bukkit-generation-registry-v1", registry.runtimeIdentity());
|
||||
assertEquals(new NativeWorldGenerationImpl().generationRendererIdentity(),
|
||||
registry.generatedDefinitionRendererIdentity());
|
||||
assertEquals(registry.canonicalDefinition("minecraft:worldgen/biome", "iris:native_test", biome),
|
||||
registry.generatedDefinition("minecraft:worldgen/biome", "iris:native_test"));
|
||||
assertEquals(registry.canonicalDefinition("minecraft:dimension_type", "iris:native_test", dimension),
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package art.arcane.volmlib.nativelib.minecraft26_2.forge;
|
||||
|
||||
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeRegistryDefinitions;
|
||||
import art.arcane.volmlib.nativelib.modded.NativeLoaderOptions;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.RegistrationInfo;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.world.attribute.EnvironmentAttributes;
|
||||
import net.minecraft.world.attribute.modifier.MobSpawnSettingsModifier;
|
||||
import net.minecraft.world.entity.EntityTypes;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.carver.WorldCarver;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraftforge.common.world.BiomeModifier;
|
||||
import net.minecraftforge.common.world.ModifiableBiomeInfo;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class NativeForgeBiomeDefinitionTest {
|
||||
private static final String BIOME_REGISTRY = "minecraft:worldgen/biome";
|
||||
private static final String BIOME_KEY = "iris:biomes/forge_modified";
|
||||
private static final String SOURCE_JSON = "{\"has_precipitation\":true,\"temperature\":0.8,\"downfall\":0.4,"
|
||||
+ "\"effects\":{\"water_color\":\"#3f76e4\"},\"carvers\":[],\"features\":[]}";
|
||||
|
||||
@BeforeClass
|
||||
public static void bootstrap() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatedBiomeDefinitionExcludesForgeBiomeModifierOutput() {
|
||||
MappedRegistry<PlacedFeature> features = new MappedRegistry<>(Registries.PLACED_FEATURE, Lifecycle.stable());
|
||||
Holder.Reference<PlacedFeature> ore = features.register(
|
||||
ResourceKey.create(Registries.PLACED_FEATURE, Identifier.parse("iris:modded_ore")),
|
||||
new PlacedFeature(Holder.direct(mock(Feature.class)), List.of()),
|
||||
RegistrationInfo.BUILT_IN);
|
||||
features.freeze();
|
||||
MappedRegistry<WorldCarver> carvers = new MappedRegistry<>(Registries.CARVER, Lifecycle.stable());
|
||||
carvers.freeze();
|
||||
MappedRegistry<Biome> biomes = new MappedRegistry<>(Registries.BIOME, Lifecycle.stable());
|
||||
RegistryAccess access = new RegistryAccess.ImmutableRegistryAccess(List.of(biomes, features, carvers));
|
||||
Biome source = Biome.DIRECT_CODEC.parse(RegistryOps.create(JsonOps.INSTANCE, access),
|
||||
JsonParser.parseString(SOURCE_JSON)).getOrThrow();
|
||||
Holder.Reference<Biome> biome = biomes.register(
|
||||
ResourceKey.create(Registries.BIOME, Identifier.parse(BIOME_KEY)), source, RegistrationInfo.BUILT_IN);
|
||||
biomes.freeze();
|
||||
biome.value().modifiableBiomeInfo().applyBiomeModifiers(biome, List.of(new ModdedContent(ore)));
|
||||
NativeRegistryDefinitions definitions = new NativeRegistryDefinitions(() -> access,
|
||||
new NativeForgeLoader(new NativeLoaderOptions("irisworldgen", "treefeller",
|
||||
BooleanSupplier::getAsBoolean))::unmodifiedBiome);
|
||||
|
||||
assertEquals(0.1F, biome.value().getBaseTemperature(), 0.0F);
|
||||
assertEquals(0x102030, biome.value().getWaterColor() & 0xFFFFFF);
|
||||
assertTrue(biome.value().getGenerationSettings().hasFeature(ore.value()));
|
||||
assertTrue(biome.value().getAttributes().contains(EnvironmentAttributes.NATURAL_MOB_SPAWNS));
|
||||
assertEquals(JsonParser.parseString(definitions.canonicalDefinition(BIOME_REGISTRY, BIOME_KEY, SOURCE_JSON).value()),
|
||||
JsonParser.parseString(definitions.generatedDefinition(BIOME_REGISTRY, BIOME_KEY).value()));
|
||||
}
|
||||
|
||||
private record ModdedContent(Holder<PlacedFeature> ore) implements BiomeModifier {
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder) {
|
||||
if (phase != Phase.ADD) {
|
||||
return;
|
||||
}
|
||||
builder.climateSettings().setTemperature(0.1F);
|
||||
builder.effects().waterColor(0x102030);
|
||||
builder.attributes().modify(EnvironmentAttributes.NATURAL_MOB_SPAWNS, MobSpawnSettingsModifier.overlay(),
|
||||
new MobSpawnSettings.Builder().addSpawn(EntityTypes.ZOMBIE, 5, 1, 2).build());
|
||||
builder.generationSettings().addFeature(GenerationStep.Decoration.UNDERGROUND_ORES, ore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<? extends BiomeModifier> codec() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -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"
|
||||
|
||||
+2
-12
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public final class ModdedPlatform implements IrisPlatform {
|
||||
this.loader = loader;
|
||||
this.registries = new ModdedRegistries(
|
||||
NativeModdedServer.registryAccess(ModdedEngineBootstrap::currentServer, ModdedRegistries::warnNotReady),
|
||||
ModdedPlatform::generationRegistry);
|
||||
() -> generationRegistry(loader));
|
||||
this.scheduler = new ModdedScheduler();
|
||||
this.structureHooks = new ModdedStructureHooks(ModdedEngineBootstrap::currentServer);
|
||||
this.biomeWriter = new ModdedBiomeWriter(new NativeBiomeRegistry(ModdedEngineBootstrap::currentServer, "minecraft:plains"));
|
||||
@@ -352,13 +352,12 @@ public final class ModdedPlatform implements IrisPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
private static PlatformGenerationRegistry generationRegistry() {
|
||||
private static PlatformGenerationRegistry generationRegistry(NativeModdedLoader loader) {
|
||||
if (ModdedEngineBootstrap.currentServer() == null) {
|
||||
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));
|
||||
return new ModdedGenerationRegistry(NativeModdedServer.registryDefinitions(ModdedEngineBootstrap::currentServer, loader),
|
||||
"modded-generation-registry-v1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -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"),
|
||||
|
||||
+2
-2
@@ -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"
|
||||
|
||||
+28
@@ -20,6 +20,7 @@ package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.volmlib.util.collection.KSet;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.iris.pack.datapack.DataVersion;
|
||||
import art.arcane.iris.pack.datapack.v1217.DataFixerV1217;
|
||||
import art.arcane.iris.world.history.GenerationEpochContractFactory;
|
||||
import art.arcane.iris.world.history.GenerationRegistryContract;
|
||||
@@ -27,6 +28,8 @@ import art.arcane.iris.world.history.GenerationRegistryContractFactory;
|
||||
import art.arcane.iris.generation.biome.IrisCustomBiomeAliasResolver;
|
||||
import art.arcane.iris.generation.terrain.IrisDimension;
|
||||
import art.arcane.iris.generation.terrain.IrisDimensionType;
|
||||
import art.arcane.iris.spi.IrisPlatform;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.spi.PlatformGenerationRegistry;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Set;
|
||||
@@ -48,6 +51,8 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class ModdedForcedDatapackTest {
|
||||
@Test
|
||||
@@ -65,6 +70,29 @@ public class ModdedForcedDatapackTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void metadataFollowsTheRuntimeDataVersionThatValidationUses() throws IOException {
|
||||
IrisPlatform previous = IrisPlatforms.getOrNull();
|
||||
IrisPlatform runtime = mock(IrisPlatform.class);
|
||||
when(runtime.minecraftVersion()).thenReturn("26.2");
|
||||
Path packDirectory = Files.createTempDirectory("iris-modded-runtime-pack-format");
|
||||
IrisPlatforms.unbind();
|
||||
IrisPlatforms.bind(runtime);
|
||||
try {
|
||||
ModdedForcedDatapack.writePackMeta(packDirectory);
|
||||
JSONObject pack = new JSONObject(Files.readString(packDirectory.resolve("pack.mcmeta")))
|
||||
.getJSONObject("pack");
|
||||
assertEquals(DataVersion.getRuntime().getPackFormat(), pack.getInt("pack_format"));
|
||||
assertEquals(DataVersion.V26_2.getPackFormat(), pack.getInt("pack_format"));
|
||||
} finally {
|
||||
IrisPlatforms.unbind();
|
||||
if (previous != null) {
|
||||
IrisPlatforms.bind(previous);
|
||||
}
|
||||
deleteTree(packDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retainedDimensionSourceRendersBeforeNativeRegistryExists() throws Exception {
|
||||
DataFixerV1217 fixer = new DataFixerV1217();
|
||||
|
||||
+6
@@ -12,6 +12,7 @@ import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.EntitySpawnReason;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -91,6 +92,11 @@ public class ModdedPlatformPathsTest {
|
||||
public boolean checkSpawnPosition(Mob mob, ServerLevelAccessor level, EntitySpawnReason reason) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome unmodifiedBiome(Biome biome) {
|
||||
return biome;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class BukkitBinding implements INMSBinding {
|
||||
|
||||
@Override
|
||||
public PlatformGenerationRegistry generationRegistry() {
|
||||
return new BukkitGenerationRegistry(registry, "bukkit-generation-registry-v1", generation.generationRendererIdentity());
|
||||
return new BukkitGenerationRegistry(registry, "bukkit-generation-registry-v1");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-3
@@ -9,13 +9,11 @@ import java.util.Objects;
|
||||
|
||||
public record BukkitGenerationRegistry(
|
||||
NativeGenerationRegistry registry,
|
||||
String runtimeIdentity,
|
||||
String generatedDefinitionRendererIdentity
|
||||
String runtimeIdentity
|
||||
) implements PlatformGenerationRegistry {
|
||||
public BukkitGenerationRegistry {
|
||||
registry = Objects.requireNonNull(registry, "registry");
|
||||
runtimeIdentity = requireText(runtimeIdentity, "runtimeIdentity");
|
||||
generatedDefinitionRendererIdentity = requireText(generatedDefinitionRendererIdentity, "rendererIdentity");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+13
-125
@@ -552,15 +552,14 @@ public final class GenerationRegistryContractFactory {
|
||||
for (Map.Entry<GenerationRegistryContract.PhysicalResourceKey, GenerationRegistryContract.GeneratedSource>
|
||||
entry
|
||||
: requiredContract.generatedSources().entrySet()) {
|
||||
GenerationRegistryContract.GeneratedSource previous = generatedSources.get(entry.getKey());
|
||||
GenerationRegistryContract.GeneratedSource previous = generatedSources.putIfAbsent(
|
||||
entry.getKey(),
|
||||
entry.getValue()
|
||||
);
|
||||
if (previous != null && !sameGeneratedSemantic(previous, entry.getValue())) {
|
||||
throw new IOException("Retained generation epochs require conflicting generated sources for "
|
||||
+ entry.getKey().registryKey() + " / " + entry.getKey().resourceKey() + ".");
|
||||
}
|
||||
generatedSources.put(
|
||||
entry.getKey(),
|
||||
preferredGeneratedSource(previous, entry.getValue(), registry)
|
||||
);
|
||||
}
|
||||
}
|
||||
Map<GenerationRegistryContract.PhysicalResourceKey, String> captured = new TreeMap<>();
|
||||
@@ -596,18 +595,6 @@ public final class GenerationRegistryContractFactory {
|
||||
return GenerationRegistryContract.fromDefinitions(captured);
|
||||
}
|
||||
|
||||
public static String requireGeneratedSource(
|
||||
GenerationRegistryContract contract,
|
||||
GenerationRegistryContract.PhysicalResourceKey key
|
||||
) throws IOException {
|
||||
return requireGeneratedSource(
|
||||
contract,
|
||||
key,
|
||||
DataVersion.getRuntime().get(),
|
||||
IrisPlatforms.get().registries().generationRegistry()
|
||||
);
|
||||
}
|
||||
|
||||
public static String renderGeneratedSource(
|
||||
GenerationRegistryContract contract,
|
||||
GenerationRegistryContract.PhysicalResourceKey key,
|
||||
@@ -622,68 +609,9 @@ public final class GenerationRegistryContractFactory {
|
||||
+ requiredKey.registryKey() + " / " + requiredKey.resourceKey() + ".");
|
||||
}
|
||||
requireGeneratedSemanticFingerprint(requiredKey, source, requiredContract.definitions().get(requiredKey));
|
||||
String sourceFingerprint = fingerprintDefinition(requiredKey,
|
||||
PlatformGenerationRegistry.Definition.exactJson(source.sourceJson()), "generated");
|
||||
if (!source.renderedDefinitionSha256().equals(sourceFingerprint)) {
|
||||
throw new IOException("Historical generated registry source changed for "
|
||||
+ requiredKey.registryKey() + " / " + requiredKey.resourceKey() + ".");
|
||||
}
|
||||
return renderGeneratedSemantic(requiredKey, source, requiredFixer);
|
||||
}
|
||||
|
||||
public static String requireGeneratedSource(
|
||||
GenerationRegistryContract contract,
|
||||
GenerationRegistryContract.PhysicalResourceKey key,
|
||||
IDataFixer fixer
|
||||
) throws IOException {
|
||||
return requireGeneratedSource(
|
||||
contract,
|
||||
key,
|
||||
fixer,
|
||||
IrisPlatforms.get().registries().generationRegistry()
|
||||
);
|
||||
}
|
||||
|
||||
public static String requireGeneratedSource(
|
||||
GenerationRegistryContract contract,
|
||||
GenerationRegistryContract.PhysicalResourceKey key,
|
||||
PlatformGenerationRegistry generationRegistry
|
||||
) throws IOException {
|
||||
return requireGeneratedSource(
|
||||
contract,
|
||||
key,
|
||||
DataVersion.getRuntime().get(),
|
||||
generationRegistry
|
||||
);
|
||||
}
|
||||
|
||||
public static String requireGeneratedSource(
|
||||
GenerationRegistryContract contract,
|
||||
GenerationRegistryContract.PhysicalResourceKey key,
|
||||
IDataFixer fixer,
|
||||
PlatformGenerationRegistry generationRegistry
|
||||
) throws IOException {
|
||||
GenerationRegistryContract requiredContract = Objects.requireNonNull(contract, "contract");
|
||||
GenerationRegistryContract.PhysicalResourceKey requiredKey = Objects.requireNonNull(key, "key");
|
||||
IDataFixer requiredFixer = Objects.requireNonNull(fixer, "fixer");
|
||||
PlatformGenerationRegistry registry = Objects.requireNonNull(
|
||||
generationRegistry,
|
||||
"generationRegistry"
|
||||
);
|
||||
GenerationRegistryContract.GeneratedSource source = requiredContract.generatedSources().get(requiredKey);
|
||||
if (source == null) {
|
||||
throw new IOException("Historical generated registry source is missing for "
|
||||
+ requiredKey.registryKey() + " / " + requiredKey.resourceKey() + ".");
|
||||
}
|
||||
String expectedFingerprint = requiredContract.definitions().get(requiredKey);
|
||||
if (expectedFingerprint == null) {
|
||||
throw new IOException("Historical generated registry definition is missing for "
|
||||
+ requiredKey.registryKey() + " / " + requiredKey.resourceKey() + ".");
|
||||
}
|
||||
requireGeneratedSemanticFingerprint(requiredKey, source, expectedFingerprint);
|
||||
return canonicalGeneratedDefinition(requiredKey, source, requiredFixer, registry).value();
|
||||
}
|
||||
|
||||
public static String fingerprintDefinition(
|
||||
GenerationRegistryContract.PhysicalResourceKey key,
|
||||
PlatformGenerationRegistry.Definition definition,
|
||||
@@ -783,7 +711,7 @@ public final class GenerationRegistryContractFactory {
|
||||
DIMENSION_TYPE_EFFECTIVE_SOURCE_SCHEMA,
|
||||
GenerationEpochContractFactory.fingerprintDimensionType(dimension.getDimensionType()),
|
||||
GenerationEpochContractFactory.dimensionTypeSemanticJson(dimension.getDimensionType()),
|
||||
registry.generatedDefinitionRendererIdentity(),
|
||||
rendererIdentity(fixer),
|
||||
canonicalDefinition
|
||||
);
|
||||
}
|
||||
@@ -833,7 +761,7 @@ public final class GenerationRegistryContractFactory {
|
||||
CUSTOM_BIOME_EFFECTIVE_SOURCE_SCHEMA,
|
||||
generated.semanticFingerprint(),
|
||||
generated.semanticJson(),
|
||||
registry.generatedDefinitionRendererIdentity(),
|
||||
rendererIdentity(fixer),
|
||||
generated.definition()
|
||||
);
|
||||
Set<String> tags = biomeTags.computeIfAbsent(generated.physicalKey().resourceKey(), ignored -> new TreeSet<>());
|
||||
@@ -882,7 +810,7 @@ public final class GenerationRegistryContractFactory {
|
||||
CUSTOM_BIOME_EFFECTIVE_SOURCE_SCHEMA,
|
||||
generated.semanticFingerprint(),
|
||||
generated.semanticJson(),
|
||||
registry.generatedDefinitionRendererIdentity(),
|
||||
rendererIdentity(fixer),
|
||||
generated.definition()
|
||||
);
|
||||
}
|
||||
@@ -1087,32 +1015,9 @@ public final class GenerationRegistryContractFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static GenerationRegistryContract.GeneratedSource preferredGeneratedSource(
|
||||
GenerationRegistryContract.GeneratedSource previous,
|
||||
GenerationRegistryContract.GeneratedSource candidate,
|
||||
PlatformGenerationRegistry registry
|
||||
) {
|
||||
if (previous == null) {
|
||||
return candidate;
|
||||
}
|
||||
String currentRenderer = requireText(
|
||||
registry.generatedDefinitionRendererIdentity(),
|
||||
"Generated registry renderer identity"
|
||||
);
|
||||
boolean previousMatches = previous.rendererIdentity().equals(currentRenderer);
|
||||
boolean candidateMatches = candidate.rendererIdentity().equals(currentRenderer);
|
||||
if (previousMatches != candidateMatches) {
|
||||
return candidateMatches ? candidate : previous;
|
||||
}
|
||||
return generatedSourceOrder(candidate).compareTo(generatedSourceOrder(previous)) < 0
|
||||
? candidate
|
||||
: previous;
|
||||
}
|
||||
|
||||
private static String generatedSourceOrder(GenerationRegistryContract.GeneratedSource source) {
|
||||
return source.rendererIdentity() + '\u0000'
|
||||
+ source.renderedDefinitionSha256() + '\u0000'
|
||||
+ source.sourceJson();
|
||||
// Recorded for diagnostics only. Validation always re-renders the semantics with the current fixer.
|
||||
private static String rendererIdentity(IDataFixer fixer) {
|
||||
return fixer.getClass().getName();
|
||||
}
|
||||
|
||||
private static boolean sameGeneratedSemantic(
|
||||
@@ -1130,36 +1035,19 @@ public final class GenerationRegistryContractFactory {
|
||||
IDataFixer fixer,
|
||||
PlatformGenerationRegistry registry
|
||||
) throws IOException {
|
||||
String currentRenderer = requireText(
|
||||
registry.generatedDefinitionRendererIdentity(),
|
||||
"Generated registry renderer identity"
|
||||
);
|
||||
String renderedSource;
|
||||
if (source.rendererIdentity().equals(currentRenderer)) {
|
||||
renderedSource = source.sourceJson();
|
||||
} else {
|
||||
renderedSource = renderGeneratedSemantic(key, source, fixer);
|
||||
}
|
||||
PlatformGenerationRegistry.Definition definition;
|
||||
String renderedSource = renderGeneratedSemantic(key, source, fixer);
|
||||
try {
|
||||
definition = registry.canonicalDefinition(
|
||||
PlatformGenerationRegistry.Definition definition = registry.canonicalDefinition(
|
||||
key.registryKey(),
|
||||
key.resourceKey(),
|
||||
renderedSource
|
||||
);
|
||||
requireGeneratedDefinition(definition, "historical generated registry definition");
|
||||
return definition;
|
||||
} catch (RuntimeException failure) {
|
||||
throw new IOException("Historical generated registry source is incompatible for "
|
||||
+ key.registryKey() + " / " + key.resourceKey() + ".", failure);
|
||||
}
|
||||
if (source.rendererIdentity().equals(currentRenderer)) {
|
||||
String renderedFingerprint = fingerprintDefinition(key, definition, "generated");
|
||||
if (!source.renderedDefinitionSha256().equals(renderedFingerprint)) {
|
||||
throw new IOException("Historical generated registry source changed for "
|
||||
+ key.registryKey() + " / " + key.resourceKey() + ".");
|
||||
}
|
||||
}
|
||||
return definition;
|
||||
}
|
||||
|
||||
private static String renderGeneratedSemantic(
|
||||
|
||||
@@ -675,11 +675,6 @@ public class IrisDatapackCompilerTest {
|
||||
return "bootstrap-test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generatedDefinitionRendererIdentity() {
|
||||
return "bootstrap-renderer-v1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dimensionTypeResourceKey(String packName, String dimensionKey, String dimensionTypeKey) {
|
||||
return "iris:" + dimensionTypeKey;
|
||||
|
||||
@@ -120,11 +120,6 @@ public class ArchivedRegistryCompilerTest {
|
||||
return "bootstrap-test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generatedDefinitionRendererIdentity() {
|
||||
return "bootstrap-renderer-v1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dimensionTypeResourceKey(String packName, String dimensionKey, String dimensionTypeKey) {
|
||||
return "iris:" + dimensionTypeKey;
|
||||
|
||||
+198
-40
@@ -8,7 +8,11 @@ import art.arcane.iris.pack.datapack.DataVersion;
|
||||
import art.arcane.iris.pack.datapack.IDataFixer;
|
||||
import art.arcane.iris.generation.biome.IrisBiome;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustom;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustomCategory;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustomParticle;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustomPrecipType;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustomSpawn;
|
||||
import art.arcane.iris.generation.biome.IrisBiomeCustomSpawnType;
|
||||
import art.arcane.iris.generation.terrain.IrisDimension;
|
||||
import art.arcane.iris.generation.terrain.IrisDimensionType;
|
||||
import art.arcane.iris.generation.terrain.IrisDimensionTypeOptions;
|
||||
@@ -510,7 +514,7 @@ public class GenerationRegistryContractFactoryTest {
|
||||
GenerationRegistryContractFactory.CUSTOM_BIOME_EFFECTIVE_SOURCE_SCHEMA,
|
||||
semanticFingerprint,
|
||||
semantic,
|
||||
registry.generatedDefinitionRendererIdentity(),
|
||||
"test-renderer-v1",
|
||||
GenerationRegistryContractFactory.fingerprintDefinition(
|
||||
generated,
|
||||
definition,
|
||||
@@ -528,18 +532,18 @@ public class GenerationRegistryContractFactoryTest {
|
||||
|
||||
GenerationRegistryContract available = GenerationRegistryContractFactory.captureRequiredDefinitions(
|
||||
Set.of(required),
|
||||
firstFixer,
|
||||
registry
|
||||
);
|
||||
|
||||
required.requireDefinitionsAvailableIn(available);
|
||||
assertEquals(
|
||||
source,
|
||||
GenerationRegistryContractFactory.requireGeneratedSource(
|
||||
JsonParser.parseString(source),
|
||||
JsonParser.parseString(GenerationRegistryContractFactory.renderGeneratedSource(
|
||||
required,
|
||||
generated,
|
||||
firstFixer,
|
||||
registry
|
||||
)
|
||||
firstFixer
|
||||
))
|
||||
);
|
||||
|
||||
registry.put(generated, PlatformGenerationRegistry.Definition.exactJson(
|
||||
@@ -547,33 +551,199 @@ public class GenerationRegistryContractFactoryTest {
|
||||
));
|
||||
assertThrows(
|
||||
IOException.class,
|
||||
() -> GenerationRegistryContractFactory.captureRequiredDefinitions(Set.of(required), registry)
|
||||
() -> GenerationRegistryContractFactory.captureRequiredDefinitions(
|
||||
Set.of(required),
|
||||
firstFixer,
|
||||
registry
|
||||
)
|
||||
);
|
||||
registry.remove(generated);
|
||||
assertThrows(
|
||||
IOException.class,
|
||||
() -> GenerationRegistryContractFactory.captureRequiredDefinitions(Set.of(required), registry)
|
||||
() -> GenerationRegistryContractFactory.captureRequiredDefinitions(
|
||||
Set.of(required),
|
||||
firstFixer,
|
||||
registry
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validatesTheCurrentRenderingWhenTheRendererChangedUnderTheSameIdentity() throws Exception {
|
||||
FakeGenerationRegistry registry = new FakeGenerationRegistry("runtime-a");
|
||||
GenerationRegistryContract.PhysicalResourceKey generated = key(
|
||||
GenerationRegistryContractFactory.BIOME_REGISTRY,
|
||||
"iris:biomes/" + HASH_A
|
||||
);
|
||||
IrisBiomeCustom customBiome = new IrisBiomeCustom().setId("mist").setTemperature(0.5D);
|
||||
String semantic = GenerationRegistryContractFactory.customBiomeEffectiveSemanticJson(customBiome, null);
|
||||
String capturedSource = customBiome.generateJson(
|
||||
new TaggedBiomeFixer("first"),
|
||||
new ContentGate(null, Map.of(), null)
|
||||
);
|
||||
GenerationRegistryContract.GeneratedSource generatedSource = new GenerationRegistryContract.GeneratedSource(
|
||||
GenerationRegistryContractFactory.CUSTOM_BIOME_EFFECTIVE_SOURCE_SCHEMA,
|
||||
GenerationRegistryContractFactory.fingerprintCustomBiomeAuthoredDefinition(semantic),
|
||||
semantic,
|
||||
"test-renderer-v1",
|
||||
GenerationRegistryContractFactory.fingerprintDefinition(
|
||||
generated,
|
||||
PlatformGenerationRegistry.Definition.exactJson(capturedSource),
|
||||
"generated"
|
||||
),
|
||||
capturedSource
|
||||
);
|
||||
GenerationRegistryContract required = GenerationRegistryContract.fromDefinitionsAndGeneratedSources(
|
||||
Map.of(generated, GenerationRegistryContractFactory.fingerprintGeneratedSemantic(
|
||||
generated,
|
||||
generatedSource
|
||||
)),
|
||||
Map.of(generated, generatedSource)
|
||||
);
|
||||
IDataFixer currentFixer = new TaggedBiomeFixer("second");
|
||||
String installed = GenerationRegistryContractFactory.renderGeneratedSource(required, generated, currentFixer);
|
||||
assertNotEquals(JsonParser.parseString(capturedSource), JsonParser.parseString(installed));
|
||||
registry.put(generated, PlatformGenerationRegistry.Definition.exactJson(installed));
|
||||
|
||||
GenerationRegistryContract available = GenerationRegistryContractFactory.captureRequiredDefinitions(
|
||||
Set.of(required),
|
||||
currentFixer,
|
||||
registry
|
||||
);
|
||||
|
||||
FakeGenerationRegistry changedRenderer = new FakeGenerationRegistry("runtime-b") {
|
||||
@Override
|
||||
public String generatedDefinitionRendererIdentity() {
|
||||
return "test-renderer-v2";
|
||||
}
|
||||
};
|
||||
IDataFixer secondFixer = new TaggedBiomeFixer("second");
|
||||
String rerendered = GenerationRegistryContractFactory.requireGeneratedSource(
|
||||
required,
|
||||
generated,
|
||||
secondFixer,
|
||||
changedRenderer
|
||||
required.requireDefinitionsAvailableIn(available);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void semanticRenderingMatchesTheCapturedRenderingForEverySupportedFixer() throws Exception {
|
||||
IrisData data = mock(IrisData.class);
|
||||
when(data.getContentGate()).thenReturn(new ContentGate(null, Map.of(), null));
|
||||
IrisDimension dimension = new IrisDimension();
|
||||
dimension.setLoadKey("overworld");
|
||||
IrisBiomeCustom biome = richCustomBiome();
|
||||
IrisDimensionTypeOptions options = new IrisDimensionTypeOptions()
|
||||
.coordinateScale(4.0)
|
||||
.ambientLight(0.25F)
|
||||
.fixedTime(18000L)
|
||||
.cloudHeight(-96)
|
||||
.monsterSpawnBlockLightLimit(11)
|
||||
.ultrawarm(IrisDimensionTypeOptions.TriState.TRUE)
|
||||
.natural(IrisDimensionTypeOptions.TriState.FALSE)
|
||||
.piglinSafe(IrisDimensionTypeOptions.TriState.TRUE)
|
||||
.respawnAnchorWorks(IrisDimensionTypeOptions.TriState.TRUE)
|
||||
.bedWorks(IrisDimensionTypeOptions.TriState.FALSE)
|
||||
.raids(IrisDimensionTypeOptions.TriState.FALSE)
|
||||
.skylight(IrisDimensionTypeOptions.TriState.FALSE)
|
||||
.ceiling(IrisDimensionTypeOptions.TriState.TRUE);
|
||||
FakeGenerationRegistry registry = new FakeGenerationRegistry("runtime");
|
||||
GenerationRegistryContract.PhysicalResourceKey dimensionKey = key(
|
||||
GenerationRegistryContractFactory.DIMENSION_TYPE_REGISTRY,
|
||||
"iris:overworld_type"
|
||||
);
|
||||
assertTrue(rerendered.contains("second"));
|
||||
assertNotEquals(source, rerendered);
|
||||
changedRenderer.put(generated, PlatformGenerationRegistry.Definition.exactJson(rerendered));
|
||||
GenerationRegistryContract availableAfterUpgrade = GenerationRegistryContractFactory
|
||||
.captureRequiredDefinitions(Set.of(required), secondFixer, changedRenderer);
|
||||
required.requireDefinitionsAvailableIn(availableAfterUpgrade);
|
||||
int fixers = 0;
|
||||
for (DataVersion version : DataVersion.values()) {
|
||||
if (version == DataVersion.UNSUPPORTED) {
|
||||
continue;
|
||||
}
|
||||
fixers++;
|
||||
IDataFixer fixer = version.get();
|
||||
GenerationRegistryContractFactory.CustomBiomeDefinition captured = GenerationRegistryContractFactory
|
||||
.customBiomeDefinition(data, dimension, biome, fixer, registry);
|
||||
assertCapturedRenderingRoundTrips(
|
||||
version,
|
||||
captured.physicalKey(),
|
||||
GenerationRegistryContractFactory.CUSTOM_BIOME_EFFECTIVE_SOURCE_SCHEMA,
|
||||
captured.semanticFingerprint(),
|
||||
captured.semanticJson(),
|
||||
captured.definition(),
|
||||
fixer,
|
||||
registry
|
||||
);
|
||||
for (IDataFixer.Dimension base : IDataFixer.Dimension.values()) {
|
||||
IrisDimensionType dimensionType = new IrisDimensionType(base, options, 192, 384, -128);
|
||||
assertCapturedRenderingRoundTrips(
|
||||
version,
|
||||
dimensionKey,
|
||||
GenerationRegistryContractFactory.DIMENSION_TYPE_EFFECTIVE_SOURCE_SCHEMA,
|
||||
GenerationEpochContractFactory.fingerprintDimensionType(dimensionType),
|
||||
GenerationEpochContractFactory.dimensionTypeSemanticJson(dimensionType),
|
||||
registry.canonicalDefinition(
|
||||
dimensionKey.registryKey(),
|
||||
dimensionKey.resourceKey(),
|
||||
dimensionType.toJson(fixer)
|
||||
),
|
||||
fixer,
|
||||
registry
|
||||
);
|
||||
}
|
||||
}
|
||||
assertEquals(DataVersion.values().length - 1, fixers);
|
||||
}
|
||||
|
||||
private static void assertCapturedRenderingRoundTrips(
|
||||
DataVersion version,
|
||||
GenerationRegistryContract.PhysicalResourceKey key,
|
||||
String sourceSchema,
|
||||
String semanticFingerprint,
|
||||
String semanticJson,
|
||||
PlatformGenerationRegistry.Definition captured,
|
||||
IDataFixer fixer,
|
||||
PlatformGenerationRegistry registry
|
||||
) throws IOException {
|
||||
GenerationRegistryContract.GeneratedSource source = new GenerationRegistryContract.GeneratedSource(
|
||||
sourceSchema,
|
||||
semanticFingerprint,
|
||||
semanticJson,
|
||||
"round-trip",
|
||||
GenerationRegistryContractFactory.fingerprintDefinition(key, captured, "generated"),
|
||||
captured.value()
|
||||
);
|
||||
GenerationRegistryContract contract = GenerationRegistryContract.fromDefinitionsAndGeneratedSources(
|
||||
Map.of(key, GenerationRegistryContractFactory.fingerprintGeneratedSemantic(key, source)),
|
||||
Map.of(key, source)
|
||||
);
|
||||
String rendered = GenerationRegistryContractFactory.renderGeneratedSource(contract, key, fixer);
|
||||
assertEquals(
|
||||
version + " " + key.resourceKey(),
|
||||
JsonParser.parseString(captured.value()),
|
||||
JsonParser.parseString(registry.canonicalDefinition(
|
||||
key.registryKey(),
|
||||
key.resourceKey(),
|
||||
rendered
|
||||
).value())
|
||||
);
|
||||
}
|
||||
|
||||
private static IrisBiomeCustom richCustomBiome() {
|
||||
String[] entities = {
|
||||
"minecraft:zombie", "minecraft:cow", "minecraft:bat", "minecraft:axolotl",
|
||||
"minecraft:glow_squid", "minecraft:squid", "minecraft:cod", "minecraft:allay"
|
||||
};
|
||||
IrisBiomeCustomSpawnType[] groups = IrisBiomeCustomSpawnType.values();
|
||||
KList<IrisBiomeCustomSpawn> spawns = new KList<>();
|
||||
for (int index = 0; index < groups.length; index++) {
|
||||
spawns.add(new IrisBiomeCustomSpawn()
|
||||
.setType(entities[index % entities.length])
|
||||
.setGroup(groups[index])
|
||||
.setWeight(index + 1)
|
||||
.setMinCount(index + 1)
|
||||
.setMaxCount(index % 2 == 0 ? index + 3 : index + 1));
|
||||
}
|
||||
return new IrisBiomeCustom()
|
||||
.setId("round_trip")
|
||||
.setTemperature(1.25D)
|
||||
.setHumidity(0.3D)
|
||||
.setDownfallType(IrisBiomeCustomPrecipType.snow)
|
||||
.setCategory(IrisBiomeCustomCategory.forest)
|
||||
.setSpawnRarity(7)
|
||||
.setSkyColor("#112233")
|
||||
.setFogColor("445566")
|
||||
.setWaterColor("#778899")
|
||||
.setWaterFogColor("#aabbcc")
|
||||
.setGrassColor("#55aa33")
|
||||
.setFoliageColor("#335511")
|
||||
.setAmbientParticle(new IrisBiomeCustomParticle().setParticle("ash").setRarity(80))
|
||||
.setSpawns(spawns);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -621,18 +791,11 @@ public class GenerationRegistryContractFactoryTest {
|
||||
Map.of(key, GenerationRegistryContractFactory.fingerprintGeneratedSemantic(key, generatedSource)),
|
||||
Map.of(key, generatedSource)
|
||||
);
|
||||
FakeGenerationRegistry upgraded = new FakeGenerationRegistry("runtime-b") {
|
||||
@Override
|
||||
public String generatedDefinitionRendererIdentity() {
|
||||
return "test-renderer-v2";
|
||||
}
|
||||
};
|
||||
|
||||
String rerendered = GenerationRegistryContractFactory.requireGeneratedSource(
|
||||
String rerendered = GenerationRegistryContractFactory.renderGeneratedSource(
|
||||
contract,
|
||||
key,
|
||||
new TaggedBiomeFixer("second"),
|
||||
upgraded
|
||||
new TaggedBiomeFixer("second")
|
||||
);
|
||||
|
||||
assertTrue(rerendered.contains("second"));
|
||||
@@ -750,11 +913,6 @@ public class GenerationRegistryContractFactoryTest {
|
||||
return runtimeIdentity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generatedDefinitionRendererIdentity() {
|
||||
return "test-renderer-v1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String customBiomeResourceKey(String identitySha256) {
|
||||
return "test:biomes/" + identitySha256;
|
||||
|
||||
@@ -11,8 +11,6 @@ public interface PlatformGenerationRegistry extends NativeGenerationRegistry {
|
||||
|
||||
String runtimeIdentity();
|
||||
|
||||
String generatedDefinitionRendererIdentity();
|
||||
|
||||
default String customBiomeResourceKey(String identitySha256) {
|
||||
return contentAddressedCustomBiomeResourceKey(identitySha256);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user