--- a/net/minecraft/world/entity/animal/Turtle.java
+++ b/net/minecraft/world/entity/animal/Turtle.java
@@ -4,6 +4,7 @@
 import javax.annotation.Nullable;
 import net.minecraft.advancements.CriteriaTriggers;
 import net.minecraft.core.BlockPos;
+import net.minecraft.core.Holder;
 import net.minecraft.nbt.CompoundTag;
 import net.minecraft.network.syncher.EntityDataAccessor;
 import net.minecraft.network.syncher.EntityDataSerializers;
@@ -63,6 +64,7 @@
 import net.minecraft.world.phys.Vec3;
 
 public class Turtle extends Animal {
+
     private static final EntityDataAccessor<BlockPos> HOME_POS = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BLOCK_POS);
     private static final EntityDataAccessor<Boolean> HAS_EGG = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN);
     private static final EntityDataAccessor<Boolean> LAYING_EGG = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN);
@@ -70,12 +72,11 @@
     private static final EntityDataAccessor<Boolean> GOING_HOME = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN);
     private static final EntityDataAccessor<Boolean> TRAVELLING = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN);
     private static final float BABY_SCALE = 0.3F;
-    private static final EntityDimensions BABY_DIMENSIONS = EntityType.TURTLE
-        .getDimensions()
-        .withAttachments(EntityAttachments.builder().attach(EntityAttachment.PASSENGER, 0.0F, EntityType.TURTLE.getHeight(), -0.25F))
-        .scale(0.3F);
+    private static final EntityDimensions BABY_DIMENSIONS = EntityType.TURTLE.getDimensions().withAttachments(EntityAttachments.builder().attach(EntityAttachment.PASSENGER, 0.0F, EntityType.TURTLE.getHeight(), -0.25F)).scale(0.3F);
     int layEggCounter;
-    public static final Predicate<LivingEntity> BABY_ON_LAND_SELECTOR = entity -> entity.isBaby() && !entity.isInWater();
+    public static final Predicate<LivingEntity> BABY_ON_LAND_SELECTOR = (entityliving) -> {
+        return entityliving.isBaby() && !entityliving.isInWater();
+    };
 
     public Turtle(EntityType<? extends Turtle> type, Level world) {
         super(type, world);
@@ -87,63 +88,63 @@
     }
 
     public void setHomePos(BlockPos pos) {
-        this.entityData.set(HOME_POS, pos);
+        this.entityData.set(Turtle.HOME_POS, pos);
     }
 
     public BlockPos getHomePos() {
-        return this.entityData.get(HOME_POS);
+        return (BlockPos) this.entityData.get(Turtle.HOME_POS);
     }
 
     void setTravelPos(BlockPos pos) {
-        this.entityData.set(TRAVEL_POS, pos);
+        this.entityData.set(Turtle.TRAVEL_POS, pos);
     }
 
     BlockPos getTravelPos() {
-        return this.entityData.get(TRAVEL_POS);
+        return (BlockPos) this.entityData.get(Turtle.TRAVEL_POS);
     }
 
     public boolean hasEgg() {
-        return this.entityData.get(HAS_EGG);
+        return (Boolean) this.entityData.get(Turtle.HAS_EGG);
     }
 
     public void setHasEgg(boolean hasEgg) {
-        this.entityData.set(HAS_EGG, hasEgg);
+        this.entityData.set(Turtle.HAS_EGG, hasEgg);
     }
 
     public boolean isLayingEgg() {
-        return this.entityData.get(LAYING_EGG);
+        return (Boolean) this.entityData.get(Turtle.LAYING_EGG);
     }
 
     void setLayingEgg(boolean diggingSand) {
         this.layEggCounter = diggingSand ? 1 : 0;
-        this.entityData.set(LAYING_EGG, diggingSand);
+        this.entityData.set(Turtle.LAYING_EGG, diggingSand);
     }
 
     public boolean isGoingHome() {
-        return this.entityData.get(GOING_HOME);
+        return (Boolean) this.entityData.get(Turtle.GOING_HOME);
     }
 
     public void setGoingHome(boolean landBound) {
-        this.entityData.set(GOING_HOME, landBound);
+        this.entityData.set(Turtle.GOING_HOME, landBound);
     }
 
     public boolean isTravelling() {
-        return this.entityData.get(TRAVELLING);
+        return (Boolean) this.entityData.get(Turtle.TRAVELLING);
     }
 
     public void setTravelling(boolean traveling) {
-        this.entityData.set(TRAVELLING, traveling);
+        this.entityData.set(Turtle.TRAVELLING, traveling);
     }
 
     @Override
     protected void defineSynchedData(SynchedEntityData.Builder builder) {
         super.defineSynchedData(builder);
-        builder.define(HOME_POS, BlockPos.ZERO);
-        builder.define(HAS_EGG, false);
-        builder.define(TRAVEL_POS, BlockPos.ZERO);
-        builder.define(GOING_HOME, false);
-        builder.define(TRAVELLING, false);
-        builder.define(LAYING_EGG, false);
+        builder.define(Turtle.HOME_POS, BlockPos.ZERO);
+        builder.define(Turtle.HAS_EGG, false);
+        builder.define(Turtle.TRAVEL_POS, BlockPos.ZERO);
+        builder.define(Turtle.GOING_HOME, false);
+        builder.define(Turtle.TRAVELLING, false);
+        builder.define(Turtle.LAYING_EGG, false);
     }
 
     @Override
