Skip to main content
The suite shares one walker: com.n3plugins.sdk.walker plans and runs paths for every plugin, and PacketUtilsPlugin is the only component that ticks it. Feature plugins should call the result-aware NavigationActions facade rather than the walker directly, unless they need manual path control like Walk Assistant.

How a route runs

The walker facade

Concurrency is serialized with a reentrant lock, so walkTo and walkPath calls from multiple script threads cannot corrupt the active path, and stop() is safe from any thread.

Deterministic land steps

Land movement uses a deterministic lookahead (no random tile selection): the base lookahead is half the remaining distance clamped to a 5-25 tile window before door clipping. Accepted movements are tracked as queued commands, so an in-flight hop is not re-dispatched, and landing beyond the queued hop resynchronizes from the observed player position instead of walking back to a stale tile. Path recalculation is a last resort: a stalled movement is retried only after the bounded stall window, and a second stalled window cancels the movement and requests a fresh route. Transport-type stall thresholds adapt through multipliers (land 1.0, toll gates 1.1, teleports 1.2, canoes 1.3, transports 1.5).

Route options

WalkerRouteOptions controls what the planner may use:
  • smartDefaults() enables walking, teleports, transports, and wilderness avoidance.
  • walkingOnly() disables every teleport and transport category.
  • useTeleports and useTransports disable broad route families before specific types are considered.
  • avoidWilderness skips wilderness routes unless the destination is inside it.
  • withBankedRoutePlanning(true) asks the planner to select a complete bank-aware route: the walker walks only the prefix to that bank, waits for fresh bank-container evidence, revalidates the item manifest, withdraws through BankActions, and requests a fresh route. Bank contents are unknown until a container event arrives after login; known-empty and unknown are distinct states.
  • Transport costs adjust edge weights per category before planning:
Raising a category’s cost makes the planner prefer alternatives; a fairy-ring cost increase pushes routes toward walking. Catalog rows are classified by source: agility and grapple shortcuts, boats, canoes, charter ships, ships, fairy rings, gnome gliders, hot air balloons, magic carpets, magic mushtrees, minecarts, quetzals, spirit trees, teleport items, levers, portals, POH, spells, minigame teleports, wilderness obelisks, and generic transports. NavigationActions is the result-aware facade for plugins:
  • walkTo(goal) plans globally to the tile; walkNear(goal, distance) completes within the accepted Chebyshev radius on the target plane.
  • cancelWalk() stops the shared walker and resets navigation state.
  • It tracks the exact WalkerPath handle it started. If the shared path belongs to another caller or has terminated, stale goal state clears before reporting an active-walk block.
  • walkTo and walkNear never gate global planning on the local collision preview, so doors, stairs, cross-plane routes, and transports still plan.

Transport execution

When the planner selects a transport edge, the edge is converted to a typed route step and resolved to an executor: Key behaviors:
  • Game interactions stay in Api.actions. Executors return boolean progress to the path engine; the walker context preserves InteractionResult acceptance before that.
  • Requirements revalidate at execution time, not just planning time: fairy rings verify the staff, teleport items verify the item still exists, spells verify availability, canoes verify the axe and level, toll gates verify coins. A failed validation triggers a requirements-changed-replan.
  • Completion relies on observed position, not on an accepted click: arrival means the player is on the destination plane within the edge’s radius (five tiles for most transports, three for canoes, up to twenty for minigame teleports, zero or two for objects).
  • Generic transports resolve exactly one target. A row ID that matches one NPC delegates to the NPC executor; one object delegates to the object executor; both or neither fails closed and replans. This prevents ID-namespace mistakes from producing empty dispatch loops.
  • Vessel boundaries are explicit. Board and Embark never count as blocking doors during land traversal, disembarkation recovery is bounded to one nearby attempt, and destination-side gangplank crossings keep transport actions active until exact arrival.
  • Destination selectors never blind-click. Dialogue and widget selectors dispatch only on one unambiguous match; zero matches wait and multiple matches fail closed for that tick.
  • Agility and grapple shortcuts fail after ten action ticks without completion so the path can recover, while ordinary object transports wait longer because their animations legitimately vary.

Walk Assistant

WalkAssistantPlugin is a quality-of-life plugin (n3walkassistant config group) that walks to destinations on demand:
  • Hotkeys for quest or clue destinations, the nearest bank, and cancellation.
  • A destination panel with curated banks and cities plus metadata-driven farming, hunter, slayer, minigame, and guild catalogs.
  • POH resolution from the configured house-portal varbit, failing closed on unknown values.
  • An ETA and status panel while it owns a non-terminal path.
The embedded Shortest Path UI owns world-map target selection. Set Target selects the route, starts the shared walker when no other non-terminal path is active, and closes the world map after the walk is accepted. Manual world-map walking works without Walk Assistant enabled. Clearing the path from the world map (the Clear Path entry or the CTRL+X hotkey by default) calls Walker.stop() first, so the active path ends cleanly.

Telemetry

WalkerTelemetry keeps a thread-safe ring buffer (capacity 256) of recent decision events plus suite counters (recoveryCount, stallRecalcCount, unreachableCount). Each WalkerPath emits one terminal event (target-reached, accepted-distance-reached, walker-cancelled, or a failure with its diagnostic) before the walker clears or replaces the handle, so the last outcome stays readable after getActivePath() returns null:
The Agent Server exposes the same bounded history (at most 20 events) in its navigation state.

Reachability checks

ReachabilityActions reads the global collision map for local spatial reasoning. It never replaces the walker: Door detection is collision-based and conservative. Live object-aware door interaction belongs to the walker context, not to these checks.

Resource cache

The walker’s bulk data (collision maps, destinations, transports) is not packaged in the jar. On startup the resource downloader fetches the pinned, SHA-checked archive into .runelite/n3Plugins/shortestpath/, stages it, validates it, and installs it. A complete installer-prepared cache means no runtime download. Feature plugins must not download, embed, or independently tick this data.