aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch')
-rw-r--r--patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch580
1 files changed, 580 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch
new file mode 100644
index 0000000000..e6905ed1f3
--- /dev/null
+++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch
@@ -0,0 +1,580 @@
+--- a/net/minecraft/world/entity/monster/Drowned.java
++++ b/net/minecraft/world/entity/monster/Drowned.java
+@@ -13,15 +13,15 @@
+ import net.minecraft.util.RandomSource;
+ import net.minecraft.world.Difficulty;
+ import net.minecraft.world.DifficultyInstance;
+-import net.minecraft.world.InteractionHand;
++import net.minecraft.world.EnumHand;
+ import net.minecraft.world.damagesource.DamageSource;
+ import net.minecraft.world.entity.EntityType;
++import net.minecraft.world.entity.EnumMobSpawn;
++import net.minecraft.world.entity.EnumMoveType;
+ import net.minecraft.world.entity.EquipmentSlot;
++import net.minecraft.world.entity.GroupDataEntity;
+ import net.minecraft.world.entity.LivingEntity;
+-import net.minecraft.world.entity.MobSpawnType;
+-import net.minecraft.world.entity.MoverType;
+ import net.minecraft.world.entity.PathfinderMob;
+-import net.minecraft.world.entity.SpawnGroupData;
+ import net.minecraft.world.entity.ai.attributes.Attributes;
+ import net.minecraft.world.entity.ai.control.MoveControl;
+ import net.minecraft.world.entity.ai.goal.Goal;
+@@ -53,10 +53,11 @@
+ import net.minecraft.world.phys.Vec3;
+
+ public class Drowned extends Zombie implements RangedAttackMob {
++
+ public static final float NAUTILUS_SHELL_CHANCE = 0.03F;
+ boolean searchingForLand;
+- protected final WaterBoundPathNavigation waterNavigation;
+- protected final GroundPathNavigation groundNavigation;
++ public final WaterBoundPathNavigation waterNavigation;
++ public final GroundPathNavigation groundNavigation;
+
+ public Drowned(EntityType<? extends Drowned> entityType, Level level) {
+ super(entityType, level);
+@@ -69,13 +70,13 @@
+
+ @Override
+ protected void addBehaviourGoals() {
+- this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0));
+- this.goalSelector.addGoal(2, new Drowned.DrownedTridentAttackGoal(this, 1.0, 40, 10.0F));
+- this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0, false));
+- this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0));
+- this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0, this.level().getSeaLevel()));
+- this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0));
+- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class));
++ this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D));
++ this.goalSelector.addGoal(2, new Drowned.DrownedTridentAttackGoal(this, 1.0D, 40, 10.0F));
++ this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0D, false));
++ this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0D));
++ this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0D, this.level().getSeaLevel()));
++ this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D));
++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class));
+ this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget));
+ this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
+ this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
+@@ -84,35 +85,24 @@
+ }
+
+ @Override
+- public SpawnGroupData finalizeSpawn(
+- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag
+- ) {
+- SpawnGroupData var6 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag);
++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) {
++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag);
+ if (this.getItemBySlot(EquipmentSlot.OFFHAND).isEmpty() && level.getRandom().nextFloat() < 0.03F) {
+ this.setItemSlot(EquipmentSlot.OFFHAND, new ItemStack(Items.NAUTILUS_SHELL));
+ this.setGuaranteedDrop(EquipmentSlot.OFFHAND);
+ }
+
+- return var6;
++ return spawnData;
+ }
+
+- public static boolean checkDrownedSpawnRules(
+- EntityType<Drowned> drowned, ServerLevelAccessor serverLevel, MobSpawnType mobSpawnType, BlockPos pos, RandomSource random
+- ) {
+- if (!serverLevel.getFluidState(pos.below()).is(FluidTags.WATER) && !MobSpawnType.isSpawner(mobSpawnType)) {
++ public static boolean checkDrownedSpawnRules(EntityType<Drowned> drowned, ServerLevelAccessor serverLevel, EnumMobSpawn mobSpawnType, BlockPos pos, RandomSource random) {
++ if (!serverLevel.getFluidState(pos.below()).is(FluidTags.WATER) && !EnumMobSpawn.isSpawner(mobSpawnType)) {
+ return false;
+ } else {
+- Holder<Biome> biome = serverLevel.getBiome(pos);
+- boolean flag = serverLevel.getDifficulty() != Difficulty.PEACEFUL
+- && (MobSpawnType.ignoresLightRequirements(mobSpawnType) || isDarkEnoughToSpawn(serverLevel, pos, random))
+- && (MobSpawnType.isSpawner(mobSpawnType) || serverLevel.getFluidState(pos).is(FluidTags.WATER));
+- if (flag && MobSpawnType.isSpawner(mobSpawnType)) {
+- return true;
+- } else {
+- return biome.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS)
+- ? random.nextInt(15) == 0 && flag
+- : random.nextInt(40) == 0 && isDeepEnoughToSpawn(serverLevel, pos) && flag;
+- }
++ Holder<Biome> holder = serverLevel.getBiome(pos);
++ boolean flag = serverLevel.getDifficulty() != Difficulty.PEACEFUL && (EnumMobSpawn.ignoresLightRequirements(mobSpawnType) || isDarkEnoughToSpawn(serverLevel, pos, random)) && (EnumMobSpawn.isSpawner(mobSpawnType) || serverLevel.getFluidState(pos).is(FluidTags.WATER));
++
++ return flag && EnumMobSpawn.isSpawner(mobSpawnType) ? true : (holder.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS) ? random.nextInt(15) == 0 && flag : random.nextInt(40) == 0 && isDeepEnoughToSpawn(serverLevel, pos) && flag);
+ }
+ }
+
+@@ -157,25 +147,21 @@
+
+ @Override
+ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) {
+- if ((double)random.nextFloat() > 0.9) {
+- int randomInt = random.nextInt(16);
+- if (randomInt < 10) {
++ if ((double) random.nextFloat() > 0.9D) {
++ int i = random.nextInt(16);
++
++ if (i < 10) {
+ this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.TRIDENT));
+ } else {
+ this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.FISHING_ROD));
+ }
+ }
++
+ }
+
+ @Override
+ protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) {
+- if (existing.is(Items.NAUTILUS_SHELL)) {
+- return false;
+- } else {
+- return existing.is(Items.TRIDENT)
+- ? candidate.is(Items.TRIDENT) && candidate.getDamageValue() < existing.getDamageValue()
+- : candidate.is(Items.TRIDENT) || super.canReplaceCurrentItem(candidate, existing);
+- }
++ return existing.is(Items.NAUTILUS_SHELL) ? false : (existing.is(Items.TRIDENT) ? (candidate.is(Items.TRIDENT) ? candidate.getDamageValue() < existing.getDamageValue() : false) : (candidate.is(Items.TRIDENT) ? true : super.canReplaceCurrentItem(candidate, existing)));
+ }
+
+ @Override
+@@ -189,7 +175,7 @@
+ }
+
+ public boolean okTarget(@Nullable LivingEntity target) {
+- return target != null && (!this.level().isDay() || target.isInWater());
++ return target != null ? !this.level().isDay() || target.isInWater() : false;
+ }
+
+ @Override
+@@ -201,8 +187,9 @@
+ if (this.searchingForLand) {
+ return true;
+ } else {
+- LivingEntity target = this.getTarget();
+- return target != null && target.isInWater();
++ LivingEntity entityliving = this.getTarget();
++
++ return entityliving != null && entityliving.isInWater();
+ }
+ }
+
+@@ -210,11 +197,12 @@
+ public void travel(Vec3 travelVector) {
+ if (this.isControlledByLocalInstance() && this.isInWater() && this.wantsToSwim()) {
+ this.moveRelative(0.01F, travelVector);
+- this.move(MoverType.SELF, this.getDeltaMovement());
+- this.setDeltaMovement(this.getDeltaMovement().scale(0.9));
++ this.move(EnumMoveType.SELF, this.getDeltaMovement());
++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D));
+ } else {
+ super.travel(travelVector);
+ }
++
+ }
+
+ @Override
+@@ -228,6 +216,7 @@
+ this.setSwimming(false);
+ }
+ }
++
+ }
+
+ @Override
+@@ -236,12 +225,15 @@
+ }
+
+ protected boolean closeToNextPos() {
+- Path path = this.getNavigation().getPath();
+- if (path != null) {
+- BlockPos target = path.getTarget();
+- if (target != null) {
+- double d = this.distanceToSqr((double)target.getX(), (double)target.getY(), (double)target.getZ());
+- if (d < 4.0) {
++ Path pathentity = this.getNavigation().getPath();
++
++ if (pathentity != null) {
++ BlockPos blockposition = pathentity.getTarget();
++
++ if (blockposition != null) {
++ double d0 = this.distanceToSqr((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ());
++
++ if (d0 < 4.0D) {
+ return true;
+ }
+ }
+@@ -252,80 +244,72 @@
+
+ @Override
+ public void performRangedAttack(LivingEntity target, float distanceFactor) {
+- ThrownTrident thrownTrident = new ThrownTrident(this.level(), this, new ItemStack(Items.TRIDENT));
+- double d = target.getX() - this.getX();
+- double d1 = target.getY(0.3333333333333333) - thrownTrident.getY();
++ ThrownTrident entitythrowntrident = new ThrownTrident(this.level(), this, this.getItemInHand(net.minecraft.world.entity.projectile.ProjectileUtil.getWeaponHoldingHand(this, Items.TRIDENT))); // CraftBukkit - Use Trident in hand like skeletons (SPIGOT-7025)
++ double d0 = target.getX() - this.getX();
++ double d1 = target.getY(0.3333333333333333D) - entitythrowntrident.getY();
+ double d2 = target.getZ() - this.getZ();
+- double squareRoot = Math.sqrt(d * d + d2 * d2);
+- thrownTrident.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4));
++ double d3 = Math.sqrt(d0 * d0 + d2 * d2);
++
++ entitythrowntrident.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4));
+ this.playSound(SoundEvents.DROWNED_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
+- this.level().addFreshEntity(thrownTrident);
++ this.level().addFreshEntity(entitythrowntrident);
+ }
+
+ public void setSearchingForLand(boolean searchingForLand) {
+ this.searchingForLand = searchingForLand;
+ }
+
+- static class DrownedAttackGoal extends ZombieAttackGoal {
++ private static class DrownedMoveControl extends MoveControl {
++
+ private final Drowned drowned;
+
+- public DrownedAttackGoal(Drowned drowned, double speedModifier, boolean followingTargetEvenIfNotSeen) {
+- super(drowned, speedModifier, followingTargetEvenIfNotSeen);
++ public DrownedMoveControl(Drowned drowned) {
++ super(drowned);
+ this.drowned = drowned;
+ }
+
+ @Override
+- public boolean canUse() {
+- return super.canUse() && this.drowned.okTarget(this.drowned.getTarget());
+- }
++ public void tick() {
++ LivingEntity entityliving = this.drowned.getTarget();
+
+- @Override
+- public boolean canContinueToUse() {
+- return super.canContinueToUse() && this.drowned.okTarget(this.drowned.getTarget());
+- }
+- }
++ if (this.drowned.wantsToSwim() && this.drowned.isInWater()) {
++ if (entityliving != null && entityliving.getY() > this.drowned.getY() || this.drowned.searchingForLand) {
++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, 0.002D, 0.0D));
++ }
+
+- static class DrownedGoToBeachGoal extends MoveToBlockGoal {
+- private final Drowned drowned;
++ if (this.operation != MoveControl.Operation.MOVE_TO || this.drowned.getNavigation().isDone()) {
++ this.drowned.setSpeed(0.0F);
++ return;
++ }
+
+- public DrownedGoToBeachGoal(Drowned drowned, double speedModifier) {
+- super(drowned, speedModifier, 8, 2);
+- this.drowned = drowned;
+- }
++ double d0 = this.wantedX - this.drowned.getX();
++ double d1 = this.wantedY - this.drowned.getY();
++ double d2 = this.wantedZ - this.drowned.getZ();
++ double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
+
+- @Override
+- public boolean canUse() {
+- return super.canUse()
+- && !this.drowned.level().isDay()
+- && this.drowned.isInWater()
+- && this.drowned.getY() >= (double)(this.drowned.level().getSeaLevel() - 3);
+- }
++ d1 /= d3;
++ float f = (float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F;
+
+- @Override
+- public boolean canContinueToUse() {
+- return super.canContinueToUse();
+- }
++ this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F));
++ this.drowned.yBodyRot = this.drowned.getYRot();
++ float f1 = (float) (this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED));
++ float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1);
+
+- @Override
+- protected boolean isValidTarget(LevelReader level, BlockPos pos) {
+- BlockPos blockPos = pos.above();
+- return level.isEmptyBlock(blockPos) && level.isEmptyBlock(blockPos.above()) && level.getBlockState(pos).entityCanStandOn(level, pos, this.drowned);
+- }
++ this.drowned.setSpeed(f2);
++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add((double) f2 * d0 * 0.005D, (double) f2 * d1 * 0.1D, (double) f2 * d2 * 0.005D));
++ } else {
++ if (!this.drowned.onGround()) {
++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, -0.008D, 0.0D));
++ }
+
+- @Override
+- public void start() {
+- this.drowned.setSearchingForLand(false);
+- this.drowned.navigation = this.drowned.groundNavigation;
+- super.start();
+- }
++ super.tick();
++ }
+
+- @Override
+- public void stop() {
+- super.stop();
+ }
+ }
+
+- static class DrownedGoToWaterGoal extends Goal {
++ private static class DrownedGoToWaterGoal extends Goal {
++
+ private final PathfinderMob mob;
+ private double wantedX;
+ private double wantedY;
+@@ -337,7 +321,7 @@
+ this.mob = mob;
+ this.speedModifier = speedModifier;
+ this.level = mob.level();
+- this.setFlags(EnumSet.of(Goal.Flag.MOVE));
++ this.setFlags(EnumSet.of(Goal.Type.MOVE));
+ }
+
+ @Override
+@@ -347,13 +331,14 @@
+ } else if (this.mob.isInWater()) {
+ return false;
+ } else {
+- Vec3 waterPos = this.getWaterPos();
+- if (waterPos == null) {
++ Vec3 vec3d = this.getWaterPos();
++
++ if (vec3d == null) {
+ return false;
+ } else {
+- this.wantedX = waterPos.x;
+- this.wantedY = waterPos.y;
+- this.wantedZ = waterPos.z;
++ this.wantedX = vec3d.x;
++ this.wantedY = vec3d.y;
++ this.wantedZ = vec3d.z;
+ return true;
+ }
+ }
+@@ -371,13 +356,14 @@
+
+ @Nullable
+ private Vec3 getWaterPos() {
+- RandomSource random = this.mob.getRandom();
+- BlockPos blockPos = this.mob.blockPosition();
++ RandomSource randomsource = this.mob.getRandom();
++ BlockPos blockposition = this.mob.blockPosition();
+
+- for (int i = 0; i < 10; i++) {
+- BlockPos blockPos1 = blockPos.offset(random.nextInt(20) - 10, 2 - random.nextInt(8), random.nextInt(20) - 10);
+- if (this.level.getBlockState(blockPos1).is(Blocks.WATER)) {
+- return Vec3.atBottomCenterOf(blockPos1);
++ for (int i = 0; i < 10; ++i) {
++ BlockPos blockposition1 = blockposition.offset(randomsource.nextInt(20) - 10, 2 - randomsource.nextInt(8), randomsource.nextInt(20) - 10);
++
++ if (this.level.getBlockState(blockposition1).is(Blocks.WATER)) {
++ return Vec3.atBottomCenterOf(blockposition1);
+ }
+ }
+
+@@ -385,123 +371,141 @@
+ }
+ }
+
+- static class DrownedMoveControl extends MoveControl {
++ private static class DrownedTridentAttackGoal extends RangedAttackGoal {
++
+ private final Drowned drowned;
+
+- public DrownedMoveControl(Drowned mob) {
+- super(mob);
+- this.drowned = mob;
++ public DrownedTridentAttackGoal(RangedAttackMob rangedAttackMob, double speedModifier, int i, float attackInterval) {
++ super(rangedAttackMob, speedModifier, i, attackInterval);
++ this.drowned = (Drowned) rangedAttackMob;
+ }
+
+ @Override
+- public void tick() {
+- LivingEntity target = this.drowned.getTarget();
+- if (this.drowned.wantsToSwim() && this.drowned.isInWater()) {
+- if (target != null && target.getY() > this.drowned.getY() || this.drowned.searchingForLand) {
+- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, 0.002, 0.0));
+- }
++ public boolean canUse() {
++ return super.canUse() && this.drowned.getMainHandItem().is(Items.TRIDENT);
++ }
+
+- if (this.operation != MoveControl.Operation.MOVE_TO || this.drowned.getNavigation().isDone()) {
+- this.drowned.setSpeed(0.0F);
+- return;
+- }
++ @Override
++ public void start() {
++ super.start();
++ this.drowned.setAggressive(true);
++ this.drowned.startUsingItem(EnumHand.MAIN_HAND);
++ }
+
+- double d = this.wantedX - this.drowned.getX();
+- double d1 = this.wantedY - this.drowned.getY();
+- double d2 = this.wantedZ - this.drowned.getZ();
+- double squareRoot = Math.sqrt(d * d + d1 * d1 + d2 * d2);
+- d1 /= squareRoot;
+- float f = (float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F;
+- this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F));
+- this.drowned.yBodyRot = this.drowned.getYRot();
+- float f1 = (float)(this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED));
+- float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1);
+- this.drowned.setSpeed(f2);
+- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add((double)f2 * d * 0.005, (double)f2 * d1 * 0.1, (double)f2 * d2 * 0.005));
+- } else {
+- if (!this.drowned.onGround()) {
+- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, -0.008, 0.0));
+- }
++ @Override
++ public void stop() {
++ super.stop();
++ this.drowned.stopUsingItem();
++ this.drowned.setAggressive(false);
++ }
++ }
+
+- super.tick();
+- }
++ private static class DrownedAttackGoal extends ZombieAttackGoal {
++
++ private final Drowned drowned;
++
++ public DrownedAttackGoal(Drowned drowned, double speedModifier, boolean flag) {
++ super((Zombie) drowned, speedModifier, flag);
++ this.drowned = drowned;
+ }
++
++ @Override
++ public boolean canUse() {
++ return super.canUse() && this.drowned.okTarget(this.drowned.getTarget());
++ }
++
++ @Override
++ public boolean canContinueToUse() {
++ return super.canContinueToUse() && this.drowned.okTarget(this.drowned.getTarget());
++ }
+ }
+
+- static class DrownedSwimUpGoal extends Goal {
++ private static class DrownedGoToBeachGoal extends MoveToBlockGoal {
++
+ private final Drowned drowned;
+- private final double speedModifier;
+- private final int seaLevel;
+- private boolean stuck;
+
+- public DrownedSwimUpGoal(Drowned drowned, double speedModifier, int seaLevel) {
++ public DrownedGoToBeachGoal(Drowned drowned, double speedModifier) {
++ super(drowned, speedModifier, 8, 2);
+ this.drowned = drowned;
+- this.speedModifier = speedModifier;
+- this.seaLevel = seaLevel;
+ }
+
+ @Override
+ public boolean canUse() {
+- return !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() < (double)(this.seaLevel - 2);
++ return super.canUse() && !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() >= (double) (this.drowned.level().getSeaLevel() - 3);
+ }
+
+ @Override
+ public boolean canContinueToUse() {
+- return this.canUse() && !this.stuck;
++ return super.canContinueToUse();
+ }
+
+ @Override
+- public void tick() {
+- if (this.drowned.getY() < (double)(this.seaLevel - 1) && (this.drowned.getNavigation().isDone() || this.drowned.closeToNextPos())) {
+- Vec3 posTowards = DefaultRandomPos.getPosTowards(
+- this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double)(this.seaLevel - 1), this.drowned.getZ()), (float) (Math.PI / 2)
+- );
+- if (posTowards == null) {
+- this.stuck = true;
+- return;
+- }
++ protected boolean isValidTarget(LevelReader level, BlockPos pos) {
++ BlockPos blockposition1 = pos.above();
+
+- this.drowned.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier);
+- }
++ return level.isEmptyBlock(blockposition1) && level.isEmptyBlock(blockposition1.above()) ? level.getBlockState(pos).entityCanStandOn(level, pos, this.drowned) : false;
+ }
+
+ @Override
+ public void start() {
+- this.drowned.setSearchingForLand(true);
+- this.stuck = false;
++ this.drowned.setSearchingForLand(false);
++ this.drowned.navigation = this.drowned.groundNavigation;
++ super.start();
+ }
+
+ @Override
+ public void stop() {
+- this.drowned.setSearchingForLand(false);
++ super.stop();
+ }
+ }
+
+- static class DrownedTridentAttackGoal extends RangedAttackGoal {
++ private static class DrownedSwimUpGoal extends Goal {
++
+ private final Drowned drowned;
++ private final double speedModifier;
++ private final int seaLevel;
++ private boolean stuck;
+
+- public DrownedTridentAttackGoal(RangedAttackMob rangedAttackMob, double speedModifier, int attackInterval, float attackRadius) {
+- super(rangedAttackMob, speedModifier, attackInterval, attackRadius);
+- this.drowned = (Drowned)rangedAttackMob;
++ public DrownedSwimUpGoal(Drowned drowned, double speedModifier, int i) {
++ this.drowned = drowned;
++ this.speedModifier = speedModifier;
++ this.seaLevel = i;
+ }
+
+ @Override
+ public boolean canUse() {
+- return super.canUse() && this.drowned.getMainHandItem().is(Items.TRIDENT);
++ return !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() < (double) (this.seaLevel - 2);
+ }
+
+ @Override
++ public boolean canContinueToUse() {
++ return this.canUse() && !this.stuck;
++ }
++
++ @Override
++ public void tick() {
++ if (this.drowned.getY() < (double) (this.seaLevel - 1) && (this.drowned.getNavigation().isDone() || this.drowned.closeToNextPos())) {
++ Vec3 vec3d = DefaultRandomPos.getPosTowards(this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double) (this.seaLevel - 1), this.drowned.getZ()), 1.5707963705062866D);
++
++ if (vec3d == null) {
++ this.stuck = true;
++ return;
++ }
++
++ this.drowned.getNavigation().moveTo(vec3d.x, vec3d.y, vec3d.z, this.speedModifier);
++ }
++
++ }
++
++ @Override
+ public void start() {
+- super.start();
+- this.drowned.setAggressive(true);
+- this.drowned.startUsingItem(InteractionHand.MAIN_HAND);
++ this.drowned.setSearchingForLand(true);
++ this.stuck = false;
+ }
+
+ @Override
+ public void stop() {
+- super.stop();
+- this.drowned.stopUsingItem();
+- this.drowned.setAggressive(false);
++ this.drowned.setSearchingForLand(false);
+ }
+ }
+ }