I'm trying to write an AI Goal for an entity to move towards its target on each tick (with quite a few restrictions on when, which is why I need a new goal). It seemed to be working when I also added a WaterAvoidingRandomWalkingGoal, but I don't want the entity to move around randomly anymore, so I removed that. My code overrides the canUse function to determine whether or not it should start moving towards the target, and that ends with creating a path to the target, which always returns NULL, so nothing happens. Here's the relevant functions:
public FloatingEyesGoal(EntityFloatingEyes e, double speed) {
this.entity = e;
this.random = e.getRandom();
this.speed = speed;
this.setFlags(EnumSet.of(Flag.LOOK, Flag.MOVE, Flag.TARGET));
this.entity.getNavigation().setCanFloat(true);
}
@Override
public boolean canUse() {
LivingEntity target = this.entity.getTarget();
if (target == null || !target.isAlive() || !isFacingTargetBack())
return false;
setTargetPos(target);
this.path = this.entity.getNavigation().createPath(target, 0);
// Logging this.path == null prints "true", and this.entity.getNavigation() == null prints "false"
return this.path != null || isInRange(target);
}
@Override
public boolean canContinueToUse() {
LivingEntity target = this.entity.getTarget();
if (target == null || !target.isAlive() || !isFacingTargetBack())
return false;
return !this.entity.getNavigation().isDone();
}
@Override
public void start() {
this.entity.getNavigation().moveTo(this.path, this.speed);
this.entity.setAggressive(true);
this.ticksToMove = 0;
}
@Override
public void stop() {
LivingEntity target = this.entity.getTarget();
if (!EntityPredicates.NO_CREATIVE_OR_SPECTATOR.test(target)) {
this.entity.setTarget(null);
}
this.entity.setAggressive(false);
this.entity.getNavigation().stop();
this.targetPosX = 0.0D;
this.targetPosY = 0.0D;
this.targetPosZ = 0.0D;
}
@Override
public void tick() {
// Look at target
LivingEntity target = this.entity.getTarget();
this.entity.getLookControl().setLookAt(target, 32.0F, 32.0F);
setTargetPos(target);
final double distance = this.entity.distanceToSqr(this.targetPosX, this.targetPosY, this.targetPosZ);
this.ticksToMove--;
LilSpooks.LOGGER.info(this.ticksToMove);
if (this.ticksToMove <= 0
&& this.entity.getSensing().canSee(target)
&& target.distanceToSqr(this.targetPosX, this.targetPosY, this.targetPosZ) >= 1.0D) {
this.ticksToMove = 5 + this.random.nextInt(8);
// Add extra time if eyes can't move to hopefully wait enough to try again (1 second).
this.path = this.entity.getNavigation().createPath(new BlockPos(this.targetPosX, this.targetPosY, this.targetPosZ), 0);
// Logging this.path == null returns "true" here as well
if (!this.entity.getNavigation().moveTo(this.path, this.speed)) {
this.ticksToMove += 20;
}
}
this.attackTick = Math.max(this.attackTick - 1, 0);
this.attemptAttack(target, distance);
}
protected void setTargetPos(LivingEntity target) {
this.targetPosX = target.getX();
this.targetPosY = target.getBoundingBox().minY;
this.targetPosZ = target.getZ();
}
I have tried multiple ways of invoking createPath, I tried setting the moveControl of the entity with the goal to a new FlyingMovementController, and I've looked at how the createPath function works (though I can't figure out how to do a live debugging session, so I couldn't set a breakpoint at that code which would tell me exactly what causes it to be null). I tried my best to work through this for a few hours but I can't seem to figure it out. Any help is appreciated.