-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
One NavigationSystem per server, one controller per mob, and you call tick().
NavigationSystem navigation = NavigationSystem.create(); // owns the workers
EntityNavigationController controller = navigation.controller(mob);
controller.moveTo(destination);
controller.tick(); // every tick, from the entity/instance tick thread
controller.close(); // when the mob despawns
navigation.close(); // at shutdownA mob that never moves is almost always a controller that is never ticked. Nothing ticks it for you.
moveTo is cheap enough to call every tick. The mob keeps walking its current
route until the replacement lands, so a chased target never stands still.
public void update(long time) {
controller.moveTo(player.getPosition()); // fine every tick
controller.tick();
}switch (controller.state()) {
case COMPUTING, FOLLOWING -> {} // working on it
case COMPLETED -> onArrived(mob);
case PARTIAL -> { // ran out short of the goal
if (controller.targetUnreachable()) chooseAnotherGoal(mob);
}
case STUCK -> unwedge(mob); // cannot walk the route it has
case IDLE, FAILED, CANCELLED -> {}
}PARTIAL and STUCK are different problems:
-
PARTIAL+targetUnreachable()— no further search reaches that goal. Pick a new one. -
STUCK— the follower could not walk a route it was given. Unwedge the mob.
A follower that reported targetUnreachable() is never later relabelled
STUCK.
Polling like this works, but you have to remember what you saw last tick,
because COMPLETED persists. Reacting to Navigation does it for you.
navigation.controller(mob, 0.18); // blocks per tickOr set the default for every controller the system makes:
NavigationSystem navigation = NavigationSystem.builder()
.movementPerTick(0.2)
.parallelism(8)
.queueCapacity(256)
.build();
NavigationOptions options = navigation.options(); // reads it all backDefaults are sized for a normal server: one controller search per worker, with newest-per-mob intents held in a bounded scheduler so a crowd never becomes an executor queue. See Running at Scale before changing them.
- Reacting to Navigation — stop polling
- Seeing the Path — watch what it actually chose
Start here
Shaping behaviour
Going deeper
Reference