Interface GameAPI

All Superinterfaces:
ActionAPI, DrawAPI, NavigationAPI, SystemAPI, VariableAPI

public interface GameAPI extends SystemAPI, ActionAPI, NavigationAPI, VariableAPI, DrawAPI
Slim RPC-shaped surface for talking to the game producer. After the GameAPI rewrite (Path B) most legacy reads moved to GameSnapshot (obtained via Client.snapshot()); only mutations, the two state probes that the producer always handles, and the cache-type lookups (slice 5 stubs) live here.

Domain split:

  • SystemAPI — pipe ping / introspection
  • ActionAPI — action queue + behavior modifiers
  • NavigationAPI — walker, pathfinder queries, region cache
  • VariableAPI — on-demand varp / varbit / varc reads
  • DrawAPI — debug drawing over the client (api.draw())

Per-tick reads of game state (local player, NPCs, players, inventories) go through Client.snapshot(); transient changes (varp/varbit deltas, chat) arrive as events on the EventBus. On-demand variable reads (current value of an arbitrary varp/varbit/varc) live on VariableAPI below.

See Also:
  • Field Details

    • UNRESOLVED_VARIABLE

      static final int UNRESOLVED_VARIABLE
      Value the gameval-named variable reads return when the name does not resolve — the same "no value" sentinel VariableAPI.getVarp(int) yields for a varp that does not exist or could not be read.

      It is not the value of an unset varp. An unset varp reads its type default, which is usually 0 and, for object-typed varps, is itself -1; a set varp can hold -1 too. So -1 never means "unset" on its own: ask VariableAPI.readVarp(int) or VariableAPI.varpState(int).

      See Also:
    • TOP_LEVEL_COMPONENT

      static final int TOP_LEVEL_COMPONENT
      Sub-component id meaning "the component itself" in a component trigger.
      See Also:
  • Method Details

    • snapshot

      GameSnapshot snapshot()
      Returns a tick-scoped read view over the producer's published snapshot, or null if no shared-memory region is bound (e.g. tests using the legacy 1-/2-arg GameAPIImpl constructor). Same instance shape as Client.snapshot(); surfaced here so the entity query facades (npcs(), players()) and skill helpers (getLocalPlayer(), getPlayerStat(int)) can read snapshot fields without forcing scripts to thread Client through every helper.

      The returned view is bounded to the current tick — don't cache it. Each call resolves the published front buffer.

    • isInterfaceOpen

      default boolean isInterfaceOpen(int ifaceId)
      Convenience shim — delegates to snapshot().isInterfaceOpen(ifaceId). Kept so call sites that pre-date the rewrite (api.isInterfaceOpen(...)) keep compiling. New code should go through GameSnapshot directly.
    • gamevals

      default GamevalIndex gamevals()
      Resolves gameval symbolic names — the game's own stable names for items, scenery, NPCs, interfaces, components and variables — to ids. Never null: when no index is deployed this returns GamevalIndex.empty(), whose lookups all come back empty.

      Backed by an out-of-band gameval.sqlite in ~/.botwithus/native/, so a game renumber is fixed by refreshing that file rather than by editing scripts. The same instance is shared by every connected client.

      int yew = api.gamevals().require(GamevalType.ITEM, "YEW_LOGS");
      
    • getVarp

      default int getVarp(String gameval)
      Value of a player variable named by its gameval, e.g. "WOODCUTTING_WOODBOX_LASTUSED_TIER". Convenience over VariableAPI.getVarp(int).

      Returns UNRESOLVED_VARIABLE when the name does not resolve — the same value VariableAPI.getVarp(int) yields for a varp that does not exist or could not be read — so a host with no gameval index deployed degrades rather than killing the script. An unset varp is different: it reads its type default. Use gamevals().require(...) explicitly when you would rather fail fast.

    • getVarpLong

      default long getVarpLong(String gameval)
      Full 64-bit value of a player variable named by its gameval. Convenience over VariableAPI.getVarpLong(int); UNRESOLVED_VARIABLE when the name does not resolve.
    • getVarbit

      default int getVarbit(String gameval)
      Value of a variable bit named by its gameval, e.g. "ZAROS_SPELLBOOK". Convenience over VariableAPI.getVarbit(int); UNRESOLVED_VARIABLE when the name does not resolve.
    • getVarcInt

      default int getVarcInt(String gameval)
      Value of an integer client variable named by its gameval. Convenience over VariableAPI.getVarcInt(int); UNRESOLVED_VARIABLE when the name does not resolve.
    • npcs

      Npcs npcs()
      NPC query facade. Singleton per GameAPI; returns the same instance every call so the underlying NpcType cache is shared.
    • players

      Players players()
      Player query facade. Singleton per GameAPI.
    • backpack

      Backpack backpack()
      Backpack facade. Singleton per GameAPI.
    • bank

      Bank bank()
      Bank facade. Singleton per GameAPI.
    • equipment

      Equipment equipment()
      Worn equipment facade. Singleton per GameAPI.
    • getObjVars

      Map<Integer, Map<Integer,Integer>> getObjVars(int invId)
      Per-item obj vars for every filled slot of a container — the per-instance variables an item carries in its slot's ObjVarDomain (augmentation XP, charges, etc.), distinct from the global player/client var domains. Read on demand over the RPC pipe (the obj-var hashmaps are walked on the game thread). Returns slot -> (varId -> value); an empty map when nothing in the container carries obj vars.
      Parameters:
      invId - container id (e.g. 93 = backpack, 94 = equipment)
    • getObjVars

      Map<Integer,Integer> getObjVars(int invId, int slot)
      Per-item obj vars for a single container slot. Returns varId -> value, or an empty map when the slot is empty or carries no obj vars.
      Parameters:
      invId - container id
      slot - 0-based slot index
    • objects

      SceneObjects objects()
      Scene-object query facade. Singleton per GameAPI.
    • groundItems

      GroundItems groundItems()
      Ground-item query facade. Singleton per GameAPI.
    • projectiles

      Projectiles projectiles()
      In-flight projectile query facade (v17+). Singleton per GameAPI.

      Read-only: projectiles carry no menu actions and no cache definition, so the entities this yields have no interact() and no name(). See Projectile.

    • mapElements

      WorldMapElements mapElements()
      World-map element query facade. Singleton per GameAPI.
    • queryWorldMapElements

      List<WorldMapElement> queryWorldMapElements(Map<String,Object> filter)
      Low-level RPC: ask the producer for cache-resident world map elements matching filter. The map shape is the same one WorldMapElements.Query accumulates. Most scripts go through mapElements() instead. Stub-empty until producer iteration lands.
    • getWorldMapElement

      default WorldMapElement getWorldMapElement(int id)
      Single world-map element by id, or null when not found. Default implementation scans the unfiltered query result client-side, so it inherits the producer-side stub-empty behaviour — once cache iteration lands, this returns real data without a code change.

      Convenience for callers that already know the id (e.g. resolving a named-location catalog entry). For map searches with filters use mapElements().

    • getLocalPlayer

      LocalPlayer getLocalPlayer()
      The local player, with LocalPlayer.currentHealth() and LocalPlayer.maxHealth() filled in. Returns null when not in-game (matches snapshot semantics).

      Otherwise the same record snapshot().self() returns — but health is not in the mapping, so filling it costs one batched varp read over the pipe. That read is cached per server tick, so calling this in a loop costs at most one round-trip per 600ms tick; both values degrade to LocalPlayer.HEALTH_UNKNOWN if the read doesn't land. Callers that only want position, skills or animation should prefer snapshot().self(), which never touches the pipe.

    • walkWorldPath

      default void walkWorldPath(int x, int y)
      No-plane convenience for NavigationAPI.walkWorldPathAsync(int, int, int) — uses the local player's current plane, falling back to plane 0 when not in-game. Lives here (not on NavigationAPI) because it needs snapshot().

      Reads the plane off the snapshot rather than getLocalPlayer(): only the plane is wanted, and the health read that accessor pays for would be a round-trip spent on nothing.

    • getPlayerStat

      PlayerStat getPlayerStat(int skillId)
      Returns one of the local player's skill stats by skill type id. null when not in-game or the skill isn't in the published skills array. Ids match the in-game StatType.id (e.g. 25 for Divination, 26 for Invention, 6 for Magic); take them from Skills rather than writing the number.

      Read out of the snapshot — no RPC round-trip.

    • getGameCycle

      int getGameCycle()
      Returns the producer's monotonically increasing game cycle counter. Backed by the get_game_cycle RPC.
    • getLoginState

      LoginState getLoginState()
      Returns the producer's current login state. Backed by the get_login_state RPC.
    • setWorld

      void setWorld(int worldId)
      Initiates a world hop to the given world id.
    • changeLoginState

      void changeLoginState(int oldState, int newState)
      Requests a login state transition.
      Parameters:
      oldState - the expected current state, or <= 0 to skip the check
      newState - the desired new state
    • loginToLobby

      void loginToLobby()
      Triggers a login from the login screen to the lobby.
      Throws:
      RuntimeException - if the client is not on the login screen
    • scheduleBreak

      void scheduleBreak(int durationMs)
      Schedules a break (action-queue gate) for the given duration.
    • interruptBreak

      void interruptBreak()
      Interrupts any currently active break.
    • getAutoLogin

      boolean getAutoLogin()
      Returns whether the producer's auto-login state machine is enabled.
    • setAutoLogin

      void setAutoLogin(boolean enabled)
      Enables or disables the producer's auto-login state machine.
    • getScriptHandle

      long getScriptHandle(int scriptId)
      Obtains a producer-side handle to a client script for repeated execution. Release with destroyScriptHandle(long) when done.
    • executeScript

      ScriptResult executeScript(long handle, int[] intArgs, String[] stringArgs, String[] returns)
      Executes a previously-obtained client script handle.
      Parameters:
      handle - handle from getScriptHandle(int)
      intArgs - integer args, or null
      stringArgs - string args, or null
      returns - expected return-type descriptors, or null
    • destroyScriptHandle

      void destroyScriptHandle(long handle)
      Releases a script handle.
    • fireComponentTrigger

      void fireComponentTrigger(int interfaceId, int componentId, int subId, int triggerType, int arg)
      Fires a component's CS2 event trigger (click / key / ...) by event type, reproducing the engine's own component-event path. Enqueued on the action queue and run on the game thread; a component that carries no trigger of the requested type is a silent no-op.
      Parameters:
      interfaceId - owning interface id
      componentId - component id
      subId - sub-component id, or -1 for the top-level component
      triggerType - event type — 9 = click, 10 = key (see ActionTypes.TRIGGER_TYPE_*)
      arg - type-dependent argument. For key triggers, either form:
      • a bare Jagex key code (0..0xFFFF, e.g. KeyStroke.CODE_ENTER): sent as a key-down with no character, (arg << 16) | 0;
      • a packed KeyStroke.packed() ((keyCode << 16) | keyChar, non-zero high half): sent unchanged. Use this to type a character (KeyStroke.character(c).packed()).
      See KeyStroke.keyTriggerArg(int). For click triggers, packed (x << 16) | y component-relative press coordinates. 0 if unused.
    • fireKeys

      default int fireKeys(int interfaceId, int componentId, List<KeyStroke> keys)
      Fires a component's key (type-10) CS2 trigger once per stroke, in order, as a single batched action-queue request (one RPC round-trip). The agent dispatches one queued action per game tick, so n strokes take n ticks to land. A component with no key trigger — an input dialog that has already closed, for one — drops the strokes silently.

      For the game's own input dialog, inputDialog() is the checked way in: it validates what it types against the dialog's mode and submits.

      Returns:
      the number of strokes queued
    • fireKeyTrigger

      default void fireKeyTrigger(int interfaceId, int componentId, String input)
      Types input into a component through its key (type-10) CS2 trigger, one KeyStroke.character(char) per character, batched as by fireKeys(int, int, List). Types only — it does not submit; follow it with fireKeys(interfaceId, componentId, List.of(KeyStroke.ENTER)), or use inputDialog(), which types and submits in one batch. A null or empty input queues nothing.
      Throws:
      IllegalArgumentException - when input holds a character that is not printable ASCII
    • inputDialog

      InputDialog inputDialog()
      The game's text/amount input dialog (withdraw-X, add-friend, ...). Singleton per GameAPI.
    • components

      Components components()
      Interface-component query facade — the high-level, fluent entry point for inspecting interface components (parallel to npcs() / mapElements()). Singleton per GameAPI. Most scripts use this rather than the low-level getComponent(int, int) / getInterfaceTree(int, int) primitives below.
    • getComponent

      Component getComponent(int interfaceId, int componentId)
      Returns the component at (interfaceId, componentId) or null when no such component is loaded. Each call is a pipe round-trip — Phase 1 has no consumer-side cache.

      Phase 1 starter set covers identity + post-layout geometry only; text, item, sprite, hidden, color, font and other per-type fields are not yet surfaced and arrive in later slices.

    • getComponents

      List<Component> getComponents(List<ComponentRef> refs)
      Batch counterpart of getComponent(int, int). The producer walks every target on a single game-thread visit, collapsing the latency of N independent getComponent calls (one tick each) into one tick total.

      The producer hard-caps the per-call batch (currently 64). Oversize inputs are silently truncated by the producer, so the returned list may be shorter than refs; callers that need more than the cap should split into chunks themselves.

      Parameters:
      refs - components to resolve, in the desired result order
      Returns:
      one element per resolved ref, in input order; null entries signal "not found" (matches the single-component contract). Length may be less than refs.size() when the producer cap is exceeded.
    • getStaticChildren

      List<Integer> getStaticChildren(int interfaceId, int componentId)
      Returns the static (cache-defined) child component ids of (interfaceId, componentId). Each call is a pipe round-trip — Phase 1 has no consumer-side cache, so don't loop this in tight code yet.

      The list contains each child's own componentId within the same interface; entries equal to -1 indicate a child whose packed address slot is unset (the producer surfaces the game's 0xFFFF sentinel as -1). Returns an empty list when the parent is unresolvable (interface not loaded, component slot empty, or no static children).

    • getDynamicChildren

      List<Integer> getDynamicChildren(int interfaceId, int componentId)
      Returns the dynamic (script-spawned) child component ids of (interfaceId, componentId). Same shape and caveats as getStaticChildren(int, int); this is the path embedded dropdowns and other transient sub-trees travel through.
    • getInterfaceTree

      List<ComponentTreeNode> getInterfaceTree(int interfaceId, int componentId)
      Returns the component at (interfaceId, componentId) and its entire descendant subtree, flattened breadth-first, in a single pipe round-trip. Empty list when the root doesn't resolve.

      Each ComponentTreeNode carries its component plus a parentIndex into the same list (-1 for the root). The producer follows the live Component* children vectors, so the walk spans mounted sub-interface boundaries — a child's own interface id rides along in component.ifaceId(), which per-node getStaticChildren(int, int) cannot follow.

      Most scripts use components() instead; this is the seam the Components facade drives.

    • findComponentAt

      Component findComponentAt(int screenX, int screenY)
      Locate the deepest visible component under a screen-space coordinate, or null when nothing is there. Coordinates are raw screen pixels (the value of Win32 GetCursorPos); the producer runs inside the game process and converts to client-window space itself.

      The producer walks every open sub-interface on the game thread and picks the component with the greatest tree depth whose post-layout AABB contains the point — ties broken by the smaller AABB. Hidden components are excluded. Useful for debugger "pick on screen" tools and for scripters who know a feature's location but not its component id.

    • getItemType

      ItemType getItemType(int id)
      API Note:
      slice 5 stub — producer returns a sentinel response until the real cache-backed lookup lands.
    • getNpcType

      NpcType getNpcType(int id)
      API Note:
      slice 5 stub — see getItemType(int).
    • getLocationType

      LocationType getLocationType(int id)
      API Note:
      slice 5 stub — see getItemType(int).
    • getEnumType

      EnumType getEnumType(int id)
      API Note:
      slice 5 stub — see getItemType(int).
    • getStructType

      StructType getStructType(int id)
      API Note:
      slice 5 stub — see getItemType(int).
    • getSequenceType

      SequenceType getSequenceType(int id)
      API Note:
      slice 5 stub — see getItemType(int).
    • getQuestType

      QuestType getQuestType(int id)
      API Note:
      slice 5 stub — see getItemType(int).