--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.dispenser;
 
 import com.mojang.logging.LogUtils;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
 import net.minecraft.Util;
@@ -39,6 +40,7 @@
 import net.minecraft.world.entity.vehicle.Boat;
 import net.minecraft.world.item.ArmorItem;
 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;
@@ -49,7 +51,6 @@
 import net.minecraft.world.item.alchemy.PotionUtils;
 import net.minecraft.world.item.alchemy.Potions;
 import net.minecraft.world.level.Level;
-import net.minecraft.world.level.LevelAccessor;
 import net.minecraft.world.level.block.BaseFireBlock;
 import net.minecraft.world.level.block.BeehiveBlock;
 import net.minecraft.world.level.block.Block;
@@ -60,7 +61,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;
@@ -73,14 +76,25 @@
 import net.minecraft.world.level.block.state.properties.BlockStateProperties;
 import net.minecraft.world.level.block.state.properties.RotationSegment;
 import net.minecraft.world.level.gameevent.GameEvent;
+import org.slf4j.Logger;
+import net.minecraft.world.level.material.Material;
 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.v1_19_R2.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_19_R2.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 {
+
     Logger LOGGER = LogUtils.getLogger();
-    DispenseItemBehavior NOOP = (pointer, stack) -> {
-        return stack;
+    DispenseItemBehavior NOOP = (isourceblock, itemstack) -> {
+        return itemstack;
     };
 
     ItemStack dispense(BlockSource pointer, ItemStack stack);
@@ -89,49 +103,52 @@
         DispenserBlock.registerBehavior(Items.ARROW, new AbstractProjectileDispenseBehavior() {
             @Override
             protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                Arrow arrow = new Arrow(world, position.x(), position.y(), position.z());
-                arrow.pickup = AbstractArrow.Pickup.ALLOWED;
-                return arrow;
+                Arrow entitytippedarrow = new Arrow(world, position.x(), position.y(), position.z());
+
+                entitytippedarrow.pickup = AbstractArrow.Pickup.ALLOWED;
+                return entitytippedarrow;
             }
         });
         DispenserBlock.registerBehavior(Items.TIPPED_ARROW, new AbstractProjectileDispenseBehavior() {
             @Override
             protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                Arrow arrow = new Arrow(world, position.x(), position.y(), position.z());
-                arrow.setEffectsFromItem(stack);
-                arrow.pickup = AbstractArrow.Pickup.ALLOWED;
-                return arrow;
+                Arrow entitytippedarrow = new Arrow(world, position.x(), position.y(), position.z());
+
+                entitytippedarrow.setEffectsFromItem(stack);
+                entitytippedarrow.pickup = AbstractArrow.Pickup.ALLOWED;
+                return entitytippedarrow;
             }
         });
         DispenserBlock.registerBehavior(Items.SPECTRAL_ARROW, new AbstractProjectileDispenseBehavior() {
             @Override
             protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                AbstractArrow abstractArrow = new SpectralArrow(world, position.x(), position.y(), position.z());
-                abstractArrow.pickup = AbstractArrow.Pickup.ALLOWED;
-                return abstractArrow;
+                SpectralArrow entityspectralarrow = new SpectralArrow(world, position.x(), position.y(), position.z());
+
+                entityspectralarrow.pickup = AbstractArrow.Pickup.ALLOWED;
+                return entityspectralarrow;
             }
         });
         DispenserBlock.registerBehavior(Items.EGG, new AbstractProjectileDispenseBehavior() {
             @Override
             protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                return Util.make(new ThrownEgg(world, position.x(), position.y(), position.z()), (entity) -> {
-                    entity.setItem(stack);
+                return (Projectile) Util.make(new ThrownEgg(world, position.x(), position.y(), position.z()), (entityegg) -> {
+                    entityegg.setItem(stack);
                 });
             }
         });
         DispenserBlock.registerBehavior(Items.SNOWBALL, new AbstractProjectileDispenseBehavior() {
             @Override
             protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                return Util.make(new Snowball(world, position.x(), position.y(), position.z()), (entity) -> {
-                    entity.setItem(stack);
+                return (Projectile) Util.make(new Snowball(world, position.x(), position.y(), position.z()), (entitysnowball) -> {
+                    entitysnowball.setItem(stack);
                 });
             }
         });
         DispenserBlock.registerBehavior(Items.EXPERIENCE_BOTTLE, new AbstractProjectileDispenseBehavior() {
             @Override
             protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                return Util.make(new ThrownExperienceBottle(world, position.x(), position.y(), position.z()), (entity) -> {
-                    entity.setItem(stack);
+                return (Projectile) Util.make(new ThrownExperienceBottle(world, position.x(), position.y(), position.z()), (entitythrownexpbottle) -> {
+                    entitythrownexpbottle.setItem(stack);
                 });
             }
 
@@ -151,8 +168,8 @@
                 return (new AbstractProjectileDispenseBehavior() {
                     @Override
                     protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                        return Util.make(new ThrownPotion(world, position.x(), position.y(), position.z()), (entity) -> {
-                            entity.setItem(stack);
+                        return (Projectile) Util.make(new ThrownPotion(world, position.x(), position.y(), position.z()), (entitypotion) -> {
+                            entitypotion.setItem(stack);
                         });
                     }
 
@@ -174,8 +191,8 @@
                 return (new AbstractProjectileDispenseBehavior() {
                     @Override
                     protected Projectile getProjectile(Level world, Position position, ItemStack stack) {
-                        return Util.make(new ThrownPotion(world, position.x(), position.y(), position.z()), (entity) -> {
-                            entity.setItem(stack);
+                        return (Projectile) Util.make(new ThrownPotion(world, position.x(), position.y(), position.z()), (entitypotion) -> {
+                            entitypotion.setItem(stack);
                         });
                     }
 
@@ -191,57 +208,147 @@
                 }).dispense(pointer, stack);
             }
         });
-        DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior() {
+        DefaultDispenseItemBehavior dispensebehavioritem = new DefaultDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
-                EntityType<?> entityType = ((SpawnEggItem)stack.getItem()).getType(stack.getTag());
+                Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+                EntityType entitytypes = ((SpawnEggItem) stack.getItem()).getType(stack.getTag());
+
+                // CraftBukkit start
+                ServerLevel worldserver = pointer.getLevel();
+                ItemStack itemstack1 = stack.split(1);
+                org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                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);
+                    return stack;
+                }
+
+                if (!event.getItem().equals(craftItem)) {
+                    stack.grow(1);
+                    // Chain to handler for new item
+                    ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+                    DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+                        idispensebehavior.dispense(pointer, eventStack);
+                        return stack;
+                    }
+                }
 
                 try {
-                    entityType.spawn(pointer.getLevel(), stack, (Player)null, pointer.getPos().relative(direction), MobSpawnType.DISPENSER, direction != Direction.UP, false);
-                } catch (Exception var6) {
-                    LOGGER.error("Error while dispensing spawn egg from dispenser at {}", pointer.getPos(), var6);
+                    entitytypes.spawn(pointer.getLevel(), stack, (Player) null, pointer.getPos().relative(enumdirection), MobSpawnType.DISPENSER, enumdirection != Direction.UP, false);
+                } catch (Exception exception) {
+                    DispenseItemBehavior.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", pointer.getPos(), exception); // CraftBukkit - decompile error
                     return ItemStack.EMPTY;
                 }
 
-                stack.shrink(1);
-                pointer.getLevel().gameEvent((Entity)null, GameEvent.ENTITY_PLACE, pointer.getPos());
+                // itemstack.shrink(1); // Handled during event processing
+                // CraftBukkit end
+                pointer.getLevel().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, pointer.getPos());
                 return stack;
             }
         };
+        Iterator iterator = SpawnEggItem.eggs().iterator();
 
-        for(SpawnEggItem spawnEggItem : SpawnEggItem.eggs()) {
-            DispenserBlock.registerBehavior(spawnEggItem, defaultDispenseItemBehavior);
+        while (iterator.hasNext()) {
+            SpawnEggItem itemmonsteregg = (SpawnEggItem) iterator.next();
+
+            DispenserBlock.registerBehavior(itemmonsteregg, dispensebehavioritem);
         }
 
         DispenserBlock.registerBehavior(Items.ARMOR_STAND, new DefaultDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
-                BlockPos blockPos = pointer.getPos().relative(direction);
-                Level level = pointer.getLevel();
-                ArmorStand armorStand = new ArmorStand(level, (double)blockPos.getX() + 0.5D, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5D);
-                EntityType.updateCustomEntityTag(level, (Player)null, armorStand, stack.getTag());
-                armorStand.setYRot(direction.toYRot());
-                level.addFreshEntity(armorStand);
-                stack.shrink(1);
+                Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+                BlockPos blockposition = pointer.getPos().relative(enumdirection);
+                ServerLevel worldserver = pointer.getLevel();
+
+                // CraftBukkit start
+                ItemStack itemstack1 = stack.split(1);
+                org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                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);
+                    return stack;
+                }
+
+                if (!event.getItem().equals(craftItem)) {
+                    stack.grow(1);
+                    // Chain to handler for new item
+                    ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+                    DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+                        idispensebehavior.dispense(pointer, eventStack);
+                        return stack;
+                    }
+                }
+                // CraftBukkit end
+
+                ArmorStand entityarmorstand = new ArmorStand(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D);
+
+                EntityType.updateCustomEntityTag(worldserver, (Player) null, entityarmorstand, stack.getTag());
+                entityarmorstand.setYRot(enumdirection.toYRot());
+                worldserver.addFreshEntity(entityarmorstand);
+                // itemstack.shrink(1); // CraftBukkit - Handled during event processing
                 return stack;
             }
         });
         DispenserBlock.registerBehavior(Items.SADDLE, new OptionalDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                List<LivingEntity> list = pointer.getLevel().getEntitiesOfClass(LivingEntity.class, new AABB(blockPos), (entity) -> {
-                    if (!(entity instanceof Saddleable saddleable)) {
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                List<LivingEntity> list = pointer.getLevel().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> {
+                    if (!(entityliving instanceof Saddleable)) {
                         return false;
                     } else {
-                        return !saddleable.isSaddled() && saddleable.isSaddleable();
+                        Saddleable isaddleable = (Saddleable) entityliving;
+
+                        return !isaddleable.isSaddled() && isaddleable.isSaddleable();
                     }
                 });
+
                 if (!list.isEmpty()) {
-                    ((Saddleable)list.get(0)).equipSaddle(SoundSource.BLOCKS);
-                    stack.shrink(1);
+                    // CraftBukkit start
+                    ItemStack itemstack1 = stack.split(1);
+                    Level world = pointer.getLevel();
+                    org.bukkit.block.Block block = world.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                    CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+
+                    BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.v1_19_R2.entity.CraftLivingEntity) list.get(0).getBukkitEntity());
+                    if (!DispenserBlock.eventFired) {
+                        world.getCraftServer().getPluginManager().callEvent(event);
+                    }
+
+                    if (event.isCancelled()) {
+                        stack.grow(1);
+                        return stack;
+                    }
+
+                    if (!event.getItem().equals(craftItem)) {
+                        stack.grow(1);
+                        // Chain to handler for new item
+                        ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+                        DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                        if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
+                            idispensebehavior.dispense(pointer, eventStack);
+                            return stack;
+                        }
+                    }
+                    // CraftBukkit end
+                    ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS);
+                    // itemstack.shrink(1); // CraftBukkit - handled above
                     this.setSuccess(true);
                     return stack;
                 } else {
@@ -249,71 +356,169 @@
                 }
             }
         });
