--- a/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
+++ b/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
@@ -17,13 +17,20 @@
 import net.minecraft.world.level.Level;
 import net.minecraft.world.phys.HitResult;
 import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
 
 public abstract class AbstractHurtingProjectile extends Projectile {
-    public static final double ATTACK_DEFLECTION_SCALE = 0.1;
-    public static final double BOUNCE_DEFLECTION_SCALE = 0.05;
+
+    public static final double ATTACK_DEFLECTION_SCALE = 0.1D;
+    public static final double BOUNCE_DEFLECTION_SCALE = 0.05D;
     public double xPower;
     public double yPower;
     public double zPower;
+    public float bukkitYield = 1; // CraftBukkit
+    public boolean isIncendiary = true; // CraftBukkit
 
     protected AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> type, Level world) {
         super(type, world);
@@ -34,43 +41,32 @@
         this.setPos(x, y, z);
     }
 
-    public AbstractHurtingProjectile(
-        EntityType<? extends AbstractHurtingProjectile> type,
-        double x,
-        double y,
-        double z,
-        double directionX,
-        double directionY,
-        double directionZ,
-        Level world
-    ) {
+    public AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> type, double x, double y, double z, double directionX, double directionY, double directionZ, Level world) {
         this(type, world);
         this.moveTo(x, y, z, this.getYRot(), this.getXRot());
         this.reapplyPosition();
         this.assignPower(directionX, directionY, directionZ);
     }
 
-    public AbstractHurtingProjectile(
-        EntityType<? extends AbstractHurtingProjectile> type, LivingEntity owner, double directionX, double directionY, double directionZ, Level world
-    ) {
+    public AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> type, LivingEntity owner, double directionX, double directionY, double directionZ, Level world) {
         this(type, owner.getX(), owner.getY(), owner.getZ(), directionX, directionY, directionZ, world);
         this.setOwner(owner);
         this.setRot(owner.getYRot(), owner.getXRot());
     }
 
     @Override
