net.minecraft.core.dispenser
This commit is contained in:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user