Name Age save folders after player titles
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-21 15:07:41 -04:00
1 parent 2da52f2658
commit 3242eb8192
6 files changed
+65 -8

No files matched your search

@@ -33,6 +33,28 @@ public record AgeDefinition(
return ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "age/" + ageId);
}
public static ResourceLocation namedDimensionId(String ageName) {
StringBuilder pathName = new StringBuilder();
boolean lastWasSeparator = false;
for (int index = 0; index < ageName.length(); index++) {
char character = Character.toLowerCase(ageName.charAt(index));
if (character >= 'a' && character <= 'z' || character >= '0' && character <= '9') {
pathName.append(character);
lastWasSeparator = false;
} else if (!lastWasSeparator && !pathName.isEmpty()) {
pathName.append('_');
lastWasSeparator = true;
}
}
while (!pathName.isEmpty() && pathName.charAt(pathName.length() - 1) == '_') {
pathName.deleteCharAt(pathName.length() - 1);
}
if (pathName.isEmpty()) {
pathName.append("unnamed_age");
}
return ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "age/" + pathName);
}
public AgeDefinition withSpawn(BlockPos spawn) {
return new AgeDefinition(id, name, seed, generationProfile, generationVersion,
createdGameTime, dimensionId, spawn.immutable());
@@ -71,14 +71,16 @@ public final class AgeRegistrySavedData extends SavedData {
return existing;
}
String name = normalizedName(reference.name());
ResourceLocation dimensionId = availableDimensionId(name);
AgeDefinition created = new AgeDefinition(
reference.id(),
normalizedName(reference.name()),
ageSeed(worldSeed, reference.id()),
name,
ageSeed(worldSeed, dimensionId),
AgeDefinition.RANDOM_VANILLA_PROFILE,
AgeDefinition.CURRENT_GENERATION_VERSION,
createdGameTime,
AgeDefinition.dimensionId(reference.id()),
dimensionId,
null
);
ages.put(created.id(), created);
@@ -150,9 +152,25 @@ public final class AgeRegistrySavedData extends SavedData {
return normalized.isEmpty() ? "Unnamed Age" : normalized;
}
private static long ageSeed(long worldSeed, UUID ageId) {
private ResourceLocation availableDimensionId(String ageName) {
ResourceLocation base = AgeDefinition.namedDimensionId(ageName);
ResourceLocation candidate = base;
int suffix = 2;
while (dimensionIdInUse(candidate)) {
candidate = ResourceLocation.fromNamespaceAndPath(
base.getNamespace(), base.getPath() + "_" + suffix++
);
}
return candidate;
}
private boolean dimensionIdInUse(ResourceLocation candidate) {
return ages.values().stream().anyMatch(age -> age.dimensionId().equals(candidate));
}
private static long ageSeed(long worldSeed, ResourceLocation dimensionId) {
// Dynamic Dimensions AR derives each level seed from the primary world
// seed and the dimension key. Persist the same value as Age metadata.
return worldSeed + AgeDefinition.dimensionId(ageId).hashCode();
return worldSeed + dimensionId.hashCode();
}
}
@@ -82,7 +82,8 @@ public final class LinkingGameTests {
@GameTest(template = "empty")
public static void ageDefinitionIsCreatedOnceWithDeterministicData(GameTestHelper helper) {
UUID ageId = UUID.randomUUID();
AgeReference reference = new AgeReference(ageId, "Test Age");
String requestedName = "Test Age " + ageId;
AgeReference reference = new AgeReference(ageId, requestedName);
AgeDefinition first = AgeRegistrySavedData.resolveOrCreate(helper.getLevel(), reference);
AgeDefinition second = AgeRegistrySavedData.resolveOrCreate(
@@ -91,10 +92,17 @@ public final class LinkingGameTests {
AgeDefinition another = AgeRegistrySavedData.resolveOrCreate(
helper.getLevel(), new AgeReference(UUID.randomUUID(), "Another Age")
);
AgeDefinition conflicting = AgeRegistrySavedData.resolveOrCreate(
helper.getLevel(), new AgeReference(UUID.randomUUID(), requestedName)
);
helper.assertValueEqual(second, first,
"An existing Age UUID must retain its original immutable generation definition");
helper.assertValueEqual(first.name(), "Test Age", "The first book name must become the canonical Age name");
helper.assertValueEqual(first.name(), requestedName, "The first book name must become the canonical Age name");
helper.assertValueEqual(first.dimensionId(), AgeDefinition.namedDimensionId(requestedName),
"A new Age dimension folder must derive from the player-assigned name");
helper.assertValueEqual(conflicting.dimensionId().getPath(), first.dimensionId().getPath() + "_2",
"A conflicting Age dimension folder must receive an incrementing suffix");
helper.assertValueEqual(first.generationProfile(), AgeDefinition.RANDOM_VANILLA_PROFILE,
"A page-free book must use the random vanilla generation profile");
helper.assertValueEqual(first.generationVersion(), AgeDefinition.CURRENT_GENERATION_VERSION,