--- a/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java
@@ -20,6 +_,44 @@
 import net.minecraft.world.ticks.ContainerSingleItem;
 
 public class JukeboxBlockEntity extends BlockEntity implements ContainerSingleItem.BlockContainerSingleItem {
+
+    // CraftBukkit start - add fields and methods
+    public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
+    private int maxStack = MAX_STACK;
+    public boolean opened;
+
+    @Override
+    public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
+        return java.util.Collections.singletonList(this.item);
+    }
+
+    @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 @javax.annotation.Nullable org.bukkit.Location getLocation() {
+        if (this.level == null) return null;
+        return org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.worldPosition, this.level);
+    }
+    // CraftBukkit end
+
     public static final String SONG_ITEM_TAG_ID = "RecordItem";
     public static final String TICKS_SINCE_SONG_STARTED_TAG_ID = "ticks_since_song_started";
     private ItemStack item = ItemStack.EMPTY;
@@ -130,7 +_,7 @@
 
     @Override
     public int getMaxStackSize() {
-        return 1;
+        return this.maxStack; // CraftBukkit
     }
 
     @Override
@@ -154,11 +_,16 @@
     }
 
     @VisibleForTesting
-    public void setSongItemWithoutPlaying(ItemStack stack) {
+    public void setSongItemWithoutPlaying(ItemStack stack, final long ticksSinceSongStarted) { // CraftBukkit - passed ticks since song started
         this.item = stack;
-        JukeboxSong.fromStack(this.level.registryAccess(), stack)
-            .ifPresent(holder -> this.jukeboxSongPlayer.setSongWithoutPlaying((Holder<JukeboxSong>)holder, 0L));
-        this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock());
+        this.jukeboxSongPlayer.song = null; // CraftBukkit - reset
+        JukeboxSong.fromStack(this.level != null ? this.level.registryAccess() : org.bukkit.craftbukkit.CraftRegistry.getMinecraftRegistry(), stack) // Paper - fallback to other RegistryAccess if no level
+            .ifPresent(holder -> this.jukeboxSongPlayer.setSongWithoutPlaying((Holder<JukeboxSong>)holder, ticksSinceSongStarted)); // CraftBukkit - passed ticks since song started
+        // CraftBukkit start - add null check for level
+        if (this.level != null) {
+            this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock());
+        }
+        // CraftBukkit end
         this.setChanged();
     }
 
