--- a/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
+++ b/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java
@@ -17,14 +17,22 @@
 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 INITAL_ACCELERATION_POWER = 0.1;
-    public static final double DEFLECTION_SCALE = 0.5;
-    public double accelerationPower = 0.1;
+
+    public static final double INITAL_ACCELERATION_POWER = 0.1D;
+    public static final double DEFLECTION_SCALE = 0.5D;
+    public double accelerationPower;
+    public float bukkitYield = 1; // CraftBukkit
+    public boolean isIncendiary = true; // CraftBukkit
 
     protected AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> type, Level world) {
         super(type, world);
+        this.accelerationPower = 0.1D;
     }
 
     protected AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> type, double x, double y, double z, Level world) {
@@ -46,18 +54,18 @@
     }
 
     @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() {
@@ -67,44 +75,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.0F);
             }
 
-            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(vec3.normalize().scale(this.accelerationPower)).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(vec3d.normalize().scale(this.accelerationPower)).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);
         }
     }
 
@@ -147,6 +167,7 @@
         if (nbt.contains("acceleration_power", 6)) {
             this.accelerationPower = nbt.getDouble("acceleration_power");
         }
+
     }
 
     @Override
@@ -158,27 +179,17 @@
     public Packet<ClientGamePacketListener> getAddEntityPacket(ServerEntity entityTrackerEntry) {
         Entity entity = this.getOwner();
         int i = entity == null ? 0 : entity.getId();
-        Vec3 vec3 = entityTrackerEntry.getPositionBase();
-        return new ClientboundAddEntityPacket(
-            this.getId(),
-            this.getUUID(),
-            vec3.x(),
-            vec3.y(),
-            vec3.z(),
-            entityTrackerEntry.getLastSentXRot(),
-            entityTrackerEntry.getLastSentYRot(),
-            this.getType(),
-            i,
-            entityTrackerEntry.getLastSentMovement(),
-            0.0
-        );
+        Vec3 vec3d = entityTrackerEntry.getPositionBase();
+
+        return new ClientboundAddEntityPacket(this.getId(), this.getUUID(), vec3d.x(), vec3d.y(), vec3d.z(), entityTrackerEntry.getLastSentXRot(), entityTrackerEntry.getLastSentYRot(), this.getType(), i, entityTrackerEntry.getLastSentMovement(), 0.0D);
     }
 
     @Override
     public void recreateFromPacket(ClientboundAddEntityPacket packet) {
         super.recreateFromPacket(packet);
-        Vec3 vec3 = new Vec3(packet.getXa(), packet.getYa(), packet.getZa());
-        this.setDeltaMovement(vec3);
+        Vec3 vec3d = new Vec3(packet.getXa(), packet.getYa(), packet.getZa());
+
+        this.setDeltaMovement(vec3d);
     }
 
     public void assignDirectionalMovement(Vec3 velocity, double accelerationPower) {
@@ -190,9 +201,10 @@
     protected void onDeflection(@Nullable Entity deflector, boolean fromAttack) {
         super.onDeflection(deflector, fromAttack);
         if (fromAttack) {
-            this.accelerationPower = 0.1;
+            this.accelerationPower = 0.1D;
         } else {
-            this.accelerationPower *= 0.5;
+            this.accelerationPower *= 0.5D;
         }
+
     }
 }
