From 7d42b87010153b1ed1014c1d66c3eb136f5990e8 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Fri, 13 Dec 2024 19:17:03 +0100
Subject: [PATCH] net/minecraft/world + Tadpole?

---
 .../net/minecraft/world/BossEvent.java.patch  | 32 ++++----
 .../world/CompoundContainer.java.patch        | 60 +++++++++++++++
 .../net/minecraft/world/Container.java.patch  | 36 +++++++++
 .../world/RandomizableContainer.java.patch    | 64 ++++++++--------
 .../world/SimpleContainer.java.patch          | 54 +++++---------
 .../entity/animal/frog/Tadpole.java.patch     | 22 +++---
 .../world/CompoundContainer.java.patch        | 74 -------------------
 .../net/minecraft/world/Container.java.patch  | 49 ------------
 8 files changed, 173 insertions(+), 218 deletions(-)
 rename paper-server/patches/{unapplied => sources}/net/minecraft/world/BossEvent.java.patch (77%)
 create mode 100644 paper-server/patches/sources/net/minecraft/world/CompoundContainer.java.patch
 create mode 100644 paper-server/patches/sources/net/minecraft/world/Container.java.patch
 rename paper-server/patches/{unapplied => sources}/net/minecraft/world/RandomizableContainer.java.patch (65%)
 rename paper-server/patches/{unapplied => sources}/net/minecraft/world/SimpleContainer.java.patch (68%)
 delete mode 100644 paper-server/patches/unapplied/net/minecraft/world/CompoundContainer.java.patch
 delete mode 100644 paper-server/patches/unapplied/net/minecraft/world/Container.java.patch

diff --git a/paper-server/patches/unapplied/net/minecraft/world/BossEvent.java.patch b/paper-server/patches/sources/net/minecraft/world/BossEvent.java.patch
similarity index 77%
rename from paper-server/patches/unapplied/net/minecraft/world/BossEvent.java.patch
rename to paper-server/patches/sources/net/minecraft/world/BossEvent.java.patch
index 3210ddc320..ae696def49 100644
--- a/paper-server/patches/unapplied/net/minecraft/world/BossEvent.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/BossEvent.java.patch
@@ -1,14 +1,14 @@
 --- a/net/minecraft/world/BossEvent.java
 +++ b/net/minecraft/world/BossEvent.java
-@@ -13,6 +13,7 @@
+@@ -13,6 +_,7 @@
      protected boolean darkenScreen;
      protected boolean playBossMusic;
      protected boolean createWorldFog;
 +    public net.kyori.adventure.bossbar.BossBar adventure; // Paper
  
