Open stored books from book stands
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-21 07:59:36 -04:00
1 parent 7b3bc328f2
commit f57afab363
8 files changed
+89 -9

No files matched your search

@@ -2,9 +2,7 @@ package net.dnorberg.rivencraft.block;
import com.mojang.serialization.MapCodec;
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
import net.dnorberg.rivencraft.item.LinkingBookItem;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
@@ -63,10 +61,6 @@ public final class BookStandBlock extends LecternBlock {
return InteractionResult.sidedSuccess(level.isClientSide);
}
ItemStack book = stand.getBook();
if (book.getItem() instanceof LinkingBookItem && player instanceof ServerPlayer serverPlayer) {
LinkingBookItem.useBoundBook(serverPlayer, book);
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
@@ -2,9 +2,12 @@ package net.dnorberg.rivencraft.client;
import net.dnorberg.rivencraft.client.screen.LinkingBookScreen;
import net.dnorberg.rivencraft.client.screen.DescriptiveBookScreen;
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
import net.dnorberg.rivencraft.registry.ModBlocks;
import net.dnorberg.rivencraft.registry.ModItems;
import net.minecraft.client.Minecraft;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
public final class ClientBookInteractionHandler {
@@ -32,4 +35,27 @@ public final class ClientBookInteractionHandler {
Minecraft.getInstance().setScreen(new DescriptiveBookScreen(event.getItemStack().copy()));
}
}
public static void onRightClickBlock(PlayerInteractEvent.RightClickBlock event) {
if (!event.getEntity().level().isClientSide()
|| event.getEntity().isShiftKeyDown()
|| !event.getItemStack().isEmpty()
|| !event.getLevel().getBlockState(event.getPos()).is(ModBlocks.BOOK_STAND.get())
|| !(event.getLevel().getBlockEntity(event.getPos()) instanceof BookStandBlockEntity stand)) {
return;
}
ItemStack book = stand.getBook();
if (book.isEmpty()) {
return;
}
event.setCanceled(true);
event.setCancellationResult(InteractionResult.SUCCESS);
if (book.is(ModItems.LINKING_BOOK.get())) {
Minecraft.getInstance().setScreen(new LinkingBookScreen(event.getPos(), book.copy()));
} else if (book.is(ModItems.DESCRIPTIVE_BOOK.get())) {
Minecraft.getInstance().setScreen(new DescriptiveBookScreen(book.copy()));
}
}
}
@@ -22,5 +22,6 @@ public final class ClientEvents {
@SubscribeEvent
public static void clientSetup(FMLClientSetupEvent event) {
NeoForge.EVENT_BUS.addListener(ClientBookInteractionHandler::onRightClickItem);
NeoForge.EVENT_BUS.addListener(ClientBookInteractionHandler::onRightClickBlock);
}
}
@@ -6,6 +6,7 @@ import net.dnorberg.rivencraft.client.preview.PonderDestinationPreviewRenderer;
import net.dnorberg.rivencraft.network.BindLinkingBookPayload;
import net.dnorberg.rivencraft.network.ModNetworking;
import net.dnorberg.rivencraft.network.UseLinkingBookPayload;
import net.dnorberg.rivencraft.network.UseBookStandPayload;
import net.dnorberg.rivencraft.registry.ModDataComponents;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
@@ -35,6 +36,7 @@ public final class LinkingBookScreen extends Screen {
private final InteractionHand hand;
private final ItemStack book;
private final LinkTarget target;
private final BlockPos bookStandPos;
private DestinationPreviewRenderer preview;
private EditBox titleInput;
@@ -43,6 +45,15 @@ public final class LinkingBookScreen extends Screen {
this.hand = hand;
this.book = book;
target = book.get(ModDataComponents.LINK_TARGET.get());
bookStandPos = null;
}
public LinkingBookScreen(BlockPos bookStandPos, ItemStack book) {
super(book.getHoverName());
hand = InteractionHand.MAIN_HAND;
this.book = book;
target = book.get(ModDataComponents.LINK_TARGET.get());
this.bookStandPos = bookStandPos.immutable();
}
@Override
@@ -140,7 +151,11 @@ public final class LinkingBookScreen extends Screen {
}
private void link() {
PacketDistributor.sendToServer(new UseLinkingBookPayload(hand == InteractionHand.OFF_HAND));
if (bookStandPos == null) {
PacketDistributor.sendToServer(new UseLinkingBookPayload(hand == InteractionHand.OFF_HAND));
} else {
PacketDistributor.sendToServer(new UseBookStandPayload(bookStandPos));
}
onClose();
}
}
@@ -1,6 +1,7 @@
package net.dnorberg.rivencraft.network;
import net.dnorberg.rivencraft.book.LinkTarget;
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
import net.dnorberg.rivencraft.item.LinkingBookItem;
import net.dnorberg.rivencraft.registry.ModDataComponents;
import net.dnorberg.rivencraft.registry.ModItems;
@@ -11,6 +12,7 @@ import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
@@ -25,6 +27,7 @@ public final class ModNetworking {
PayloadRegistrar registrar = event.registrar("1");
registrar.playToServer(BindLinkingBookPayload.TYPE, BindLinkingBookPayload.STREAM_CODEC, ModNetworking::bindBook);
registrar.playToServer(UseLinkingBookPayload.TYPE, UseLinkingBookPayload.STREAM_CODEC, ModNetworking::useBook);
registrar.playToServer(UseBookStandPayload.TYPE, UseBookStandPayload.STREAM_CODEC, ModNetworking::useBookStand);
}
private static void bindBook(BindLinkingBookPayload payload, IPayloadContext context) {
@@ -59,6 +62,19 @@ public final class ModNetworking {
}
}
private static void useBookStand(UseBookStandPayload payload, IPayloadContext context) {
if (!(context.player() instanceof ServerPlayer player)
|| player.distanceToSqr(Vec3.atCenterOf(payload.pos())) > 64.0D
|| !(player.level().getBlockEntity(payload.pos()) instanceof BookStandBlockEntity stand)) {
return;
}
ItemStack stack = stand.getBook();
if (stack.is(ModItems.LINKING_BOOK.get()) && stack.has(ModDataComponents.LINK_TARGET.get())) {
LinkingBookItem.useBoundBook(player, stack);
}
}
private static InteractionHand hand(boolean offhand) {
return offhand ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
}
@@ -0,0 +1,24 @@
package net.dnorberg.rivencraft.network;
import net.dnorberg.rivencraft.Rivencraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
public record UseBookStandPayload(BlockPos pos) implements CustomPacketPayload {
public static final Type<UseBookStandPayload> TYPE = new Type<>(
ResourceLocation.fromNamespaceAndPath(Rivencraft.MOD_ID, "use_book_stand")
);
public static final StreamCodec<RegistryFriendlyByteBuf, UseBookStandPayload> STREAM_CODEC = StreamCodec.composite(
BlockPos.STREAM_CODEC,
UseBookStandPayload::pos,
UseBookStandPayload::new
);
@Override
public Type<? extends CustomPacketPayload> type() {
return TYPE;
}
}