-        DefaultDispenseItemBehavior defaultDispenseItemBehavior2 = new OptionalDispenseItemBehavior() {
+        OptionalDispenseItemBehavior dispensebehaviormaybe = new OptionalDispenseItemBehavior() {
             @Override
             protected ItemStack execute(BlockSource pointer, ItemStack stack) {
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                List<AbstractHorse> list = pointer.getLevel().getEntitiesOfClass(AbstractHorse.class, new AABB(blockposition), (entityhorseabstract) -> {
+                    return entityhorseabstract.isAlive() && entityhorseabstract.canWearArmor();
+                });
+                Iterator iterator1 = list.iterator();
 
-                for(AbstractHorse abstractHorse : pointer.getLevel().getEntitiesOfClass(AbstractHorse.class, new AABB(blockPos), (entity) -> {
-                    return entity.isAlive() && entity.canWearArmor();
-                })) {
-                    if (abstractHorse.isArmor(stack) && !abstractHorse.isWearingArmor() && abstractHorse.isTamed()) {
-                        abstractHorse.getSlot(401).set(stack.split(1));
-                        this.setSuccess(true);
+                AbstractHorse entityhorseabstract;
+
+                do {
+                    if (!iterator1.hasNext()) {
+                        return super.execute(pointer, stack);
+                    }
+
+                    entityhorseabstract = (AbstractHorse) iterator1.next();
+                } while (!entityhorseabstract.isArmor(stack) || entityhorseabstract.isWearingArmor() || !entityhorseabstract.isTamed());
+
+                // CraftBukkit start
+                ItemStack itemstack1 = stack.split(1);
+                Level world = pointer.getLevel();
+                org.bukkit.block.Block block = world.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+
+                BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.v1_19_R2.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity());
+                if (!DispenserBlock.eventFired) {
+                    world.getCraftServer().getPluginManager().callEvent(event);
+                }
+
+                if (event.isCancelled()) {
+                    stack.grow(1);
+                    return stack;
+                }
+
+                if (!event.getItem().equals(craftItem)) {
+                    stack.grow(1);
+                    // Chain to handler for new item
+                    ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+                    DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
+                        idispensebehavior.dispense(pointer, eventStack);
                         return stack;
                     }
                 }
 
-                return super.execute(pointer, stack);
+                entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem()));
+                // CraftBukkit end
+                this.setSuccess(true);
+                return stack;
             }
         };
