aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch')
-rw-r--r--patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch869
1 files changed, 869 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch
new file mode 100644
index 0000000000..3963921386
--- /dev/null
+++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch
@@ -0,0 +1,869 @@
+--- a/net/minecraft/world/entity/animal/Turtle.java
++++ b/net/minecraft/world/entity/animal/Turtle.java
+@@ -23,14 +23,14 @@
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.entity.EntityDimensions;
+ import net.minecraft.world.entity.EntityType;
++import net.minecraft.world.entity.EnumMobSpawn;
++import net.minecraft.world.entity.EnumMonsterType;
++import net.minecraft.world.entity.EnumMoveType;
+ import net.minecraft.world.entity.ExperienceOrb;
++import net.minecraft.world.entity.GroupDataEntity;
+ import net.minecraft.world.entity.LightningBolt;
+ import net.minecraft.world.entity.LivingEntity;
+ import net.minecraft.world.entity.Mob;
+-import net.minecraft.world.entity.MobSpawnType;
+-import net.minecraft.world.entity.MobType;
+-import net.minecraft.world.entity.MoverType;
+-import net.minecraft.world.entity.SpawnGroupData;
+ import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
+ import net.minecraft.world.entity.ai.attributes.Attributes;
+ import net.minecraft.world.entity.ai.control.MoveControl;
+@@ -56,13 +56,14 @@
+ import net.minecraft.world.level.block.Block;
+ import net.minecraft.world.level.block.Blocks;
+ import net.minecraft.world.level.block.TurtleEggBlock;
+-import net.minecraft.world.level.block.state.BlockState;
++import net.minecraft.world.level.block.state.IBlockData;
+ import net.minecraft.world.level.gameevent.GameEvent;
+ import net.minecraft.world.level.pathfinder.BlockPathTypes;
+ import net.minecraft.world.phys.Vec3;
+ import org.joml.Vector3f;
+
+ 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);
+@@ -71,7 +72,9 @@
+ private static final EntityDataAccessor<Boolean> TRAVELLING = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN);
+ public static final Ingredient FOOD_ITEMS = Ingredient.of(Blocks.SEAGRASS.asItem());
+ int layEggCounter;
+- public static final Predicate<LivingEntity> BABY_ON_LAND_SELECTOR = livingEntity -> livingEntity.isBaby() && !livingEntity.isInWater();
++ public static final Predicate<LivingEntity> BABY_ON_LAND_SELECTOR = (entityliving) -> {
++ return entityliving.isBaby() && !entityliving.isInWater();
++ };
+
+ public Turtle(EntityType<? extends Turtle> entityType, Level level) {
+ super(entityType, level);
+@@ -84,63 +87,63 @@
+ }
+
+ public void setHomePos(BlockPos homePos) {
+- this.entityData.set(HOME_POS, homePos);
++ this.entityData.set(Turtle.HOME_POS, homePos);
+ }
+
+ BlockPos getHomePos() {
+- return this.entityData.get(HOME_POS);
++ return (BlockPos) this.entityData.get(Turtle.HOME_POS);
+ }
+
+ void setTravelPos(BlockPos travelPos) {
+- this.entityData.set(TRAVEL_POS, travelPos);
++ this.entityData.set(Turtle.TRAVEL_POS, travelPos);
+ }
+
+ 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);
+ }
+
+ 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 isLayingEgg) {
+ this.layEggCounter = isLayingEgg ? 1 : 0;
+- this.entityData.set(LAYING_EGG, isLayingEgg);
++ this.entityData.set(Turtle.LAYING_EGG, isLayingEgg);
+ }
+
+ boolean isGoingHome() {
+- return this.entityData.get(GOING_HOME);
++ return (Boolean) this.entityData.get(Turtle.GOING_HOME);
+ }
+
+ void setGoingHome(boolean isGoingHome) {
+- this.entityData.set(GOING_HOME, isGoingHome);
++ this.entityData.set(Turtle.GOING_HOME, isGoingHome);
+ }
+
+ boolean isTravelling() {
+- return this.entityData.get(TRAVELLING);
++ return (Boolean) this.entityData.get(Turtle.TRAVELLING);
+ }
+
+ void setTravelling(boolean isTravelling) {
+- this.entityData.set(TRAVELLING, isTravelling);
++ this.entityData.set(Turtle.TRAVELLING, isTravelling);
+ }
+
+ @Override
+ protected void defineSynchedData() {
+ super.defineSynchedData();
+- this.entityData.define(HOME_POS, BlockPos.ZERO);
+- this.entityData.define(HAS_EGG, false);
+- this.entityData.define(TRAVEL_POS, BlockPos.ZERO);
+- this.entityData.define(GOING_HOME, false);
+- this.entityData.define(TRAVELLING, false);
+- this.entityData.define(LAYING_EGG, false);
++ this.entityData.define(Turtle.HOME_POS, BlockPos.ZERO);
++ this.entityData.define(Turtle.HAS_EGG, false);
++ this.entityData.define(Turtle.TRAVEL_POS, BlockPos.ZERO);
++ this.entityData.define(Turtle.GOING_HOME, false);
++ this.entityData.define(Turtle.TRAVELLING, false);
++ this.entityData.define(Turtle.LAYING_EGG, false);
+ }
+
+ @Override
+@@ -157,47 +160,47 @@
+
+ @Override
+ public void readAdditionalSaveData(CompoundTag compound) {
+- int _int = compound.getInt("HomePosX");
+- int _int1 = compound.getInt("HomePosY");
+- int _int2 = compound.getInt("HomePosZ");
+- this.setHomePos(new BlockPos(_int, _int1, _int2));
++ int i = compound.getInt("HomePosX");
++ int j = compound.getInt("HomePosY");
++ int k = compound.getInt("HomePosZ");
++
++ this.setHomePos(new BlockPos(i, j, k));
+ super.readAdditionalSaveData(compound);
+ this.setHasEgg(compound.getBoolean("HasEgg"));
+- int _int3 = compound.getInt("TravelPosX");
+- int _int4 = compound.getInt("TravelPosY");
+- int _int5 = compound.getInt("TravelPosZ");
+- this.setTravelPos(new BlockPos(_int3, _int4, _int5));
++ int l = compound.getInt("TravelPosX");
++ int i1 = compound.getInt("TravelPosY");
++ int j1 = compound.getInt("TravelPosZ");
++
++ this.setTravelPos(new BlockPos(l, i1, j1));
+ }
+
+ @Nullable
+ @Override
+- public SpawnGroupData finalizeSpawn(
+- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag
+- ) {
++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) {
+ this.setHomePos(this.blockPosition());
+ this.setTravelPos(BlockPos.ZERO);
+ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag);
+ }
+
+- public static boolean checkTurtleSpawnRules(EntityType<Turtle> turtle, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) {
++ public static boolean checkTurtleSpawnRules(EntityType<Turtle> turtle, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) {
+ return pos.getY() < level.getSeaLevel() + 4 && TurtleEggBlock.onSand(level, pos) && isBrightEnoughToSpawn(level, pos);
+ }
+
+ @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, FOOD_ITEMS, 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, Turtle.FOOD_ITEMS, 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);
++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0D).add(Attributes.MOVEMENT_SPEED, 0.25D);
+ }
+
+ @Override
+@@ -206,8 +209,8 @@
+ }
+
+ @Override
+- public MobType getMobType() {
+- return MobType.WATER;
++ public EnumMonsterType getMobType() {
++ return EnumMonsterType.WATER;
+ }
+
+ @Override
+@@ -244,9 +247,10 @@
+ }
+
+ @Override
+- protected void playStepSound(BlockPos pos, BlockState block) {
+- SoundEvent soundEvent = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE;
+- this.playSound(soundEvent, 0.15F, 1.0F);
++ protected void playStepSound(BlockPos pos, IBlockData block) {
++ SoundEvent soundeffect = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE;
++
++ this.playSound(soundeffect, 0.15F, 1.0F);
+ }
+
+ @Override
+@@ -272,7 +276,7 @@
+ @Nullable
+ @Override
+ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) {
+- return EntityType.TURTLE.create(level);
++ return (AgeableMob) EntityType.TURTLE.create(level);
+ }
+
+ @Override
+@@ -282,45 +286,47 @@
+
+ @Override
+ public float getWalkTargetValue(BlockPos pos, LevelReader level) {
+- if (!this.isGoingHome() && level.getFluidState(pos).is(FluidTags.WATER)) {
+- return 10.0F;
+- } else {
+- return TurtleEggBlock.onSand(level, pos) ? 10.0F : level.getPathfindingCostFromLightLevels(pos);
+- }
++ return !this.isGoingHome() && level.getFluidState(pos).is(FluidTags.WATER) ? 10.0F : (TurtleEggBlock.onSand(level, pos) ? 10.0F : level.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.SCUTE, 1);
++ this.forceDrops = false; // CraftBukkit
+ }
++
+ }
+
+ @Override
+ public void travel(Vec3 travelVector) {
+ if (this.isControlledByLocalInstance() && this.isInWater()) {
+ this.moveRelative(0.1F, travelVector);
+- 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.move(EnumMoveType.SELF, this.getDeltaMovement());
++ 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(travelVector);
+ }
++
+ }
+
+ @Override
+@@ -330,17 +336,98 @@
+
+ @Override
+ public void thunderHit(ServerLevel level, LightningBolt lightning) {
++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = lightning; // CraftBukkit
+ this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE);
++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit
+ }
+
+ @Override
+- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) {
+- return new Vector3f(0.0F, entityDimensions.height + (this.isBaby() ? 0.0F : 0.15625F) * f, -0.25F * f);
++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) {
++ return new Vector3f(0.0F, entitysize.height + (this.isBaby() ? 0.0F : 0.15625F) * f, -0.25F * f);
+ }
+
+- 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 speedModifier) {
++ super(turtle, speedModifier);
++ }
++
++ @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 speedModifier) {
+ super(turtle, speedModifier);
+ this.turtle = turtle;
+@@ -353,14 +440,15 @@
+
+ @Override
+ protected void breed() {
+- ServerPlayer loveCause = this.animal.getLoveCause();
+- if (loveCause == null && this.partner.getLoveCause() != null) {
+- loveCause = this.partner.getLoveCause();
++ ServerPlayer entityplayer = this.animal.getLoveCause();
++
++ if (entityplayer == null && this.partner.getLoveCause() != null) {
++ entityplayer = this.partner.getLoveCause();
+ }
+
+- if (loveCause != null) {
+- loveCause.awardStat(Stats.ANIMALS_BRED);
+- CriteriaTriggers.BRED_ANIMALS.trigger(loveCause, 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);
+@@ -368,89 +456,78 @@
+ this.partner.setAge(6000);
+ this.animal.resetLove();
+ this.partner.resetLove();
+- RandomSource random = 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(), random.nextInt(7) + 1));
++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1));
+ }
++
+ }
+ }
+
+- 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 speedModifier) {
++ TurtleLayEggGoal(Turtle turtle, double speedModifier) {
++ super(turtle, speedModifier, 16);
+ this.turtle = turtle;
+- this.speedModifier = speedModifier;
+ }
+
+ @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)
+- );
++ return this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0D) ? super.canUse() : false;
+ }
+
+ @Override
+- public void start() {
+- this.turtle.setGoingHome(true);
+- this.stuck = false;
+- this.closeToHomeTryTicks = 0;
+- }
+-
+- @Override
+- public void stop() {
+- this.turtle.setGoingHome(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 homePos = this.turtle.getHomePos();
+- boolean flag = homePos.closerToCenterThan(this.turtle.position(), 16.0);
+- if (flag) {
+- this.closeToHomeTryTicks++;
+- }
++ super.tick();
++ BlockPos blockposition = this.turtle.blockPosition();
+
+- if (this.turtle.getNavigation().isDone()) {
+- Vec3 vec3 = Vec3.atBottomCenterOf(homePos);
+- Vec3 posTowards = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, (float) (Math.PI / 10));
+- if (posTowards == null) {
+- posTowards = 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(true);
++ } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) {
++ Level world = this.turtle.level();
+
+- if (posTowards != null && !flag && !this.turtle.level().getBlockState(BlockPos.containing(posTowards)).is(Blocks.WATER)) {
+- posTowards = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3, (float) (Math.PI / 2));
+- }
++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1))) { // CraftBukkit
++ 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();
++ IBlockData iblockdata = (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1);
+
+- if (posTowards == null) {
+- this.stuck = true;
+- return;
++ world.setBlock(blockposition1, iblockdata, 3);
++ world.gameEvent(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(posTowards.x, posTowards.y, posTowards.z, this.speedModifier);
++ if (this.turtle.isLayingEgg()) {
++ ++this.turtle.layEggCounter;
++ }
+ }
++
+ }
++
++ @Override
++ protected boolean isValidTarget(LevelReader level, BlockPos pos) {
++ return !level.isEmptyBlock(pos.above()) ? false : TurtleEggBlock.isSand(level, 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 speedModifier) {
+- super(turtle, turtle.isBaby() ? 2.0 : speedModifier, 24);
++ super(turtle, turtle.isBaby() ? 2.0D : speedModifier, 24);
+ this.turtle = turtle;
+ this.verticalSearchStart = -1;
+ }
+@@ -462,9 +539,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
+@@ -478,158 +553,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 speedModifier) {
+- super(turtle, speedModifier, 16);
++ TurtleGoHomeGoal(Turtle turtle, double speedModifier) {
+ this.turtle = turtle;
++ this.speedModifier = speedModifier;
+ }
+
+ @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)));
+ }
+
+ @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 blockPos1 = this.blockPos.above();
+- BlockState blockState = Blocks.TURTLE_EGG
+- .defaultBlockState()
+- .setValue(TurtleEggBlock.EGGS, Integer.valueOf(this.turtle.random.nextInt(4) + 1));
+- level.setBlock(blockPos1, blockState, 3);
+- level.gameEvent(GameEvent.BLOCK_PLACE, blockPos1, 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 level, BlockPos pos) {
+- return level.isEmptyBlock(pos.above()) && TurtleEggBlock.isSand(level, 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 mob) {
+- super(mob);
+- this.turtle = mob;
+- }
++ 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 d1 = this.wantedY - this.turtle.getY();
+- double d2 = this.wantedZ - this.turtle.getZ();
+- double squareRoot = Math.sqrt(d * d + d1 * d1 + d2 * d2);
+- if (squareRoot < 1.0E-5F) {
+- this.mob.setSpeed(0.0F);
+- } else {
+- d1 /= squareRoot;
+- float f = (float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 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.0, (double)this.turtle.getSpeed() * d1 * 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 speedModifier) {
+- super(turtle, speedModifier);
+- }
+-
+- @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 turtle, Level level) {
+- super(turtle, level);
+- }
+-
+- @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;
++ private static class TurtleTravelGoal extends Goal {
+
+- TurtleRandomStrollGoal(Turtle turtle, double speedModifier, int interval) {
+- super(turtle, speedModifier, interval);
+- this.turtle = turtle;
+- }
+-
+- @Override
+- public boolean canUse() {
+- return !this.mob.isInWater() && !this.turtle.isGoingHome() && !this.turtle.hasEgg() && super.canUse();
+- }
+- }
+-
+- static class TurtleTravelGoal extends Goal {
+ private final Turtle turtle;
+ private final double speedModifier;
+ private boolean stuck;
+@@ -646,18 +638,20 @@
+
+ @Override
+ public void start() {
+- int i = 512;
+- int i1 = 4;
+- RandomSource randomSource = this.turtle.random;
+- int i2 = randomSource.nextInt(1025) - 512;
+- int i3 = randomSource.nextInt(9) - 4;
+- int i4 = randomSource.nextInt(1025) - 512;
+- if ((double)i3 + this.turtle.getY() > (double)(this.turtle.level().getSeaLevel() - 1)) {
+- i3 = 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)i2 + this.turtle.getX(), (double)i3 + this.turtle.getY(), (double)i4 + 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;
+ }
+@@ -665,28 +659,31 @@
+ @Override
+ public void tick() {
+ if (this.turtle.getNavigation().isDone()) {
+- Vec3 vec3 = Vec3.atBottomCenterOf(this.turtle.getTravelPos());
+- Vec3 posTowards = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, (float) (Math.PI / 10));
+- if (posTowards == null) {
+- posTowards = 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 (posTowards != null) {
+- int floor = Mth.floor(posTowards.x);
+- int floor1 = Mth.floor(posTowards.z);
+- int i = 34;
+- if (!this.turtle.level().hasChunksAt(floor - 34, floor1 - 34, floor + 34, floor1 + 34)) {
+- posTowards = null;
++ 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)) {
++ vec3d1 = null;
+ }
+ }
+
+- if (posTowards == null) {
++ if (vec3d1 == null) {
+ this.stuck = true;
+ return;
+ }
+
+- this.turtle.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier);
++ this.turtle.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier);
+ }
++
+ }
+
+ @Override
+@@ -700,4 +697,41 @@
+ super.stop();
+ }
+ }
++
++ private static class TurtleRandomStrollGoal extends RandomStrollGoal {
++
++ private final Turtle turtle;
++
++ TurtleRandomStrollGoal(Turtle turtle, double speedModifier, int i) {
++ super(turtle, speedModifier, i);
++ 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 turtle, Level level) {
++ super(turtle, level);
++ }
++
++ @Override
++ public boolean isStableDestination(BlockPos pos) {
++ Mob entityinsentient = this.mob;
++
++ if (entityinsentient instanceof Turtle) {
++ Turtle entityturtle = (Turtle) entityinsentient;
++
++ if (entityturtle.isTravelling()) {
++ return this.level.getBlockState(pos).is(Blocks.WATER);
++ }
++ }
++
++ return !this.level.getBlockState(pos.below()).isAir();
++ }
++ }
+ }