--- a/net/minecraft/server/DispenseBehaviorShears.java
+++ b/net/minecraft/server/DispenseBehaviorShears.java
@@ -2,6 +2,11 @@
 
 import java.util.Iterator;
 import java.util.List;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.event.block.BlockDispenseEvent;
+// CraftBukkit end
 
 public class DispenseBehaviorShears extends DispenseBehaviorMaybe {
 
@@ -10,11 +15,34 @@
     @Override
     protected ItemStack a(ISourceBlock isourceblock, ItemStack itemstack) {
         World world = isourceblock.getWorld();
+        // CraftBukkit start
+        org.bukkit.block.Block bukkitBlock = world.getWorld().getBlockAt(isourceblock.getBlockPosition().getX(), isourceblock.getBlockPosition().getY(), isourceblock.getBlockPosition().getZ());
+        CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
+
+        BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
+        if (!BlockDispenser.eventFired) {
+            world.getServer().getPluginManager().callEvent(event);
+        }
+
+        if (event.isCancelled()) {
+            return itemstack;
+        }
+
+        if (!event.getItem().equals(craftItem)) {
+            // Chain to handler for new item
+            ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+            IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.REGISTRY.get(eventStack.getItem());
+            if (idispensebehavior != IDispenseBehavior.NONE && idispensebehavior != this) {
+                idispensebehavior.dispense(isourceblock, eventStack);
+                return itemstack;
+            }
+        }
+        // CraftBukkit end
 
         if (!world.s_()) {
             BlockPosition blockposition = isourceblock.getBlockPosition().shift((EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING));
 
-            this.a(a((WorldServer) world, blockposition) || b((WorldServer) world, blockposition));
+            this.a(a((WorldServer) world, blockposition) || b((WorldServer) world, blockposition, bukkitBlock, craftItem)); // CraftBukkit
             if (this.a() && itemstack.isDamaged(1, world.getRandom(), (EntityPlayer) null)) {
                 itemstack.setCount(0);
             }
@@ -40,7 +68,7 @@
         return false;
     }
 
-    private static boolean b(WorldServer worldserver, BlockPosition blockposition) {
+    private static boolean b(WorldServer worldserver, BlockPosition blockposition, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args
         List<EntityLiving> list = worldserver.a(EntityLiving.class, new AxisAlignedBB(blockposition), IEntitySelector.g);
         Iterator iterator = list.iterator();
 
@@ -51,6 +79,11 @@
                 IShearable ishearable = (IShearable) entityliving;
 
                 if (ishearable.canShear()) {
+                    // CraftBukkit start
+                    if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) {
+                        continue;
+                    }
+                    // CraftBukkit end
                     ishearable.shear(SoundCategory.BLOCKS);
                     return true;
                 }