-        DispenserBlock.registerBehavior(Items.LEATHER_HORSE_ARMOR, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.IRON_HORSE_ARMOR, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.GOLDEN_HORSE_ARMOR, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.DIAMOND_HORSE_ARMOR, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.WHITE_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.ORANGE_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.CYAN_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.BLUE_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.BROWN_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.BLACK_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.GRAY_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.GREEN_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.LIGHT_BLUE_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.LIGHT_GRAY_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.LIME_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.MAGENTA_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.PINK_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.PURPLE_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.RED_CARPET, defaultDispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.YELLOW_CARPET, defaultDispenseItemBehavior2);
+
+        DispenserBlock.registerBehavior(Items.LEATHER_HORSE_ARMOR, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.IRON_HORSE_ARMOR, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.GOLDEN_HORSE_ARMOR, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.DIAMOND_HORSE_ARMOR, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.WHITE_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.ORANGE_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.CYAN_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.BLUE_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.BROWN_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.BLACK_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.GRAY_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.GREEN_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.LIGHT_BLUE_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.LIGHT_GRAY_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.LIME_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.MAGENTA_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.PINK_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.PURPLE_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.RED_CARPET, dispensebehaviormaybe);
+        DispenserBlock.registerBehavior(Items.YELLOW_CARPET, dispensebehaviormaybe);
         DispenserBlock.registerBehavior(Items.CHEST, new OptionalDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                List<AbstractChestedHorse> list = pointer.getLevel().getEntitiesOfClass(AbstractChestedHorse.class, new AABB(blockposition), (entityhorsechestedabstract) -> {
+                    return entityhorsechestedabstract.isAlive() && !entityhorsechestedabstract.hasChest();
+                });
+                Iterator iterator1 = list.iterator();
 
-                for(AbstractChestedHorse abstractChestedHorse : pointer.getLevel().getEntitiesOfClass(AbstractChestedHorse.class, new AABB(blockPos), (entity) -> {
-                    return entity.isAlive() && !entity.hasChest();
-                })) {
-                    if (abstractChestedHorse.isTamed() && abstractChestedHorse.getSlot(499).set(stack)) {
-                        stack.shrink(1);
-                        this.setSuccess(true);
+                AbstractChestedHorse entityhorsechestedabstract;
+
+                do {
+                    if (!iterator1.hasNext()) {
+                        return super.execute(pointer, stack);
+                    }
+
+                    entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next();
+                    // CraftBukkit start
+                } while (!entityhorsechestedabstract.isTamed());
+                ItemStack itemstack1 = stack.split(1);
+                Level world = pointer.getLevel();
+                org.bukkit.block.Block block = world.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+
+                BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.v1_19_R2.entity.CraftLivingEntity) entityhorsechestedabstract.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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) {
+                        idispensebehavior.dispense(pointer, eventStack);
                         return stack;
                     }
                 }
