Derived retained borrowed pack names

- Retained borrowed-type packs take their pack name from the scoped biome aliases recorded in their generation history instead of the dimension key
- Scoped legacy biome aliases of retained borrowed packs now match the definitions their worlds reference
- A retained pack whose recorded aliases name several packs is refused instead of staged with a guessed name
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-14 20:53:08 -04:00
1 parent 4244aa4ea7
commit a0c9d48601
3 files changed
+155 -1

No files matched your search

@@ -830,7 +830,7 @@ public final class ModdedForcedDatapack {
GenerationEpoch.DimensionContract contract = retained.epoch().dimensionContract();
Optional<ModdedWorldgenIds.ScopedDimension> scoped = ModdedWorldgenIds.scopedDimensionType(contract.dimensionTypeKey());
if (scoped.isEmpty()) {
return PackStageContext.retained(normalizedRoot, contract.dimensionKey(), retained.epoch());
return PackStageContext.retained(normalizedRoot, retainedPackName(retained.epoch(), normalizedRoot), retained.epoch());
}
ModdedWorldgenIds.ScopedDimension identity = scoped.get();
if (!identity.dimension().equals(contract.dimensionKey())) {
@@ -849,6 +849,16 @@ public final class ModdedForcedDatapack {
return PackStageContext.installed(normalizedRoot, packName, legacyDimensions);
}
static String retainedPackName(GenerationEpoch epoch, Path packRoot) throws IOException {
String dimensionKey = epoch.dimensionContract().dimensionKey();
Set<String> packs = ModdedWorldgenIds.aliasPacks(epoch.registryContract(), dimensionKey);
if (packs.size() > 1) {
throw new IOException("Retained Iris generation pack at " + packRoot
+ " records scoped biome aliases from several packs " + packs + ".");
}
return packs.isEmpty() ? dimensionKey : packs.iterator().next();
}
private static RetainedPack retainedPack(Path packRoot) throws IOException {
Path epochRoot = packRoot.getParent();
Path epochsRoot = epochRoot == null ? null : epochRoot.getParent();
@@ -2,12 +2,17 @@ package art.arcane.iris.modded;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.generation.terrain.IrisDimension;
import art.arcane.iris.world.history.GenerationRegistryContract;
import art.arcane.iris.world.history.GenerationRegistryContract.PhysicalResourceKey;
import art.arcane.iris.world.history.GenerationRegistryContractFactory;
import java.nio.charset.StandardCharsets;
import java.util.HexFormat;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
public final class ModdedWorldgenIds {
private static final String NAMESPACE = "irisworldgen";
@@ -68,6 +73,41 @@ public final class ModdedWorldgenIds {
return Optional.of(new ScopedDimension(pack, dimension));
}
static Set<String> aliasPacks(GenerationRegistryContract contract, String dimension) {
Set<String> packs = new TreeSet<>();
for (PhysicalResourceKey key : contract.definitions().keySet()) {
if (!GenerationRegistryContractFactory.BIOME_REGISTRY.equals(key.registryKey())) {
continue;
}
Optional<ScopedDimension> scoped = scopedBiome(key.resourceKey());
if (scoped.isPresent() && scoped.get().dimension().equals(dimension)) {
packs.add(scoped.get().pack());
}
}
return packs;
}
static Optional<ScopedDimension> scopedBiome(String biomeRef) {
String prefix = NAMESPACE + ":";
if (biomeRef == null || !biomeRef.startsWith(prefix)) {
return Optional.empty();
}
String[] parts = biomeRef.substring(prefix.length()).split("/", 6);
if (parts.length != 6
|| !"packs".equals(parts[0])
|| !"dimensions".equals(parts[2])
|| !"biomes".equals(parts[4])
|| parts[5].isEmpty()) {
return Optional.empty();
}
String pack = decode(parts[1]);
String dimension = decode(parts[3]);
if (pack == null || dimension == null) {
return Optional.empty();
}
return Optional.of(new ScopedDimension(pack, dimension));
}
public static String displayName(String presetPath) {
String[] parts = presetPath.split("/");
if (parts.length != 5 || !"packs".equals(parts[0])