Use HUD overlay for book exploration
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-22 05:58:02 -04:00
1 parent d878c89ba4
commit 1586597161
9 files changed
+244 -34

No files matched your search

@@ -0,0 +1,62 @@
package net.dnorberg.rivencraft.client;
import com.mojang.blaze3d.platform.InputConstants;
import net.dnorberg.rivencraft.client.screen.ExplorableBookScreen;
import net.dnorberg.rivencraft.network.LinkPreviewPayload;
import net.minecraft.client.Minecraft;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.InputEvent;
import net.neoforged.neoforge.client.event.RenderGuiEvent;
import org.lwjgl.glfw.GLFW;
public final class ClientBookExploreOverlay {
private static ExplorableBookScreen bookScreen;
private ClientBookExploreOverlay() {
}
public static void open(ExplorableBookScreen screen) {
bookScreen = screen;
}
public static boolean acceptPreview(LinkPreviewPayload payload) {
if (bookScreen == null) {
return false;
}
bookScreen.acceptExplorePreview(payload);
return true;
}
public static void onClientTick(ClientTickEvent.Post event) {
if (bookScreen == null) {
return;
}
Minecraft minecraft = Minecraft.getInstance();
if (minecraft.player == null || minecraft.level == null) {
bookScreen.abandonExploreOverlay();
bookScreen = null;
return;
}
bookScreen.tickExploreOverlay();
}
public static void onRenderGui(RenderGuiEvent.Post event) {
if (bookScreen != null && Minecraft.getInstance().screen == null) {
bookScreen.renderExploreOverlay(event.getGuiGraphics(),
event.getPartialTick().getGameTimeDeltaPartialTick(false));
}
}
public static void onMouseButton(InputEvent.MouseButton.Pre event) {
if (bookScreen == null
|| Minecraft.getInstance().screen != null
|| event.getButton() != GLFW.GLFW_MOUSE_BUTTON_RIGHT
|| event.getAction() != InputConstants.PRESS) {
return;
}
event.setCanceled(true);
ExplorableBookScreen screen = bookScreen;
bookScreen = null;
screen.returnFromExploreOverlay();
}
}
@@ -23,6 +23,9 @@ public final class ClientEvents {
public static void clientSetup(FMLClientSetupEvent event) {
NeoForge.EVENT_BUS.addListener(ClientBookInteractionHandler::onRightClickItem);
NeoForge.EVENT_BUS.addListener(ClientBookInteractionHandler::onRightClickBlock);
NeoForge.EVENT_BUS.addListener(ClientBookExploreOverlay::onClientTick);
NeoForge.EVENT_BUS.addListener(ClientBookExploreOverlay::onRenderGui);
NeoForge.EVENT_BUS.addListener(ClientBookExploreOverlay::onMouseButton);
}
}
@@ -12,7 +12,9 @@ public final class ClientLinkPreviewHandler {
public static void handle(LinkPreviewPayload payload, IPayloadContext context) {
context.enqueueWork(() -> {
if (Minecraft.getInstance().screen instanceof LinkingBookScreen screen) {
if (ClientBookExploreOverlay.acceptPreview(payload)) {
return;
} else if (Minecraft.getInstance().screen instanceof LinkingBookScreen screen) {
screen.acceptPreview(payload);
} else if (Minecraft.getInstance().screen instanceof DescriptiveBookScreen screen) {
screen.acceptPreview(payload);
@@ -26,6 +26,10 @@ public final class ImmersivePortalsDestinationPreviewRenderer implements Destina
private Vec3 cameraPosition;
private Vec3 explorationPlayerOrigin;
private Vec3 explorationCameraOrigin;
private float explorationPlayerYaw;
private float explorationPlayerPitch;
private float explorationCameraYaw;
private float explorationCameraPitch;
private float yaw;
private float pitch;
private int ticks;
@@ -52,6 +56,9 @@ public final class ImmersivePortalsDestinationPreviewRenderer implements Destina
}
if (minecraft.player != null && explorationPlayerOrigin != null && explorationCameraOrigin != null) {
cameraPosition = explorationCameraOrigin.add(minecraft.player.position().subtract(explorationPlayerOrigin));
yaw = explorationCameraYaw + Mth.wrapDegrees(minecraft.player.getYRot() - explorationPlayerYaw);
pitch = Mth.clamp(explorationCameraPitch
+ minecraft.player.getXRot() - explorationPlayerPitch, -89.0F, 89.0F);
}
}
@@ -127,6 +134,10 @@ public final class ImmersivePortalsDestinationPreviewRenderer implements Destina
if (exploring && minecraft.player != null) {
explorationPlayerOrigin = minecraft.player.position();
explorationCameraOrigin = cameraPosition;
explorationPlayerYaw = minecraft.player.getYRot();
explorationPlayerPitch = minecraft.player.getXRot();
explorationCameraYaw = yaw;
explorationCameraPitch = pitch;
} else {
clearMovement();
explorationPlayerOrigin = null;
@@ -1,6 +1,7 @@
package net.dnorberg.rivencraft.client.screen;
import net.dnorberg.rivencraft.book.AgeReference;
import net.dnorberg.rivencraft.client.ClientBookExploreOverlay;
import net.dnorberg.rivencraft.network.UseDescriptiveBookPayload;
import net.dnorberg.rivencraft.network.BindDescriptiveBookPayload;
import net.dnorberg.rivencraft.network.ModNetworking;
@@ -22,7 +23,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.InteractionHand;
import net.neoforged.neoforge.network.PacketDistributor;
public final class DescriptiveBookScreen extends Screen {
public final class DescriptiveBookScreen extends Screen implements ExplorableBookScreen {
private static final int BOOK_TEXT_COLOR = 0xFF3B281B;
private static final ResourceLocation BOOK_TEXTURE = ResourceLocation.fromNamespaceAndPath(
"rivencraft", "textures/gui/linking_book.png"
@@ -43,6 +44,7 @@ public final class DescriptiveBookScreen extends Screen {
private DestinationPreviewRenderer preview;
private EditBox titleInput;
private Button exploreButton;
private boolean movingToExploreOverlay;
public DescriptiveBookScreen(InteractionHand hand, ItemStack book) {
super(book.getHoverName());
@@ -79,19 +81,24 @@ public final class DescriptiveBookScreen extends Screen {
.bounds(rightPage + 65, top + 100, 59, 20)
.build());
} else {
preview = DestinationPreviewRenderers.create();
boolean requestPreview = preview == null;
if (requestPreview) {
preview = DestinationPreviewRenderers.create();
}
if (preview.supportsExploration()) {
exploreButton = addRenderableWidget(Button.builder(
Component.translatable("screen.rivencraft.book.explore"), button -> toggleExploration())
Component.translatable("screen.rivencraft.book.explore"), button -> enterExploreOverlay())
.bounds(left + 61, top + 145, 60, 20).build());
}
PacketDistributor.sendToServer(new RequestLinkPreviewPayload(
true,
bookStandPos != null,
bookStandPos == null && hand == InteractionHand.OFF_HAND,
bookStandPos == null ? BlockPos.ZERO : bookStandPos,
preview.supportsExploration()
));
if (requestPreview) {
PacketDistributor.sendToServer(new RequestLinkPreviewPayload(
true,
bookStandPos != null,
bookStandPos == null && hand == InteractionHand.OFF_HAND,
bookStandPos == null ? BlockPos.ZERO : bookStandPos,
preview.supportsExploration()
));
}
}
}
@@ -114,6 +121,11 @@ public final class DescriptiveBookScreen extends Screen {
@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
renderBook(graphics, partialTick);
super.render(graphics, mouseX, mouseY, partialTick);
}
private void renderBook(GuiGraphics graphics, float partialTick) {
int left = (width - BOOK_WIDTH) / 2;
int top = (height - BOOK_HEIGHT) / 2;
graphics.blit(BOOK_TEXTURE, left, top, BOOK_WIDTH, BOOK_HEIGHT, 0, 0,
@@ -135,16 +147,16 @@ public final class DescriptiveBookScreen extends Screen {
}
}
super.render(graphics, mouseX, mouseY, partialTick);
}
@Override
public void removed() {
if (preview != null) {
if (preview != null && !movingToExploreOverlay) {
if (preview.supportsExploration()) {
PacketDistributor.sendToServer(new ReleaseLinkPreviewPayload());
}
preview.close();
preview = null;
}
}
@@ -193,10 +205,11 @@ public final class DescriptiveBookScreen extends Screen {
|| super.keyReleased(keyCode, scanCode, modifiers);
}
private void toggleExploration() {
preview.setExploring(!preview.isExploring());
exploreButton.setMessage(Component.translatable(preview.isExploring()
? "screen.rivencraft.book.exploring" : "screen.rivencraft.book.explore"));
private void enterExploreOverlay() {
preview.setExploring(true);
movingToExploreOverlay = true;
ClientBookExploreOverlay.open(this);
minecraft.setScreen(null);
}
private void resetExploration() {
@@ -204,6 +217,49 @@ public final class DescriptiveBookScreen extends Screen {
exploreButton.setMessage(Component.translatable("screen.rivencraft.book.explore"));
}
@Override
public Screen asScreen() {
return this;
}
@Override
public void tickExploreOverlay() {
preview.tick();
}
@Override
public void renderExploreOverlay(GuiGraphics graphics, float partialTick) {
width = minecraft.getWindow().getGuiScaledWidth();
height = minecraft.getWindow().getGuiScaledHeight();
renderBook(graphics, partialTick);
int left = (width - BOOK_WIDTH) / 2;
int top = (height - BOOK_HEIGHT) / 2;
graphics.drawCenteredString(font,
Component.translatable("screen.rivencraft.book.return_from_explore"),
left + 91, top + 154, BOOK_TEXT_COLOR);
}
@Override
public void returnFromExploreOverlay() {
movingToExploreOverlay = false;
preview.resetView();
minecraft.setScreen(this);
}
@Override
public void abandonExploreOverlay() {
movingToExploreOverlay = false;
if (preview != null) {
preview.close();
preview = null;
}
}
@Override
public void acceptExplorePreview(LinkPreviewPayload payload) {
acceptPreview(payload);
}
private void link() {
PacketDistributor.sendToServer(new UseDescriptiveBookPayload(
bookStandPos != null,
@@ -0,0 +1,19 @@
package net.dnorberg.rivencraft.client.screen;
import net.dnorberg.rivencraft.network.LinkPreviewPayload;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
public interface ExplorableBookScreen {
Screen asScreen();
void tickExploreOverlay();
void renderExploreOverlay(GuiGraphics graphics, float partialTick);
void returnFromExploreOverlay();
void abandonExploreOverlay();
void acceptExplorePreview(LinkPreviewPayload payload);
}
@@ -1,6 +1,7 @@
package net.dnorberg.rivencraft.client.screen;
import net.dnorberg.rivencraft.book.LinkTarget;
import net.dnorberg.rivencraft.client.ClientBookExploreOverlay;
import net.dnorberg.rivencraft.client.preview.DestinationPreviewRenderer;
import net.dnorberg.rivencraft.client.preview.DestinationPreviewRenderers;
import net.dnorberg.rivencraft.network.BindLinkingBookPayload;
@@ -24,7 +25,7 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.network.PacketDistributor;
public final class LinkingBookScreen extends Screen {
public final class LinkingBookScreen extends Screen implements ExplorableBookScreen {
private static final int BOOK_TEXT_COLOR = 0xFF3B281B;
private static final ResourceLocation BOOK_TEXTURE = ResourceLocation.fromNamespaceAndPath(
"rivencraft", "textures/gui/linking_book.png"
@@ -45,6 +46,7 @@ public final class LinkingBookScreen extends Screen {
private DestinationPreviewRenderer preview;
private EditBox titleInput;
private Button exploreButton;
private boolean movingToExploreOverlay;
public LinkingBookScreen(InteractionHand hand, ItemStack book) {
super(book.getHoverName());
@@ -81,19 +83,24 @@ public final class LinkingBookScreen extends Screen {
.bounds(rightPage + 65, top + 100, 59, 20)
.build());
} else {
preview = DestinationPreviewRenderers.create();
boolean requestPreview = preview == null;
if (requestPreview) {
preview = DestinationPreviewRenderers.create();
}
if (preview.supportsExploration()) {
exploreButton = addRenderableWidget(Button.builder(
Component.translatable("screen.rivencraft.book.explore"), button -> toggleExploration())
Component.translatable("screen.rivencraft.book.explore"), button -> enterExploreOverlay())
.bounds(left + 61, top + 145, 60, 20).build());
}
PacketDistributor.sendToServer(new RequestLinkPreviewPayload(
false,
bookStandPos != null,
bookStandPos == null && hand == InteractionHand.OFF_HAND,
bookStandPos == null ? BlockPos.ZERO : bookStandPos,
preview.supportsExploration()
));
if (requestPreview) {
PacketDistributor.sendToServer(new RequestLinkPreviewPayload(
false,
bookStandPos != null,
bookStandPos == null && hand == InteractionHand.OFF_HAND,
bookStandPos == null ? BlockPos.ZERO : bookStandPos,
preview.supportsExploration()
));
}
}
}
@@ -117,6 +124,11 @@ public final class LinkingBookScreen extends Screen {
@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
renderBook(graphics, partialTick);
super.render(graphics, mouseX, mouseY, partialTick);
}
private void renderBook(GuiGraphics graphics, float partialTick) {
int left = (width - BOOK_WIDTH) / 2;
int top = (height - BOOK_HEIGHT) / 2;
graphics.blit(BOOK_TEXTURE, left, top, BOOK_WIDTH, BOOK_HEIGHT, 0, 0,
@@ -141,7 +153,6 @@ public final class LinkingBookScreen extends Screen {
Component.translatable("screen.rivencraft.book.click_to_link"), rightCenter, top + 119);
}
super.render(graphics, mouseX, mouseY, partialTick);
}
@Override
@@ -164,11 +175,12 @@ public final class LinkingBookScreen extends Screen {
@Override
public void removed() {
if (preview != null) {
if (preview != null && !movingToExploreOverlay) {
if (preview.supportsExploration()) {
PacketDistributor.sendToServer(new ReleaseLinkPreviewPayload());
}
preview.close();
preview = null;
}
}
@@ -193,10 +205,11 @@ public final class LinkingBookScreen extends Screen {
|| super.keyReleased(keyCode, scanCode, modifiers);
}
private void toggleExploration() {
preview.setExploring(!preview.isExploring());
exploreButton.setMessage(Component.translatable(preview.isExploring()
? "screen.rivencraft.book.exploring" : "screen.rivencraft.book.explore"));
private void enterExploreOverlay() {
preview.setExploring(true);
movingToExploreOverlay = true;
ClientBookExploreOverlay.open(this);
minecraft.setScreen(null);
}
private void resetExploration() {
@@ -210,6 +223,49 @@ public final class LinkingBookScreen extends Screen {
}
}
@Override
public Screen asScreen() {
return this;
}
@Override
public void tickExploreOverlay() {
preview.tick();
}
@Override
public void renderExploreOverlay(GuiGraphics graphics, float partialTick) {
width = minecraft.getWindow().getGuiScaledWidth();
height = minecraft.getWindow().getGuiScaledHeight();
renderBook(graphics, partialTick);
int left = (width - BOOK_WIDTH) / 2;
int top = (height - BOOK_HEIGHT) / 2;
drawCenteredWithoutShadow(graphics,
Component.translatable("screen.rivencraft.book.return_from_explore"),
left + 91, top + 154);
}
@Override
public void returnFromExploreOverlay() {
movingToExploreOverlay = false;
preview.resetView();
minecraft.setScreen(this);
}
@Override
public void abandonExploreOverlay() {
movingToExploreOverlay = false;
if (preview != null) {
preview.close();
preview = null;
}
}
@Override
public void acceptExplorePreview(LinkPreviewPayload payload) {
acceptPreview(payload);
}
private void bind() {
String name = titleInput.getValue().strip();
if (!name.isEmpty()) {
@@ -40,5 +40,6 @@
"screen.rivencraft.book.click_to_link": "Click the panel to link",
"screen.rivencraft.book.explore": "Explore",
"screen.rivencraft.book.exploring": "Exploring",
"screen.rivencraft.book.return_from_explore": "Right-click to return",
"itemGroup.rivencraft": "Rivencraft"
}