+                entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem()));
+                // CraftBukkit end
 
-                return super.execute(pointer, stack);
+                // itemstack.shrink(1); // CraftBukkit - handled above
+                this.setSuccess(true);
+                return stack;
             }
         });
         DispenserBlock.registerBehavior(Items.FIREWORK_ROCKET, new DefaultDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
-                FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(pointer.getLevel(), stack, pointer.x(), pointer.y(), pointer.x(), true);
-                DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, fireworkRocketEntity, direction);
-                fireworkRocketEntity.shoot((double)direction.getStepX(), (double)direction.getStepY(), (double)direction.getStepZ(), 0.5F, 1.0F);
-                pointer.getLevel().addFreshEntity(fireworkRocketEntity);
-                stack.shrink(1);
+                Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+                // CraftBukkit start
+                ServerLevel worldserver = pointer.getLevel();
+                ItemStack itemstack1 = stack.split(1);
+                org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+
+                BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(enumdirection.getStepX(), enumdirection.getStepY(), enumdirection.getStepZ()));
+                if (!DispenserBlock.eventFired) {
+                    worldserver.getCraftServer().getPluginManager().callEvent(event);
+                }
+
+                if (event.isCancelled()) {
+                    stack.grow(1);
+                    return stack;
+                }
+
+                if (!event.getItem().equals(craftItem)) {
+                    stack.grow(1);
+                    // Chain to handler for new item
+                    ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+                    DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+                        idispensebehavior.dispense(pointer, eventStack);
+                        return stack;
+                    }
+                }
+
+                itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
+                FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), itemstack1, pointer.x(), pointer.y(), pointer.x(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed
+                entityfireworks.projectileSource = new org.bukkit.craftbukkit.v1_19_R2.projectiles.CraftBlockProjectileSource(pointer.getEntity()); // Paper - track projectile source for fireworks
+
+                DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection);
+                entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F);
+                pointer.getLevel().addFreshEntity(entityfireworks);
+                // itemstack.shrink(1); // Handled during event processing
+                // CraftBukkit end
                 return stack;
             }
 
@@ -325,21 +530,50 @@
         DispenserBlock.registerBehavior(Items.FIRE_CHARGE, new DefaultDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
-                Position position = DispenserBlock.getDispensePosition(pointer);
-                double d = position.x() + (double)((float)direction.getStepX() * 0.3F);
-                double e = position.y() + (double)((float)direction.getStepY() * 0.3F);
-                double f = position.z() + (double)((float)direction.getStepZ() * 0.3F);
-                Level level = pointer.getLevel();
-                RandomSource randomSource = level.random;
-                double g = randomSource.triangle((double)direction.getStepX(), 0.11485000000000001D);
-                double h = randomSource.triangle((double)direction.getStepY(), 0.11485000000000001D);
-                double i = randomSource.triangle((double)direction.getStepZ(), 0.11485000000000001D);
-                SmallFireball smallFireball = new SmallFireball(level, d, e, f, g, h, i);
-                level.addFreshEntity(Util.make(smallFireball, (entity) -> {
-                    entity.setItem(stack);
-                }));
-                stack.shrink(1);
+                Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+                Position iposition = DispenserBlock.getDispensePosition(pointer);
+                double d0 = iposition.x() + (double) ((float) enumdirection.getStepX() * 0.3F);
+                double d1 = iposition.y() + (double) ((float) enumdirection.getStepY() * 0.3F);
+                double d2 = iposition.z() + (double) ((float) enumdirection.getStepZ() * 0.3F);
+                ServerLevel worldserver = pointer.getLevel();
+                RandomSource randomsource = worldserver.random;
+                double d3 = randomsource.triangle((double) enumdirection.getStepX(), 0.11485000000000001D);
+                double d4 = randomsource.triangle((double) enumdirection.getStepY(), 0.11485000000000001D);
+                double d5 = randomsource.triangle((double) enumdirection.getStepZ(), 0.11485000000000001D);
+
+                // CraftBukkit start
+                ItemStack itemstack1 = stack.split(1);
+                org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
+
+                BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5));
+                if (!DispenserBlock.eventFired) {
+                    worldserver.getCraftServer().getPluginManager().callEvent(event);
+                }
+
+                if (event.isCancelled()) {
+                    stack.grow(1);
+                    return stack;
+                }
+
+                if (!event.getItem().equals(craftItem)) {
+                    stack.grow(1);
+                    // Chain to handler for new item
+                    ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+                    DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+                        idispensebehavior.dispense(pointer, eventStack);
+                        return stack;
+                    }
+                }
+
+                SmallFireball entitysmallfireball = new SmallFireball(worldserver, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ());
+                entitysmallfireball.setItem(itemstack1);
+                entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.v1_19_R2.projectiles.CraftBlockProjectileSource((DispenserBlockEntity) pointer.getEntity());
+
+                worldserver.addFreshEntity(entitysmallfireball);
+                // itemstack.shrink(1); // Handled during event processing
+                // CraftBukkit end
                 return stack;
             }
 
