Environment
- Cardboard branch/build:
ver/1.21.11, official 1.21.11-14, also reproduced on self-built patched jar
- Minecraft:
1.21.11
- Fabric Loader:
0.18.6
- Java:
21
- Server mode:
online-mode=false
- Plugins used when reproducing: reproducible even without Bukkit plugins loaded
- Mods: Fabric server with mods; lectern works in singleplayer with same mods
Problem
Interacting with a lectern on Cardboard 1.21.11 is broken.
Initial behavior:
- Opening a lectern with a book caused a
ClassCastException in LecternMenuMixin#setPlayerInv
- Root cause:
Container passed to LecternMenu(int, Container, ContainerData) was cast to player Inventory, but for lecterns it is not a player inventory
After patching that:
- Opening the lectern started working
- Then taking the book caused a
NullPointerException because this.player in CraftInventoryView was null
- I patched this by setting the Bukkit player in
ServerPlayerMixin#openHandledScreen_c before the inventory open event for LecternMenu
After that:
- Opening the lectern works
- Taking the book works
- But
PlayerTakeLecternBookEvent still logs an error in WorldGuard because CraftInventoryLectern#getHolder() expects ContainerBridge, while the lectern container is not always a ContainerBridge
Observed errors
- Original open crash:
java.lang.ClassCastException: class net.minecraft.class_3722$1 cannot be cast to class net.minecraft.class_1661
at ... LecternMenuMixin#setPlayerInv
- After first patch:
java.lang.NullPointerException: Cannot invoke "org.bukkit.craftbukkit.entity.CraftHumanEntity.getInventory()" because "this.player" is null
- Current remaining issue when taking the book:
Could not pass event PlayerTakeLecternBookEvent to WorldGuard
java.lang.ClassCastException: class net.minecraft.class_3722$1 cannot be cast to class org.cardboardpowered.bridge.world.ContainerBridge
at org.bukkit.craftbukkit.inventory.CraftInventoryLectern.getHolder(CraftInventoryLectern.java:17)
Vanilla source context
LecternMenu in 1.21.11 only has:
LecternMenu(int)
LecternMenu(int, Container, ContainerData)
So the mixin assumption that the second argument is always Inventory is invalid for lecterns.
Suggested fix direction
- Do not cast the
Container in LecternMenuMixin#setPlayerInv to Inventory without an instanceof check
- Populate the Bukkit player for
LecternMenu later, at menu-open time, where the actual ServerPlayer is known
- Make
CraftInventoryLectern#getHolder() safe when the backing inventory is not a ContainerBridge
Reproduction
- Start Cardboard 1.21.11 server
- Place lectern
- Put written book into lectern
- Right click lectern
- Try to take the book
Result
Lectern behavior is broken unless Cardboard is manually patched.
Environment
ver/1.21.11, official1.21.11-14, also reproduced on self-built patched jar1.21.110.18.621online-mode=falseProblem
Interacting with a lectern on Cardboard 1.21.11 is broken.
Initial behavior:
ClassCastExceptioninLecternMenuMixin#setPlayerInvContainerpassed toLecternMenu(int, Container, ContainerData)was cast to playerInventory, but for lecterns it is not a player inventoryAfter patching that:
NullPointerExceptionbecausethis.playerinCraftInventoryViewwas nullServerPlayerMixin#openHandledScreen_cbefore the inventory open event forLecternMenuAfter that:
PlayerTakeLecternBookEventstill logs an error in WorldGuard becauseCraftInventoryLectern#getHolder()expectsContainerBridge, while the lectern container is not always aContainerBridgeObserved errors
Vanilla source context
LecternMenuin 1.21.11 only has:LecternMenu(int)LecternMenu(int, Container, ContainerData)So the mixin assumption that the second argument is always
Inventoryis invalid for lecterns.Suggested fix direction
ContainerinLecternMenuMixin#setPlayerInvtoInventorywithout aninstanceofcheckLecternMenulater, at menu-open time, where the actualServerPlayeris knownCraftInventoryLectern#getHolder()safe when the backing inventory is not aContainerBridgeReproduction
Result
Lectern behavior is broken unless Cardboard is manually patched.