@@ -163,13 +164,15 @@
         int i = nbt.getInt("HomePosX");
         int j = nbt.getInt("HomePosY");
         int k = nbt.getInt("HomePosZ");
+
         this.setHomePos(new BlockPos(i, j, k));
         super.readAdditionalSaveData(nbt);
         this.setHasEgg(nbt.getBoolean("HasEgg"));
         int l = nbt.getInt("TravelPosX");
-        int m = nbt.getInt("TravelPosY");
-        int n = nbt.getInt("TravelPosZ");
-        this.setTravelPos(new BlockPos(l, m, n));
+        int i1 = nbt.getInt("TravelPosY");
+        int j1 = nbt.getInt("TravelPosZ");
+
+        this.setTravelPos(new BlockPos(l, i1, j1));
     }
 
     @Nullable
@@ -186,19 +189,21 @@
 
     @Override
     protected void registerGoals() {
-        this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2));
-        this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0));
-        this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0));
-        this.goalSelector.addGoal(2, new TemptGoal(this, 1.1, stack -> stack.is(ItemTags.TURTLE_FOOD), false));
-        this.goalSelector.addGoal(3, new Turtle.TurtleGoToWaterGoal(this, 1.0));
-        this.goalSelector.addGoal(4, new Turtle.TurtleGoHomeGoal(this, 1.0));
-        this.goalSelector.addGoal(7, new Turtle.TurtleTravelGoal(this, 1.0));
+        this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2D));
+        this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0D));
+        this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0D));
+        this.goalSelector.addGoal(2, new TemptGoal(this, 1.1D, (itemstack) -> {
+            return itemstack.is(ItemTags.TURTLE_FOOD);
+        }, false));
+        this.goalSelector.addGoal(3, new Turtle.TurtleGoToWaterGoal(this, 1.0D));
+        this.goalSelector.addGoal(4, new Turtle.TurtleGoHomeGoal(this, 1.0D));
+        this.goalSelector.addGoal(7, new Turtle.TurtleTravelGoal(this, 1.0D));
         this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
-        this.goalSelector.addGoal(9, new Turtle.TurtleRandomStrollGoal(this, 1.0, 100));
+        this.goalSelector.addGoal(9, new Turtle.TurtleRandomStrollGoal(this, 1.0D, 100));
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0).add(Attributes.MOVEMENT_SPEED, 0.25).add(Attributes.STEP_HEIGHT, 1.0);
+        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0D).add(Attributes.MOVEMENT_SPEED, 0.25D).add(Attributes.STEP_HEIGHT, 1.0D);
     }
 
     @Override
