Skip to content

Commit c240c1c

Browse files
Fix: Virtual lecterns not displaying book contents (#5169)
1 parent c145c3f commit c240c1c

File tree

3 files changed

+16
-19
lines changed

3 files changed

+16
-19
lines changed

core/src/main/java/org/geysermc/geyser/inventory/LecternContainer.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,24 @@
3434
import org.geysermc.geyser.translator.protocol.java.inventory.JavaOpenBookTranslator;
3535
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
3636

37+
@Getter
3738
public class LecternContainer extends Container {
38-
@Getter @Setter
39+
@Setter
3940
private int currentBedrockPage = 0;
40-
@Getter @Setter
41+
@Setter
4142
private NbtMap blockEntityTag;
42-
@Getter @Setter
43+
@Setter
4344
private Vector3i position;
4445

45-
// Sigh. When the lectern container is created, we don't know (yet) if it's fake or not.
46-
// So... time for a manual check :/
47-
@Getter
4846
private boolean isFakeLectern = false;
4947

5048
public LecternContainer(String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory) {
5149
super(title, id, size, containerType, playerInventory);
5250
}
5351

5452
/**
55-
* When we are using a fake lectern, the Java server expects us to still be in a player inventory.
56-
* We can't use {@link #isUsingRealBlock()} as that may not be determined yet.
53+
* 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.
54+
* We can't use the {@link #isUsingRealBlock()} check as we may also be dealing with a real virtual lectern (with its own inventory).
5755
*/
5856
@Override
5957
public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) {

core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public void openInventory(InventoryTranslator translator, GeyserSession session,
157157
@Override
158158
public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
159159
if (inventory instanceof Container container) {
160-
if (container.isUsingRealBlock() && !(inventory instanceof LecternContainer)) {
160+
if (container.isUsingRealBlock() && !(container instanceof LecternContainer)) {
161161
// No need to reset a block since we didn't change any blocks
162162
// But send a container close packet because we aren't destroying the original.
163163
ContainerClosePacket packet = new ContainerClosePacket();

core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import org.cloudburstmc.nbt.NbtMapBuilder;
3131
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
3232
import org.geysermc.erosion.util.LecternUtils;
33-
import org.geysermc.geyser.GeyserImpl;
34-
import org.geysermc.geyser.inventory.Container;
3533
import org.geysermc.geyser.inventory.GeyserItemStack;
3634
import org.geysermc.geyser.inventory.Inventory;
3735
import org.geysermc.geyser.inventory.LecternContainer;
@@ -55,7 +53,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
5553
* Hack: Java opens a lectern first, and then follows it up with a ClientboundContainerSetContentPacket
5654
* to actually send the book's contents. We delay opening the inventory until the book was sent.
5755
*/
58-
private boolean initialized = false;
56+
private boolean receivedBook = false;
5957

6058
public LecternInventoryTranslator() {
6159
super(1, Blocks.LECTERN, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE);
@@ -64,11 +62,12 @@ public LecternInventoryTranslator() {
6462
@Override
6563
public boolean prepareInventory(GeyserSession session, Inventory inventory) {
6664
super.prepareInventory(session, inventory);
67-
if (((Container) inventory).isUsingRealBlock()) {
68-
initialized = false; // We have to wait until we get the book to show to the client
65+
if (((LecternContainer) inventory).isFakeLectern()) {
66+
// See JavaOpenBookTranslator; this isn't a lectern but a book in the player inventory
67+
updateBook(session, inventory, inventory.getItem(0));
68+
receivedBook = true;
6969
} else {
70-
updateBook(session, inventory, inventory.getItem(0)); // See JavaOpenBookTranslator; placed here manually
71-
initialized = true;
70+
receivedBook = false; // We have to wait until we get the book
7271
}
7372
return true;
7473
}
@@ -79,7 +78,7 @@ public void openInventory(GeyserSession session, Inventory inventory) {
7978
// "initialized" indicates whether we've received the book from the Java server yet.
8079
// dropping lectern book is the fun workaround when we have to enter the gui to drop the book.
8180
// Since we leave it immediately... don't open it!
82-
if (initialized && !session.isDroppingLecternBook()) {
81+
if (receivedBook && !session.isDroppingLecternBook()) {
8382
super.openInventory(session, inventory);
8483
}
8584
}
@@ -122,8 +121,8 @@ public void updateInventory(GeyserSession session, Inventory inventory) {
122121
boolean isDropping = session.isDroppingLecternBook();
123122
updateBook(session, inventory, itemStack);
124123

125-
if (!initialized && !isDropping) {
126-
initialized = true;
124+
if (!receivedBook && !isDropping) {
125+
receivedBook = true;
127126
openInventory(session, inventory);
128127
}
129128
}

0 commit comments

Comments
 (0)