From 5df0660d63ce26d6609b96cca7520c436c2d638c Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Mon, 10 Jun 2024 08:24:52 +0200 Subject: [PATCH] Prevent internal NPE on ItemStack#damage (#10836) ItemStack#damage internally uses ItemStack#hurtAndBreak, which previously would call a Consumer in case the item broke. Since 1.20.5 the break game event logic however resides in said method and was using the equipment slot passed, which is null in the case of the API ItemStack#damage method. This commit prevents the NPE by first null checking the slot. Addittionally, hurtAndBreak also now checks if the player has infinite materials, e.g. is in creative mode, to prevent damaging the item. As such as filter is undesirable for API calls, this commit also skips this logic in case of an API invocation. --- patches/server/Friction-API.patch | 2 +- patches/server/ItemStack-damage-API.patch | 30 ++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/patches/server/Friction-API.patch b/patches/server/Friction-API.patch index de81f4a1be..f452441c23 100644 --- a/patches/server/Friction-API.patch +++ b/patches/server/Friction-API.patch @@ -137,7 +137,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - nmsStack.hurtAndBreak(amount, this.getHandle(), slot); + nmsStack.hurtAndBreakWithoutChecks(amount, this.getHandle(), slot); } // Paper end - ItemStack damage API + diff --git a/patches/server/ItemStack-damage-API.patch b/patches/server/ItemStack-damage-API.patch index 0a67545d0f..55a5656bd7 100644 --- a/patches/server/ItemStack-damage-API.patch +++ b/patches/server/ItemStack-damage-API.patch @@ -10,6 +10,34 @@ the logic associated with damaging them == AT == public net.minecraft.world.entity.LivingEntity entityEventForEquipmentBreak(Lnet/minecraft/world/entity/EquipmentSlot;)B +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 { + return; + } + } ++ // Paper start - ItemStack damage API - split hurtAndBreak to skip pre-checks like creative mode ++ this.hurtAndBreakWithoutChecks(amount, entity, slot); ++ } ++ } + ++ public void hurtAndBreakWithoutChecks(int amount, LivingEntity entity, @org.checkerframework.checker.nullness.qual.Nullable EquipmentSlot slot) { ++ { ++ // Paper end - ItemStack damage API - split hurtAndBreak to skip pre-checks like creative mode + RandomSource randomsource = entity.getRandom(); + ServerPlayer entityplayer; + +@@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder { + } + + this.hurtAndBreak(amount, randomsource, entity, () -> { // Paper - Add EntityDamageItemEvent +- entity.broadcastBreakEvent(slot); ++ if (slot != null) entity.broadcastBreakEvent(slot); // Paper - ItemStack damage API - slot is nullable + Item item = this.getItem(); + // CraftBukkit start - Check for item breaking + if (this.count == 1 && entity instanceof net.minecraft.world.entity.player.Player) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -59,7 +87,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private void damageItemStack0(final net.minecraft.world.item.ItemStack nmsStack, final int amount, final net.minecraft.world.entity.EquipmentSlot slot) { -+ nmsStack.hurtAndBreak(amount, this.getHandle(), slot); ++ nmsStack.hurtAndBreakWithoutChecks(amount, this.getHandle(), slot); + } + // Paper end - ItemStack damage API }