Skip to main content

Scene Query Actions

Verification boundary

This page documents the committed source. Treat revision-sensitive RuneLite UI, packet, or in-game outcomes as pending live-client verification unless the page records direct evidence.

ProjectileActions and GraphicsObjectActions expose lightweight predicate helpers for combat and environment state detection. For composable filtering, the fluent facades Projectiles and GraphicsObjects in com.n3plugins.sdk.query scan the live scene and return the same query-object pipeline used by NPCs.search() (see query-helpers.md).

Need tile-level or path-level safety instead of raw entity existence? See ThreatMapApi and LineOfSightApi in client-utilities.md.

ProjectileActions

  • getAll(Predicate<Projectile>)
  • getFirst(Predicate<Projectile>)
  • exists(Predicate<Projectile>)
  • count(Predicate<Projectile>)
  • Overloads accept an Iterable<Projectile> for pure tests and pre-filtered caller-owned collections.

GraphicsObjectActions

  • getAll(Predicate<GraphicsObject>)
  • getFirst(Predicate<GraphicsObject>)
  • exists(Predicate<GraphicsObject>)
  • count(Predicate<GraphicsObject>)
  • Overloads accept an Iterable<GraphicsObject> for pure tests and pre-filtered caller-owned collections.

Behavior notes:

  • Live graphics-object queries use the top-level world view.
  • Null clients and null collections return empty results.

Projectile Warning Example

Use projectile predicates for lightweight hazard detection. Keep predicates cheap because callers usually run them once per game tick.

InteractionResult incoming = ProjectileActions.exists(projectile ->
projectile.getId() == DANGEROUS_PROJECTILE_ID
&& projectile.getInteracting() == client.getLocalPlayer()
);

if (incoming) {
log.debug("Incoming projectile detected");
}

Pure Collection Tests

The iterable overloads let tests exercise filtering behavior with caller-owned collections.

List<Projectile> projectiles = Arrays.asList(first, second, third);

int dangerousCount = ProjectileActions.count(
projectiles,
projectile -> projectile.getId() == DANGEROUS_PROJECTILE_ID
);

Fluent Facades (Projectiles / GraphicsObjects)

Projectiles.search() returns a ProjectileQuery over the client's live projectile list; GraphicsObjects.search() returns a GraphicsObjectQuery over the top-level world view. Both take a fresh snapshot on every call (not tick-cached) and chain filters in place:

  • ProjectileQuery: withId(int), idIn(Collection<Integer>), targeting(Actor) (null matches area-effect projectiles with no interacting target), firedBy(Actor), filter(Predicate)
  • GraphicsObjectQuery: withId(int), idIn(Collection<Integer>), active() (excludes finished objects), atLevel(int), filter(Predicate)
  • Shared terminals: empty, exists, count, single, first, result, limit, sorted, filterUnique
boolean incoming = Projectiles.search()
.withId(DANGEROUS_PROJECTILE_ID)
.targeting(client.getLocalPlayer())
.exists();

Optional<GraphicsObject> marker = GraphicsObjects.search()
.withId(MARKER_GRAPHICS_ID)
.atLevel(client.getTopLevelWorldView().getPlane())
.first();

Keep predicates and filters cheap; callers usually run one read per game tick.

Graphics Object Checks

Graphics objects are useful for environment state such as spell effects, resource effects, or temporary hazards.

Optional<GraphicsObject> marker = GraphicsObjectActions.getFirst(object ->
object.getId() == MARKER_GRAPHICS_ID
);

marker.ifPresent(object -> log.debug("Marker at {}", object.getLocation()));