--- a/net/minecraft/world/entity/projectile/ShulkerBullet.java
+++ b/net/minecraft/world/entity/projectile/ShulkerBullet.java
@@ -29,6 +29,7 @@
 import net.minecraft.world.phys.Vec3;
 
 public class ShulkerBullet extends Projectile {
+
     private static final double SPEED = 0.15D;
     @Nullable
     private Entity finalTarget;
@@ -49,15 +50,29 @@
     public ShulkerBullet(Level world, LivingEntity owner, Entity target, Direction.Axis axis) {
         this(EntityType.SHULKER_BULLET, world);
         this.setOwner(owner);
-        BlockPos blockPos = owner.blockPosition();
-        double d = (double)blockPos.getX() + 0.5D;
-        double e = (double)blockPos.getY() + 0.5D;
-        double f = (double)blockPos.getZ() + 0.5D;
-        this.moveTo(d, e, f, this.getYRot(), this.getXRot());
+        BlockPos blockposition = owner.blockPosition();
+        double d0 = (double) blockposition.getX() + 0.5D;
+        double d1 = (double) blockposition.getY() + 0.5D;
+        double d2 = (double) blockposition.getZ() + 0.5D;
+
+        this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot());
         this.finalTarget = target;
         this.currentMoveDirection = Direction.UP;
         this.selectNextMoveDirection(axis);
+        projectileSource = (org.bukkit.entity.LivingEntity) owner.getBukkitEntity(); // CraftBukkit
+    }
+
+    // CraftBukkit start
+    public Entity getTarget() {
+        return this.finalTarget;
+    }
+
+    public void setTarget(Entity e) {
+        this.finalTarget = e;
+        this.currentMoveDirection = Direction.UP;
+        this.selectNextMoveDirection(Direction.Axis.X);
     }
+    // CraftBukkit end
 
     @Override
     public SoundSource getSoundSource() {
@@ -99,8 +114,7 @@
     }
 
     @Override
