Walker Engine & Navigation
This document covers the Walker Engine, Navigation Actions, Walk Assistant plugin, and Movement Transport Actions/Data components.
Walker Route Planning & Execution Flow
1. Walker Engine
com.n3plugins.sdk.walker plans and runs paths across the world. A single static walker serves the entire suite, ticked by PacketUtilsPlugin.onGameTick via Walker.tick(). Feature plugins should use the result-aware NavigationActions facade instead of interacting with the Walker directly, unless they require manual path manipulation (like Walk Assistant).
Static Facade API
WalkerPath path = Walker.walkTo(new WorldPoint(3164, 3486, 0));
if (Walker.isWalking()) {
// Player is currently moving along the path
}
Walker.stop(); // Cancels active path
| Method | Description |
|---|---|
planTo(WorldPoint target) | Builds a WalkerPath without starting movement. |
planTo(WorldPoint target, WalkerRouteOptions options) | Builds a WalkerPath with custom routing options. |
walkTo(WorldPoint target) | Builds and starts a path to a point. |
walkTo(WorldPoint target, WalkerRouteOptions options) | Builds and starts a path using custom routing options. |
walkPath(List<WorldPoint> path) | Executes a specific pre-defined path. |
tick() | Advances the active path; called by PacketUtilsPlugin, not by feature plugins. |
stop() | Cancels and terminates the active path. |
getActivePath() | Returns the running WalkerPath (or null). |
isWalking() | Returns true if a path is active and running. |
prewarm() | Pre-computes collision and planning data to avoid first-use lag. |
Route Options (WalkerRouteOptions)
WalkerRouteOptions.smartDefaults(): Enables walking, teleports, transports, and wilderness avoidance.WalkerRouteOptions.walkingOnly(): Disables all teleports and transport categories, forcing standard walking.- Master Switches:
useTeleportsanduseTransportsdisable broad route families before any specific route type is considered. - Shortest Path categories: vendored TSV rows are classified by source file, including agility/grapple shortcuts, boats, canoes, charter ships, ships, fairy rings, gnome gliders, hot air balloons, magic carpets, magic mushtrees, minecarts, quetzals, quetzal whistle, spirit trees, teleport item/box/lever/portal/POH/spell/home-spell/minigame rows, wilderness obelisks, seasonal transports, and generic transports.
avoidWilderness: Skips wilderness routes unless the destination itself is in the wilderness.withBankedRoutePlanning(true): Compares direct route costs against a bank preparation route throughBankedRoutePlanner. Returns decisions (DIRECT,BANK_PREP_REQUIRED, etc.) asynchronously.
PacketUtils applies the suite route policy for each Walker.planTo(...) and
Walker.walkTo(...) call. The PacketUtils config maps the pinned Shortest Path
settings, POH options, transport cost thresholds, currency threshold, and route
display settings into the walker. Planner requirements still decide whether a
configured route edge is usable.
Curated widget transports in WalkerMovementRegistry use named
WidgetInfoExtended constants. For example, gnome glider buttons are backed by
RuneLite gameval InterfaceID.Glidermap.* entries; do not add raw packed widget
IDs for in-repo transport actions.
Route Resource Metadata
WalkerResourceApi is the read-only SDK facade for stable walker resource
metadata. It exposes immutable descriptors for route categories, vendored
shortest-path transport TSV resources, agility/grapple shortcut resources, and
curated in-repo transport networks. It does not publish every upstream row or
the package-private planner transport definitions.
for (WalkerTransportResourceDescriptor resource : WalkerResourceApi.shortestPathTransportResources()) {
log.debug("{} -> {}", resource.getResourceName(), resource.getCategory());
}
WalkerResourceApi.curatedTransportNetworks().forEach(network ->
log.debug("{} has {} registered edges", network.getDisplayName(), network.getEdgeCount()));
The Path Handle (WalkerPath)
A WalkerPath represents the active route state:
getStatus(): ReturnsWalkerStatus(PLANNING,PLANNED,RUNNING,WAITING,COMPLETED,FAILED,CANCELLED).getSteps(): List of plannedRouteSteps.getCurrentStep()/getCurrentStepIndex(): Returns active step details.getRequestedTarget()/getNormalizedTarget(): Returns the requested destination and the snapped target.getDisplayPath(): List of remaining points (useful for overlays).isTerminal(): Returns true if the path has finished (success, failed, or cancelled).
2. Navigation Actions API
NavigationActions provides a result-aware, paced wrapper around the shared Walker.
Core Methods
canReach(WorldPoint)/canReach(NPC)/canReach(TileObject): Spatial reachability checks.pathTo(WorldPoint goal): Plans a route and returns a list of points (never null).walkTo(WorldPoint goal): Directs the walker to path to a goal tile.walkNear(WorldPoint goal, int distance): Walks within a certain radius of a goal tile.walkPath(List<WorldPoint> path): Directs the walker to execute a contiguous land route.cancelWalk(): Stops the shared walker and resets navigation states.clear(): Resets current path, goal, and reached distance variables.
NavigationActions tracks the exact WalkerPath handle it started. If the
shared walker path belongs to another caller or has already terminated, stale
NavigationActions goal/path state is cleared before reporting an active-walk
block.
WorldPoint altar = new WorldPoint(3052, 3484, 0);
InteractionResult result = NavigationActions.walkNear(altar, 2);
if (result.failed()) {
log.debug("Navigation failed: {}", result.getMessage());
}
3. Walk Assistant Plugin
WalkAssistantPlugin is a QoL plugin that walks to destinations on demand (Quest Helper steps, nearest bank, or world-map clicks).
- Config group:
n3walkassistant - Properties registration:
runelite-plugin.properties
Triggers
- Quest/Clue Destination (
questDestHotkey): Resolves targets throughWalkDestinationResolverand walks there. - Nearest Bank (
nearestBankHotkey): Coordinates withWalkBankResolverto rank plane-local banks. - Cancel (
cancelWalkHotkey): Stops the active Walk Assistant path. - World Map Option (
enableWorldMapWalkOption): Adds a right-click "Walk-to" menu option on the world map.
Walk Assistant calls the shared Walker.walkTo(...) facade directly. PacketUtils
owns suite-level route settings, ticking, and path overlay display.
PacketUtilsWalkerOverlay renders Walker.getActivePath() from PacketUtils
display settings so all walker callers share one overlay owner. New world-map
or hotkey requests may replace a Walk Assistant-owned active path, but foreign
active shared walker paths are still blocked. Explicit Walk Assistant cancel
stops any current non-terminal shared walker path and clears both Walk Assistant
and NavigationActions tracking; it reports no active walk only when
Walker.getActivePath() is null or terminal.
4. Movement Transport Actions & Data
The package com.n3plugins.InteractionApi.actions.movement contains transport action controllers and coordinate/ID data enums.
n3Plugins vendors Skretzo shortest-path resources under
src/main/resources/com/n3plugins/sdk/walker/shortestpath/: collision-map.zip,
destinations/**, transports/**, UPSTREAM-LICENSE.txt, and
vendor.properties. ShortestPathRouteService loads the modern Skretzo
transport TSVs; the old single transports.txt bridge is not packaged.
collision-map.zip stores per-region raw flag bitsets inside the zip. The
loader accepts those raw entries, plus older gzip/serialized region payloads.
Do not GZIP-decompress a zip entry unless its bytes start with GZIP magic
1F 8B; otherwise live planning fails in SplitFlagMap with
ZipException: Not in GZIP format.
Run refresh and freshness checks by hand:
.\gradlew.bat updateShortestPathVendor --console plain
.\gradlew.bat checkShortestPathVendor --console plain
Use -PshortestPathSha=<commit> with updateShortestPathVendor to pin a
specific upstream commit. Compile/test/build tasks skip GitHub.
Transport Action Classes
All transport actions return InteractionResult and are paced.
Fairy Rings (FairyRingActions)
travelTo(FairyRing destination): Travels to a fairy ring destination by code.dial(FairyRing code): Configures the ring dial wheels to code without traveling.currentCode(): Reads the active dial code.
InteractionResult result = FairyRingActions.travelTo(FairyRing.fromCode("BKR"));
Charter Ships (CharterShipActions)
travelTo(CharterShip port): Interacts with charter captains to sail to destination.
Gnome Gliders (GnomeGliderActions)
travelTo(GnomeGlider destination): Interacts with pilots to fly to destination.
Spirit Trees (SpiritTreeActions)
travelTo(SpiritTree destination): Interacts with spirit trees (usesWorldAreabounds checking).
Other Transports (TransportActions)
travelTo(MagicCarpet)/travelTo(Minecart)/travelTo(BirdFlight).
Coordinate Data Enums
FairyRing
47 entries. Fields: getCode(), getDestination(), getWorldPoint().
Lookup: FairyRing.fromCode(String code) (case-insensitive).
GnomeGlider
7 entries. Fields: getNpcId() (always 491), getDestination(), getWorldPoint().
CharterShip
9 entries. Fields: getNpcId() (always 1519), getPortName(), getWorldPoint().
SpiritTree
11 entries. Fields: getDestination(), getWorldArea().
MagicCarpet
7 entries. Fields: getNpcId() (always 1566), getLocation(), getWorldPoint().
Minecart
3 entries. Fields: getStation(), getWorldPoint() (Keldagrim, GE, Dwarven Mine underground).
BirdFlight
5 eagle destinations. Fields: getDestination(), getWorldPoint().
BankLocation
40 entries outlining bank boundary boxes. Fields: getWorldArea().
WorldPoint here = client.getLocalPlayer().getWorldLocation();
for (BankLocation bank : BankLocation.values()) {
if (bank.getWorldArea().contains(here)) {
log.debug("Currently inside bank: {}", bank.name());
break;
}
}
5. Requirements System
com.n3plugins.sdk.walker.requirements models transport prerequisites evaluated prior to including route edges.
ItemRequirement: Checks items in inventory/equipment.QuestRequirement: Gates on RuneLiteQuestandQuestState.SkillRequirement: Gates on minimum real skill levels.VarRequirement: Gates on varbit/varplayer values.RuneRequirement: Gates on magic rune counts (reads inventory + rune pouch).AnyRequirement: Logical OR combiner.
Testing
For routing tests, inject a fake WalkerContext in @Before so the pathfinder runs without client threads:
@Before
public void setUp() {
WalkerContextBridge.setAdapterForTesting(fakeContext);
ActionPacer.reset();
}
@After
public void tearDown() {
WalkerContextBridge.resetAdapterForTesting();
}
ShortestPathRouteServiceModernResourcesTest.collisionResourceSupportsVarrockWalkingRoute
guards the collision resource loader using the live failure case
WorldPoint(3165, 3463, 0) to WorldPoint(3173, 3441, 0). Run it when
changing collision-map.zip, SplitFlagMap, FlagMap, or the vendor refresh
task.