@@ -241,8 +246,9 @@
 
     @Override
     protected void playStepSound(BlockPos pos, BlockState state) {
-        SoundEvent soundEvent = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE;
-        this.playSound(soundEvent, 0.15F, 1.0F);
+        SoundEvent soundeffect = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE;
+
+        this.playSound(soundeffect, 0.15F, 1.0F);
     }
 
     @Override
@@ -268,7 +274,7 @@
     @Nullable
     @Override
     public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) {
-        return EntityType.TURTLE.create(world);
+        return (AgeableMob) EntityType.TURTLE.create(world);
     }
 
     @Override
@@ -278,31 +284,32 @@
 
     @Override
     public float getWalkTargetValue(BlockPos pos, LevelReader world) {
-        if (!this.isGoingHome() && world.getFluidState(pos).is(FluidTags.WATER)) {
-            return 10.0F;
-        } else {
-            return TurtleEggBlock.onSand(world, pos) ? 10.0F : world.getPathfindingCostFromLightLevels(pos);
-        }
+        return !this.isGoingHome() && world.getFluidState(pos).is(FluidTags.WATER) ? 10.0F : (TurtleEggBlock.onSand(world, pos) ? 10.0F : world.getPathfindingCostFromLightLevels(pos));
     }
 
     @Override
     public void aiStep() {
         super.aiStep();
         if (this.isAlive() && this.isLayingEgg() && this.layEggCounter >= 1 && this.layEggCounter % 5 == 0) {
-            BlockPos blockPos = this.blockPosition();
-            if (TurtleEggBlock.onSand(this.level(), blockPos)) {
-                this.level().levelEvent(2001, blockPos, Block.getId(this.level().getBlockState(blockPos.below())));
+            BlockPos blockposition = this.blockPosition();
+
+            if (TurtleEggBlock.onSand(this.level(), blockposition)) {
+                this.level().levelEvent(2001, blockposition, Block.getId(this.level().getBlockState(blockposition.below())));
                 this.gameEvent(GameEvent.ENTITY_ACTION);
             }
         }
+
     }
 
     @Override
     protected void ageBoundaryReached() {
         super.ageBoundaryReached();
         if (!this.isBaby() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
+            this.forceDrops = true; // CraftBukkit
             this.spawnAtLocation(Items.TURTLE_SCUTE, 1);
+            this.forceDrops = false; // CraftBukkit
         }
+
     }
 
     @Override
@@ -310,13 +317,14 @@
         if (this.isControlledByLocalInstance() && this.isInWater()) {
             this.moveRelative(0.1F, movementInput);
             this.move(MoverType.SELF, this.getDeltaMovement());
-            this.setDeltaMovement(this.getDeltaMovement().scale(0.9));
-            if (this.getTarget() == null && (!this.isGoingHome() || !this.getHomePos().closerToCenterThan(this.position(), 20.0))) {
-                this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.005, 0.0));
+            this.setDeltaMovement(this.getDeltaMovement().scale(0.9D));
+            if (this.getTarget() == null && (!this.isGoingHome() || !this.getHomePos().closerToCenterThan(this.position(), 20.0D))) {
+                this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D));
             }
         } else {
             super.travel(movementInput);
         }
+
     }
 
     @Override
@@ -326,15 +334,94 @@
 
     @Override
     public void thunderHit(ServerLevel world, LightningBolt lightning) {
-        this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE);
+        this.hurt(this.damageSources().lightningBolt().customEventDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
     }
 
     @Override
     public EntityDimensions getDefaultDimensions(Pose pose) {
-        return this.isBaby() ? BABY_DIMENSIONS : super.getDefaultDimensions(pose);
+        return this.isBaby() ? Turtle.BABY_DIMENSIONS : super.getDefaultDimensions(pose);
     }
 
