diff --git a/src/main/java/net/minecraft/server/BlockButtonAbstract.java b/src/main/java/net/minecraft/server/BlockButtonAbstract.java
index 5627ba47b3..6e542058e1 100644
--- a/src/main/java/net/minecraft/server/BlockButtonAbstract.java
+++ b/src/main/java/net/minecraft/server/BlockButtonAbstract.java
@@ -201,20 +201,19 @@ public abstract class BlockButtonAbstract extends Block {
             int l = world.getData(i, j, k);
 
             if ((l & 8) != 0) {
-                // CraftBukkit start
-                org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
-
-                BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, 15, 0);
-                world.getServer().getPluginManager().callEvent(eventRedstone);
-
-                if (eventRedstone.getNewCurrent() > 0) {
-                    return;
-                }
-                // CraftBukkit end
-
                 if (this.a) {
                     this.n(world, i, j, k);
                 } else {
+                    // CraftBukkit start
+                    org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
+
+                    BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, 15, 0);
+                    world.getServer().getPluginManager().callEvent(eventRedstone);
+
+                    if (eventRedstone.getNewCurrent() > 0) {
+                        return;
+                    }
+                    // CraftBukkit end
                     world.setData(i, j, k, l & 7, 3);
                     int i1 = l & 7;
 
@@ -278,6 +277,16 @@ public abstract class BlockButtonAbstract extends Block {
         // CraftBukkit end
 
         if (flag1 && !flag) {
+            // CraftBukkit start
+            org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
+
+            BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, 0, 15);
+            world.getServer().getPluginManager().callEvent(eventRedstone);
+
+            if (eventRedstone.getNewCurrent() <= 0) {
+                return;
+            }
+            // CraftBukkit end
             world.setData(i, j, k, i1 | 8, 3);
             this.a(world, i, j, k, i1);
             world.c(i, j, k, i, j, k);
@@ -285,6 +294,16 @@ public abstract class BlockButtonAbstract extends Block {
         }
 
         if (!flag1 && flag) {
+            // CraftBukkit start
+            org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
+
+            BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, 15, 0);
+            world.getServer().getPluginManager().callEvent(eventRedstone);
+
+            if (eventRedstone.getNewCurrent() > 0) {
+                return;
+            }
+            // CraftBukkit end
             world.setData(i, j, k, i1, 3);
             this.a(world, i, j, k, i1);
             world.c(i, j, k, i, j, k);
diff --git a/src/main/java/net/minecraft/server/BlockCocoa.java b/src/main/java/net/minecraft/server/BlockCocoa.java
index 7084c880cc..88efe0b3f8 100644
--- a/src/main/java/net/minecraft/server/BlockCocoa.java
+++ b/src/main/java/net/minecraft/server/BlockCocoa.java
@@ -2,6 +2,8 @@ package net.minecraft.server;
 
 import java.util.Random;
 
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+
 public class BlockCocoa extends BlockDirectional implements IBlockFragilePlantElement {
 
     public BlockCocoa() {
@@ -20,7 +22,7 @@ public class BlockCocoa extends BlockDirectional implements IBlockFragilePlantEl
             if (i1 < 2) {
                 ++i1;
                 // CraftBukkit
-                org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, i1 << 2 | l(l));
+                CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, i1 << 2 | l(l));
             }
         }
     }
@@ -137,6 +139,6 @@ public class BlockCocoa extends BlockDirectional implements IBlockFragilePlantEl
         int j1 = c(l);
 
         ++j1;
-        world.setData(i, j, k, j1 << 2 | i1, 2);
+        CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, j1 << 2 | i1); // CraftBukkit
     }
 }
