--- a/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java
@@ -24,16 +24,61 @@
 import net.minecraft.world.phys.Vec3;
 import net.minecraft.world.ticks.ContainerSingleItem;
 
+// CraftBukkit start
+import java.util.List;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_20_R2.entity.CraftHumanEntity;
+import org.bukkit.entity.HumanEntity;
+// CraftBukkit end
+
 public class JukeboxBlockEntity extends BlockEntity implements Clearable, ContainerSingleItem {
+
     private static final int SONG_END_PADDING = 20;
-    private final NonNullList<ItemStack> items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
+    private final NonNullList<ItemStack> items;
     private int ticksSinceLastEvent;
     public long tickCount;
     public long recordStartedTick;
     public boolean isPlaying;
+    // CraftBukkit start - add fields and methods
+    public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
+    private int maxStack = MAX_STACK;
+    public boolean opened;
+
+    @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 (this.level == null) return null;
+        return new org.bukkit.Location(this.level.getWorld(), this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
+    }
+    // CraftBukkit end
 
     public JukeboxBlockEntity(BlockPos pos, BlockState state) {
         super(BlockEntityType.JUKEBOX, pos, state);
+        this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
     }
 
     @Override
@@ -66,7 +111,7 @@
 
     private void setHasRecordBlockState(@Nullable Entity entity, boolean hasRecord) {
         if (this.level.getBlockState(this.getBlockPos()) == this.getBlockState()) {
-            this.level.setBlock(this.getBlockPos(), this.getBlockState().setValue(JukeboxBlock.HAS_RECORD, Boolean.valueOf(hasRecord)), 2);
+            this.level.setBlock(this.getBlockPos(), (BlockState) this.getBlockState().setValue(JukeboxBlock.HAS_RECORD, hasRecord), 2);
             this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState()));
         }
 
@@ -77,7 +122,7 @@
         this.recordStartedTick = this.tickCount;
         this.isPlaying = true;
         this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock());
-        this.level.levelEvent((Player)null, 1010, this.getBlockPos(), Item.getId(this.getFirstItem().getItem()));
+        this.level.levelEvent((Player) null, 1010, this.getBlockPos(), Item.getId(this.getFirstItem().getItem()));
         this.setChanged();
     }
 
@@ -92,10 +137,12 @@
     private void tick(Level world, BlockPos pos, BlockState state) {
         ++this.ticksSinceLastEvent;
         if (this.isRecordPlaying()) {
-            Item var5 = this.getFirstItem().getItem();
-            if (var5 instanceof RecordItem) {
-                RecordItem recordItem = (RecordItem)var5;
-                if (this.shouldRecordStopPlaying(recordItem)) {
+            Item item = this.getFirstItem().getItem();
+
+            if (item instanceof RecordItem) {
+                RecordItem itemrecord = (RecordItem) item;
+
+                if (this.shouldRecordStopPlaying(itemrecord)) {
                     this.stopPlaying();
                 } else if (this.shouldSendJukeboxPlayingEvent()) {
                     this.ticksSinceLastEvent = 0;
@@ -109,7 +156,7 @@
     }
 
     private boolean shouldRecordStopPlaying(RecordItem musicDisc) {
-        return this.tickCount >= this.recordStartedTick + (long)musicDisc.getLengthInTicks() + 20L;
+        return this.tickCount >= this.recordStartedTick + (long) musicDisc.getLengthInTicks() + 20L;
     }
 
     private boolean shouldSendJukeboxPlayingEvent() {
@@ -118,26 +165,27 @@
 
     @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()) {
-            this.setHasRecordBlockState((Entity)null, false);
+        if (!itemstack.isEmpty()) {
+            this.setHasRecordBlockState((Entity) null, false);
             this.stopPlaying();
         }
 
-        return itemStack;
+        return itemstack;
     }
 
     @Override
     public void setItem(int slot, ItemStack stack) {
         if (stack.is(ItemTags.MUSIC_DISCS) && this.level != null) {
             this.items.set(slot, stack);
-            this.setHasRecordBlockState((Entity)null, true);
+            this.setHasRecordBlockState((Entity) null, true);
             this.startPlaying();
         } else if (stack.isEmpty()) {
             this.removeItem(slot, 1);
@@ -147,7 +195,7 @@
 
     @Override
     public int getMaxStackSize() {
-        return 1;
+        return this.maxStack; // CraftBukkit
     }
 
     @Override
@@ -166,25 +214,29 @@
     }
 
     private void spawnMusicParticles(Level world, BlockPos pos) {
-        if (world instanceof ServerLevel serverLevel) {
-            Vec3 vec3 = Vec3.atBottomCenterOf(pos).add(0.0D, (double)1.2F, 0.0D);
-            float f = (float)world.getRandom().nextInt(4) / 24.0F;
-            serverLevel.sendParticles(ParticleTypes.NOTE, vec3.x(), vec3.y(), vec3.z(), 0, (double)f, 0.0D, 0.0D, 1.0D);
+        if (world instanceof ServerLevel) {
+            ServerLevel worldserver = (ServerLevel) world;
+            Vec3 vec3d = Vec3.atBottomCenterOf(pos).add(0.0D, 1.2000000476837158D, 0.0D);
+            float f = (float) world.getRandom().nextInt(4) / 24.0F;
+
+            worldserver.sendParticles(ParticleTypes.NOTE, vec3d.x(), vec3d.y(), vec3d.z(), 0, (double) f, 0.0D, 0.0D, 1.0D);
         }
 
     }
 
     public void popOutRecord() {
         if (this.level != null && !this.level.isClientSide) {
-            BlockPos blockPos = this.getBlockPos();
-            ItemStack itemStack = this.getFirstItem();
-            if (!itemStack.isEmpty()) {
+            BlockPos blockposition = this.getBlockPos();
+            ItemStack itemstack = this.getFirstItem();
+
+            if (!itemstack.isEmpty()) {
                 this.removeFirstItem();
-                Vec3 vec3 = Vec3.atLowerCornerWithOffset(blockPos, 0.5D, 1.01D, 0.5D).offsetRandom(this.level.random, 0.7F);
-                ItemStack itemStack2 = itemStack.copy();
-                ItemEntity itemEntity = new ItemEntity(this.level, vec3.x(), vec3.y(), vec3.z(), itemStack2);
-                itemEntity.setDefaultPickUpDelay();
-                this.level.addFreshEntity(itemEntity);
+                Vec3 vec3d = Vec3.atLowerCornerWithOffset(blockposition, 0.5D, 1.01D, 0.5D).offsetRandom(this.level.random, 0.7F);
+                ItemStack itemstack1 = itemstack.copy();
+                ItemEntity entityitem = new ItemEntity(this.level, vec3d.x(), vec3d.y(), vec3d.z(), itemstack1);
+
+                entityitem.setDefaultPickUpDelay();
+                this.level.addFreshEntity(entityitem);
             }
         }
     }
@@ -196,7 +248,11 @@
     @VisibleForTesting
     public void setRecordWithoutPlaying(ItemStack stack) {
         this.items.set(0, stack);
-        this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock());
+        // CraftBukkit start - add null check for level
+        if (this.level != null) {
+            this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock());
+        }
+        // CraftBukkit end
         this.setChanged();
     }
 }