-    protected void defineSynchedData() {
-    }
+    protected void defineSynchedData() {}
 
     @Nullable
     private Direction getMoveDirection() {
@@ -112,73 +126,77 @@
     }
 
     private void selectNextMoveDirection(@Nullable Direction.Axis axis) {
-        double d = 0.5D;
-        BlockPos blockPos;
+        double d0 = 0.5D;
+        BlockPos blockposition;
+
         if (this.finalTarget == null) {
-            blockPos = this.blockPosition().below();
+            blockposition = this.blockPosition().below();
         } else {
-            d = (double)this.finalTarget.getBbHeight() * 0.5D;
-            blockPos = new BlockPos(this.finalTarget.getX(), this.finalTarget.getY() + d, this.finalTarget.getZ());
+            d0 = (double) this.finalTarget.getBbHeight() * 0.5D;
+            blockposition = new BlockPos(this.finalTarget.getX(), this.finalTarget.getY() + d0, this.finalTarget.getZ());
         }
 
-        double e = (double)blockPos.getX() + 0.5D;
-        double f = (double)blockPos.getY() + d;
-        double g = (double)blockPos.getZ() + 0.5D;
-        Direction direction = null;
-        if (!blockPos.closerToCenterThan(this.position(), 2.0D)) {
-            BlockPos blockPos3 = this.blockPosition();
+        double d1 = (double) blockposition.getX() + 0.5D;
+        double d2 = (double) blockposition.getY() + d0;
+        double d3 = (double) blockposition.getZ() + 0.5D;
+        Direction enumdirection = null;
+
+        if (!blockposition.closerToCenterThan(this.position(), 2.0D)) {
+            BlockPos blockposition1 = this.blockPosition();
             List<Direction> list = Lists.newArrayList();
+
             if (axis != Direction.Axis.X) {
-                if (blockPos3.getX() < blockPos.getX() && this.level.isEmptyBlock(blockPos3.east())) {
+                if (blockposition1.getX() < blockposition.getX() && this.level.isEmptyBlock(blockposition1.east())) {
                     list.add(Direction.EAST);
-                } else if (blockPos3.getX() > blockPos.getX() && this.level.isEmptyBlock(blockPos3.west())) {
+                } else if (blockposition1.getX() > blockposition.getX() && this.level.isEmptyBlock(blockposition1.west())) {
                     list.add(Direction.WEST);
                 }
             }
 
             if (axis != Direction.Axis.Y) {
-                if (blockPos3.getY() < blockPos.getY() && this.level.isEmptyBlock(blockPos3.above())) {
+                if (blockposition1.getY() < blockposition.getY() && this.level.isEmptyBlock(blockposition1.above())) {
                     list.add(Direction.UP);
-                } else if (blockPos3.getY() > blockPos.getY() && this.level.isEmptyBlock(blockPos3.below())) {
+                } else if (blockposition1.getY() > blockposition.getY() && this.level.isEmptyBlock(blockposition1.below())) {
                     list.add(Direction.DOWN);
                 }
             }
 
             if (axis != Direction.Axis.Z) {
-                if (blockPos3.getZ() < blockPos.getZ() && this.level.isEmptyBlock(blockPos3.south())) {
+                if (blockposition1.getZ() < blockposition.getZ() && this.level.isEmptyBlock(blockposition1.south())) {
                     list.add(Direction.SOUTH);
-                } else if (blockPos3.getZ() > blockPos.getZ() && this.level.isEmptyBlock(blockPos3.north())) {
+                } else if (blockposition1.getZ() > blockposition.getZ() && this.level.isEmptyBlock(blockposition1.north())) {
                     list.add(Direction.NORTH);
                 }
             }
 
-            direction = Direction.getRandom(this.random);
+            enumdirection = Direction.getRandom(this.random);
             if (list.isEmpty()) {
-                for(int i = 5; !this.level.isEmptyBlock(blockPos3.relative(direction)) && i > 0; --i) {
-                    direction = Direction.getRandom(this.random);
+                for (int i = 5; !this.level.isEmptyBlock(blockposition1.relative(enumdirection)) && i > 0; --i) {
+                    enumdirection = Direction.getRandom(this.random);
                 }
             } else {
-                direction = list.get(this.random.nextInt(list.size()));
+                enumdirection = (Direction) list.get(this.random.nextInt(list.size()));
             }
 
-            e = this.getX() + (double)direction.getStepX();
-            f = this.getY() + (double)direction.getStepY();
-            g = this.getZ() + (double)direction.getStepZ();
+            d1 = this.getX() + (double) enumdirection.getStepX();
+            d2 = this.getY() + (double) enumdirection.getStepY();
+            d3 = this.getZ() + (double) enumdirection.getStepZ();
         }
 
-        this.setMoveDirection(direction);
-        double h = e - this.getX();
-        double j = f - this.getY();
-        double k = g - this.getZ();
-        double l = Math.sqrt(h * h + j * j + k * k);
-        if (l == 0.0D) {
+        this.setMoveDirection(enumdirection);
+        double d4 = d1 - this.getX();
+        double d5 = d2 - this.getY();
+        double d6 = d3 - this.getZ();
+        double d7 = Math.sqrt(d4 * d4 + d5 * d5 + d6 * d6);
+
+        if (d7 == 0.0D) {
             this.targetDeltaX = 0.0D;
             this.targetDeltaY = 0.0D;
             this.targetDeltaZ = 0.0D;
         } else {
-            this.targetDeltaX = h / l * 0.15D;
-            this.targetDeltaY = j / l * 0.15D;
-            this.targetDeltaZ = k / l * 0.15D;
+            this.targetDeltaX = d4 / d7 * 0.15D;
+            this.targetDeltaY = d5 / d7 * 0.15D;
+            this.targetDeltaZ = d6 / d7 * 0.15D;
         }
 
         this.hasImpulse = true;
@@ -196,38 +214,39 @@
     @Override
     public void tick() {
         super.tick();
+        Vec3 vec3d;
+
         if (!this.level.isClientSide) {
             if (this.finalTarget == null && this.targetId != null) {
-                this.finalTarget = ((ServerLevel)this.level).getEntity(this.targetId);
+                this.finalTarget = ((ServerLevel) this.level).getEntity(this.targetId);
                 if (this.finalTarget == null) {
                     this.targetId = null;
                 }
             }
 
-            if (this.finalTarget == null || !this.finalTarget.isAlive() || this.finalTarget instanceof Player && this.finalTarget.isSpectator()) {
-                if (!this.isNoGravity()) {
-                    this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D));
-                }
-            } else {
+            if (this.finalTarget != null && this.finalTarget.isAlive() && (!(this.finalTarget instanceof Player) || !this.finalTarget.isSpectator())) {
                 this.targetDeltaX = Mth.clamp(this.targetDeltaX * 1.025D, -1.0D, 1.0D);
                 this.targetDeltaY = Mth.clamp(this.targetDeltaY * 1.025D, -1.0D, 1.0D);
                 this.targetDeltaZ = Mth.clamp(this.targetDeltaZ * 1.025D, -1.0D, 1.0D);
-                Vec3 vec3 = this.getDeltaMovement();
-                this.setDeltaMovement(vec3.add((this.targetDeltaX - vec3.x) * 0.2D, (this.targetDeltaY - vec3.y) * 0.2D, (this.targetDeltaZ - vec3.z) * 0.2D));
+                vec3d = this.getDeltaMovement();
+                this.setDeltaMovement(vec3d.add((this.targetDeltaX - vec3d.x) * 0.2D, (this.targetDeltaY - vec3d.y) * 0.2D, (this.targetDeltaZ - vec3d.z) * 0.2D));
+            } else if (!this.isNoGravity()) {
+                this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D));
             }
 
-            HitResult hitResult = ProjectileUtil.getHitResult(this, this::canHitEntity);
-            if (hitResult.getType() != HitResult.Type.MISS) {
-                this.onHit(hitResult);
+            HitResult movingobjectposition = ProjectileUtil.getHitResult(this, this::canHitEntity);
+
+            if (movingobjectposition.getType() != HitResult.Type.MISS) {
+                this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event
             }
         }
 
         this.checkInsideBlocks();
-        Vec3 vec32 = this.getDeltaMovement();
-        this.setPos(this.getX() + vec32.x, this.getY() + vec32.y, this.getZ() + vec32.z);
+        vec3d = this.getDeltaMovement();
+        this.setPos(this.getX() + vec3d.x, this.getY() + vec3d.y, this.getZ() + vec3d.z);
         ProjectileUtil.rotateTowardsMovement(this, 0.5F);
         if (this.level.isClientSide) {
-            this.level.addParticle(ParticleTypes.END_ROD, this.getX() - vec32.x, this.getY() - vec32.y + 0.15D, this.getZ() - vec32.z, 0.0D, 0.0D, 0.0D);
+            this.level.addParticle(ParticleTypes.END_ROD, this.getX() - vec3d.x, this.getY() - vec3d.y + 0.15D, this.getZ() - vec3d.z, 0.0D, 0.0D, 0.0D);
         } else if (this.finalTarget != null && !this.finalTarget.isRemoved()) {
             if (this.flightSteps > 0) {
                 --this.flightSteps;
@@ -237,14 +256,16 @@
             }
 
             if (this.currentMoveDirection != null) {
-                BlockPos blockPos = this.blockPosition();
-                Direction.Axis axis = this.currentMoveDirection.getAxis();
-                if (this.level.loadedAndEntityCanStandOn(blockPos.relative(this.currentMoveDirection), this)) {
-                    this.selectNextMoveDirection(axis);
+                BlockPos blockposition = this.blockPosition();
+                Direction.Axis enumdirection_enumaxis = this.currentMoveDirection.getAxis();
+
+                if (this.level.loadedAndEntityCanStandOn(blockposition.relative(this.currentMoveDirection), this)) {
+                    this.selectNextMoveDirection(enumdirection_enumaxis);
                 } else {
-                    BlockPos blockPos2 = this.finalTarget.blockPosition();
-                    if (axis == Direction.Axis.X && blockPos.getX() == blockPos2.getX() || axis == Direction.Axis.Z && blockPos.getZ() == blockPos2.getZ() || axis == Direction.Axis.Y && blockPos.getY() == blockPos2.getY()) {
-                        this.selectNextMoveDirection(axis);
+                    BlockPos blockposition1 = this.finalTarget.blockPosition();
+
+                    if (enumdirection_enumaxis == Direction.Axis.X && blockposition.getX() == blockposition1.getX() || enumdirection_enumaxis == Direction.Axis.Z && blockposition.getZ() == blockposition1.getZ() || enumdirection_enumaxis == Direction.Axis.Y && blockposition.getY() == blockposition1.getY()) {
+                        this.selectNextMoveDirection(enumdirection_enumaxis);
                     }
                 }
             }
@@ -276,13 +297,14 @@
     protected void onHitEntity(EntityHitResult entityHitResult) {
         super.onHitEntity(entityHitResult);
         Entity entity = entityHitResult.getEntity();
-        Entity entity2 = this.getOwner();
-        LivingEntity livingEntity = entity2 instanceof LivingEntity ? (LivingEntity)entity2 : null;
-        boolean bl = entity.hurt(DamageSource.indirectMobAttack(this, livingEntity).setProjectile(), 4.0F);
-        if (bl) {
-            this.doEnchantDamageEffects(livingEntity, entity);
+        Entity entity1 = this.getOwner();
+        LivingEntity entityliving = entity1 instanceof LivingEntity ? (LivingEntity) entity1 : null;
+        boolean flag = entity.hurt(DamageSource.indirectMobAttack(this, entityliving).setProjectile(), 4.0F);
+
+        if (flag) {
+            this.doEnchantDamageEffects(entityliving, entity);
             if (entity instanceof LivingEntity) {
-                ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), MoreObjects.firstNonNull(entity2, this));
+                ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
             }
         }
 
@@ -291,7 +313,7 @@
     @Override
     protected void onHitBlock(BlockHitResult blockHitResult) {
         super.onHitBlock(blockHitResult);
-        ((ServerLevel)this.level).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(), this.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D);
+        ((ServerLevel) this.level).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(), this.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D);
         this.playSound(SoundEvents.SHULKER_BULLET_HIT, 1.0F, 1.0F);
     }
 
@@ -308,9 +330,14 @@
 
     @Override
     public boolean hurt(DamageSource source, float amount) {
+        // CraftBukkit start
+        if (org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) {
+            return false;
+        }
+        // CraftBukkit end
         if (!this.level.isClientSide) {
             this.playSound(SoundEvents.SHULKER_BULLET_HURT, 1.0F, 1.0F);
-            ((ServerLevel)this.level).sendParticles(ParticleTypes.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2D, 0.2D, 0.2D, 0.0D);
+            ((ServerLevel) this.level).sendParticles(ParticleTypes.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2D, 0.2D, 0.2D, 0.0D);
             this.discard();
         }
 
@@ -320,9 +347,10 @@
     @Override
     public void recreateFromPacket(ClientboundAddEntityPacket packet) {
         super.recreateFromPacket(packet);
-        double d = packet.getXa();
-        double e = packet.getYa();
-        double f = packet.getZa();
-        this.setDeltaMovement(d, e, f);
+        double d0 = packet.getXa();
+        double d1 = packet.getYa();
+        double d2 = packet.getZa();
+
+        this.setDeltaMovement(d0, d1, d2);
     }
 }