@@ -364,52 +598,125 @@
         DispenserBlock.registerBehavior(Items.ACACIA_CHEST_BOAT, new BoatDispenseItemBehavior(Boat.Type.ACACIA, true));
         DispenserBlock.registerBehavior(Items.MANGROVE_CHEST_BOAT, new BoatDispenseItemBehavior(Boat.Type.MANGROVE, true));
         DispenserBlock.registerBehavior(Items.BAMBOO_CHEST_RAFT, new BoatDispenseItemBehavior(Boat.Type.BAMBOO, true));
-        DispenseItemBehavior dispenseItemBehavior = new DefaultDispenseItemBehavior() {
+        DefaultDispenseItemBehavior dispensebehavioritem1 = new DefaultDispenseItemBehavior() {
             private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior();
 
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem)stack.getItem();
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                Level level = pointer.getLevel();
-                if (dispensibleContainerItem.emptyContents((Player)null, level, blockPos, (BlockHitResult)null)) {
-                    dispensibleContainerItem.checkExtraContent((Player)null, level, stack, blockPos);
-                    return new ItemStack(Items.BUCKET);
+                DispensibleContainerItem dispensiblecontaineritem = (DispensibleContainerItem) stack.getItem();
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                ServerLevel worldserver = pointer.getLevel();
+
+                // CraftBukkit start
+                int x = blockposition.getX();
+                int y = blockposition.getY();
+                int z = blockposition.getZ();
+                BlockState iblockdata = worldserver.getBlockState(blockposition);
+                Material material = iblockdata.getMaterial();
+                if (worldserver.isEmptyBlock(blockposition) || !material.isSolid() || material.isReplaceable() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid(worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) {
+                    org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                    CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+
+                    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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                        if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+                            idispensebehavior.dispense(pointer, eventStack);
+                            return stack;
+                        }
+                    }
+
+                    dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem();
+                }
+                // CraftBukkit end
+
+                if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) {
+                    dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, stack, blockposition);
+                    // CraftBukkit start - Handle stacked buckets
+                    Item item = Items.BUCKET;
+                    stack.shrink(1);
+                    if (stack.isEmpty()) {
+                        stack = new ItemStack(item); // Paper - clear tag
+                    } else if (((DispenserBlockEntity) pointer.getEntity()).addItem(new ItemStack(item)) < 0) {
+                        this.defaultDispenseItemBehavior.dispense(pointer, new ItemStack(item));
+                    }
+                    return stack;
+                    // CraftBukkit end
                 } else {
                     return this.defaultDispenseItemBehavior.dispense(pointer, stack);
                 }
             }
         };
-        DispenserBlock.registerBehavior(Items.LAVA_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.WATER_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.POWDER_SNOW_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.SALMON_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.COD_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.PUFFERFISH_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.TROPICAL_FISH_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.AXOLOTL_BUCKET, dispenseItemBehavior);
-        DispenserBlock.registerBehavior(Items.TADPOLE_BUCKET, dispenseItemBehavior);
+
+        DispenserBlock.registerBehavior(Items.LAVA_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.WATER_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.POWDER_SNOW_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.SALMON_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.COD_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.PUFFERFISH_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.TROPICAL_FISH_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.AXOLOTL_BUCKET, dispensebehavioritem1);
+        DispenserBlock.registerBehavior(Items.TADPOLE_BUCKET, dispensebehavioritem1);
         DispenserBlock.registerBehavior(Items.BUCKET, new DefaultDispenseItemBehavior() {
             private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior();
 
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                LevelAccessor levelAccessor = pointer.getLevel();
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                BlockState blockState = levelAccessor.getBlockState(blockPos);
-                Block block = blockState.getBlock();
+                ServerLevel worldserver = pointer.getLevel();
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                BlockState iblockdata = worldserver.getBlockState(blockposition);
+                Block block = iblockdata.getBlock();
+
                 if (block instanceof BucketPickup) {
-                    ItemStack itemStack = ((BucketPickup)block).pickupBlock(levelAccessor, blockPos, blockState);
-                    if (itemStack.isEmpty()) {
+                    ItemStack itemstack1 = ((BucketPickup) block).pickupBlock(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit
+
+                    if (itemstack1.isEmpty()) {
                         return super.execute(pointer, stack);
                     } else {
-                        levelAccessor.gameEvent((Entity)null, GameEvent.FLUID_PICKUP, blockPos);
-                        Item item = itemStack.getItem();
+                        worldserver.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition);
+                        Item item = itemstack1.getItem();
+
+                        // CraftBukkit start
+                        org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                        CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+
+                        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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                            if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+                                idispensebehavior.dispense(pointer, eventStack);
+                                return stack;
+                            }
+                        }
+
+                        itemstack1 = ((BucketPickup) block).pickupBlock(worldserver, blockposition, iblockdata); // From above
+                        // CraftBukkit end
+
                         stack.shrink(1);
                         if (stack.isEmpty()) {
                             return new ItemStack(item);
                         } else {
-                            if (pointer.<DispenserBlockEntity>getEntity().addItem(new ItemStack(item)) < 0) {
+                            if (((DispenserBlockEntity) pointer.getEntity()).addItem(new ItemStack(item)) < 0) {
                                 this.defaultDispenseItemBehavior.dispense(pointer, new ItemStack(item));
                             }
 
@@ -424,27 +731,57 @@
         DispenserBlock.registerBehavior(Items.FLINT_AND_STEEL, new OptionalDispenseItemBehavior() {
             @Override
             protected ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Level level = pointer.getLevel();
+                ServerLevel worldserver = pointer.getLevel();
+
+                // CraftBukkit start
+                org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+
+                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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) {
+                        idispensebehavior.dispense(pointer, eventStack);
+                        return stack;
+                    }
+                }
+                // CraftBukkit end
+
                 this.setSuccess(true);
-                Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
-                BlockPos blockPos = pointer.getPos().relative(direction);
-                BlockState blockState = level.getBlockState(blockPos);
-                if (BaseFireBlock.canBePlacedAt(level, blockPos, direction)) {
-                    level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos));
-                    level.gameEvent((Entity)null, GameEvent.BLOCK_PLACE, blockPos);
-                } else if (!CampfireBlock.canLight(blockState) && !CandleBlock.canLight(blockState) && !CandleCakeBlock.canLight(blockState)) {
-                    if (blockState.getBlock() instanceof TntBlock) {
-                        TntBlock.explode(level, blockPos);
-                        level.removeBlock(blockPos, false);
+                Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+                BlockPos blockposition = pointer.getPos().relative(enumdirection);
+                BlockState iblockdata = worldserver.getBlockState(blockposition);
+
+                if (BaseFireBlock.canBePlacedAt(worldserver, blockposition, enumdirection)) {
+                    // CraftBukkit start - Ignition by dispensing flint and steel
+                    if (!org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, pointer.getPos()).isCancelled()) {
+                        worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition));
+                        worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition);
+                    }
+                    // CraftBukkit end
+                } else if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) {
+                    if (iblockdata.getBlock() instanceof TntBlock) {
+                        TntBlock.explode(worldserver, blockposition);
+                        worldserver.removeBlock(blockposition, false);
                     } else {
                         this.setSuccess(false);
                     }
                 } else {
-                    level.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)));
-                    level.gameEvent((Entity)null, GameEvent.BLOCK_CHANGE, blockPos);
+                    worldserver.setBlockAndUpdate(blockposition, (BlockState) iblockdata.setValue(BlockStateProperties.LIT, true));
+                    worldserver.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockposition);
                 }
 
