Game API
This page covers the parts of the API that are easy to misuse. It is not a class-by-class reference.
Most scripts should prefer the high-level helpers first:
Loadoutsfor banking, equipment, inventory preparation, rune pouch setup, and depletion handling.Restockerfor buying/selling and retrying Grand Exchange work.GrandExchange.Requestonly when you need direct control over offer placement.- Raw
Inventory,Bank,Interfaces, and entity queries for small local decisions.
Lazy Views
Query APIs usually return views. Views are resolved against the current client state when you call a terminal operation such as first(), count(), forEach(...), or mapToInt(...).
Inventory.items()
.id(ItemId.SHARK)
.first()
.ifPresent(shark -> shark.interact("Eat"));
Do not store wrappers for long-running logic. Query again immediately before interacting.
Optional<Item> old = Inventory.item(ItemId.SHARK);
// The inventory may change here.
old.ifPresent(item -> item.interact("Eat"));
That pattern is fine inside a single branch, but avoid carrying Item, Npc, SceneObject, IfComponent, or GrandExchangeOffer objects across ticks unless you revalidate them.
State Progression
UI-heavy APIs intentionally do one meaningful action and return. The client needs time to update widgets, inventory state, selected items, varbits, and offer memory.
Prefer branches that can be called repeatedly:
if (!Bank.showing()) {
Bank.open();
return;
}
Loadouts.withdraw(inventoryLoadout, equipmentLoadout);
The same applies to Grand Exchange placement:
GrandExchange.buy(ItemId.SHARK)
.amount(100)
.price(GrandExchange.Price.live().plus5())
.place();
place() may open the GE, return to the overview, click a buy/sell slot, select the item, set price/quantity, or confirm. It should be called again after the game has processed the previous action.
IDs And Noted Items
Use generated IDs such as ItemId.SHARK and InterfaceId.GeOffers.BACK. Avoid hardcoded numbers in plugin code unless you are handling a temporary missing constant.
Grand Exchange buying normalizes noted IDs to the unnoted item. Selling may need to query both forms because bank withdrawals often prefer notes for non-stackable items.
GrandExchange.sell(items -> items.id(ItemId.MAGIC_LOGS, ItemId.CERT_MAGIC_LOGS).first())
.amount(27)
.price(GrandExchange.Price.live().minus5())
.place();
For full setup flows, prefer loadouts/restocking so noted handling, rune pouch preparation, and depletion callbacks stay in one place.
Bank And Loadouts
Use direct bank calls for small one-off actions. Use loadouts when you care about exact inventory/equipment state.
Loadouts can:
- deposit foreign items,
- withdraw/equip equipment first,
- fill rune pouches,
- withdraw remaining inventory items,
- cap actions per tick,
- report depleted required items.
See Loadouts and Restocking.
Grand Exchange
Use GrandExchange.Price.live() when you want OSRS Wiki real-time prices. It falls back to the client market price if live data is unavailable.
GrandExchange.buy(ItemId.SHARK)
.amount(100)
.price(GrandExchange.Price.live().plus5())
.place();
Use Restocker if you need retries, cancellation, price adjustment, collection mode, or per-item defaults.
Offer State
Offer memory comes from the client, not from widget text. Use it for progress checks and retry decisions.
GrandExchange.offers()
.id(ItemId.SHARK)
.type(GrandExchangeOffer.Type.BUY)
.state(GrandExchangeOffer.State.FINISHED)
.first()
.ifPresent(offer -> GrandExchange.collect(offer, GrandExchange.CollectionMode.BANK));
Useful fields:
offer.slot();
offer.item();
offer.type();
offer.state();
offer.unitPrice();
offer.amount();
offer.transferred();
offer.remaining();
offer.progress();
Interface Work
Generated interface IDs are preferred over raw component IDs.
Interfaces.component(InterfaceId.GeOffers.BACK)
.filter(IfComponent::visible)
.ifPresent(Interactable::interact);
Component options and text can be conditional. Query them from the wrapper at the point of interaction instead of caching arrays or assuming a fixed option index.
Coordinates
Coord(x, y) uses floor 0. Use the three-argument overload when the plane matters.
Coord ge = new Coord(3164, 3487);
Coord upstairs = new Coord(3200, 3200, 1);
Navigation and world-area checks should also be treated as progressive. Issue a step/request, then let the client move and recalculate.