--- a/net/minecraft/world/level/block/entity/LecternBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/LecternBlockEntity.java
@@ -36,7 +_,53 @@
     public static final int NUM_DATA = 1;
     public static final int SLOT_BOOK = 0;
     public static final int NUM_SLOTS = 1;
-    private final Container bookAccess = new Container() {
+    // CraftBukkit start - add fields and methods
+    public final Container bookAccess = new LecternInventory();
+    public class LecternInventory implements Container {
+        public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
+        private int maxStack = 1;
+
+        @Override
+        public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
+            return java.util.List.of(LecternBlockEntity.this.book);
+        }
+
+        @Override
+        public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
+            this.transaction.add(player);
+        }
+
+        @Override
+        public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity player) {
+            this.transaction.remove(player);
+        }
+
+        @Override
+        public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
+            return this.transaction;
+        }
+
+        @Override
+        public void setMaxStackSize(int size) {
+            this.maxStack = size;
+        }
+
+        @Override
+        public @Nullable org.bukkit.Location getLocation() {
+            if (LecternBlockEntity.this.level == null) return null;
+            return org.bukkit.craftbukkit.util.CraftLocation.toBukkit(LecternBlockEntity.this.worldPosition, LecternBlockEntity.this.level);
+        }
+
+        @Override
+        public org.bukkit.inventory.InventoryHolder getOwner() {
+            return LecternBlockEntity.this.getOwner();
+        }
+
+        public LecternBlockEntity getLectern() {
+            return LecternBlockEntity.this;
+        }
+        // CraftBukkit end
+
         @Override
         public int getContainerSize() {
             return 1;
@@ -80,11 +_,19 @@
 
         @Override
         public void setItem(int slot, ItemStack stack) {
+            // CraftBukkit start
+            if (slot == 0) {
+                LecternBlockEntity.this.setBook(stack);
+                if (LecternBlockEntity.this.getLevel() != null) {
+                    LecternBlock.resetBookState(null, LecternBlockEntity.this.getLevel(), LecternBlockEntity.this.getBlockPos(), LecternBlockEntity.this.getBlockState(), LecternBlockEntity.this.hasBook());
+                }
+            }
+            // CraftBukkit end
         }
 
         @Override
         public int getMaxStackSize() {
-            return 1;
+            return this.maxStack; // CraftBukkit
         }
 
         @Override
@@ -157,12 +_,12 @@
         this.setChanged();
     }
 
-    void setPage(int page) {
+    public void setPage(int page) {
         int i = Mth.clamp(page, 0, this.pageCount - 1);
         if (i != this.page) {
             this.page = i;
             this.setChanged();
-            LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState());
+            if (this.level != null) LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit
         }
     }
 
@@ -183,6 +_,36 @@
         return stack;
     }
 
+    // CraftBukkit start
+    private final CommandSource commandSource = new CommandSource() {
+
+        @Override
+        public void sendSystemMessage(Component message) {
+        }
+
+        @Override
+        public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack commandSourceStack) {
+            return commandSourceStack.getEntity() != null
+                ? commandSourceStack.getEntity().getBukkitEntity()
+                : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(commandSourceStack, LecternBlockEntity.this);
+        }
+
+        @Override
+        public boolean acceptsSuccess() {
+            return false;
+        }
+
+        @Override
+        public boolean acceptsFailure() {
+            return false;
+        }
+
+        @Override
+        public boolean shouldInformAdmins() {
+            return false;
+        }
+    };
+    // CraftBukkit end
     private CommandSourceStack createCommandSourceStack(@Nullable Player player, ServerLevel level) {
         String string;
         Component component;
@@ -195,7 +_,7 @@
         }
 
         Vec3 vec3 = Vec3.atCenterOf(this.worldPosition);
-        return new CommandSourceStack(CommandSource.NULL, vec3, Vec2.ZERO, level, 2, string, component, level.getServer(), player);
+        return new CommandSourceStack(this.commandSource, vec3, Vec2.ZERO, level, 2, string, component, level.getServer(), player); // CraftBukkit - commandSource
     }
 
     @Override
@@ -237,7 +_,7 @@
 
     @Override
     public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
-        return new LecternMenu(containerId, this.bookAccess, this.dataAccess);
+        return new LecternMenu(containerId, this.bookAccess, this.dataAccess, playerInventory); // CraftBukkit
     }
 
     @Override