-                if (this.isSuccess() && stack.hurt(1, level.random, (ServerPlayer)null)) {
+                if (this.isSuccess() && stack.hurt(1, worldserver.random, (ServerPlayer) null)) {
                     stack.setCount(0);
                 }
 
@@ -455,13 +792,64 @@
             @Override
             protected ItemStack execute(BlockSource pointer, ItemStack stack) {
                 this.setSuccess(true);
-                Level level = pointer.getLevel();
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                if (!BoneMealItem.growCrop(stack, level, blockPos) && !BoneMealItem.growWaterPlant(stack, level, blockPos, (Direction)null)) {
+                ServerLevel worldserver = pointer.getLevel();
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                // CraftBukkit start
+                org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+
+                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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    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 (!level.isClientSide) {
-                    level.levelEvent(1505, blockPos, 0);
+                } else if (!worldserver.isClientSide) {
+                    worldserver.levelEvent(1505, blockposition, 0);
+                }
+                // CraftBukkit start
+                worldserver.captureTreeGeneration = false;
+                if (worldserver.capturedBlockStates.size() > 0) {
+                    TreeType treeType = SaplingBlock.treeType;
+                    SaplingBlock.treeType = null;
+                    Location location = new Location(worldserver.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ());
+                    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);
+                        }
+                    }
                 }
+                // CraftBukkit end
 
                 return stack;
             }
@@ -469,41 +857,98 @@
         DispenserBlock.registerBehavior(Blocks.TNT, new DefaultDispenseItemBehavior() {
             @Override
             protected ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Level level = pointer.getLevel();
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                PrimedTnt primedTnt = new PrimedTnt(level, (double)blockPos.getX() + 0.5D, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5D, (LivingEntity)null);
-                level.addFreshEntity(primedTnt);
-                level.playSound((Player)null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
-                level.gameEvent((Entity)null, GameEvent.ENTITY_PLACE, blockPos);
-                stack.shrink(1);
+                ServerLevel worldserver = pointer.getLevel();
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                // CraftBukkit start
+                // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null);
+
+                ItemStack itemstack1 = stack.split(1);
+                org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                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);
+                    return stack;
+                }
+
+                if (!event.getItem().equals(craftItem)) {
+                    stack.grow(1);
+                    // Chain to handler for new item
+                    ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+                    DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    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, GameEvent.ENTITY_PLACE, blockposition);
+                // itemstack.shrink(1); // CraftBukkit - handled above
                 return stack;
             }
         });
