--- a/net/minecraft/world/entity/projectile/EyeOfEnder.java
+++ b/net/minecraft/world/entity/projectile/EyeOfEnder.java
@@ -17,6 +17,7 @@
 import net.minecraft.world.phys.Vec3;
 
 public class EyeOfEnder extends Entity implements ItemSupplier {
+
     private static final EntityDataAccessor<ItemStack> DATA_ITEM_STACK = SynchedEntityData.defineId(EyeOfEnder.class, EntityDataSerializers.ITEM_STACK);
     public double tx;
     public double ty;
@@ -34,66 +35,77 @@
     }
 
     public void setItem(ItemStack stack) {
-        if (!stack.is(Items.ENDER_EYE) || stack.hasTag()) {
-            this.getEntityData().set(DATA_ITEM_STACK, stack.copyWithCount(1));
+        if (true || !stack.is(Items.ENDER_EYE) || stack.hasTag()) { // CraftBukkit - always allow item changing
+            this.getEntityData().set(EyeOfEnder.DATA_ITEM_STACK, stack.copyWithCount(1));
         }
 
     }
 
     private ItemStack getItemRaw() {
-        return this.getEntityData().get(DATA_ITEM_STACK);
+        return (ItemStack) this.getEntityData().get(EyeOfEnder.DATA_ITEM_STACK);
     }
 
     @Override
     public ItemStack getItem() {
-        ItemStack itemStack = this.getItemRaw();
-        return itemStack.isEmpty() ? new ItemStack(Items.ENDER_EYE) : itemStack;
+        ItemStack itemstack = this.getItemRaw();
+
+        return itemstack.isEmpty() ? new ItemStack(Items.ENDER_EYE) : itemstack;
     }
 
     @Override
     protected void defineSynchedData() {
-        this.getEntityData().define(DATA_ITEM_STACK, ItemStack.EMPTY);
+        this.getEntityData().define(EyeOfEnder.DATA_ITEM_STACK, ItemStack.EMPTY);
     }
 
     @Override
     public boolean shouldRenderAtSqrDistance(double distance) {
-        double d = this.getBoundingBox().getSize() * 4.0D;
-        if (Double.isNaN(d)) {
-            d = 4.0D;
+        double d1 = this.getBoundingBox().getSize() * 4.0D;
+
+        if (Double.isNaN(d1)) {
+            d1 = 4.0D;
         }
 
-        d *= 64.0D;
-        return distance < d * d;
+        d1 *= 64.0D;
+        return distance < d1 * d1;
     }
 
     public void signalTo(BlockPos pos) {
-        double d = (double)pos.getX();
+        // Paper start
+        this.signalTo(pos, true);
+    }
+    public void signalTo(BlockPos pos, boolean update) {
+        // Paper end
+        double d0 = (double) pos.getX();
         int i = pos.getY();
-        double e = (double)pos.getZ();
-        double f = d - this.getX();
-        double g = e - this.getZ();
-        double h = Math.sqrt(f * f + g * g);
-        if (h > 12.0D) {
-            this.tx = this.getX() + f / h * 12.0D;
-            this.tz = this.getZ() + g / h * 12.0D;
+        double d1 = (double) pos.getZ();
+        double d2 = d0 - this.getX();
+        double d3 = d1 - this.getZ();
+        double d4 = Math.sqrt(d2 * d2 + d3 * d3);
+
+        if (d4 > 12.0D) {
+            this.tx = this.getX() + d2 / d4 * 12.0D;
+            this.tz = this.getZ() + d3 / d4 * 12.0D;
             this.ty = this.getY() + 8.0D;
         } else {
-            this.tx = d;
-            this.ty = (double)i;
-            this.tz = e;
+            this.tx = d0;
+            this.ty = (double) i;
+            this.tz = d1;
         }
 
+        if (update) { // Paper
         this.life = 0;
         this.surviveAfterDeath = this.random.nextInt(5) > 0;
+        } // Paper
     }
 
     @Override
     public void lerpMotion(double x, double y, double z) {
         this.setDeltaMovement(x, y, z);
         if (this.xRotO == 0.0F && this.yRotO == 0.0F) {
-            double d = Math.sqrt(x * x + z * z);
-            this.setYRot((float)(Mth.atan2(x, z) * (double)(180F / (float)Math.PI)));
-            this.setXRot((float)(Mth.atan2(y, d) * (double)(180F / (float)Math.PI)));
+            double d3 = Math.sqrt(x * x + z * z);
+
+            this.setYRot((float) (Mth.atan2(x, z) * 57.2957763671875D));
+            this.setXRot((float) (Mth.atan2(y, d3) * 57.2957763671875D));
             this.yRotO = this.getYRot();
             this.xRotO = this.getXRot();
         }
@@ -103,41 +115,45 @@
     @Override
     public void tick() {
         super.tick();
-        Vec3 vec3 = this.getDeltaMovement();
-        double d = this.getX() + vec3.x;
-        double e = this.getY() + vec3.y;
-        double f = this.getZ() + vec3.z;
-        double g = vec3.horizontalDistance();
-        this.setXRot(Projectile.lerpRotation(this.xRotO, (float)(Mth.atan2(vec3.y, g) * (double)(180F / (float)Math.PI))));
-        this.setYRot(Projectile.lerpRotation(this.yRotO, (float)(Mth.atan2(vec3.x, vec3.z) * (double)(180F / (float)Math.PI))));
+        Vec3 vec3d = this.getDeltaMovement();
+        double d0 = this.getX() + vec3d.x;
+        double d1 = this.getY() + vec3d.y;
+        double d2 = this.getZ() + vec3d.z;
+        double d3 = vec3d.horizontalDistance();
+
+        this.setXRot(Projectile.lerpRotation(this.xRotO, (float) (Mth.atan2(vec3d.y, d3) * 57.2957763671875D)));
+        this.setYRot(Projectile.lerpRotation(this.yRotO, (float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D)));
         if (!this.level().isClientSide) {
-            double h = this.tx - d;
-            double i = this.tz - f;
-            float j = (float)Math.sqrt(h * h + i * i);
-            float k = (float)Mth.atan2(i, h);
-            double l = Mth.lerp(0.0025D, g, (double)j);
-            double m = vec3.y;
-            if (j < 1.0F) {
-                l *= 0.8D;
-                m *= 0.8D;
+            double d4 = this.tx - d0;
+            double d5 = this.tz - d2;
+            float f = (float) Math.sqrt(d4 * d4 + d5 * d5);
+            float f1 = (float) Mth.atan2(d5, d4);
+            double d6 = Mth.lerp(0.0025D, d3, (double) f);
+            double d7 = vec3d.y;
+
+            if (f < 1.0F) {
+                d6 *= 0.8D;
+                d7 *= 0.8D;
             }
 
-            int n = this.getY() < this.ty ? 1 : -1;
-            vec3 = new Vec3(Math.cos((double)k) * l, m + ((double)n - m) * (double)0.015F, Math.sin((double)k) * l);
-            this.setDeltaMovement(vec3);
+            int i = this.getY() < this.ty ? 1 : -1;
+
+            vec3d = new Vec3(Math.cos((double) f1) * d6, d7 + ((double) i - d7) * 0.014999999664723873D, Math.sin((double) f1) * d6);
+            this.setDeltaMovement(vec3d);
         }
 
-        float o = 0.25F;
+        float f2 = 0.25F;
+
         if (this.isInWater()) {
-            for(int p = 0; p < 4; ++p) {
-                this.level().addParticle(ParticleTypes.BUBBLE, d - vec3.x * 0.25D, e - vec3.y * 0.25D, f - vec3.z * 0.25D, vec3.x, vec3.y, vec3.z);
+            for (int j = 0; j < 4; ++j) {
+                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);
             }
         } else {
-            this.level().addParticle(ParticleTypes.PORTAL, d - vec3.x * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, e - vec3.y * 0.25D - 0.5D, f - vec3.z * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, vec3.x, vec3.y, vec3.z);
+            this.level().addParticle(ParticleTypes.PORTAL, d0 - vec3d.x * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, d1 - vec3d.y * 0.25D - 0.5D, d2 - vec3d.z * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, vec3d.x, vec3d.y, vec3d.z);
         }
 
         if (!this.level().isClientSide) {
-            this.setPos(d, e, f);
+            this.setPos(d0, d1, d2);
             ++this.life;
             if (this.life > 80 && !this.level().isClientSide) {
                 this.playSound(SoundEvents.ENDER_EYE_DEATH, 1.0F, 1.0F);
@@ -149,24 +165,26 @@
                 }
             }
         } else {
-            this.setPosRaw(d, e, f);
+            this.setPosRaw(d0, d1, d2);
         }
 
     }
 
     @Override
     public void addAdditionalSaveData(CompoundTag nbt) {
-        ItemStack itemStack = this.getItemRaw();
-        if (!itemStack.isEmpty()) {
-            nbt.put("Item", itemStack.save(new CompoundTag()));
+        ItemStack itemstack = this.getItemRaw();
+
+        if (!itemstack.isEmpty()) {
+            nbt.put("Item", itemstack.save(new CompoundTag()));
         }
 
     }
 
     @Override
     public void readAdditionalSaveData(CompoundTag nbt) {
-        ItemStack itemStack = ItemStack.of(nbt.getCompound("Item"));
-        this.setItem(itemStack);
+        ItemStack itemstack = ItemStack.of(nbt.getCompound("Item"));
+
+        if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-6103 summon, see also SPIGOT-5474
     }
 
     @Override