-     public BossEvent(UUID uuid, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay style) {
-         this.id = uuid;
-@@ -27,61 +28,75 @@
+     public BossEvent(UUID id, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay overlay) {
+         this.id = id;
+@@ -27,61 +_,75 @@
      }
  
      public Component getName() {
@@ -26,9 +26,9 @@
          return this.progress;
      }
  
-     public void setProgress(float percent) {
-+        if (this.adventure != null) this.adventure.progress(percent); // Paper
-         this.progress = percent;
+     public void setProgress(float progress) {
++        if (this.adventure != null) this.adventure.progress(progress); // Paper
+         this.progress = progress;
      }
  
      public BossEvent.BossBarColor getColor() {
@@ -46,9 +46,9 @@
          return this.overlay;
      }
  
-     public void setOverlay(BossEvent.BossBarOverlay style) {
-+        if (this.adventure != null) this.adventure.overlay(io.papermc.paper.adventure.PaperAdventure.asAdventure(style)); // Paper
-         this.overlay = style;
+     public void setOverlay(BossEvent.BossBarOverlay overlay) {
++        if (this.adventure != null) this.adventure.overlay(io.papermc.paper.adventure.PaperAdventure.asAdventure(overlay)); // Paper
+         this.overlay = overlay;
      }
  
      public boolean shouldDarkenScreen() {
@@ -67,15 +67,15 @@
          return this.playBossMusic;
      }
  
-     public BossEvent setPlayBossMusic(boolean dragonMusic) {
-+        if (this.adventure != null) io.papermc.paper.adventure.PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC, dragonMusic); // Paper
-         this.playBossMusic = dragonMusic;
+     public BossEvent setPlayBossMusic(boolean playEndBossMusic) {
++        if (this.adventure != null) io.papermc.paper.adventure.PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC, playEndBossMusic); // Paper
+         this.playBossMusic = playEndBossMusic;
          return this;
      }
  
-     public BossEvent setCreateWorldFog(boolean thickenFog) {
-+        if (this.adventure != null) io.papermc.paper.adventure.PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG, thickenFog); // Paper
-         this.createWorldFog = thickenFog;
+     public BossEvent setCreateWorldFog(boolean createFog) {
++        if (this.adventure != null) io.papermc.paper.adventure.PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG, createFog); // Paper
+         this.createWorldFog = createFog;
          return this;
      }
  
diff --git a/paper-server/patches/sources/net/minecraft/world/CompoundContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/CompoundContainer.java.patch
new file mode 100644
index 0000000000..ffcea4eeab
--- /dev/null
+++ b/paper-server/patches/sources/net/minecraft/world/CompoundContainer.java.patch
@@ -0,0 +1,60 @@
+--- a/net/minecraft/world/CompoundContainer.java
++++ b/net/minecraft/world/CompoundContainer.java
+@@ -7,6 +_,48 @@
+     private final Container container1;
+     private final Container container2;
+ 
++    // Paper start - add fields and methods
++    public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<org.bukkit.entity.HumanEntity>();
++
++    public java.util.List<ItemStack> getContents() {
++        java.util.List<ItemStack> result = new java.util.ArrayList<>(this.getContainerSize());
++        for (int i = 0; i < this.getContainerSize(); i++) {
++            result.add(this.getItem(i));
++        }
++        return result;
++    }
++
++    public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
++        this.container1.onOpen(who);
++        this.container2.onOpen(who);
++        this.transaction.add(who);
++    }
++
++    public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
++        this.container1.onClose(who);
++        this.container2.onClose(who);
++        this.transaction.remove(who);
++    }
++
++    public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
++        return this.transaction;
++    }
++
++    public org.bukkit.inventory.InventoryHolder getOwner() {
++        return null; // This method won't be called since CraftInventoryDoubleChest doesn't defer to here
++    }
++
++    public void setMaxStackSize(int size) {
++        this.container1.setMaxStackSize(size);
++        this.container2.setMaxStackSize(size);
++    }
++
++    @Override
++    public org.bukkit.Location getLocation() {
++        return this.container1.getLocation(); // TODO: right?
++    }
++    // Paper end
++
+     public CompoundContainer(Container container1, Container container2) {
+         this.container1 = container1;
+         this.container2 = container2;
+@@ -58,7 +_,7 @@
+ 
+     @Override
+     public int getMaxStackSize() {
+-        return this.container1.getMaxStackSize();
++        return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // Paper - check both sides
+     }
+ 
+     @Override
diff --git a/paper-server/patches/sources/net/minecraft/world/Container.java.patch b/paper-server/patches/sources/net/minecraft/world/Container.java.patch
new file mode 100644
index 0000000000..ac7f19ed19
--- /dev/null
+++ b/paper-server/patches/sources/net/minecraft/world/Container.java.patch
@@ -0,0 +1,36 @@
+--- a/net/minecraft/world/Container.java
++++ b/net/minecraft/world/Container.java
+@@ -24,9 +_,7 @@
+ 
+     void setItem(int slot, ItemStack stack);
+ 
+-    default int getMaxStackSize() {
+-        return 99;
+-    }
++    int getMaxStackSize(); // Paper
+ 
+     default int getMaxStackSize(ItemStack stack) {
+         return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
+@@ -87,4 +_,22 @@
+         BlockPos blockPos = blockEntity.getBlockPos();
+         return level != null && level.getBlockEntity(blockPos) == blockEntity && player.canInteractWithBlock(blockPos, distance);
+     }
++
++    // Paper start
++    java.util.List<ItemStack> getContents();
++
++    void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who);
++
++    void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who);
++
++    java.util.List<org.bukkit.entity.HumanEntity> getViewers();
++
++    org.bukkit.inventory.@org.jetbrains.annotations.Nullable InventoryHolder getOwner(); // Paper - annotation
++
++    void setMaxStackSize(int size);
++
++    org.bukkit.Location getLocation();
++
++    int MAX_STACK = 99;
++    // Paper end
+ }
diff --git a/paper-server/patches/unapplied/net/minecraft/world/RandomizableContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/RandomizableContainer.java.patch
similarity index 65%
rename from paper-server/patches/unapplied/net/minecraft/world/RandomizableContainer.java.patch
rename to paper-server/patches/sources/net/minecraft/world/RandomizableContainer.java.patch
index a79a33da44..8467c86645 100644
--- a/paper-server/patches/unapplied/net/minecraft/world/RandomizableContainer.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/RandomizableContainer.java.patch
@@ -1,23 +1,23 @@
 --- a/net/minecraft/world/RandomizableContainer.java
 +++ b/net/minecraft/world/RandomizableContainer.java