-        DispenseItemBehavior dispenseItemBehavior2 = new OptionalDispenseItemBehavior() {
+        OptionalDispenseItemBehavior dispensebehaviormaybe1 = new OptionalDispenseItemBehavior() {
             @Override
             protected ItemStack execute(BlockSource pointer, ItemStack stack) {
                 this.setSuccess(ArmorItem.dispenseArmor(pointer, stack));
                 return stack;
             }
         };
-        DispenserBlock.registerBehavior(Items.CREEPER_HEAD, dispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, dispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.DRAGON_HEAD, dispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.SKELETON_SKULL, dispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, dispenseItemBehavior2);
-        DispenserBlock.registerBehavior(Items.PLAYER_HEAD, dispenseItemBehavior2);
+
+        DispenserBlock.registerBehavior(Items.CREEPER_HEAD, dispensebehaviormaybe1);
+        DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, dispensebehaviormaybe1);
+        DispenserBlock.registerBehavior(Items.DRAGON_HEAD, dispensebehaviormaybe1);
+        DispenserBlock.registerBehavior(Items.SKELETON_SKULL, dispensebehaviormaybe1);
+        DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, dispensebehaviormaybe1);
+        DispenserBlock.registerBehavior(Items.PLAYER_HEAD, dispensebehaviormaybe1);
         DispenserBlock.registerBehavior(Items.WITHER_SKELETON_SKULL, new OptionalDispenseItemBehavior() {
             @Override
             protected ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Level level = pointer.getLevel();
-                Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
-                BlockPos blockPos = pointer.getPos().relative(direction);
-                if (level.isEmptyBlock(blockPos) && WitherSkullBlock.canSpawnMob(level, blockPos, stack)) {
-                    level.setBlock(blockPos, Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, Integer.valueOf(RotationSegment.convertToSegment(direction))), 3);
-                    level.gameEvent((Entity)null, GameEvent.BLOCK_PLACE, blockPos);
-                    BlockEntity blockEntity = level.getBlockEntity(blockPos);
-                    if (blockEntity instanceof SkullBlockEntity) {
-                        WitherSkullBlock.checkSpawn(level, blockPos, (SkullBlockEntity)blockEntity);
+                ServerLevel worldserver = pointer.getLevel();
+                Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+                BlockPos blockposition = pointer.getPos().relative(enumdirection);
+
+                // CraftBukkit start
+                org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+
+                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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    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, GameEvent.BLOCK_PLACE, blockposition);
+                    BlockEntity tileentity = worldserver.getBlockEntity(blockposition);
+
+                    if (tileentity instanceof SkullBlockEntity) {
+                        WitherSkullBlock.checkSpawn(worldserver, blockposition, (SkullBlockEntity) tileentity);
                     }
 
                     stack.shrink(1);
@@ -518,13 +963,38 @@
         DispenserBlock.registerBehavior(Blocks.CARVED_PUMPKIN, new OptionalDispenseItemBehavior() {
             @Override
             protected ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Level level = pointer.getLevel();
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                CarvedPumpkinBlock carvedPumpkinBlock = (CarvedPumpkinBlock)Blocks.CARVED_PUMPKIN;
-                if (level.isEmptyBlock(blockPos) && carvedPumpkinBlock.canSpawnGolem(level, blockPos)) {
-                    if (!level.isClientSide) {
-                        level.setBlock(blockPos, carvedPumpkinBlock.defaultBlockState(), 3);
-                        level.gameEvent((Entity)null, GameEvent.BLOCK_PLACE, blockPos);
+                ServerLevel worldserver = pointer.getLevel();
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN;
+
+                // CraftBukkit start
+                org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+
+                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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    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);
+                        worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition);
                     }
 
                     stack.shrink(1);
@@ -537,9 +1007,13 @@
             }
         });
         DispenserBlock.registerBehavior(Blocks.SHULKER_BOX.asItem(), new ShulkerBoxDispenseBehavior());
+        DyeColor[] aenumcolor = DyeColor.values();
+        int i = aenumcolor.length;
 
