diff options
Diffstat (limited to 'patches/server/1056-Fix-inconsistencies-in-dispense-events-regarding-sta.patch')
-rw-r--r-- | patches/server/1056-Fix-inconsistencies-in-dispense-events-regarding-sta.patch | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/patches/server/1056-Fix-inconsistencies-in-dispense-events-regarding-sta.patch b/patches/server/1056-Fix-inconsistencies-in-dispense-events-regarding-sta.patch new file mode 100644 index 0000000000..564f0bb367 --- /dev/null +++ b/patches/server/1056-Fix-inconsistencies-in-dispense-events-regarding-sta.patch @@ -0,0 +1,432 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic <[email protected]> +Date: Sun, 11 Dec 2022 23:47:22 -0800 +Subject: [PATCH] Fix inconsistencies in dispense events regarding stack size + +The javadocs for BlockDispenseEvent suggest the ItemStack is a single +item which is being dispensed. Before this fix, sometimes it was the whole +stack before a single item had been taken. This fixes that so the stack size +is always 1. + +diff --git a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +index dff30954e4c588ee4cc79d3f6dab6fb456934d65..ddb264443f2e38b6348226016f9139727c588898 100644 +--- a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +@@ -49,7 +49,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { + } + + // CraftBukkit start +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink at end and single item in event + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +@@ -59,12 +59,13 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -80,8 +81,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { + abstractboat.setInitialPos(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); // CraftBukkit + EntityType.createDefaultStackConfig(worldserver, stack, (Player) null).accept(abstractboat); + abstractboat.setYRot(enumdirection.toYRot()); +- if (!worldserver.addFreshEntity(abstractboat)) stack.grow(1); // CraftBukkit +- // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ if (worldserver.addFreshEntity(abstractboat) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink + } + + return stack; +diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +index 9246ec011c7d94618c0aa73792d1bef8f447c88c..c81050f58a8c75f7f3b16ab466d8d87edd83ea31 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -106,7 +106,7 @@ public interface DispenseItemBehavior { + + // CraftBukkit start + ServerLevel worldserver = pointer.level(); +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +@@ -116,12 +116,13 @@ public interface DispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -142,7 +143,7 @@ public interface DispenseItemBehavior { + return ItemStack.EMPTY; + } + +- // itemstack.shrink(1); // Handled during event processing ++ if (shrink) stack.shrink(1); // Paper - actually handle here + // CraftBukkit end + pointer.level().gameEvent((Entity) null, (Holder) GameEvent.ENTITY_PLACE, pointer.pos()); + return stack; +@@ -164,7 +165,7 @@ public interface DispenseItemBehavior { + ServerLevel worldserver = pointer.level(); + + // CraftBukkit start +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +@@ -174,12 +175,13 @@ public interface DispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -197,7 +199,7 @@ public interface DispenseItemBehavior { + ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, consumer, blockposition, EntitySpawnReason.DISPENSER, false, false); + + if (entityarmorstand != null) { +- // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ if (shrink) stack.shrink(1); // Paper - actually handle here + } + + return stack; +@@ -217,7 +219,7 @@ public interface DispenseItemBehavior { + + if (!list.isEmpty()) { + // CraftBukkit start +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event + ServerLevel world = pointer.level(); + org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); +@@ -228,12 +230,13 @@ public interface DispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -244,6 +247,7 @@ public interface DispenseItemBehavior { + } + ((Saddleable) list.get(0)).equipSaddle(CraftItemStack.asNMSCopy(event.getItem()), SoundSource.BLOCKS); // Paper - track changed items in dispense event + // CraftBukkit end ++ if (shrink) stack.shrink(1); // Paper - actually handle here + this.setSuccess(true); + return stack; + } else { +@@ -270,7 +274,7 @@ public interface DispenseItemBehavior { + entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next(); + // CraftBukkit start + } while (!entityhorsechestedabstract.isTamed()); +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below + ServerLevel world = pointer.level(); + org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); +@@ -281,10 +285,13 @@ public interface DispenseItemBehavior { + } + + if (event.isCancelled()) { ++ // stack.grow(1); // Paper - shrink below (this was actually missing and should be here, added it commented out to be consistent) + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -296,7 +303,7 @@ public interface DispenseItemBehavior { + entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem())); + // CraftBukkit end + +- // itemstack.shrink(1); // CraftBukkit - handled above ++ if (shrink) stack.shrink(1); // Paper - actually handle here + this.setSuccess(true); + return stack; + } +@@ -344,7 +351,7 @@ public interface DispenseItemBehavior { + if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) { + // Paper end - correctly check if the bucket place will succeed + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event + + BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); + if (!DispenserBlock.eventFired) { +@@ -409,7 +416,7 @@ public interface DispenseItemBehavior { + + // CraftBukkit start + org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event + + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); + if (!DispenserBlock.eventFired) { +@@ -447,7 +454,7 @@ public interface DispenseItemBehavior { + + // CraftBukkit start + org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items + + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); + if (!DispenserBlock.eventFired) { +@@ -509,7 +516,7 @@ public interface DispenseItemBehavior { + BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); + // CraftBukkit start + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event + + BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); + if (!DispenserBlock.eventFired) { +@@ -576,7 +583,7 @@ public interface DispenseItemBehavior { + // CraftBukkit start + // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); + +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink at end and single item in event + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +@@ -586,12 +593,13 @@ public interface DispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -607,7 +615,7 @@ public interface DispenseItemBehavior { + worldserver.addFreshEntity(entitytntprimed); + worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); + worldserver.gameEvent((Entity) null, (Holder) GameEvent.ENTITY_PLACE, blockposition); +- // itemstack.shrink(1); // CraftBukkit - handled above ++ if (shrink) stack.shrink(1); // Paper - actually handle here + return stack; + } + }); +@@ -620,7 +628,7 @@ public interface DispenseItemBehavior { + + // CraftBukkit start + org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event + + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); + if (!DispenserBlock.eventFired) { +@@ -669,7 +677,7 @@ public interface DispenseItemBehavior { + + // CraftBukkit start + org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event + + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); + if (!DispenserBlock.eventFired) { +@@ -731,7 +739,7 @@ public interface DispenseItemBehavior { + + // CraftBukkit start + org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - only single item in event + + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); + if (!DispenserBlock.eventFired) { +@@ -813,7 +821,7 @@ public interface DispenseItemBehavior { + ItemStack itemstack1 = stack; + ServerLevel world = pointer.level(); + org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); // Paper - ignore stack size on damageable items + + BlockDispenseEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); + if (!DispenserBlock.eventFired) { +diff --git a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +index a43ea83dbbd5946096cdde31af766674bda6c3be..bf8c511739265c6a9cd277752e844481598f8966 100644 +--- a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +@@ -42,7 +42,7 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { + } else { + LivingEntity entityliving = (LivingEntity) list.getFirst(); + EquipmentSlot enumitemslot = entityliving.getEquipmentSlotForItem(stack); +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event + + // CraftBukkit start + Level world = pointer.level(); +@@ -55,12 +55,13 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return false; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -79,6 +80,7 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { + entityinsentient.setPersistenceRequired(); + } + ++ if (shrink) stack.shrink(1); // Paper - shrink here + return true; + } + } +diff --git a/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java +index aae9ec8f3bd39685b37251bef3f9ac846d65c192..3588896b7413be73ade6b3f8fd111d02c48ec550 100644 +--- a/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java +@@ -69,7 +69,7 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior { + Vec3 vec3d1 = new Vec3(d0, d1 + d3, d2); + // CraftBukkit start + // EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, vec3d1.x, vec3d1.y, vec3d1.z, this.entityType, EntitySpawnReason.DISPENSER, itemstack, (EntityHuman) null); +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event + org.bukkit.block.Block block2 = CraftBlock.at(worldserver, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +@@ -79,12 +79,13 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -98,8 +99,7 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior { + AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.entityType, EntitySpawnReason.DISPENSER, itemstack1, (Player) null); + + if (entityminecartabstract != null) { +- if (!worldserver.addFreshEntity(entityminecartabstract)) stack.grow(1); +- // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ if (worldserver.addFreshEntity(entityminecartabstract) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink + // CraftBukkit end + } + +diff --git a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java +index 281439e430fb8e587549da783bdd93432f8f957f..54c72cf472e06e214eb61bd8615a0bb27690c807 100644 +--- a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java +@@ -38,7 +38,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { + + // CraftBukkit start + // IProjectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(worldserver, iposition, itemstack, enumdirection), worldserver, itemstack, (double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); // CraftBukkit - call when finish the BlockDispenseEvent +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +@@ -48,12 +48,13 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { + } + + if (event.isCancelled()) { +- stack.grow(1); ++ // stack.grow(1); // Paper - shrink below + return stack; + } + ++ boolean shrink = true; // Paper + if (!event.getItem().equals(craftItem)) { +- stack.grow(1); ++ shrink = false; // Paper - shrink below + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior +@@ -68,7 +69,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { + Projectile iprojectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(worldserver, iposition, CraftItemStack.unwrap(event.getItem()), enumdirection), worldserver, itemstack1, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty()); // Paper - track changed items in the dispense event; unwrap is safe here because all uses of the stack make their own copies + iprojectile.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(pointer.blockEntity()); + } +- // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ if (shrink) stack.shrink(1); // Paper - actually handle here + // CraftBukkit end + return stack; + } +diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +index afad4fa3ca1a3186c4569ea073f776dac16817e1..65ed3d77a51b8299517e0c165403b0c5ac413475 100644 +--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +@@ -38,7 +38,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { + ServerLevel worldserver = pointer.level(); + // CraftBukkit start + org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items + + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); + if (!DispenserBlock.eventFired) { +diff --git a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +index 16b435216dc7c6a3f8c1c0f9e2323e6afb3a6cb9..8f9fde5489c0e1d0a91203536caddec5a9c96f6c 100644 +--- a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +@@ -34,7 +34,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { + + // CraftBukkit start + org.bukkit.block.Block bukkitBlock = CraftBlock.at(pointer.level(), pointer.pos()); +- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event + + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); + if (!DispenserBlock.eventFired) { |