diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/AbstractContainerMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/AbstractContainerMenu.java.patch new file mode 100644 index 0000000000..e1f470371c --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/AbstractContainerMenu.java.patch @@ -0,0 +1,281 @@ +--- a/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -19,6 +_,8 @@ + import net.minecraft.ReportedException; + import net.minecraft.core.NonNullList; + import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.Container; +@@ -63,6 +_,31 @@ + @Nullable + private ContainerSynchronizer synchronizer; + private boolean suppressRemoteUpdates; ++ // CraftBukkit start ++ public boolean checkReachable = true; ++ public abstract org.bukkit.inventory.InventoryView getBukkitView(); ++ public void transferTo(AbstractContainerMenu other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) { ++ org.bukkit.inventory.InventoryView source = this.getBukkitView(), destination = other.getBukkitView(); ++ ((org.bukkit.craftbukkit.inventory.CraftInventory) source.getTopInventory()).getInventory().onClose(player); ++ ((org.bukkit.craftbukkit.inventory.CraftInventory) source.getBottomInventory()).getInventory().onClose(player); ++ ((org.bukkit.craftbukkit.inventory.CraftInventory) destination.getTopInventory()).getInventory().onOpen(player); ++ ((org.bukkit.craftbukkit.inventory.CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player); ++ } ++ private Component title; ++ public final Component getTitle() { ++ // Paper start - return chat component with empty text instead of throwing error ++ // Preconditions.checkState(this.title != null, "Title not set"); ++ if (this.title == null){ ++ return Component.literal(""); ++ } ++ // Paper end - return chat component with empty text instead of throwing error ++ return this.title; ++ } ++ public final void setTitle(Component title) { ++ com.google.common.base.Preconditions.checkState(this.title == null, "Title already set"); ++ this.title = title; ++ } ++ // CraftBukkit end + + protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { + this.menuType = menuType; +@@ -168,8 +_,18 @@ + + if (this.synchronizer != null) { + this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray()); +- } +- } ++ this.synchronizer.sendOffHandSlotChange(); // Paper - Sync offhand slot in menus; update player's offhand since the offhand slot is not added to the slots for menus but can be changed by swapping from a menu slot ++ } ++ } ++ ++ // CraftBukkit start ++ public void broadcastCarriedItem() { ++ this.remoteCarried = this.getCarried().copy(); ++ if (this.synchronizer != null) { ++ this.synchronizer.sendCarriedChange(this, this.remoteCarried); ++ } ++ } ++ // CraftBukkit end + + public void removeSlotListener(ContainerListener listener) { + this.containerListeners.remove(listener); +@@ -235,7 +_,7 @@ + this.lastSlots.set(slotIndex, itemStack1); + + for (ContainerListener containerListener : this.containerListeners) { +- containerListener.slotChanged(this, slotIndex, itemStack1); ++ containerListener.slotChanged(this, slotIndex, itemStack, itemStack1); // Paper - Add PlayerInventorySlotChangeEvent + } + } + } +@@ -343,6 +_,7 @@ + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { ++ if (slotId < 0) return; // Paper - Add slot sanity checks to container clicks + Slot slot = this.slots.get(slotId); + ItemStack carried = this.getCarried(); + if (canItemQuickReplace(slot, carried, true) +@@ -367,6 +_,7 @@ + } + + int count = this.getCarried().getCount(); ++ java.util.Map draggedSlots = new java.util.HashMap<>(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack) + + for (Slot slot1 : this.quickcraftSlots) { + ItemStack carried1 = this.getCarried(); +@@ -379,12 +_,48 @@ + int min = Math.min(itemStack.getMaxStackSize(), slot1.getMaxStackSize(itemStack)); + int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min); + count -= min1 - i2; +- slot1.setByPlayer(itemStack.copyWithCount(min1)); +- } +- } +- +- itemStack.setCount(count); +- this.setCarried(itemStack); ++ // slot1.setByPlayer(itemStack.copyWithCount(min1)); ++ draggedSlots.put(slot1.index, itemStack.copyWithCount(min1)); // CraftBukkit - Put in map instead of setting ++ } ++ } ++ ++ // CraftBukkit start - InventoryDragEvent ++ org.bukkit.inventory.InventoryView view = this.getBukkitView(); ++ org.bukkit.inventory.ItemStack newcursor = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack); ++ newcursor.setAmount(count); ++ java.util.Map eventmap = new java.util.HashMap(); ++ for (java.util.Map.Entry ditem : draggedSlots.entrySet()) { ++ eventmap.put(ditem.getKey(), org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(ditem.getValue())); ++ } ++ ++ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory. ++ ItemStack oldCursor = this.getCarried(); ++ this.setCarried(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(newcursor)); ++ ++ org.bukkit.event.inventory.InventoryDragEvent event = new org.bukkit.event.inventory.InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); ++ player.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ // Whether or not a change was made to the inventory that requires an update. ++ boolean needsUpdate = event.getResult() != org.bukkit.event.Event.Result.DEFAULT; ++ ++ if (event.getResult() != org.bukkit.event.Event.Result.DENY) { ++ for (java.util.Map.Entry dslot : draggedSlots.entrySet()) { ++ view.setItem(dslot.getKey(), org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(dslot.getValue())); ++ } ++ // The only time the carried item will be set to null is if the inventory is closed by the server. ++ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early. ++ if (this.getCarried() != null) { ++ this.setCarried(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getCursor())); ++ needsUpdate = true; ++ } ++ } else { ++ this.setCarried(oldCursor); ++ } ++ ++ if (needsUpdate && player instanceof ServerPlayer) { ++ this.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + + this.resetQuickCraft(); +@@ -398,8 +_,11 @@ + if (slotId == -999) { + if (!this.getCarried().isEmpty()) { + if (clickAction == ClickAction.PRIMARY) { +- player.drop(this.getCarried(), true); +- this.setCarried(ItemStack.EMPTY); ++ // CraftBukkit start ++ ItemStack carried = this.getCarried(); ++ this.setCarried(ItemStack.EMPTY); ++ player.drop(carried, true); ++ // CraftBukkit start + } else { + player.drop(this.getCarried().split(1), true); + } +@@ -461,8 +_,18 @@ + } + + slot.setChanged(); ++ // CraftBukkit start - Make sure the client has the right slot contents ++ if (player instanceof ServerPlayer && slot.getMaxStackSize() != 64) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot.index, slot.getItem())); ++ // Updating a crafting inventory makes the client reset the result slot, have to send it again ++ if (this.getBukkitView().getType() == org.bukkit.event.inventory.InventoryType.WORKBENCH || this.getBukkitView().getType() == org.bukkit.event.inventory.InventoryType.CRAFTING) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); ++ } ++ } ++ // CraftBukkit end + } + } else if (clickType == ClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { ++ if (slotId < 0) return; // Paper - Add slot sanity checks to container clicks + ItemStack item = inventory.getItem(button); + Slot slot = this.slots.get(slotId); + ItemStack carried = slot.getItem(); +@@ -582,8 +_,9 @@ + if (player instanceof ServerPlayer) { + ItemStack carried = this.getCarried(); + if (!carried.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); // CraftBukkit - SPIGOT-4556 - from below + dropOrPlaceInInventory(player, carried); +- this.setCarried(ItemStack.EMPTY); ++ // this.setCarried(ItemStack.EMPTY); // CraftBukkit - moved up + } + } + } +@@ -629,6 +_,14 @@ + public abstract boolean stillValid(Player player); + + protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection) { ++ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent ++ return this.moveItemStackTo(stack, startIndex, endIndex, reverseDirection, false); ++ } ++ protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection, boolean isCheck) { ++ if (isCheck) { ++ stack = stack.copy(); ++ } ++ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent + boolean flag = false; + int i = startIndex; + if (reverseDirection) { +@@ -639,18 +_,27 @@ + while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) { + Slot slot = this.slots.get(i); + ItemStack item = slot.getItem(); ++ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent; clone if only a check ++ if (isCheck) { ++ item = item.copy(); ++ } ++ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent + if (!item.isEmpty() && ItemStack.isSameItemSameComponents(stack, item)) { + int i1 = item.getCount() + stack.getCount(); + int maxStackSize = slot.getMaxStackSize(item); + if (i1 <= maxStackSize) { + stack.setCount(0); + item.setCount(i1); ++ if (!isCheck) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent + slot.setChanged(); ++ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent + flag = true; + } else if (item.getCount() < maxStackSize) { + stack.shrink(maxStackSize - item.getCount()); + item.setCount(maxStackSize); ++ if (!isCheck) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent + slot.setChanged(); ++ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent + flag = true; + } + } +@@ -673,10 +_,21 @@ + while (reverseDirection ? i >= startIndex : i < endIndex) { + Slot slotx = this.slots.get(i); + ItemStack itemx = slotx.getItem(); ++ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent ++ if (isCheck) { ++ itemx = itemx.copy(); ++ } ++ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent + if (itemx.isEmpty() && slotx.mayPlace(stack)) { + int i1 = slotx.getMaxStackSize(stack); ++ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent ++ if (isCheck) { ++ stack.shrink(Math.min(stack.getCount(), i1)); ++ } else { ++ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent + slotx.setByPlayer(stack.split(Math.min(stack.getCount(), i1))); + slotx.setChanged(); ++ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent + flag = true; + break; + } +@@ -760,6 +_,11 @@ + } + + public ItemStack getCarried() { ++ // CraftBukkit start ++ if (this.carried.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); ++ } ++ // CraftBukkit end + return this.carried; + } + +@@ -808,4 +_,15 @@ + this.stateId = this.stateId + 1 & 32767; + return this.stateId; + } ++ ++ // Paper start - Add missing InventoryHolders ++ // The reason this is a supplier, is that the createHolder method uses the bukkit InventoryView#getTopInventory to get the inventory in question ++ // and that can't be obtained safely until the AbstractContainerMenu has been fully constructed. Using a supplier lazily ++ // initializes the InventoryHolder safely. ++ protected final Supplier createBlockHolder(final ContainerLevelAccess context) { ++ //noinspection ConstantValue ++ com.google.common.base.Preconditions.checkArgument(context != null, "context was null"); ++ return () -> context.createBlockHolder(this); ++ } ++ // Paper end - Add missing InventoryHolders + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/AbstractCraftingMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/AbstractCraftingMenu.java.patch new file mode 100644 index 0000000000..5e22ef73ce --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/AbstractCraftingMenu.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/inventory/AbstractCraftingMenu.java ++++ b/net/minecraft/world/inventory/AbstractCraftingMenu.java +@@ -12,14 +_,17 @@ + public abstract class AbstractCraftingMenu extends RecipeBookMenu { + private final int width; + private final int height; +- public final CraftingContainer craftSlots; ++ public final TransientCraftingContainer craftSlots; // CraftBukkit + public final ResultContainer resultSlots = new ResultContainer(); + +- public AbstractCraftingMenu(MenuType menuType, int containerId, int width, int height) { ++ public AbstractCraftingMenu(MenuType menuType, int containerId, int width, int height, Inventory playerInventory) { // CraftBukkit + super(menuType, containerId); + this.width = width; + this.height = height; +- this.craftSlots = new TransientCraftingContainer(this, width, height); ++ // CraftBukkit start ++ this.craftSlots = new TransientCraftingContainer(this, width, height, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; // CraftBukkit - let InventoryCrafting know about its result slot ++ // CraftBukkit end + } + + protected Slot addResultSlot(Player player, int x, int y) { +@@ -35,13 +_,13 @@ + } + + @Override +- public RecipeBookMenu.PostPlaceAction handlePlacement( ++ public PostPlaceAction handlePlacement( + boolean useMaxItems, boolean isCreative, RecipeHolder recipe, ServerLevel level, Inventory playerInventory + ) { + RecipeHolder recipeHolder = (RecipeHolder)recipe; + this.beginPlacingRecipe(); + +- RecipeBookMenu.PostPlaceAction var8; ++ PostPlaceAction var8; + try { + List inputGridSlots = this.getInputGridSlots(); + var8 = ServerPlaceRecipe.placeRecipe(new ServerPlaceRecipe.CraftingMenuAccess() { diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch new file mode 100644 index 0000000000..17fc9ef5af --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java ++++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java +@@ -34,6 +_,21 @@ + private final RecipeType recipeType; + private final RecipePropertySet acceptedInputs; + private final RecipeBookType recipeBookType; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftFurnaceView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftFurnaceView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryFurnace inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryFurnace((net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity) this.container); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftFurnaceView(this.player.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + protected AbstractFurnaceMenu( + MenuType menuType, +@@ -68,6 +_,7 @@ + this.addSlot(new Slot(container, 0, 56, 17)); + this.addSlot(new FurnaceFuelSlot(this, container, 1, 56, 53)); + this.addSlot(new FurnaceResultSlot(inventory.player, container, 2, 116, 35)); ++ this.player = inventory; // CraftBukkit - save player + this.addStandardInventorySlots(inventory, 8, 84); + this.addDataSlots(data); + } +@@ -85,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + +@@ -170,7 +_,7 @@ + } + + @Override +- public RecipeBookMenu.PostPlaceAction handlePlacement( ++ public PostPlaceAction handlePlacement( + boolean useMaxItems, boolean isCreative, RecipeHolder recipe, final ServerLevel level, Inventory playerInventory + ) { + final List list = List.of(this.getSlot(0), this.getSlot(2)); diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/AnvilMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/AnvilMenu.java.patch similarity index 63% rename from paper-server/patches/unapplied/net/minecraft/world/inventory/AnvilMenu.java.patch rename to paper-server/patches/sources/net/minecraft/world/inventory/AnvilMenu.java.patch index 1c6f48d25b..a1143aed14 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/AnvilMenu.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/inventory/AnvilMenu.java.patch @@ -1,68 +1,55 @@ --- a/net/minecraft/world/inventory/AnvilMenu.java +++ b/net/minecraft/world/inventory/AnvilMenu.java -@@ -21,6 +21,10 @@ - import net.minecraft.world.level.block.state.BlockState; - import org.slf4j.Logger; - -+// CraftBukkit start -+import org.bukkit.craftbukkit.inventory.view.CraftAnvilView; -+// CraftBukkit end -+ - public class AnvilMenu extends ItemCombinerMenu { - - public static final int INPUT_SLOT = 0; -@@ -45,6 +49,12 @@ +@@ -43,6 +_,12 @@ private static final int ADDITIONAL_SLOT_X_PLACEMENT = 76; private static final int RESULT_SLOT_X_PLACEMENT = 134; private static final int SLOT_Y_PLACEMENT = 47; + // CraftBukkit start + public static final int DEFAULT_DENIED_COST = -1; + public int maximumRepairCost = 40; -+ private CraftAnvilView bukkitEntity; ++ private org.bukkit.craftbukkit.inventory.view.CraftAnvilView bukkitEntity; + // CraftBukkit end + public boolean bypassEnchantmentLevelRestriction = false; // Paper - bypass anvil level restrictions - public AnvilMenu(int syncId, Inventory inventory) { - this(syncId, inventory, ContainerLevelAccess.NULL); -@@ -72,7 +82,7 @@ + public AnvilMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -68,7 +_,7 @@ @Override - protected boolean mayPickup(Player player, boolean present) { + protected boolean mayPickup(Player player, boolean hasStack) { - return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && this.cost.get() > 0; -+ return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && present; // CraftBukkit - allow cost 0 like a free item ++ return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && hasStack; // CraftBukkit - allow cost 0 like a free item } @Override -@@ -94,7 +104,7 @@ +@@ -89,12 +_,22 @@ this.inputSlots.setItem(1, ItemStack.EMPTY); } - this.cost.set(0); + this.cost.set(AnvilMenu.DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item this.inputSlots.setItem(0, ItemStack.EMPTY); - this.access.execute((world, blockposition) -> { - BlockState iblockdata = world.getBlockState(blockposition); -@@ -102,6 +112,16 @@ - if (!player.hasInfiniteMaterials() && iblockdata.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { - BlockState iblockdata1 = AnvilBlock.damage(iblockdata); - + this.access.execute((level, blockPos) -> { + BlockState blockState = level.getBlockState(blockPos); + if (!player.hasInfiniteMaterials() && blockState.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { + BlockState blockState1 = AnvilBlock.damage(blockState); + // Paper start - AnvilDamageEvent -+ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); ++ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), blockState1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(blockState1) : null); + if (!event.callEvent()) { + return; + } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { -+ iblockdata1 = null; ++ blockState1 = null; + } else { -+ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().setValue(AnvilBlock.FACING, iblockdata.getValue(AnvilBlock.FACING)); ++ blockState1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().setValue(AnvilBlock.FACING, blockState.getValue(AnvilBlock.FACING)); + } + // Paper end - AnvilDamageEvent - if (iblockdata1 == null) { - world.removeBlock(blockposition, false); - world.levelEvent(1029, blockposition, 0); -@@ -143,8 +163,8 @@ - if (itemstack1.isDamageableItem() && itemstack.isValidRepairItem(itemstack2)) { - k = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); - if (k <= 0) { + if (blockState1 == null) { + level.removeBlock(blockPos, false); + level.levelEvent(1029, blockPos, 0); +@@ -128,8 +_,8 @@ + if (itemStack.isDamageableItem() && item.isValidRepairItem(item1)) { + int min = Math.min(itemStack.getDamageValue(), itemStack.getMaxDamage() / 4); + if (min <= 0) { - this.resultSlots.setItem(0, ItemStack.EMPTY); - this.cost.set(0); + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), ItemStack.EMPTY); // CraftBukkit @@ -70,10 +57,10 @@ return; } -@@ -158,8 +178,8 @@ - this.repairItemCountCost = i1; +@@ -144,8 +_,8 @@ + this.repairItemCountCost = i2; } else { - if (!flag && (!itemstack1.is(itemstack2.getItem()) || !itemstack1.isDamageableItem())) { + if (!hasStoredEnchantments && (!itemStack.is(item1.getItem()) || !itemStack.isDamageableItem())) { - this.resultSlots.setItem(0, ItemStack.EMPTY); - this.cost.set(0); + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), ItemStack.EMPTY); // CraftBukkit @@ -81,19 +68,19 @@ return; } -@@ -214,7 +234,7 @@ - flag2 = true; - } else { +@@ -191,7 +_,7 @@ flag1 = true; -- if (i2 > enchantment.getMaxLevel()) { -+ if (i2 > enchantment.getMaxLevel() && !this.bypassEnchantmentLevelRestriction) { // Paper - bypass anvil level restrictions - i2 = enchantment.getMaxLevel(); + } else { + flag = true; +- if (intValue > enchantment.getMaxLevel()) { ++ if (intValue > enchantment.getMaxLevel() && !this.bypassEnchantmentLevelRestriction) { // Paper - bypass anvil level restrictions + intValue = enchantment.getMaxLevel(); } -@@ -233,8 +253,8 @@ +@@ -209,8 +_,8 @@ } - if (flag2 && !flag1) { + if (flag1 && !flag) { - this.resultSlots.setItem(0, ItemStack.EMPTY); - this.cost.set(0); + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), ItemStack.EMPTY); // CraftBukkit @@ -101,14 +88,16 @@ return; } } -@@ -260,14 +280,14 @@ +@@ -235,14 +_,16 @@ } - if (b0 == i && b0 > 0) { + if (i1 == i && i1 > 0) { - if (this.cost.get() >= 40) { - this.cost.set(39); -+ if (this.cost.get() >= this.maximumRepairCost) { // CraftBukkit -+ this.cost.set(this.maximumRepairCost - 1); // CraftBukkit ++ // CraftBukkit start ++ if (this.cost.get() >= this.maximumRepairCost) { ++ this.cost.set(this.maximumRepairCost - 1); ++ // CraftBukkit end } this.onlyRenaming = true; @@ -116,15 +105,15 @@ - if (this.cost.get() >= 40 && !this.player.getAbilities().instabuild) { + if (this.cost.get() >= this.maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit - itemstack1 = ItemStack.EMPTY; + itemStack = ItemStack.EMPTY; } -@@ -285,12 +305,13 @@ - EnchantmentHelper.setEnchantments(itemstack1, itemenchantments_a.toImmutable()); +@@ -260,12 +_,13 @@ + EnchantmentHelper.setEnchantments(itemStack, mutable.toImmutable()); } -- this.resultSlots.setItem(0, itemstack1); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemstack1); // CraftBukkit +- this.resultSlots.setItem(0, itemStack); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemStack); // CraftBukkit this.broadcastChanges(); } else { - this.resultSlots.setItem(0, ItemStack.EMPTY); @@ -135,8 +124,8 @@ + this.sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686, SPIGOT-7931: Always send completed inventory to stay in sync with client } - public static int calculateIncreasedRepairCost(int cost) { -@@ -313,6 +334,7 @@ + public static int calculateIncreasedRepairCost(int oldRepairCost) { +@@ -286,6 +_,7 @@ } this.createResult(); @@ -144,21 +133,21 @@ return true; } else { return false; -@@ -329,4 +351,19 @@ +@@ -301,4 +_,19 @@ public int getCost() { return this.cost.get(); } + + // CraftBukkit start + @Override -+ public CraftAnvilView getBukkitView() { ++ public org.bukkit.craftbukkit.inventory.view.CraftAnvilView getBukkitView() { + if (this.bukkitEntity != null) { + return this.bukkitEntity; + } + + org.bukkit.craftbukkit.inventory.CraftInventoryAnvil inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryAnvil( + this.access.getLocation(), this.inputSlots, this.resultSlots); -+ this.bukkitEntity = new CraftAnvilView(this.player.getBukkitEntity(), inventory, this); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftAnvilView(this.player.getBukkitEntity(), inventory, this); + this.bukkitEntity.updateFromLegacy(inventory); + return this.bukkitEntity; + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/BeaconMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/BeaconMenu.java.patch new file mode 100644 index 0000000000..48cbfd3a8e --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/BeaconMenu.java.patch @@ -0,0 +1,121 @@ +--- a/net/minecraft/world/inventory/BeaconMenu.java ++++ b/net/minecraft/world/inventory/BeaconMenu.java +@@ -22,20 +_,14 @@ + private static final int USE_ROW_SLOT_START = 28; + private static final int USE_ROW_SLOT_END = 37; + private static final int NO_EFFECT = 0; +- private final Container beacon = new SimpleContainer(1) { +- @Override +- public boolean canPlaceItem(int slot, ItemStack stack) { +- return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); +- } +- +- @Override +- public int getMaxStackSize() { +- return 1; +- } +- }; +- private final BeaconMenu.PaymentSlot paymentSlot; ++ private final Container beacon; // Paper - Add missing InventoryHolders Move down ++ private final PaymentSlot paymentSlot; + private final ContainerLevelAccess access; + private final ContainerData beaconData; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftBeaconView bukkitEntity = null; ++ private net.minecraft.world.entity.player.Inventory player; ++ // CraftBukkit end + + public BeaconMenu(int containerId, Container container) { + this(containerId, container, new SimpleContainerData(3), ContainerLevelAccess.NULL); +@@ -43,10 +_,31 @@ + + public BeaconMenu(int containerId, Container container, ContainerData beaconData, ContainerLevelAccess access) { + super(MenuType.BEACON, containerId); ++ this.player = (net.minecraft.world.entity.player.Inventory) container; // CraftBukkit - TODO: check this ++ // Paper - Add missing InventoryHolders ++ this.beacon = new SimpleContainer(this.createBlockHolder(access), 1) { ++ @Override ++ public boolean canPlaceItem(int slot, ItemStack stack) { ++ return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return 1; ++ } ++ ++ // Paper start - Fix inventories returning null Locations ++ @Override ++ public org.bukkit.Location getLocation() { ++ return access.getLocation(); ++ } ++ // Paper end - Fix inventories returning null Locations ++ }; ++ // Paper end + checkContainerDataCount(beaconData, 3); + this.beaconData = beaconData; + this.access = access; +- this.paymentSlot = new BeaconMenu.PaymentSlot(this.beacon, 0, 136, 110); ++ this.paymentSlot = new PaymentSlot(this.beacon, 0, 136, 110); + this.addSlot(this.paymentSlot); + this.addDataSlots(beaconData); + this.addStandardInventorySlots(container, 36, 137); +@@ -65,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.BEACON); + } + +@@ -141,13 +_,30 @@ + public Holder getSecondaryEffect() { + return decodeEffect(this.beaconData.get(2)); + } ++ // Paper start - Add PlayerChangeBeaconEffectEvent ++ private static @Nullable org.bukkit.potion.PotionEffectType convert(Optional> optionalEffect) { ++ return optionalEffect.map(org.bukkit.craftbukkit.potion.CraftPotionEffectType::minecraftHolderToBukkit).orElse(null); ++ } ++ // Paper end - Add PlayerChangeBeaconEffectEvent + + public void updateEffects(Optional> primaryEffect, Optional> secondaryEffect) { ++ // Paper start - fix MC-174630 - validate secondary power ++ if (secondaryEffect.isPresent() && secondaryEffect.get() != net.minecraft.world.effect.MobEffects.REGENERATION && (primaryEffect.isPresent() && secondaryEffect.get() != primaryEffect.get())) { ++ secondaryEffect = Optional.empty(); ++ } ++ // Paper end + if (this.paymentSlot.hasItem()) { +- this.beaconData.set(1, encodeEffect(primaryEffect.orElse(null))); +- this.beaconData.set(2, encodeEffect(secondaryEffect.orElse(null))); ++ // Paper start - Add PlayerChangeBeaconEffectEvent ++ io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent event = new io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), convert(primaryEffect), convert(secondaryEffect), this.access.getLocation().getBlock()); ++ if (event.callEvent()) { ++ // Paper end - Add PlayerChangeBeaconEffectEvent ++ this.beaconData.set(1, BeaconMenu.encodeEffect(event.getPrimary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getPrimary())));// CraftBukkit - decompile error ++ this.beaconData.set(2, BeaconMenu.encodeEffect(event.getSecondary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getSecondary())));// CraftBukkit - decompile error ++ if (event.willConsumeItem()) { // Paper + this.paymentSlot.remove(1); ++ } // Paper + this.access.execute(Level::blockEntityChanged); ++ } // Paper end - Add PlayerChangeBeaconEffectEvent + } + } + +@@ -170,4 +_,17 @@ + return 1; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftBeaconView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryBeacon inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftBeaconView(this.player.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/BrewingStandMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/BrewingStandMenu.java.patch new file mode 100644 index 0000000000..f7754c7cbf --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/BrewingStandMenu.java.patch @@ -0,0 +1,139 @@ +--- a/net/minecraft/world/inventory/BrewingStandMenu.java ++++ b/net/minecraft/world/inventory/BrewingStandMenu.java +@@ -1,6 +_,5 @@ + package net.minecraft.world.inventory; + +-import java.util.Optional; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.Holder; + import net.minecraft.core.component.DataComponents; +@@ -16,6 +_,7 @@ + import net.minecraft.world.item.alchemy.Potion; + import net.minecraft.world.item.alchemy.PotionBrewing; + import net.minecraft.world.item.alchemy.PotionContents; ++import java.util.Optional; + + public class BrewingStandMenu extends AbstractContainerMenu { + static final ResourceLocation EMPTY_SLOT_FUEL = ResourceLocation.withDefaultNamespace("container/slot/brewing_fuel"); +@@ -33,29 +_,50 @@ + private final Container brewingStand; + public final ContainerData brewingStandData; + private final Slot ingredientSlot; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftBrewingStandView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public BrewingStandMenu(int containerId, Inventory playerInventory) { +- this(containerId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2)); ++ this(containerId, playerInventory, new SimpleContainer(5), new io.papermc.paper.inventory.BrewingSimpleContainerData()); // Paper - Add totalBrewTime + } + + public BrewingStandMenu(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData) { + super(MenuType.BREWING_STAND, containerId); ++ this.player = playerInventory; // CraftBukkit + checkContainerSize(brewingStandContainer, 5); + checkContainerDataCount(brewingStandData, 2); + this.brewingStand = brewingStandContainer; + this.brewingStandData = brewingStandData; + PotionBrewing potionBrewing = playerInventory.player.level().potionBrewing(); +- this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 0, 56, 51)); +- this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 1, 79, 58)); +- this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 2, 102, 51)); +- this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(potionBrewing, brewingStandContainer, 3, 79, 17)); +- this.addSlot(new BrewingStandMenu.FuelSlot(brewingStandContainer, 4, 17, 17)); +- this.addDataSlots(brewingStandData); ++ // Paper start - custom potion mixes ++ this.addSlot(new PotionSlot(brewingStandContainer, 0, 56, 51, potionBrewing)); ++ this.addSlot(new PotionSlot(brewingStandContainer, 1, 79, 58, potionBrewing)); ++ this.addSlot(new PotionSlot(brewingStandContainer, 2, 102, 51, potionBrewing)); ++ // Paper end - custom potion mixes ++ this.ingredientSlot = this.addSlot(new IngredientsSlot(potionBrewing, brewingStandContainer, 3, 79, 17)); ++ this.addSlot(new FuelSlot(brewingStandContainer, 4, 17, 17)); ++ // Paper start - Add recipeBrewTime ++ this.addDataSlots(new SimpleContainerData(2) { ++ @Override ++ public int get(final int index) { ++ if (index == 0) return 400 * brewingStandData.get(index) / brewingStandData.get(2); ++ return brewingStandData.get(index); ++ } ++ ++ @Override ++ public void set(final int index, final int value) { ++ brewingStandData.set(index, value); ++ } ++ }); ++ // Paper end - Add recipeBrewTime + this.addStandardInventorySlots(playerInventory, 8, 84); + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.brewingStand.stillValid(player); + } + +@@ -67,7 +_,7 @@ + ItemStack item = slot.getItem(); + itemStack = item.copy(); + if ((index < 0 || index > 2) && index != 3 && index != 4) { +- if (BrewingStandMenu.FuelSlot.mayPlaceItem(itemStack)) { ++ if (FuelSlot.mayPlaceItem(itemStack)) { + if (this.moveItemStackTo(item, 4, 5, false) || this.ingredientSlot.mayPlace(item) && !this.moveItemStackTo(item, 3, 4, false)) { + return ItemStack.EMPTY; + } +@@ -75,7 +_,7 @@ + if (!this.moveItemStackTo(item, 3, 4, false)) { + return ItemStack.EMPTY; + } +- } else if (BrewingStandMenu.PotionSlot.mayPlaceItem(itemStack)) { ++ } else if (PotionSlot.mayPlaceItem(itemStack, this.player.player.level().potionBrewing())) { // Paper - custom potion mixes + if (!this.moveItemStackTo(item, 0, 3, false)) { + return ItemStack.EMPTY; + } +@@ -157,13 +_,15 @@ + } + + static class PotionSlot extends Slot { +- public PotionSlot(Container container, int slot, int x, int y) { ++ private final PotionBrewing potionBrewing; // Paper - custom potion mixes ++ public PotionSlot(Container container, int slot, int x, int y, PotionBrewing potionBrewing) { // Paper - custom potion mixes + super(container, slot, x, y); ++ this.potionBrewing = potionBrewing; // Paper - custom potion mixes + } + + @Override + public boolean mayPlace(ItemStack stack) { +- return mayPlaceItem(stack); ++ return mayPlaceItem(stack, this.potionBrewing); // Paper - custom potion mixes + } + + @Override +@@ -181,8 +_,8 @@ + super.onTake(player, stack); + } + +- public static boolean mayPlaceItem(ItemStack stack) { +- return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE); ++ public static boolean mayPlaceItem(ItemStack stack, PotionBrewing potionBrewing) { // Paper - custom potion mixes ++ return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || potionBrewing.isCustomInput(stack); // Paper - Custom Potion Mixes + } + + @Override +@@ -190,4 +_,16 @@ + return BrewingStandMenu.EMPTY_SLOT_POTION; + } + } ++ // CraftBukkit start ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftBrewingStandView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryBrewer inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBrewer(this.brewingStand); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftBrewingStandView(this.player.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/CartographyTableMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/CartographyTableMenu.java.patch new file mode 100644 index 0000000000..854683fadb --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/CartographyTableMenu.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -15,6 +_,21 @@ + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + + public class CartographyTableMenu extends AbstractContainerMenu { ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity = null; ++ private org.bukkit.entity.Player player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryCartography inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryCartography(this.container, this.resultContainer); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player, inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAP_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; + public static final int RESULT_SLOT = 2; +@@ -24,20 +_,8 @@ + private static final int USE_ROW_SLOT_END = 39; + private final ContainerLevelAccess access; + long lastSoundTime; +- public final Container container = new SimpleContainer(2) { +- @Override +- public void setChanged() { +- CartographyTableMenu.this.slotsChanged(this); +- super.setChanged(); +- } +- }; +- private final ResultContainer resultContainer = new ResultContainer() { +- @Override +- public void setChanged() { +- CartographyTableMenu.this.slotsChanged(this); +- super.setChanged(); +- } +- }; ++ public final Container container; // Paper - Add missing InventoryHolders - move down ++ private final ResultContainer resultContainer; // Paper - Add missing InventoryHolders - move down + + public CartographyTableMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -45,6 +_,34 @@ + + public CartographyTableMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.CARTOGRAPHY_TABLE, containerId); ++ // Paper Start - Add missing InventoryHolders - move down ++ this.container = new SimpleContainer(this.createBlockHolder(access), 2) { // Paper - Add missing InventoryHolders ++ @Override ++ public void setChanged() { ++ CartographyTableMenu.this.slotsChanged(this); ++ super.setChanged(); ++ } ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.resultContainer = new ResultContainer(this.createBlockHolder(access)) { // Paper - Add missing InventoryHolders ++ @Override ++ public void setChanged() { ++ CartographyTableMenu.this.slotsChanged(this); ++ super.setChanged(); ++ } ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ // Paper Start - Add missing InventoryHolders - move down + this.access = access; + this.addSlot(new Slot(this.container, 0, 15, 15) { + @Override +@@ -80,10 +_,12 @@ + } + }); + this.addStandardInventorySlots(playerInventory, 8, 84); ++ this.player = (org.bukkit.entity.Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CARTOGRAPHY_TABLE); + } + +@@ -99,6 +_,7 @@ + } else { + this.resultContainer.removeItemNoUpdate(2); + } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent + } + + private void setupResultSlot(ItemStack map, ItemStack firstSlotStack, ItemStack resultOutput) { diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/ChestMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ChestMenu.java.patch new file mode 100644 index 0000000000..c86ead27cc --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ChestMenu.java.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/inventory/ChestMenu.java ++++ b/net/minecraft/world/inventory/ChestMenu.java +@@ -9,6 +_,29 @@ + public class ChestMenu extends AbstractContainerMenu { + private final Container container; + private final int containerRows; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory; ++ if (this.container instanceof Inventory) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryPlayer((Inventory) this.container); ++ } else if (this.container instanceof net.minecraft.world.CompoundContainer) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((net.minecraft.world.CompoundContainer) this.container); ++ } else { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventory(this.container); ++ } ++ ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + private ChestMenu(MenuType type, int containerId, Inventory playerInventory, int rows) { + this(type, containerId, playerInventory, new SimpleContainer(9 * rows), rows); +@@ -52,6 +_,9 @@ + this.container = container; + this.containerRows = rows; + container.startOpen(playerInventory.player); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end + int i = 18; + this.addChestGrid(container, 8, 18); + int i1 = 18 + this.containerRows * 18 + 13; +@@ -68,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerLevelAccess.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerLevelAccess.java.patch similarity index 83% rename from paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerLevelAccess.java.patch rename to paper-server/patches/sources/net/minecraft/world/inventory/ContainerLevelAccess.java.patch index 3202223f24..273a80aee1 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerLevelAccess.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerLevelAccess.java.patch @@ -1,9 +1,46 @@ --- a/net/minecraft/world/inventory/ContainerLevelAccess.java +++ b/net/minecraft/world/inventory/ContainerLevelAccess.java -@@ -8,16 +8,66 @@ +@@ -12,6 +_,12 @@ + public Optional evaluate(BiFunction levelPosConsumer) { + return Optional.empty(); + } ++ // Paper start - fix menus with empty level accesses ++ @Override ++ public org.bukkit.Location getLocation() { ++ return null; ++ } ++ // Paper end - fix menus with empty level accesses + }; - public interface ContainerLevelAccess { + static ContainerLevelAccess create(final Level level, final BlockPos pos) { +@@ -20,6 +_,23 @@ + public Optional evaluate(BiFunction levelPosConsumer) { + return Optional.of(levelPosConsumer.apply(level, pos)); + } ++ // CraftBukkit start ++ @Override ++ public Level getWorld() { ++ return level; ++ } ++ ++ @Override ++ public BlockPos getPosition() { ++ return pos; ++ } ++ // CraftBukkit end ++ // Paper start - Add missing InventoryHolders ++ @Override ++ public boolean isBlock() { ++ return true; ++ } ++ // Paper end - Add missing InventoryHolders + }; + } +@@ -35,4 +_,29 @@ + return Optional.empty(); + }); + } + // CraftBukkit start + default Level getWorld() { + throw new UnsupportedOperationException("Not supported yet."); @@ -29,41 +66,4 @@ + return new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(this, menu.getBukkitView().getTopInventory()); + } + // Paper end - Add missing InventoryHolders -+ - ContainerLevelAccess NULL = new ContainerLevelAccess() { - @Override - public Optional evaluate(BiFunction getter) { - return Optional.empty(); - } -+ // Paper start - fix menus with empty level accesses -+ @Override -+ public org.bukkit.Location getLocation() { -+ return null; -+ } -+ // Paper end - fix menus with empty level accesses - }; - - static ContainerLevelAccess create(final Level world, final BlockPos pos) { - return new ContainerLevelAccess() { -+ // CraftBukkit start - @Override -+ public Level getWorld() { -+ return world; -+ } -+ -+ @Override -+ public BlockPos getPosition() { -+ return pos; -+ } -+ // CraftBukkit end -+ // Paper start - Add missing InventoryHolders -+ @Override -+ public boolean isBlock() { -+ return true; -+ } -+ // Paper end - Add missing InventoryHolders -+ -+ @Override - public Optional evaluate(BiFunction getter) { - return Optional.of(getter.apply(world, pos)); - } + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/ContainerListener.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerListener.java.patch new file mode 100644 index 0000000000..0f457f3e8b --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerListener.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/inventory/ContainerListener.java ++++ b/net/minecraft/world/inventory/ContainerListener.java +@@ -6,4 +_,10 @@ + void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack stack); + + void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value); ++ ++ // Paper start - Add PlayerInventorySlotChangeEvent ++ default void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack oldStack, ItemStack stack) { ++ slotChanged(containerToSend, dataSlotIndex, stack); ++ } ++ // Paper end - Add PlayerInventorySlotChangeEvent + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch new file mode 100644 index 0000000000..a5f19041a8 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/inventory/ContainerSynchronizer.java ++++ b/net/minecraft/world/inventory/ContainerSynchronizer.java +@@ -11,4 +_,6 @@ + void sendCarriedChange(AbstractContainerMenu containerMenu, ItemStack stack); + + void sendDataChange(AbstractContainerMenu container, int id, int value); ++ ++ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/CrafterMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/CrafterMenu.java.patch new file mode 100644 index 0000000000..e5fb558412 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/CrafterMenu.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/inventory/CrafterMenu.java ++++ b/net/minecraft/world/inventory/CrafterMenu.java +@@ -19,6 +_,20 @@ + private final ContainerData containerData; + private final Player player; + private final CraftingContainer container; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftCrafterView bukkitEntity = null; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftCrafterView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryCrafter inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryCrafter(this.container, this.resultContainer); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftCrafterView(this.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + public CrafterMenu(int containerId, Inventory playerInventory) { + super(MenuType.CRAFTER_3x3, containerId); +@@ -100,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/CraftingContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/CraftingContainer.java.patch new file mode 100644 index 0000000000..2225d1d404 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/CraftingContainer.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/inventory/CraftingContainer.java ++++ b/net/minecraft/world/inventory/CraftingContainer.java +@@ -12,6 +_,15 @@ + + List getItems(); + ++ // CraftBukkit start ++ default net.minecraft.world.item.crafting.RecipeHolder getCurrentRecipe() { ++ return null; ++ } ++ ++ default void setCurrentRecipe(net.minecraft.world.item.crafting.RecipeHolder recipe) { ++ } ++ // CraftBukkit end ++ + default CraftingInput asCraftInput() { + return this.asPositionedCraftInput().input(); + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/CraftingMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/CraftingMenu.java.patch new file mode 100644 index 0000000000..a569fb6dd8 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/CraftingMenu.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/inventory/CraftingMenu.java ++++ b/net/minecraft/world/inventory/CraftingMenu.java +@@ -30,13 +_,16 @@ + public final ContainerLevelAccess access; + private final Player player; + private boolean placingRecipe; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity = null; ++ // CraftBukkit end + + public CraftingMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + + public CraftingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { +- super(MenuType.CRAFTING, containerId, 3, 3); ++ super(MenuType.CRAFTING, containerId, 3, 3, playerInventory); // CraftBukkit - pass player + this.access = access; + this.player = playerInventory.player; + this.addResultSlot(this.player, 124, 35); +@@ -56,6 +_,7 @@ + ServerPlayer serverPlayer = (ServerPlayer)player; + ItemStack itemStack = ItemStack.EMPTY; + Optional> recipeFor = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftInput, level, recipe); ++ craftSlots.setCurrentRecipe(recipeFor.orElse(null)); // CraftBukkit + if (recipeFor.isPresent()) { + RecipeHolder recipeHolder = recipeFor.get(); + CraftingRecipe craftingRecipe = recipeHolder.value(); +@@ -66,6 +_,7 @@ + } + } + } ++ itemStack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(craftSlots, resultSlots, itemStack, menu.getBukkitView(), recipeFor.map(RecipeHolder::value).orElse(null) instanceof net.minecraft.world.item.crafting.RepairItemRecipe); // CraftBukkit + + resultSlots.setItem(0, itemStack); + menu.setRemoteSlot(0, itemStack); +@@ -102,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CRAFTING_TABLE); + } + +@@ -176,4 +_,17 @@ + protected Player owner() { + return this.player; + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/DispenserMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/DispenserMenu.java.patch new file mode 100644 index 0000000000..de6614874c --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/DispenserMenu.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/inventory/DispenserMenu.java ++++ b/net/minecraft/world/inventory/DispenserMenu.java +@@ -13,6 +_,10 @@ + private static final int USE_ROW_SLOT_START = 36; + private static final int USE_ROW_SLOT_END = 45; + public final Container dispenser; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public DispenserMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(9)); +@@ -20,6 +_,9 @@ + + public DispenserMenu(int containerId, Inventory playerInventory, Container container) { + super(MenuType.GENERIC_3x3, containerId); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end + checkContainerSize(container, 9); + this.dispenser = container; + container.startOpen(playerInventory.player); +@@ -38,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.dispenser.stillValid(player); + } + +@@ -77,4 +_,17 @@ + super.removed(player); + this.dispenser.stopOpen(player); + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventory(this.dispenser); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/EnchantmentMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/EnchantmentMenu.java.patch new file mode 100644 index 0000000000..bb590914a6 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/EnchantmentMenu.java.patch @@ -0,0 +1,205 @@ +--- a/net/minecraft/world/inventory/EnchantmentMenu.java ++++ b/net/minecraft/world/inventory/EnchantmentMenu.java +@@ -31,19 +_,17 @@ + + public class EnchantmentMenu extends AbstractContainerMenu { + static final ResourceLocation EMPTY_SLOT_LAPIS_LAZULI = ResourceLocation.withDefaultNamespace("container/slot/lapis_lazuli"); +- private final Container enchantSlots = new SimpleContainer(2) { +- @Override +- public void setChanged() { +- super.setChanged(); +- EnchantmentMenu.this.slotsChanged(this); +- } +- }; ++ private final Container enchantSlots; // Paper - Add missing InventoryHolders - move down + private final ContainerLevelAccess access; + private final RandomSource random = RandomSource.create(); + private final DataSlot enchantmentSeed = DataSlot.standalone(); + public final int[] costs = new int[3]; + public final int[] enchantClue = new int[]{-1, -1, -1}; + public final int[] levelClue = new int[]{-1, -1, -1}; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftEnchantmentView bukkitEntity = null; ++ private org.bukkit.entity.Player player; ++ // CraftBukkit end + + public EnchantmentMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -51,6 +_,22 @@ + + public EnchantmentMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { + super(MenuType.ENCHANTMENT, containerId); ++ // Paper start - Add missing InventoryHolders ++ this.enchantSlots = new SimpleContainer(this.createBlockHolder(access), 2) { // Paper - Add missing InventoryHolders ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ EnchantmentMenu.this.slotsChanged(this); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ // Paper end - Add missing InventoryHolders + this.access = access; + this.addSlot(new Slot(this.enchantSlots, 0, 15, 47) { + @Override +@@ -80,13 +_,16 @@ + this.addDataSlot(DataSlot.shared(this.levelClue, 0)); + this.addDataSlot(DataSlot.shared(this.levelClue, 1)); + this.addDataSlot(DataSlot.shared(this.levelClue, 2)); ++ // CraftBukkit start ++ this.player = (org.bukkit.entity.Player) playerInventory.player.getBukkitEntity(); ++ // CraftBukkit end + } + + @Override + public void slotsChanged(Container inventory) { + if (inventory == this.enchantSlots) { + ItemStack item = inventory.getItem(0); +- if (!item.isEmpty() && item.isEnchantable()) { ++ if (!item.isEmpty()) { // CraftBukkit - relax condition + this.access.execute((level, blockPos) -> { + IdMap> holderIdMap = level.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).asHolderIdMap(); + int i1 = 0; +@@ -119,6 +_,42 @@ + } + } + ++ // CraftBukkit start ++ org.bukkit.craftbukkit.inventory.CraftItemStack craftItemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); ++ org.bukkit.enchantments.EnchantmentOffer[] offers = new org.bukkit.enchantments.EnchantmentOffer[3]; ++ for (int j = 0; j < 3; ++j) { ++ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.craftbukkit.enchantments.CraftEnchantment.minecraftHolderToBukkit(holderIdMap.byId(this.enchantClue[j])) : null; ++ offers[j] = (enchantment != null) ? new org.bukkit.enchantments.EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; ++ } ++ ++ org.bukkit.event.enchantment.PrepareItemEnchantEvent event = new org.bukkit.event.enchantment.PrepareItemEnchantEvent(this.player, this.getBukkitView(), this.access.getLocation().getBlock(), craftItemStack, offers, i1); ++ event.setCancelled(!item.isEnchantable()); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (int j = 0; j < 3; ++j) { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ return; ++ } ++ ++ for (int j = 0; j < 3; j++) { ++ org.bukkit.enchantments.EnchantmentOffer offer = event.getOffers()[j]; ++ if (offer != null) { ++ this.costs[j] = offer.getCost(); ++ this.enchantClue[j] = holderIdMap.getId(org.bukkit.craftbukkit.enchantments.CraftEnchantment ++ .bukkitToMinecraftHolder(offer.getEnchantment())); ++ this.levelClue[j] = offer.getEnchantmentLevel(); ++ } else { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ } ++ // CraftBukkit end ++ + this.broadcastChanges(); + }); + } else { +@@ -145,19 +_,51 @@ + return false; + } else { + this.access.execute((level, blockPos) -> { +- ItemStack itemStack = item; ++ ItemStack itemStack = item; // Paper - diff on change + List enchantmentList = this.getEnchantmentList(level.registryAccess(), item, id, this.costs[id]); +- if (!enchantmentList.isEmpty()) { ++ // CraftBukkit start ++ IdMap> registry = level.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).asHolderIdMap(); ++ if (true || !enchantmentList.isEmpty()) { ++ // player.onEnchantmentPerformed(item, i); // Moved down ++ java.util.Map enchants = new java.util.HashMap<>(); ++ for (EnchantmentInstance instance : enchantmentList) { ++ enchants.put(org.bukkit.craftbukkit.enchantments.CraftEnchantment.minecraftHolderToBukkit(instance.enchantment), instance.level); ++ } ++ org.bukkit.craftbukkit.inventory.CraftItemStack craftItemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack); ++ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.craftbukkit.enchantments.CraftEnchantment.minecraftHolderToBukkit(registry.byId(this.enchantClue[id])); ++ int hintedEnchantmentLevel = this.levelClue[id]; ++ org.bukkit.event.enchantment.EnchantItemEvent event = new org.bukkit.event.enchantment.EnchantItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), this.getBukkitView(), this.access.getLocation().getBlock(), craftItemStack, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ int itemLevel = event.getExpLevelCost(); ++ if (event.isCancelled() || (itemLevel > player.experienceLevel && !player.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { ++ return; ++ } ++ // CraftBukkit end ++ // Paper start ++ itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.getOrCloneOnMutation(craftItemStack, event.getItem()); ++ if (itemStack != item) { ++ this.enchantSlots.setItem(0, itemStack); ++ } ++ if (itemStack.is(Items.BOOK)) { ++ itemStack = itemStack.transmuteCopy(Items.ENCHANTED_BOOK); ++ this.enchantSlots.setItem(0, itemStack); ++ } ++ // Paper end ++ ++ // CraftBukkit start ++ for (java.util.Map.Entry entry : event.getEnchantsToAdd().entrySet()) { ++ Holder nms = org.bukkit.craftbukkit.enchantments.CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()); ++ if (nms == null) { ++ continue; ++ } ++ ++ EnchantmentInstance weightedrandomenchant = new EnchantmentInstance(nms, entry.getValue()); ++ itemStack.enchant(weightedrandomenchant.enchantment, weightedrandomenchant.level); ++ } + player.onEnchantmentPerformed(item, i); +- if (item.is(Items.BOOK)) { +- itemStack = item.transmuteCopy(Items.ENCHANTED_BOOK); +- this.enchantSlots.setItem(0, itemStack); +- } +- +- for (EnchantmentInstance enchantmentInstance : enchantmentList) { +- itemStack.enchant(enchantmentInstance.enchantment, enchantmentInstance.level); +- } +- ++ // CraftBukkit end ++ ++ // CraftBukkit - TODO: let plugins change this + item1.consume(i, player); + if (item1.isEmpty()) { + this.enchantSlots.setItem(1, ItemStack.EMPTY); +@@ -214,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.ENCHANTING_TABLE); + } + +@@ -261,4 +_,22 @@ + + return itemStack; + } ++ // CraftBukkit start ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftEnchantmentView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting(this.enchantSlots); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftEnchantmentView(this.player, inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end ++ ++ // Paper start - add enchantment seed update API ++ public void setEnchantmentSeed(int seed) { ++ this.enchantmentSeed.set(seed); ++ } ++ // Paper end - add enchantment seed update API + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/FurnaceResultSlot.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/FurnaceResultSlot.java.patch new file mode 100644 index 0000000000..8cf409634d --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/FurnaceResultSlot.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/inventory/FurnaceResultSlot.java ++++ b/net/minecraft/world/inventory/FurnaceResultSlot.java +@@ -45,7 +_,7 @@ + protected void checkTakeAchievements(ItemStack stack) { + stack.onCraftedBy(this.player.level(), this.player, this.removeCount); + if (this.player instanceof ServerPlayer serverPlayer && this.container instanceof AbstractFurnaceBlockEntity abstractFurnaceBlockEntity) { +- abstractFurnaceBlockEntity.awardUsedRecipesAndPopExperience(serverPlayer); ++ abstractFurnaceBlockEntity.awardUsedRecipesAndPopExperience(serverPlayer, stack, this.removeCount); // CraftBukkit + } + + this.removeCount = 0; diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/GrindstoneMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/GrindstoneMenu.java.patch new file mode 100644 index 0000000000..3ef40a1183 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/GrindstoneMenu.java.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -20,6 +_,21 @@ + import net.minecraft.world.phys.Vec3; + + public class GrindstoneMenu extends AbstractContainerMenu { ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity = null; ++ private org.bukkit.entity.Player player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone(this.repairSlots, this.resultSlots); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player, inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAX_NAME_LENGTH = 35; + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; +@@ -28,14 +_,8 @@ + private static final int INV_SLOT_END = 30; + private static final int USE_ROW_SLOT_START = 30; + private static final int USE_ROW_SLOT_END = 39; +- private final Container resultSlots = new ResultContainer(); +- final Container repairSlots = new SimpleContainer(2) { +- @Override +- public void setChanged() { +- super.setChanged(); +- GrindstoneMenu.this.slotsChanged(this); +- } +- }; ++ private final Container resultSlots; // Paper - Add missing InventoryHolders - move down ++ final Container repairSlots; // Paper - Add missing InventoryHolders - move down + private final ContainerLevelAccess access; + + public GrindstoneMenu(int containerId, Inventory playerInventory) { +@@ -44,6 +_,22 @@ + + public GrindstoneMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.GRINDSTONE, containerId); ++ // Paper start - Add missing InventoryHolders ++ this.resultSlots = new ResultContainer(this.createBlockHolder(access)); // Paper - Add missing InventoryHolders ++ this.repairSlots = new SimpleContainer(this.createBlockHolder(access), 2) { // Paper - Add missing InventoryHolders ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ GrindstoneMenu.this.slotsChanged(this); ++ } ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ // Paper end - Add missing InventoryHolders + this.access = access; + this.addSlot(new Slot(this.repairSlots, 0, 49, 19) { + @Override +@@ -67,7 +_,11 @@ + public void onTake(Player player, ItemStack stack) { + access.execute((level, blockPos) -> { + if (level instanceof ServerLevel) { +- ExperienceOrb.award((ServerLevel)level, Vec3.atCenterOf(blockPos), this.getExperienceAmount(level)); ++ // Paper start - Fire BlockExpEvent on grindstone use ++ org.bukkit.event.block.BlockExpEvent event = new org.bukkit.event.block.BlockExpEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPos), this.getExperienceAmount(level)); ++ event.callEvent(); ++ ExperienceOrb.award((ServerLevel) level, Vec3.atCenterOf(blockPos), event.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); ++ // Paper end - Fire BlockExpEvent on grindstone use + } + + level.levelEvent(1042, blockPos, 0); +@@ -104,6 +_,7 @@ + } + }); + this.addStandardInventorySlots(playerInventory, 8, 84); ++ this.player = (org.bukkit.entity.Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -111,11 +_,13 @@ + super.slotsChanged(inventory); + if (inventory == this.repairSlots) { + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent + } + } + + private void createResult() { +- this.resultSlots.setItem(0, this.computeResult(this.repairSlots.getItem(0), this.repairSlots.getItem(1))); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(this.getBukkitView(), this.computeResult(this.repairSlots.getItem(0), this.repairSlots.getItem(1))); // CraftBukkit ++ this.sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + +@@ -201,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.GRINDSTONE); + } + diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/HopperMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/HopperMenu.java.patch new file mode 100644 index 0000000000..d6d2f6c1de --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/HopperMenu.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/inventory/HopperMenu.java ++++ b/net/minecraft/world/inventory/HopperMenu.java +@@ -9,6 +_,21 @@ + public class HopperMenu extends AbstractContainerMenu { + public static final int CONTAINER_SIZE = 5; + private final Container hopper; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventory(this.hopper); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + public HopperMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(5)); +@@ -17,6 +_,7 @@ + public HopperMenu(int containerId, Inventory playerInventory, Container container) { + super(MenuType.HOPPER, containerId); + this.hopper = container; ++ this.player = playerInventory; // CraftBukkit - save player + checkContainerSize(container, 5); + container.startOpen(playerInventory.player); + +@@ -29,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.hopper.stillValid(player); + } + diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/HorseInventoryMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/HorseInventoryMenu.java.patch new file mode 100644 index 0000000000..8128aca0d5 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/HorseInventoryMenu.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -19,9 +_,23 @@ + private final AbstractHorse horse; + public static final int SLOT_BODY_ARMOR = 1; + private static final int SLOT_HORSE_INVENTORY_START = 2; ++ // CraftBukkit start ++ org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ Inventory player; ++ ++ @Override ++ public org.bukkit.inventory.InventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ return this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.player.getBukkitEntity(), this.horseContainer.getOwner().getInventory(), this); ++ } ++ // CraftBukkit end + + public HorseInventoryMenu(int containerId, Inventory inventory, Container horseContainer, final AbstractHorse horse, int columns) { + super(null, containerId); ++ this.player = inventory; // CraftBukkit - save player + this.horseContainer = horseContainer; + this.armorContainer = horse.getBodyArmorAccess(); + this.horse = horse; diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/InventoryMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/InventoryMenu.java.patch new file mode 100644 index 0000000000..678db72493 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/InventoryMenu.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/inventory/InventoryMenu.java ++++ b/net/minecraft/world/inventory/InventoryMenu.java +@@ -2,6 +_,7 @@ + + import java.util.List; + import java.util.Map; ++import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.Container; +@@ -44,9 +_,15 @@ + private static final EquipmentSlot[] SLOT_IDS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; + public final boolean active; + private final Player owner; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity = null; ++ // CraftBukkit end + + public InventoryMenu(Inventory playerInventory, boolean active, final Player owner) { +- super(null, 0, 2, 2); ++ // CraftBukkit start ++ super((MenuType) null, 0, 2, 2, playerInventory); // CraftBukkit - save player ++ this.setTitle(Component.translatable("container.crafting")); // SPIGOT-4722: Allocate title for player inventory ++ // CraftBukkit end + this.active = active; + this.owner = owner; + this.addResultSlot(owner, 154, 28); +@@ -188,4 +_,17 @@ + protected Player owner() { + return this.owner; + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryCrafting inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.owner.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/ItemCombinerMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ItemCombinerMenu.java.patch similarity index 51% rename from paper-server/patches/unapplied/net/minecraft/world/inventory/ItemCombinerMenu.java.patch rename to paper-server/patches/sources/net/minecraft/world/inventory/ItemCombinerMenu.java.patch index 7d50fbdafb..447c6217c1 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/ItemCombinerMenu.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ItemCombinerMenu.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/inventory/ItemCombinerMenu.java +++ b/net/minecraft/world/inventory/ItemCombinerMenu.java -@@ -17,12 +17,7 @@ +@@ -15,12 +_,7 @@ protected final ContainerLevelAccess access; protected final Player player; protected final Container inputSlots; @@ -13,11 +13,11 @@ + protected final ResultContainer resultSlots; // Paper - Add missing InventoryHolders; delay field init private final int resultSlotIndex; - protected boolean mayPickup(Player player, boolean present) { -@@ -36,6 +31,14 @@ - public ItemCombinerMenu(@Nullable MenuType type, int syncId, Inventory playerInventory, ContainerLevelAccess context, ItemCombinerMenuSlotDefinition forgingSlotsManager) { - super(type, syncId); - this.access = context; + protected boolean mayPickup(Player player, boolean hasStack) { +@@ -36,6 +_,14 @@ + ) { + super(menuType, containerId); + this.access = access; + // Paper start - Add missing InventoryHolders; delay field init + this.resultSlots = new ResultContainer(this.createBlockHolder(this.access)) { + @Override @@ -26,19 +26,10 @@ + } + }; + // Paper end - Add missing InventoryHolders; delay field init - this.player = playerInventory.player; - this.inputSlots = this.createContainer(forgingSlotsManager.getNumOfInputSlots()); - this.resultSlotIndex = forgingSlotsManager.getResultSlotIndex(); -@@ -50,7 +53,7 @@ - while (iterator.hasNext()) { - final ItemCombinerMenuSlotDefinition.SlotDefinition itemcombinermenuslotdefinition_b = (ItemCombinerMenuSlotDefinition.SlotDefinition) iterator.next(); - -- this.addSlot(new Slot(this, this.inputSlots, itemcombinermenuslotdefinition_b.slotIndex(), itemcombinermenuslotdefinition_b.x(), itemcombinermenuslotdefinition_b.y()) { -+ this.addSlot(new Slot(this.inputSlots, itemcombinermenuslotdefinition_b.slotIndex(), itemcombinermenuslotdefinition_b.x(), itemcombinermenuslotdefinition_b.y()) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return itemcombinermenuslotdefinition_b.mayPlace().test(stack); -@@ -82,7 +85,7 @@ + this.player = inventory.player; + this.inputSlots = this.createContainer(slotDefinition.getNumOfInputSlots()); + this.resultSlotIndex = slotDefinition.getResultSlotIndex(); +@@ -79,7 +_,7 @@ public abstract void createResult(); private SimpleContainer createContainer(int size) { @@ -47,19 +38,19 @@ @Override public void setChanged() { super.setChanged(); -@@ -96,6 +99,7 @@ +@@ -93,6 +_,7 @@ super.slotsChanged(inventory); if (inventory == this.inputSlots) { this.createResult(); + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, this instanceof SmithingMenu ? 3 : 2); // Paper - Add PrepareResultEvent } - } -@@ -110,6 +114,7 @@ + +@@ -104,6 +_,7 @@ @Override public boolean stillValid(Player player) { + if (!this.checkReachable) return true; // CraftBukkit - return (Boolean) this.access.evaluate((world, blockposition) -> { - return !this.isValidBlock(world.getBlockState(blockposition)) ? false : player.canInteractWithBlock(blockposition, 4.0D); - }, true); + return this.access + .evaluate((level, blockPos) -> !this.isValidBlock(level.getBlockState(blockPos)) ? false : player.canInteractWithBlock(blockPos, 4.0), true); + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/LecternMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/LecternMenu.java.patch new file mode 100644 index 0000000000..eb58b2f0ef --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/LecternMenu.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/world/inventory/LecternMenu.java ++++ b/net/minecraft/world/inventory/LecternMenu.java +@@ -14,12 +_,29 @@ + public static final int BUTTON_PAGE_JUMP_RANGE_START = 100; + private final Container lectern; + private final ContainerData lecternData; +- +- public LecternMenu(int containerId) { +- this(containerId, new SimpleContainer(1), new SimpleContainerData(1)); +- } +- +- public LecternMenu(int containerId, Container lectern, ContainerData lecternData) { ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftLecternView bukkitEntity = null; ++ private org.bukkit.entity.Player player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftLecternView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryLectern inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryLectern(this.lectern); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftLecternView(this.player, inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - add player ++ public LecternMenu(int containerId, net.minecraft.world.entity.player.Inventory playerinventory) { ++ this(containerId, new SimpleContainer(1), new SimpleContainerData(1), playerinventory); ++ // CraftBukkit end - add player ++ } ++ ++ public LecternMenu(int containerId, Container lectern, ContainerData lecternData, net.minecraft.world.entity.player.Inventory playerinventory) { + super(MenuType.LECTERN, containerId); + checkContainerSize(lectern, 1); + checkContainerDataCount(lecternData, 1); +@@ -33,10 +_,12 @@ + } + }); + this.addDataSlots(lecternData); ++ this.player = (org.bukkit.entity.Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override + public boolean clickMenuButton(Player player, int id) { ++ io.papermc.paper.event.player.PlayerLecternPageChangeEvent playerLecternPageChangeEvent; org.bukkit.craftbukkit.inventory.CraftInventoryLectern bukkitView; // Paper - Add PlayerLecternPageChangeEvent + if (id >= 100) { + int i = id - 100; + this.setData(0, i); +@@ -45,12 +_,26 @@ + switch (id) { + case 1: { + int i = this.lecternData.get(0); +- this.setData(0, i - 1); ++ // Paper start - Add PlayerLecternPageChangeEvent ++ bukkitView = (org.bukkit.craftbukkit.inventory.CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, i, i - 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end - Add PlayerLecternPageChangeEvent + return true; + } + case 2: { + int i = this.lecternData.get(0); +- this.setData(0, i + 1); ++ // Paper start - Add PlayerLecternPageChangeEvent ++ bukkitView = (org.bukkit.craftbukkit.inventory.CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, i, i + 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end - Add PlayerLecternPageChangeEvent + return true; + } + case 3: +@@ -58,6 +_,13 @@ + return false; + } + ++ // CraftBukkit start - Event for taking the book ++ org.bukkit.event.player.PlayerTakeLecternBookEvent event = new org.bukkit.event.player.PlayerTakeLecternBookEvent(this.player, ((org.bukkit.craftbukkit.inventory.CraftInventoryLectern) this.getBukkitView().getTopInventory()).getHolder()); ++ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + ItemStack itemStack = this.lectern.removeItemNoUpdate(0); + this.lectern.setChanged(); + if (!player.getInventory().add(itemStack)) { +@@ -84,6 +_,8 @@ + + @Override + public boolean stillValid(Player player) { ++ if (this.lectern instanceof net.minecraft.world.level.block.entity.LecternBlockEntity.LecternInventory && !((net.minecraft.world.level.block.entity.LecternBlockEntity.LecternInventory) this.lectern).getLectern().hasBook()) return false; // CraftBukkit ++ if (!this.checkReachable) return true; // CraftBukkit + return this.lectern.stillValid(player); + } + diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/LoomMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/LoomMenu.java.patch new file mode 100644 index 0000000000..8182e17e77 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/LoomMenu.java.patch @@ -0,0 +1,143 @@ +--- a/net/minecraft/world/inventory/LoomMenu.java ++++ b/net/minecraft/world/inventory/LoomMenu.java +@@ -38,21 +_,23 @@ + private final Slot patternSlot; + private final Slot resultSlot; + long lastSoundTime; +- private final Container inputContainer = new SimpleContainer(3) { +- @Override +- public void setChanged() { +- super.setChanged(); +- LoomMenu.this.slotsChanged(this); +- LoomMenu.this.slotUpdateListener.run(); +- } +- }; +- private final Container outputContainer = new SimpleContainer(1) { +- @Override +- public void setChanged() { +- super.setChanged(); +- LoomMenu.this.slotUpdateListener.run(); +- } +- }; ++ private final Container inputContainer; // Paper - Add missing InventoryHolders - move down ++ private final Container outputContainer; // Paper - Add missing InventoryHolders - move down ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftLoomView bukkitEntity = null; ++ private org.bukkit.entity.Player player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftLoomView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryLoom inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryLoom(this.inputContainer, this.outputContainer); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftLoomView(this.player, inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + public LoomMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -61,6 +_,28 @@ + public LoomMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.LOOM, containerId); + this.access = access; ++ // CraftBukkit start ++ this.inputContainer = new SimpleContainer(this.createBlockHolder(access), 3) { // Paper - Add missing InventoryHolders ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ LoomMenu.this.slotsChanged(this); ++ LoomMenu.this.slotUpdateListener.run(); ++ } ++ }; ++ this.outputContainer = new SimpleContainer(this.createBlockHolder(access), 1) { // Paper - Add missing InventoryHolders ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ LoomMenu.this.slotUpdateListener.run(); ++ } ++ ++ @Override ++ public org.bukkit.Location getLocation() { ++ return access.getLocation(); ++ } ++ }; ++ // CraftBukkit end + this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { + @Override + public boolean mayPlace(ItemStack stack) { +@@ -106,18 +_,44 @@ + this.addStandardInventorySlots(playerInventory, 8, 84); + this.addDataSlot(this.selectedBannerPatternIndex); + this.patternGetter = playerInventory.player.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN); ++ this.player = (org.bukkit.entity.Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.LOOM); + } + + @Override + public boolean clickMenuButton(Player player, int id) { + if (id >= 0 && id < this.selectablePatterns.size()) { +- this.selectedBannerPatternIndex.set(id); +- this.setupResultSlot(this.selectablePatterns.get(id)); ++ // Paper start - Add PlayerLoomPatternSelectEvent ++ int selectablePatternIndex = id; ++ io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((org.bukkit.entity.Player) player.getBukkitEntity(), ((org.bukkit.craftbukkit.inventory.CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.craftbukkit.block.banner.CraftPatternType.minecraftHolderToBukkit(this.selectablePatterns.get(selectablePatternIndex))); ++ if (!event.callEvent()) { ++ player.containerMenu.sendAllDataToRemote(); ++ return false; ++ } ++ final Holder eventPattern = org.bukkit.craftbukkit.block.banner.CraftPatternType.bukkitToMinecraftHolder(event.getPatternType()); ++ Holder selectedPattern = null; ++ for (int i = 0; i < this.selectablePatterns.size(); i++) { ++ final Holder holder = this.selectablePatterns.get(i); ++ if (eventPattern.equals(holder)) { ++ selectablePatternIndex = i; ++ selectedPattern = holder; ++ break; ++ } ++ } ++ if (selectedPattern == null) { ++ selectedPattern = eventPattern; ++ selectablePatternIndex = -1; ++ } ++ ++ player.containerMenu.sendAllDataToRemote(); ++ this.selectedBannerPatternIndex.set(selectablePatternIndex); ++ this.setupResultSlot(java.util.Objects.requireNonNull(selectedPattern, "selectedPattern was null, this is unexpected")); ++ // Paper end - Add PlayerLoomPatternSelectEvent + return true; + } else { + return false; +@@ -180,7 +_,8 @@ + this.resultSlot.set(ItemStack.EMPTY); + } + +- this.broadcastChanges(); ++ // this.broadcastChanges(); // Paper - Add PrepareResultEvent; done below ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper - Add PrepareResultEvent + } else { + this.resultSlot.set(ItemStack.EMPTY); + this.selectablePatterns = List.of(); +@@ -269,7 +_,14 @@ + itemStack.update( + DataComponents.BANNER_PATTERNS, + BannerPatternLayers.EMPTY, +- bannerPatternLayers -> new BannerPatternLayers.Builder().addAll(bannerPatternLayers).add(pattern, dyeColor).build() ++ // CraftBukkit start ++ bannerPatternLayers -> { ++ if (bannerPatternLayers.layers().size() > 20) { ++ bannerPatternLayers = new BannerPatternLayers(List.copyOf(bannerPatternLayers.layers().subList(0, 20))); ++ } ++ return new BannerPatternLayers.Builder().addAll(bannerPatternLayers).add(pattern, dyeColor).build(); ++ } ++ // CraftBukkit end + ); + } + diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/MenuType.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/MenuType.java.patch new file mode 100644 index 0000000000..f28a7e6d38 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/MenuType.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/inventory/MenuType.java ++++ b/net/minecraft/world/inventory/MenuType.java +@@ -26,7 +_,7 @@ + public static final MenuType FURNACE = register("furnace", FurnaceMenu::new); + public static final MenuType GRINDSTONE = register("grindstone", GrindstoneMenu::new); + public static final MenuType HOPPER = register("hopper", HopperMenu::new); +- public static final MenuType LECTERN = register("lectern", (containerId, playerInventory) -> new LecternMenu(containerId)); ++ public static final MenuType LECTERN = register("lectern", LecternMenu::new); // CraftBukkit + public static final MenuType LOOM = register("loom", LoomMenu::new); + public static final MenuType MERCHANT = register("merchant", MerchantMenu::new); + public static final MenuType SHULKER_BOX = register("shulker_box", ShulkerBoxMenu::new); +@@ -35,17 +_,17 @@ + public static final MenuType CARTOGRAPHY_TABLE = register("cartography_table", CartographyTableMenu::new); + public static final MenuType STONECUTTER = register("stonecutter", StonecutterMenu::new); + private final FeatureFlagSet requiredFeatures; +- private final MenuType.MenuSupplier constructor; ++ private final MenuSupplier constructor; + +- private static MenuType register(String key, MenuType.MenuSupplier factory) { ++ private static MenuType register(String key, MenuSupplier factory) { + return Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.VANILLA_SET)); + } + +- private static MenuType register(String key, MenuType.MenuSupplier factory, FeatureFlag... requiredFeatures) { ++ private static MenuType register(String key, MenuSupplier factory, FeatureFlag... requiredFeatures) { + return Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.REGISTRY.subset(requiredFeatures))); + } + +- private MenuType(MenuType.MenuSupplier constructor, FeatureFlagSet requiredFeatures) { ++ private MenuType(MenuSupplier constructor, FeatureFlagSet requiredFeatures) { + this.constructor = constructor; + this.requiredFeatures = requiredFeatures; + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/MerchantContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/MerchantContainer.java.patch new file mode 100644 index 0000000000..a460afb9b4 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/MerchantContainer.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/inventory/MerchantContainer.java ++++ b/net/minecraft/world/inventory/MerchantContainer.java +@@ -17,6 +_,45 @@ + private MerchantOffer activeOffer; + public int selectionHint; + private int futureXp; ++ // CraftBukkit start - add fields and methods ++ public java.util.List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public java.util.List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) { ++ this.transaction.add(who); ++ } ++ ++ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) { ++ this.transaction.remove(who); ++ this.merchant.setTradingPlayer((Player) null); // SPIGOT-4860 ++ } ++ ++ public java.util.List getViewers() { ++ return this.transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return this.maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ this.maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (this.merchant instanceof net.minecraft.world.entity.npc.AbstractVillager abstractVillager) ? (org.bukkit.craftbukkit.entity.CraftAbstractVillager) ((net.minecraft.world.entity.npc.AbstractVillager) this.merchant).getBukkitEntity() : null; ++ } ++ ++ @Override ++ public org.bukkit.Location getLocation() { ++ return (this.merchant instanceof net.minecraft.world.entity.npc.AbstractVillager) ? ((net.minecraft.world.entity.npc.AbstractVillager) this.merchant).getBukkitEntity().getLocation() : null; // Paper - Fix inventories returning null Locations ++ } ++ // CraftBukkit end + + public MerchantContainer(Merchant merchant) { + this.merchant = merchant; diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/MerchantMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/MerchantMenu.java.patch new file mode 100644 index 0000000000..d3c402326c --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/MerchantMenu.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/inventory/MerchantMenu.java ++++ b/net/minecraft/world/inventory/MerchantMenu.java +@@ -30,6 +_,18 @@ + private int merchantLevel; + private boolean showProgressBar; + private boolean canRestock; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftMerchantView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftMerchantView getBukkitView() { ++ if (this.bukkitEntity == null) { ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftMerchantView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventoryMerchant(this.trader, this.tradeContainer), this, this.trader); ++ } ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + public MerchantMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new ClientSideMerchant(playerInventory.player)); +@@ -42,6 +_,7 @@ + this.addSlot(new Slot(this.tradeContainer, 0, 136, 37)); + this.addSlot(new Slot(this.tradeContainer, 1, 162, 37)); + this.addSlot(new MerchantResultSlot(playerInventory.player, trader, this.tradeContainer, 2, 220, 37)); ++ this.player = playerInventory; // CraftBukkit - save player + this.addStandardInventorySlots(playerInventory, 108, 84); + } + +@@ -105,12 +_,12 @@ + ItemStack item = slot.getItem(); + itemStack = item.copy(); + if (index == 2) { +- if (!this.moveItemStackTo(item, 3, 39, true)) { ++ if (!this.moveItemStackTo(item, 3, 39, true, true)) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); +- this.playTradeSound(); ++ // slot.onQuickCraft(item, itemStack); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; moved to after the non-check moveItemStackTo call ++ // this.playTradeSound(); + } else if (index != 0 && index != 1) { + if (index >= 3 && index < 30) { + if (!this.moveItemStackTo(item, 30, 39, false)) { +@@ -123,6 +_,7 @@ + return ItemStack.EMPTY; + } + ++ if (index != 2) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; moved down for slot 2 + if (item.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { +@@ -134,13 +_,28 @@ + } + + slot.onTake(player, item); ++ } // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent; handle slot 2 ++ if (index == 2) { // is merchant result slot ++ slot.onTake(player, item); ++ if (item.isEmpty()) { ++ slot.set(ItemStack.EMPTY); ++ return ItemStack.EMPTY; ++ } ++ ++ this.moveItemStackTo(item, 3, 39, true, false); // This should always succeed because it's checked above ++ ++ slot.onQuickCraft(item, itemStack); ++ this.playTradeSound(); ++ slot.set(ItemStack.EMPTY); // item should ALWAYS be empty ++ } ++ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent + } + + return itemStack; + } + + private void playTradeSound() { +- if (!this.trader.isClientSide()) { ++ if (!this.trader.isClientSide() && this.trader instanceof Entity) { // CraftBukkit - SPIGOT-5035 + Entity entity = (Entity)this.trader; + entity.level() + .playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantResultSlot.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/MerchantResultSlot.java.patch similarity index 57% rename from paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantResultSlot.java.patch rename to paper-server/patches/sources/net/minecraft/world/inventory/MerchantResultSlot.java.patch index f363fb2ef5..ceb2902468 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantResultSlot.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/inventory/MerchantResultSlot.java.patch @@ -1,19 +1,19 @@ --- a/net/minecraft/world/inventory/MerchantResultSlot.java +++ b/net/minecraft/world/inventory/MerchantResultSlot.java -@@ -47,13 +47,32 @@ +@@ -47,13 +_,32 @@ @Override public void onTake(Player player, ItemStack stack) { - this.checkTakeAchievements(stack); + // this.checkTakeAchievements(stack); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; move to after event is called and not cancelled - MerchantOffer merchantOffer = this.slots.getActiveOffer(); + MerchantOffer activeOffer = this.slots.getActiveOffer(); + // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent + io.papermc.paper.event.player.PlayerPurchaseEvent event = null; -+ if (merchantOffer != null && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { ++ if (activeOffer != null && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { + if (this.merchant instanceof net.minecraft.world.entity.npc.AbstractVillager abstractVillager) { -+ event = new io.papermc.paper.event.player.PlayerTradeEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.AbstractVillager) abstractVillager.getBukkitEntity(), merchantOffer.asBukkit(), true, true); ++ event = new io.papermc.paper.event.player.PlayerTradeEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.AbstractVillager) abstractVillager.getBukkitEntity(), activeOffer.asBukkit(), true, true); + } else if (this.merchant instanceof org.bukkit.craftbukkit.inventory.CraftMerchantCustom.MinecraftMerchant) { -+ event = new io.papermc.paper.event.player.PlayerPurchaseEvent(serverPlayer.getBukkitEntity(), merchantOffer.asBukkit(), false, true); ++ event = new io.papermc.paper.event.player.PlayerPurchaseEvent(serverPlayer.getBukkitEntity(), activeOffer.asBukkit(), false, true); + } + if (event != null) { + if (!event.callEvent()) { @@ -21,17 +21,17 @@ + event.getPlayer().updateInventory(); + return; + } -+ merchantOffer = org.bukkit.craftbukkit.inventory.CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); ++ activeOffer = org.bukkit.craftbukkit.inventory.CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); + } + } + this.checkTakeAchievements(stack); + // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent - if (merchantOffer != null) { - ItemStack itemStack = this.slots.getItem(0); - ItemStack itemStack2 = this.slots.getItem(1); - if (merchantOffer.take(itemStack, itemStack2) || merchantOffer.take(itemStack2, itemStack)) { -- this.merchant.notifyTrade(merchantOffer); -+ this.merchant.processTrade(merchantOffer, event); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent + if (activeOffer != null) { + ItemStack item = this.slots.getItem(0); + ItemStack item1 = this.slots.getItem(1); + if (activeOffer.take(item, item1) || activeOffer.take(item1, item)) { +- this.merchant.notifyTrade(activeOffer); ++ this.merchant.processTrade(activeOffer, event); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent player.awardStat(Stats.TRADED_WITH_VILLAGER); - this.slots.setItem(0, itemStack); - this.slots.setItem(1, itemStack2); + this.slots.setItem(0, item); + this.slots.setItem(1, item1); diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch new file mode 100644 index 0000000000..62ebcb22a9 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java ++++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java +@@ -12,9 +_,22 @@ + public class PlayerEnderChestContainer extends SimpleContainer { + @Nullable + private EnderChestBlockEntity activeChest; +- +- public PlayerEnderChestContainer() { ++ // CraftBukkit start ++ private final Player owner; ++ ++ public org.bukkit.inventory.InventoryHolder getBukkitOwner() { ++ return this.owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public org.bukkit.Location getLocation() { ++ return this.activeChest != null ? org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.activeChest.getBlockPos(), this.activeChest.getLevel().getWorld()) : null; ++ } ++ ++ public PlayerEnderChestContainer(Player owner) { + super(27); ++ this.owner = owner; ++ // CraftBukkit end + } + + public void setActiveChest(EnderChestBlockEntity enderChestBlockEntity) { diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/ResultContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ResultContainer.java.patch similarity index 65% rename from paper-server/patches/unapplied/net/minecraft/world/inventory/ResultContainer.java.patch rename to paper-server/patches/sources/net/minecraft/world/inventory/ResultContainer.java.patch index a26bc470cf..da8f31ffe7 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/ResultContainer.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ResultContainer.java.patch @@ -1,21 +1,9 @@ --- a/net/minecraft/world/inventory/ResultContainer.java +++ b/net/minecraft/world/inventory/ResultContainer.java -@@ -9,12 +9,64 @@ - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.RecipeHolder; - -+// CraftBukkit start -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.entity.CraftHumanEntity; -+import org.bukkit.entity.HumanEntity; -+// CraftBukkit end -+ - public class ResultContainer implements Container, RecipeCraftingHolder { - - private final NonNullList itemStacks; +@@ -12,6 +_,53 @@ + private final NonNullList itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); @Nullable private RecipeHolder recipeUsed; - + // CraftBukkit start + private int maxStack = MAX_STACK; + @@ -33,10 +21,10 @@ + } + + // Don't need a transaction; the InventoryCrafting keeps track of it for us -+ public void onOpen(CraftHumanEntity who) {} -+ public void onClose(CraftHumanEntity who) {} -+ public java.util.List getViewers() { -+ return new java.util.ArrayList(); ++ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {} ++ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {} ++ public java.util.List getViewers() { ++ return new java.util.ArrayList<>(); + } + + @Override @@ -49,7 +37,7 @@ + } + + @Override -+ public Location getLocation() { ++ public org.bukkit.Location getLocation() { + return null; + } + // CraftBukkit end @@ -57,11 +45,12 @@ + private @Nullable java.util.function.Supplier holderCreator; + private @Nullable org.bukkit.inventory.InventoryHolder holder; + public ResultContainer(java.util.function.Supplier holderCreator) { -+ this(); + this.holderCreator = holderCreator; + } -+ // Paper end - Add missing InventoryHolders + - public ResultContainer() { - this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); - } ++ public ResultContainer() { ++ } ++ // Paper end - Add missing InventoryHolders + + @Override + public int getContainerSize() { diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch new file mode 100644 index 0000000000..a65b4c24dc --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -9,6 +_,20 @@ + public class ShulkerBoxMenu extends AbstractContainerMenu { + private static final int CONTAINER_SIZE = 27; + private final Container container; ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ private Inventory player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventory(this.container), this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + public ShulkerBoxMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(27)); +@@ -18,6 +_,7 @@ + super(MenuType.SHULKER_BOX, containerId); + checkContainerSize(container, 27); + this.container = container; ++ this.player = playerInventory; // CraftBukkit - save player + container.startOpen(playerInventory.player); + int i = 3; + int i1 = 9; +@@ -33,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/SmithingMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/SmithingMenu.java.patch new file mode 100644 index 0000000000..1277f3d7ac --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/SmithingMenu.java.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/inventory/SmithingMenu.java ++++ b/net/minecraft/world/inventory/SmithingMenu.java +@@ -32,6 +_,9 @@ + private final RecipePropertySet templateItemTest; + private final RecipePropertySet additionItemTest; + private final DataSlot hasRecipeError = DataSlot.standalone(); ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public SmithingMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -99,6 +_,7 @@ + if (this.level instanceof ServerLevel) { + boolean flag = this.getSlot(0).hasItem() && this.getSlot(1).hasItem() && this.getSlot(2).hasItem() && !this.getSlot(this.getResultSlot()).hasItem(); + this.hasRecipeError.set(flag ? 1 : 0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent + } + } + +@@ -115,7 +_,9 @@ + recipeFor.ifPresentOrElse(recipe -> { + ItemStack itemStack = recipe.value().assemble(smithingRecipeInput, this.level.registryAccess()); + this.resultSlots.setRecipeUsed((RecipeHolder)recipe); +- this.resultSlots.setItem(0, itemStack); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(this.getBukkitView(), itemStack); ++ // CraftBukkit end + }, () -> { + this.resultSlots.setRecipeUsed(null); + this.resultSlots.setItem(0, ItemStack.EMPTY); +@@ -137,4 +_,18 @@ + public boolean hasRecipeError() { + return this.hasRecipeError.get() > 0; + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventorySmithing( ++ this.access.getLocation(), this.inputSlots, this.resultSlots); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/StonecutterMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/StonecutterMenu.java.patch new file mode 100644 index 0000000000..4f3754e2e4 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/StonecutterMenu.java.patch @@ -0,0 +1,128 @@ +--- a/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/net/minecraft/world/inventory/StonecutterMenu.java +@@ -25,7 +_,7 @@ + private static final int USE_ROW_SLOT_START = 29; + private static final int USE_ROW_SLOT_END = 38; + private final ContainerLevelAccess access; +- final DataSlot selectedRecipeIndex = DataSlot.standalone(); ++ final DataSlot selectedRecipeIndex = DataSlot.shared(new int[1], 0); // Paper - Add PlayerStonecutterRecipeSelectEvent + private final Level level; + private SelectableRecipe.SingleInputSet recipesForInput = SelectableRecipe.SingleInputSet.empty(); + private ItemStack input = ItemStack.EMPTY; +@@ -33,15 +_,23 @@ + final Slot inputSlot; + final Slot resultSlot; + Runnable slotUpdateListener = () -> {}; +- public final Container container = new SimpleContainer(1) { +- @Override +- public void setChanged() { +- super.setChanged(); +- StonecutterMenu.this.slotsChanged(this); +- StonecutterMenu.this.slotUpdateListener.run(); ++ public final Container container; // Paper - Add missing InventoryHolders - move down ++ final ResultContainer resultContainer; // Paper - Add missing InventoryHolders - move down ++ // CraftBukkit start ++ private org.bukkit.craftbukkit.inventory.view.CraftStonecutterView bukkitEntity = null; ++ private org.bukkit.entity.Player player; ++ ++ @Override ++ public org.bukkit.craftbukkit.inventory.view.CraftStonecutterView getBukkitView() { ++ if (this.bukkitEntity != null) { ++ return this.bukkitEntity; + } +- }; +- final ResultContainer resultContainer = new ResultContainer(); ++ ++ org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter(this.container, this.resultContainer); ++ this.bukkitEntity = new org.bukkit.craftbukkit.inventory.view.CraftStonecutterView(this.player, inventory, this); ++ return this.bukkitEntity; ++ } ++ // CraftBukkit end + + public StonecutterMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -51,6 +_,23 @@ + super(MenuType.STONECUTTER, containerId); + this.access = access; + this.level = playerInventory.player.level(); ++ // Paper start ++ this.container = new SimpleContainer(this.createBlockHolder(access), 1) { // Paper - Add missing InventoryHolders ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ StonecutterMenu.this.slotsChanged(this); ++ StonecutterMenu.this.slotUpdateListener.run(); ++ } ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.resultContainer = new ResultContainer(this.createBlockHolder(access)); // Paper - Add missing InventoryHolders ++ // Paper end + this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33)); + this.resultSlot = this.addSlot(new Slot(this.resultContainer, 1, 143, 33) { + @Override +@@ -83,6 +_,7 @@ + }); + this.addStandardInventorySlots(playerInventory, 8, 84); + this.addDataSlot(this.selectedRecipeIndex); ++ this.player = (org.bukkit.entity.Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + public int getSelectedRecipeIndex() { +@@ -103,6 +_,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.STONECUTTER); + } + +@@ -112,8 +_,34 @@ + return false; + } else { + if (this.isValidRecipeIndex(id)) { +- this.selectedRecipeIndex.set(id); +- this.setupResultSlot(id); ++ // Paper start - Add PlayerStonecutterRecipeSelectEvent ++ int recipeIndex = id; ++ this.selectedRecipeIndex.set(recipeIndex); ++ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed ++ paperEventBlock: if (this.isValidRecipeIndex(id)) { ++ final Optional> recipe = this.recipesForInput.entries().get(id).recipe().recipe(); ++ if (recipe.isEmpty()) break paperEventBlock; // The recipe selected does not have an actual server recipe (presumably its the empty one). Cannot call the event, just break. ++ ++ io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent event = new io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent((org.bukkit.entity.Player) player.getBukkitEntity(), getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) recipe.get().toBukkitRecipe()); ++ if (!event.callEvent()) { ++ player.containerMenu.sendAllDataToRemote(); ++ return false; ++ } ++ ++ net.minecraft.resources.ResourceLocation key = org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()); ++ if (!recipe.get().id().location().equals(key)) { // If the recipe did NOT stay the same ++ for (int newRecipeIndex = 0; newRecipeIndex < this.recipesForInput.entries().size(); newRecipeIndex++) { ++ if (this.recipesForInput.entries().get(newRecipeIndex).recipe().recipe().filter(r -> r.id().location().equals(key)).isPresent()) { ++ recipeIndex = newRecipeIndex; ++ break; ++ } ++ } ++ } ++ } ++ player.containerMenu.sendAllDataToRemote(); ++ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it ++ this.setupResultSlot(recipeIndex); ++ // Paper end - Add PlayerStonecutterRecipeSelectEvent + } + + return true; +@@ -131,6 +_,7 @@ + this.input = item.copy(); + this.setupRecipeList(item); + } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent + } + + private void setupRecipeList(ItemStack stack) { diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/TransientCraftingContainer.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/TransientCraftingContainer.java.patch new file mode 100644 index 0000000000..bc3a488239 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/inventory/TransientCraftingContainer.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/inventory/TransientCraftingContainer.java ++++ b/net/minecraft/world/inventory/TransientCraftingContainer.java +@@ -13,6 +_,68 @@ + private final int height; + private final AbstractContainerMenu menu; + ++ // CraftBukkit start - add fields ++ public List transaction = new java.util.ArrayList<>(); ++ private net.minecraft.world.item.crafting.RecipeHolder currentRecipe; ++ public net.minecraft.world.Container resultInventory; ++ private Player owner; ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) { ++ this.transaction.add(who); ++ } ++ ++ public org.bukkit.event.inventory.InventoryType getInvType() { ++ return this.items.size() == 4 ? org.bukkit.event.inventory.InventoryType.CRAFTING : org.bukkit.event.inventory.InventoryType.WORKBENCH; ++ } ++ ++ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) { ++ this.transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return this.transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (this.owner == null) ? null : this.owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return this.maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ this.maxStack = size; ++ this.resultInventory.setMaxStackSize(size); ++ } ++ ++ @Override ++ public org.bukkit.Location getLocation() { ++ return this.menu instanceof CraftingMenu ? ((CraftingMenu) this.menu).access.getLocation() : this.owner.getBukkitEntity().getLocation(); ++ } ++ ++ @Override ++ public net.minecraft.world.item.crafting.RecipeHolder getCurrentRecipe() { ++ return this.currentRecipe; ++ } ++ ++ @Override ++ public void setCurrentRecipe(net.minecraft.world.item.crafting.RecipeHolder currentRecipe) { ++ this.currentRecipe = currentRecipe; ++ } ++ ++ public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height, Player player) { ++ this(menu, width, height); ++ this.owner = player; ++ } ++ // CraftBukkit end ++ + public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height) { + this(menu, width, height, NonNullList.withSize(width * height, ItemStack.EMPTY)); + } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractContainerMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractContainerMenu.java.patch deleted file mode 100644 index a0c2f5bf6b..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractContainerMenu.java.patch +++ /dev/null @@ -1,310 +0,0 @@ ---- a/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -21,6 +21,8 @@ - import net.minecraft.ReportedException; - import net.minecraft.core.NonNullList; - import net.minecraft.core.registries.BuiltInRegistries; -+import net.minecraft.network.chat.Component; -+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; - import net.minecraft.server.level.ServerPlayer; - import net.minecraft.util.Mth; - import net.minecraft.world.Container; -@@ -35,6 +37,18 @@ - import net.minecraft.world.level.block.entity.BlockEntity; - import org.slf4j.Logger; - -+// CraftBukkit start -+import com.google.common.base.Preconditions; -+import java.util.HashMap; -+import java.util.Map; -+import org.bukkit.craftbukkit.inventory.CraftInventory; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.event.Event.Result; -+import org.bukkit.event.inventory.InventoryDragEvent; -+import org.bukkit.event.inventory.InventoryType; -+import org.bukkit.inventory.InventoryView; -+// CraftBukkit end -+ - public abstract class AbstractContainerMenu { - - private static final Logger LOGGER = LogUtils.getLogger(); -@@ -67,6 +81,32 @@ - private ContainerSynchronizer synchronizer; - private boolean suppressRemoteUpdates; - -+ // CraftBukkit start -+ public boolean checkReachable = true; -+ public abstract InventoryView getBukkitView(); -+ public void transferTo(AbstractContainerMenu other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) { -+ InventoryView source = this.getBukkitView(), destination = other.getBukkitView(); -+ ((CraftInventory) source.getTopInventory()).getInventory().onClose(player); -+ ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player); -+ ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player); -+ ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player); -+ } -+ private Component title; -+ public final Component getTitle() { -+ // Paper start - return chat component with empty text instead of throwing error -+ // Preconditions.checkState(this.title != null, "Title not set"); -+ if (this.title == null){ -+ return Component.literal(""); -+ } -+ // Paper end - return chat component with empty text instead of throwing error -+ return this.title; -+ } -+ public final void setTitle(Component title) { -+ Preconditions.checkState(this.title == null, "Title already set"); -+ this.title = title; -+ } -+ // CraftBukkit end -+ - protected AbstractContainerMenu(@Nullable MenuType type, int syncId) { - this.carried = ItemStack.EMPTY; - this.remoteSlots = NonNullList.create(); -@@ -188,10 +228,20 @@ - - if (this.synchronizer != null) { - this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray()); -+ this.synchronizer.sendOffHandSlotChange(); // Paper - Sync offhand slot in menus; update player's offhand since the offhand slot is not added to the slots for menus but can be changed by swapping from a menu slot - } - - } - -+ // CraftBukkit start -+ public void broadcastCarriedItem() { -+ this.remoteCarried = this.getCarried().copy(); -+ if (this.synchronizer != null) { -+ this.synchronizer.sendCarriedChange(this, this.remoteCarried); -+ } -+ } -+ // CraftBukkit end -+ - public void removeSlotListener(ContainerListener listener) { - this.containerListeners.remove(listener); - } -@@ -281,7 +331,7 @@ - while (iterator.hasNext()) { - ContainerListener icrafting = (ContainerListener) iterator.next(); - -- icrafting.slotChanged(this, slot, itemstack2); -+ icrafting.slotChanged(this, slot, itemstack1, itemstack2); // Paper - Add PlayerInventorySlotChangeEvent - } - } - -@@ -410,6 +460,7 @@ - this.resetQuickCraft(); - } - } else if (this.quickcraftStatus == 1) { -+ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks - slot = (Slot) this.slots.get(slotIndex); - itemstack = this.getCarried(); - if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { -@@ -417,7 +468,7 @@ - } - } else if (this.quickcraftStatus == 2) { - if (!this.quickcraftSlots.isEmpty()) { -- if (this.quickcraftSlots.size() == 1) { -+ if (this.quickcraftSlots.size() == 1) { // Paper - Fix CraftBukkit drag system - k = ((Slot) this.quickcraftSlots.iterator().next()).index; - this.resetQuickCraft(); - this.doClick(k, this.quickcraftType, ClickType.PICKUP, player); -@@ -433,6 +484,7 @@ - l = this.getCarried().getCount(); - Iterator iterator = this.quickcraftSlots.iterator(); - -+ Map draggedSlots = new HashMap(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack) - while (iterator.hasNext()) { - Slot slot1 = (Slot) iterator.next(); - ItemStack itemstack2 = this.getCarried(); -@@ -443,12 +495,48 @@ - int l1 = Math.min(AbstractContainerMenu.getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemstack1) + j1, k1); - - l -= l1 - j1; -- slot1.setByPlayer(itemstack1.copyWithCount(l1)); -+ // slot1.setByPlayer(itemstack1.copyWithCount(l1)); -+ draggedSlots.put(slot1.index, itemstack1.copyWithCount(l1)); // CraftBukkit - Put in map instead of setting - } - } - -- itemstack1.setCount(l); -- this.setCarried(itemstack1); -+ // CraftBukkit start - InventoryDragEvent -+ InventoryView view = this.getBukkitView(); -+ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack1); -+ newcursor.setAmount(l); -+ Map eventmap = new HashMap(); -+ for (Map.Entry ditem : draggedSlots.entrySet()) { -+ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); -+ } -+ -+ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory. -+ ItemStack oldCursor = this.getCarried(); -+ this.setCarried(CraftItemStack.asNMSCopy(newcursor)); -+ -+ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); -+ player.level().getCraftServer().getPluginManager().callEvent(event); -+ -+ // Whether or not a change was made to the inventory that requires an update. -+ boolean needsUpdate = event.getResult() != Result.DEFAULT; -+ -+ if (event.getResult() != Result.DENY) { -+ for (Map.Entry dslot : draggedSlots.entrySet()) { -+ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); -+ } -+ // The only time the carried item will be set to null is if the inventory is closed by the server. -+ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early. -+ if (this.getCarried() != null) { -+ this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); -+ needsUpdate = true; -+ } -+ } else { -+ this.setCarried(oldCursor); -+ } -+ -+ if (needsUpdate && player instanceof ServerPlayer) { -+ this.sendAllDataToRemote(); -+ } -+ // CraftBukkit end - } - - this.resetQuickCraft(); -@@ -466,8 +554,11 @@ - if (slotIndex == -999) { - if (!this.getCarried().isEmpty()) { - if (clickaction == ClickAction.PRIMARY) { -- player.drop(this.getCarried(), true); -+ // CraftBukkit start -+ ItemStack carried = this.getCarried(); - this.setCarried(ItemStack.EMPTY); -+ player.drop(carried, true); -+ // CraftBukkit start - } else { - player.drop(this.getCarried().split(1), true); - } -@@ -530,11 +621,21 @@ - } - - slot.setChanged(); -+ // CraftBukkit start - Make sure the client has the right slot contents -+ if (player instanceof ServerPlayer && slot.getMaxStackSize() != 64) { -+ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot.index, slot.getItem())); -+ // Updating a crafting inventory makes the client reset the result slot, have to send it again -+ if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) { -+ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); -+ } -+ } -+ // CraftBukkit end - } - } else { - int j2; - - if (actionType == ClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { -+ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks - ItemStack itemstack4 = playerinventory.getItem(button); - - slot = (Slot) this.slots.get(slotIndex); -@@ -662,8 +763,9 @@ - ItemStack itemstack = this.getCarried(); - - if (!itemstack.isEmpty()) { -+ this.setCarried(ItemStack.EMPTY); // CraftBukkit - SPIGOT-4556 - from below - AbstractContainerMenu.dropOrPlaceInInventory(player, itemstack); -- this.setCarried(ItemStack.EMPTY); -+ // this.setCarried(ItemStack.EMPTY); // CraftBukkit - moved up - } - - } -@@ -729,6 +831,14 @@ - public abstract boolean stillValid(Player player); - - protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean fromLast) { -+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent -+ return this.moveItemStackTo(stack, startIndex, endIndex, fromLast, false); -+ } -+ protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean fromLast, boolean isCheck) { -+ if (isCheck) { -+ stack = stack.copy(); -+ } -+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent - boolean flag1 = false; - int k = startIndex; - -@@ -752,6 +862,11 @@ - - slot = (Slot) this.slots.get(k); - itemstack1 = slot.getItem(); -+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent; clone if only a check -+ if (isCheck) { -+ itemstack1 = itemstack1.copy(); -+ } -+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent - if (!itemstack1.isEmpty() && ItemStack.isSameItemSameComponents(stack, itemstack1)) { - l = itemstack1.getCount() + stack.getCount(); - int i1 = slot.getMaxStackSize(itemstack1); -@@ -759,12 +874,16 @@ - if (l <= i1) { - stack.setCount(0); - itemstack1.setCount(l); -+ if (!isCheck) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent - slot.setChanged(); -+ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent - flag1 = true; - } else if (itemstack1.getCount() < i1) { - stack.shrink(i1 - itemstack1.getCount()); - itemstack1.setCount(i1); -+ if (!isCheck) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent - slot.setChanged(); -+ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent - flag1 = true; - } - } -@@ -795,10 +914,21 @@ - - slot = (Slot) this.slots.get(k); - itemstack1 = slot.getItem(); -+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent -+ if (isCheck) { -+ itemstack1 = itemstack1.copy(); -+ } -+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent - if (itemstack1.isEmpty() && slot.mayPlace(stack)) { - l = slot.getMaxStackSize(stack); -+ // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent -+ if (isCheck) { -+ stack.shrink(Math.min(stack.getCount(), l)); -+ } else { -+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent - slot.setByPlayer(stack.split(Math.min(stack.getCount(), l))); - slot.setChanged(); -+ } // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent - flag1 = true; - break; - } -@@ -893,6 +1023,11 @@ - } - - public ItemStack getCarried() { -+ // CraftBukkit start -+ if (this.carried.isEmpty()) { -+ this.setCarried(ItemStack.EMPTY); -+ } -+ // CraftBukkit end - return this.carried; - } - -@@ -947,4 +1082,15 @@ - this.stateId = this.stateId + 1 & 32767; - return this.stateId; - } -+ -+ // Paper start - Add missing InventoryHolders -+ // The reason this is a supplier, is that the createHolder method uses the bukkit InventoryView#getTopInventory to get the inventory in question -+ // and that can't be obtained safely until the AbstractContainerMenu has been fully constructed. Using a supplier lazily -+ // initializes the InventoryHolder safely. -+ protected final Supplier createBlockHolder(final ContainerLevelAccess context) { -+ //noinspection ConstantValue -+ Preconditions.checkArgument(context != null, "context was null"); -+ return () -> context.createBlockHolder(this); -+ } -+ // Paper end - Add missing InventoryHolders - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractCraftingMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractCraftingMenu.java.patch deleted file mode 100644 index bda213246a..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractCraftingMenu.java.patch +++ /dev/null @@ -1,44 +0,0 @@ ---- a/net/minecraft/world/inventory/AbstractCraftingMenu.java -+++ b/net/minecraft/world/inventory/AbstractCraftingMenu.java -@@ -13,14 +13,17 @@ - - private final int width; - private final int height; -- public final CraftingContainer craftSlots; -+ public final TransientCraftingContainer craftSlots; // CraftBukkit - public final ResultContainer resultSlots = new ResultContainer(); - -- public AbstractCraftingMenu(MenuType type, int syncId, int width, int height) { -- super(type, syncId); -- this.width = width; -- this.height = height; -- this.craftSlots = new TransientCraftingContainer(this, width, height); -+ public AbstractCraftingMenu(MenuType containers, int i, int j, int k, Inventory playerInventory) { // CraftBukkit -+ super(containers, i); -+ this.width = j; -+ this.height = k; -+ // CraftBukkit start -+ this.craftSlots = new TransientCraftingContainer(this, j, k, playerInventory.player); // CraftBukkit - pass player -+ this.craftSlots.resultInventory = this.resultSlots; // CraftBukkit - let InventoryCrafting know about its result slot -+ // CraftBukkit end - } - - protected Slot addResultSlot(Player player, int x, int y) { -@@ -38,7 +41,7 @@ - - @Override - public RecipeBookMenu.PostPlaceAction handlePlacement(boolean craftAll, boolean creative, RecipeHolder recipe, ServerLevel world, Inventory inventory) { -- RecipeHolder recipeholder1 = recipe; -+ RecipeHolder recipeholder1 = (RecipeHolder) recipe; // CraftBukkit - decompile error - - this.beginPlacingRecipe(); - -@@ -65,7 +68,7 @@ - } - }, this.width, this.height, list, list, inventory, recipeholder1, craftAll, creative); - } finally { -- this.finishPlacingRecipe(world, recipe); -+ this.finishPlacingRecipe(world, recipeholder1); // CraftBukkit - decompile error - } - - return containerrecipebook_a; diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch deleted file mode 100644 index 42a568418f..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch +++ /dev/null @@ -1,60 +0,0 @@ ---- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java -+++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java -@@ -17,6 +17,10 @@ - import net.minecraft.world.item.crafting.RecipeType; - import net.minecraft.world.item.crafting.SingleRecipeInput; - import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -+import org.bukkit.craftbukkit.inventory.CraftInventoryFurnace; -+import org.bukkit.craftbukkit.inventory.view.CraftFurnaceView; -+// CraftBukkit end - - public abstract class AbstractFurnaceMenu extends RecipeBookMenu { - -@@ -36,6 +40,22 @@ - private final RecipePropertySet acceptedInputs; - private final RecipeBookType recipeBookType; - -+ // CraftBukkit start -+ private CraftFurnaceView bukkitEntity = null; -+ private Inventory player; -+ -+ @Override -+ public CraftFurnaceView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryFurnace inventory = new CraftInventoryFurnace((AbstractFurnaceBlockEntity) this.container); -+ this.bukkitEntity = new CraftFurnaceView(this.player.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end -+ - protected AbstractFurnaceMenu(MenuType type, RecipeType recipeType, ResourceKey recipePropertySetKey, RecipeBookType category, int syncId, Inventory platerInventory) { - this(type, recipeType, recipePropertySetKey, category, syncId, platerInventory, new SimpleContainer(3), new SimpleContainerData(4)); - } -@@ -53,6 +73,7 @@ - this.addSlot(new Slot(inventory, 0, 56, 17)); - this.addSlot(new FurnaceFuelSlot(this, inventory, 1, 56, 53)); - this.addSlot(new FurnaceResultSlot(platerInventory.player, inventory, 2, 116, 35)); -+ this.player = platerInventory; // CraftBukkit - save player - this.addStandardInventorySlots(platerInventory, 8, 84); - this.addDataSlots(propertyDelegate); - } -@@ -71,6 +92,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return this.container.stillValid(player); - } - -@@ -180,6 +202,6 @@ - public boolean recipeMatches(RecipeHolder entry) { - return ((AbstractCookingRecipe) entry.value()).matches(new SingleRecipeInput(AbstractFurnaceMenu.this.container.getItem(0)), world); - } -- }, 1, 1, List.of(this.getSlot(0)), list, inventory, recipe, craftAll, creative); -+ }, 1, 1, List.of(this.getSlot(0)), list, inventory, (RecipeHolder) recipe, craftAll, creative); // CraftBukkit - decompile error - } - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/BeaconMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/BeaconMenu.java.patch deleted file mode 100644 index 587f354b49..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/BeaconMenu.java.patch +++ /dev/null @@ -1,109 +0,0 @@ ---- a/net/minecraft/world/inventory/BeaconMenu.java -+++ b/net/minecraft/world/inventory/BeaconMenu.java -@@ -8,10 +8,13 @@ - import net.minecraft.world.Container; - import net.minecraft.world.SimpleContainer; - import net.minecraft.world.effect.MobEffect; -+import net.minecraft.world.entity.player.Inventory; - 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.Blocks; -+import org.bukkit.craftbukkit.inventory.view.CraftBeaconView; -+// CraftBukkit end - - public class BeaconMenu extends AbstractContainerMenu { - -@@ -27,6 +30,10 @@ - private final BeaconMenu.PaymentSlot paymentSlot; - private final ContainerLevelAccess access; - private final ContainerData beaconData; -+ // CraftBukkit start -+ private CraftBeaconView bukkitEntity = null; -+ private Inventory player; -+ // CraftBukkit end - - public BeaconMenu(int syncId, Container inventory) { - this(syncId, inventory, new SimpleContainerData(3), ContainerLevelAccess.NULL); -@@ -34,7 +41,8 @@ - - public BeaconMenu(int syncId, Container inventory, ContainerData propertyDelegate, ContainerLevelAccess context) { - super(MenuType.BEACON, syncId); -- this.beacon = new SimpleContainer(this, 1) { -+ this.player = (Inventory) inventory; // CraftBukkit - TODO: check this -+ this.beacon = new SimpleContainer(this.createBlockHolder(context), 1) { // CraftBukkit - decompile error // Paper - Add missing InventoryHolders - @Override - public boolean canPlaceItem(int slot, ItemStack stack) { - return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); -@@ -44,6 +52,12 @@ - public int getMaxStackSize() { - return 1; - } -+ // Paper start - Fix inventories returning null Locations -+ @Override -+ public org.bukkit.Location getLocation() { -+ return context.getLocation(); -+ } -+ // Paper end - Fix inventories returning null Locations - }; - checkContainerDataCount(propertyDelegate, 3); - this.beaconData = propertyDelegate; -@@ -69,6 +83,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return stillValid(this.access, player, Blocks.BEACON); - } - -@@ -148,12 +163,30 @@ - return BeaconMenu.decodeEffect(this.beaconData.get(2)); - } - -+ // Paper start - Add PlayerChangeBeaconEffectEvent -+ private static @Nullable org.bukkit.potion.PotionEffectType convert(Optional> optionalEffect) { -+ return optionalEffect.map(org.bukkit.craftbukkit.potion.CraftPotionEffectType::minecraftHolderToBukkit).orElse(null); -+ } -+ // Paper end - Add PlayerChangeBeaconEffectEvent -+ - public void updateEffects(Optional> primary, Optional> secondary) { -+ // Paper start - fix MC-174630 - validate secondary power -+ if (secondary.isPresent() && secondary.get() != net.minecraft.world.effect.MobEffects.REGENERATION && (primary.isPresent() && secondary.get() != primary.get())) { -+ secondary = Optional.empty(); -+ } -+ // Paper end - if (this.paymentSlot.hasItem()) { -- this.beaconData.set(1, BeaconMenu.encodeEffect((Holder) primary.orElse((Object) null))); -- this.beaconData.set(2, BeaconMenu.encodeEffect((Holder) secondary.orElse((Object) null))); -+ // Paper start - Add PlayerChangeBeaconEffectEvent -+ io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent event = new io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), convert(primary), convert(secondary), this.access.getLocation().getBlock()); -+ if (event.callEvent()) { -+ // Paper end - Add PlayerChangeBeaconEffectEvent -+ this.beaconData.set(1, BeaconMenu.encodeEffect(event.getPrimary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getPrimary())));// CraftBukkit - decompile error -+ this.beaconData.set(2, BeaconMenu.encodeEffect(event.getSecondary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getSecondary())));// CraftBukkit - decompile error -+ if (event.willConsumeItem()) { // Paper - this.paymentSlot.remove(1); -+ } // Paper - this.access.execute(Level::blockEntityChanged); -+ } // Paper end - Add PlayerChangeBeaconEffectEvent - } - - } -@@ -178,4 +211,17 @@ - return 1; - } - } -+ -+ // CraftBukkit start -+ @Override -+ public CraftBeaconView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ org.bukkit.craftbukkit.inventory.CraftInventoryBeacon inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon); -+ this.bukkitEntity = new CraftBeaconView(this.player.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/BrewingStandMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/BrewingStandMenu.java.patch deleted file mode 100644 index 36dcdb7277..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/BrewingStandMenu.java.patch +++ /dev/null @@ -1,127 +0,0 @@ ---- a/net/minecraft/world/inventory/BrewingStandMenu.java -+++ b/net/minecraft/world/inventory/BrewingStandMenu.java -@@ -16,6 +16,10 @@ - import net.minecraft.world.item.alchemy.Potion; - import net.minecraft.world.item.alchemy.PotionBrewing; - import net.minecraft.world.item.alchemy.PotionContents; -+// CraftBukkit start -+import org.bukkit.craftbukkit.inventory.CraftInventoryBrewer; -+import org.bukkit.craftbukkit.inventory.view.CraftBrewingStandView; -+// CraftBukkit end - - public class BrewingStandMenu extends AbstractContainerMenu { - -@@ -35,29 +39,51 @@ - public final ContainerData brewingStandData; - private final Slot ingredientSlot; - -+ // CraftBukkit start -+ private CraftBrewingStandView bukkitEntity = null; -+ private Inventory player; -+ // CraftBukkit end -+ - public BrewingStandMenu(int syncId, Inventory playerInventory) { -- this(syncId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2)); -+ this(syncId, playerInventory, new SimpleContainer(5), new io.papermc.paper.inventory.BrewingSimpleContainerData()); // Paper - Add totalBrewTime - } - - public BrewingStandMenu(int syncId, Inventory playerInventory, Container inventory, ContainerData propertyDelegate) { - super(MenuType.BREWING_STAND, syncId); -+ this.player = playerInventory; // CraftBukkit - checkContainerSize(inventory, 5); -- checkContainerDataCount(propertyDelegate, 2); -+ checkContainerDataCount(propertyDelegate, 3); // Paper - Add recipeBrewTime - this.brewingStand = inventory; - this.brewingStandData = propertyDelegate; - PotionBrewing potionbrewer = playerInventory.player.level().potionBrewing(); - -- this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 0, 56, 51)); -- this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 1, 79, 58)); -- this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 2, 102, 51)); -+ // Paper start - custom potion mixes -+ this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 0, 56, 51, potionbrewer)); -+ this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 1, 79, 58, potionbrewer)); -+ this.addSlot(new BrewingStandMenu.PotionSlot(inventory, 2, 102, 51, potionbrewer)); -+ // Paper end - custom potion mixes - this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(potionbrewer, inventory, 3, 79, 17)); - this.addSlot(new BrewingStandMenu.FuelSlot(inventory, 4, 17, 17)); -- this.addDataSlots(propertyDelegate); -+ // Paper start - Add recipeBrewTime -+ this.addDataSlots(new SimpleContainerData(2) { -+ @Override -+ public int get(final int index) { -+ if (index == 0) return 400 * propertyDelegate.get(index) / propertyDelegate.get(2); -+ return propertyDelegate.get(index); -+ } -+ -+ @Override -+ public void set(final int index, final int value) { -+ propertyDelegate.set(index, value); -+ } -+ }); -+ // Paper end - Add recipeBrewTime - this.addStandardInventorySlots(playerInventory, 8, 84); - } - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return this.brewingStand.stillValid(player); - } - -@@ -79,7 +105,7 @@ - if (!this.moveItemStackTo(itemstack1, 3, 4, false)) { - return ItemStack.EMPTY; - } -- } else if (BrewingStandMenu.PotionSlot.mayPlaceItem(itemstack)) { -+ } else if (BrewingStandMenu.PotionSlot.mayPlaceItem(itemstack, this.player.player.level().potionBrewing())) { // Paper - custom potion mixes - if (!this.moveItemStackTo(itemstack1, 0, 3, false)) { - return ItemStack.EMPTY; - } -@@ -128,13 +154,15 @@ - - private static class PotionSlot extends Slot { - -- public PotionSlot(Container inventory, int index, int x, int y) { -+ private final PotionBrewing potionBrewing; // Paper - custom potion mixes -+ public PotionSlot(Container inventory, int index, int x, int y, PotionBrewing potionBrewing) { // Paper - custom potion mixes - super(inventory, index, x, y); -+ this.potionBrewing = potionBrewing; // Paper - custom potion mixes - } - - @Override - public boolean mayPlace(ItemStack stack) { -- return PotionSlot.mayPlaceItem(stack); -+ return PotionSlot.mayPlaceItem(stack, this.potionBrewing); // Paper - custom potion mixes - } - - @Override -@@ -153,8 +181,8 @@ - super.onTake(player, stack); - } - -- public static boolean mayPlaceItem(ItemStack stack) { -- return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE); -+ public static boolean mayPlaceItem(ItemStack stack, PotionBrewing potionBrewing) { // Paper - custom potion mixes -+ return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || potionBrewing.isCustomInput(stack); // Paper - Custom Potion Mixes - } - - @Override -@@ -198,4 +226,17 @@ - return BrewingStandMenu.EMPTY_SLOT_FUEL; - } - } -+ -+ // CraftBukkit start -+ @Override -+ public CraftBrewingStandView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryBrewer inventory = new CraftInventoryBrewer(this.brewingStand); -+ this.bukkitEntity = new CraftBrewingStandView(this.player.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/CartographyTableMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/CartographyTableMenu.java.patch deleted file mode 100644 index b46cd6b42c..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/CartographyTableMenu.java.patch +++ /dev/null @@ -1,146 +0,0 @@ ---- a/net/minecraft/world/inventory/CartographyTableMenu.java -+++ b/net/minecraft/world/inventory/CartographyTableMenu.java -@@ -6,16 +6,36 @@ - import net.minecraft.world.Container; - import net.minecraft.world.SimpleContainer; - import net.minecraft.world.entity.player.Inventory; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.MapItem; - import net.minecraft.world.item.component.MapPostProcessing; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.saveddata.maps.MapItemSavedData; -+// CraftBukkit start -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.inventory.CraftInventoryCartography; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+import org.bukkit.entity.Player; -+// CraftBukkit end - - public class CartographyTableMenu extends AbstractContainerMenu { - -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity = null; -+ private Player player; -+ -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryCartography inventory = new CraftInventoryCartography(this.container, this.resultContainer); -+ this.bukkitEntity = new CraftInventoryView(this.player, inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - public static final int MAP_SLOT = 0; - public static final int ADDITIONAL_SLOT = 1; - public static final int RESULT_SLOT = 2; -@@ -34,28 +54,42 @@ - - public CartographyTableMenu(int syncId, Inventory inventory, final ContainerLevelAccess context) { - super(MenuType.CARTOGRAPHY_TABLE, syncId); -- this.container = new SimpleContainer(2) { -+ this.container = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders - @Override - public void setChanged() { - CartographyTableMenu.this.slotsChanged(this); - super.setChanged(); - } -+ -+ // CraftBukkit start -+ @Override -+ public Location getLocation() { -+ return context.getLocation(); -+ } -+ // CraftBukkit end - }; -- this.resultContainer = new ResultContainer() { -+ this.resultContainer = new ResultContainer(this.createBlockHolder(context)) { // Paper - Add missing InventoryHolders - @Override - public void setChanged() { -- CartographyTableMenu.this.slotsChanged(this); -+ // CartographyTableMenu.this.slotsChanged(this); // Paper - Add CatographyItemEvent - do not recompute results if the result slot changes - allows to set the result slot via api - super.setChanged(); - } -+ -+ // CraftBukkit start -+ @Override -+ public Location getLocation() { -+ return context.getLocation(); -+ } -+ // CraftBukkit end - }; - this.access = context; -- this.addSlot(new Slot(this, this.container, 0, 15, 15) { -+ this.addSlot(new Slot(this.container, 0, 15, 15) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.has(DataComponents.MAP_ID); - } - }); -- this.addSlot(new Slot(this, this.container, 1, 15, 52) { -+ this.addSlot(new Slot(this.container, 1, 15, 52) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.is(Items.PAPER) || stack.is(Items.MAP) || stack.is(Items.GLASS_PANE); -@@ -68,7 +102,7 @@ - } - - @Override -- public void onTake(Player player, ItemStack stack) { -+ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { - ((Slot) CartographyTableMenu.this.slots.get(0)).remove(1); - ((Slot) CartographyTableMenu.this.slots.get(1)).remove(1); - stack.getItem().onCraftedBy(stack, player.level(), player); -@@ -76,7 +110,7 @@ - long j = world.getGameTime(); - - if (CartographyTableMenu.this.lastSoundTime != j) { -- world.playSound((Player) null, blockposition, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); -+ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); - CartographyTableMenu.this.lastSoundTime = j; - } - -@@ -85,10 +119,12 @@ - } - }); - this.addStandardInventorySlots(inventory, 8, 84); -+ this.player = (Player) inventory.player.getBukkitEntity(); // CraftBukkit - } - - @Override -- public boolean stillValid(Player player) { -+ public boolean stillValid(net.minecraft.world.entity.player.Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return stillValid(this.access, player, Blocks.CARTOGRAPHY_TABLE); - } - -@@ -104,6 +140,7 @@ - this.setupResultSlot(itemstack, itemstack1, itemstack2); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent - } - - private void setupResultSlot(ItemStack map, ItemStack item, ItemStack oldResult) { -@@ -147,7 +184,7 @@ - } - - @Override -- public ItemStack quickMoveStack(Player player, int slot) { -+ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int slot) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot1 = (Slot) this.slots.get(slot); - -@@ -199,7 +236,7 @@ - } - - @Override -- public void removed(Player player) { -+ public void removed(net.minecraft.world.entity.player.Player player) { - super.removed(player); - this.resultContainer.removeItemNoUpdate(2); - this.access.execute((world, blockposition) -> { diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/ChestMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/ChestMenu.java.patch deleted file mode 100644 index 8ba0e1a6a1..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/ChestMenu.java.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- a/net/minecraft/world/inventory/ChestMenu.java -+++ b/net/minecraft/world/inventory/ChestMenu.java -@@ -1,16 +1,43 @@ - package net.minecraft.world.inventory; - -+import net.minecraft.world.CompoundContainer; - import net.minecraft.world.Container; - import net.minecraft.world.SimpleContainer; - import net.minecraft.world.entity.player.Inventory; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; -+import org.bukkit.craftbukkit.inventory.CraftInventory; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+// CraftBukkit end - - public class ChestMenu extends AbstractContainerMenu { - - private final Container container; - private final int containerRows; -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity = null; -+ private Inventory player; - -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventory inventory; -+ if (this.container instanceof Inventory) { -+ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryPlayer((Inventory) this.container); -+ } else if (this.container instanceof CompoundContainer) { -+ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) this.container); -+ } else { -+ inventory = new CraftInventory(this.container); -+ } -+ -+ this.bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end -+ - private ChestMenu(MenuType type, int syncId, Inventory playerInventory, int rows) { - this(type, syncId, playerInventory, new SimpleContainer(9 * rows), rows); - } -@@ -53,6 +80,9 @@ - this.container = inventory; - this.containerRows = rows; - inventory.startOpen(playerInventory.player); -+ // CraftBukkit start - Save player -+ this.player = playerInventory; -+ // CraftBukkit end - boolean flag = true; - - this.addChestGrid(inventory, 8, 18); -@@ -72,6 +102,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return this.container.stillValid(player); - } - diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerListener.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerListener.java.patch deleted file mode 100644 index 7d9e714dfe..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerListener.java.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/net/minecraft/world/inventory/ContainerListener.java -+++ b/net/minecraft/world/inventory/ContainerListener.java -@@ -5,5 +5,11 @@ - public interface ContainerListener { - void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack stack); - -+ // Paper start - Add PlayerInventorySlotChangeEvent -+ default void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack oldStack, ItemStack stack) { -+ slotChanged(handler, slotId, stack); -+ } -+ // Paper end - Add PlayerInventorySlotChangeEvent -+ - void dataChanged(AbstractContainerMenu handler, int property, int value); - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerSynchronizer.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerSynchronizer.java.patch deleted file mode 100644 index a76ea56e99..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/ContainerSynchronizer.java.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/net/minecraft/world/inventory/ContainerSynchronizer.java -+++ b/net/minecraft/world/inventory/ContainerSynchronizer.java -@@ -6,6 +6,7 @@ - public interface ContainerSynchronizer { - void sendInitialData(AbstractContainerMenu handler, NonNullList stacks, ItemStack cursorStack, int[] properties); - -+ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus - void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack); - - void sendCarriedChange(AbstractContainerMenu handler, ItemStack stack); diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/CrafterMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/CrafterMenu.java.patch deleted file mode 100644 index e998f9ae45..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/CrafterMenu.java.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/net/minecraft/world/inventory/CrafterMenu.java -+++ b/net/minecraft/world/inventory/CrafterMenu.java -@@ -10,8 +10,27 @@ - import net.minecraft.world.item.crafting.CraftingRecipe; - import net.minecraft.world.level.block.CrafterBlock; - -+// CraftBukkit start -+import org.bukkit.craftbukkit.inventory.CraftInventoryCrafter; -+import org.bukkit.craftbukkit.inventory.view.CraftCrafterView; -+// CraftBukkit end -+ - public class CrafterMenu extends AbstractContainerMenu implements ContainerListener { - -+ // CraftBukkit start -+ private CraftCrafterView bukkitEntity = null; -+ -+ @Override -+ public CraftCrafterView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryCrafter inventory = new CraftInventoryCrafter(this.container, this.resultContainer); -+ this.bukkitEntity = new CraftCrafterView(this.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - protected static final int SLOT_COUNT = 9; - private static final int INV_SLOT_START = 9; - private static final int INV_SLOT_END = 36; -@@ -106,6 +125,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return this.container.stillValid(player); - } - diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/CraftingContainer.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/CraftingContainer.java.patch deleted file mode 100644 index 0c5babe735..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/CraftingContainer.java.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/net/minecraft/world/inventory/CraftingContainer.java -+++ b/net/minecraft/world/inventory/CraftingContainer.java -@@ -5,6 +5,10 @@ - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.CraftingInput; - -+// CraftBukkit start -+import net.minecraft.world.item.crafting.RecipeHolder; -+// CraftBukkit end -+ - public interface CraftingContainer extends Container, StackedContentsCompatible { - - int getWidth(); -@@ -13,6 +17,15 @@ - - List getItems(); - -+ // CraftBukkit start -+ default RecipeHolder getCurrentRecipe() { -+ return null; -+ } -+ -+ default void setCurrentRecipe(RecipeHolder recipe) { -+ } -+ // CraftBukkit end -+ - default CraftingInput asCraftInput() { - return this.asPositionedCraftInput().input(); - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/CraftingMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/CraftingMenu.java.patch deleted file mode 100644 index 9f0941d40b..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/CraftingMenu.java.patch +++ /dev/null @@ -1,74 +0,0 @@ ---- a/net/minecraft/world/inventory/CraftingMenu.java -+++ b/net/minecraft/world/inventory/CraftingMenu.java -@@ -14,7 +14,11 @@ - import net.minecraft.world.item.crafting.CraftingRecipe; - import net.minecraft.world.item.crafting.RecipeHolder; - import net.minecraft.world.item.crafting.RecipeType; -+import net.minecraft.world.item.crafting.RepairItemRecipe; - import net.minecraft.world.level.block.Blocks; -+import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+// CraftBukkit end - - public class CraftingMenu extends AbstractCraftingMenu { - -@@ -31,13 +35,16 @@ - public final ContainerLevelAccess access; - private final Player player; - private boolean placingRecipe; -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity = null; -+ // CraftBukkit end - - public CraftingMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, ContainerLevelAccess.NULL); - } - - public CraftingMenu(int syncId, Inventory playerInventory, ContainerLevelAccess context) { -- super(MenuType.CRAFTING, syncId, 3, 3); -+ super(MenuType.CRAFTING, syncId, 3, 3, playerInventory); // CraftBukkit - pass player - this.access = context; - this.player = playerInventory.player; - this.addResultSlot(this.player, 124, 35); -@@ -50,6 +57,7 @@ - ServerPlayer entityplayer = (ServerPlayer) player; - ItemStack itemstack = ItemStack.EMPTY; - Optional> optional = world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftinginput, world, recipe); -+ craftingInventory.setCurrentRecipe(optional.orElse(null)); // CraftBukkit - - if (optional.isPresent()) { - RecipeHolder recipeholder1 = (RecipeHolder) optional.get(); -@@ -63,6 +71,7 @@ - } - } - } -+ itemstack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(craftingInventory, resultInventory, itemstack, handler.getBukkitView(), optional.map(RecipeHolder::value).orElse(null) instanceof RepairItemRecipe); // CraftBukkit - - resultInventory.setItem(0, itemstack); - handler.setRemoteSlot(0, itemstack); -@@ -103,6 +112,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return stillValid(this.access, player, Blocks.CRAFTING_TABLE); - } - -@@ -181,4 +191,17 @@ - protected Player owner() { - return this.player; - } -+ -+ // CraftBukkit start -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); -+ this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/DispenserMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/DispenserMenu.java.patch deleted file mode 100644 index 18ed7c2049..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/DispenserMenu.java.patch +++ /dev/null @@ -1,62 +0,0 @@ ---- a/net/minecraft/world/inventory/DispenserMenu.java -+++ b/net/minecraft/world/inventory/DispenserMenu.java -@@ -6,6 +6,11 @@ - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - -+// CraftBukkit start -+import org.bukkit.craftbukkit.inventory.CraftInventory; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+// CraftBukkit end -+ - public class DispenserMenu extends AbstractContainerMenu { - - private static final int SLOT_COUNT = 9; -@@ -14,6 +19,10 @@ - private static final int USE_ROW_SLOT_START = 36; - private static final int USE_ROW_SLOT_END = 45; - public final Container dispenser; -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity = null; -+ private Inventory player; -+ // CraftBukkit end - - public DispenserMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, new SimpleContainer(9)); -@@ -21,6 +30,10 @@ - - public DispenserMenu(int syncId, Inventory playerInventory, Container inventory) { - super(MenuType.GENERIC_3x3, syncId); -+ // CraftBukkit start - Save player -+ this.player = playerInventory; -+ // CraftBukkit end -+ - checkContainerSize(inventory, 9); - this.dispenser = inventory; - inventory.startOpen(playerInventory.player); -@@ -41,6 +54,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return this.dispenser.stillValid(player); - } - -@@ -82,4 +96,17 @@ - super.removed(player); - this.dispenser.stopOpen(player); - } -+ -+ // CraftBukkit start -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventory inventory = new CraftInventory(this.dispenser); -+ this.bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/EnchantmentMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/EnchantmentMenu.java.patch deleted file mode 100644 index 531e6792cc..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/EnchantmentMenu.java.patch +++ /dev/null @@ -1,270 +0,0 @@ ---- a/net/minecraft/world/inventory/EnchantmentMenu.java -+++ b/net/minecraft/world/inventory/EnchantmentMenu.java -@@ -21,7 +21,6 @@ - import net.minecraft.world.Container; - import net.minecraft.world.SimpleContainer; - import net.minecraft.world.entity.player.Inventory; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.Enchantment; -@@ -29,6 +28,18 @@ - import net.minecraft.world.item.enchantment.EnchantmentInstance; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.EnchantingTableBlock; -+// CraftBukkit start -+import java.util.Map; -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.enchantments.CraftEnchantment; -+import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.craftbukkit.inventory.view.CraftEnchantmentView; -+import org.bukkit.enchantments.EnchantmentOffer; -+import org.bukkit.event.enchantment.EnchantItemEvent; -+import org.bukkit.event.enchantment.PrepareItemEnchantEvent; -+import org.bukkit.entity.Player; -+// CraftBukkit end - - public class EnchantmentMenu extends AbstractContainerMenu { - -@@ -40,6 +51,10 @@ - public final int[] costs; - public final int[] enchantClue; - public final int[] levelClue; -+ // CraftBukkit start -+ private CraftEnchantmentView bukkitEntity = null; -+ private Player player; -+ // CraftBukkit end - - public EnchantmentMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, ContainerLevelAccess.NULL); -@@ -47,12 +62,19 @@ - - public EnchantmentMenu(int syncId, Inventory playerInventory, ContainerLevelAccess context) { - super(MenuType.ENCHANTMENT, syncId); -- this.enchantSlots = new SimpleContainer(2) { -+ this.enchantSlots = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders - @Override - public void setChanged() { - super.setChanged(); - EnchantmentMenu.this.slotsChanged(this); - } -+ -+ // CraftBukkit start -+ @Override -+ public Location getLocation() { -+ return context.getLocation(); -+ } -+ // CraftBukkit end - }; - this.random = RandomSource.create(); - this.enchantmentSeed = DataSlot.standalone(); -@@ -60,13 +82,13 @@ - this.enchantClue = new int[]{-1, -1, -1}; - this.levelClue = new int[]{-1, -1, -1}; - this.access = context; -- this.addSlot(new Slot(this, this.enchantSlots, 0, 15, 47) { -+ this.addSlot(new Slot(this.enchantSlots, 0, 15, 47) { // CraftBukkit - decompile error - @Override - public int getMaxStackSize() { - return 1; - } - }); -- this.addSlot(new Slot(this, this.enchantSlots, 1, 35, 47) { -+ this.addSlot(new Slot(this.enchantSlots, 1, 35, 47) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.is(Items.LAPIS_LAZULI); -@@ -88,6 +110,9 @@ - this.addDataSlot(DataSlot.shared(this.levelClue, 0)); - this.addDataSlot(DataSlot.shared(this.levelClue, 1)); - this.addDataSlot(DataSlot.shared(this.levelClue, 2)); -+ // CraftBukkit start -+ this.player = (Player) playerInventory.player.getBukkitEntity(); -+ // CraftBukkit end - } - - @Override -@@ -95,7 +120,7 @@ - if (inventory == this.enchantSlots) { - ItemStack itemstack = inventory.getItem(0); - -- if (!itemstack.isEmpty() && itemstack.isEnchantable()) { -+ if (!itemstack.isEmpty()) { // CraftBukkit - relax condition - this.access.execute((world, blockposition) -> { - IdMap> registry = world.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).asHolderIdMap(); - int i = 0; -@@ -135,6 +160,41 @@ - } - } - -+ // CraftBukkit start -+ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); -+ org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; -+ for (j = 0; j < 3; ++j) { -+ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? CraftEnchantment.minecraftHolderToBukkit(registry.byId(this.enchantClue[j])) : null; -+ offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; -+ } -+ -+ PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(this.player, this.getBukkitView(), this.access.getLocation().getBlock(), item, offers, i); -+ event.setCancelled(!itemstack.isEnchantable()); -+ world.getCraftServer().getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ for (j = 0; j < 3; ++j) { -+ this.costs[j] = 0; -+ this.enchantClue[j] = -1; -+ this.levelClue[j] = -1; -+ } -+ return; -+ } -+ -+ for (j = 0; j < 3; j++) { -+ EnchantmentOffer offer = event.getOffers()[j]; -+ if (offer != null) { -+ this.costs[j] = offer.getCost(); -+ this.enchantClue[j] = registry.getId(CraftEnchantment.bukkitToMinecraftHolder(offer.getEnchantment())); -+ this.levelClue[j] = offer.getEnchantmentLevel(); -+ } else { -+ this.costs[j] = 0; -+ this.enchantClue[j] = -1; -+ this.levelClue[j] = -1; -+ } -+ } -+ // CraftBukkit end -+ - this.broadcastChanges(); - }); - } else { -@@ -149,7 +209,7 @@ - } - - @Override -- public boolean clickMenuButton(Player player, int id) { -+ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - if (id >= 0 && id < this.costs.length) { - ItemStack itemstack = this.enchantSlots.getItem(0); - ItemStack itemstack1 = this.enchantSlots.getItem(1); -@@ -159,24 +219,55 @@ - return false; - } else if (this.costs[id] > 0 && !itemstack.isEmpty() && (player.experienceLevel >= j && player.experienceLevel >= this.costs[id] || player.getAbilities().instabuild)) { - this.access.execute((world, blockposition) -> { -- ItemStack itemstack2 = itemstack; -+ ItemStack itemstack2 = itemstack; // Paper - diff on change - List list = this.getEnchantmentList(world.registryAccess(), itemstack, id, this.costs[id]); - -- if (!list.isEmpty()) { -- player.onEnchantmentPerformed(itemstack, j); -- if (itemstack.is(Items.BOOK)) { -- itemstack2 = itemstack.transmuteCopy(Items.ENCHANTED_BOOK); -- this.enchantSlots.setItem(0, itemstack2); -+ // CraftBukkit start -+ IdMap> registry = world.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).asHolderIdMap(); -+ if (true || !list.isEmpty()) { -+ // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down -+ Map enchants = new java.util.HashMap(); -+ for (EnchantmentInstance instance : list) { -+ enchants.put(CraftEnchantment.minecraftHolderToBukkit(instance.enchantment), instance.level); - } -+ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); - -- Iterator iterator = list.iterator(); -+ org.bukkit.enchantments.Enchantment hintedEnchantment = CraftEnchantment.minecraftHolderToBukkit(registry.byId(this.enchantClue[id])); -+ int hintedEnchantmentLevel = this.levelClue[id]; -+ EnchantItemEvent event = new EnchantItemEvent((Player) player.getBukkitEntity(), this.getBukkitView(), this.access.getLocation().getBlock(), item, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id); -+ world.getCraftServer().getPluginManager().callEvent(event); - -- while (iterator.hasNext()) { -- EnchantmentInstance weightedrandomenchant = (EnchantmentInstance) iterator.next(); -+ int level = event.getExpLevelCost(); -+ if (event.isCancelled() || (level > player.experienceLevel && !player.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { -+ return; -+ } -+ // CraftBukkit end -+ // Paper start -+ itemstack2 = org.bukkit.craftbukkit.inventory.CraftItemStack.getOrCloneOnMutation(item, event.getItem()); -+ if (itemstack2 != itemstack) { -+ this.enchantSlots.setItem(0, itemstack2); -+ } -+ if (itemstack2.is(Items.BOOK)) { -+ itemstack2 = itemstack2.transmuteCopy(Items.ENCHANTED_BOOK); -+ this.enchantSlots.setItem(0, itemstack2); -+ } -+ // Paper end - -+ // CraftBukkit start -+ for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { -+ Holder nms = CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()); -+ if (nms == null) { -+ continue; -+ } -+ -+ EnchantmentInstance weightedrandomenchant = new EnchantmentInstance(nms, entry.getValue()); - itemstack2.enchant(weightedrandomenchant.enchantment, weightedrandomenchant.level); - } - -+ player.onEnchantmentPerformed(itemstack, j); -+ // CraftBukkit end -+ -+ // CraftBukkit - TODO: let plugins change this - itemstack1.consume(j, player); - if (itemstack1.isEmpty()) { - this.enchantSlots.setItem(1, ItemStack.EMPTY); -@@ -190,7 +281,7 @@ - this.enchantSlots.setChanged(); - this.enchantmentSeed.set(player.getEnchantmentSeed()); - this.slotsChanged(this.enchantSlots); -- world.playSound((Player) null, blockposition, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.1F + 0.9F); -+ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.1F + 0.9F); - } - - }); -@@ -234,7 +325,7 @@ - } - - @Override -- public void removed(Player player) { -+ public void removed(net.minecraft.world.entity.player.Player player) { - super.removed(player); - this.access.execute((world, blockposition) -> { - this.clearContainer(player, this.enchantSlots); -@@ -242,12 +333,13 @@ - } - - @Override -- public boolean stillValid(Player player) { -+ public boolean stillValid(net.minecraft.world.entity.player.Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return stillValid(this.access, player, Blocks.ENCHANTING_TABLE); - } - - @Override -- public ItemStack quickMoveStack(Player player, int slot) { -+ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int slot) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot1 = (Slot) this.slots.get(slot); - -@@ -293,4 +385,23 @@ - - return itemstack; - } -+ -+ // CraftBukkit start -+ @Override -+ public CraftEnchantmentView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryEnchanting inventory = new CraftInventoryEnchanting(this.enchantSlots); -+ this.bukkitEntity = new CraftEnchantmentView(this.player, inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end -+ -+ // Paper start - add enchantment seed update API -+ public void setEnchantmentSeed(int seed) { -+ this.enchantmentSeed.set(seed); -+ } -+ // Paper end - add enchantment seed update API - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/FurnaceResultSlot.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/FurnaceResultSlot.java.patch deleted file mode 100644 index 488614cbf6..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/FurnaceResultSlot.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/net/minecraft/world/inventory/FurnaceResultSlot.java -+++ b/net/minecraft/world/inventory/FurnaceResultSlot.java -@@ -51,7 +51,7 @@ - Container iinventory = this.container; - - if (iinventory instanceof AbstractFurnaceBlockEntity tileentityfurnace) { -- tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer); -+ tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer, stack, this.removeCount); // CraftBukkit - } - } - diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/GrindstoneMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/GrindstoneMenu.java.patch deleted file mode 100644 index 0ba3910b94..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/GrindstoneMenu.java.patch +++ /dev/null @@ -1,141 +0,0 @@ ---- a/net/minecraft/world/inventory/GrindstoneMenu.java -+++ b/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -10,7 +10,6 @@ - import net.minecraft.world.SimpleContainer; - import net.minecraft.world.entity.ExperienceOrb; - import net.minecraft.world.entity.player.Inventory; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.Enchantment; -@@ -19,9 +18,30 @@ - import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.phys.Vec3; -+// CraftBukkit start -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+import org.bukkit.entity.Player; -+// CraftBukkit end - - public class GrindstoneMenu extends AbstractContainerMenu { - -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity = null; -+ private Player player; -+ -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryGrindstone inventory = new CraftInventoryGrindstone(this.repairSlots, this.resultSlots); -+ this.bukkitEntity = new CraftInventoryView(this.player, inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - public static final int MAX_NAME_LENGTH = 35; - public static final int INPUT_SLOT = 0; - public static final int ADDITIONAL_SLOT = 1; -@@ -40,22 +60,29 @@ - - public GrindstoneMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { - super(MenuType.GRINDSTONE, syncId); -- this.resultSlots = new ResultContainer(); -- this.repairSlots = new SimpleContainer(2) { -+ this.resultSlots = new ResultContainer(this.createBlockHolder(context)); // Paper - Add missing InventoryHolders -+ this.repairSlots = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders - @Override - public void setChanged() { - super.setChanged(); - GrindstoneMenu.this.slotsChanged(this); - } -+ -+ // CraftBukkit start -+ @Override -+ public Location getLocation() { -+ return context.getLocation(); -+ } -+ // CraftBukkit end - }; - this.access = context; -- this.addSlot(new Slot(this, this.repairSlots, 0, 49, 19) { -+ this.addSlot(new Slot(this.repairSlots, 0, 49, 19) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.isDamageableItem() || EnchantmentHelper.hasAnyEnchantments(stack); - } - }); -- this.addSlot(new Slot(this, this.repairSlots, 1, 49, 40) { -+ this.addSlot(new Slot(this.repairSlots, 1, 49, 40) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.isDamageableItem() || EnchantmentHelper.hasAnyEnchantments(stack); -@@ -68,10 +95,14 @@ - } - - @Override -- public void onTake(Player player, ItemStack stack) { -+ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { - context.execute((world, blockposition) -> { - if (world instanceof ServerLevel) { -- ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), this.getExperienceAmount(world)); -+ // Paper start - Fire BlockExpEvent on grindstone use -+ org.bukkit.event.block.BlockExpEvent event = new org.bukkit.event.block.BlockExpEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition), this.getExperienceAmount(world)); -+ event.callEvent(); -+ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), event.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); -+ // Paper end - Fire BlockExpEvent on grindstone use - } - - world.levelEvent(1042, blockposition, 0); -@@ -113,6 +144,7 @@ - } - }); - this.addStandardInventorySlots(playerInventory, 8, 84); -+ this.player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit - } - - @Override -@@ -120,12 +152,14 @@ - super.slotsChanged(inventory); - if (inventory == this.repairSlots) { - this.createResult(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent - } - - } - - private void createResult() { -- this.resultSlots.setItem(0, this.computeResult(this.repairSlots.getItem(0), this.repairSlots.getItem(1))); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(this.getBukkitView(), this.computeResult(this.repairSlots.getItem(0), this.repairSlots.getItem(1))); // CraftBukkit -+ this.sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client - this.broadcastChanges(); - } - -@@ -218,7 +252,7 @@ - } - - @Override -- public void removed(Player player) { -+ public void removed(net.minecraft.world.entity.player.Player player) { - super.removed(player); - this.access.execute((world, blockposition) -> { - this.clearContainer(player, this.repairSlots); -@@ -226,12 +260,13 @@ - } - - @Override -- public boolean stillValid(Player player) { -+ public boolean stillValid(net.minecraft.world.entity.player.Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return stillValid(this.access, player, Blocks.GRINDSTONE); - } - - @Override -- public ItemStack quickMoveStack(Player player, int slot) { -+ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int slot) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot1 = (Slot) this.slots.get(slot); - diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/HopperMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/HopperMenu.java.patch deleted file mode 100644 index 2174c38e81..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/HopperMenu.java.patch +++ /dev/null @@ -1,51 +0,0 @@ ---- a/net/minecraft/world/inventory/HopperMenu.java -+++ b/net/minecraft/world/inventory/HopperMenu.java -@@ -6,11 +6,32 @@ - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - -+// CraftBukkit start -+import org.bukkit.craftbukkit.inventory.CraftInventory; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+// CraftBukkit end -+ - public class HopperMenu extends AbstractContainerMenu { - - public static final int CONTAINER_SIZE = 5; - private final Container hopper; - -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity = null; -+ private Inventory player; -+ -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventory inventory = new CraftInventory(this.hopper); -+ this.bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end -+ - public HopperMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, new SimpleContainer(5)); - } -@@ -18,6 +39,7 @@ - public HopperMenu(int syncId, Inventory playerInventory, Container inventory) { - super(MenuType.HOPPER, syncId); - this.hopper = inventory; -+ this.player = playerInventory; // CraftBukkit - save player - checkContainerSize(inventory, 5); - inventory.startOpen(playerInventory.player); - -@@ -30,6 +52,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return this.hopper.stillValid(player); - } - diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/HorseInventoryMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/HorseInventoryMenu.java.patch deleted file mode 100644 index 2657cf4ccb..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/HorseInventoryMenu.java.patch +++ /dev/null @@ -1,53 +0,0 @@ ---- a/net/minecraft/world/inventory/HorseInventoryMenu.java -+++ b/net/minecraft/world/inventory/HorseInventoryMenu.java -@@ -11,6 +11,11 @@ - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - -+// CraftBukkit start -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+import org.bukkit.inventory.InventoryView; -+// CraftBukkit end -+ - public class HorseInventoryMenu extends AbstractContainerMenu { - - static final ResourceLocation SADDLE_SLOT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot/saddle"); -@@ -22,13 +27,28 @@ - public static final int SLOT_BODY_ARMOR = 1; - private static final int SLOT_HORSE_INVENTORY_START = 2; - -+ // CraftBukkit start -+ org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; -+ Inventory player; -+ -+ @Override -+ public InventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ return this.bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), this.horseContainer.getOwner().getInventory(), this); -+ } -+ - public HorseInventoryMenu(int syncId, Inventory playerInventory, Container inventory, final AbstractHorse entity, int slotColumnCount) { - super((MenuType) null, syncId); -+ this.player = playerInventory; -+ // CraftBukkit end - this.horseContainer = inventory; - this.armorContainer = entity.getBodyArmorAccess(); - this.horse = entity; - inventory.startOpen(playerInventory.player); -- this.addSlot(new Slot(this, inventory, 0, 8, 18) { -+ this.addSlot(new Slot(inventory, 0, 8, 18) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.is(Items.SADDLE) && !this.hasItem() && entity.isSaddleable(); -@@ -46,7 +66,7 @@ - }); - ResourceLocation minecraftkey = entity instanceof Llama ? HorseInventoryMenu.LLAMA_ARMOR_SLOT_SPRITE : HorseInventoryMenu.ARMOR_SLOT_SPRITE; - -- this.addSlot(new ArmorSlot(this, this.armorContainer, entity, EquipmentSlot.BODY, 0, 8, 36, minecraftkey) { -+ this.addSlot(new ArmorSlot(this.armorContainer, entity, EquipmentSlot.BODY, 0, 8, 36, minecraftkey) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return entity.isEquippableInSlot(stack, EquipmentSlot.BODY); diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/InventoryMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/InventoryMenu.java.patch deleted file mode 100644 index 78a5d31f7d..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/InventoryMenu.java.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- a/net/minecraft/world/inventory/InventoryMenu.java -+++ b/net/minecraft/world/inventory/InventoryMenu.java -@@ -2,6 +2,7 @@ - - import java.util.List; - import java.util.Map; -+import net.minecraft.network.chat.Component; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.Container; -@@ -11,6 +12,9 @@ - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.RecipeHolder; - import net.minecraft.world.level.Level; -+import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+// CraftBukkit end - - public class InventoryMenu extends AbstractCraftingMenu { - -@@ -38,9 +42,15 @@ - private static final EquipmentSlot[] SLOT_IDS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; - public final boolean active; - private final Player owner; -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity = null; -+ // CraftBukkit end - - public InventoryMenu(Inventory inventory, boolean onServer, final Player owner) { -- super((MenuType) null, 0, 2, 2); -+ // CraftBukkit start -+ super((MenuType) null, 0, 2, 2, inventory); // CraftBukkit - save player -+ this.setTitle(Component.translatable("container.crafting")); // SPIGOT-4722: Allocate title for player inventory -+ // CraftBukkit end - this.active = onServer; - this.owner = owner; - this.addResultSlot(owner, 154, 28); -@@ -54,7 +64,7 @@ - } - - this.addStandardInventorySlots(inventory, 8, 84); -- this.addSlot(new Slot(this, inventory, 40, 77, 62) { -+ this.addSlot(new Slot(inventory, 40, 77, 62) { // CraftBukkit - decompile error - @Override - public void setByPlayer(ItemStack stack, ItemStack previousStack) { - owner.onEquipItem(EquipmentSlot.OFFHAND, previousStack, stack); -@@ -190,4 +200,17 @@ - protected Player owner() { - return this.owner; - } -+ -+ // CraftBukkit start -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); -+ this.bukkitEntity = new CraftInventoryView(this.owner.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/LecternMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/LecternMenu.java.patch deleted file mode 100644 index 667c188455..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/LecternMenu.java.patch +++ /dev/null @@ -1,143 +0,0 @@ ---- a/net/minecraft/world/inventory/LecternMenu.java -+++ b/net/minecraft/world/inventory/LecternMenu.java -@@ -2,11 +2,33 @@ - - import net.minecraft.world.Container; - import net.minecraft.world.SimpleContainer; --import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.entity.player.Inventory; - import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.entity.LecternBlockEntity.LecternInventory; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.inventory.CraftInventoryLectern; -+import org.bukkit.craftbukkit.inventory.view.CraftLecternView; -+import org.bukkit.entity.Player; -+import org.bukkit.event.player.PlayerTakeLecternBookEvent; -+// CraftBukkit end - - public class LecternMenu extends AbstractContainerMenu { - -+ // CraftBukkit start -+ private CraftLecternView bukkitEntity = null; -+ private Player player; -+ -+ @Override -+ public CraftLecternView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryLectern inventory = new CraftInventoryLectern(this.lectern); -+ this.bukkitEntity = new CraftLecternView(this.player, inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - private static final int DATA_COUNT = 1; - private static final int SLOT_COUNT = 1; - public static final int BUTTON_PREV_PAGE = 1; -@@ -16,29 +38,33 @@ - private final Container lectern; - private final ContainerData lecternData; - -- public LecternMenu(int syncId) { -- this(syncId, new SimpleContainer(1), new SimpleContainerData(1)); -+ // CraftBukkit start - add player -+ public LecternMenu(int i, Inventory playerinventory) { -+ this(i, new SimpleContainer(1), new SimpleContainerData(1), playerinventory); - } - -- public LecternMenu(int syncId, Container inventory, ContainerData propertyDelegate) { -- super(MenuType.LECTERN, syncId); -- checkContainerSize(inventory, 1); -- checkContainerDataCount(propertyDelegate, 1); -- this.lectern = inventory; -- this.lecternData = propertyDelegate; -- this.addSlot(new Slot(inventory, 0, 0, 0) { -+ public LecternMenu(int i, Container iinventory, ContainerData icontainerproperties, Inventory playerinventory) { -+ // CraftBukkit end -+ super(MenuType.LECTERN, i); -+ checkContainerSize(iinventory, 1); -+ checkContainerDataCount(icontainerproperties, 1); -+ this.lectern = iinventory; -+ this.lecternData = icontainerproperties; -+ this.addSlot(new Slot(iinventory, 0, 0, 0) { - @Override - public void setChanged() { - super.setChanged(); - LecternMenu.this.slotsChanged(this.container); - } - }); -- this.addDataSlots(propertyDelegate); -+ this.addDataSlots(icontainerproperties); -+ this.player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit - } - - @Override -- public boolean clickMenuButton(Player player, int id) { -+ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - int j; -+ io.papermc.paper.event.player.PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper - Add PlayerLecternPageChangeEvent - - if (id >= 100) { - j = id - 100; -@@ -48,17 +74,38 @@ - switch (id) { - case 1: - j = this.lecternData.get(0); -- this.setData(0, j - 1); -+ // Paper start - Add PlayerLecternPageChangeEvent -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - Add PlayerLecternPageChangeEvent - return true; - case 2: - j = this.lecternData.get(0); -- this.setData(0, j + 1); -+ // Paper start - Add PlayerLecternPageChangeEvent -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - Add PlayerLecternPageChangeEvent - return true; - case 3: - if (!player.mayBuild()) { - return false; - } - -+ // CraftBukkit start - Event for taking the book -+ PlayerTakeLecternBookEvent event = new PlayerTakeLecternBookEvent(this.player, ((CraftInventoryLectern) this.getBukkitView().getTopInventory()).getHolder()); -+ Bukkit.getServer().getPluginManager().callEvent(event); -+ if (event.isCancelled()) { -+ return false; -+ } -+ // CraftBukkit end - ItemStack itemstack = this.lectern.removeItemNoUpdate(0); - - this.lectern.setChanged(); -@@ -74,7 +121,7 @@ - } - - @Override -- public ItemStack quickMoveStack(Player player, int slot) { -+ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int slot) { - return ItemStack.EMPTY; - } - -@@ -85,7 +132,9 @@ - } - - @Override -- public boolean stillValid(Player player) { -+ public boolean stillValid(net.minecraft.world.entity.player.Player player) { -+ if (this.lectern instanceof LecternInventory && !((LecternInventory) this.lectern).getLectern().hasBook()) return false; // CraftBukkit -+ if (!this.checkReachable) return true; // CraftBukkit - return this.lectern.stillValid(player); - } - diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/LoomMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/LoomMenu.java.patch deleted file mode 100644 index 1d534db5e0..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/LoomMenu.java.patch +++ /dev/null @@ -1,203 +0,0 @@ ---- a/net/minecraft/world/inventory/LoomMenu.java -+++ b/net/minecraft/world/inventory/LoomMenu.java -@@ -12,7 +12,6 @@ - import net.minecraft.world.Container; - import net.minecraft.world.SimpleContainer; - import net.minecraft.world.entity.player.Inventory; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.BannerItem; - import net.minecraft.world.item.BannerPatternItem; - import net.minecraft.world.item.DyeColor; -@@ -22,9 +21,30 @@ - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.BannerPattern; - import net.minecraft.world.level.block.entity.BannerPatternLayers; -+// CraftBukkit start -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; -+import org.bukkit.craftbukkit.inventory.view.CraftLoomView; -+import org.bukkit.entity.Player; -+// CraftBukkit end - - public class LoomMenu extends AbstractContainerMenu { - -+ // CraftBukkit start -+ private CraftLoomView bukkitEntity = null; -+ private Player player; -+ -+ @Override -+ public CraftLoomView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryLoom inventory = new CraftInventoryLoom(this.inputContainer, this.outputContainer); -+ this.bukkitEntity = new CraftLoomView(this.player, inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - private static final int PATTERN_NOT_SET = -1; - private static final int INV_SLOT_START = 4; - private static final int INV_SLOT_END = 31; -@@ -53,35 +73,49 @@ - this.selectablePatterns = List.of(); - this.slotUpdateListener = () -> { - }; -- this.inputContainer = new SimpleContainer(3) { -+ this.inputContainer = new SimpleContainer(this.createBlockHolder(context), 3) { // Paper - Add missing InventoryHolders - @Override - public void setChanged() { - super.setChanged(); - LoomMenu.this.slotsChanged(this); - LoomMenu.this.slotUpdateListener.run(); - } -+ -+ // CraftBukkit start -+ @Override -+ public Location getLocation() { -+ return context.getLocation(); -+ } -+ // CraftBukkit end - }; -- this.outputContainer = new SimpleContainer(1) { -+ this.outputContainer = new SimpleContainer(this.createBlockHolder(context), 1) { // Paper - Add missing InventoryHolders - @Override - public void setChanged() { - super.setChanged(); - LoomMenu.this.slotUpdateListener.run(); - } -+ -+ // CraftBukkit start -+ @Override -+ public Location getLocation() { -+ return context.getLocation(); -+ } -+ // CraftBukkit end - }; - this.access = context; -- this.bannerSlot = this.addSlot(new Slot(this, this.inputContainer, 0, 13, 26) { -+ this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.getItem() instanceof BannerItem; - } - }); -- this.dyeSlot = this.addSlot(new Slot(this, this.inputContainer, 1, 33, 26) { -+ this.dyeSlot = this.addSlot(new Slot(this.inputContainer, 1, 33, 26) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.getItem() instanceof DyeItem; - } - }); -- this.patternSlot = this.addSlot(new Slot(this, this.inputContainer, 2, 23, 45) { -+ this.patternSlot = this.addSlot(new Slot(this.inputContainer, 2, 23, 45) { // CraftBukkit - decompile error - @Override - public boolean mayPlace(ItemStack stack) { - return stack.getItem() instanceof BannerPatternItem; -@@ -94,7 +128,7 @@ - } - - @Override -- public void onTake(Player player, ItemStack stack) { -+ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { - LoomMenu.this.bannerSlot.remove(1); - LoomMenu.this.dyeSlot.remove(1); - if (!LoomMenu.this.bannerSlot.hasItem() || !LoomMenu.this.dyeSlot.hasItem()) { -@@ -105,7 +139,7 @@ - long j = world.getGameTime(); - - if (LoomMenu.this.lastSoundTime != j) { -- world.playSound((Player) null, blockposition, SoundEvents.UI_LOOM_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); -+ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_LOOM_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); - LoomMenu.this.lastSoundTime = j; - } - -@@ -116,18 +150,44 @@ - this.addStandardInventorySlots(playerInventory, 8, 84); - this.addDataSlot(this.selectedBannerPatternIndex); - this.patternGetter = playerInventory.player.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN); -+ this.player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit - } - - @Override -- public boolean stillValid(Player player) { -+ public boolean stillValid(net.minecraft.world.entity.player.Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return stillValid(this.access, player, Blocks.LOOM); - } - - @Override -- public boolean clickMenuButton(Player player, int id) { -+ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - if (id >= 0 && id < this.selectablePatterns.size()) { -- this.selectedBannerPatternIndex.set(id); -- this.setupResultSlot((Holder) this.selectablePatterns.get(id)); -+ // Paper start - Add PlayerLoomPatternSelectEvent -+ int selectablePatternIndex = id; -+ io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.craftbukkit.block.banner.CraftPatternType.minecraftHolderToBukkit(this.selectablePatterns.get(selectablePatternIndex))); -+ if (!event.callEvent()) { -+ player.containerMenu.sendAllDataToRemote(); -+ return false; -+ } -+ final Holder eventPattern = org.bukkit.craftbukkit.block.banner.CraftPatternType.bukkitToMinecraftHolder(event.getPatternType()); -+ Holder selectedPattern = null; -+ for (int i = 0; i < this.selectablePatterns.size(); i++) { -+ final Holder holder = this.selectablePatterns.get(i); -+ if (eventPattern.equals(holder)) { -+ selectablePatternIndex = i; -+ selectedPattern = holder; -+ break; -+ } -+ } -+ if (selectedPattern == null) { -+ selectedPattern = eventPattern; -+ selectablePatternIndex = -1; -+ } -+ -+ player.containerMenu.sendAllDataToRemote(); -+ this.selectedBannerPatternIndex.set(selectablePatternIndex); -+ this.setupResultSlot(java.util.Objects.requireNonNull(selectedPattern, "selectedPattern was null, this is unexpected")); -+ // Paper end - Add PlayerLoomPatternSelectEvent - return true; - } else { - return false; -@@ -201,7 +261,8 @@ - this.resultSlot.set(ItemStack.EMPTY); - } - -- this.broadcastChanges(); -+ // this.broadcastChanges(); // Paper - Add PrepareResultEvent; done below -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper - Add PrepareResultEvent - } else { - this.resultSlot.set(ItemStack.EMPTY); - this.selectablePatterns = List.of(); -@@ -222,7 +283,7 @@ - } - - @Override -- public ItemStack quickMoveStack(Player player, int slot) { -+ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int slot) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot1 = (Slot) this.slots.get(slot); - -@@ -277,7 +338,7 @@ - } - - @Override -- public void removed(Player player) { -+ public void removed(net.minecraft.world.entity.player.Player player) { - super.removed(player); - this.access.execute((world, blockposition) -> { - this.clearContainer(player, this.inputContainer); -@@ -294,6 +355,11 @@ - DyeColor enumcolor = ((DyeItem) itemstack1.getItem()).getDyeColor(); - - itemstack2.update(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY, (bannerpatternlayers) -> { -+ // CraftBukkit start -+ if (bannerpatternlayers.layers().size() > 20) { -+ bannerpatternlayers = new BannerPatternLayers(List.copyOf(bannerpatternlayers.layers().subList(0, 20))); -+ } -+ // CraftBukkit end - return (new BannerPatternLayers.Builder()).addAll(bannerpatternlayers).add(pattern, enumcolor).build(); - }); - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/MenuType.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/MenuType.java.patch deleted file mode 100644 index ac3dc03175..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/MenuType.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/net/minecraft/world/inventory/MenuType.java -+++ b/net/minecraft/world/inventory/MenuType.java -@@ -28,7 +28,7 @@ - public static final MenuType GRINDSTONE = MenuType.register("grindstone", GrindstoneMenu::new); - public static final MenuType HOPPER = MenuType.register("hopper", HopperMenu::new); - public static final MenuType LECTERN = MenuType.register("lectern", (i, playerinventory) -> { -- return new LecternMenu(i); -+ return new LecternMenu(i, playerinventory); // CraftBukkit - }); - public static final MenuType LOOM = MenuType.register("loom", LoomMenu::new); - public static final MenuType MERCHANT = MenuType.register("merchant", MerchantMenu::new); diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantContainer.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantContainer.java.patch deleted file mode 100644 index 82bbe5e4c7..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantContainer.java.patch +++ /dev/null @@ -1,70 +0,0 @@ ---- a/net/minecraft/world/inventory/MerchantContainer.java -+++ b/net/minecraft/world/inventory/MerchantContainer.java -@@ -5,11 +5,20 @@ - import net.minecraft.core.NonNullList; - import net.minecraft.world.Container; - import net.minecraft.world.ContainerHelper; -+import net.minecraft.world.entity.npc.AbstractVillager; -+import net.minecraft.world.entity.npc.Villager; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.trading.Merchant; - import net.minecraft.world.item.trading.MerchantOffer; - import net.minecraft.world.item.trading.MerchantOffers; -+// CraftBukkit start -+import java.util.List; -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.entity.CraftHumanEntity; -+import org.bukkit.craftbukkit.entity.CraftAbstractVillager; -+import org.bukkit.entity.HumanEntity; -+// CraftBukkit end - - public class MerchantContainer implements Container { - -@@ -20,6 +29,46 @@ - public int selectionHint; - private int futureXp; - -+ // CraftBukkit start - add fields and methods -+ public List transaction = new java.util.ArrayList(); -+ private int maxStack = MAX_STACK; -+ -+ public List getContents() { -+ return this.itemStacks; -+ } -+ -+ public void onOpen(CraftHumanEntity who) { -+ this.transaction.add(who); -+ } -+ -+ public void onClose(CraftHumanEntity who) { -+ this.transaction.remove(who); -+ this.merchant.setTradingPlayer((Player) null); // SPIGOT-4860 -+ } -+ -+ public List getViewers() { -+ return this.transaction; -+ } -+ -+ @Override -+ public int getMaxStackSize() { -+ return this.maxStack; -+ } -+ -+ public void setMaxStackSize(int i) { -+ this.maxStack = i; -+ } -+ -+ public org.bukkit.inventory.InventoryHolder getOwner() { -+ return (this.merchant instanceof AbstractVillager) ? (CraftAbstractVillager) ((AbstractVillager) this.merchant).getBukkitEntity() : null; -+ } -+ -+ @Override -+ public Location getLocation() { -+ return (this.merchant instanceof AbstractVillager) ? ((AbstractVillager) this.merchant).getBukkitEntity().getLocation() : null; // Paper - Fix inventories returning null Locations -+ } -+ // CraftBukkit end -+ - public MerchantContainer(Merchant merchant) { - this.itemStacks = NonNullList.withSize(3, ItemStack.EMPTY); - this.merchant = merchant; diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantMenu.java.patch deleted file mode 100644 index 9fecebd95a..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/MerchantMenu.java.patch +++ /dev/null @@ -1,92 +0,0 @@ ---- a/net/minecraft/world/inventory/MerchantMenu.java -+++ b/net/minecraft/world/inventory/MerchantMenu.java -@@ -12,6 +12,7 @@ - import net.minecraft.world.item.trading.Merchant; - import net.minecraft.world.item.trading.MerchantOffer; - import net.minecraft.world.item.trading.MerchantOffers; -+import org.bukkit.craftbukkit.inventory.view.CraftMerchantView; // CraftBukkit - - public class MerchantMenu extends AbstractContainerMenu { - -@@ -32,6 +33,19 @@ - private boolean showProgressBar; - private boolean canRestock; - -+ // CraftBukkit start -+ private CraftMerchantView bukkitEntity = null; -+ private Inventory player; -+ -+ @Override -+ public CraftMerchantView getBukkitView() { -+ if (this.bukkitEntity == null) { -+ this.bukkitEntity = new CraftMerchantView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventoryMerchant(this.trader, this.tradeContainer), this, this.trader); -+ } -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end -+ - public MerchantMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, new ClientSideMerchant(playerInventory.player)); - } -@@ -43,6 +57,7 @@ - this.addSlot(new Slot(this.tradeContainer, 0, 136, 37)); - this.addSlot(new Slot(this.tradeContainer, 1, 162, 37)); - this.addSlot(new MerchantResultSlot(playerInventory.player, merchant, this.tradeContainer, 2, 220, 37)); -+ this.player = playerInventory; // CraftBukkit - save player - this.addStandardInventorySlots(playerInventory, 108, 84); - } - -@@ -108,12 +123,12 @@ - - itemstack = itemstack1.copy(); - if (slot == 2) { -- if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { -+ if (!this.moveItemStackTo(itemstack1, 3, 39, true, true)) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent - return ItemStack.EMPTY; - } - -- slot1.onQuickCraft(itemstack1, itemstack); -- this.playTradeSound(); -+ // slot1.onQuickCraft(itemstack1, itemstack); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; moved to after the non-check moveItemStackTo call -+ // this.playTradeSound(); - } else if (slot != 0 && slot != 1) { - if (slot >= 3 && slot < 30) { - if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { -@@ -126,6 +141,7 @@ - return ItemStack.EMPTY; - } - -+ if (slot != 2) { // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; moved down for slot 2 - if (itemstack1.isEmpty()) { - slot1.setByPlayer(ItemStack.EMPTY); - } else { -@@ -137,13 +153,28 @@ - } - - slot1.onTake(player, itemstack1); -+ } // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent; handle slot 2 -+ if (slot == 2) { // is merchant result slot -+ slot1.onTake(player, itemstack1); -+ if (itemstack1.isEmpty()) { -+ slot1.set(ItemStack.EMPTY); -+ return ItemStack.EMPTY; -+ } -+ -+ this.moveItemStackTo(itemstack1, 3, 39, true, false); // This should always succeed because it's checked above -+ -+ slot1.onQuickCraft(itemstack1, itemstack); -+ this.playTradeSound(); -+ slot1.set(ItemStack.EMPTY); // itemstack1 should ALWAYS be empty -+ } -+ // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent - } - - return itemstack; - } - - private void playTradeSound() { -- if (!this.trader.isClientSide()) { -+ if (!this.trader.isClientSide() && this.trader instanceof Entity) { // CraftBukkit - SPIGOT-5035 - Entity entity = (Entity) this.trader; - - entity.level().playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch deleted file mode 100644 index e83e892d8e..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch +++ /dev/null @@ -1,36 +0,0 @@ ---- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java -+++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java -@@ -8,14 +8,32 @@ - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.block.entity.EnderChestBlockEntity; -+// CraftBukkit start -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.util.CraftLocation; -+import org.bukkit.inventory.InventoryHolder; -+// CraftBukkit end - - public class PlayerEnderChestContainer extends SimpleContainer { - - @Nullable - private EnderChestBlockEntity activeChest; -+ // CraftBukkit start -+ private final Player owner; - -- public PlayerEnderChestContainer() { -+ public InventoryHolder getBukkitOwner() { -+ return this.owner.getBukkitEntity(); -+ } -+ -+ @Override -+ public Location getLocation() { -+ return this.activeChest != null ? CraftLocation.toBukkit(this.activeChest.getBlockPos(), this.activeChest.getLevel().getWorld()) : null; -+ } -+ -+ public PlayerEnderChestContainer(Player owner) { - super(27); -+ this.owner = owner; -+ // CraftBukkit end - } - - public void setActiveChest(EnderChestBlockEntity blockEntity) { diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch deleted file mode 100644 index 4efe4724bc..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch +++ /dev/null @@ -1,49 +0,0 @@ ---- a/net/minecraft/world/inventory/ShulkerBoxMenu.java -+++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java -@@ -6,11 +6,30 @@ - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - -+// CraftBukkit start -+import org.bukkit.craftbukkit.inventory.CraftInventory; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; -+// CraftBukkit end -+ - public class ShulkerBoxMenu extends AbstractContainerMenu { - - private static final int CONTAINER_SIZE = 27; - private final Container container; -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity; -+ private Inventory player; - -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ this.bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new CraftInventory(this.container), this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end -+ - public ShulkerBoxMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, new SimpleContainer(27)); - } -@@ -19,6 +38,7 @@ - super(MenuType.SHULKER_BOX, syncId); - checkContainerSize(inventory, 27); - this.container = inventory; -+ this.player = playerInventory; // CraftBukkit - save player - inventory.startOpen(playerInventory.player); - boolean flag = true; - boolean flag1 = true; -@@ -34,6 +54,7 @@ - - @Override - public boolean stillValid(Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return this.container.stillValid(player); - } - diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/SmithingMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/SmithingMenu.java.patch deleted file mode 100644 index 46bc8ef32c..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/SmithingMenu.java.patch +++ /dev/null @@ -1,66 +0,0 @@ ---- a/net/minecraft/world/inventory/SmithingMenu.java -+++ b/net/minecraft/world/inventory/SmithingMenu.java -@@ -17,6 +17,7 @@ - import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; -+import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit - - public class SmithingMenu extends ItemCombinerMenu { - -@@ -34,6 +35,9 @@ - private final RecipePropertySet templateItemTest; - private final RecipePropertySet additionItemTest; - private final DataSlot hasRecipeError; -+ // CraftBukkit start -+ private CraftInventoryView bukkitEntity; -+ // CraftBukkit end - - public SmithingMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, ContainerLevelAccess.NULL); -@@ -111,13 +115,14 @@ - this.hasRecipeError.set(flag ? 1 : 0); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent - } - - @Override - public void createResult() { - SmithingRecipeInput smithingrecipeinput = this.createRecipeInput(); - Level world = this.level; -- Optional optional; -+ Optional> optional; // CraftBukkit - decompile error - - if (world instanceof ServerLevel worldserver) { - optional = worldserver.recipeAccess().getRecipeFor(RecipeType.SMITHING, smithingrecipeinput, worldserver); -@@ -129,7 +134,9 @@ - ItemStack itemstack = ((SmithingRecipe) recipeholder.value()).assemble(smithingrecipeinput, this.level.registryAccess()); - - this.resultSlots.setRecipeUsed(recipeholder); -- this.resultSlots.setItem(0, itemstack); -+ // CraftBukkit start -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(this.getBukkitView(), itemstack); -+ // CraftBukkit end - }, () -> { - this.resultSlots.setRecipeUsed((RecipeHolder) null); - this.resultSlots.setItem(0, ItemStack.EMPTY); -@@ -149,4 +156,18 @@ - public boolean hasRecipeError() { - return this.hasRecipeError.get() > 0; - } -+ -+ // CraftBukkit start -+ @Override -+ public CraftInventoryView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventorySmithing( -+ this.access.getLocation(), this.inputSlots, this.resultSlots); -+ this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end - } diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/StonecutterMenu.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/StonecutterMenu.java.patch deleted file mode 100644 index 95cd1f3220..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/StonecutterMenu.java.patch +++ /dev/null @@ -1,188 +0,0 @@ ---- a/net/minecraft/world/inventory/StonecutterMenu.java -+++ b/net/minecraft/world/inventory/StonecutterMenu.java -@@ -7,7 +7,6 @@ - import net.minecraft.world.Container; - import net.minecraft.world.SimpleContainer; - import net.minecraft.world.entity.player.Inventory; --import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.RecipeHolder; -@@ -17,6 +16,13 @@ - import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Blocks; - -+// CraftBukkit start -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; -+import org.bukkit.craftbukkit.inventory.view.CraftStonecutterView; -+import org.bukkit.entity.Player; -+// CraftBukkit end -+ - public class StonecutterMenu extends AbstractContainerMenu { - - public static final int INPUT_SLOT = 0; -@@ -36,27 +42,49 @@ - Runnable slotUpdateListener; - public final Container container; - final ResultContainer resultContainer; -+ // CraftBukkit start -+ private CraftStonecutterView bukkitEntity = null; -+ private Player player; - -+ @Override -+ public CraftStonecutterView getBukkitView() { -+ if (this.bukkitEntity != null) { -+ return this.bukkitEntity; -+ } -+ -+ CraftInventoryStonecutter inventory = new CraftInventoryStonecutter(this.container, this.resultContainer); -+ this.bukkitEntity = new CraftStonecutterView(this.player, inventory, this); -+ return this.bukkitEntity; -+ } -+ // CraftBukkit end -+ - public StonecutterMenu(int syncId, Inventory playerInventory) { - this(syncId, playerInventory, ContainerLevelAccess.NULL); - } - - public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { - super(MenuType.STONECUTTER, syncId); -- this.selectedRecipeIndex = DataSlot.standalone(); -+ this.selectedRecipeIndex = DataSlot.shared(new int[1], 0); // Paper - Add PlayerStonecutterRecipeSelectEvent - this.recipesForInput = SelectableRecipe.SingleInputSet.empty(); - this.input = ItemStack.EMPTY; - this.slotUpdateListener = () -> { - }; -- this.container = new SimpleContainer(1) { -+ this.container = new SimpleContainer(this.createBlockHolder(context), 1) { // Paper - Add missing InventoryHolders - @Override - public void setChanged() { - super.setChanged(); - StonecutterMenu.this.slotsChanged(this); - StonecutterMenu.this.slotUpdateListener.run(); - } -+ -+ // CraftBukkit start -+ @Override -+ public Location getLocation() { -+ return context.getLocation(); -+ } -+ // CraftBukkit end - }; -- this.resultContainer = new ResultContainer(); -+ this.resultContainer = new ResultContainer(this.createBlockHolder(context)); // Paper - Add missing InventoryHolders - this.access = context; - this.level = playerInventory.player.level(); - this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33)); -@@ -67,7 +95,7 @@ - } - - @Override -- public void onTake(Player player, ItemStack stack) { -+ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { - stack.onCraftedBy(player.level(), player, stack.getCount()); - StonecutterMenu.this.resultContainer.awardUsedRecipes(player, this.getRelevantItems()); - ItemStack itemstack1 = StonecutterMenu.this.inputSlot.remove(1); -@@ -80,7 +108,7 @@ - long j = world.getGameTime(); - - if (StonecutterMenu.this.lastSoundTime != j) { -- world.playSound((Player) null, blockposition, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); -+ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); - StonecutterMenu.this.lastSoundTime = j; - } - -@@ -94,6 +122,7 @@ - }); - this.addStandardInventorySlots(playerInventory, 8, 84); - this.addDataSlot(this.selectedRecipeIndex); -+ this.player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit - } - - public int getSelectedRecipeIndex() { -@@ -113,18 +142,45 @@ - } - - @Override -- public boolean stillValid(Player player) { -+ public boolean stillValid(net.minecraft.world.entity.player.Player player) { -+ if (!this.checkReachable) return true; // CraftBukkit - return stillValid(this.access, player, Blocks.STONECUTTER); - } - - @Override -- public boolean clickMenuButton(Player player, int id) { -+ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { - if (this.selectedRecipeIndex.get() == id) { - return false; - } else { - if (this.isValidRecipeIndex(id)) { -- this.selectedRecipeIndex.set(id); -- this.setupResultSlot(id); -+ // Paper start - Add PlayerStonecutterRecipeSelectEvent -+ int recipeIndex = id; -+ this.selectedRecipeIndex.set(recipeIndex); -+ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed -+ paperEventBlock: if (this.isValidRecipeIndex(id)) { -+ final Optional> recipe = this.recipesForInput.entries().get(id).recipe().recipe(); -+ if (recipe.isEmpty()) break paperEventBlock; // The recipe selected does not have an actual server recipe (presumably its the empty one). Cannot call the event, just break. -+ -+ io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent event = new io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) recipe.get().toBukkitRecipe()); -+ if (!event.callEvent()) { -+ player.containerMenu.sendAllDataToRemote(); -+ return false; -+ } -+ -+ net.minecraft.resources.ResourceLocation key = org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()); -+ if (!recipe.get().id().location().equals(key)) { // If the recipe did NOT stay the same -+ for (int newRecipeIndex = 0; newRecipeIndex < this.recipesForInput.entries().size(); newRecipeIndex++) { -+ if (this.recipesForInput.entries().get(newRecipeIndex).recipe().recipe().filter(r -> r.id().location().equals(key)).isPresent()) { -+ recipeIndex = newRecipeIndex; -+ break; -+ } -+ } -+ } -+ } -+ player.containerMenu.sendAllDataToRemote(); -+ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it -+ this.setupResultSlot(recipeIndex); -+ // Paper end - Add PlayerStonecutterRecipeSelectEvent - } - - return true; -@@ -144,6 +200,7 @@ - this.setupRecipeList(itemstack); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent - } - - private void setupRecipeList(ItemStack stack) { -@@ -158,7 +215,7 @@ - } - - void setupResultSlot(int selectedId) { -- Optional optional; -+ Optional> optional; // CraftBukkit - decompile error - - if (!this.recipesForInput.isEmpty() && this.isValidRecipeIndex(selectedId)) { - SelectableRecipe.SingleInputEntry selectablerecipe_a = (SelectableRecipe.SingleInputEntry) this.recipesForInput.entries().get(selectedId); -@@ -193,7 +250,7 @@ - } - - @Override -- public ItemStack quickMoveStack(Player player, int slot) { -+ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int slot) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot1 = (Slot) this.slots.get(slot); - -@@ -246,7 +303,7 @@ - } - - @Override -- public void removed(Player player) { -+ public void removed(net.minecraft.world.entity.player.Player player) { - super.removed(player); - this.resultContainer.removeItemNoUpdate(1); - this.access.execute((world, blockposition) -> { diff --git a/paper-server/patches/unapplied/net/minecraft/world/inventory/TransientCraftingContainer.java.patch b/paper-server/patches/unapplied/net/minecraft/world/inventory/TransientCraftingContainer.java.patch deleted file mode 100644 index 67ed6a0fb4..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/inventory/TransientCraftingContainer.java.patch +++ /dev/null @@ -1,93 +0,0 @@ ---- a/net/minecraft/world/inventory/TransientCraftingContainer.java -+++ b/net/minecraft/world/inventory/TransientCraftingContainer.java -@@ -3,11 +3,21 @@ - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.NonNullList; -+import net.minecraft.world.Container; - import net.minecraft.world.ContainerHelper; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.entity.player.StackedItemContents; - import net.minecraft.world.item.ItemStack; - -+// CraftBukkit start -+import java.util.List; -+import net.minecraft.world.item.crafting.RecipeHolder; -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.entity.CraftHumanEntity; -+import org.bukkit.entity.HumanEntity; -+import org.bukkit.event.inventory.InventoryType; -+// CraftBukkit end -+ - public class TransientCraftingContainer implements CraftingContainer { - - private final NonNullList items; -@@ -15,6 +25,68 @@ - private final int height; - private final AbstractContainerMenu menu; - -+ // CraftBukkit start - add fields -+ public List transaction = new java.util.ArrayList(); -+ private RecipeHolder currentRecipe; -+ public Container resultInventory; -+ private Player owner; -+ private int maxStack = MAX_STACK; -+ -+ public List getContents() { -+ return this.items; -+ } -+ -+ public void onOpen(CraftHumanEntity who) { -+ this.transaction.add(who); -+ } -+ -+ public InventoryType getInvType() { -+ return this.items.size() == 4 ? InventoryType.CRAFTING : InventoryType.WORKBENCH; -+ } -+ -+ public void onClose(CraftHumanEntity who) { -+ this.transaction.remove(who); -+ } -+ -+ public List getViewers() { -+ return this.transaction; -+ } -+ -+ public org.bukkit.inventory.InventoryHolder getOwner() { -+ return (this.owner == null) ? null : this.owner.getBukkitEntity(); -+ } -+ -+ @Override -+ public int getMaxStackSize() { -+ return this.maxStack; -+ } -+ -+ public void setMaxStackSize(int size) { -+ this.maxStack = size; -+ this.resultInventory.setMaxStackSize(size); -+ } -+ -+ @Override -+ public Location getLocation() { -+ return this.menu instanceof CraftingMenu ? ((CraftingMenu) this.menu).access.getLocation() : this.owner.getBukkitEntity().getLocation(); -+ } -+ -+ @Override -+ public RecipeHolder getCurrentRecipe() { -+ return this.currentRecipe; -+ } -+ -+ @Override -+ public void setCurrentRecipe(RecipeHolder currentRecipe) { -+ this.currentRecipe = currentRecipe; -+ } -+ -+ public TransientCraftingContainer(AbstractContainerMenu container, int i, int j, Player player) { -+ this(container, i, j); -+ this.owner = player; -+ } -+ // CraftBukkit end -+ - public TransientCraftingContainer(AbstractContainerMenu handler, int width, int height) { - this(handler, width, height, NonNullList.withSize(width * height, ItemStack.EMPTY)); - }