mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-27 15:00:13 +01:00
net.minecraft.core.dispenser
This commit is contained in:
parent
732cf86b99
commit
f252b67a97
16 changed files with 1009 additions and 1168 deletions
|
@ -0,0 +1,45 @@
|
|||
--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
@@ -40,13 +_,39 @@
|
||||
d4 = 0.0;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink at end and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
AbstractBoat abstractBoat = this.type.create(serverLevel, EntitySpawnReason.DISPENSER);
|
||||
if (abstractBoat != null) {
|
||||
- abstractBoat.setInitialPos(d1, d2 + d4, d3);
|
||||
+ abstractBoat.setInitialPos(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); // CraftBukkit
|
||||
EntityType.<AbstractBoat>createDefaultStackConfig(serverLevel, item, null).accept(abstractBoat);
|
||||
abstractBoat.setYRot(direction.toYRot());
|
||||
- serverLevel.addFreshEntity(abstractBoat);
|
||||
- item.shrink(1);
|
||||
+ if (serverLevel.addFreshEntity(abstractBoat) && shrink) item.shrink(1); // Paper - if entity add was successful and supposed to shrink
|
||||
}
|
||||
|
||||
return item;
|
|
@ -0,0 +1,100 @@
|
|||
--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
@@ -8,25 +_,48 @@
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
|
||||
public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
|
||||
+ private Direction direction; // Paper - cache facing direction
|
||||
private static final int DEFAULT_ACCURACY = 6;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private boolean dropper;
|
||||
+
|
||||
+ public DefaultDispenseItemBehavior(boolean dropper) {
|
||||
+ this.dropper = dropper;
|
||||
+ }
|
||||
+
|
||||
+ public DefaultDispenseItemBehavior() {}
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
public final ItemStack dispense(BlockSource blockSource, ItemStack item) {
|
||||
+ this.direction = blockSource.state().getValue(DispenserBlock.FACING); // Paper - cache facing direction
|
||||
ItemStack itemStack = this.execute(blockSource, item);
|
||||
this.playSound(blockSource);
|
||||
- this.playAnimation(blockSource, blockSource.state().getValue(DispenserBlock.FACING));
|
||||
+ this.playAnimation(blockSource, this.direction); // Paper - cache facing direction
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
- Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
+ // Paper - cached enum direction
|
||||
Position dispensePosition = DispenserBlock.getDispensePosition(blockSource);
|
||||
ItemStack itemStack = item.split(1);
|
||||
- spawnItem(blockSource.level(), itemStack, 6, direction, dispensePosition);
|
||||
+ // CraftBukkit start
|
||||
+ if (!DefaultDispenseItemBehavior.spawnItem(blockSource.level(), itemStack, 6, this.direction, dispensePosition, blockSource, this.dropper)) {
|
||||
+ item.grow(1);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return item;
|
||||
}
|
||||
|
||||
public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position position) {
|
||||
+ // CraftBukkit start
|
||||
+ ItemEntity itemEntity = prepareItem(level, stack, speed, facing, position);
|
||||
+ level.addFreshEntity(itemEntity);
|
||||
+ }
|
||||
+
|
||||
+ private static ItemEntity prepareItem(Level level, ItemStack stack, int speed, Direction facing, Position position) {
|
||||
+ // CraftBukkit end
|
||||
double d = position.x();
|
||||
double d1 = position.y();
|
||||
double d2 = position.z();
|
||||
@@ -44,6 +_,45 @@
|
||||
level.random.triangle(facing.getStepZ() * d3, 0.0172275 * speed)
|
||||
);
|
||||
level.addFreshEntity(itemEntity);
|
||||
+ return itemEntity; // CraftBukkit
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper
|
||||
+ public static boolean spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position dispensePosition, BlockSource blockSource, boolean dropper) {
|
||||
+ if (stack.isEmpty()) return true;
|
||||
+ ItemEntity itemEntity = DefaultDispenseItemBehavior.prepareItem(level, stack, speed, facing, dispensePosition);
|
||||
+
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(itemEntity.getDeltaMovement()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ itemEntity.setItem(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ itemEntity.setDeltaMovement(org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getVelocity()));
|
||||
+
|
||||
+ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior.getClass() != DefaultDispenseItemBehavior.class) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ } else {
|
||||
+ level.addFreshEntity(itemEntity);
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ level.addFreshEntity(itemEntity);
|
||||
+
|
||||
+ return true;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
protected void playSound(BlockSource blockSource) {
|
|
@ -0,0 +1,606 @@
|
|||
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -43,7 +_,9 @@
|
||||
import net.minecraft.world.level.block.CandleCakeBlock;
|
||||
import net.minecraft.world.level.block.CarvedPumpkinBlock;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
+import net.minecraft.world.level.block.LiquidBlockContainer;
|
||||
import net.minecraft.world.level.block.RespawnAnchorBlock;
|
||||
+import net.minecraft.world.level.block.SaplingBlock;
|
||||
import net.minecraft.world.level.block.ShulkerBoxBlock;
|
||||
import net.minecraft.world.level.block.SkullBlock;
|
||||
import net.minecraft.world.level.block.TntBlock;
|
||||
@@ -82,16 +_,48 @@
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
EntityType<?> type = ((SpawnEggItem)item.getItem()).getType(blockSource.level().registryAccess(), item);
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ ServerLevel serverLevel = blockSource.level();
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ // Paper start - track changed items in the dispense event
|
||||
+ itemstack1 = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()); // unwrap is safe because the stack won't be modified
|
||||
+ type = ((SpawnEggItem) itemstack1.getItem()).getType(serverLevel.registryAccess(), itemstack1);
|
||||
+ // Paper end - track changed item from dispense event
|
||||
+ }
|
||||
try {
|
||||
type.spawn(
|
||||
- blockSource.level(), item, null, blockSource.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false
|
||||
+ blockSource.level(), itemstack1, null, blockSource.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false // Paper - track changed item in dispense event
|
||||
);
|
||||
} catch (Exception var6) {
|
||||
LOGGER.error("Error while dispensing spawn egg from dispenser at {}", blockSource.pos(), var6);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
- item.shrink(1);
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
+ // CraftBukkit end
|
||||
blockSource.level().gameEvent(null, GameEvent.ENTITY_PLACE, blockSource.pos());
|
||||
return item;
|
||||
}
|
||||
@@ -109,12 +_,40 @@
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ final ItemStack newStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()); // Paper - use event itemstack (unwrap is fine here because the stack won't be modified)
|
||||
Consumer<ArmorStand> consumer = EntityType.appendDefaultStackConfig(
|
||||
- armorStand1 -> armorStand1.setYRot(direction.toYRot()), serverLevel, item, null
|
||||
+ armorStand1 -> armorStand1.setYRot(direction.toYRot()), serverLevel, newStack, null // Paper - track changed items in the dispense event
|
||||
);
|
||||
ArmorStand armorStand = EntityType.ARMOR_STAND.spawn(serverLevel, consumer, blockPos, EntitySpawnReason.DISPENSER, false, false);
|
||||
if (armorStand != null) {
|
||||
- item.shrink(1);
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -134,7 +_,36 @@
|
||||
livingEntity -> livingEntity instanceof Saddleable saddleable && !saddleable.isSaddled() && saddleable.isSaddleable()
|
||||
);
|
||||
if (!entitiesOfClass.isEmpty()) {
|
||||
- ((Saddleable)entitiesOfClass.get(0)).equipSaddle(item.split(1), SoundSource.BLOCKS);
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ ServerLevel world = blockSource.level();
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ ((Saddleable) entitiesOfClass.get(0)).equipSaddle(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), SoundSource.BLOCKS); // Paper - track changed items in dispense event
|
||||
+ // CraftBukkit end
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
this.setSuccess(true);
|
||||
return item;
|
||||
} else {
|
||||
@@ -156,8 +_,36 @@
|
||||
new AABB(blockPos),
|
||||
abstractChestedHorse1 -> abstractChestedHorse1.isAlive() && !abstractChestedHorse1.hasChest()
|
||||
)) {
|
||||
- if (abstractChestedHorse.isTamed() && abstractChestedHorse.getSlot(499).set(item)) {
|
||||
- item.shrink(1);
|
||||
+ if (abstractChestedHorse.isTamed()/* && abstractChestedHorse.getSlot(499).set(item)*/) {
|
||||
+ ItemStack singleCopy = item.copyWithCount(1); // Paper - shrink below
|
||||
+ ServerLevel world = blockSource.level();
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleCopy);
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), abstractChestedHorse.getBukkitLivingEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ 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 item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ abstractChestedHorse.getSlot(499).set(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
this.setSuccess(true);
|
||||
return item;
|
||||
}
|
||||
@@ -195,8 +_,50 @@
|
||||
DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem)item.getItem();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
Level level = blockSource.level();
|
||||
+ // CraftBukkit start
|
||||
+ int x = blockPos.getX();
|
||||
+ int y = blockPos.getY();
|
||||
+ int z = blockPos.getZ();
|
||||
+ BlockState iblockdata = level.getBlockState(blockPos);
|
||||
+ ItemStack dispensedItem = item; // Paper - track changed item from the dispense event
|
||||
+ // Paper start - correctly check if the bucket place will succeed
|
||||
+ /* Taken from SolidBucketItem#emptyContents */
|
||||
+ boolean willEmptyContentsSolidBucketItem = dispensibleContainerItem instanceof net.minecraft.world.item.SolidBucketItem && level.isInWorldBounds(blockPos) && iblockdata.isAir();
|
||||
+ /* Taken from BucketItem#emptyContents */
|
||||
+ boolean willEmptyBucketItem = dispensibleContainerItem instanceof final net.minecraft.world.item.BucketItem bucketItem && bucketItem.content instanceof net.minecraft.world.level.material.FlowingFluid && (iblockdata.isAir() || iblockdata.canBeReplaced(bucketItem.content) || (iblockdata.getBlock() instanceof LiquidBlockContainer liquidBlockContainer && liquidBlockContainer.canPlaceLiquid(null, level, blockPos, iblockdata, bucketItem.content)));
|
||||
+ if (willEmptyContentsSolidBucketItem || willEmptyBucketItem) {
|
||||
+ // Paper end - correctly check if the bucket place will succeed
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - track changed item from dispense event
|
||||
+ dispensedItem = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()); // unwrap is safe here as the stack isn't mutated
|
||||
+ dispensibleContainerItem = (DispensibleContainerItem) dispensedItem.getItem();
|
||||
+ // Paper end - track changed item from dispense event
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (dispensibleContainerItem.emptyContents(null, level, blockPos, null)) {
|
||||
- dispensibleContainerItem.checkExtraContent(null, level, item, blockPos);
|
||||
+ dispensibleContainerItem.checkExtraContent(null, level, dispensedItem, blockPos); // Paper - track changed item from dispense event
|
||||
return this.consumeWithRemainder(blockSource, item, new ItemStack(Items.BUCKET));
|
||||
} else {
|
||||
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
|
||||
@@ -219,12 +_,37 @@
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
BlockState blockState = levelAccessor.getBlockState(blockPos);
|
||||
if (blockState.getBlock() instanceof BucketPickup bucketPickup) {
|
||||
- ItemStack itemStack = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState);
|
||||
+ ItemStack itemStack = bucketPickup.pickupBlock(null, org.bukkit.craftbukkit.util.DummyGeneratorAccess.INSTANCE, blockPos, blockState); // CraftBukkit
|
||||
if (itemStack.isEmpty()) {
|
||||
return super.execute(blockSource, item);
|
||||
} else {
|
||||
levelAccessor.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos);
|
||||
Item item1 = itemStack.getItem();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ levelAccessor.getMinecraftWorld().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ itemStack = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState); // From above
|
||||
+ // CraftBukkit end
|
||||
return this.consumeWithRemainder(blockSource, item, new ItemStack(item1));
|
||||
}
|
||||
} else {
|
||||
@@ -236,17 +_,44 @@
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.setSuccess(true);
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
BlockState blockState = serverLevel.getBlockState(blockPos);
|
||||
if (BaseFireBlock.canBePlacedAt(serverLevel, blockPos, direction)) {
|
||||
- serverLevel.setBlockAndUpdate(blockPos, BaseFireBlock.getState(serverLevel, blockPos));
|
||||
- serverLevel.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos);
|
||||
+ // CraftBukkit start - Ignition by dispensing flint and steel
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(serverLevel, blockPos, blockSource.pos()).isCancelled()) {
|
||||
+ serverLevel.setBlockAndUpdate(blockPos, BaseFireBlock.getState(serverLevel, blockPos));
|
||||
+ serverLevel.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
} else if (CampfireBlock.canLight(blockState) || CandleBlock.canLight(blockState) || CandleCakeBlock.canLight(blockState)) {
|
||||
serverLevel.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)));
|
||||
serverLevel.gameEvent(null, GameEvent.BLOCK_CHANGE, blockPos);
|
||||
- } else if (blockState.getBlock() instanceof TntBlock) {
|
||||
+ } else if (blockState.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(serverLevel, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, blockSource.pos())) { // CraftBukkit - TNTPrimeEvent
|
||||
TntBlock.explode(serverLevel, blockPos);
|
||||
serverLevel.removeBlock(blockPos, false);
|
||||
} else {
|
||||
@@ -266,11 +_,62 @@
|
||||
this.setSuccess(true);
|
||||
Level level = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ level.captureTreeGeneration = true;
|
||||
+ // CraftBukkit end
|
||||
if (!BoneMealItem.growCrop(item, level, blockPos) && !BoneMealItem.growWaterPlant(item, level, blockPos, null)) {
|
||||
this.setSuccess(false);
|
||||
} else if (!level.isClientSide) {
|
||||
level.levelEvent(1505, blockPos, 15);
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ level.captureTreeGeneration = false;
|
||||
+ if (level.capturedBlockStates.size() > 0) {
|
||||
+ org.bukkit.TreeType treeType = SaplingBlock.treeType;
|
||||
+ SaplingBlock.treeType = null;
|
||||
+ org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(blockPos, level.getWorld());
|
||||
+ List<org.bukkit.block.BlockState> blocks = new java.util.ArrayList<>(level.capturedBlockStates.values());
|
||||
+ level.capturedBlockStates.clear();
|
||||
+ org.bukkit.event.world.StructureGrowEvent structureEvent = null;
|
||||
+ if (treeType != null) {
|
||||
+ structureEvent = new org.bukkit.event.world.StructureGrowEvent(location, treeType, false, null, blocks);
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent);
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.block.BlockFertilizeEvent fertilizeEvent = new org.bukkit.event.block.BlockFertilizeEvent(location.getBlock(), null, blocks);
|
||||
+ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled());
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent);
|
||||
+
|
||||
+ if (!fertilizeEvent.isCancelled()) {
|
||||
+ for (org.bukkit.block.BlockState blockstate : blocks) {
|
||||
+ blockstate.update(true);
|
||||
+ blockSource.level().checkCapturedTreeStateForObserverNotify(blockPos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -280,11 +_,39 @@
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
Level level = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
- PrimedTnt primedTnt = new PrimedTnt(level, blockPos.getX() + 0.5, blockPos.getY(), blockPos.getZ() + 0.5, null);
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink at end and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ PrimedTnt primedTnt = new PrimedTnt(level, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
|
||||
+ // CraftBukkit end
|
||||
level.addFreshEntity(primedTnt);
|
||||
level.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos);
|
||||
- item.shrink(1);
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
return item;
|
||||
}
|
||||
});
|
||||
@@ -296,6 +_,29 @@
|
||||
Level level = blockSource.level();
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (level.isEmptyBlock(blockPos) && WitherSkullBlock.canSpawnMob(level, blockPos, item)) {
|
||||
level.setBlock(
|
||||
blockPos,
|
||||
@@ -313,7 +_,7 @@
|
||||
item.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(blockSource, item));
|
||||
+ this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(blockSource, item, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -326,6 +_,29 @@
|
||||
Level level = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
CarvedPumpkinBlock carvedPumpkinBlock = (CarvedPumpkinBlock)Blocks.CARVED_PUMPKIN;
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (level.isEmptyBlock(blockPos) && carvedPumpkinBlock.canSpawnGolem(level, blockPos)) {
|
||||
if (!level.isClientSide) {
|
||||
level.setBlock(blockPos, carvedPumpkinBlock.defaultBlockState(), 3);
|
||||
@@ -335,7 +_,7 @@
|
||||
item.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(blockSource, item));
|
||||
+ this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(blockSource, item, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -361,6 +_,29 @@
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
BlockState blockState = serverLevel.getBlockState(blockPos);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - only single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (blockState.is(
|
||||
BlockTags.BEEHIVES,
|
||||
blockStateBase -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockStateBase.getBlock() instanceof BeehiveBlock
|
||||
@@ -389,6 +_,13 @@
|
||||
this.setSuccess(true);
|
||||
if (blockState.is(Blocks.RESPAWN_ANCHOR)) {
|
||||
if (blockState.getValue(RespawnAnchorBlock.CHARGE) != 4) {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
RespawnAnchorBlock.charge(null, level, blockPos, blockState);
|
||||
item.shrink(1);
|
||||
} else {
|
||||
@@ -412,6 +_,29 @@
|
||||
this.setSuccess(false);
|
||||
return item;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
for (Armadillo armadillo : entitiesOfClass) {
|
||||
if (armadillo.brushOffScute()) {
|
||||
item.hurtAndBreak(16, serverLevel, null, item1 -> {});
|
||||
@@ -432,6 +_,13 @@
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
Optional<BlockState> waxed = HoneycombItem.getWaxed(blockState);
|
||||
if (waxed.isPresent()) {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos, item, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
level.setBlockAndUpdate(blockPos, waxed.get());
|
||||
level.levelEvent(3003, blockPos, 0);
|
||||
item.shrink(1);
|
||||
@@ -459,6 +_,12 @@
|
||||
if (!serverLevel.getBlockState(blockPos1).is(BlockTags.CONVERTABLE_TO_MUD)) {
|
||||
return this.defaultDispenseItemBehavior.dispense(blockSource, item);
|
||||
} else {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(blockSource, blockPos1, item, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
if (!serverLevel.isClientSide) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
serverLevel.sendParticles(
|
|
@ -0,0 +1,61 @@
|
|||
--- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
@@ -17,7 +_,13 @@
|
||||
return dispenseEquipment(blockSource, item) ? item : super.execute(blockSource, item);
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
|
||||
public static boolean dispenseEquipment(BlockSource blockSource, ItemStack item) {
|
||||
+ // Paper start
|
||||
+ return dispenseEquipment(blockSource, item, null);
|
||||
+ }
|
||||
+ public static boolean dispenseEquipment(BlockSource blockSource, ItemStack item, @javax.annotation.Nullable DispenseItemBehavior currentBehavior) {
|
||||
+ // Paper end
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
List<LivingEntity> entitiesOfClass = blockSource.level()
|
||||
.getEntitiesOfClass(LivingEntity.class, new AABB(blockPos), entity -> entity.canEquipWithDispenser(item));
|
||||
@@ -26,13 +_,42 @@
|
||||
} else {
|
||||
LivingEntity livingEntity = entitiesOfClass.getFirst();
|
||||
EquipmentSlot equipmentSlotForItem = livingEntity.getEquipmentSlotForItem(item);
|
||||
- ItemStack itemStack = item.split(1);
|
||||
- livingEntity.setItemSlot(equipmentSlotForItem, itemStack);
|
||||
+ ItemStack itemStack = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ // CraftBukkit start
|
||||
+ net.minecraft.world.level.Level world = blockSource.level();
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) livingEntity.getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || dispenseItemBehavior != currentBehavior)) { // Paper - fix possible StackOverflowError
|
||||
+ dispenseItemBehavior.dispense(blockSource, eventStack);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ livingEntity.setItemSlot(equipmentSlotForItem, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
if (livingEntity instanceof Mob mob) {
|
||||
mob.setDropChance(equipmentSlotForItem, 2.0F);
|
||||
mob.setPersistenceRequired();
|
||||
}
|
||||
|
||||
+ if (shrink) item.shrink(1); // Paper - shrink here
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
--- a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||
@@ -57,12 +_,38 @@
|
||||
}
|
||||
|
||||
Vec3 vec31 = new Vec3(d, d1 + d3, d2);
|
||||
- AbstractMinecart abstractMinecart = AbstractMinecart.createMinecart(
|
||||
- serverLevel, vec31.x, vec31.y, vec31.z, this.entityType, EntitySpawnReason.DISPENSER, item, null
|
||||
- );
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ org.bukkit.block.Block block2 = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(vec31.x, vec31.y, vec31.z));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseItemBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseItemBehavior != DispenseItemBehavior.NOOP && dispenseItemBehavior != this) {
|
||||
+ dispenseItemBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ itemstack1 = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ AbstractMinecart abstractMinecart = AbstractMinecart.createMinecart(serverLevel, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.entityType, EntitySpawnReason.DISPENSER, itemstack1, null);
|
||||
+
|
||||
if (abstractMinecart != null) {
|
||||
- serverLevel.addFreshEntity(abstractMinecart);
|
||||
- item.shrink(1);
|
||||
+ if (serverLevel.addFreshEntity(abstractMinecart) && shrink) item.shrink(1); // Paper - if entity add was successful and supposed to shrink
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
return item;
|
|
@ -0,0 +1,52 @@
|
|||
--- a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
|
||||
@@ -27,16 +_,39 @@
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
Direction direction = blockSource.state().getValue(DispenserBlock.FACING);
|
||||
Position dispensePosition = this.dispenseConfig.positionFunction().getDispensePosition(blockSource, direction);
|
||||
- Projectile.spawnProjectileUsingShoot(
|
||||
- this.projectileItem.asProjectile(serverLevel, dispensePosition, item, direction),
|
||||
- serverLevel,
|
||||
- item,
|
||||
- direction.getStepX(),
|
||||
- direction.getStepY(),
|
||||
- direction.getStepZ(),
|
||||
- this.dispenseConfig.power(),
|
||||
- this.dispenseConfig.uncertainty()
|
||||
- );
|
||||
+ ItemStack itemstack1 = item.copyWithCount(1); // Paper - shrink below and single item in event
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // item.grow(1); // Paper - shrink below
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ boolean shrink = true; // Paper
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ shrink = false; // Paper - shrink below
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // SPIGOT-7923: Avoid create projectiles with empty item
|
||||
+ if (!itemstack1.isEmpty()) {
|
||||
+ Projectile iprojectile = Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(serverLevel, dispensePosition, org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getItem()), direction), serverLevel, 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(blockSource.blockEntity());
|
||||
+ }
|
||||
+ if (shrink) item.shrink(1); // Paper - actually handle here
|
||||
+ // CraftBukkit end
|
||||
item.shrink(1);
|
||||
return item;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
@@ -20,9 +_,32 @@
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
|
||||
ServerLevel serverLevel = blockSource.level();
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ serverLevel.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
if (!serverLevel.isClientSide()) {
|
||||
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
|
||||
- this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos, item));
|
||||
+ this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos, item, bukkitBlock, craftItem)); // CraftBukkit
|
||||
if (this.isSuccess()) {
|
||||
item.hurtAndBreak(1, serverLevel, null, item1 -> {});
|
||||
}
|
||||
@@ -50,10 +_,18 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
- private static boolean tryShearLivingEntity(ServerLevel level, BlockPos pos, ItemStack stack) {
|
||||
+ private static boolean tryShearLivingEntity(ServerLevel level, BlockPos pos, ItemStack stack, org.bukkit.block.Block bukkitBlock, org.bukkit.craftbukkit.inventory.CraftItemStack craftItem) { // CraftBukkit - add args
|
||||
for (LivingEntity livingEntity : level.getEntitiesOfClass(LivingEntity.class, new AABB(pos), EntitySelector.NO_SPECTATORS)) {
|
||||
if (livingEntity instanceof Shearable shearable && shearable.readyForShearing()) {
|
||||
- shearable.shear(level, SoundSource.BLOCKS, stack);
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - Add drops to shear events
|
||||
+ org.bukkit.event.block.BlockShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockShearEntityEvent(livingEntity, bukkitBlock, craftItem, shearable.generateDefaultDrops(level, stack));
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Paper end - Add drops to shear events
|
||||
+ continue;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ shearable.shear(level, SoundSource.BLOCKS, stack, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops())); // Paper - Add drops to shear events
|
||||
level.gameEvent(null, GameEvent.SHEAR, pos);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
@@ -22,10 +_,38 @@
|
||||
BlockPos blockPos = blockSource.pos().relative(direction);
|
||||
Direction direction1 = blockSource.level().isEmptyBlock(blockPos.below()) ? direction : Direction.UP;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(blockSource.level(), blockSource.pos());
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event
|
||||
+
|
||||
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ blockSource.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior dispenseBehavior = DispenserBlock.getDispenseBehavior(blockSource, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (dispenseBehavior != DispenseItemBehavior.NOOP && dispenseBehavior != this) {
|
||||
+ dispenseBehavior.dispense(blockSource, eventStack);
|
||||
+ return item;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
try {
|
||||
+ // Paper start - track changed items in the dispense event
|
||||
this.setSuccess(
|
||||
- ((BlockItem)item1).place(new DirectionalPlaceContext(blockSource.level(), blockPos, direction, item, direction1)).consumesAction()
|
||||
+ ((BlockItem) item1).place(new DirectionalPlaceContext(blockSource.level(), blockPos, direction, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItem()), direction1)).consumesAction()
|
||||
);
|
||||
+ if (this.isSuccess()) {
|
||||
+ item.shrink(1); // vanilla shrink is in the place function above, manually handle it here
|
||||
+ }
|
||||
+ // Paper end - track changed items in the dispense event
|
||||
} catch (Exception var8) {
|
||||
LOGGER.error("Error trying to place shulker box at {}", blockPos, var8);
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
@@ -11,6 +11,11 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||
|
||||
@@ -43,14 +48,40 @@
|
||||
d4 = 0.0D;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ 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);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
AbstractBoat abstractboat = (AbstractBoat) this.type.create(worldserver, EntitySpawnReason.DISPENSER);
|
||||
|
||||
if (abstractboat != null) {
|
||||
- abstractboat.setInitialPos(d1, d2 + d4, d3);
|
||||
+ abstractboat.setInitialPos(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); // CraftBukkit
|
||||
EntityType.createDefaultStackConfig(worldserver, stack, (Player) null).accept(abstractboat);
|
||||
abstractboat.setYRot(enumdirection.toYRot());
|
||||
- worldserver.addFreshEntity(abstractboat);
|
||||
- stack.shrink(1);
|
||||
+ if (worldserver.addFreshEntity(abstractboat) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink
|
||||
}
|
||||
|
||||
return stack;
|
|
@ -1,126 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java
|
||||
@@ -6,47 +6,114 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.craftbukkit.util.CraftVector;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class DefaultDispenseItemBehavior implements DispenseItemBehavior {
|
||||
+ private Direction enumdirection; // Paper - cache facing direction
|
||||
|
||||
private static final int DEFAULT_ACCURACY = 6;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private boolean dropper;
|
||||
+
|
||||
+ public DefaultDispenseItemBehavior(boolean dropper) {
|
||||
+ this.dropper = dropper;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public DefaultDispenseItemBehavior() {}
|
||||
|
||||
@Override
|
||||
public final ItemStack dispense(BlockSource pointer, ItemStack stack) {
|
||||
+ enumdirection = pointer.state().getValue(DispenserBlock.FACING); // Paper - cache facing direction
|
||||
ItemStack itemstack1 = this.execute(pointer, stack);
|
||||
|
||||
this.playSound(pointer);
|
||||
- this.playAnimation(pointer, (Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
+ this.playAnimation(pointer, enumdirection); // Paper - cache facing direction
|
||||
return itemstack1;
|
||||
}
|
||||
|
||||
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
|
||||
- Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING);
|
||||
+ // Paper - cached enum direction
|
||||
Position iposition = DispenserBlock.getDispensePosition(pointer);
|
||||
ItemStack itemstack1 = stack.split(1);
|
||||
|
||||
- DefaultDispenseItemBehavior.spawnItem(pointer.level(), itemstack1, 6, enumdirection, iposition);
|
||||
+ // CraftBukkit start
|
||||
+ if (!DefaultDispenseItemBehavior.spawnItem(pointer.level(), itemstack1, 6, enumdirection, pointer, this.dropper)) {
|
||||
+ stack.grow(1);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static void spawnItem(Level world, ItemStack stack, int speed, Direction side, Position pos) {
|
||||
- double d0 = pos.x();
|
||||
- double d1 = pos.y();
|
||||
- double d2 = pos.z();
|
||||
+ // CraftBukkit start
|
||||
+ ItemEntity entityitem = DefaultDispenseItemBehavior.prepareItem(world, stack, speed, side, pos);
|
||||
+ world.addFreshEntity(entityitem);
|
||||
+ }
|
||||
|
||||
- if (side.getAxis() == Direction.Axis.Y) {
|
||||
+ private static ItemEntity prepareItem(Level world, ItemStack itemstack, int i, Direction enumdirection, Position iposition) {
|
||||
+ // CraftBukkit end
|
||||
+ double d0 = iposition.x();
|
||||
+ double d1 = iposition.y();
|
||||
+ double d2 = iposition.z();
|
||||
+
|
||||
+ if (enumdirection.getAxis() == Direction.Axis.Y) {
|
||||
d1 -= 0.125D;
|
||||
} else {
|
||||
d1 -= 0.15625D;
|
||||
}
|
||||
|
||||
- ItemEntity entityitem = new ItemEntity(world, d0, d1, d2, stack);
|
||||
+ ItemEntity entityitem = new ItemEntity(world, d0, d1, d2, itemstack);
|
||||
double d3 = world.random.nextDouble() * 0.1D + 0.2D;
|
||||
|
||||
- entityitem.setDeltaMovement(world.random.triangle((double) side.getStepX() * d3, 0.0172275D * (double) speed), world.random.triangle(0.2D, 0.0172275D * (double) speed), world.random.triangle((double) side.getStepZ() * d3, 0.0172275D * (double) speed));
|
||||
+ entityitem.setDeltaMovement(world.random.triangle((double) enumdirection.getStepX() * d3, 0.0172275D * (double) i), world.random.triangle(0.2D, 0.0172275D * (double) i), world.random.triangle((double) enumdirection.getStepZ() * d3, 0.0172275D * (double) i));
|
||||
+ // CraftBukkit start
|
||||
+ return entityitem;
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper
|
||||
+ public static boolean spawnItem(Level world, ItemStack itemstack, int i, Direction enumdirection, BlockSource sourceblock, boolean dropper) {
|
||||
+ if (itemstack.isEmpty()) return true;
|
||||
+ Position iposition = DispenserBlock.getDispensePosition(sourceblock);
|
||||
+ ItemEntity entityitem = DefaultDispenseItemBehavior.prepareItem(world, itemstack, i, enumdirection, iposition);
|
||||
+
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ entityitem.setItem(CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ entityitem.setDeltaMovement(CraftVector.toNMS(event.getVelocity()));
|
||||
+
|
||||
+ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) {
|
||||
+ // Chain to handler for new item
|
||||
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ DispenseItemBehavior idispensebehavior = DispenserBlock.getDispenseBehavior(sourceblock, eventStack); // Paper - Fix NPE with equippable and items without behavior
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior.getClass() != DefaultDispenseItemBehavior.class) {
|
||||
+ idispensebehavior.dispense(sourceblock, eventStack);
|
||||
+ } else {
|
||||
+ world.addFreshEntity(entityitem);
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
world.addFreshEntity(entityitem);
|
||||
+
|
||||
+ return true;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
protected void playSound(BlockSource pointer) {
|
|
@ -1,651 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -28,6 +28,7 @@
|
||||
import net.minecraft.world.entity.item.PrimedTnt;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BoneMealItem;
|
||||
+import net.minecraft.world.item.BucketItem;
|
||||
import net.minecraft.world.item.DispensibleContainerItem;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.item.HoneycombItem;
|
||||
@@ -47,7 +48,9 @@
|
||||
import net.minecraft.world.level.block.CandleCakeBlock;
|
||||
import net.minecraft.world.level.block.CarvedPumpkinBlock;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
+import net.minecraft.world.level.block.LiquidBlockContainer;
|
||||
import net.minecraft.world.level.block.RespawnAnchorBlock;
|
||||
+import net.minecraft.world.level.block.SaplingBlock;
|
||||
import net.minecraft.world.level.block.ShulkerBoxBlock;
|
||||
import net.minecraft.world.level.block.SkullBlock;
|
||||
import net.minecraft.world.level.block.TntBlock;
|
||||
@@ -62,6 +65,17 @@
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import org.slf4j.Logger;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.TreeType;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
+import org.bukkit.craftbukkit.util.DummyGeneratorAccess;
|
||||
+import org.bukkit.event.block.BlockDispenseArmorEvent;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+import org.bukkit.event.block.BlockFertilizeEvent;
|
||||
+import org.bukkit.event.world.StructureGrowEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public interface DispenseItemBehavior {
|
||||
|
||||
@@ -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.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);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ // Paper start - track changed items in the dispense event
|
||||
+ itemstack1 = CraftItemStack.unwrap(event.getItem()); // unwrap is safe because the stack won't be modified
|
||||
+ entitytypes = ((SpawnEggItem) itemstack1.getItem()).getType(worldserver.registryAccess(), itemstack1);
|
||||
+ // Paper end - track changed item from dispense event
|
||||
+ }
|
||||
+
|
||||
try {
|
||||
- entitytypes.spawn(pointer.level(), stack, (Player) null, pointer.pos().relative(enumdirection), EntitySpawnReason.DISPENSER, enumdirection != Direction.UP, false);
|
||||
+ entitytypes.spawn(pointer.level(), itemstack1, (Player) null, pointer.pos().relative(enumdirection), EntitySpawnReason.DISPENSER, enumdirection != Direction.UP, false); // Paper - track changed item in dispense event
|
||||
} catch (Exception exception) {
|
||||
- null.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", pointer.pos(), exception);
|
||||
+ DispenseItemBehavior.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", pointer.pos(), exception); // CraftBukkit - decompile error
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
- stack.shrink(1);
|
||||
+ 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 +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.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);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ final ItemStack newStack = CraftItemStack.unwrap(event.getItem()); // Paper - use event itemstack (unwrap is fine here because the stack won't be modified)
|
||||
Consumer<ArmorStand> consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> {
|
||||
entityarmorstand.setYRot(enumdirection.toYRot());
|
||||
- }, worldserver, stack, (Player) null);
|
||||
+ }, worldserver, newStack, (Player) null); // Paper - track changed items in the dispense event
|
||||
ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, consumer, blockposition, EntitySpawnReason.DISPENSER, false, false);
|
||||
|
||||
if (entityarmorstand != null) {
|
||||
- stack.shrink(1);
|
||||
+ if (shrink) stack.shrink(1); // Paper - actually handle here
|
||||
}
|
||||
|
||||
return stack;
|
||||
@@ -141,7 +218,36 @@
|
||||
});
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
- ((Saddleable) list.get(0)).equipSaddle(stack.split(1), SoundSource.BLOCKS);
|
||||
+ // CraftBukkit start
|
||||
+ 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);
|
||||
+
|
||||
+ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ ((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 +272,38 @@
|
||||
}
|
||||
|
||||
entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next();
|
||||
- } while (!entityhorsechestedabstract.isTamed() || !entityhorsechestedabstract.getSlot(499).set(stack));
|
||||
+ // CraftBukkit start
|
||||
+ } while (!entityhorsechestedabstract.isTamed());
|
||||
+ 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);
|
||||
|
||||
- stack.shrink(1);
|
||||
+ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ if (shrink) stack.shrink(1); // Paper - actually handle here
|
||||
this.setSuccess(true);
|
||||
return stack;
|
||||
}
|
||||
@@ -202,8 +337,50 @@
|
||||
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
ServerLevel worldserver = pointer.level();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ int x = blockposition.getX();
|
||||
+ int y = blockposition.getY();
|
||||
+ int z = blockposition.getZ();
|
||||
+ BlockState iblockdata = worldserver.getBlockState(blockposition);
|
||||
+ ItemStack dispensedItem = stack; // Paper - track changed item from the dispense event
|
||||
+ // Paper start - correctly check if the bucket place will succeed
|
||||
+ /* Taken from SolidBucketItem#emptyContents */
|
||||
+ boolean willEmptyContentsSolidBucketItem = dispensiblecontaineritem instanceof net.minecraft.world.item.SolidBucketItem && worldserver.isInWorldBounds(blockposition) && iblockdata.isAir();
|
||||
+ /* Taken from BucketItem#emptyContents */
|
||||
+ boolean willEmptyBucketItem = dispensiblecontaineritem instanceof final BucketItem bucketItem && bucketItem.content instanceof net.minecraft.world.level.material.FlowingFluid && (iblockdata.isAir() || iblockdata.canBeReplaced(bucketItem.content) || (iblockdata.getBlock() instanceof LiquidBlockContainer liquidBlockContainer && liquidBlockContainer.canPlaceLiquid(null, worldserver, blockposition, iblockdata, bucketItem.content)));
|
||||
+ 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.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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - track changed item from dispense event
|
||||
+ dispensedItem = CraftItemStack.unwrap(event.getItem()); // unwrap is safe here as the stack isn't mutated
|
||||
+ dispensiblecontaineritem = (DispensibleContainerItem) dispensedItem.getItem();
|
||||
+ // Paper end - track changed item from dispense event
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) {
|
||||
- dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, stack, blockposition);
|
||||
+ dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, dispensedItem, blockposition); // Paper - track changed item from dispense event
|
||||
return this.consumeWithRemainder(pointer, stack, new ItemStack(Items.BUCKET));
|
||||
} else {
|
||||
return this.defaultDispenseItemBehavior.dispense(pointer, stack);
|
||||
@@ -229,7 +406,7 @@
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block instanceof BucketPickup ifluidsource) {
|
||||
- ItemStack itemstack1 = ifluidsource.pickupBlock((Player) null, worldserver, blockposition, iblockdata);
|
||||
+ ItemStack itemstack1 = ifluidsource.pickupBlock((Player) null, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit
|
||||
|
||||
if (itemstack1.isEmpty()) {
|
||||
return super.execute(pointer, stack);
|
||||
@@ -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.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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ itemstack1 = ifluidsource.pickupBlock((Player) null, worldserver, blockposition, iblockdata); // From above
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
return this.consumeWithRemainder(pointer, stack, new ItemStack(item));
|
||||
}
|
||||
} else {
|
||||
@@ -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); // 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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
this.setSuccess(true);
|
||||
Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING);
|
||||
BlockPos blockposition = pointer.pos().relative(enumdirection);
|
||||
BlockState iblockdata = worldserver.getBlockState(blockposition);
|
||||
|
||||
if (BaseFireBlock.canBePlacedAt(worldserver, blockposition, enumdirection)) {
|
||||
- worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition));
|
||||
- worldserver.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_PLACE, blockposition);
|
||||
+ // CraftBukkit start - Ignition by dispensing flint and steel
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, pointer.pos()).isCancelled()) {
|
||||
+ worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition));
|
||||
+ worldserver.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_PLACE, blockposition);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
} else if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) {
|
||||
- if (iblockdata.getBlock() instanceof TntBlock) {
|
||||
+ if (iblockdata.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, pointer.pos())) { // CraftBukkit - TNTPrimeEvent
|
||||
TntBlock.explode(worldserver, blockposition);
|
||||
worldserver.removeBlock(blockposition, false);
|
||||
} else {
|
||||
@@ -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.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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ worldserver.captureTreeGeneration = true;
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (!BoneMealItem.growCrop(stack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(stack, worldserver, blockposition, (Direction) null)) {
|
||||
this.setSuccess(false);
|
||||
} else if (!worldserver.isClientSide) {
|
||||
worldserver.levelEvent(1505, blockposition, 15);
|
||||
}
|
||||
+ // CraftBukkit start
|
||||
+ worldserver.captureTreeGeneration = false;
|
||||
+ if (worldserver.capturedBlockStates.size() > 0) {
|
||||
+ TreeType treeType = SaplingBlock.treeType;
|
||||
+ SaplingBlock.treeType = null;
|
||||
+ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld());
|
||||
+ List<org.bukkit.block.BlockState> blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values());
|
||||
+ worldserver.capturedBlockStates.clear();
|
||||
+ StructureGrowEvent structureEvent = null;
|
||||
+ if (treeType != null) {
|
||||
+ structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks);
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent);
|
||||
+ }
|
||||
|
||||
+ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(location.getBlock(), null, blocks);
|
||||
+ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled());
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent);
|
||||
+
|
||||
+ if (!fertilizeEvent.isCancelled()) {
|
||||
+ for (org.bukkit.block.BlockState blockstate : blocks) {
|
||||
+ blockstate.update(true);
|
||||
+ worldserver.checkCapturedTreeStateForObserverNotify(blockposition, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
return stack;
|
||||
}
|
||||
});
|
||||
@@ -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));
|
||||
- PrimedTnt entitytntprimed = new PrimedTnt(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (LivingEntity) null);
|
||||
+ // 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.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);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ PrimedTnt entitytntprimed = new PrimedTnt(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (LivingEntity) null);
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
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);
|
||||
- stack.shrink(1);
|
||||
+ if (shrink) stack.shrink(1); // Paper - actually handle here
|
||||
return stack;
|
||||
}
|
||||
});
|
||||
@@ -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.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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
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 +662,7 @@
|
||||
stack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack));
|
||||
+ this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return stack;
|
||||
@@ -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.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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) {
|
||||
if (!worldserver.isClientSide) {
|
||||
worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3);
|
||||
@@ -348,7 +708,7 @@
|
||||
stack.shrink(1);
|
||||
this.setSuccess(true);
|
||||
} else {
|
||||
- this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack));
|
||||
+ this.setSuccess(EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack, this)); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
return stack;
|
||||
@@ -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.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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
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 +786,13 @@
|
||||
this.setSuccess(true);
|
||||
if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) {
|
||||
if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata);
|
||||
stack.shrink(1);
|
||||
} else {
|
||||
@@ -426,6 +817,31 @@
|
||||
this.setSuccess(false);
|
||||
return stack;
|
||||
} else {
|
||||
+ // CraftBukkit start
|
||||
+ ItemStack itemstack1 = stack;
|
||||
+ ServerLevel world = pointer.level();
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
|
||||
+ 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) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
Iterator iterator1 = list.iterator();
|
||||
|
||||
Armadillo armadillo;
|
||||
@@ -454,6 +870,13 @@
|
||||
Optional<BlockState> optional = HoneycombItem.getWaxed(iblockdata);
|
||||
|
||||
if (optional.isPresent()) {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this);
|
||||
+ if (result != null) {
|
||||
+ this.setSuccess(false);
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get());
|
||||
worldserver.levelEvent(3003, blockposition, 0);
|
||||
stack.shrink(1);
|
||||
@@ -481,6 +904,12 @@
|
||||
if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) {
|
||||
return this.defaultDispenseItemBehavior.dispense(pointer, stack);
|
||||
} else {
|
||||
+ // Paper start - Call missing BlockDispenseEvent
|
||||
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition1, stack, this);
|
||||
+ if (result != null) {
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end - Call missing BlockDispenseEvent
|
||||
if (!worldserver.isClientSide) {
|
||||
for (int k = 0; k < 5; ++k) {
|
||||
worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + worldserver.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + worldserver.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D);
|
|
@ -1,82 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java
|
||||
@@ -7,8 +7,13 @@
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
+import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseArmorEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||
|
||||
@@ -18,10 +23,15 @@
|
||||
|
||||
@Override
|
||||
protected ItemStack execute(BlockSource pointer, ItemStack stack) {
|
||||
- return EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack) ? stack : super.execute(pointer, stack);
|
||||
+ return EquipmentDispenseItemBehavior.dispenseEquipment(pointer, stack, this) ? stack : super.execute(pointer, stack); // Paper - fix possible StackOverflowError
|
||||
}
|
||||
|
||||
- public static boolean dispenseEquipment(BlockSource pointer, ItemStack stack) {
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
|
||||
+ public static boolean dispenseEquipment(BlockSource pointer, ItemStack armor) {
|
||||
+ // Paper start
|
||||
+ return dispenseEquipment(pointer, armor, null);
|
||||
+ }
|
||||
+ public static boolean dispenseEquipment(BlockSource pointer, ItemStack stack, @javax.annotation.Nullable DispenseItemBehavior currentBehavior) {
|
||||
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
List<LivingEntity> list = pointer.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> {
|
||||
return entityliving.canEquipWithDispenser(stack);
|
||||
@@ -32,9 +42,37 @@
|
||||
} 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
|
||||
|
||||
- entityliving.setItemSlot(enumitemslot, itemstack1);
|
||||
+ // CraftBukkit start
|
||||
+ Level world = pointer.level();
|
||||
+ org.bukkit.block.Block block = CraftBlock.at(world, pointer.pos());
|
||||
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
+
|
||||
+ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity());
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && (currentBehavior == null || idispensebehavior != currentBehavior)) { // Paper - fix possible StackOverflowError
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ entityliving.setItemSlot(enumitemslot, CraftItemStack.asNMSCopy(event.getItem()));
|
||||
+ // CraftBukkit end
|
||||
if (entityliving instanceof Mob) {
|
||||
Mob entityinsentient = (Mob) entityliving;
|
||||
|
||||
@@ -42,6 +80,7 @@
|
||||
entityinsentient.setPersistenceRequired();
|
||||
}
|
||||
|
||||
+ if (shrink) stack.shrink(1); // Paper - shrink here
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java
|
||||
@@ -15,6 +15,11 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.RailShape;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||
|
||||
@@ -62,11 +67,40 @@
|
||||
}
|
||||
|
||||
Vec3 vec3d1 = new Vec3(d0, d1 + d3, d2);
|
||||
- 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.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);
|
||||
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(vec3d1.x, vec3d1.y, vec3d1.z));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
|
||||
+ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.entityType, EntitySpawnReason.DISPENSER, itemstack1, (Player) null);
|
||||
+
|
||||
if (entityminecartabstract != null) {
|
||||
- worldserver.addFreshEntity(entityminecartabstract);
|
||||
- stack.shrink(1);
|
||||
+ if (worldserver.addFreshEntity(entityminecartabstract) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
return stack;
|
|
@ -1,58 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java
|
||||
@@ -8,6 +8,11 @@
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.ProjectileItem;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior {
|
||||
|
||||
@@ -31,8 +36,41 @@
|
||||
Direction enumdirection = (Direction) pointer.state().getValue(DispenserBlock.FACING);
|
||||
Position iposition = this.dispenseConfig.positionFunction().getDispensePosition(pointer, enumdirection);
|
||||
|
||||
- Projectile.spawnProjectileUsingShoot(this.projectileItem.asProjectile(worldserver, iposition, stack, enumdirection), worldserver, stack, (double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), this.dispenseConfig.power(), this.dispenseConfig.uncertainty());
|
||||
- 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.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);
|
||||
+
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ()));
|
||||
+ if (!DispenserBlock.eventFired) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ // stack.grow(1); // Paper - shrink below
|
||||
+ 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // SPIGOT-7923: Avoid create projectiles with empty item
|
||||
+ if (!itemstack1.isEmpty()) {
|
||||
+ 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());
|
||||
+ }
|
||||
+ if (shrink) stack.shrink(1); // Paper - actually handle here
|
||||
+ // CraftBukkit end
|
||||
return stack;
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
|
||||
@@ -22,6 +22,12 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
|
||||
|
||||
@@ -30,11 +36,34 @@
|
||||
@Override
|
||||
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); // 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) {
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (!worldserver.isClientSide()) {
|
||||
BlockPos blockposition = pointer.pos().relative((Direction) pointer.state().getValue(DispenserBlock.FACING));
|
||||
|
||||
- this.setSuccess(ShearsDispenseItemBehavior.tryShearBeehive(worldserver, blockposition) || ShearsDispenseItemBehavior.tryShearLivingEntity(worldserver, blockposition, stack));
|
||||
+ this.setSuccess(ShearsDispenseItemBehavior.tryShearBeehive(worldserver, blockposition) || ShearsDispenseItemBehavior.tryShearLivingEntity(worldserver, blockposition, stack, bukkitBlock, craftItem)); // CraftBukkit
|
||||
if (this.isSuccess()) {
|
||||
stack.hurtAndBreak(1, worldserver, (ServerPlayer) null, (item) -> {
|
||||
});
|
||||
@@ -64,8 +93,8 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
- private static boolean tryShearLivingEntity(ServerLevel world, BlockPos pos, ItemStack shears) {
|
||||
- List<LivingEntity> list = world.getEntitiesOfClass(LivingEntity.class, new AABB(pos), EntitySelector.NO_SPECTATORS);
|
||||
+ private static boolean tryShearLivingEntity(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args
|
||||
+ List<LivingEntity> list = worldserver.getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS);
|
||||
Iterator iterator = list.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@@ -73,8 +102,16 @@
|
||||
|
||||
if (entityliving instanceof Shearable ishearable) {
|
||||
if (ishearable.readyForShearing()) {
|
||||
- ishearable.shear(world, SoundSource.BLOCKS, shears);
|
||||
- world.gameEvent((Entity) null, (Holder) GameEvent.SHEAR, pos);
|
||||
+ // CraftBukkit start
|
||||
+ // Paper start - Add drops to shear events
|
||||
+ org.bukkit.event.block.BlockShearEntityEvent event = CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem, ishearable.generateDefaultDrops(worldserver, itemstack));
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Paper end - Add drops to shear events
|
||||
+ continue;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ ishearable.shear(worldserver, SoundSource.BLOCKS, itemstack, CraftItemStack.asNMSCopy(event.getDrops())); // Paper - Add drops to shear events
|
||||
+ worldserver.gameEvent((Entity) null, (Holder) GameEvent.SHEAR, blockposition);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
|
||||
@@ -10,6 +10,12 @@
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockDispenseEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -26,8 +32,37 @@
|
||||
BlockPos blockposition = pointer.pos().relative(enumdirection);
|
||||
Direction enumdirection1 = pointer.level().isEmptyBlock(blockposition.below()) ? enumdirection : Direction.UP;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(pointer.level(), pointer.pos());
|
||||
+ 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) {
|
||||
+ pointer.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+ }
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+
|
||||
+ if (!event.getItem().equals(craftItem)) {
|
||||
+ // 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
|
||||
+ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
|
||||
+ idispensebehavior.dispense(pointer, eventStack);
|
||||
+ return stack;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
try {
|
||||
- this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(pointer.level(), blockposition, enumdirection, stack, enumdirection1)).consumesAction());
|
||||
+ // Paper start - track changed items in the dispense event
|
||||
+ this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(pointer.level(), blockposition, enumdirection, CraftItemStack.asNMSCopy(event.getItem()), enumdirection1)).consumesAction());
|
||||
+ if (this.isSuccess()) {
|
||||
+ stack.shrink(1); // vanilla shrink is in the place function above, manually handle it here
|
||||
+ }
|
||||
+ // Paper end - track changed items in the dispense event
|
||||
} catch (Exception exception) {
|
||||
ShulkerBoxDispenseBehavior.LOGGER.error("Error trying to place shulker box at {}", blockposition, exception);
|
||||
}
|
Loading…
Reference in a new issue