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.
This commit is contained in:
Jake Potrebic
2022-12-11 23:47:22 -08:00
parent 0d8c3dc008
commit b620df8e20
7 changed files with 86 additions and 65 deletions

View File

@@ -17,7 +17,7 @@
} }
+ // CraftBukkit start + // 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()); + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+ +
@@ -27,12 +27,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return stack; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
@@ -51,8 +52,7 @@
abstractboat.setYRot(enumdirection.toYRot()); abstractboat.setYRot(enumdirection.toYRot());
- worldserver.addFreshEntity(abstractboat); - worldserver.addFreshEntity(abstractboat);
- stack.shrink(1); - stack.shrink(1);
+ if (!worldserver.addFreshEntity(abstractboat)) stack.grow(1); // CraftBukkit + if (worldserver.addFreshEntity(abstractboat) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink
+ // itemstack.shrink(1); // CraftBukkit - handled during event processing
} }
return stack; return stack;

View File

@@ -36,13 +36,13 @@
public interface DispenseItemBehavior { public interface DispenseItemBehavior {
@@ -90,14 +104,46 @@ @@ -90,14 +104,47 @@
Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING);
EntityType<?> entitytypes = ((SpawnEggItem) stack.getItem()).getType(pointer.level().registryAccess(), stack); EntityType<?> entitytypes = ((SpawnEggItem) stack.getItem()).getType(pointer.level().registryAccess(), stack);
+ // CraftBukkit start + // CraftBukkit start
+ ServerLevel worldserver = pointer.level(); + 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()); + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+ +
@@ -52,12 +52,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return stack; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
@@ -81,18 +82,18 @@
} }
- stack.shrink(1); - stack.shrink(1);
+ // itemstack.shrink(1); // Handled during event processing + if (shrink) stack.shrink(1); // Paper - actually handle here
+ // CraftBukkit end + // CraftBukkit end
pointer.level().gameEvent((Entity) null, (Holder) GameEvent.ENTITY_PLACE, pointer.pos()); pointer.level().gameEvent((Entity) null, (Holder) GameEvent.ENTITY_PLACE, pointer.pos());
return stack; return stack;
} }
@@ -116,13 +162,42 @@ @@ -116,13 +163,43 @@
Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING);
BlockPos blockposition = pointer.pos().relative(enumdirection); BlockPos blockposition = pointer.pos().relative(enumdirection);
ServerLevel worldserver = pointer.level(); ServerLevel worldserver = pointer.level();
+ +
+ // CraftBukkit start + // 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()); + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+ +
@@ -102,12 +103,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return stack; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
@@ -127,17 +129,17 @@
if (entityarmorstand != null) { if (entityarmorstand != null) {
- stack.shrink(1); - stack.shrink(1);
+ // itemstack.shrink(1); // CraftBukkit - Handled during event processing + if (shrink) stack.shrink(1); // Paper - actually handle here
} }
return stack; return stack;
@@ -141,7 +216,34 @@ @@ -141,7 +218,36 @@
}); });
if (!list.isEmpty()) { if (!list.isEmpty()) {
- ((Saddleable) list.get(0)).equipSaddle(stack.split(1), SoundSource.BLOCKS); - ((Saddleable) list.get(0)).equipSaddle(stack.split(1), SoundSource.BLOCKS);
+ // CraftBukkit start + // CraftBukkit start
+ ItemStack itemstack1 = stack.split(1); + ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
+ ServerLevel world = pointer.level(); + ServerLevel world = pointer.level();
+ org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos()); + org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -148,12 +150,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return stack; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + 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 + ((Saddleable) list.get(0)).equipSaddle(CraftItemStack.asNMSCopy(event.getItem()), SoundSource.BLOCKS); // Paper - track changed items in dispense event
+ // CraftBukkit end + // CraftBukkit end
+ if (shrink) stack.shrink(1); // Paper - actually handle here
this.setSuccess(true); this.setSuccess(true);
return stack; return stack;
} else { } else {
@@ -166,9 +268,35 @@ @@ -166,9 +272,38 @@
} }
entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next(); entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next();
- } while (!entityhorsechestedabstract.isTamed() || !entityhorsechestedabstract.getSlot(499).set(stack)); - } while (!entityhorsechestedabstract.isTamed() || !entityhorsechestedabstract.getSlot(499).set(stack));
+ // CraftBukkit start + // CraftBukkit start
+ } while (!entityhorsechestedabstract.isTamed()); + } while (!entityhorsechestedabstract.isTamed());
+ ItemStack itemstack1 = stack.split(1); + ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below
+ ServerLevel world = pointer.level(); + ServerLevel world = pointer.level();
+ org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos()); + org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -186,10 +190,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + 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; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + 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())); + entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem()));
+ // CraftBukkit end + // CraftBukkit end
+ +
+ // itemstack.shrink(1); // CraftBukkit - handled above + if (shrink) stack.shrink(1); // Paper - actually handle here
this.setSuccess(true); this.setSuccess(true);
return stack; return stack;
} }
@@ -202,8 +330,50 @@ @@ -202,8 +337,50 @@
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
ServerLevel worldserver = pointer.level(); ServerLevel worldserver = pointer.level();
@@ -223,7 +230,7 @@
+ if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) { + if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) {
+ // Paper end - correctly check if the bucket place will succeed + // Paper end - correctly check if the bucket place will succeed
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); + 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)); + BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -257,7 +264,7 @@
return this.consumeWithRemainder(pointer, stack, new ItemStack(Items.BUCKET)); return this.consumeWithRemainder(pointer, stack, new ItemStack(Items.BUCKET));
} else { } else {
return this.defaultDispenseItemBehavior.dispense(pointer, stack); return this.defaultDispenseItemBehavior.dispense(pointer, stack);
@@ -229,7 +399,7 @@ @@ -229,7 +406,7 @@
Block block = iblockdata.getBlock(); Block block = iblockdata.getBlock();
if (block instanceof BucketPickup ifluidsource) { if (block instanceof BucketPickup ifluidsource) {
@@ -266,13 +273,13 @@
if (itemstack1.isEmpty()) { if (itemstack1.isEmpty()) {
return super.execute(pointer, stack); return super.execute(pointer, stack);
@@ -237,6 +407,32 @@ @@ -237,6 +414,32 @@
worldserver.gameEvent((Entity) null, (Holder) GameEvent.FLUID_PICKUP, blockposition); worldserver.gameEvent((Entity) null, (Holder) GameEvent.FLUID_PICKUP, blockposition);
Item item = itemstack1.getItem(); Item item = itemstack1.getItem();
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); + 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())); + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -299,13 +306,13 @@
return this.consumeWithRemainder(pointer, stack, new ItemStack(item)); return this.consumeWithRemainder(pointer, stack, new ItemStack(item));
} }
} else { } else {
@@ -249,16 +445,44 @@ @@ -249,16 +452,44 @@
protected ItemStack execute(BlockSource pointer, ItemStack stack) { protected ItemStack execute(BlockSource pointer, ItemStack stack) {
ServerLevel worldserver = pointer.level(); ServerLevel worldserver = pointer.level();
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); + 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)); + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -347,13 +354,13 @@
TntBlock.explode(worldserver, blockposition); TntBlock.explode(worldserver, blockposition);
worldserver.removeBlock(blockposition, false); worldserver.removeBlock(blockposition, false);
} else { } else {
@@ -283,13 +507,64 @@ @@ -283,13 +514,64 @@
this.setSuccess(true); this.setSuccess(true);
ServerLevel worldserver = pointer.level(); ServerLevel worldserver = pointer.level();
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos()); + 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)); + BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -412,7 +419,7 @@
return stack; return stack;
} }
}); });
@@ -298,12 +573,41 @@ @@ -298,12 +580,42 @@
protected ItemStack execute(BlockSource pointer, ItemStack stack) { protected ItemStack execute(BlockSource pointer, ItemStack stack) {
ServerLevel worldserver = pointer.level(); ServerLevel worldserver = pointer.level();
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
@@ -420,7 +427,7 @@
+ // CraftBukkit start + // CraftBukkit start
+ // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); + // 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()); + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+ +
@@ -430,12 +437,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return stack; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + 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.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); worldserver.gameEvent((Entity) null, (Holder) GameEvent.ENTITY_PLACE, blockposition);
- stack.shrink(1); - stack.shrink(1);
+ // itemstack.shrink(1); // CraftBukkit - handled above + if (shrink) stack.shrink(1); // Paper - actually handle here
return stack; return stack;
} }
}); });
@@ -313,7 +617,31 @@ @@ -313,7 +625,31 @@
ServerLevel worldserver = pointer.level(); ServerLevel worldserver = pointer.level();
Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING);
BlockPos blockposition = pointer.pos().relative(enumdirection); BlockPos blockposition = pointer.pos().relative(enumdirection);
+ +
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); + 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())); + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -488,7 +496,7 @@
if (worldserver.isEmptyBlock(blockposition) && WitherSkullBlock.canSpawnMob(worldserver, blockposition, stack)) { 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.setBlock(blockposition, (BlockState) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(enumdirection)), 3);
worldserver.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_PLACE, blockposition); worldserver.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_PLACE, blockposition);
@@ -326,7 +654,7 @@ @@ -326,7 +662,7 @@
stack.shrink(1); stack.shrink(1);
this.setSuccess(true); this.setSuccess(true);
} else { } else {
@@ -497,13 +505,13 @@
} }
return stack; return stack;
@@ -339,6 +667,30 @@ @@ -339,6 +675,30 @@
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN; CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN;
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); + 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())); + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -528,7 +536,7 @@
if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) { if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) {
if (!worldserver.isClientSide) { if (!worldserver.isClientSide) {
worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3); worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3);
@@ -348,7 +700,7 @@ @@ -348,7 +708,7 @@
stack.shrink(1); stack.shrink(1);
this.setSuccess(true); this.setSuccess(true);
} else { } else {
@@ -537,13 +545,13 @@
} }
return stack; return stack;
@@ -377,6 +729,30 @@ @@ -377,6 +737,30 @@
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
BlockState iblockdata = worldserver.getBlockState(blockposition); BlockState iblockdata = worldserver.getBlockState(blockposition);
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); + 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())); + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -568,7 +576,7 @@
if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> {
return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock;
}) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { }) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) {
@@ -402,6 +778,13 @@ @@ -402,6 +786,13 @@
this.setSuccess(true); this.setSuccess(true);
if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) { if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) {
if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) { if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) {
@@ -582,7 +590,7 @@
RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata); RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata);
stack.shrink(1); stack.shrink(1);
} else { } else {
@@ -426,6 +809,31 @@ @@ -426,6 +817,31 @@
this.setSuccess(false); this.setSuccess(false);
return stack; return stack;
} else { } else {
@@ -590,7 +598,7 @@
+ ItemStack itemstack1 = stack; + ItemStack itemstack1 = stack;
+ ServerLevel world = pointer.level(); + ServerLevel world = pointer.level();
+ org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos()); + 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()); + BlockDispenseEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity());
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {
@@ -614,7 +622,7 @@
Iterator iterator1 = list.iterator(); Iterator iterator1 = list.iterator();
Armadillo armadillo; Armadillo armadillo;
@@ -454,6 +862,13 @@ @@ -454,6 +870,13 @@
Optional<BlockState> optional = HoneycombItem.getWaxed(iblockdata); Optional<BlockState> optional = HoneycombItem.getWaxed(iblockdata);
if (optional.isPresent()) { if (optional.isPresent()) {
@@ -628,7 +636,7 @@
worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get()); worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get());
worldserver.levelEvent(3003, blockposition, 0); worldserver.levelEvent(3003, blockposition, 0);
stack.shrink(1); stack.shrink(1);
@@ -481,6 +896,12 @@ @@ -481,6 +904,12 @@
if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) { if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) {
return this.defaultDispenseItemBehavior.dispense(pointer, stack); return this.defaultDispenseItemBehavior.dispense(pointer, stack);
} else { } else {

View File

@@ -32,9 +32,12 @@
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING)); BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
List<LivingEntity> list = pointer.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> { List<LivingEntity> list = pointer.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> {
return entityliving.canEquipWithDispenser(stack); return entityliving.canEquipWithDispenser(stack);
@@ -34,7 +44,34 @@ @@ -32,9 +42,37 @@
} else {
LivingEntity entityliving = (LivingEntity) list.getFirst();
EquipmentSlot enumitemslot = entityliving.getEquipmentSlotForItem(stack); 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); - entityliving.setItemSlot(enumitemslot, itemstack1);
+ // CraftBukkit start + // CraftBukkit start
@@ -48,12 +51,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return false; + return false;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
@@ -68,3 +72,11 @@
if (entityliving instanceof Mob) { if (entityliving instanceof Mob) {
Mob entityinsentient = (Mob) entityliving; Mob entityinsentient = (Mob) entityliving;
@@ -42,6 +80,7 @@
entityinsentient.setPersistenceRequired();
}
+ if (shrink) stack.shrink(1); // Paper - shrink here
return true;
}
}

View File

@@ -19,7 +19,7 @@
- AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, vec3d1.x, vec3d1.y, vec3d1.z, this.entityType, EntitySpawnReason.DISPENSER, stack, (Player) null); - AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, vec3d1.x, vec3d1.y, vec3d1.z, this.entityType, EntitySpawnReason.DISPENSER, stack, (Player) null);
+ // CraftBukkit start + // CraftBukkit start
+ // EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, vec3d1.x, vec3d1.y, vec3d1.z, this.entityType, EntitySpawnReason.DISPENSER, itemstack, (EntityHuman) null); + // 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()); + org.bukkit.block.Block block2 = CraftBlock.at(worldserver, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -29,12 +29,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return stack; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior
@@ -50,8 +51,7 @@
if (entityminecartabstract != null) { if (entityminecartabstract != null) {
- worldserver.addFreshEntity(entityminecartabstract); - worldserver.addFreshEntity(entityminecartabstract);
- stack.shrink(1); - stack.shrink(1);
+ if (!worldserver.addFreshEntity(entityminecartabstract)) stack.grow(1); + if (worldserver.addFreshEntity(entityminecartabstract) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink
+ // itemstack.shrink(1); // CraftBukkit - handled during event processing
+ // CraftBukkit end + // CraftBukkit end
} }

View File

@@ -12,7 +12,7 @@
public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior {
@@ -31,8 +36,40 @@ @@ -31,8 +36,41 @@
Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING); Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING);
Position iposition = this.dispenseConfig.positionFunction().getDispensePosition(pointer, enumdirection); Position iposition = this.dispenseConfig.positionFunction().getDispensePosition(pointer, enumdirection);
@@ -20,7 +20,7 @@
- stack.shrink(1); - stack.shrink(1);
+ // CraftBukkit start + // 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 + // 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()); + org.bukkit.block.Block block = CraftBlock.at(worldserver, pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+ +
@@ -30,12 +30,13 @@
+ } + }
+ +
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ stack.grow(1); + // stack.grow(1); // Paper - shrink below
+ return stack; + return stack;
+ } + }
+ +
+ boolean shrink = true; // Paper
+ if (!event.getItem().equals(craftItem)) { + if (!event.getItem().equals(craftItem)) {
+ stack.grow(1); + shrink = false; // Paper - shrink below
+ // Chain to handler for new item + // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(pointer, eventStack); // Paper - Fix NPE with equippable and items without behavior + 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 + 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()); + 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 + // CraftBukkit end
return stack; return stack;
} }

View File

@@ -19,7 +19,7 @@
ServerLevel worldserver = pointer.level(); ServerLevel worldserver = pointer.level();
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, pointer.pos()); + 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)); + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {

View File

@@ -19,7 +19,7 @@
+ // CraftBukkit start + // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(pointer.level(), pointer.pos()); + 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())); + BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
+ if (!DispenserBlock.eventFired) { + if (!DispenserBlock.eventFired) {