-    static class TurtleBreedGoal extends BreedGoal {
+    private static class TurtleMoveControl extends MoveControl {
+
+        private final Turtle turtle;
+
+        TurtleMoveControl(Turtle turtle) {
+            super(turtle);
+            this.turtle = turtle;
+        }
+
+        private void updateSpeed() {
+            if (this.turtle.isInWater()) {
+                this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0D, 0.005D, 0.0D));
+                if (!this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 16.0D)) {
+                    this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.08F));
+                }
+
+                if (this.turtle.isBaby()) {
+                    this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 3.0F, 0.06F));
+                }
+            } else if (this.turtle.onGround()) {
+                this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.06F));
+            }
+
+        }
+
+        @Override
+        public void tick() {
+            this.updateSpeed();
+            if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) {
+                double d0 = this.wantedX - this.turtle.getX();
+                double d1 = this.wantedY - this.turtle.getY();
+                double d2 = this.wantedZ - this.turtle.getZ();
+                double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
+
+                if (d3 < 9.999999747378752E-6D) {
+                    this.mob.setSpeed(0.0F);
+                } else {
+                    d1 /= d3;
+                    float f = (float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F;
+
+                    this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F));
+                    this.turtle.yBodyRot = this.turtle.getYRot();
+                    float f1 = (float) (this.speedModifier * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED));
+
+                    this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), f1));
+                    this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0D, (double) this.turtle.getSpeed() * d1 * 0.1D, 0.0D));
+                }
+            } else {
+                this.turtle.setSpeed(0.0F);
+            }
+        }
+    }
+
+    private static class TurtlePanicGoal extends PanicGoal {
+
+        TurtlePanicGoal(Turtle turtle, double speed) {
+            super(turtle, speed);
+        }
+
+        @Override
+        public boolean canUse() {
+            if (!this.shouldPanic()) {
+                return false;
+            } else {
+                BlockPos blockposition = this.lookForWater(this.mob.level(), this.mob, 7);
+
+                if (blockposition != null) {
+                    this.posX = (double) blockposition.getX();
+                    this.posY = (double) blockposition.getY();
+                    this.posZ = (double) blockposition.getZ();
+                    return true;
+                } else {
+                    return this.findRandomPosition();
+                }
+            }
+        }
+    }
+
+    private static class TurtleBreedGoal extends BreedGoal {
+
         private final Turtle turtle;
 
         TurtleBreedGoal(Turtle turtle, double speed) {
@@ -349,14 +436,19 @@
 
         @Override
         protected void breed() {
-            ServerPlayer serverPlayer = this.animal.getLoveCause();
-            if (serverPlayer == null && this.partner.getLoveCause() != null) {
-                serverPlayer = this.partner.getLoveCause();
+            ServerPlayer entityplayer = this.animal.getLoveCause();
+
+            if (entityplayer == null && this.partner.getLoveCause() != null) {
+                entityplayer = this.partner.getLoveCause();
             }
+            // Paper start - Add EntityFertilizeEggEvent event
+            io.papermc.paper.event.entity.EntityFertilizeEggEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this.animal, this.partner);
+            if (event.isCancelled()) return;
+            // Paper end - Add EntityFertilizeEggEvent event
 
-            if (serverPlayer != null) {
-                serverPlayer.awardStat(Stats.ANIMALS_BRED);
-                CriteriaTriggers.BRED_ANIMALS.trigger(serverPlayer, this.animal, this.partner, null);
+            if (entityplayer != null) {
+                entityplayer.awardStat(Stats.ANIMALS_BRED);
+                CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this.animal, this.partner, (AgeableMob) null);
             }
 
             this.turtle.setHasEgg(true);
@@ -364,90 +456,81 @@
             this.partner.setAge(6000);
             this.animal.resetLove();
             this.partner.resetLove();
-            RandomSource randomSource = this.animal.getRandom();
+            RandomSource randomsource = this.animal.getRandom();
+
             if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
-                this.level
-                    .addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomSource.nextInt(7) + 1));
+                if (event.getExperience() > 0) this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), event.getExperience(), org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper - Add EntityFertilizeEggEvent event
             }
+
         }
     }
 
