Complete Milestone 5 acceptance and streamline tests and assets (#42)
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-10-08 06:01:33 -04:00
1 parent 32b676db30
commit a03e005a03
30 files changed
+127 -70

No files matched your search

@@ -311,45 +311,51 @@ public final class AgeFeatureSelection {
}
public static boolean isRock(ResourceLocation choice) {
return choice.equals(ResourceLocation.fromNamespaceAndPath("rivencraft", "rocks"));
return is(choice, "rocks");
}
public static boolean isLake(ResourceLocation choice) {
return choice.getNamespace().equals("rivencraft") && List.of(
"surface_lakes", "deep_lakes", "lava_lakes").contains(choice.getPath());
if (!choice.getNamespace().equals("rivencraft")) return false;
return switch (choice.getPath()) {
case "surface_lakes", "deep_lakes", "lava_lakes" -> true;
default -> false;
};
}
public static boolean surfaceVegetation(ResourceLocation choice) {
return choice.getNamespace().equals("rivencraft")
&& List.of("flowers", "trees", "huge_trees").contains(choice.getPath());
if (!choice.getNamespace().equals("rivencraft")) return false;
return switch (choice.getPath()) {
case "flowers", "trees", "huge_trees" -> true;
default -> false;
};
}
public static boolean caves(ResourceLocation choice) {
return choice.equals(ResourceLocation.fromNamespaceAndPath("rivencraft", "caves"));
return is(choice, "caves");
}
public static boolean ravines(ResourceLocation choice) {
return choice.equals(ResourceLocation.fromNamespaceAndPath("rivencraft", "ravines"));
return is(choice, "ravines");
}
public static boolean floatingIslands(ResourceLocation choice) {
return choice.equals(ResourceLocation.fromNamespaceAndPath("rivencraft", "floating_islands"));
return is(choice, "floating_islands");
}
public static boolean tendrils(ResourceLocation choice) {
return choice.equals(id("tendrils"));
return is(choice, "tendrils");
}
public static boolean spheres(ResourceLocation choice) {
return choice.equals(id("spheres"));
return is(choice, "spheres");
}
public static boolean spikes(ResourceLocation choice) {
return choice.equals(id("spikes"));
return is(choice, "spikes");
}
public static boolean obelisks(ResourceLocation choice) {
return choice.equals(id("obelisks"));
return is(choice, "obelisks");
}
private static boolean solidFeature(ResourceLocation choice) {
@@ -358,7 +364,11 @@ public final class AgeFeatureSelection {
}
public static boolean skylands(ResourceLocation choice) {
return choice.equals(id("skylands"));
return is(choice, "skylands");
}
private static boolean is(ResourceLocation choice, String path) {
return choice.getNamespace().equals("rivencraft") && choice.getPath().equals(path);
}
public static boolean supportsSurfaceVegetation(ResourceLocation id, RegistryAccess registries) {
@@ -18,7 +18,7 @@ import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
/** Authored structure pages gate their own structure sets without enabling unrelated structures. */
@GameTestHolder(Rivencraft.MOD_ID)
@GameTestHolder("rivencraft_archive_generation")
@PrefixGameTestTemplate(false)
public final class AgeStructureGameTests {
private static final Map<String, ResourceLocation> SETS = Map.ofEntries(
@@ -23,7 +23,7 @@ import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
/** Issue #35: authored decorations must resolve to real placed features and survive plan reload. */
@GameTestHolder(Rivencraft.MOD_ID)
@GameTestHolder("rivencraft_archive_generation")
@PrefixGameTestTemplate(false)
public final class FeatureWritingGameTests {
private FeatureWritingGameTests() {}
@@ -24,7 +24,7 @@ public final class SymbolPageItemRenderer extends BlockEntityWithoutLevelRendere
ResourceLocation texture = switch (PageItem.content(stack).kind()) {
case BLANK -> texture("page");
case LINK_PANEL -> texture("page_link_panel");
case UNRESOLVED_SYMBOL -> texture("page_unresolved");
case UNRESOLVED_SYMBOL -> texture("page_symbol");
case SYMBOL -> SymbolPageTextures.forItem(stack);
};
VertexConsumer vertices = buffers.getBuffer(RenderType.entityCutoutNoCull(texture));
@@ -73,12 +73,12 @@ public final class SymbolPageTextures {
public static ResourceLocation forDisplay(SymbolDisplayMetadata display) {
return display.resolved()
? forSymbol(display.id(), display.poem(), false)
: texture("item/page_unresolved");
: FALLBACK;
}
private static ResourceLocation forPage(ItemStack stack, boolean item) {
PageContent content = PageItem.content(stack);
if (content.kind() == PageContent.Kind.UNRESOLVED_SYMBOL) return texture("item/page_unresolved");
if (content.kind() == PageContent.Kind.UNRESOLVED_SYMBOL) return FALLBACK;
if (content.kind() != PageContent.Kind.SYMBOL) return FALLBACK;
SymbolDisplayMetadata metadata = stack.get(ModDataComponents.PAGE_SYMBOL_DISPLAY.get());
ResourceLocation id = content.symbol().orElseThrow().id();
@@ -8,7 +8,7 @@ import net.minecraft.resources.ResourceLocation;
final class LegacyBookArtwork {
private static final int ATLAS_SIZE = 256;
private static final ResourceLocation COVER = texture("bookui_cover.png");
private static final ResourceLocation LEFT_PAGE = texture("bookui_pagel.png");
private static final ResourceLocation LEFT_PAGE = texture("notebook_pages.png");
private static final ResourceLocation RIGHT_PANEL = texture("bookui_pager.png");
private static final ResourceLocation RIGHT_FULL = texture("bookui_rpage_full.png");
@@ -101,7 +101,6 @@ public final class BookBinderGameTests {
helper.succeed();
}
@GameTest(template = "empty")
public static void conflictingGrammarKeepsBinderInputsRecoverable(GameTestHelper helper) {
BookBinderBlockEntity binder = place(helper);
binder.setTitle("Recoverable Duplicate");
@@ -138,7 +138,6 @@ public final class WritingDataGameTests {
helper.succeed();
}
@GameTest(template = "empty")
public static void semanticSchemaIsServerOnlyBoundedAndV1Compatible(GameTestHelper helper) {
var builtIn = SymbolCatalog.find(reference("rivencraft:terrain/standard")).orElseThrow();
helper.assertValueEqual(builtIn.schemaVersion(), 2, "Built-in symbol must use semantic schema v2");
@@ -23,7 +23,6 @@ import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
public final class WritingGrammarGameTests {
private WritingGrammarGameTests() {}
@GameTest(template = "empty")
public static void orderedGrammarAcceptsPartialWritingAndDiagnosesInvalidSequences(GameTestHelper helper) {
SymbolReference terrain = ref("rivencraft:terrain/standard");
SymbolReference nativeBiomes = ref("rivencraft:biome/native");
@@ -26,7 +26,7 @@ import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
/** Dense Ores remains authored-only and discovers ore configurations without a namespace allow-list. */
@GameTestHolder(Rivencraft.MOD_ID)
@GameTestHolder("rivencraft_archive_generation")
@PrefixGameTestTemplate(false)
public final class AgeDenseOreGameTests {
private AgeDenseOreGameTests() {}
@@ -23,7 +23,7 @@ import net.minecraft.world.level.block.Blocks;
import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
@GameTestHolder(Rivencraft.MOD_ID)
@GameTestHolder("rivencraft_archive_generation")
@PrefixGameTestTemplate(false)
public final class CrystalFormationsGameTests {
private CrystalFormationsGameTests() {}
@@ -20,7 +20,7 @@ import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
/** Obelisks must retain ordered materials and generate a stable Legacy-sized shape. */
@GameTestHolder(Rivencraft.MOD_ID)
@GameTestHolder("rivencraft_archive_generation")
@PrefixGameTestTemplate(false)
public final class ObelisksGameTests {
private ObelisksGameTests() {}
@@ -1,6 +1,5 @@
package net.dnorberg.rivencraft.world;
import net.dnorberg.rivencraft.Rivencraft;
import net.minecraft.gametest.framework.GameTest;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.world.level.block.Blocks;
@@ -8,7 +7,7 @@ import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
/** Checks the Legacy-style filter independently of a slow dimension-generation test. */
@GameTestHolder(Rivencraft.MOD_ID)
@GameTestHolder("rivencraft_archive_generation")
@PrefixGameTestTemplate(false)
public final class SkylandsFeatureGameTests {
private SkylandsFeatureGameTests() {}
@@ -20,7 +20,7 @@ import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
/** Pure selection and footprint checks; runtime carving is left to the in-game visual check. */
@GameTestHolder(Rivencraft.MOD_ID)
@GameTestHolder("rivencraft_archive_generation")
@PrefixGameTestTemplate(false)
public final class StarFissureGameTests {
private StarFissureGameTests() {}
@@ -11,10 +11,13 @@ import net.dnorberg.rivencraft.writing.SymbolSemantics.ChoiceValue;
import net.dnorberg.rivencraft.writing.SymbolSemantics.Role;
import net.minecraft.resources.ResourceLocation;
/** Server-owned interpretation of ordered writing; compilation belongs to the next release slice. */
/** Server-owned interpretation of ordered writing before Age-plan compilation. */
public final class WritingGrammar {
// A newly assembled book has one Link Panel plus at most 27 page positions.
public static final int MAX_NEW_ENTRIES = NotebookContents.MAX_PAGES + 1;
private static final Set<String> MATERIAL_FEATURES = Set.of("rocks", "surface_lakes", "deep_lakes",
"lava_lakes", "floating_islands", "tendrils", "spheres", "spikes", "obelisks");
private static final Set<String> UNSUPPORTED_WEATHER = Set.of("snow", "cloudy", "rain");
private WritingGrammar() {}
@@ -77,9 +80,8 @@ public final class WritingGrammar {
pendingBlock = parsed;
} else if (role == Role.FEATURE && pendingBlock != null) {
ResourceLocation feature = ((SymbolSemantics.ResourceValue) parsed.semantics().value()).id();
if (!Set.of("rocks", "surface_lakes", "deep_lakes", "lava_lakes",
"floating_islands", "tendrils", "spheres", "spikes", "obelisks")
.contains(feature.getPath()) || !feature.getNamespace().equals("rivencraft")) {
if (!MATERIAL_FEATURES.contains(feature.getPath())
|| !feature.getNamespace().equals("rivencraft")) {
diagnostics.add(new Diagnostic(Code.MISPLACED_MODIFIER, pendingBlock.index(),
"This feature cannot consume a material page"));
}
@@ -87,7 +89,7 @@ public final class WritingGrammar {
}
if (role == Role.ANGLE_MODIFIER || role == Role.WEATHER
&& parsed.semantics().value() instanceof ChoiceValue choice
&& Set.of("snow", "cloudy", "rain").contains(choice.id())) {
&& UNSUPPORTED_WEATHER.contains(choice.id())) {
diagnostics.add(new Diagnostic(Code.UNSUPPORTED_ENVIRONMENT, index,
"This environment effect needs renderer or precipitation support"));
}
@@ -1 +1 @@
{"parent":"minecraft:block/cube_all","textures":{"all":"rivencraft:block/budding_crystal"}}
{"parent":"minecraft:block/cube_all","textures":{"all":"rivencraft:block/crystal_block"}}
@@ -1,6 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "rivencraft:item/page_unresolved"
"layer0": "rivencraft:item/page_symbol"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB