--- a/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
+++ b/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
@@ -2,7 +2,9 @@
 
 import java.util.EnumSet;
 import net.minecraft.core.BlockPos;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.Mob;
 import net.minecraft.world.entity.TamableAnimal;
 import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
 import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
@@ -12,8 +14,14 @@
 import net.minecraft.world.level.block.state.BlockState;
 import net.minecraft.world.level.pathfinder.PathType;
 import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
+// CraftBukkit start
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityTeleportEvent;
+// CraftBukkit end
 
 public class FollowOwnerGoal extends Goal {
+
     public static final int TELEPORT_WHEN_DISTANCE_IS = 12;
     private static final int MIN_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 2;
     private static final int MAX_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 3;
@@ -45,26 +53,25 @@
 
     @Override
     public boolean canUse() {
-        LivingEntity livingEntity = this.tamable.getOwner();
-        if (livingEntity == null) {
+        LivingEntity entityliving = this.tamable.getOwner();
+
+        if (entityliving == null) {
             return false;
-        } else if (livingEntity.isSpectator()) {
+        } else if (entityliving.isSpectator()) {
             return false;
         } else if (this.unableToMove()) {
             return false;
-        } else if (this.tamable.distanceToSqr(livingEntity) < (double)(this.startDistance * this.startDistance)) {
+        } else if (this.tamable.distanceToSqr((Entity) entityliving) < (double) (this.startDistance * this.startDistance)) {
             return false;
         } else {
-            this.owner = livingEntity;
+            this.owner = entityliving;
             return true;
         }
     }
 
     @Override
     public boolean canContinueToUse() {
-        return !this.navigation.isDone()
-            && !this.unableToMove()
-            && !(this.tamable.distanceToSqr(this.owner) <= (double)(this.stopDistance * this.stopDistance));
+        return this.navigation.isDone() ? false : (this.unableToMove() ? false : this.tamable.distanceToSqr((Entity) this.owner) > (double) (this.stopDistance * this.stopDistance));
     }
 
     private boolean unableToMove() {
@@ -87,54 +94,67 @@
 
     @Override
     public void tick() {
-        this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamable.getMaxHeadXRot());
+        if (this.tamable.distanceToSqr(this.owner) <= 16 * 16) this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float) this.tamable.getMaxHeadXRot()); // Paper - Limit pet look distance
         if (--this.timeToRecalcPath <= 0) {
             this.timeToRecalcPath = this.adjustedTickDelay(10);
-            if (this.tamable.distanceToSqr(this.owner) >= 144.0) {
+            if (this.tamable.distanceToSqr((Entity) this.owner) >= 144.0D) {
                 this.teleportToOwner();
             } else {
-                this.navigation.moveTo(this.owner, this.speedModifier);
+                this.navigation.moveTo((Entity) this.owner, this.speedModifier);
             }
+
         }
     }
 
     private void teleportToOwner() {
-        BlockPos blockPos = this.owner.blockPosition();
+        BlockPos blockposition = this.owner.blockPosition();
 
-        for (int i = 0; i < 10; i++) {
+        for (int i = 0; i < 10; ++i) {
             int j = this.randomIntInclusive(-3, 3);
             int k = this.randomIntInclusive(-1, 1);
             int l = this.randomIntInclusive(-3, 3);
-            boolean bl = this.maybeTeleportTo(blockPos.getX() + j, blockPos.getY() + k, blockPos.getZ() + l);
-            if (bl) {
+            boolean flag = this.maybeTeleportTo(blockposition.getX() + j, blockposition.getY() + k, blockposition.getZ() + l);
+
+            if (flag) {
                 return;
             }
         }
+
     }
 
     private boolean maybeTeleportTo(int x, int y, int z) {
-        if (Math.abs((double)x - this.owner.getX()) < 2.0 && Math.abs((double)z - this.owner.getZ()) < 2.0) {
+        if (Math.abs((double) x - this.owner.getX()) < 2.0D && Math.abs((double) z - this.owner.getZ()) < 2.0D) {
             return false;
         } else if (!this.canTeleportTo(new BlockPos(x, y, z))) {
             return false;
         } else {
-            this.tamable.moveTo((double)x + 0.5, (double)y, (double)z + 0.5, this.tamable.getYRot(), this.tamable.getXRot());
+            // CraftBukkit start
+            EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) x + 0.5D, (double) y, (double) z + 0.5D);
+            if (event.isCancelled() || event.getTo() == null) { // Paper
+                return false;
+            }
+            Location to = event.getTo();
+            this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
+            // CraftBukkit end
             this.navigation.stop();
             return true;
         }
     }
 
     private boolean canTeleportTo(BlockPos pos) {
-        PathType pathType = WalkNodeEvaluator.getPathTypeStatic(this.tamable, pos);
-        if (pathType != PathType.WALKABLE) {
+        PathType pathtype = WalkNodeEvaluator.getPathTypeStatic((Mob) this.tamable, pos);
+
+        if (pathtype != PathType.WALKABLE) {
             return false;
         } else {
-            BlockState blockState = this.level.getBlockState(pos.below());
-            if (!this.canFly && blockState.getBlock() instanceof LeavesBlock) {
+            BlockState iblockdata = this.level.getBlockState(pos.below());
+
+            if (!this.canFly && iblockdata.getBlock() instanceof LeavesBlock) {
                 return false;
             } else {
-                BlockPos blockPos = pos.subtract(this.tamable.blockPosition());
-                return this.level.noCollision(this.tamable, this.tamable.getBoundingBox().move(blockPos));
+                BlockPos blockposition1 = pos.subtract(this.tamable.blockPosition());
+
+                return this.level.noCollision(this.tamable, this.tamable.getBoundingBox().move(blockposition1));
             }
         }
     }
