--- a/net/minecraft/world/level/block/DropperBlock.java
+++ b/net/minecraft/world/level/block/DropperBlock.java
@@ -6,6 +6,7 @@
 import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
 import net.minecraft.core.dispenser.DispenseItemBehavior;
 import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.CompoundContainer;
 import net.minecraft.world.Container;
 import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.level.block.entity.BlockEntity;
@@ -14,9 +15,13 @@
 import net.minecraft.world.level.block.entity.HopperBlockEntity;
 import net.minecraft.world.level.block.state.BlockBehaviour;
 import net.minecraft.world.level.block.state.BlockState;
+import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
+import org.bukkit.event.inventory.InventoryMoveItemEvent;
+// CraftBukkit end
 
 public class DropperBlock extends DispenserBlock {
-    private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior();
+
+    private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(true); // CraftBukkit
 
     public DropperBlock(BlockBehaviour.Properties settings) {
         super(settings);
@@ -24,7 +29,7 @@
 
     @Override
     protected DispenseItemBehavior getDispenseMethod(ItemStack stack) {
-        return DISPENSE_BEHAVIOUR;
+        return DropperBlock.DISPENSE_BEHAVIOUR;
     }
 
     @Override
@@ -34,30 +39,51 @@
 
     @Override
     public void dispenseFrom(ServerLevel world, BlockPos pos) {
-        BlockSourceImpl blockSourceImpl = new BlockSourceImpl(world, pos);
-        DispenserBlockEntity dispenserBlockEntity = blockSourceImpl.getEntity();
-        int i = dispenserBlockEntity.getRandomSlot(world.random);
+        BlockSourceImpl sourceblock = new BlockSourceImpl(world, pos);
+        DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) sourceblock.getEntity();
+        int i = tileentitydispenser.getRandomSlot(world.random);
+
         if (i < 0) {
+            if (org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) // Paper - BlockFailedDispenseEvent is called here
             world.levelEvent(1001, pos, 0);
         } else {
-            ItemStack itemStack = dispenserBlockEntity.getItem(i);
-            if (!itemStack.isEmpty()) {
-                Direction direction = world.getBlockState(pos).getValue(FACING);
-                Container container = HopperBlockEntity.getContainerAt(world, pos.relative(direction));
-                ItemStack itemStack2;
-                if (container == null) {
-                    itemStack2 = DISPENSE_BEHAVIOUR.dispense(blockSourceImpl, itemStack);
+            ItemStack itemstack = tileentitydispenser.getItem(i);
+
+            if (!itemstack.isEmpty()) {
+                Direction enumdirection = (Direction) world.getBlockState(pos).getValue(DropperBlock.FACING);
+                Container iinventory = HopperBlockEntity.getContainerAt(world, pos.relative(enumdirection));
+                ItemStack itemstack1;
+
+                if (iinventory == null) {
+                    itemstack1 = DropperBlock.DISPENSE_BEHAVIOUR.dispense(sourceblock, itemstack);
                 } else {
-                    itemStack2 = HopperBlockEntity.addItem(dispenserBlockEntity, container, itemStack.copy().split(1), direction.getOpposite());
-                    if (itemStack2.isEmpty()) {
-                        itemStack2 = itemStack.copy();
-                        itemStack2.shrink(1);
+                    // CraftBukkit start - Fire event when pushing items into other inventories
+                    CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack.copy().split(1));
+
+                    org.bukkit.inventory.Inventory destinationInventory;
+                    // Have to special case large chests as they work oddly
+                    if (iinventory instanceof CompoundContainer) {
+                        destinationInventory = new org.bukkit.craftbukkit.v1_19_R2.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
                     } else {
-                        itemStack2 = itemStack.copy();
+                        destinationInventory = iinventory.getOwner().getInventory();
+                    }
+
+                    InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentitydispenser.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true);
+                    world.getCraftServer().getPluginManager().callEvent(event);
+                    if (event.isCancelled()) {
+                        return;
+                    }
+                    itemstack1 = HopperBlockEntity.addItem(tileentitydispenser, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection.getOpposite());
+                    if (event.getItem().equals(oitemstack) && itemstack1.isEmpty()) {
+                        // CraftBukkit end
+                        itemstack1 = itemstack.copy();
+                        itemstack1.shrink(1);
+                    } else {
+                        itemstack1 = itemstack.copy();
                     }
                 }
 
-                dispenserBlockEntity.setItem(i, itemStack2);
+                tileentitydispenser.setItem(i, itemstack1);
             }
         }
     }
