From c240c1cfb540b79145a4bf758621dbcfe6f06551 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 29 Nov 2024 11:43:58 +0800 Subject: [PATCH] Fix: Virtual lecterns not displaying book contents (#5169) --- .../geyser/inventory/LecternContainer.java | 14 ++++++-------- .../holder/BlockInventoryHolder.java | 2 +- .../inventory/LecternInventoryTranslator.java | 19 +++++++++---------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java index 389611c67..ff21f561e 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java @@ -34,17 +34,15 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.java.inventory.JavaOpenBookTranslator; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; +@Getter public class LecternContainer extends Container { - @Getter @Setter + @Setter private int currentBedrockPage = 0; - @Getter @Setter + @Setter private NbtMap blockEntityTag; - @Getter @Setter + @Setter private Vector3i position; - // Sigh. When the lectern container is created, we don't know (yet) if it's fake or not. - // So... time for a manual check :/ - @Getter private boolean isFakeLectern = false; public LecternContainer(String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory) { @@ -52,8 +50,8 @@ public class LecternContainer extends Container { } /** - * When we are using a fake lectern, the Java server expects us to still be in a player inventory. - * We can't use {@link #isUsingRealBlock()} as that may not be determined yet. + * When the Java server asks the client to open a book in their hotbar, we create a fake lectern to show it to the client. + * We can't use the {@link #isUsingRealBlock()} check as we may also be dealing with a real virtual lectern (with its own inventory). */ @Override public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) { diff --git a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java index cdda4fe4c..385a1e2bd 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java @@ -157,7 +157,7 @@ public class BlockInventoryHolder extends InventoryHolder { @Override public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { if (inventory instanceof Container container) { - if (container.isUsingRealBlock() && !(inventory instanceof LecternContainer)) { + if (container.isUsingRealBlock() && !(container instanceof LecternContainer)) { // No need to reset a block since we didn't change any blocks // But send a container close packet because we aren't destroying the original. ContainerClosePacket packet = new ContainerClosePacket(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java index 3b33f5909..007811999 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java @@ -30,8 +30,6 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.erosion.util.LecternUtils; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.LecternContainer; @@ -55,7 +53,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator * Hack: Java opens a lectern first, and then follows it up with a ClientboundContainerSetContentPacket * to actually send the book's contents. We delay opening the inventory until the book was sent. */ - private boolean initialized = false; + private boolean receivedBook = false; public LecternInventoryTranslator() { super(1, Blocks.LECTERN, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE); @@ -64,11 +62,12 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator @Override public boolean prepareInventory(GeyserSession session, Inventory inventory) { super.prepareInventory(session, inventory); - if (((Container) inventory).isUsingRealBlock()) { - initialized = false; // We have to wait until we get the book to show to the client + if (((LecternContainer) inventory).isFakeLectern()) { + // See JavaOpenBookTranslator; this isn't a lectern but a book in the player inventory + updateBook(session, inventory, inventory.getItem(0)); + receivedBook = true; } else { - updateBook(session, inventory, inventory.getItem(0)); // See JavaOpenBookTranslator; placed here manually - initialized = true; + receivedBook = false; // We have to wait until we get the book } return true; } @@ -79,7 +78,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator // "initialized" indicates whether we've received the book from the Java server yet. // dropping lectern book is the fun workaround when we have to enter the gui to drop the book. // Since we leave it immediately... don't open it! - if (initialized && !session.isDroppingLecternBook()) { + if (receivedBook && !session.isDroppingLecternBook()) { super.openInventory(session, inventory); } } @@ -122,8 +121,8 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator boolean isDropping = session.isDroppingLecternBook(); updateBook(session, inventory, itemStack); - if (!initialized && !isDropping) { - initialized = true; + if (!receivedBook && !isDropping) { + receivedBook = true; openInventory(session, inventory); } }