-    protected void defineSynchedData(SynchedEntityData.Builder builder) {
-    }
+    protected void defineSynchedData(SynchedEntityData.Builder builder) {}
 
     @Override
     public boolean shouldRenderAtSqrDistance(double distance) {
-        double d = this.getBoundingBox().getSize() * 4.0;
-        if (Double.isNaN(d)) {
-            d = 4.0;
+        double d1 = this.getBoundingBox().getSize() * 4.0D;
+
+        if (Double.isNaN(d1)) {
+            d1 = 4.0D;
         }
 
-        d *= 64.0;
-        return distance < d * d;
+        d1 *= 64.0D;
+        return distance < d1 * d1;
     }
 
     protected ClipContext.Block getClipType() {
@@ -80,44 +76,56 @@
     @Override
     public void tick() {
         Entity entity = this.getOwner();
-        if (this.level().isClientSide || (entity == null || !entity.isRemoved()) && this.level().hasChunkAt(this.blockPosition())) {
+
+        if (!this.level().isClientSide && (entity != null && entity.isRemoved() || !this.level().hasChunkAt(this.blockPosition()))) {
+            this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
+        } else {
             super.tick();
             if (this.shouldBurn()) {
                 this.igniteForSeconds(1);
             }
 
-            HitResult hitResult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType());
-            if (hitResult.getType() != HitResult.Type.MISS) {
-                this.hitTargetOrDeflectSelf(hitResult);
+            HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType());
+
+            if (movingobjectposition.getType() != HitResult.Type.MISS) {
+                this.preHitTargetOrDeflectSelf(movingobjectposition); // CraftBukkit - projectile hit event
+
+                // CraftBukkit start - Fire ProjectileHitEvent
+                if (this.isRemoved()) {
+                    // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event
+                }
+                // CraftBukkit end
             }
 
             this.checkInsideBlocks();
-            Vec3 vec3 = this.getDeltaMovement();
-            double d = this.getX() + vec3.x;
-            double e = this.getY() + vec3.y;
-            double f = this.getZ() + vec3.z;
+            Vec3 vec3d = this.getDeltaMovement();
+            double d0 = this.getX() + vec3d.x;
+            double d1 = this.getY() + vec3d.y;
+            double d2 = this.getZ() + vec3d.z;
+
             ProjectileUtil.rotateTowardsMovement(this, 0.2F);
-            float h;
+            float f;
+
             if (this.isInWater()) {
-                for (int i = 0; i < 4; i++) {
-                    float g = 0.25F;
-                    this.level().addParticle(ParticleTypes.BUBBLE, d - vec3.x * 0.25, e - vec3.y * 0.25, f - vec3.z * 0.25, vec3.x, vec3.y, vec3.z);
+                for (int i = 0; i < 4; ++i) {
+                    float f1 = 0.25F;
+
+                    this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z);
                 }
 
-                h = this.getLiquidInertia();
+                f = this.getLiquidInertia();
             } else {
-                h = this.getInertia();
+                f = this.getInertia();
             }
 
-            this.setDeltaMovement(vec3.add(this.xPower, this.yPower, this.zPower).scale((double)h));
-            ParticleOptions particleOptions = this.getTrailParticle();
-            if (particleOptions != null) {
-                this.level().addParticle(particleOptions, d, e + 0.5, f, 0.0, 0.0, 0.0);
+            this.setDeltaMovement(vec3d.add(this.xPower, this.yPower, this.zPower).scale((double) f));
+            ParticleOptions particleparam = this.getTrailParticle();
+
+            if (particleparam != null) {
+                this.level().addParticle(particleparam, d0, d1 + 0.5D, d2, 0.0D, 0.0D, 0.0D);
             }
 
-            this.setPos(d, e, f);
-        } else {
-            this.discard();
+            this.setPos(d0, d1, d2);
         }
     }
 
@@ -158,13 +166,15 @@
     public void readAdditionalSaveData(CompoundTag nbt) {
         super.readAdditionalSaveData(nbt);
         if (nbt.contains("power", 9)) {
-            ListTag listTag = nbt.getList("power", 6);
-            if (listTag.size() == 3) {
-                this.xPower = listTag.getDouble(0);
-                this.yPower = listTag.getDouble(1);
-                this.zPower = listTag.getDouble(2);
+            ListTag nbttaglist = nbt.getList("power", 6);
+
+            if (nbttaglist.size() == 3) {
+                this.xPower = nbttaglist.getDouble(0);
+                this.yPower = nbttaglist.getDouble(1);
+                this.zPower = nbttaglist.getDouble(2);
             }
         }
+
     }
 
     @Override
@@ -176,50 +186,43 @@
     public Packet<ClientGamePacketListener> getAddEntityPacket() {
         Entity entity = this.getOwner();
         int i = entity == null ? 0 : entity.getId();
-        return new ClientboundAddEntityPacket(
-            this.getId(),
-            this.getUUID(),
-            this.getX(),
-            this.getY(),
-            this.getZ(),
-            this.getXRot(),
-            this.getYRot(),
-            this.getType(),
-            i,
-            new Vec3(this.xPower, this.yPower, this.zPower),
-            0.0
-        );
+
+        return new ClientboundAddEntityPacket(this.getId(), this.getUUID(), this.getX(), this.getY(), this.getZ(), this.getXRot(), this.getYRot(), this.getType(), i, new Vec3(this.xPower, this.yPower, this.zPower), 0.0D);
     }
 
     @Override
     public void recreateFromPacket(ClientboundAddEntityPacket packet) {
         super.recreateFromPacket(packet);
-        double d = packet.getXa();
-        double e = packet.getYa();
-        double f = packet.getZa();
-        this.assignPower(d, e, f);
+        double d0 = packet.getXa();
+        double d1 = packet.getYa();
+        double d2 = packet.getZa();
+
+        this.assignPower(d0, d1, d2);
     }
 
     public void assignPower(double velocityX, double velocityY, double velocityZ) {
-        double d = Math.sqrt(velocityX * velocityX + velocityY * velocityY + velocityZ * velocityZ);
-        if (d != 0.0) {
-            this.xPower = velocityX / d * 0.1;
-            this.yPower = velocityY / d * 0.1;
-            this.zPower = velocityZ / d * 0.1;
+        double d3 = Math.sqrt(velocityX * velocityX + velocityY * velocityY + velocityZ * velocityZ);
+
+        if (d3 != 0.0D) {
+            this.xPower = velocityX / d3 * 0.1D;
+            this.yPower = velocityY / d3 * 0.1D;
+            this.zPower = velocityZ / d3 * 0.1D;
         }
+
     }
 
     @Override
     protected void onDeflection(@Nullable Entity deflector, boolean fromAttack) {
         super.onDeflection(deflector, fromAttack);
         if (fromAttack) {
-            this.xPower = this.getDeltaMovement().x * 0.1;
-            this.yPower = this.getDeltaMovement().y * 0.1;
-            this.zPower = this.getDeltaMovement().z * 0.1;
+            this.xPower = this.getDeltaMovement().x * 0.1D;
+            this.yPower = this.getDeltaMovement().y * 0.1D;
+            this.zPower = this.getDeltaMovement().z * 0.1D;
         } else {
-            this.xPower = this.getDeltaMovement().x * 0.05;
-            this.yPower = this.getDeltaMovement().y * 0.05;
-            this.zPower = this.getDeltaMovement().z * 0.05;
+            this.xPower = this.getDeltaMovement().x * 0.05D;
+            this.yPower = this.getDeltaMovement().y * 0.05D;
+            this.zPower = this.getDeltaMovement().z * 0.05D;
         }
+
     }
 }
