-
Notifications
You must be signed in to change notification settings - Fork 0
Shared Mesh
Opt-in and off by default. It promotes repeated, compatible traffic into revisioned regional route fields, so a crowd converging on one target does not each pay for a full search.
NavigationSystem navigation = NavigationSystem.builder()
.sharedMesh(SharedMeshOptions.enabledWith(
SharedMeshPolicy.builder()
.promotionRequests(16)
.regionSize(64)
.maximumRegions(128)
.build()))
.build();
SharedMeshNavigation mesh = navigation.sharedMesh();
mesh.tick(tick); // once per world tick
mesh.disable(); // out of service without touching a call site
mesh.tick(tick)takes a tick id, not a timestamp. It is compared againsttargetIdleTicksandregionIdleTicks, and a pursuit swallows a repeated id so a mob is never walked twice. Feeding itSystem.currentTimeMillis()would expire retained routes about fifty times early.
A pursuit owns its follower and ticks it — the opposite contract to a plain controller.
SharedMeshPursuit pursuit = mesh.pursue(hostileMob, player, worldRevision, tick);
pursuit.tick(worldRevision, tick); // instance tick thread only
NavigationState state = pursuit.state();
pursuit.close(); // death and removal are also detected| You hold | You call once per tick | Who ticks the follower |
|---|---|---|
EntityNavigationController |
controller.tick() |
you |
SharedMeshPursuit |
pursuit.tick(worldRevision, tick) |
the pursuit |
A pursuit never hands out its follower; read state(), nodes(),
generation() and spliceCounts() instead. Driving one from two places is
safe: one tick id advances it once.
Enabled wrongly it costs more than it saves.
-
Regions partition on the whole request — world, regional start cell,
bounding box, profile, ordered influence snapshot, sea level, all four search
limits and build heights. A diverse population can exhaust the default
maximumRegions = 128, after which every further request takesUNTRACKED_FALLBACK: ordinary A* plus bookkeeping, strictly worse than leaving the mesh off. Watchstatus().regionsExhausted(). - A destination merges to its cell; a source never merges. Reuse happens when a follower's own position repeats. Measured on the seeded sweep, a stationary pursuer answered 61.7% of requests from a shared field, a moving one 0%.
- Promotion is a visible hitch — about 8.1 ms inline against a 1.2 ms baseline for the same search.
- The steady-state win is about twelvefold, not orders of magnitude: roughly 0.1 to 0.2 ms against 1.2 ms end to end.
Enable it for crowds converging on shared objectives from repeated positions: sieges, spawn corridors, chokepoints, guards holding a post. Leave it off for sparse populations, varied bounding boxes and profiles, or mobs in constant open transit.
SharedMeshHandle handle = mesh.plan(SharedMeshRequest.builder(request)
.actor(mob.getUuid())
.target(target.getUuid())
.worldRevision(worldRevision)
.currentTick(tick)
.build());NavigationStrategy defaults to PREFER_SHARED, which consults the mesh and
falls back to ordinary A*; INDIVIDUAL_ONLY never consults it. Neither relaxes
the parity gate: a shared plan is served only from a promoted region holding a
certified ordinary-A* plan for that exact source and destination class. There
is no force-shared mode. handle.source() reports what answered.
mesh.status() bundles the switch state, the policy, SharedMeshRetention and
this mesh's own request counts. That is what to alarm on when it is enabled.
SharedRouteMesh is the low-level primitive: directed edges of complete
NavigationPlan segments, directed because climbing, falling, jumping, doors
and costs are not symmetric.
SharedRouteMesh<String> mesh = SharedRouteMesh.<String>builder(worldRevision)
.route("spawn-west", "junction", westToJunction, 12.5)
.route("junction", "arena", junctionToArena, 20.0)
.build();
NavigationPlan plan = mesh.routesTo("arena", worldRevision)
.routeFrom("spawn-west")
.orElseThrow()
.plan();A target field runs reverse Dijkstra once and stores one next edge per reachable node. A mesh key must include the world and its revision, the profile and cost policy, entity width, height and depth, movement capabilities including jump and fall limits, and the allowed areas. Never share a mesh across incompatible bounding boxes or profiles.
Shared routes do not solve crowd collision. Add a local steering or reservation layer for velocity and short-term lanes.
Start here
Shaping behaviour
Going deeper
Reference