From 3ecb01940d14d50e4da81bb12cdd08c427825b0f Mon Sep 17 00:00:00 2001 From: Dustin Norberg Date: Mon, 21 Sep 2026 08:48:20 -0400 Subject: [PATCH] Lock preview view to local scene --- README.md | 9 +++++---- docs/PORTING.md | 4 ++++ gradle.properties | 2 +- .../PonderDestinationPreviewRenderer.java | 17 +++++++++-------- .../rivencraft/gametest/LinkingGameTests.java | 4 +++- .../rivencraft/network/LinkPreviewPayload.java | 4 ++-- .../rivencraft/network/ModNetworking.java | 8 ++++---- 7 files changed, 28 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 0c1b0f6..1207110 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,11 @@ right-clicking with an empty hand. Sneak-right-click with an empty hand to take the book back and restore the vanilla lectern. Breaking a Book Stand drops both the stored book and a vanilla lectern. -Bound Linking Books request a server-validated 9-by-128-by-9 snapshot around -their destination and render its blocks as a rotating Ponder scene on the left -page, backed by the destination biome's sky color. The snapshot is visual only; -the server independently validates every link. +Bound Linking Books request a server-validated 9-by-64-by-9 snapshot around +their destination. The book renders a fixed 9-by-7-by-9 window centered on the +link point as a rotating Ponder scene on the left page, backed by the +destination biome's sky color. The snapshot is visual only; the server +independently validates every link. ## Requirements diff --git a/docs/PORTING.md b/docs/PORTING.md index 6229a3c..7945b69 100644 --- a/docs/PORTING.md +++ b/docs/PORTING.md @@ -131,6 +131,10 @@ Version 0.1.17 changes destination previews to a 9-by-128-by-9 volume: a square horizontal footprint with a vertical slice spanning 64 blocks below and 63 blocks above the recorded linking location. +Version 0.1.18 changes the preview cache to 9-by-64-by-9, spanning 32 blocks +below and 31 above the link point. The Ponder section remains locked to the +centered 9-by-7-by-9 window so the book retains a readable close-up. + The preview code is separated behind a renderer interface and uses an isolated Ponder level populated from server-authoritative destination snapshots. diff --git a/gradle.properties b/gradle.properties index 580faee..2f8ca50 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,7 +33,7 @@ mod_name=Rivencraft # 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 # The mod version. See https://semver.org/ -mod_version=0.1.17 +mod_version=0.1.18 # 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. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/main/java/net/dnorberg/rivencraft/client/preview/PonderDestinationPreviewRenderer.java b/src/main/java/net/dnorberg/rivencraft/client/preview/PonderDestinationPreviewRenderer.java index 8773ab6..3d0545e 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/preview/PonderDestinationPreviewRenderer.java +++ b/src/main/java/net/dnorberg/rivencraft/client/preview/PonderDestinationPreviewRenderer.java @@ -34,7 +34,7 @@ public final class PonderDestinationPreviewRenderer implements DestinationPrevie private static final Vector3f DIFFUSE_LIGHT_0 = new Vector3f(0.4F, -1.0F, 0.7F).normalize(); private static final Vector3f DIFFUSE_LIGHT_1 = new Vector3f(-0.4F, -0.5F, 0.7F).normalize(); private final PonderLevel previewLevel; - private final Selection selection; + private final Selection snapshotSelection; private final PonderSceneElement section; private int ticks; private boolean loaded; @@ -43,13 +43,16 @@ public final class PonderDestinationPreviewRenderer implements DestinationPrevie public PonderDestinationPreviewRenderer() { Minecraft minecraft = Minecraft.getInstance(); previewLevel = new PonderLevel(BlockPos.ZERO, minecraft.level); - selection = SelectionImpl.of(new BoundingBox(0, 0, 0, 8, 127, 8)); - section = new WorldSectionElementImpl(selection); + snapshotSelection = SelectionImpl.of(new BoundingBox(0, 0, 0, 8, 63, 8)); + // The target sits at y=32 in the snapshot. Render only its familiar + // y=30..36 window, giving the page a fixed 9×7×9 close-up. + Selection viewSelection = SelectionImpl.of(new BoundingBox(0, 30, 0, 8, 36, 8)); + section = new WorldSectionElementImpl(viewSelection); } @Override public void accept(LinkPreviewPayload payload) { - selection.forEach(pos -> previewLevel.setBlock(pos, Blocks.AIR.defaultBlockState(), 2)); + snapshotSelection.forEach(pos -> previewLevel.setBlock(pos, Blocks.AIR.defaultBlockState(), 2)); payload.blocks().forEach(block -> previewLevel.setBlock(block.pos(), block.state(), 2)); ((net.createmod.ponder.api.element.WorldSectionElement)section).queueRedraw(); backgroundColor = 0xFF000000 | payload.skyColor() & 0x00FFFFFF; @@ -105,10 +108,8 @@ public final class PonderDestinationPreviewRenderer implements DestinationPrevie poseStack.mulPose(Axis.XP.rotationDegrees(-28.0F)); poseStack.mulPose(Axis.YP.rotationDegrees((ticks + partialTick) * 0.6F)); UIRenderHelper.flipForGuiRender(poseStack); - // Fit the complete 128-block vertical slice, while keeping the 9×9 - // footprint centered during the full horizontal orbit. - poseStack.scale(0.58F, 0.58F, 0.58F); - poseStack.translate(-4.5F, -64.0F, -4.5F); + poseStack.scale(7.0F, 7.0F, 7.0F); + poseStack.translate(-4.5F, -31.5F, -4.5F); SuperRenderTypeBuffer buffer = DefaultSuperRenderTypeBuffer.getInstance(); section.renderFirst(previewLevel, buffer, graphics, partialTick); diff --git a/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java b/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java index bd37429..28bbf08 100644 --- a/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java +++ b/src/main/java/net/dnorberg/rivencraft/gametest/LinkingGameTests.java @@ -65,7 +65,9 @@ public final class LinkingGameTests { BlockPos absoluteOrigin = helper.absolutePos(ORIGIN); for (BlockPos position : BlockPos.betweenClosed( absoluteOrigin.offset(-4, -2, -4), absoluteOrigin.offset(4, 2, 4))) { - helper.getLevel().setBlockAndUpdate(position, Blocks.STONE.defaultBlockState()); + // This test only needs collision states. Avoid propagating 405 + // neighbor updates through the GameTest world while preparing it. + helper.getLevel().setBlock(position, Blocks.STONE.defaultBlockState(), 2); } ServerPlayer player = helper.makeMockServerPlayerInLevel(); diff --git a/src/main/java/net/dnorberg/rivencraft/network/LinkPreviewPayload.java b/src/main/java/net/dnorberg/rivencraft/network/LinkPreviewPayload.java index f2e54f7..43497de 100644 --- a/src/main/java/net/dnorberg/rivencraft/network/LinkPreviewPayload.java +++ b/src/main/java/net/dnorberg/rivencraft/network/LinkPreviewPayload.java @@ -12,8 +12,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; public record LinkPreviewPayload(int skyColor, List blocks) implements CustomPacketPayload { - /** A square footprint keeps every side visible during an orbit, with a tall vertical slice. */ - private static final int MAX_BLOCKS = 9 * 128 * 9; + /** A square footprint keeps every side visible during an orbit, with a vertical snapshot cache. */ + private static final int MAX_BLOCKS = 9 * 64 * 9; public static final Type TYPE = new Type<>( ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "link_preview") ); diff --git a/src/main/java/net/dnorberg/rivencraft/network/ModNetworking.java b/src/main/java/net/dnorberg/rivencraft/network/ModNetworking.java index 70f08d8..f5a2c11 100644 --- a/src/main/java/net/dnorberg/rivencraft/network/ModNetworking.java +++ b/src/main/java/net/dnorberg/rivencraft/network/ModNetworking.java @@ -114,12 +114,12 @@ public final class ModNetworking { BlockPos origin = target.location().pos(); List blocks = new ArrayList<>(); - // The square footprint survives every angle of the orbit. The vertical - // slice captures 64 blocks below through 63 blocks above the link point. - for (BlockPos pos : BlockPos.betweenClosed(origin.offset(-4, -64, -4), origin.offset(4, 63, 4))) { + // The square footprint survives every angle of the orbit. Retain a + // 64-block vertical slice, while the renderer shows its 7-block window. + for (BlockPos pos : BlockPos.betweenClosed(origin.offset(-4, -32, -4), origin.offset(4, 31, 4))) { var state = level.getBlockState(pos); if (!state.isAir()) { - blocks.add(new LinkPreviewPayload.SnapshotBlock(pos.subtract(origin).offset(4, 64, 4), state)); + blocks.add(new LinkPreviewPayload.SnapshotBlock(pos.subtract(origin).offset(4, 32, 4), state)); } } int skyColor = level.getBiome(origin).value().getSkyColor();