-    static class TurtleGoHomeGoal extends Goal {
+    private static class TurtleLayEggGoal extends MoveToBlockGoal {
+
         private final Turtle turtle;
-        private final double speedModifier;
-        private boolean stuck;
-        private int closeToHomeTryTicks;
-        private static final int GIVE_UP_TICKS = 600;
 
-        TurtleGoHomeGoal(Turtle turtle, double speed) {
+        TurtleLayEggGoal(Turtle turtle, double speed) {
+            super(turtle, speed, 16);
             this.turtle = turtle;
-            this.speedModifier = speed;
         }
 
         @Override
         public boolean canUse() {
-            return !this.turtle.isBaby()
-                && (
-                    this.turtle.hasEgg()
-                        || this.turtle.getRandom().nextInt(reducedTickDelay(700)) == 0
-                            && !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0)
-                );
-        }
-
-        @Override
-        public void start() {
-            this.turtle.setGoingHome(true);
-            this.stuck = false;
-            this.closeToHomeTryTicks = 0;
-        }
-
-        @Override
-        public void stop() {
-            this.turtle.setGoingHome(false);
+            return this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0D) ? super.canUse() : false;
         }
 
         @Override
         public boolean canContinueToUse() {
-            return !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 7.0)
-                && !this.stuck
-                && this.closeToHomeTryTicks <= this.adjustedTickDelay(600);
+            return super.canContinueToUse() && this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0D);
         }
 
         @Override
         public void tick() {
-            BlockPos blockPos = this.turtle.getHomePos();
-            boolean bl = blockPos.closerToCenterThan(this.turtle.position(), 16.0);
-            if (bl) {
-                this.closeToHomeTryTicks++;
-            }
+            super.tick();
+            BlockPos blockposition = this.turtle.blockPosition();
 
-            if (this.turtle.getNavigation().isDone()) {
-                Vec3 vec3 = Vec3.atBottomCenterOf(blockPos);
-                Vec3 vec32 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, (float) (Math.PI / 10));
-                if (vec32 == null) {
-                    vec32 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3, (float) (Math.PI / 2));
-                }
+            if (!this.turtle.isInWater() && this.isReachedTarget()) {
+                if (this.turtle.layEggCounter < 1) {
+                    this.turtle.setLayingEgg(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.blockPos)).callEvent()); // Paper - Turtle API
+                } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) {
+                    Level world = this.turtle.level();
 
-                if (vec32 != null && !bl && !this.turtle.level().getBlockState(BlockPos.containing(vec32)).is(Blocks.WATER)) {
-                    vec32 = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3, (float) (Math.PI / 2));
-                }
+                    // Paper start - Turtle API
+                    int eggCount = this.turtle.random.nextInt(4) + 1;
+                    com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(this.turtle.level(), this.blockPos.above()), eggCount);
+                    if (layEggEvent.callEvent() && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()))) {
+                    world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F);
+                    BlockPos blockposition1 = this.blockPos.above();
+                    BlockState iblockdata = (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()); // Paper
 
-                if (vec32 == null) {
-                    this.stuck = true;
-                    return;
+                    world.setBlock(blockposition1, iblockdata, 3);
+                    world.gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition1, GameEvent.Context.of(this.turtle, iblockdata));
+                    } // CraftBukkit
+                    this.turtle.setHasEgg(false);
+                    this.turtle.setLayingEgg(false);
+                    this.turtle.setInLoveTime(600);
                 }
 
-                this.turtle.getNavigation().moveTo(vec32.x, vec32.y, vec32.z, this.speedModifier);
+                if (this.turtle.isLayingEgg()) {
+                    ++this.turtle.layEggCounter;
+                }
             }
+
+        }
+
+        @Override
+        protected boolean isValidTarget(LevelReader world, BlockPos pos) {
+            return !world.isEmptyBlock(pos.above()) ? false : TurtleEggBlock.isSand(world, pos);
         }
     }
 
-    static class TurtleGoToWaterGoal extends MoveToBlockGoal {
+    private static class TurtleGoToWaterGoal extends MoveToBlockGoal {
+
         private static final int GIVE_UP_TICKS = 1200;
         private final Turtle turtle;
 
         TurtleGoToWaterGoal(Turtle turtle, double speed) {
-            super(turtle, turtle.isBaby() ? 2.0 : speed, 24);
+            super(turtle, turtle.isBaby() ? 2.0D : speed, 24);
             this.turtle = turtle;
             this.verticalSearchStart = -1;
         }
@@ -459,9 +542,7 @@
 
         @Override
         public boolean canUse() {
-            return this.turtle.isBaby() && !this.turtle.isInWater()
-                ? super.canUse()
-                : !this.turtle.isGoingHome() && !this.turtle.isInWater() && !this.turtle.hasEgg() && super.canUse();
+            return this.turtle.isBaby() && !this.turtle.isInWater() ? super.canUse() : (!this.turtle.isGoingHome() && !this.turtle.isInWater() && !this.turtle.hasEgg() ? super.canUse() : false);
         }
 
         @Override
@@ -475,158 +556,75 @@
         }
     }
 
-    static class TurtleLayEggGoal extends MoveToBlockGoal {
+    private static class TurtleGoHomeGoal extends Goal {
+
         private final Turtle turtle;
+        private final double speedModifier;
+        private boolean stuck;
+        private int closeToHomeTryTicks;
+        private static final int GIVE_UP_TICKS = 600;
 
-        TurtleLayEggGoal(Turtle turtle, double speed) {
-            super(turtle, speed, 16);
+        TurtleGoHomeGoal(Turtle turtle, double speed) {
             this.turtle = turtle;
+            this.speedModifier = speed;
         }
 
         @Override
         public boolean canUse() {
-            return this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0) && super.canUse();
+            return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity()).callEvent(); // Paper - Turtle API
         }
 
         @Override
-        public boolean canContinueToUse() {
-            return super.canContinueToUse() && this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0);
+        public void start() {
+            this.turtle.setGoingHome(true);
+            this.stuck = false;
+            this.closeToHomeTryTicks = 0;
         }
 
         @Override
-        public void tick() {
-            super.tick();
-            BlockPos blockPos = this.turtle.blockPosition();
-            if (!this.turtle.isInWater() && this.isReachedTarget()) {
-                if (this.turtle.layEggCounter < 1) {
-                    this.turtle.setLayingEgg(true);
-                } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) {
-                    Level level = this.turtle.level();
-                    level.playSound(null, blockPos, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + level.random.nextFloat() * 0.2F);
-                    BlockPos blockPos2 = this.blockPos.above();
-                    BlockState blockState = Blocks.TURTLE_EGG
-                        .defaultBlockState()
-                        .setValue(TurtleEggBlock.EGGS, Integer.valueOf(this.turtle.random.nextInt(4) + 1));
-                    level.setBlock(blockPos2, blockState, 3);
-                    level.gameEvent(GameEvent.BLOCK_PLACE, blockPos2, GameEvent.Context.of(this.turtle, blockState));
-                    this.turtle.setHasEgg(false);
-                    this.turtle.setLayingEgg(false);
-                    this.turtle.setInLoveTime(600);
-                }
-
-                if (this.turtle.isLayingEgg()) {
-                    this.turtle.layEggCounter++;
-                }
-            }
+        public void stop() {
+            this.turtle.setGoingHome(false);
         }
 
         @Override
-        protected boolean isValidTarget(LevelReader world, BlockPos pos) {
-            return world.isEmptyBlock(pos.above()) && TurtleEggBlock.isSand(world, pos);
+        public boolean canContinueToUse() {
+            return !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 7.0D) && !this.stuck && this.closeToHomeTryTicks <= this.adjustedTickDelay(600);
         }
-    }
 