-@@ -28,7 +28,7 @@
+@@ -28,7 +_,7 @@
  
      void setLootTable(@Nullable ResourceKey<LootTable> lootTable);
  
--    default void setLootTable(ResourceKey<LootTable> lootTableId, long lootTableSeed) {
-+    default void setLootTable(@Nullable ResourceKey<LootTable> lootTableId, long lootTableSeed) { // Paper - add nullable
-         this.setLootTable(lootTableId);
-         this.setLootTableSeed(lootTableSeed);
+-    default void setLootTable(ResourceKey<LootTable> lootTable, long seed) {
++    default void setLootTable(@Nullable ResourceKey<LootTable> lootTable, long seed) { // Paper - add nullable
+         this.setLootTable(lootTable);
+         this.setLootTableSeed(seed);
      }
-@@ -50,14 +50,15 @@
+@@ -50,14 +_,15 @@
  
-     default boolean tryLoadLootTable(CompoundTag nbt) {
-         if (nbt.contains("LootTable", 8)) {
--            this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(nbt.getString("LootTable"))));
-+            this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
-+            if (this.lootableData() != null && this.getLootTable() != null) this.lootableData().loadNbt(nbt); // Paper - LootTable API
-             if (nbt.contains("LootTableSeed", 4)) {
-                 this.setLootTableSeed(nbt.getLong("LootTableSeed"));
+     default boolean tryLoadLootTable(CompoundTag tag) {
+         if (tag.contains("LootTable", 8)) {
+-            this.setLootTable(ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(tag.getString("LootTable"))));
++            this.setLootTable(net.minecraft.Optionull.map(ResourceLocation.tryParse(tag.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl))); // Paper - Validate ResourceLocation
++            if (this.lootableData() != null && this.getLootTable() != null) this.lootableData().loadNbt(tag); // Paper - LootTable API
+             if (tag.contains("LootTableSeed", 4)) {
+                 this.setLootTableSeed(tag.getLong("LootTableSeed"));
              } else {
                  this.setLootTableSeed(0L);
              }
@@ -27,14 +27,14 @@
          } else {
              return false;
          }
-@@ -69,26 +70,44 @@
+@@ -69,26 +_,42 @@
              return false;
          } else {
-             nbt.putString("LootTable", resourceKey.location().toString());
-+            if (this.lootableData() != null) this.lootableData().saveNbt(nbt); // Paper - LootTable API
-             long l = this.getLootTableSeed();
-             if (l != 0L) {
-                 nbt.putLong("LootTableSeed", l);
+             tag.putString("LootTable", lootTable.location().toString());
++            if (this.lootableData() != null) this.lootableData().saveNbt(tag); // Paper - LootTable API
+             long lootTableSeed = this.getLootTableSeed();
+             if (lootTableSeed != 0L) {
+                 tag.putLong("LootTableSeed", lootTableSeed);
              }
  
 -            return true;
@@ -50,10 +50,10 @@
 +        // Paper end - LootTable API
          Level level = this.getLevel();
          BlockPos blockPos = this.getBlockPos();
-         ResourceKey<LootTable> resourceKey = this.getLootTable();
--        if (resourceKey != null && level != null && level.getServer() != null) {
+         ResourceKey<LootTable> lootTable = this.getLootTable();
+-        if (lootTable != null && level != null && level.getServer() != null) {
 +        // Paper start - LootTable API
-+        lootReplenish: if (resourceKey != null && level != null && level.getServer() != null) {
++        lootReplenish: if (lootTable != null && level != null && level.getServer() != null) {
 +            if (this.lootableData() != null && !this.lootableData().shouldReplenish(this, com.destroystokyo.paper.loottable.PaperLootableInventoryData.CONTAINER, player)) {
 +                if (forceClearLootTable) {
 +                    this.setLootTable(null);
@@ -61,27 +61,25 @@
 +                break lootReplenish;
 +            }
 +            // Paper end - LootTable API
-             LootTable lootTable = level.getServer().reloadableRegistries().getLootTable(resourceKey);
+             LootTable lootTable1 = level.getServer().reloadableRegistries().getLootTable(lootTable);
              if (player instanceof ServerPlayer) {
-                 CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)player, resourceKey);
+                 CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)player, lootTable);
              }
  
--            this.setLootTable(null);
-+            // Paper start - LootTable API
-+            if (forceClearLootTable || this.lootableData() == null || this.lootableData().shouldClearLootTable(this, com.destroystokyo.paper.loottable.PaperLootableInventoryData.CONTAINER, player)) {
-+                this.setLootTable(null);
-+            }
-+            // Paper end - LootTable API
++            if (forceClearLootTable || this.lootableData() == null || this.lootableData().shouldClearLootTable(this, com.destroystokyo.paper.loottable.PaperLootableInventoryData.CONTAINER, player)) { // Paper - LootTable API
+             this.setLootTable(null);
++            } // Paper - LootTable API
              LootParams.Builder builder = new LootParams.Builder((ServerLevel)level).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockPos));
              if (player != null) {
                  builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player);
-@@ -97,4 +116,16 @@
-             lootTable.fill(this, builder.create(LootContextParamSets.CHEST), this.getLootTableSeed());
+@@ -97,4 +_,17 @@
+             lootTable1.fill(this, builder.create(LootContextParamSets.CHEST), this.getLootTableSeed());
          }
      }
 +
 +    // Paper start - LootTable API
-+    @Nullable @org.jetbrains.annotations.Contract(pure = true)
++    @Nullable
++    @org.jetbrains.annotations.Contract(pure = true)
 +    default com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData() {
 +        return null; // some containers don't really have a "replenish" ability like decorated pots
 +    }
diff --git a/paper-server/patches/unapplied/net/minecraft/world/SimpleContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/SimpleContainer.java.patch
similarity index 68%
rename from paper-server/patches/unapplied/net/minecraft/world/SimpleContainer.java.patch
rename to paper-server/patches/sources/net/minecraft/world/SimpleContainer.java.patch
index ff3587753c..314fec3e3b 100644
--- a/paper-server/patches/unapplied/net/minecraft/world/SimpleContainer.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/SimpleContainer.java.patch
@@ -1,24 +1,11 @@
 --- a/net/minecraft/world/SimpleContainer.java
 +++ b/net/minecraft/world/SimpleContainer.java
-@@ -14,18 +14,98 @@
- import net.minecraft.world.item.Item;
- import net.minecraft.world.item.ItemStack;
- 
-+// CraftBukkit start
-+import org.bukkit.Location;
-+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
-+import org.bukkit.entity.HumanEntity;
-+// CraftBukkit end
-+
- public class SimpleContainer implements Container, StackedContentsCompatible {
- 
-     private final int size;
-     public final NonNullList<ItemStack> items;
+@@ -19,7 +_,84 @@
      @Nullable
      private List<ContainerListener> listeners;
-+
-+    // CraftBukkit start - add fields and methods
-+    public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
+ 
++    // Paper start - add fields and methods
++    public List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
 +    private int maxStack = MAX_STACK;
 +    protected @Nullable org.bukkit.inventory.InventoryHolder bukkitOwner; // Paper - annotation
 +
@@ -26,15 +13,15 @@
 +        return this.items;
 +    }
 +
-+    public void onOpen(CraftHumanEntity who) {
++    public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
 +        this.transaction.add(who);
 +    }
 +
-+    public void onClose(CraftHumanEntity who) {
++    public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
 +        this.transaction.remove(who);
 +    }
 +
-+    public List<HumanEntity> getViewers() {
++    public List<org.bukkit.entity.HumanEntity> getViewers() {
 +        return this.transaction;
 +    }
 +
@@ -55,9 +42,9 @@
 +        // Paper end - Add missing InventoryHolders
 +        return this.bukkitOwner;
 +    }
- 
++
 +    @Override
-+    public Location getLocation() {
++    public org.bukkit.Location getLocation() {
 +        // Paper start - Fix inventories returning null Locations
 +        // When the block inventory does not have a tile state that implements getLocation, e. g. composters
 +        if (this.bukkitOwner instanceof org.bukkit.inventory.BlockInventoryHolder blockInventoryHolder) {
@@ -77,27 +64,24 @@
 +            this.items.set(slot, original.items.get(slot).copy());
 +        }
 +    }
++    // Paper end
 +
      public SimpleContainer(int size) {
--        this.size = size;
--        this.items = NonNullList.withSize(size, ItemStack.EMPTY);
 +        this(size, null);
 +    }
++
 +    // Paper start - Add missing InventoryHolders
 +    private @Nullable java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> bukkitOwnerCreator;
++
 +    public SimpleContainer(java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> bukkitOwnerCreator, int size) {
 +        this(size);
 +        this.bukkitOwnerCreator = bukkitOwnerCreator;
-     }
-+    // Paper end - Add missing InventoryHolders
- 
-+    public SimpleContainer(int i, org.bukkit.inventory.InventoryHolder owner) {
-+        this.bukkitOwner = owner;
-+        // CraftBukkit end
-+        this.size = i;
-+        this.items = NonNullList.withSize(i, ItemStack.EMPTY);
 +    }
++    // Paper end - Add missing InventoryHolders
 +
-     public SimpleContainer(ItemStack... items) {
-         this.size = items.length;
-         this.items = NonNullList.of(ItemStack.EMPTY, items);
++    public SimpleContainer(int size, org.bukkit.inventory.InventoryHolder owner) {
++        this.bukkitOwner = owner;
++        // Paper end
+         this.size = size;
+         this.items = NonNullList.withSize(size, ItemStack.EMPTY);
+     }
diff --git a/paper-server/patches/sources/net/minecraft/world/entity/animal/frog/Tadpole.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/animal/frog/Tadpole.java.patch
index 215b78b19d..46c558cd76 100644
--- a/paper-server/patches/sources/net/minecraft/world/entity/animal/frog/Tadpole.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/entity/animal/frog/Tadpole.java.patch
@@ -18,17 +18,17 @@
          }
      }
 @@ -122,12 +_,14 @@
-     public void addAdditionalSaveData(CompoundTag compound) {
-         super.addAdditionalSaveData(compound);
-         compound.putInt("Age", this.age);
-+        compound.putBoolean("AgeLocked", this.ageLocked); // Paper
+     public void addAdditionalSaveData(CompoundTag tag) {
+         super.addAdditionalSaveData(tag);
+         tag.putInt("Age", this.age);
++        tag.putBoolean("AgeLocked", this.ageLocked); // Paper
      }
  
      @Override
-     public void readAdditionalSaveData(CompoundTag compound) {
-         super.readAdditionalSaveData(compound);
-         this.setAge(compound.getInt("Age"));
-+        this.ageLocked = compound.getBoolean("AgeLocked"); // Paper
+     public void readAdditionalSaveData(CompoundTag tag) {
+         super.readAdditionalSaveData(tag);
+         this.setAge(tag.getInt("Age"));
++        this.ageLocked = tag.getBoolean("AgeLocked"); // Paper
      }
  
      @Nullable
@@ -67,18 +67,18 @@
      private void ageUp() {
          if (this.level() instanceof ServerLevel serverLevel) {
 -            this.convertTo(EntityType.FROG, ConversionParams.single(this, false, false), mob -> {
-+            Frog converted = this.convertTo(EntityType.FROG, ConversionParams.single(this, false, false), mob -> { // CraftBukkit
++            Frog converted = this.convertTo(EntityType.FROG, ConversionParams.single(this, false, false), mob -> { // Paper
                  mob.finalizeSpawn(serverLevel, this.level().getCurrentDifficultyAt(mob.blockPosition()), EntitySpawnReason.CONVERSION, null);
                  mob.setPersistenceRequired();
                  mob.fudgePositionAfterSizeChange(this.getDimensions(this.getPose()));
                  this.playSound(SoundEvents.TADPOLE_GROW_UP, 0.15F, 1.0F);
 -            });
-+            // CraftBukkit start
++            // Paper start
 +            }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.METAMORPHOSIS);
 +            if (converted == null) {
 +                this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled
 +            }
-+            // CraftBukkit end
++            // Paper end
          }
      }
  
diff --git a/paper-server/patches/unapplied/net/minecraft/world/CompoundContainer.java.patch b/paper-server/patches/unapplied/net/minecraft/world/CompoundContainer.java.patch
deleted file mode 100644
index 1a360b99ad..0000000000
--- a/paper-server/patches/unapplied/net/minecraft/world/CompoundContainer.java.patch
+++ /dev/null
@@ -1,74 +0,0 @@
---- a/net/minecraft/world/CompoundContainer.java
-+++ b/net/minecraft/world/CompoundContainer.java
-@@ -3,11 +3,62 @@
- import net.minecraft.world.entity.player.Player;
- import net.minecraft.world.item.ItemStack;
- 
-+// CraftBukkit start
-+import java.util.ArrayList;
-+import java.util.List;
-+import org.bukkit.Location;
-+
-+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
-+import org.bukkit.entity.HumanEntity;
-+// CraftBukkit end
-+
- public class CompoundContainer implements Container {
- 
-     public final Container container1;
-     public final Container container2;
- 
-+    // CraftBukkit start - add fields and methods
-+    public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
-+
-+    public List<ItemStack> getContents() {
-+        List<ItemStack> result = new ArrayList<ItemStack>(this.getContainerSize());
-+        for (int i = 0; i < this.getContainerSize(); i++) {
-+            result.add(this.getItem(i));
-+        }
-+        return result;
-+    }
-+
-+    public void onOpen(CraftHumanEntity who) {
-+        this.container1.onOpen(who);
-+        this.container2.onOpen(who);
-+        this.transaction.add(who);
-+    }
-+
-+    public void onClose(CraftHumanEntity who) {
-+        this.container1.onClose(who);
-+        this.container2.onClose(who);
-+        this.transaction.remove(who);
-+    }
-+
-+    public List<HumanEntity> getViewers() {
-+        return this.transaction;
-+    }
-+
-+    public org.bukkit.inventory.InventoryHolder getOwner() {
-+        return null; // This method won't be called since CraftInventoryDoubleChest doesn't defer to here
-+    }
-+
-+    public void setMaxStackSize(int size) {
-+        this.container1.setMaxStackSize(size);
-+        this.container2.setMaxStackSize(size);
-+    }
-+
-+    @Override
-+    public Location getLocation() {
-+        return this.container1.getLocation(); // TODO: right?
-+    }
-+    // CraftBukkit end
-+
-     public CompoundContainer(Container first, Container second) {
-         this.container1 = first;
-         this.container2 = second;
-@@ -54,7 +105,7 @@
- 
-     @Override
-     public int getMaxStackSize() {
--        return this.container1.getMaxStackSize();
-+        return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // CraftBukkit - check both sides
-     }
- 
-     @Override
diff --git a/paper-server/patches/unapplied/net/minecraft/world/Container.java.patch b/paper-server/patches/unapplied/net/minecraft/world/Container.java.patch
deleted file mode 100644
index cc552af92d..0000000000
--- a/paper-server/patches/unapplied/net/minecraft/world/Container.java.patch
+++ /dev/null
@@ -1,49 +0,0 @@
---- a/net/minecraft/world/Container.java
-+++ b/net/minecraft/world/Container.java
-@@ -6,8 +6,12 @@
- import net.minecraft.world.entity.player.Player;
- import net.minecraft.world.item.Item;
- import net.minecraft.world.item.ItemStack;
-+// CraftBukkit start
-+import net.minecraft.world.item.crafting.RecipeHolder;
- import net.minecraft.world.level.Level;
- import net.minecraft.world.level.block.entity.BlockEntity;
-+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
-+// CraftBukkit end
- 
- public interface Container extends Clearable {
- 
-@@ -25,9 +29,7 @@
- 
-     void setItem(int slot, ItemStack stack);
- 
--    default int getMaxStackSize() {
--        return 99;
--    }
-+    int getMaxStackSize(); // CraftBukkit
- 
-     default int getMaxStackSize(ItemStack stack) {
-         return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
-@@ -91,4 +93,22 @@
- 
-         return world == null ? false : (world.getBlockEntity(blockposition) != blockEntity ? false : player.canInteractWithBlock(blockposition, (double) range));
-     }
-+
-+    // CraftBukkit start
-+    java.util.List<ItemStack> getContents();
-+
-+    void onOpen(CraftHumanEntity who);
-+
-+    void onClose(CraftHumanEntity who);
-+
-+    java.util.List<org.bukkit.entity.HumanEntity> getViewers();
-+
-+    org.bukkit.inventory.@org.jetbrains.annotations.Nullable InventoryHolder getOwner(); // Paper - annotation
-+
-+    void setMaxStackSize(int size);
-+
-+    org.bukkit.Location getLocation();
-+
-+    int MAX_STACK = 99;
-+    // CraftBukkit end
- }