--- a/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
+++ b/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
@@ -2,6 +2,7 @@
 
 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.TamableAnimal;
 import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
@@ -12,8 +13,14 @@
 import net.minecraft.world.level.block.state.BlockState;
 import net.minecraft.world.level.pathfinder.BlockPathTypes;
 import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
+// CraftBukkit start
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_20_R2.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,34 +52,29 @@
 
     @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() {
-        if (this.navigation.isDone()) {
-            return false;
-        } else if (this.unableToMove()) {
-            return false;
-        } else {
-            return !(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() {
-        return this.tamable.isOrderedToSit() || this.tamable.isPassenger() || this.tamable.isLeashed();
+        return this.tamable.isOrderedToSit() || this.tamable.isPassenger() || this.tamable.isLeashed() || this.tamable.leashInfoTag != null; // Paper - Fix MC-173303
     }
 
     @Override
@@ -91,27 +93,28 @@
 
     @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
         if (--this.timeToRecalcPath <= 0) {
             this.timeToRecalcPath = this.adjustedTickDelay(10);
-            if (this.tamable.distanceToSqr(this.owner) >= 144.0D) {
+            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;
             }
         }
@@ -119,28 +122,38 @@
     }
 
     private boolean maybeTeleportTo(int x, int y, int z) {
-        if (Math.abs((double)x - this.owner.getX()) < 2.0D && Math.abs((double)z - this.owner.getZ()) < 2.0D) {
+        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.5D, (double)y, (double)z + 0.5D, 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()) {
+                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) {
-        BlockPathTypes blockPathTypes = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, pos.mutable());
-        if (blockPathTypes != BlockPathTypes.WALKABLE) {
+        BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, pos.mutable());
+
+        if (pathtype != BlockPathTypes.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));
             }
         }
     }
