Display book names above book stands
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-21 07:53:43 -04:00
1 parent d7fb1855a8
commit ec82296624
4 files changed
+60 -4

No files matched your search

+5 -1
View File
@@ -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
+1 -1
View File
@@ -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
@@ -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<ClientGamePacketListener> 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);
@@ -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<BookStandBlockEntity> {
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<BookStandBlo
VertexConsumer consumer = EnchantTableRenderer.BOOK_LOCATION.buffer(bufferSource, RenderType::entitySolid);
bookModel.render(poseStack, consumer, packedLight, packedOverlay, -1);
poseStack.popPose();
if (!blockEntity.getBook().isEmpty()) {
renderName(blockEntity.getBook().getHoverName(), poseStack, bufferSource, packedLight);
}
}
private void renderName(
Component name,
PoseStack poseStack,
MultiBufferSource bufferSource,
int packedLight
) {
poseStack.pushPose();
poseStack.translate(0.5F, 1.6F, 0.5F);
poseStack.mulPose(entityRenderer.cameraOrientation());
poseStack.scale(-0.025F, -0.025F, 0.025F);
Matrix4f matrix = poseStack.last().pose();
float x = -font.width(name) / 2.0F;
int background = (int)(Minecraft.getInstance().options.getBackgroundOpacity(0.25F) * 255.0F) << 24;
font.drawInBatch(name, x, 0.0F, 0xFFFFFFFF, false, matrix, bufferSource,
Font.DisplayMode.NORMAL, background, packedLight);
poseStack.popPose();
}
}