diff --git a/src/main/java/net/minecraft/server/BlockCrops.java b/src/main/java/net/minecraft/server/BlockCrops.java
index 942d6ab203..875181f58b 100644
--- a/src/main/java/net/minecraft/server/BlockCrops.java
+++ b/src/main/java/net/minecraft/server/BlockCrops.java
@@ -2,6 +2,8 @@ package net.minecraft.server;
 
 import java.util.Random;
 
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+
 public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement {
 
     protected BlockCrops() {
@@ -29,7 +31,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement
 
                 if (random.nextInt((int) (25.0F / f) + 1) == 0) {
                     ++l;
-                    org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, l); // CraftBukkit
+                    CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, l); // CraftBukkit
                 }
             }
         }
@@ -42,7 +44,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement
             l = 7;
         }
 
-        world.setData(i, j, k, l, 2);
+        CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, l); // CraftBukkit
     }
 
     private float n(World world, int i, int j, int k) {
diff --git a/src/main/java/net/minecraft/server/BlockGrass.java b/src/main/java/net/minecraft/server/BlockGrass.java
index bf14bbb0b2..abd991b41f 100644
--- a/src/main/java/net/minecraft/server/BlockGrass.java
+++ b/src/main/java/net/minecraft/server/BlockGrass.java
@@ -7,6 +7,7 @@ import org.apache.logging.log4j.Logger;
 
 // CraftBukkit start
 import org.bukkit.block.BlockState;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
 import org.bukkit.craftbukkit.util.CraftMagicNumbers;
 import org.bukkit.event.block.BlockSpreadEvent;
 import org.bukkit.event.block.BlockFadeEvent;
@@ -96,7 +97,7 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement {
                 } else if (world.getType(i1, j1, k1).material == Material.AIR) {
                     if (random.nextInt(8) != 0) {
                         if (Blocks.LONG_GRASS.j(world, i1, j1, k1)) {
-                            world.setTypeAndData(i1, j1, k1, Blocks.LONG_GRASS, 1, 3);
+                            CraftEventFactory.handleBlockGrowEvent(world, i1, j1, k1, Blocks.LONG_GRASS, 1); // CraftBukkit
                         }
                     } else {
                         String s = world.getBiome(i1, k1).a(random, i1, j1, k1);
@@ -107,7 +108,7 @@ public class BlockGrass extends Block implements IBlockFragilePlantElement {
                         if (blockflowers != null && blockflowers.j(world, i1, j1, k1)) {
                             int i2 = BlockFlowers.f(s);
 
-                            world.setTypeAndData(i1, j1, k1, blockflowers, i2, 3);
+                            CraftEventFactory.handleBlockGrowEvent(world, i1, j1, k1, blockflowers, i2); // CraftBukkit
                         }
                     }
                 }
diff --git a/src/main/java/net/minecraft/server/BlockRedstoneOre.java b/src/main/java/net/minecraft/server/BlockRedstoneOre.java
index d5ed37e06c..0cd2e04efc 100644
--- a/src/main/java/net/minecraft/server/BlockRedstoneOre.java
+++ b/src/main/java/net/minecraft/server/BlockRedstoneOre.java
@@ -2,7 +2,10 @@ package net.minecraft.server;
 
 import java.util.Random;
 
-import org.bukkit.event.entity.EntityInteractEvent; // CraftBukkit
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityInteractEvent;
+// CraftBukkit end
 
 public class BlockRedstoneOre extends Block {
 
@@ -22,7 +25,7 @@ public class BlockRedstoneOre extends Block {
     }
 
     public void attack(World world, int i, int j, int k, EntityHuman entityhuman) {
-        this.e(world, i, j, k);
+        this.e(world, i, j, k, entityhuman); // CraftBukkit - add entityhuman
         super.attack(world, i, j, k, entityhuman);
     }
 
@@ -31,14 +34,14 @@ public class BlockRedstoneOre extends Block {
         if (entity instanceof EntityHuman) {
             org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, i, j, k, -1, null);
             if (!event.isCancelled()) {
-                this.e(world, i, j, k);
+                this.e(world, i, j, k, entity); // add entity
                 super.b(world, i, j, k, entity);
             }
         } else {
             EntityInteractEvent event = new EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(i, j, k));
             world.getServer().getPluginManager().callEvent(event);
             if (!event.isCancelled()) {
-                this.e(world, i, j, k);
+                this.e(world, i, j, k, entity); // add entity
                 super.b(world, i, j, k, entity);
             }
         }
@@ -46,19 +49,29 @@ public class BlockRedstoneOre extends Block {
     }
 
     public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman, int l, float f, float f1, float f2) {
-        this.e(world, i, j, k);
+        this.e(world, i, j, k, entityhuman); // CraftBukkit - add entityhuman
         return super.interact(world, i, j, k, entityhuman, l, f, f1, f2);
     }
 
-    private void e(World world, int i, int j, int k) {
+    private void e(World world, int i, int j, int k, Entity entity) { // CraftBukkit - add Entity
         this.m(world, i, j, k);
         if (this == Blocks.REDSTONE_ORE) {
+            // CraftBukkit start
+            if (CraftEventFactory.callEntityChangeBlockEvent(entity, i, j, k, Blocks.GLOWING_REDSTONE_ORE, 0).isCancelled()) {
+                return;
+            }
+            // CraftBukkit end
             world.setTypeUpdate(i, j, k, Blocks.GLOWING_REDSTONE_ORE);
         }
     }
 
     public void a(World world, int i, int j, int k, Random random) {
         if (this == Blocks.GLOWING_REDSTONE_ORE) {
+            // CraftBukkit start
+            if (CraftEventFactory.callBlockFadeEvent(world.getWorld().getBlockAt(i, j, k), Blocks.REDSTONE_ORE).isCancelled()) {
+                return;
+            }
+            // CraftBukkit end
             world.setTypeUpdate(i, j, k, Blocks.REDSTONE_ORE);
         }
     }
diff --git a/src/main/java/net/minecraft/server/BlockSoil.java b/src/main/java/net/minecraft/server/BlockSoil.java
index c7a48a6a54..b234a5378b 100644
--- a/src/main/java/net/minecraft/server/BlockSoil.java
+++ b/src/main/java/net/minecraft/server/BlockSoil.java
@@ -67,8 +67,11 @@ public class BlockSoil extends Block {
             if (cancellable.isCancelled()) {
                 return;
             }
-            // CraftBukkit end
 
+            if (CraftEventFactory.callEntityChangeBlockEvent(entity, i, j, k, Blocks.DIRT, 0).isCancelled()) {
+                return;
+            }
+            // CraftBukkit end
             world.setTypeUpdate(i, j, k, Blocks.DIRT);
         }
     }
diff --git a/src/main/java/net/minecraft/server/BlockStem.java b/src/main/java/net/minecraft/server/BlockStem.java
index 4fae805bff..40ad1c65c2 100644
--- a/src/main/java/net/minecraft/server/BlockStem.java
+++ b/src/main/java/net/minecraft/server/BlockStem.java
@@ -86,7 +86,7 @@ public class BlockStem extends BlockPlant implements IBlockFragilePlantElement {
             l = 7;
         }
 
-        world.setData(i, j, k, l, 2);
+        CraftEventFactory.handleBlockGrowEvent(world, i, j, k, this, l); // CraftBukkit
     }
 
     private float n(World world, int i, int j, int k) {
diff --git a/src/main/java/net/minecraft/server/BlockTallPlant.java b/src/main/java/net/minecraft/server/BlockTallPlant.java
index 2bb9b7d009..4a0e988952 100644
--- a/src/main/java/net/minecraft/server/BlockTallPlant.java
+++ b/src/main/java/net/minecraft/server/BlockTallPlant.java
@@ -76,7 +76,7 @@ public class BlockTallPlant extends BlockPlant implements IBlockFragilePlantElem
 
     public void c(World world, int i, int j, int k, int l, int i1) {
         world.setTypeAndData(i, j, k, this, l, i1);
-        world.setTypeAndData(i, j + 1, k, this, 8, i1);
+        org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, i, j + 1, k, this, 8); // CraftBukkit
     }
 
     public void postPlace(World world, int i, int j, int k, EntityLiving entityliving, ItemStack itemstack) {
diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java
index 1def068f47..a542c9a137 100644
--- a/src/main/java/net/minecraft/server/EntityEnderCrystal.java
+++ b/src/main/java/net/minecraft/server/EntityEnderCrystal.java
@@ -1,6 +1,9 @@
 package net.minecraft.server;
 
-import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.ExplosionPrimeEvent;
+// CraftBukkit end
 
 public class EntityEnderCrystal extends Entity {
 
@@ -64,10 +67,18 @@ public class EntityEnderCrystal extends Entity {
 
                 this.b = 0;
                 if (this.b <= 0) {
-                    this.die();
+                    // this.die(); // CraftBukkit - moved down
                     if (!this.world.isStatic) {
-                        this.world.explode(this, this.locX, this.locY, this.locZ, 6.0F, true); // CraftBukkit - (Entity) null -> this
+                        // CraftBukkit start
+                        ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 6.0F, false);
+                        this.world.getServer().getPluginManager().callEvent(event);
+                        if (event.isCancelled()) {
+                            return false;
+                        }
+                        this.world.createExplosion(this, this.locX, this.locY, this.locZ, event.getRadius(), event.getFire(), true);
                     }
+                    this.die();
+                    // CraftBukkit end
                 }
             }
 
diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java
index 5978ea3830..7d67210e69 100644
--- a/src/main/java/net/minecraft/server/EntityHorse.java
+++ b/src/main/java/net/minecraft/server/EntityHorse.java
@@ -6,6 +6,7 @@ import java.util.List;
 // CraftBukkit start
 import org.bukkit.craftbukkit.event.CraftEventFactory;
 import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
 // CraftBukkit end
 
 public class EntityHorse extends EntityAnimal implements IInventoryListener {
@@ -601,7 +602,7 @@ public class EntityHorse extends EntityAnimal implements IInventoryListener {
                     }
 
                     if (this.getHealth() < this.getMaxHealth() && f > 0.0F) {
-                        this.heal(f);
+                        this.heal(f, RegainReason.EATING); // CraftBukkit
                         flag = true;
                     }
 
@@ -720,7 +721,7 @@ public class EntityHorse extends EntityAnimal implements IInventoryListener {
         super.e();
         if (!this.world.isStatic) {
             if (this.random.nextInt(900) == 0 && this.deathTicks == 0) {
-                this.heal(1.0F);
+                this.heal(1.0F, RegainReason.REGEN); // CraftBukkit
             }
 
             if (!this.cm() && this.passenger == null && this.random.nextInt(300) == 0 && this.world.getType(MathHelper.floor(this.locX), MathHelper.floor(this.locY) - 1, MathHelper.floor(this.locZ)) == Blocks.GRASS) {
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
index b4a0122752..381ba31653 100644
--- a/src/main/java/net/minecraft/server/EntityHuman.java
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
@@ -911,8 +911,15 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen
                     int j = EnchantmentManager.getFireAspectEnchantmentLevel(this);
 
                     if (entity instanceof EntityLiving && j > 0 && !entity.isBurning()) {
-                        flag1 = true;
-                        entity.setOnFire(1);
+                        // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item
+                        EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 1);
+                        org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent);
+
+                        if (!combustEvent.isCancelled()) {
+                            flag1 = true;
+                            entity.setOnFire(combustEvent.getDuration());
+                        }
+                        // CraftBukkit end
                     }
 
                     boolean flag2 = entity.damageEntity(DamageSource.playerAttack(this), f);
diff --git a/src/main/java/net/minecraft/server/EntityMonster.java b/src/main/java/net/minecraft/server/EntityMonster.java
index 6e02e2a5b8..d13a91e45f 100644
--- a/src/main/java/net/minecraft/server/EntityMonster.java
+++ b/src/main/java/net/minecraft/server/EntityMonster.java
@@ -1,5 +1,6 @@
 package net.minecraft.server;
 
+import org.bukkit.event.entity.EntityCombustByEntityEvent;
 import org.bukkit.event.entity.EntityTargetEvent; // CraftBukkit
 
 public abstract class EntityMonster extends EntityCreature implements IMonster {
@@ -108,7 +109,14 @@ public abstract class EntityMonster extends EntityCreature implements IMonster {
             int j = EnchantmentManager.getFireAspectEnchantmentLevel(this);
 
             if (j > 0) {
-                entity.setOnFire(j * 4);
+                // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item
+                EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), j * 4);
+                org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent);
+
+                if (!combustEvent.isCancelled()) {
+                    entity.setOnFire(combustEvent.getDuration());
+                }
+                // CraftBukkit end
             }
 
             if (entity instanceof EntityLiving) {
diff --git a/src/main/java/net/minecraft/server/EntitySkeleton.java b/src/main/java/net/minecraft/server/EntitySkeleton.java
index cb25df17a5..fd3fd3bf99 100644
--- a/src/main/java/net/minecraft/server/EntitySkeleton.java
+++ b/src/main/java/net/minecraft/server/EntitySkeleton.java
@@ -240,7 +240,14 @@ public class EntitySkeleton extends EntityMonster implements IRangedEntity {
         }
 
         if (EnchantmentManager.getEnchantmentLevel(Enchantment.ARROW_FIRE.id, this.bd()) > 0 || this.getSkeletonType() == 1) {
-            entityarrow.setOnFire(100);
+            // CraftBukkit start - call EntityCombustEvent
+            EntityCombustEvent event = new EntityCombustEvent(entityarrow.getBukkitEntity(), 100);
+            this.world.getServer().getPluginManager().callEvent(event);
+
+            if (!event.isCancelled()) {
+                entityarrow.setOnFire(event.getDuration());
+            }
+            // CraftBukkit end
         }
 
         // CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java
index 99526b99b1..352f7396d9 100644
--- a/src/main/java/net/minecraft/server/EntityWither.java
+++ b/src/main/java/net/minecraft/server/EntityWither.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 // CraftBukkit start
 import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRegainHealthEvent;
 import org.bukkit.event.entity.ExplosionPrimeEvent;
 // CraftBukkit end
 
@@ -177,7 +178,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
 
             this.s(i);
             if (this.ticksLived % 10 == 0) {
-                this.heal(10.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit
+                this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit
             }
         } else {
             super.bm();
@@ -280,7 +281,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
             }
 
             if (this.ticksLived % 20 == 0) {
-                this.heal(1.0F);
+                this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
             }
         }
     }
diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java
index dc144413da..9a4e0c4cc6 100644
--- a/src/main/java/net/minecraft/server/EntityWolf.java
+++ b/src/main/java/net/minecraft/server/EntityWolf.java
@@ -210,7 +210,7 @@ public class EntityWolf extends EntityTameableAnimal {
                             --itemstack.count;
                         }
 
-                        this.heal((float) itemfood.getNutrition(itemstack));
+                        this.heal((float) itemfood.getNutrition(itemstack), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit
                         if (itemstack.count <= 0) {
                             entityhuman.inventory.setItem(entityhuman.inventory.itemInHandIndex, (ItemStack) null);
                         }
diff --git a/src/main/java/net/minecraft/server/ItemBow.java b/src/main/java/net/minecraft/server/ItemBow.java
index b3472dd1b2..a1bf31af48 100644
--- a/src/main/java/net/minecraft/server/ItemBow.java
+++ b/src/main/java/net/minecraft/server/ItemBow.java
@@ -1,5 +1,7 @@
 package net.minecraft.server;
 
+import org.bukkit.event.entity.EntityCombustEvent; // CraftBukkit
+
 public class ItemBow extends Item {
 
     public static final String[] a = new String[] { "pulling_0", "pulling_1", "pulling_2"};
@@ -45,7 +47,14 @@ public class ItemBow extends Item {
             }
 
             if (EnchantmentManager.getEnchantmentLevel(Enchantment.ARROW_FIRE.id, itemstack) > 0) {
-                entityarrow.setOnFire(100);
+                // CraftBukkit start - call EntityCombustEvent
+                EntityCombustEvent event = new EntityCombustEvent(entityarrow.getBukkitEntity(), 100);
+                entityarrow.world.getServer().getPluginManager().callEvent(event);
+
+                if (!event.isCancelled()) {
+                    entityarrow.setOnFire(event.getDuration());
+                }
+                // CraftBukkit end
             }
 
             // CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/ItemFireball.java b/src/main/java/net/minecraft/server/ItemFireball.java
index 9f8291ed43..bee5320be1 100644
--- a/src/main/java/net/minecraft/server/ItemFireball.java
+++ b/src/main/java/net/minecraft/server/ItemFireball.java
@@ -1,5 +1,10 @@
 package net.minecraft.server;
 
+// CraftBukkit start
+import org.bukkit.craftbukkit.block.CraftBlockState;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
+
 public class ItemFireball extends Item {
 
     public ItemFireball() {
@@ -7,6 +12,7 @@ public class ItemFireball extends Item {
     }
 
     public boolean interactWith(ItemStack itemstack, EntityHuman entityhuman, World world, int i, int j, int k, int l, float f, float f1, float f2) {
+        int clickedX = i, clickedY = j, clickedZ = k; // CraftBukkit
         if (world.isStatic) {
             return true;
         } else {
@@ -45,10 +51,21 @@ public class ItemFireball extends Item {
                         }
                         return false;
                     }
+
+                    CraftBlockState blockState = CraftBlockState.getBlockState(world, i, j, k);
                     // CraftBukkit end
 
                     world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "fire.ignite", 1.0F, g.nextFloat() * 0.4F + 0.8F);
                     world.setTypeUpdate(i, j, k, Blocks.FIRE);
+
+                    // CraftBukkit start
+                    org.bukkit.event.block.BlockPlaceEvent placeEvent = CraftEventFactory.callBlockPlaceEvent(world, entityhuman, blockState, clickedX, clickedY, clickedZ);
+
+                    if (placeEvent.isCancelled() || !placeEvent.canBuild()) {
+                        placeEvent.getBlockPlaced().setTypeIdAndData(0, (byte) 0, false);
+                        return false;
+                    }
+                    // CraftBukkit end
                 }
 
                 if (!entityhuman.abilities.canInstantlyBuild) {
diff --git a/src/main/java/net/minecraft/server/MobEffectList.java b/src/main/java/net/minecraft/server/MobEffectList.java
index dbbe63ce79..a66e66cbbd 100644
--- a/src/main/java/net/minecraft/server/MobEffectList.java
+++ b/src/main/java/net/minecraft/server/MobEffectList.java
@@ -95,7 +95,18 @@ public class MobEffectList {
             ((EntityHuman) entityliving).a(0.025F * (float) (i + 1));
         } else if (this.id == SATURATION.id && entityliving instanceof EntityHuman) {
             if (!entityliving.world.isStatic) {
-                ((EntityHuman) entityliving).getFoodData().eat(i + 1, 1.0F);
+                // CraftBukkit start
+                EntityHuman entityhuman = (EntityHuman) entityliving;
+                int oldFoodLevel = entityhuman.getFoodData().foodLevel;
+
+                org.bukkit.event.entity.FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, i + 1 + oldFoodLevel);
+
+                if (!event.isCancelled()) {
+                    entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F);
+                }
+
+                ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutUpdateHealth(((EntityPlayer) entityhuman).getBukkitEntity().getScaledHealth(), entityhuman.getFoodData().foodLevel, entityhuman.getFoodData().saturationLevel));
+                // CraftBukkit end
             }
         } else if ((this.id != HEAL.id || entityliving.aQ()) && (this.id != HARM.id || !entityliving.aQ())) {
             if (this.id == HARM.id && !entityliving.aQ() || this.id == HEAL.id && entityliving.aQ()) {