-    static class TurtleMoveControl extends MoveControl {
-        private final Turtle turtle;
+        @Override
+        public void tick() {
+            BlockPos blockposition = this.turtle.getHomePos();
+            boolean flag = blockposition.closerToCenterThan(this.turtle.position(), 16.0D);
 
-        TurtleMoveControl(Turtle turtle) {
-            super(turtle);
-            this.turtle = turtle;
-        }
+            if (flag) {
+                ++this.closeToHomeTryTicks;
+            }
 
-        private void updateSpeed() {
-            if (this.turtle.isInWater()) {
-                this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0, 0.005, 0.0));
-                if (!this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 16.0)) {
-                    this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.08F));
-                }
+            if (this.turtle.getNavigation().isDone()) {
+                Vec3 vec3d = Vec3.atBottomCenterOf(blockposition);
+                Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3d, 0.3141592741012573D);
 
-                if (this.turtle.isBaby()) {
-                    this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 3.0F, 0.06F));
+                if (vec3d1 == null) {
+                    vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3d, 1.5707963705062866D);
                 }
-            } else if (this.turtle.onGround()) {
-                this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.06F));
-            }
-        }
 
-        @Override
-        public void tick() {
-            this.updateSpeed();
-            if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) {
-                double d = this.wantedX - this.turtle.getX();
-                double e = this.wantedY - this.turtle.getY();
-                double f = this.wantedZ - this.turtle.getZ();
-                double g = Math.sqrt(d * d + e * e + f * f);
-                if (g < 1.0E-5F) {
-                    this.mob.setSpeed(0.0F);
-                } else {
-                    e /= g;
-                    float h = (float)(Mth.atan2(f, d) * 180.0F / (float)Math.PI) - 90.0F;
-                    this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), h, 90.0F));
-                    this.turtle.yBodyRot = this.turtle.getYRot();
-                    float i = (float)(this.speedModifier * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED));
-                    this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), i));
-                    this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0, (double)this.turtle.getSpeed() * e * 0.1, 0.0));
+                if (vec3d1 != null && !flag && !this.turtle.level().getBlockState(BlockPos.containing(vec3d1)).is(Blocks.WATER)) {
+                    vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3d, 1.5707963705062866D);
                 }
-            } else {
-                this.turtle.setSpeed(0.0F);
-            }
-        }
-    }
 
-    static class TurtlePanicGoal extends PanicGoal {
-        TurtlePanicGoal(Turtle turtle, double speed) {
-            super(turtle, speed);
-        }
-
-        @Override
-        public boolean canUse() {
-            if (!this.shouldPanic()) {
-                return false;
-            } else {
-                BlockPos blockPos = this.lookForWater(this.mob.level(), this.mob, 7);
-                if (blockPos != null) {
-                    this.posX = (double)blockPos.getX();
-                    this.posY = (double)blockPos.getY();
-                    this.posZ = (double)blockPos.getZ();
-                    return true;
-                } else {
-                    return this.findRandomPosition();
+                if (vec3d1 == null) {
+                    this.stuck = true;
+                    return;
                 }
-            }
-        }
-    }
-
-    static class TurtlePathNavigation extends AmphibiousPathNavigation {
-        TurtlePathNavigation(Turtle owner, Level world) {
-            super(owner, world);
-        }
 
-        @Override
-        public boolean isStableDestination(BlockPos pos) {
-            if (this.mob instanceof Turtle turtle && turtle.isTravelling()) {
-                return this.level.getBlockState(pos).is(Blocks.WATER);
+                this.turtle.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier);
             }
 
-            return !this.level.getBlockState(pos.below()).isAir();
         }
     }
 
