-
Notifications
You must be signed in to change notification settings - Fork 0
Planning Without the Follower
To feed your own movement system instead of the built-in follower.
PathResult path = new DiscreteGroundPathfinder().findPath(
instance,
entity.getPosition(),
destination,
entity.getBoundingBox(),
MobTraversalProfile.DEFAULT,
GroundSearchLimits.ofPathLength(64),
GroundCapabilities.STANDARD,
SearchControl.NONE);
if (path.found()) {
for (PathNode node : path.nodes()) feed(node.asVec());
}PathNode positions are the entity bottom-center; the first is the snapped
start. An unreachable goal returns PARTIAL with the best route found.
Entity-aware searching across every navigation mode uses EntityPathfinder
with a NavigationRequest. Several destinations can share one frontier and one
budget:
PathResult result = new EntityPathfinder()
.findPathToAny(request, candidates, SearchControl.NONE);Reached alternatives rank by node count; if none is reached, the partial path ranks by remaining Manhattan distance, then node count.
PathStatus says what a search produced. PathResult.stop() says what ended
it, which is what decides whether retrying is worth anything.
PathStop |
Meaning |
|---|---|
REACHED |
reached; exactly the FOUND results |
FRONTIER_EXHAUSTED |
open set emptied with nothing withheld; unreachable from the start |
FRONTIER_TRUNCATED |
a budget, deadline or cancellation ended it with cells still open |
LENGTH_BOUNDED |
open set emptied only because maxPathLength withheld cells |
NOT_SEARCHED |
shed, invalid, or replayed from a cache |
Only FRONTIER_EXHAUSTED describes the world; the others describe your budget.
if (!result.found() && result.stop() == PathStop.FRONTIER_EXHAUSTED) {
chooseAnotherGoal(); // no budget will ever reach this one
}The controller republishes this as routeStop() and targetUnreachable().
NavigationPlan is immutable and does not retain the world, so cache it
against a revision you own and replay it without searching again.
NavigationPlan plan = navigation.plan(request).join();
NavigationPlanCache<String> routes = new NavigationPlanCache<>(256);
routes.put("guard:a-to-b", worldRevision, plan);
routes.get("guard:a-to-b", worldRevision, guard.getPosition(), 0.5)
.ifPresent(controller::follow);Increment the revision after relevant block changes. Store A-to-B and B-to-A separately: steps, falls, jumps, doors and costs are not symmetric.
Start here
Shaping behaviour
Going deeper
Reference