Skip to main content
Automation reads before it writes. This page collects the read-side surfaces: query helpers for scene and containers, passive event snapshots, raw game variables, revision-aware ID maps, and progress reads.

Query helpers

Start from a static container and chain filters: Common filters: withAnyAction, withoutAction, nameContainsIgnoreCase, withTextContainsIgnoreCase, idIn(Collection), withMappedName(String) (item, NPC, tile objects), exists, count, single, limit, sorted, walkable (tile objects and ground items), and geTradeable. StringMatchers centralizes tag-stripping and case-insensitive matching.
Rules that matter:
  • Never use first() as a nearest-target policy. Scene collection order is not a distance ranking. Use walkable().nearestToPoint(anchor) for a stable work area or nearestByPath() for the shortest reachable target from the player.
  • Name predicates strip tags for you. Inventory and equipment widgets return styled names like <col=ff9040>Steel axe</col>; pass bare strings.
  • Mapped names resolve through IdMapRegistry. A mapped base name such as Ancient sceptre matches its released variants. Item name filters fall back to the item-definition API when a widget carries only an ID.
  • geTradeable() is the market filter. The older tradeAble() remains for source compatibility and delegates to it.
  • ItemContainers.search(...) snapshots any container as immutable ContainerItem values. Each call copies live state; take a fresh search(...) per independent assertion.
  • ProjectileQuery and GraphicsObjectQuery snapshot on every search() rather than tick-caching. Reuse one query object to chain filters within a tick.

Event snapshots

com.n3plugins.sdk.events exposes passive, bounded recent-event snapshots. Packet Utils registers SdkEvents with the RuneLite event bus during startup and unregisters it at shutdown; consumers read snapshots and never own the bus wiring.
Snapshots carry client tick and wall-clock timestamps. The tracker retains up to 128 events per kind. Inventory-delta cursors must be persisted once per observation cycle; isGapDetected() means output may have been lost and requires resynchronization. Login, hop, and connection loss clear retained item deltas without resetting the sequence, so an old cursor never matches a later session. Unknown containers stay distinct from known-empty ones.

Scenario and replay foundation

The same package carries the offline simulation foundation used by tests and tooling:
  • EventEnvelope<T> carries a stable payload, deterministic sequence and tick metadata, and source provenance.
  • StimulusDispatcher routes envelopes to the first supporting StimulusHandler under an explicit DispatchMode (SYNC, ASYNC, DRY_RUN), deduplicating by event ID per session.
  • ScenarioRunner operates tick-driven: dispatch once, then verify state on later ticks. Posting an event never counts as proof the target processed it.
  • EventReplayService replays a recorded EventTimeline through the dispatcher under a ReplayPolicy.
  • StateFixtureService manages named state fixtures with atomic apply/rollback for deterministic scenario setup.

Utility actions

UtilityEventActions collects one-shot utility writes: All methods are result-aware. Handle the toggleAcceptAid failure explicitly rather than assuming the setting changed.

Game variables

GameVars (com.n3plugins.sdk.client) reads raw varbits and varplayers without Api dependencies:
  • getVarbit(id) and getVarPlayer(id) return 0 when the client reads null.
  • getVarPlayerBit(id, bitIndex) returns false when the client reads null.
Prefer named net.runelite.api.Varbits and VarPlayer constants as arguments. Revision-pinned named identifiers live in the suite’s GameVarsRegistry, which DevTools and rune-pouch consumers use instead of local constants classes.

ID maps

IdMapRegistry (com.n3plugins.sdk.idmaps) loads generated item, NPC, and object name/ID lookups. Bundled maps ship on the classpath; a complete revision cache under .runelite/n3Plugins/id-maps/rev-<revision>/ takes precedence when its manifest matches the active client revision.
Query helpers ItemQuery.withMappedName(...), NPCQuery.withMappedName(...), and TileObjectQuery.withMappedName(...) resolve IDs through the registry and filter by ID, including RuneLite item variation groups for the current release. Refreshes happen through imports: after generating fresh JSON map files, IdMapRegistry.importGenerated(...) validates and copies them into the revision cache with a manifest. No startup scraping or external scripts are involved.

Progress reads

com.n3plugins.sdk.progress provides read-only quest and achievement-diary progress. These APIs read eligibility state; they do not perform quest steps or claim rewards.

QuestProgressApi

Methods: state(quest), isStarted(quest), isComplete(quest), progress(quest or name), all(), started(), completed(), findQuest(name) (normalized, punctuation-insensitive matching), and satisfies(requirement) for walker quest requirements.

DiaryProgressApi

Methods: progress(region, tier), all(), forRegion(region), tasks(region, tier), isComplete(task), and progress(task). Coverage is intentionally partial: the API exposes only explicitly mapped varbit and varplayer-backed tasks and never guesses unmapped ones.