Compare commits

...
1 Commits
Author SHA1 Message Date
dnorberg 68db795216 Cover panel-only book modifiers with regression test
Build / build (push) Canceled after 0s
2026-10-03 07:46:49 -04:00
4 changed files with 58 additions and 3 deletions

No files matched your search

+4 -2
View File
@@ -22,8 +22,10 @@ and link-panel costs in the `writing` section of `rivencraft-server.toml`.
The Ink Mixer now offers a Legacy-style station for producing Link Panels: The Ink Mixer now offers a Legacy-style station for producing Link Panels:
insert paper and Ink Vials, then take a Link Panel from the result slot. Each insert paper and Ink Vials, then take a Link Panel from the result slot. Each
vial fills its 16-unit basin and returns a glass bottle; no server tick is vial fills its 16-unit basin and returns a glass bottle; no server tick is
needed. The earlier paper-in-one-hand method remains available. Ink modifier needed. The earlier paper-in-one-hand method remains available. Ink Mixer
ingredients and link properties are planned for Milestone 5. additives can roll Disarm, Maintain Momentum, and Intra Linking onto a Link
Panel. Descriptive Books retain Disarm and Momentum; Intra Linking is only
meaningful for same-dimension travel with a Linking Book.
The Writing Desk can copy a selected written page from its collection tabs. The Writing Desk can copy a selected written page from its collection tabs.
The Writing Desk is now craftable from planks, a glass bottle, and a feather. The Writing Desk is now craftable from planks, a glass bottle, and a feather.
It occupies two adjacent blocks, with one shared inventory; loaded paper and It occupies two adjacent blocks, with one shared inventory; loaded paper and
+1 -1
View File
@@ -36,7 +36,7 @@ mod_name=Rivencraft
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=LGPL-3.0-or-later mod_license=LGPL-3.0-or-later
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md. # The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
mod_version=0.4.7.3 mod_version=0.4.7.4
immersive_portals_version=6.0.7 immersive_portals_version=6.0.7
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources. # This should match the base package used for the mod sources.
@@ -6,6 +6,9 @@ import net.dnorberg.rivencraft.block.entity.BookBinderBlockEntity;
import net.dnorberg.rivencraft.book.AgeReference; import net.dnorberg.rivencraft.book.AgeReference;
import net.dnorberg.rivencraft.book.AgeDimensionService; import net.dnorberg.rivencraft.book.AgeDimensionService;
import net.dnorberg.rivencraft.book.AgeRegistrySavedData; import net.dnorberg.rivencraft.book.AgeRegistrySavedData;
import net.dnorberg.rivencraft.book.LinkProperties;
import net.dnorberg.rivencraft.book.LinkTarget;
import net.dnorberg.rivencraft.book.LinkingService;
import net.dnorberg.rivencraft.item.PageItem; import net.dnorberg.rivencraft.item.PageItem;
import net.dnorberg.rivencraft.menu.BookBinderMenu; import net.dnorberg.rivencraft.menu.BookBinderMenu;
import net.dnorberg.rivencraft.registry.ModBlocks; import net.dnorberg.rivencraft.registry.ModBlocks;
@@ -17,6 +20,7 @@ import net.dnorberg.rivencraft.writing.SymbolReference;
import net.dnorberg.rivencraft.writing.SymbolCatalog; import net.dnorberg.rivencraft.writing.SymbolCatalog;
import net.dnorberg.rivencraft.writing.WritingEntry; import net.dnorberg.rivencraft.writing.WritingEntry;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.gametest.framework.GameTest; import net.minecraft.gametest.framework.GameTest;
import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@@ -185,6 +189,50 @@ public final class BookBinderGameTests {
helper.succeed(); helper.succeed();
} }
public static void panelOnlyBookRetainsApplicableModifiers(GameTestHelper helper) {
BookBinderBlockEntity binder = place(helper);
binder.setTitle("Modified Random Age");
binder.setItem(BookBinderBlockEntity.COVER, new ItemStack(Items.LEATHER));
ItemStack panel = PageItem.createLinkPanelPage();
panel.set(ModDataComponents.LINK_PROPERTIES.get(), new LinkProperties(
LinkProperties.DISARM | LinkProperties.MAINTAIN_MOMENTUM | LinkProperties.INTRA_LINKING));
var player = helper.makeMockServerPlayerInLevel();
player.moveTo(binder.getBlockPos().getX() + 0.5, binder.getBlockPos().getY() + 0.5,
binder.getBlockPos().getZ() + 0.5);
BookBinderMenu menu = new BookBinderMenu(1, player.getInventory(), binder);
menu.setCarried(panel);
helper.assertTrue(menu.clickMenuButton(player, BookBinderMenu.STRIP_CLICK_BASE),
"The link strip must accept the modified panel without symbol pages");
ItemStack result = menu.quickMoveStack(player, BookBinderMenu.RESULT);
helper.assertTrue(result.is(ModItems.DESCRIPTIVE_BOOK.get()),
"A Link Panel alone must create a random-Age Descriptive Book");
LinkProperties expected = new LinkProperties(LinkProperties.DISARM | LinkProperties.MAINTAIN_MOMENTUM);
helper.assertValueEqual(result.get(ModDataComponents.LINK_PROPERTIES.get()), expected,
"The panel-only book must keep travel modifiers but omit Intra Linking");
ItemStack restored = ItemStack.parseOptional(helper.getLevel().registryAccess(),
(net.minecraft.nbt.CompoundTag) result.saveOptional(helper.getLevel().registryAccess()));
helper.assertValueEqual(restored.get(ModDataComponents.LINK_PROPERTIES.get()), expected,
"Panel-only book modifiers must survive save and reload");
BlockPos departure = player.blockPosition();
BlockPos destination = departure.offset(3, 0, 0);
helper.getLevel().setBlock(destination.below(), Blocks.STONE.defaultBlockState(), 3);
helper.getLevel().setBlock(destination, Blocks.AIR.defaultBlockState(), 3);
helper.getLevel().setBlock(destination.above(), Blocks.AIR.defaultBlockState(), 3);
player.getInventory().setItem(4, new ItemStack(Items.DIAMOND, 3));
LinkTarget target = new LinkTarget(GlobalPos.of(helper.getLevel().dimension(), destination), 0.0F, 0.0F);
helper.assertValueEqual(LinkingService.travelWithFooting(player, target,
restored.get(ModDataComponents.LINK_PROPERTIES.get()).forDescriptiveBook()),
LinkingService.LinkResult.SUCCESS,
"The panel-only book's properties must be accepted by grounded travel");
helper.assertTrue(player.getInventory().getItem(4).isEmpty(),
"Disarm must remove the carried items during panel-only book travel");
helper.assertTrue(helper.getLevel().getEntitiesOfClass(ItemEntity.class,
new AABB(departure).inflate(5.0), entity -> entity.getItem().is(Items.DIAMOND))
.stream().mapToInt(entity -> entity.getItem().getCount()).sum() >= 3,
"Disarm must drop the items at the departure location");
helper.succeed();
}
@GameTest(template = "empty") @GameTest(template = "empty")
public static void linkPanelOnlyCreatesCompletedRandomAgeBook(GameTestHelper helper) { public static void linkPanelOnlyCreatesCompletedRandomAgeBook(GameTestHelper helper) {
BookBinderBlockEntity binder = place(helper); BookBinderBlockEntity binder = place(helper);
@@ -87,6 +87,11 @@ public final class CoreGameTests {
BookBinderGameTests.assemblyIsAtomicAndRetainsPageOrder(helper); BookBinderGameTests.assemblyIsAtomicAndRetainsPageOrder(helper);
} }
@GameTest(template = "empty")
public static void panelOnlyBookModifiers(GameTestHelper helper) {
BookBinderGameTests.panelOnlyBookRetainsApplicableModifiers(helper);
}
@GameTest(template = "empty") @GameTest(template = "empty")
public static void binderRejectsConflictingGrammar(GameTestHelper helper) { public static void binderRejectsConflictingGrammar(GameTestHelper helper) {
BookBinderGameTests.conflictingGrammarKeepsBinderInputsRecoverable(helper); BookBinderGameTests.conflictingGrammarKeepsBinderInputsRecoverable(helper);