diff options
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.patch | 580 |
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); + } + } + } |