--- ../src-base/minecraft/net/minecraft/entity/projectile/EntityFireball.java
+++ ../src-work/minecraft/net/minecraft/entity/projectile/EntityFireball.java
@@ -2,7 +2,9 @@
 
 import cpw.mods.fml.relauncher.Side;
 import cpw.mods.fml.relauncher.SideOnly;
+
 import java.util.List;
+
 import net.minecraft.block.Block;
 import net.minecraft.entity.Entity;
 import net.minecraft.entity.EntityLivingBase;
@@ -15,6 +17,8 @@
 import net.minecraft.util.Vec3;
 import net.minecraft.world.World;
 
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+
 public abstract class EntityFireball extends Entity
 {
     private int field_145795_e = -1;
@@ -28,6 +32,8 @@
     public double accelerationX;
     public double accelerationY;
     public double accelerationZ;
+    public float bukkitYield = 1; // CraftBukkit
+    public boolean isIncendiary = true; // CraftBukkit
     private static final String __OBFID = "CL_00001717";
 
     public EntityFireball(World p_i1759_1_)
@@ -62,11 +68,19 @@
     {
         super(p_i1761_1_);
         this.shootingEntity = p_i1761_2_;
+        this.projectileSource = (org.bukkit.entity.LivingEntity) p_i1761_2_.getBukkitEntity(); // CraftBukkit
         this.setSize(1.0F, 1.0F);
         this.setLocationAndAngles(p_i1761_2_.posX, p_i1761_2_.posY, p_i1761_2_.posZ, p_i1761_2_.rotationYaw, p_i1761_2_.rotationPitch);
         this.setPosition(this.posX, this.posY, this.posZ);
         this.yOffset = 0.0F;
         this.motionX = this.motionY = this.motionZ = 0.0D;
+        // CraftBukkit start - Added setDirection method
+        this.setDirection(p_i1761_3_, p_i1761_5_, p_i1761_7_);
+    }
+
+    public void setDirection(double p_i1761_3_, double p_i1761_5_, double p_i1761_7_)
+    {
+        // CraftBukkit end
         p_i1761_3_ += this.rand.nextGaussian() * 0.4D;
         p_i1761_5_ += this.rand.nextGaussian() * 0.4D;
         p_i1761_7_ += this.rand.nextGaussian() * 0.4D;
@@ -140,7 +154,7 @@
 
                     if (movingobjectposition1 != null)
                     {
-                        double d1 = vec3.distanceTo(movingobjectposition1.hitVec);
+                        double d1 = vec3.squareDistanceTo(movingobjectposition1.hitVec); // CraftBukkit - distance efficiency
 
                         if (d1 < d0 || d0 == 0.0D)
                         {
@@ -159,6 +173,14 @@
             if (movingobjectposition != null)
             {
                 this.onImpact(movingobjectposition);
+
+                // CraftBukkit start
+                if (this.isDead)
+                {
+                    CraftEventFactory.callProjectileHitEvent(this);
+                }
+
+                // CraftBukkit end
             }
 
             this.posX += this.motionX;
@@ -227,6 +249,8 @@
         p_70014_1_.setShort("zTile", (short)this.field_145794_g);
         p_70014_1_.setByte("inTile", (byte)Block.getIdFromBlock(this.field_145796_h));
         p_70014_1_.setByte("inGround", (byte)(this.inGround ? 1 : 0));
+        // CraftBukkit - Fix direction being mismapped to invalid variables
+        p_70014_1_.setTag("power", this.newDoubleNBTList(new double[] { this.accelerationX, this.accelerationY, this.accelerationZ}));
         p_70014_1_.setTag("direction", this.newDoubleNBTList(new double[] {this.motionX, this.motionY, this.motionZ}));
     }
 
@@ -238,8 +262,17 @@
         this.field_145796_h = Block.getBlockById(p_70037_1_.getByte("inTile") & 255);
         this.inGround = p_70037_1_.getByte("inGround") == 1;
 
-        if (p_70037_1_.hasKey("direction", 9))
+        // CraftBukkit start - direction -> power
+        if (p_70037_1_.hasKey("power", 9))
         {
+            NBTTagList nbttaglist = p_70037_1_.getTagList("power", 6);
+            this.accelerationX = nbttaglist.func_150309_d(0);
+            this.accelerationY = nbttaglist.func_150309_d(1);
+            this.accelerationZ = nbttaglist.func_150309_d(2);
+            // CraftBukkit end
+        }
+        else if (p_70037_1_.hasKey("direction", 9))
+        {
             NBTTagList nbttaglist = p_70037_1_.getTagList("direction", 6);
             this.motionX = nbttaglist.func_150309_d(0);
             this.motionY = nbttaglist.func_150309_d(1);
@@ -273,6 +306,13 @@
 
             if (p_70097_1_.getEntity() != null)
             {
+                // CraftBukkit start
+                if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, p_70097_1_, p_70097_2_))
+                {
+                    return false;
+                }
+
+                // CraftBukkit end
                 Vec3 vec3 = p_70097_1_.getEntity().getLookVec();
 
                 if (vec3 != null)
@@ -288,6 +328,7 @@
                 if (p_70097_1_.getEntity() instanceof EntityLivingBase)
                 {
                     this.shootingEntity = (EntityLivingBase)p_70097_1_.getEntity();
+                    this.projectileSource = (org.bukkit.projectiles.ProjectileSource) this.shootingEntity.getBukkitEntity(); // CraftBukkit
                 }
 
                 return true;
@@ -315,4 +356,11 @@
     {
         return 15728880;
     }
+
+    // Cauldron start
+    @Override
+    public boolean entityProjectileHook() {
+        return true;
+    }
+    // Cauldron end
 }