-        for(DyeColor dyeColor : DyeColor.values()) {
-            DispenserBlock.registerBehavior(ShulkerBoxBlock.getBlockByColor(dyeColor).asItem(), new ShulkerBoxDispenseBehavior());
+        for (int j = 0; j < i; ++j) {
+            DyeColor enumcolor = aenumcolor[j];
+
+            DispenserBlock.registerBehavior(ShulkerBoxBlock.getBlockByColor(enumcolor).asItem(), new ShulkerBoxDispenseBehavior());
         }
 
         DispenserBlock.registerBehavior(Items.GLASS_BOTTLE.asItem(), new OptionalDispenseItemBehavior() {
@@ -548,10 +1022,10 @@
             private ItemStack takeLiquid(BlockSource pointer, ItemStack emptyBottleStack, ItemStack filledBottleStack) {
                 emptyBottleStack.shrink(1);
                 if (emptyBottleStack.isEmpty()) {
-                    pointer.getLevel().gameEvent((Entity)null, GameEvent.FLUID_PICKUP, pointer.getPos());
+                    pointer.getLevel().gameEvent((Entity) null, GameEvent.FLUID_PICKUP, pointer.getPos());
                     return filledBottleStack.copy();
                 } else {
-                    if (pointer.<DispenserBlockEntity>getEntity().addItem(filledBottleStack.copy()) < 0) {
+                    if (((DispenserBlockEntity) pointer.getEntity()).addItem(filledBottleStack.copy()) < 0) {
                         this.defaultDispenseItemBehavior.dispense(pointer, filledBottleStack.copy());
                     }
 
@@ -562,16 +1036,41 @@
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
                 this.setSuccess(false);
-                ServerLevel serverLevel = pointer.getLevel();
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                BlockState blockState = serverLevel.getBlockState(blockPos);
-                if (blockState.is(BlockTags.BEEHIVES, (state) -> {
-                    return state.hasProperty(BeehiveBlock.HONEY_LEVEL) && state.getBlock() instanceof BeehiveBlock;
-                }) && blockState.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) {
-                    ((BeehiveBlock)blockState.getBlock()).releaseBeesAndResetHoneyLevel(serverLevel, blockState, blockPos, (Player)null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED);
+                ServerLevel worldserver = pointer.getLevel();
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                BlockState iblockdata = worldserver.getBlockState(blockposition);
+
+                // CraftBukkit start
+                org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
+                CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+
+                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 = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+                    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) {
+                    ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(worldserver, iblockdata, blockposition, (Player) null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED);
                     this.setSuccess(true);
                     return this.takeLiquid(pointer, stack, new ItemStack(Items.HONEY_BOTTLE));
-                } else if (serverLevel.getFluidState(blockPos).is(FluidTags.WATER)) {
+                } else if (worldserver.getFluidState(blockposition).is(FluidTags.WATER)) {
                     this.setSuccess(true);
                     return this.takeLiquid(pointer, stack, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER));
                 } else {
@@ -582,14 +1081,15 @@
         DispenserBlock.registerBehavior(Items.GLOWSTONE, new OptionalDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                Direction direction = pointer.getBlockState().getValue(DispenserBlock.FACING);
-                BlockPos blockPos = pointer.getPos().relative(direction);
-                Level level = pointer.getLevel();
-                BlockState blockState = level.getBlockState(blockPos);
+                Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
+                BlockPos blockposition = pointer.getPos().relative(enumdirection);
+                ServerLevel worldserver = pointer.getLevel();
+                BlockState iblockdata = worldserver.getBlockState(blockposition);
+
                 this.setSuccess(true);
-                if (blockState.is(Blocks.RESPAWN_ANCHOR)) {
-                    if (blockState.getValue(RespawnAnchorBlock.CHARGE) != 4) {
-                        RespawnAnchorBlock.charge(level, blockPos, blockState);
+                if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) {
+                    if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) {
+                        RespawnAnchorBlock.charge(worldserver, blockposition, iblockdata);
                         stack.shrink(1);
                     } else {
                         this.setSuccess(false);
@@ -605,13 +1105,14 @@
         DispenserBlock.registerBehavior(Items.HONEYCOMB, new OptionalDispenseItemBehavior() {
             @Override
             public ItemStack execute(BlockSource pointer, ItemStack stack) {
-                BlockPos blockPos = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                Level level = pointer.getLevel();
-                BlockState blockState = level.getBlockState(blockPos);
-                Optional<BlockState> optional = HoneycombItem.getWaxed(blockState);
+                BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+                ServerLevel worldserver = pointer.getLevel();
+                BlockState iblockdata = worldserver.getBlockState(blockposition);
+                Optional<BlockState> optional = HoneycombItem.getWaxed(iblockdata);
+
                 if (optional.isPresent()) {
-                    level.setBlockAndUpdate(blockPos, optional.get());
-                    level.levelEvent(3003, blockPos, 0);
+                    worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get());
+                    worldserver.levelEvent(3003, blockposition, 0);
                     stack.shrink(1);
                     this.setSuccess(true);
                     return stack;
@@ -628,21 +1129,22 @@
                 if (PotionUtils.getPotion(stack) != Potions.WATER) {
                     return this.defaultDispenseItemBehavior.dispense(pointer, stack);
                 } else {
-                    ServerLevel serverLevel = pointer.getLevel();
-                    BlockPos blockPos = pointer.getPos();
-                    BlockPos blockPos2 = pointer.getPos().relative(pointer.getBlockState().getValue(DispenserBlock.FACING));
-                    if (!serverLevel.getBlockState(blockPos2).is(BlockTags.CONVERTABLE_TO_MUD)) {
+                    ServerLevel worldserver = pointer.getLevel();
+                    BlockPos blockposition = pointer.getPos();
+                    BlockPos blockposition1 = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
+
+                    if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) {
                         return this.defaultDispenseItemBehavior.dispense(pointer, stack);
                     } else {
-                        if (!serverLevel.isClientSide) {
-                            for(int i = 0; i < 5; ++i) {
-                                serverLevel.sendParticles(ParticleTypes.SPLASH, (double)blockPos.getX() + serverLevel.random.nextDouble(), (double)(blockPos.getY() + 1), (double)blockPos.getZ() + serverLevel.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D);
+                        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);
                             }
                         }
 
-                        serverLevel.playSound((Player)null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
-                        serverLevel.gameEvent((Entity)null, GameEvent.FLUID_PLACE, blockPos);
-                        serverLevel.setBlockAndUpdate(blockPos2, Blocks.MUD.defaultBlockState());
+                        worldserver.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
+                        worldserver.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition);
+                        worldserver.setBlockAndUpdate(blockposition1, Blocks.MUD.defaultBlockState());
                         return new ItemStack(Items.GLASS_BOTTLE);
                     }
                 }
@@ -651,6 +1153,6 @@
     }
 
     static void setEntityPokingOutOfBlock(BlockSource pointer, Entity entity, Direction direction) {
-        entity.setPos(pointer.x() + (double)direction.getStepX() * (0.5000099999997474D - (double)entity.getBbWidth() / 2.0D), pointer.y() + (double)direction.getStepY() * (0.5000099999997474D - (double)entity.getBbHeight() / 2.0D) - (double)entity.getBbHeight() / 2.0D, pointer.z() + (double)direction.getStepZ() * (0.5000099999997474D - (double)entity.getBbWidth() / 2.0D));
+        entity.setPos(pointer.x() + (double) direction.getStepX() * (0.5000099999997474D - (double) entity.getBbWidth() / 2.0D), pointer.y() + (double) direction.getStepY() * (0.5000099999997474D - (double) entity.getBbHeight() / 2.0D) - (double) entity.getBbHeight() / 2.0D, pointer.z() + (double) direction.getStepZ() * (0.5000099999997474D - (double) entity.getBbWidth() / 2.0D));
     }
 }
