diff --git a/patches/server/Correctly-call-PlayerItemBreakEvent.patch b/patches/server/Correctly-call-PlayerItemBreakEvent.patch new file mode 100644 index 0000000000..0ed89ad701 --- /dev/null +++ b/patches/server/Correctly-call-PlayerItemBreakEvent.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll +Date: Fri, 12 Jul 2024 19:09:44 +0200 +Subject: [PATCH] Correctly call PlayerItemBreakEvent + +The minecraft 1.21 update changed the invocation order in +ItemStack#hurtAndBreak, now first shrinking the itemstack to a count of +zero and then invoking the break callback. + +This leads to spigots logic no longer firing at all. This patch now +correctly executes on count of zero and temporarily bumps the count to +one before passing it to event handlers to maintain compatibility with +the event contracts. + +This fix was chosen over invoking the callback prior to shrinking the +stack to not disrupt potential new vanilla changes that might depend on +this behaviour. + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder { + + this.hurtAndBreak(amount, worldserver, entity, (item) -> { // Paper - Add EntityDamageItemEvent + // CraftBukkit start - Check for item breaking +- if (this.count == 1 && entity instanceof net.minecraft.world.entity.player.Player) { ++ if (this.count == 0 && entity instanceof net.minecraft.world.entity.player.Player) { // Paper - correctly call item break event - run if count reached 0 ++ this.setCount(1); // Paper - correctly call item break event - grow to count 1 + org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((net.minecraft.world.entity.player.Player) entity, this); ++ this.setCount(0); // Paper - correctly call item break event - reset to count 0 + } + // CraftBukkit end + if (slot != null) entity.onEquippedItemBroken(item, slot); // Paper - itemstack damage API - do not process entity related callbacks when damaging from API diff --git a/patches/server/ItemStack-damage-API.patch b/patches/server/ItemStack-damage-API.patch index ed6ff97839..11ba7ec36f 100644 --- a/patches/server/ItemStack-damage-API.patch +++ b/patches/server/ItemStack-damage-API.patch @@ -28,7 +28,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (player == null || !player.hasInfiniteMaterials() || force) { // Paper if (amount > 0) { int originalDamage = amount; // Paper - Expand PlayerItemDamageEvent - amount = EnchantmentHelper.processDurabilityChange(world, this, amount); +- amount = EnchantmentHelper.processDurabilityChange(world, this, amount); ++ if (!force) amount = EnchantmentHelper.processDurabilityChange(world, this, amount); // Paper - itemstack damage API - do not consider enchantments when damaging from API + // CraftBukkit start + if (player instanceof ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent + PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount, originalDamage); // Paper - Add EntityDamageItemEvent & Expand PlayerItemDamageEvent @@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder { } @@ -42,10 +46,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (world instanceof ServerLevel worldserver) { @@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder { + org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((net.minecraft.world.entity.player.Player) entity, this); } // CraftBukkit end - entity.onEquippedItemBroken(item, slot); +- entity.onEquippedItemBroken(item, slot); - }); ++ if (slot != null) entity.onEquippedItemBroken(item, slot); // Paper - itemstack damage API - do not process entity related callbacks when damaging from API + }, force); // Paper } diff --git a/patches/server/ItemStack-getMaxItemUseDuration.patch b/patches/server/ItemStack-getMaxItemUseDuration.patch index 8d80b80f80..37ed718722 100644 --- a/patches/server/ItemStack-getMaxItemUseDuration.patch +++ b/patches/server/ItemStack-getMaxItemUseDuration.patch @@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (entity == null && handle.is(Items.CROSSBOW)) { + throw new UnsupportedOperationException("This item requires an entity to determine the max use duration"); + } -+ return handle.getUseDuration(((CraftLivingEntity) entity).getHandle()); ++ return handle.getUseDuration(entity != null ? ((CraftLivingEntity) entity).getHandle() : null); + } + // Paper end +