From ec822966249954dae834920657e96076eb3e31a9 Mon Sep 17 00:00:00 2001 From: Dustin Norberg Date: Mon, 21 Sep 2026 07:53:43 -0400 Subject: [PATCH] Display book names above book stands --- docs/PORTING.md | 6 +++- gradle.properties | 2 +- .../block/entity/BookStandBlockEntity.java | 24 ++++++++++++-- .../rivencraft/client/BookStandRenderer.java | 32 +++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/docs/PORTING.md b/docs/PORTING.md index 204459a..522175e 100644 --- a/docs/PORTING.md +++ b/docs/PORTING.md @@ -52,7 +52,8 @@ the symbol grammar is introduced. explicit link activation. - [x] Ponder dependency and isolated destination-preview level boundary. - [ ] Server-provided destination snapshots rendered as rotating Ponder scenes. -- [ ] Book Stand floating names and opening the stored book screen. +- [x] Book Stand floating names synchronized from the stored book stack. +- [ ] Open the stored book screen from a Book Stand. - [ ] Automated in-game tests for binding, persistence, and travel. The temporary shapeless Linking Book recipe makes the linking subsystem easy @@ -96,6 +97,9 @@ the world remains sharp behind it. Version 0.1.8 renders all Linking Book destination details in the same dark ink color as the book name for consistent contrast against the parchment. +Version 0.1.9 synchronizes the Book Stand's stored stack to clients and renders +its display name as a camera-facing label above the book. + The preview code is separated behind a renderer interface and uses an isolated Ponder level. The first iteration supplies the animated loading boundary; the next iteration will add server-authoritative snapshot transport and populate diff --git a/gradle.properties b/gradle.properties index 26397cd..ad1b404 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.8 +mod_version=0.1.9 # 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/block/entity/BookStandBlockEntity.java b/src/main/java/net/dnorberg/rivencraft/block/entity/BookStandBlockEntity.java index 74c17f4..40fd197 100644 --- a/src/main/java/net/dnorberg/rivencraft/block/entity/BookStandBlockEntity.java +++ b/src/main/java/net/dnorberg/rivencraft/block/entity/BookStandBlockEntity.java @@ -4,6 +4,9 @@ import net.dnorberg.rivencraft.registry.ModBlockEntities; import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -22,16 +25,33 @@ public final class BookStandBlockEntity extends BlockEntity { public void setBook(ItemStack book) { this.book = book; - setChanged(); + setChangedAndSync(); } public ItemStack takeBook() { ItemStack result = book; book = ItemStack.EMPTY; - setChanged(); + setChangedAndSync(); return result; } + @Override + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + return saveWithoutMetadata(registries); + } + + private void setChangedAndSync() { + setChanged(); + if (level != null && !level.isClientSide) { + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2); + } + } + @Override protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.loadAdditional(tag, registries); diff --git a/src/main/java/net/dnorberg/rivencraft/client/BookStandRenderer.java b/src/main/java/net/dnorberg/rivencraft/client/BookStandRenderer.java index 66ff3f0..cf7888d 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/BookStandRenderer.java +++ b/src/main/java/net/dnorberg/rivencraft/client/BookStandRenderer.java @@ -7,18 +7,27 @@ import net.dnorberg.rivencraft.block.BookStandBlock; import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity; import net.minecraft.client.model.BookModel; import net.minecraft.client.model.geom.ModelLayers; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.blockentity.EnchantTableRenderer; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.network.chat.Component; import net.minecraft.world.level.block.state.BlockState; +import org.joml.Matrix4f; public final class BookStandRenderer implements BlockEntityRenderer { private final BookModel bookModel; + private final Font font; + private final EntityRenderDispatcher entityRenderer; public BookStandRenderer(BlockEntityRendererProvider.Context context) { bookModel = new BookModel(context.bakeLayer(ModelLayers.BOOK)); + font = context.getFont(); + entityRenderer = context.getEntityRenderer(); } @Override @@ -45,5 +54,28 @@ public final class BookStandRenderer implements BlockEntityRenderer