2023-03-14 20:37:05 +01:00
|
|
|
package net.citizensnpcs.nms.v1_19_R3.util;
|
2022-06-08 05:58:22 +02:00
|
|
|
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
import java.util.stream.Stream;
|
2023-02-22 17:06:13 +01:00
|
|
|
|
2022-06-08 05:58:22 +02:00
|
|
|
import com.google.common.collect.ImmutableSet;
|
2023-02-22 17:06:13 +01:00
|
|
|
|
2022-10-01 20:44:06 +02:00
|
|
|
import net.citizensnpcs.Settings;
|
2023-03-14 20:37:05 +01:00
|
|
|
import net.citizensnpcs.nms.v1_19_R3.entity.EntityHumanNPC;
|
2022-06-08 05:58:22 +02:00
|
|
|
import net.minecraft.core.BlockPos;
|
|
|
|
import net.minecraft.core.Vec3i;
|
|
|
|
import net.minecraft.tags.BlockTags;
|
|
|
|
import net.minecraft.util.Mth;
|
|
|
|
import net.minecraft.world.entity.Entity;
|
|
|
|
import net.minecraft.world.entity.EntityType;
|
|
|
|
import net.minecraft.world.entity.Mob;
|
|
|
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
|
|
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
|
|
|
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
|
|
|
import net.minecraft.world.level.Level;
|
|
|
|
import net.minecraft.world.level.PathNavigationRegion;
|
|
|
|
import net.minecraft.world.level.block.Blocks;
|
|
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
|
|
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
|
|
|
import net.minecraft.world.level.pathfinder.Node;
|
|
|
|
import net.minecraft.world.level.pathfinder.NodeEvaluator;
|
|
|
|
import net.minecraft.world.level.pathfinder.Path;
|
|
|
|
import net.minecraft.world.level.pathfinder.PathFinder;
|
|
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
|
|
|
|
public class PlayerNavigation extends PathNavigation {
|
|
|
|
private boolean avoidSun;
|
|
|
|
private final AttributeInstance followRange;
|
|
|
|
protected boolean hasDelayedRecomputation;
|
|
|
|
private boolean isStuck;
|
|
|
|
protected int lastStuckCheck;
|
|
|
|
protected Vec3 lastStuckCheckPos = Vec3.ZERO;
|
|
|
|
protected long lastTimeoutCheck;
|
|
|
|
protected final Level level;
|
|
|
|
protected float maxDistanceToWaypoint = 0.5F;
|
|
|
|
private float maxVisitedNodesMultiplier = 1.0F;
|
2023-03-14 20:37:05 +01:00
|
|
|
private final EntityHumanNPC mob;
|
2022-06-08 05:58:22 +02:00
|
|
|
protected PlayerNodeEvaluator nodeEvaluator;
|
|
|
|
protected Path path;
|
|
|
|
private final PlayerPathfinder pathFinder;
|
|
|
|
private int reachRange;
|
|
|
|
protected double speedModifier;
|
|
|
|
private BlockPos targetPos;
|
|
|
|
protected int tick;
|
|
|
|
protected long timeLastRecompute;
|
|
|
|
protected Vec3i timeoutCachedNode = Vec3i.ZERO;
|
|
|
|
protected double timeoutLimit;
|
|
|
|
protected long timeoutTimer;
|
|
|
|
|
|
|
|
public PlayerNavigation(EntityHumanNPC entityinsentient, Level world) {
|
|
|
|
super(getDummyInsentient(entityinsentient, world), world);
|
|
|
|
this.mob = entityinsentient;
|
|
|
|
this.level = world;
|
|
|
|
this.followRange = entityinsentient.getAttribute(Attributes.FOLLOW_RANGE);
|
|
|
|
this.nodeEvaluator = new PlayerNodeEvaluator();
|
|
|
|
this.nodeEvaluator.setCanPassDoors(true);
|
2022-10-01 20:44:06 +02:00
|
|
|
this.pathFinder = new PlayerPathfinder(this.nodeEvaluator, Settings.Setting.MAXIMUM_VISITED_NODES.asInt());
|
2022-06-08 05:58:22 +02:00
|
|
|
this.setRange(24);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean canFloat() {
|
|
|
|
return this.nodeEvaluator.canFloat();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected boolean canMoveDirectly(Vec3 var0, Vec3 var1) {
|
|
|
|
return false;
|
|
|
|
/*
|
|
|
|
int var5 = Mth.floor(var0.x);
|
|
|
|
int var6 = Mth.floor(var0.z);
|
|
|
|
double var7 = var1.x - var0.x;
|
|
|
|
double var9 = var1.z - var0.z;
|
|
|
|
double var11 = var7 * var7 + var9 * var9;
|
|
|
|
if (var11 < 1.0E-8D)
|
|
|
|
return false;
|
|
|
|
double var13 = 1.0D / Math.sqrt(var11);
|
|
|
|
var7 *= var13;
|
|
|
|
var9 *= var13;
|
|
|
|
var2 += 2;
|
|
|
|
var4 += 2;
|
|
|
|
if (!canWalkOn(var5, Mth.floor(var0.y), var6, var2, var3, var4, var0, var7, var9))
|
|
|
|
return false;
|
|
|
|
var2 -= 2;
|
|
|
|
var4 -= 2;
|
|
|
|
double var15 = 1.0D / Math.abs(var7);
|
|
|
|
double var17 = 1.0D / Math.abs(var9);
|
|
|
|
double var19 = var5 - var0.x;
|
|
|
|
double var21 = var6 - var0.z;
|
|
|
|
if (var7 >= 0.0D)
|
|
|
|
var19++;
|
|
|
|
if (var9 >= 0.0D)
|
|
|
|
var21++;
|
|
|
|
var19 /= var7;
|
|
|
|
var21 /= var9;
|
|
|
|
int var23 = (var7 < 0.0D) ? -1 : 1;
|
|
|
|
int var24 = (var9 < 0.0D) ? -1 : 1;
|
|
|
|
int var25 = Mth.floor(var1.x);
|
|
|
|
int var26 = Mth.floor(var1.z);
|
|
|
|
int var27 = var25 - var5;
|
|
|
|
int var28 = var26 - var6;
|
|
|
|
while (var27 * var23 > 0 || var28 * var24 > 0) {
|
|
|
|
if (var19 < var21) {
|
|
|
|
var19 += var15;
|
|
|
|
var5 += var23;
|
|
|
|
var27 = var25 - var5;
|
|
|
|
} else {
|
|
|
|
var21 += var17;
|
|
|
|
var6 += var24;
|
|
|
|
var28 = var26 - var6;
|
|
|
|
}
|
|
|
|
if (!canWalkOn(var5, Mth.floor(var0.y), var6, var2, var3, var4, var0, var7, var9))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;*/
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canOpenDoors() {
|
|
|
|
return this.nodeEvaluator.canPassDoors();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canPassDoors() {
|
|
|
|
return this.nodeEvaluator.canPassDoors();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected boolean canUpdatePath() {
|
|
|
|
return (this.mob.isOnGround() || isInLiquid() || this.mob.isPassenger());
|
|
|
|
}
|
2023-02-22 17:00:47 +01:00
|
|
|
|
2022-06-08 05:58:22 +02:00
|
|
|
/*
|
|
|
|
private boolean canWalkAbove(int var0, int var1, int var2, int var3, int var4, int var5, Vec3 var6, double var7,
|
|
|
|
double var9) {
|
|
|
|
for (BlockPos var12 : BlockPos.betweenClosed(new BlockPos(var0, var1, var2),
|
|
|
|
new BlockPos(var0 + var3 - 1, var1 + var4 - 1, var2 + var5 - 1))) {
|
|
|
|
double var13 = var12.getX() + 0.5D - var6.x;
|
|
|
|
double var15 = var12.getZ() + 0.5D - var6.z;
|
|
|
|
if (var13 * var7 + var15 * var9 < 0.0D)
|
|
|
|
continue;
|
|
|
|
if (!this.level.getBlockState(var12).isPathfindable(this.level, var12, PathComputationType.LAND))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2023-03-12 15:29:41 +01:00
|
|
|
|
2022-06-08 05:58:22 +02:00
|
|
|
private boolean canWalkOn(int var0, int var1, int var2, int var3, int var4, int var5, Vec3 var6, double var7,
|
|
|
|
double var9) {
|
|
|
|
int var11 = var0 - var3 / 2;
|
|
|
|
int var12 = var2 - var5 / 2;
|
|
|
|
if (!canWalkAbove(var11, var1, var12, var3, var4, var5, var6, var7, var9))
|
|
|
|
return false;
|
|
|
|
for (int var13 = var11; var13 < var11 + var3; var13++) {
|
|
|
|
for (int var14 = var12; var14 < var12 + var5; var14++) {
|
|
|
|
double var15 = var13 + 0.5D - var6.x;
|
|
|
|
double var17 = var14 + 0.5D - var6.z;
|
|
|
|
if (var15 * var7 + var17 * var9 >= 0.0D) {
|
|
|
|
BlockPathTypes var19 = this.nodeEvaluator.getBlockPathType(this.level, var13, var1 - 1, var14,
|
|
|
|
this.mob, var3, var4, var5, true, true);
|
|
|
|
if (!hasValidPathType(var19))
|
|
|
|
return false;
|
|
|
|
var19 = this.nodeEvaluator.getBlockPathType(this.level, var13, var1, var14, this.mob, var3, var4,
|
|
|
|
var5, true, true);
|
|
|
|
float var20 = this.mob.getPathfindingMalus(var19);
|
|
|
|
if (var20 < 0.0F || var20 >= 8.0F)
|
|
|
|
return false;
|
|
|
|
if (var19 == BlockPathTypes.DAMAGE_FIRE || var19 == BlockPathTypes.DANGER_FIRE
|
|
|
|
|| var19 == BlockPathTypes.DAMAGE_OTHER)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2023-02-22 17:00:47 +01:00
|
|
|
}*/ @Override
|
2022-06-08 05:58:22 +02:00
|
|
|
public Path createPath(BlockPos var0, int var1) {
|
|
|
|
if (this.level.getBlockState(var0).isAir()) {
|
|
|
|
BlockPos var2 = var0.below();
|
|
|
|
while (var2.getY() > this.level.getMinBuildHeight() && this.level.getBlockState(var2).isAir())
|
|
|
|
var2 = var2.below();
|
|
|
|
if (var2.getY() > this.level.getMinBuildHeight())
|
|
|
|
return supercreatePath(var2.above(), var1);
|
|
|
|
while (var2.getY() < this.level.getMaxBuildHeight() && this.level.getBlockState(var2).isAir())
|
|
|
|
var2 = var2.above();
|
|
|
|
var0 = var2;
|
|
|
|
}
|
|
|
|
if (this.level.getBlockState(var0).getMaterial().isSolid()) {
|
|
|
|
BlockPos var2 = var0.above();
|
|
|
|
while (var2.getY() < this.level.getMaxBuildHeight()
|
|
|
|
&& this.level.getBlockState(var2).getMaterial().isSolid())
|
|
|
|
var2 = var2.above();
|
|
|
|
return supercreatePath(var2, var1);
|
|
|
|
}
|
|
|
|
return supercreatePath(var0, var1);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Path createPath(BlockPos var0, int var1, int var2) {
|
|
|
|
return createPath(ImmutableSet.of(var0), 8, false, var1, var2);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Path createPath(Entity var0, int var1) {
|
|
|
|
return createPath(var0.blockPosition(), var1);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Path createPath(Set<BlockPos> var0, int var1) {
|
|
|
|
return createPath(var0, 8, false, var1);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Path createPath(Set<BlockPos> var0, int var1, boolean var2, int var3) {
|
|
|
|
return createPath(var0, var1, var2, var3, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Path createPath(Set<BlockPos> var0, int var1, boolean var2, int var3, float var4) {
|
|
|
|
if (var0.isEmpty() || (this.mob.getY() < this.level.getMinBuildHeight()) || !canUpdatePath())
|
|
|
|
return null;
|
|
|
|
if (this.path != null && !this.path.isDone() && var0.contains(this.targetPos))
|
|
|
|
return this.path;
|
2023-03-14 20:37:05 +01:00
|
|
|
this.level.getProfiler().push("pathfind");
|
2022-06-08 05:58:22 +02:00
|
|
|
BlockPos var5 = var2 ? this.mob.blockPosition().above() : this.mob.blockPosition();
|
|
|
|
int var6 = (int) (var4 + var1);
|
|
|
|
PathNavigationRegion var7 = new PathNavigationRegion(this.level, var5.offset(-var6, -var6, -var6),
|
|
|
|
var5.offset(var6, var6, var6));
|
|
|
|
Path var8 = this.pathFinder.findPath(var7, this.mob, var0, var4, var3, this.maxVisitedNodesMultiplier);
|
2023-03-14 20:37:05 +01:00
|
|
|
this.level.getProfiler().pop();
|
2022-06-08 05:58:22 +02:00
|
|
|
if (var8 != null && var8.getTarget() != null) {
|
|
|
|
this.targetPos = var8.getTarget();
|
|
|
|
this.reachRange = var3;
|
2023-03-14 20:37:05 +01:00
|
|
|
this.resetStuckTimeout();
|
2022-06-08 05:58:22 +02:00
|
|
|
}
|
2023-03-14 20:37:05 +01:00
|
|
|
|
2022-06-08 05:58:22 +02:00
|
|
|
return var8;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Path createPath(Stream<BlockPos> var0, int var1) {
|
|
|
|
return createPath(var0.collect(Collectors.<BlockPos> toSet()), 8, false, var1);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected PathFinder createPathFinder(int paramInt) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void doStuckDetection(Vec3 var0) {
|
|
|
|
if (this.tick - this.lastStuckCheck > 100) {
|
|
|
|
if (var0.distanceToSqr(this.lastStuckCheckPos) < 2.25D) {
|
|
|
|
this.isStuck = true;
|
|
|
|
stop();
|
|
|
|
} else {
|
|
|
|
this.isStuck = false;
|
|
|
|
}
|
|
|
|
this.lastStuckCheck = this.tick;
|
|
|
|
this.lastStuckCheckPos = var0;
|
|
|
|
}
|
|
|
|
if (this.path != null && !this.path.isDone()) {
|
|
|
|
BlockPos blockPos = this.path.getNextNodePos();
|
|
|
|
if (blockPos.equals(this.timeoutCachedNode)) {
|
|
|
|
this.timeoutTimer += System.currentTimeMillis() - this.lastTimeoutCheck;
|
|
|
|
} else {
|
|
|
|
this.timeoutCachedNode = blockPos;
|
|
|
|
double var2 = var0.distanceTo(Vec3.atBottomCenterOf(this.timeoutCachedNode));
|
|
|
|
this.timeoutLimit = (this.mob.getSpeed() > 0.0F) ? (var2 / this.mob.getSpeed() * 1000.0D) : 0.0D;
|
|
|
|
}
|
|
|
|
if (this.timeoutLimit > 0.0D && this.timeoutTimer > this.timeoutLimit * 3.0D)
|
|
|
|
timeoutPath();
|
|
|
|
this.lastTimeoutCheck = System.currentTimeMillis();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void followThePath() {
|
|
|
|
Vec3 var0 = getTempMobPos();
|
|
|
|
this.maxDistanceToWaypoint = (this.mob.getBbWidth() > 0.75F) ? (this.mob.getBbWidth() / 2.0F)
|
|
|
|
: (0.75F - this.mob.getBbWidth() / 2.0F);
|
|
|
|
BlockPos blockPos = this.path.getNextNodePos();
|
2022-08-22 16:51:33 +02:00
|
|
|
double var2 = Math.abs(this.mob.getX() - (blockPos.getX() + 0.5D));
|
2022-06-08 05:58:22 +02:00
|
|
|
double var4 = Math.abs(this.mob.getY() - blockPos.getY());
|
2022-08-22 16:51:33 +02:00
|
|
|
double var6 = Math.abs(this.mob.getZ() - (blockPos.getZ() + 0.5D));
|
2022-06-08 05:58:22 +02:00
|
|
|
boolean var8 = (var2 < this.maxDistanceToWaypoint && var6 < this.maxDistanceToWaypoint && var4 < 1.0D);
|
|
|
|
if (var8 || (this.mob.canCutCorner((this.path.getNextNode()).type) && shouldTargetNextNodeInDirection(var0)))
|
|
|
|
this.path.advance();
|
|
|
|
doStuckDetection(var0);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getMaxDistanceToWaypoint() {
|
|
|
|
return this.maxDistanceToWaypoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public NodeEvaluator getNodeEvaluator() {
|
|
|
|
return this.nodeEvaluator;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Path getPath() {
|
|
|
|
return this.path;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Path getPathEntity() {
|
|
|
|
return this.path;
|
|
|
|
}
|
|
|
|
|
|
|
|
private int getSurfaceY() {
|
2023-03-14 20:37:05 +01:00
|
|
|
if (this.mob.isInWater() && this.canFloat()) {
|
|
|
|
int var0 = this.mob.getBlockY();
|
|
|
|
BlockState var1 = this.level.getBlockState(BlockPos.containing(this.mob.getX(), var0, this.mob.getZ()));
|
|
|
|
int var2 = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (!var1.is(Blocks.WATER)) {
|
|
|
|
return var0;
|
|
|
|
}
|
|
|
|
|
|
|
|
++var0;
|
|
|
|
var1 = this.level.getBlockState(BlockPos.containing(this.mob.getX(), var0, this.mob.getZ()));
|
|
|
|
++var2;
|
|
|
|
} while (var2 <= 16);
|
|
|
|
|
|
|
|
return this.mob.getBlockY();
|
|
|
|
} else {
|
|
|
|
return Mth.floor(this.mob.getY() + 0.5);
|
2022-06-08 05:58:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public BlockPos getTargetPos() {
|
|
|
|
return this.targetPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Vec3 getTempMobPos() {
|
|
|
|
return new Vec3(this.mob.getX(), getSurfaceY(), this.mob.getZ());
|
|
|
|
}
|
|
|
|
|
|
|
|
protected boolean hasValidPathType(BlockPathTypes var0) {
|
2023-03-14 20:37:05 +01:00
|
|
|
if (var0 == BlockPathTypes.WATER) {
|
2022-06-08 05:58:22 +02:00
|
|
|
return false;
|
2023-03-14 20:37:05 +01:00
|
|
|
} else if (var0 == BlockPathTypes.LAVA) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return var0 != BlockPathTypes.OPEN;
|
|
|
|
}
|
2022-06-08 05:58:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isDone() {
|
|
|
|
return (this.path == null || this.path.isDone());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected boolean isInLiquid() {
|
|
|
|
return (this.mob.isInWaterOrBubble() || this.mob.isInLava());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isInProgress() {
|
|
|
|
return !isDone();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isStableDestination(BlockPos var0) {
|
|
|
|
BlockPos var1 = var0.below();
|
|
|
|
return this.level.getBlockState(var1).isSolidRender(this.level, var1);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isStuck() {
|
|
|
|
return this.isStuck;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean moveTo(double var0, double var2, double var4, double var6) {
|
2023-03-14 20:37:05 +01:00
|
|
|
return moveTo(createPath(BlockPos.containing(var0, var2, var4), 1), var6);
|
2022-06-08 05:58:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean moveTo(Entity var0, double var1) {
|
|
|
|
Path var3 = createPath(var0, 1);
|
|
|
|
return (var3 != null && moveTo(var3, var1));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean moveTo(Path var0, double var1) {
|
|
|
|
if (var0 == null) {
|
|
|
|
this.path = null;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!var0.sameAs(this.path))
|
|
|
|
this.path = var0;
|
|
|
|
if (isDone())
|
|
|
|
return false;
|
|
|
|
trimPath();
|
|
|
|
if (this.path.getNodeCount() <= 0)
|
|
|
|
return false;
|
|
|
|
this.speedModifier = var1;
|
|
|
|
Vec3 var3 = getTempMobPos();
|
|
|
|
this.lastStuckCheck = this.tick;
|
|
|
|
this.lastStuckCheckPos = var3;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void recomputePath() {
|
|
|
|
if (this.level.getGameTime() - this.timeLastRecompute > 20L) {
|
|
|
|
if (this.targetPos != null) {
|
|
|
|
this.path = null;
|
|
|
|
this.path = createPath(this.targetPos, this.reachRange);
|
|
|
|
this.timeLastRecompute = this.level.getGameTime();
|
|
|
|
this.hasDelayedRecomputation = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.hasDelayedRecomputation = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void resetMaxVisitedNodesMultiplier() {
|
|
|
|
this.maxVisitedNodesMultiplier = 1.0F;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void resetStuckTimeout() {
|
|
|
|
this.timeoutCachedNode = Vec3i.ZERO;
|
|
|
|
this.timeoutTimer = 0L;
|
|
|
|
this.timeoutLimit = 0.0D;
|
|
|
|
this.isStuck = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setAvoidSun(boolean var0) {
|
|
|
|
this.avoidSun = var0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setCanFloat(boolean var0) {
|
|
|
|
this.nodeEvaluator.setCanFloat(var0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setCanOpenDoors(boolean var0) {
|
|
|
|
this.nodeEvaluator.setCanOpenDoors(var0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setCanPassDoors(boolean var0) {
|
|
|
|
this.nodeEvaluator.setCanPassDoors(var0);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setMaxVisitedNodesMultiplier(float var0) {
|
|
|
|
this.maxVisitedNodesMultiplier = var0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setRange(float pathfindingRange) {
|
|
|
|
this.followRange.setBaseValue(pathfindingRange);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setSpeedModifier(double var0) {
|
|
|
|
this.speedModifier = var0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean shouldRecomputePath(BlockPos var0) {
|
|
|
|
if (this.hasDelayedRecomputation) {
|
|
|
|
return false;
|
|
|
|
} else if (this.path != null && !this.path.isDone() && this.path.getNodeCount() != 0) {
|
|
|
|
Node var1 = this.path.getEndNode();
|
|
|
|
Vec3 var2 = new Vec3((var1.x + this.mob.getX()) / 2.0D, (var1.y + this.mob.getY()) / 2.0D,
|
|
|
|
(var1.z + this.mob.getZ()) / 2.0D);
|
|
|
|
return var0.closerToCenterThan(var2, this.path.getNodeCount() - this.path.getNextNodeIndex());
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean shouldTargetNextNodeInDirection(Vec3 var0) {
|
|
|
|
if (this.path.getNextNodeIndex() + 1 >= this.path.getNodeCount())
|
|
|
|
return false;
|
|
|
|
Vec3 var1 = Vec3.atBottomCenterOf(this.path.getNextNodePos());
|
|
|
|
if (!var0.closerThan(var1, 2.0D))
|
|
|
|
return false;
|
|
|
|
Vec3 var2 = Vec3.atBottomCenterOf(this.path.getNodePos(this.path.getNextNodeIndex() + 1));
|
|
|
|
Vec3 var3 = var2.subtract(var1);
|
|
|
|
Vec3 var4 = var0.subtract(var1);
|
|
|
|
return (var3.dot(var4) > 0.0D);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void stop() {
|
|
|
|
this.path = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Path supercreatePath(BlockPos var0, int var1) {
|
|
|
|
return createPath(ImmutableSet.of(var0), 8, false, var1);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void supertrimPath() {
|
|
|
|
if (this.path == null)
|
|
|
|
return;
|
2023-03-14 20:37:05 +01:00
|
|
|
for (int var0 = 0; var0 < this.path.getNodeCount(); ++var0) {
|
2022-06-08 05:58:22 +02:00
|
|
|
Node var1 = this.path.getNode(var0);
|
2023-03-14 20:37:05 +01:00
|
|
|
Node var2 = var0 + 1 < this.path.getNodeCount() ? this.path.getNode(var0 + 1) : null;
|
2022-06-08 05:58:22 +02:00
|
|
|
BlockState var3 = this.level.getBlockState(new BlockPos(var1.x, var1.y, var1.z));
|
|
|
|
if (var3.is(BlockTags.CAULDRONS)) {
|
|
|
|
this.path.replaceNode(var0, var1.cloneAndMove(var1.x, var1.y + 1, var1.z));
|
2023-03-14 20:37:05 +01:00
|
|
|
if (var2 != null && var1.y >= var2.y) {
|
2022-06-08 05:58:22 +02:00
|
|
|
this.path.replaceNode(var0 + 1, var1.cloneAndMove(var2.x, var1.y + 1, var2.z));
|
2023-03-14 20:37:05 +01:00
|
|
|
}
|
2022-06-08 05:58:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void tick() {
|
|
|
|
this.tick++;
|
|
|
|
if (this.hasDelayedRecomputation) {
|
|
|
|
recomputePath();
|
|
|
|
}
|
|
|
|
if (isDone())
|
|
|
|
return;
|
|
|
|
if (canUpdatePath()) {
|
|
|
|
followThePath();
|
|
|
|
} else if (this.path != null && !this.path.isDone()) {
|
|
|
|
Vec3 vec31 = getTempMobPos();
|
|
|
|
Vec3 vec32 = this.path.getNextEntityPos(this.mob);
|
|
|
|
if (vec31.y > vec32.y && !this.mob.isOnGround() && Mth.floor(vec31.x) == Mth.floor(vec32.x)
|
|
|
|
&& Mth.floor(vec31.z) == Mth.floor(vec32.z))
|
|
|
|
this.path.advance();
|
|
|
|
}
|
|
|
|
if (isDone())
|
|
|
|
return;
|
|
|
|
Vec3 var0 = this.path.getNextEntityPos(this.mob);
|
2023-03-14 20:37:05 +01:00
|
|
|
this.mob.getMoveControl().setWantedPosition(var0.x, this.getGroundY(var0), var0.z, this.speedModifier);
|
2022-06-08 05:58:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void timeoutPath() {
|
|
|
|
resetStuckTimeout();
|
|
|
|
stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void trimPath() {
|
|
|
|
supertrimPath();
|
|
|
|
if (this.avoidSun) {
|
2023-03-14 20:37:05 +01:00
|
|
|
if (this.level.canSeeSky(BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()))) {
|
2022-06-08 05:58:22 +02:00
|
|
|
return;
|
2023-03-14 20:37:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int var0 = 0; var0 < this.path.getNodeCount(); ++var0) {
|
2022-06-08 05:58:22 +02:00
|
|
|
Node var1 = this.path.getNode(var0);
|
|
|
|
if (this.level.canSeeSky(new BlockPos(var1.x, var1.y, var1.z))) {
|
|
|
|
this.path.truncateNodes(var0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static Mob getDummyInsentient(EntityHumanNPC from, Level world) {
|
|
|
|
return new Mob(EntityType.VILLAGER, world) {
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|