--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
@@ -11,35 +11,82 @@
 import net.minecraft.world.ContainerHelper;
 import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.Level;
 import net.minecraft.world.level.block.ChiseledBookShelfBlock;
 import net.minecraft.world.level.block.state.BlockState;
 import net.minecraft.world.level.block.state.properties.BooleanProperty;
 import org.slf4j.Logger;
 
+// CraftBukkit start
+import java.util.List;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_19_R2.entity.CraftHumanEntity;
+import org.bukkit.entity.HumanEntity;
+// CraftBukkit end
+
 public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container {
+
     public static final int MAX_BOOKS_IN_STORAGE = 6;
     private static final Logger LOGGER = LogUtils.getLogger();
-    private final NonNullList<ItemStack> items = NonNullList.withSize(6, ItemStack.EMPTY);
-    public int lastInteractedSlot = -1;
+    private final NonNullList<ItemStack> items;
+    public int lastInteractedSlot;
+    // CraftBukkit start - add fields and methods
+    public List<HumanEntity> transaction = new java.util.ArrayList<>();
+    private int maxStack = 1;
+
+    @Override
+    public List<ItemStack> getContents() {
+        return this.items;
+    }
+
+    @Override
+    public void onOpen(CraftHumanEntity who) {
+        this.transaction.add(who);
+    }
+
+    @Override
+    public void onClose(CraftHumanEntity who) {
+        this.transaction.remove(who);
+    }
+
+    @Override
+    public List<HumanEntity> getViewers() {
+        return this.transaction;
+    }
+
+    @Override
+    public void setMaxStackSize(int size) {
+        this.maxStack = size;
+    }
+
+    @Override
+    public Location getLocation() {
+        if (level == null) return null;
+        return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ());
+    }
+    // CraftBukkit end
 
     public ChiseledBookShelfBlockEntity(BlockPos pos, BlockState state) {
         super(BlockEntityType.CHISELED_BOOKSHELF, pos, state);
+        this.items = NonNullList.withSize(6, ItemStack.EMPTY);
+        this.lastInteractedSlot = -1;
     }
 
     private void updateState(int interactedSlot) {
         if (interactedSlot >= 0 && interactedSlot < 6) {
             this.lastInteractedSlot = interactedSlot;
-            BlockState blockState = this.getBlockState();
+            BlockState iblockdata = this.getBlockState();
 
-            for(int i = 0; i < ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.size(); ++i) {
-                boolean bl = !this.getItem(i).isEmpty();
-                BooleanProperty booleanProperty = ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.get(i);
-                blockState = blockState.setValue(booleanProperty, Boolean.valueOf(bl));
+            for (int j = 0; j < ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.size(); ++j) {
+                boolean flag = !this.getItem(j).isEmpty();
+                BooleanProperty blockstateboolean = (BooleanProperty) ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.get(j);
+
+                iblockdata = (BlockState) iblockdata.setValue(blockstateboolean, flag);
             }
 
-            Objects.requireNonNull(this.level).setBlock(this.worldPosition, blockState, 3);
+            ((Level) Objects.requireNonNull(this.level)).setBlock(this.worldPosition, iblockdata, 3);
         } else {
-            LOGGER.error("Expected slot 0-5, got {}", (int)interactedSlot);
+            ChiseledBookShelfBlockEntity.LOGGER.error("Expected slot 0-5, got {}", interactedSlot);
         }
     }
 
@@ -57,7 +104,7 @@
     }
 
     public int count() {
-        return (int)this.items.stream().filter(Predicate.not(ItemStack::isEmpty)).count();
+        return (int) this.items.stream().filter(Predicate.not(ItemStack::isEmpty)).count();
     }
 
     @Override
@@ -77,18 +124,19 @@
 
     @Override
     public ItemStack getItem(int slot) {
-        return this.items.get(slot);
+        return (ItemStack) this.items.get(slot);
     }
 
     @Override
     public ItemStack removeItem(int slot, int amount) {
-        ItemStack itemStack = Objects.requireNonNullElse(this.items.get(slot), ItemStack.EMPTY);
+        ItemStack itemstack = (ItemStack) Objects.requireNonNullElse((ItemStack) this.items.get(slot), ItemStack.EMPTY);
+
         this.items.set(slot, ItemStack.EMPTY);
-        if (!itemStack.isEmpty()) {
+        if (!itemstack.isEmpty()) {
             this.updateState(slot);
         }
 
-        return itemStack;
+        return itemstack;
     }
 
     @Override
@@ -107,18 +155,12 @@
 
     @Override
     public int getMaxStackSize() {
-        return 1;
+        return this.maxStack; // CraftBukkit
     }
 
     @Override
     public boolean stillValid(Player player) {
-        if (this.level == null) {
-            return false;
-        } else if (this.level.getBlockEntity(this.worldPosition) != this) {
-            return false;
-        } else {
-            return !(player.distanceToSqr((double)this.worldPosition.getX() + 0.5D, (double)this.worldPosition.getY() + 0.5D, (double)this.worldPosition.getZ() + 0.5D) > 64.0D);
-        }
+        return this.level == null ? false : (this.level.getBlockEntity(this.worldPosition) != this ? false : player.distanceToSqr((double) this.worldPosition.getX() + 0.5D, (double) this.worldPosition.getY() + 0.5D, (double) this.worldPosition.getZ() + 0.5D) <= 64.0D);
     }
 
     @Override
