From 1be8194cfaeb4ff6f1a36b6a2b23df72931b7b06 Mon Sep 17 00:00:00 2001 From: Dustin Norberg Date: Mon, 21 Sep 2026 09:18:58 -0400 Subject: [PATCH] Match descriptive book layout to linking books --- docs/PORTING.md | 3 + gradle.properties | 2 +- .../client/screen/DescriptiveBookScreen.java | 85 +++++++++++++++---- .../assets/rivencraft/lang/en_us.json | 1 + 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/docs/PORTING.md b/docs/PORTING.md index 28cdc0b..dc73134 100644 --- a/docs/PORTING.md +++ b/docs/PORTING.md @@ -149,6 +149,9 @@ Version 0.2.0 completes Milestone 2. Until Milestone 3 provides generated Age dimensions, Descriptive Book UUIDs deterministically resolve to vanilla dimensions and create a bound Return Link to the source on successful travel. +Version 0.2.1 gives Descriptive Books the same open-parchment layout and +left-page link interaction as Linking Books. + 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 8f33516..7ed9195 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.2.0 +mod_version=0.2.1 # 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/screen/DescriptiveBookScreen.java b/src/main/java/net/dnorberg/rivencraft/client/screen/DescriptiveBookScreen.java index 335aa7d..d1696db 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/screen/DescriptiveBookScreen.java +++ b/src/main/java/net/dnorberg/rivencraft/client/screen/DescriptiveBookScreen.java @@ -5,14 +5,28 @@ import net.dnorberg.rivencraft.network.UseDescriptiveBookPayload; import net.dnorberg.rivencraft.registry.ModDataComponents; import net.minecraft.core.BlockPos; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FormattedCharSequence; import net.minecraft.world.item.ItemStack; import net.minecraft.world.InteractionHand; import net.neoforged.neoforge.network.PacketDistributor; public final class DescriptiveBookScreen extends Screen { + private static final int BOOK_TEXT_COLOR = 0xFF3B281B; + private static final ResourceLocation BOOK_TEXTURE = ResourceLocation.fromNamespaceAndPath( + "rivencraft", "textures/gui/linking_book.png" + ); + private static final int BOOK_WIDTH = 327; + private static final int BOOK_HEIGHT = 199; + private static final int TEXTURE_WIDTH = 512; + private static final int TEXTURE_HEIGHT = 312; + private static final int LINK_PANEL_X = 28; + private static final int LINK_PANEL_Y = 35; + private static final int LINK_PANEL_WIDTH = 126; + private static final int LINK_PANEL_HEIGHT = 86; + private final AgeReference age; private final InteractionHand hand; private final BlockPos bookStandPos; @@ -32,29 +46,48 @@ public final class DescriptiveBookScreen extends Screen { } @Override - protected void init() { - if (age != null) { - addRenderableWidget(Button.builder(Component.translatable("screen.rivencraft.book.link"), button -> link()) - .bounds(width / 2 - 75, height / 2 + 30, 150, 20) - .build()); - } - addRenderableWidget(Button.builder(Component.translatable("gui.done"), button -> onClose()) - .bounds(width / 2 - 75, height / 2 + 55, 150, 20) - .build()); + public void renderBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) { + // Like Linking Books, the parchment is the full screen background. } @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) { - super.render(graphics, mouseX, mouseY, partialTick); - int centerX = width / 2; - graphics.drawCenteredString(font, title, centerX, height / 2 - 70, 0xFFFFFFFF); + int left = (width - BOOK_WIDTH) / 2; + int top = (height - BOOK_HEIGHT) / 2; + graphics.blit(BOOK_TEXTURE, left, top, BOOK_WIDTH, BOOK_HEIGHT, 0, 0, + TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_WIDTH, TEXTURE_HEIGHT); + if (age == null) { - graphics.drawCenteredString(font, Component.translatable("screen.rivencraft.book.unwritten"), - centerX, height / 2 - 4, 0xFFAAAAAA); + drawWrappedWithoutShadow(graphics, Component.translatable("screen.rivencraft.book.unwritten"), + left + 177, top + 45, 124); } else { - graphics.drawCenteredString(font, Component.literal(age.name()), centerX, height / 2 - 16, 0xFFE7D7A9); - graphics.drawCenteredString(font, Component.literal(age.id().toString()), centerX, height / 2 + 4, 0xFF777777); + int leftCenter = left + 91; + int rightCenter = left + 239; + drawCenteredWithoutShadow(graphics, Component.translatable("screen.rivencraft.book.age_link"), + leftCenter, top + 50); + drawWrappedCenteredWithoutShadow(graphics, Component.literal(age.name()), leftCenter, top + 68, 112); + drawCenteredWithoutShadow(graphics, Component.literal(age.shortId()), leftCenter, top + 104); + drawWrappedWithoutShadow(graphics, title, left + 177, top + 43, 124); + drawCenteredWithoutShadow(graphics, Component.literal(age.id().toString()), rightCenter, top + 82); + drawCenteredWithoutShadow(graphics, Component.translatable("screen.rivencraft.book.click_to_link"), + rightCenter, top + 119); } + + super.render(graphics, mouseX, mouseY, partialTick); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (age != null && button == 0) { + int panelLeft = (width - BOOK_WIDTH) / 2 + LINK_PANEL_X; + int panelTop = (height - BOOK_HEIGHT) / 2 + LINK_PANEL_Y; + if (mouseX >= panelLeft && mouseX < panelLeft + LINK_PANEL_WIDTH + && mouseY >= panelTop && mouseY < panelTop + LINK_PANEL_HEIGHT) { + link(); + return true; + } + } + return super.mouseClicked(mouseX, mouseY, button); } private void link() { @@ -65,4 +98,22 @@ public final class DescriptiveBookScreen extends Screen { )); onClose(); } + + private void drawCenteredWithoutShadow(GuiGraphics graphics, Component text, int centerX, int y) { + graphics.drawString(font, text, centerX - font.width(text) / 2, y, BOOK_TEXT_COLOR, false); + } + + private void drawWrappedWithoutShadow(GuiGraphics graphics, Component text, int x, int y, int maxWidth) { + for (FormattedCharSequence line : font.split(text, maxWidth)) { + graphics.drawString(font, line, x, y, BOOK_TEXT_COLOR, false); + y += font.lineHeight; + } + } + + private void drawWrappedCenteredWithoutShadow(GuiGraphics graphics, Component text, int centerX, int y, int maxWidth) { + for (FormattedCharSequence line : font.split(text, maxWidth)) { + graphics.drawString(font, line, centerX - font.width(line) / 2, y, BOOK_TEXT_COLOR, false); + y += font.lineHeight; + } + } } diff --git a/src/main/resources/assets/rivencraft/lang/en_us.json b/src/main/resources/assets/rivencraft/lang/en_us.json index 178db7e..d044624 100644 --- a/src/main/resources/assets/rivencraft/lang/en_us.json +++ b/src/main/resources/assets/rivencraft/lang/en_us.json @@ -22,6 +22,7 @@ "screen.rivencraft.book.bind": "Bind", "screen.rivencraft.book.link": "Link", "screen.rivencraft.book.unwritten": "This Descriptive Book is unwritten", + "screen.rivencraft.book.age_link": "Age Link", "screen.rivencraft.book.preview_pending": "Loading destination...", "screen.rivencraft.book.click_to_link": "Click the panel to link", "itemGroup.rivencraft": "Rivencraft"