diff --git a/paper-server/patches/sources/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch b/paper-server/patches/sources/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch index 3b0b269b4..a97acf279 100644 --- a/paper-server/patches/sources/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch +++ b/paper-server/patches/sources/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch @@ -17,7 +17,7 @@ } + // 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); + @@ -27,12 +27,13 @@ + } + + 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 @@ -51,8 +52,7 @@ abstractboat.setYRot(enumdirection.toYRot()); - worldserver.addFreshEntity(abstractboat); - stack.shrink(1); -+ 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/paper-server/patches/sources/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch b/paper-server/patches/sources/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch index 6251abfb7..824b11e0d 100644 --- a/paper-server/patches/sources/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch +++ b/paper-server/patches/sources/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch @@ -36,13 +36,13 @@ public interface DispenseItemBehavior { -@@ -90,14 +104,46 @@ +@@ -90,14 +104,47 @@ Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); EntityType entitytypes = ((SpawnEggItem) stack.getItem()).getType(pointer.level().registryAccess(), stack); + // 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); + @@ -52,12 +52,13 @@ + } + + 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 @@ -81,18 +82,18 @@ } - stack.shrink(1); -+ // 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; } -@@ -116,13 +162,42 @@ +@@ -116,13 +163,43 @@ Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); BlockPos blockposition = pointer.pos().relative(enumdirection); 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); + @@ -102,12 +103,13 @@ + } + + 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 @@ -127,17 +129,17 @@ if (entityarmorstand != null) { - stack.shrink(1); -+ // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ if (shrink) stack.shrink(1); // Paper - actually handle here } return stack; -@@ -141,7 +216,34 @@ +@@ -141,7 +218,36 @@ }); if (!list.isEmpty()) { - ((Saddleable) list.get(0)).equipSaddle(stack.split(1), SoundSource.BLOCKS); + // 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); @@ -148,12 +150,13 @@ + } + + 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 @@ -164,17 +167,18 @@ + } + ((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 { -@@ -166,9 +268,35 @@ +@@ -166,9 +272,38 @@ } entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next(); - } while (!entityhorsechestedabstract.isTamed() || !entityhorsechestedabstract.getSlot(499).set(stack)); + // 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); @@ -186,10 +190,13 @@ + } + + 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 @@ -201,11 +208,11 @@ + 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; } -@@ -202,8 +330,50 @@ +@@ -202,8 +337,50 @@ BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); ServerLevel worldserver = pointer.level(); @@ -223,7 +230,7 @@ + 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) { @@ -257,7 +264,7 @@ return this.consumeWithRemainder(pointer, stack, new ItemStack(Items.BUCKET)); } else { return this.defaultDispenseItemBehavior.dispense(pointer, stack); -@@ -229,7 +399,7 @@ +@@ -229,7 +406,7 @@ Block block = iblockdata.getBlock(); if (block instanceof BucketPickup ifluidsource) { @@ -266,13 +273,13 @@ if (itemstack1.isEmpty()) { return super.execute(pointer, stack); -@@ -237,6 +407,32 @@ +@@ -237,6 +414,32 @@ worldserver.gameEvent((Entity) null, (Holder) GameEvent.FLUID_PICKUP, blockposition); Item item = itemstack1.getItem(); + // 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) { @@ -299,13 +306,13 @@ return this.consumeWithRemainder(pointer, stack, new ItemStack(item)); } } else { -@@ -249,16 +445,44 @@ +@@ -249,16 +452,44 @@ protected ItemStack execute(BlockSource pointer, ItemStack stack) { 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) { @@ -347,13 +354,13 @@ TntBlock.explode(worldserver, blockposition); worldserver.removeBlock(blockposition, false); } else { -@@ -283,13 +507,64 @@ +@@ -283,13 +514,64 @@ this.setSuccess(true); ServerLevel worldserver = pointer.level(); 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) { @@ -412,7 +419,7 @@ return stack; } }); -@@ -298,12 +573,41 @@ +@@ -298,12 +580,42 @@ protected ItemStack execute(BlockSource pointer, ItemStack stack) { ServerLevel worldserver = pointer.level(); BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); @@ -420,7 +427,7 @@ + // 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); + @@ -430,12 +437,13 @@ + } + + 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 @@ -452,18 +460,18 @@ 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); - stack.shrink(1); -+ // itemstack.shrink(1); // CraftBukkit - handled above ++ if (shrink) stack.shrink(1); // Paper - actually handle here return stack; } }); -@@ -313,7 +617,31 @@ +@@ -313,7 +625,31 @@ ServerLevel worldserver = pointer.level(); Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); BlockPos blockposition = pointer.pos().relative(enumdirection); + + // 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) { @@ -488,7 +496,7 @@ if (worldserver.isEmptyBlock(blockposition) && WitherSkullBlock.canSpawnMob(worldserver, blockposition, stack)) { worldserver.setBlock(blockposition, (BlockState) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(enumdirection)), 3); worldserver.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_PLACE, blockposition); -@@ -326,7 +654,7 @@ +@@ -326,7 +662,7 @@ stack.shrink(1); this.setSuccess(true); } else { @@ -497,13 +505,13 @@ } return stack; -@@ -339,6 +667,30 @@ +@@ -339,6 +675,30 @@ BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN; + // 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) { @@ -528,7 +536,7 @@ if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) { if (!worldserver.isClientSide) { worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3); -@@ -348,7 +700,7 @@ +@@ -348,7 +708,7 @@ stack.shrink(1); this.setSuccess(true); } else { @@ -537,13 +545,13 @@ } return stack; -@@ -377,6 +729,30 @@ +@@ -377,6 +737,30 @@ BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); BlockState iblockdata = worldserver.getBlockState(blockposition); + // 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) { @@ -568,7 +576,7 @@ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; }) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { -@@ -402,6 +778,13 @@ +@@ -402,6 +786,13 @@ this.setSuccess(true); if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) { if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) { @@ -582,7 +590,7 @@ RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata); stack.shrink(1); } else { -@@ -426,6 +809,31 @@ +@@ -426,6 +817,31 @@ this.setSuccess(false); return stack; } else { @@ -590,7 +598,7 @@ + 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) { @@ -614,7 +622,7 @@ Iterator iterator1 = list.iterator(); Armadillo armadillo; -@@ -454,6 +862,13 @@ +@@ -454,6 +870,13 @@ Optional optional = HoneycombItem.getWaxed(iblockdata); if (optional.isPresent()) { @@ -628,7 +636,7 @@ worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get()); worldserver.levelEvent(3003, blockposition, 0); stack.shrink(1); -@@ -481,6 +896,12 @@ +@@ -481,6 +904,12 @@ if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) { return this.defaultDispenseItemBehavior.dispense(pointer, stack); } else { diff --git a/paper-server/patches/sources/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java.patch b/paper-server/patches/sources/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java.patch index d375478ad..18eb499fb 100644 --- a/paper-server/patches/sources/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java.patch +++ b/paper-server/patches/sources/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java.patch @@ -32,9 +32,12 @@ BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); List list = pointer.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> { return entityliving.canEquipWithDispenser(stack); -@@ -34,7 +44,34 @@ +@@ -32,9 +42,37 @@ + } else { + LivingEntity entityliving = (LivingEntity) list.getFirst(); EquipmentSlot enumitemslot = entityliving.getEquipmentSlotForItem(stack); - ItemStack itemstack1 = stack.split(1); +- ItemStack itemstack1 = stack.split(1); ++ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event - entityliving.setItemSlot(enumitemslot, itemstack1); + // CraftBukkit start @@ -48,12 +51,13 @@ + } + + 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 @@ -68,3 +72,11 @@ if (entityliving instanceof Mob) { Mob entityinsentient = (Mob) entityliving; +@@ -42,6 +80,7 @@ + entityinsentient.setPersistenceRequired(); + } + ++ if (shrink) stack.shrink(1); // Paper - shrink here + return true; + } + } diff --git a/paper-server/patches/sources/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java.patch b/paper-server/patches/sources/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java.patch index 3e56db777..ea22a6dd4 100644 --- a/paper-server/patches/sources/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java.patch +++ b/paper-server/patches/sources/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java.patch @@ -19,7 +19,7 @@ - AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, vec3d1.x, vec3d1.y, vec3d1.z, this.entityType, EntitySpawnReason.DISPENSER, stack, (Player) null); + // 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); @@ -29,12 +29,13 @@ + } + + 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 @@ -50,8 +51,7 @@ if (entityminecartabstract != null) { - worldserver.addFreshEntity(entityminecartabstract); - stack.shrink(1); -+ 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/paper-server/patches/sources/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java.patch b/paper-server/patches/sources/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java.patch index 6b228a3fe..2061a3827 100644 --- a/paper-server/patches/sources/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java.patch +++ b/paper-server/patches/sources/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java.patch @@ -12,7 +12,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { -@@ -31,8 +36,40 @@ +@@ -31,8 +36,41 @@ Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); Position iposition = this.dispenseConfig.positionFunction().getDispensePosition(pointer, enumdirection); @@ -20,7 +20,7 @@ - stack.shrink(1); + // 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); + @@ -30,12 +30,13 @@ + } + + 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 @@ -50,7 +51,7 @@ + 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/paper-server/patches/sources/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch b/paper-server/patches/sources/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch index 438bd5e56..bc579690d 100644 --- a/paper-server/patches/sources/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch +++ b/paper-server/patches/sources/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch @@ -19,7 +19,7 @@ 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/paper-server/patches/sources/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch b/paper-server/patches/sources/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch index 3c544924c..bfa73fef4 100644 --- a/paper-server/patches/sources/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch +++ b/paper-server/patches/sources/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch @@ -19,7 +19,7 @@ + // 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) {