-    static class TurtleRandomStrollGoal extends RandomStrollGoal {
-        private final Turtle turtle;
-
-        TurtleRandomStrollGoal(Turtle turtle, double speed, int chance) {
-            super(turtle, speed, chance);
-            this.turtle = turtle;
-        }
-
-        @Override
-        public boolean canUse() {
-            return !this.mob.isInWater() && !this.turtle.isGoingHome() && !this.turtle.hasEgg() && super.canUse();
-        }
-    }
+    private static class TurtleTravelGoal extends Goal {
 
-    static class TurtleTravelGoal extends Goal {
         private final Turtle turtle;
         private final double speedModifier;
         private boolean stuck;
@@ -643,18 +641,20 @@
 
         @Override
         public void start() {
-            int i = 512;
-            int j = 4;
-            RandomSource randomSource = this.turtle.random;
-            int k = randomSource.nextInt(1025) - 512;
-            int l = randomSource.nextInt(9) - 4;
-            int m = randomSource.nextInt(1025) - 512;
-            if ((double)l + this.turtle.getY() > (double)(this.turtle.level().getSeaLevel() - 1)) {
-                l = 0;
+            boolean flag = true;
+            boolean flag1 = true;
+            RandomSource randomsource = this.turtle.random;
+            int i = randomsource.nextInt(1025) - 512;
+            int j = randomsource.nextInt(9) - 4;
+            int k = randomsource.nextInt(1025) - 512;
+
+            if ((double) j + this.turtle.getY() > (double) (this.turtle.level().getSeaLevel() - 1)) {
+                j = 0;
             }
 
-            BlockPos blockPos = BlockPos.containing((double)k + this.turtle.getX(), (double)l + this.turtle.getY(), (double)m + this.turtle.getZ());
-            this.turtle.setTravelPos(blockPos);
+            BlockPos blockposition = BlockPos.containing((double) i + this.turtle.getX(), (double) j + this.turtle.getY(), (double) k + this.turtle.getZ());
+
+            this.turtle.setTravelPos(blockposition);
             this.turtle.setTravelling(true);
             this.stuck = false;
         }
@@ -662,28 +662,31 @@
         @Override
         public void tick() {
             if (this.turtle.getNavigation().isDone()) {
-                Vec3 vec3 = Vec3.atBottomCenterOf(this.turtle.getTravelPos());
-                Vec3 vec32 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, (float) (Math.PI / 10));
-                if (vec32 == null) {
-                    vec32 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3, (float) (Math.PI / 2));
+                Vec3 vec3d = Vec3.atBottomCenterOf(this.turtle.getTravelPos());
+                Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3d, 0.3141592741012573D);
+
+                if (vec3d1 == null) {
+                    vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3d, 1.5707963705062866D);
                 }
 
-                if (vec32 != null) {
-                    int i = Mth.floor(vec32.x);
-                    int j = Mth.floor(vec32.z);
-                    int k = 34;
+                if (vec3d1 != null) {
+                    int i = Mth.floor(vec3d1.x);
+                    int j = Mth.floor(vec3d1.z);
+                    boolean flag = true;
+
                     if (!this.turtle.level().hasChunksAt(i - 34, j - 34, i + 34, j + 34)) {
-                        vec32 = null;
+                        vec3d1 = null;
                     }
                 }
 
-                if (vec32 == null) {
+                if (vec3d1 == null) {
                     this.stuck = true;
                     return;
                 }
 
-                this.turtle.getNavigation().moveTo(vec32.x, vec32.y, vec32.z, this.speedModifier);
+                this.turtle.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier);
             }
+
         }
 
         @Override
@@ -697,4 +700,39 @@
             super.stop();
         }
     }
+
+    private static class TurtleRandomStrollGoal extends RandomStrollGoal {
+
+        private final Turtle turtle;
+
+        TurtleRandomStrollGoal(Turtle turtle, double speed, int chance) {
+            super(turtle, speed, chance);
+            this.turtle = turtle;
+        }
+
+        @Override
+        public boolean canUse() {
+            return !this.mob.isInWater() && !this.turtle.isGoingHome() && !this.turtle.hasEgg() ? super.canUse() : false;
+        }
+    }
+
+    private static class TurtlePathNavigation extends AmphibiousPathNavigation {
+
+        TurtlePathNavigation(Turtle owner, Level world) {
+            super(owner, world);
+        }
+
+        @Override
+        public boolean isStableDestination(BlockPos pos) {
+            Mob entityinsentient = this.mob;
+
+            if (entityinsentient instanceof Turtle entityturtle) {
+                if (entityturtle.isTravelling()) {
+                    return this.level.getBlockState(pos).is(Blocks.WATER);
+                }
+            }
+
+            return !this.level.getBlockState(pos.below()).isAir();
+        }
+    }
 }
