# WorldQuery

> Talos 0.6 · Since 0.6

Read access to every entity plus the physics and navigation queries.

Reached in a behaviour as `ctx.world`.

## Signature

```ts
export interface WorldQuery {
  /** Entities matching the filter, in a fixed deterministic order. No filter returns everything. */
  query(filter?: QueryFilter): EntityHandle[]
  /** Look an entity up by scene id. */
  find(id: string): EntityHandle | null
  /**
   * The centre line of the road entity `id` (an entity with a `road` component), or null when `id`
   * is not a road. See {@link RoadLine}.
   */
  road(id: string): RoadLine | null
  /** Number of live entities. */
  readonly count: number
  /**
   * First physics hit along a ray, or null. `dir` need not be normalised. Trigger volumes count as hits
   * unless `opts.triggers` is false — pass that for a camera boom, a line of sight or an aim ray, which
   * should see through a volume the player walks through.
   */
  raycast(from: Vec3, dir: Vec3, max?: number, opts?: CastOptions): Hit | null
  /** Like `raycast` but sweeping a shape. */
  shapeCast(shape: CastShape, from: Vec3, dir: Vec3, max?: number, opts?: CastOptions): Hit | null
  /**
   * The dynamic body a pick ray lands on first, or null — what "the thing I am pointing at" means for a
   * grab. The first thing the ray meets decides: a wall in front of a crate hides it, and a static or
   * kinematic body, one over `maxMass` or one without `tag` answers null rather than letting the ray
   * carry on. Exclude the picker.
   *
   * ```ts
   * const eye = ctx.entity.worldPosition; eye[1] += 1.6
   * const hit = ctx.world.pick(eye, aim, 2.5, { exclude: ctx.entity, tag: "grabbable" })
   * ```
   */
  pick(from: Vec3, dir: Vec3, max?: number, opts?: PickOptions): Hit | null
  /**
   * Start carrying `target`'s dynamic body at `holder` (any entity: a character, a hand, a crane hook).
   * True when it is now held. False, having changed nothing, when the target is gone, has no body, is not
   * dynamic, is the holder, or is over `maxMass`. A NaN, infinite or non-positive option throws a `RangeError`.
   *
   * The body stays a physics body: each tick it is given the velocity that brings it to its hold point,
   * so it still collides with everything except its holder, stops against walls (it never passes through
   * one), and pushes other bodies aside. When it falls more than `breakDistance` behind and keeps falling
   * behind — the holder walked away from a crate wedged in a doorway — the hold breaks and the body drops;
   * `heldBy` reads null from that tick. However a hold ends — a break, a `release`, a despawn — the engine
   * raises a `"hold-broken"` bus event ({@link BusHoldBroken}) saying which and why. A character's
   * controller passes through what it is holding.
   *
   * Holding something already held replaces that hold: a hand-over, or a new `offset`, is one more call.
   * Held state is part of the physics checkpoint, so `GET /snapshot` → `POST /snapshot` restores a carry.
   */
  hold(holder: EntityHandle | string, target: EntityHandle | string, opts?: HoldOptions): boolean
  /** Let `target` go; `opts.velocity` throws it. False if it was not held. */
  release(target: EntityHandle | string, opts?: ReleaseOptions): boolean
  /** Who is holding `target`, or null. */
  heldBy(target: EntityHandle | string): EntityHandle | null
  /** What `holder` is holding, in entity order; empty when nothing. */
  holding(holder: EntityHandle | string): EntityHandle[]
  /**
   * Navmesh path as a polyline, or null when unreachable. Throws `nav-undeclared` in a scene that
   * declares no navigation (no `meta.nav`, no `navagent`): navigation is opt-in, and such a scene
   * has no navmesh. Add `"nav": {}` to the scene's meta.
   */
  path(from: Vec3, to: Vec3): Vec3[] | null
  /**
   * Put another copy of an entity the scene already has, or of a prefab, into the world, and get a
   * handle to it.
   *
   * `like` is the scene id of a live entity, and the new entity is a full copy of it: its name,
   * its tags, its parent, its scale and every one of its components, wired the way the scene's
   * own entities are — a collider becomes a physics body the solver knows, a mesh becomes
   * something the renderer draws, a script gets its own behavior instance with its own `state`,
   * all within the tick that asked for it.
   *
   * `prefab` instead of `like` spawns a copy of a project prefab file, which need not be placed in
   * any scene: its root and every entity under it, the root's id as below and each other entity's
   * `"<root id>/<prefab entity id>"`, parented as the prefab has them, with `overrides` applied as a
   * scene instance's are. The handle is the root's; {@link EntityHandle.despawn} on it removes the
   * whole copy. The project's prefabs are read and checked once, at load, so a spawn parses nothing.
   *
   * Either way, what is spawned is a shape the contract already validated: an entity of the scene,
   * or a prefab file.
   *
   * **Ids.** Give one and it must be free, or this throws. Leave it out and the engine derives
   * `"<like>#1"`, `"<like>#2"`, … from a counter kept per source id. Both are deterministic: two
   * runs of the same scene making the same calls in the same order get the same ids and the same
   * entity slots, which is what the lockstep critic checks.
   *
   * Throws rather than returning null, so a spawn that did not happen cannot be mistaken for one
   * that did. The error's `name` is `SpawnError` and its message starts with the code:
   * `spawn-no-source`, `spawn-two-sources`, `spawn-unknown-source`, `spawn-unknown-prefab`,
   * `spawn-bad-override`, `spawn-duplicate-id`.
   *
   * The copy's behaviour runs `init` on this tick, after every `update` has returned, and is then
   * handed each event emitted this tick after this call (so an `emit` straight after the spawn
   * reaches its `onEvent` and the listeners its `init` subscribed); its first `update` is next tick.
   *
   * A spawned entity is runtime state, not a scene change. The scene file is untouched,
   * `GET /snapshot` carries the entity and `POST /snapshot` puts it back — and
   * {@link SessionHandle.restart} rebuilds from the scene as loaded, so a restart removes every
   * spawned entity and brings back every authored one.
   *
   * ```ts
   * const cone = ctx.world.spawn({ like: "cone-prototype", position: [4, 0, -12] })
   * cone.set("material", { baseColor: "#ff6600" })
   *
   * const imp = ctx.world.spawn({ prefab: "prefabs/imp.prefab.json", position: [2, 0, 5],
   *   overrides: { "root/script:chase/props/speed": 5 } })   // imp#1, and imp#1/<child> for each child
   * ```
   */
  spawn(options: SpawnOptions): EntityHandle
}
```

Import: `import type { WorldQuery } from "@argus/api"`

## Members

| Member | Signature | Description |
|---|---|---|
| `query` | `query(filter?: QueryFilter): EntityHandle[]` | Entities matching the filter, in a fixed deterministic order. No filter returns everything. |
| `find` | `find(id: string): EntityHandle \| null` | Look an entity up by scene id. |
| `road` | `road(id: string): RoadLine \| null` | The centre line of the road entity `id` (an entity with a `road` component), or null when `id` is not a road. See {@link RoadLine}. |
| `count` | `readonly count: number` | Number of live entities. |
| `raycast` | `raycast(from: Vec3, dir: Vec3, max?: number, opts?: CastOptions): Hit \| null` | First physics hit along a ray, or null. `dir` need not be normalised. Trigger volumes count as hits unless `opts.triggers` is false — pass that for a camera boom, a line of sight or an aim ray, which should see through a volume the player walks through. |
| `shapeCast` | `shapeCast(shape: CastShape, from: Vec3, dir: Vec3, max?: number, opts?: CastOptions): Hit \| null` | Like `raycast` but sweeping a shape. |
| `pick` | `pick(from: Vec3, dir: Vec3, max?: number, opts?: PickOptions): Hit \| null` | The dynamic body a pick ray lands on first, or null — what "the thing I am pointing at" means for a grab. The first thing the ray meets decides: a wall in front of a crate hides it, and a static or kinematic body, one over `maxMass` or one without `tag` answers null rather than letting the ray carry on. Exclude the picker. `ts const eye = ctx.entity.worldPosition; eye[1] += 1.6 const hit = ctx.world.pick(eye, aim, 2.5, { exclude: ctx.entity, tag: "grabbable" }) ``` |
| `hold` | `hold(holder: EntityHandle \| string, target: EntityHandle \| string, opts?: HoldOptions): boolean` | Start carrying `target`'s dynamic body at `holder` (any entity: a character, a hand, a crane hook). True when it is now held. False, having changed nothing, when the target is gone, has no body, is not dynamic, is the holder, or is over `maxMass`. A NaN, infinite or non-positive option throws a `RangeError`. The body stays a physics body: each tick it is given the velocity that brings it to its hold point, so it still collides with everything except its holder, stops against walls (it never passes through one), and pushes other bodies aside. When it falls more than `breakDistance` behind and keeps falling behind — the holder walked away from a crate wedged in a doorway — the hold breaks and the body drops; `heldBy` reads null from that tick. However a hold ends — a break, a `release`, a despawn — the engine raises a `"hold-broken"` bus event ({@link BusHoldBroken}) saying which and why. A character's controller passes through what it is holding. Holding something already held replaces that hold: a hand-over, or a new `offset`, is one more call. Held state is part of the physics checkpoint, so `GET /snapshot` → `POST /snapshot` restores a carry. |
| `release` | `release(target: EntityHandle \| string, opts?: ReleaseOptions): boolean` | Let `target` go; `opts.velocity` throws it. False if it was not held. |
| `heldBy` | `heldBy(target: EntityHandle \| string): EntityHandle \| null` | Who is holding `target`, or null. |
| `holding` | `holding(holder: EntityHandle \| string): EntityHandle[]` | What `holder` is holding, in entity order; empty when nothing. |
| `path` | `path(from: Vec3, to: Vec3): Vec3[] \| null` | Navmesh path as a polyline, or null when unreachable. Throws `nav-undeclared` in a scene that declares no navigation (no `meta.nav`, no `navagent`): navigation is opt-in, and such a scene has no navmesh. Add `"nav": {}` to the scene's meta. |
| `spawn` | `spawn(options: SpawnOptions): EntityHandle` | Put another copy of an entity the scene already has, or of a prefab, into the world, and get a handle to it. `like` is the scene id of a live entity, and the new entity is a full copy of it: its name, its tags, its parent, its scale and every one of its components, wired the way the scene's own entities are — a collider becomes a physics body the solver knows, a mesh becomes something the renderer draws, a script gets its own behavior instance with its own `state`, all within the tick that asked for it. `prefab` instead of `like` spawns a copy of a project prefab file, which need not be placed in any scene: its root and every entity under it, the root's id as below and each other entity's `"<root id>/<prefab entity id>"`, parented as the prefab has them, with `overrides` applied as a scene instance's are. The handle is the root's; {@link EntityHandle.despawn} on it removes the whole copy. The project's prefabs are read and checked once, at load, so a spawn parses nothing. Either way, what is spawned is a shape the contract already validated: an entity of the scene, or a prefab file. **Ids.** Give one and it must be free, or this throws. Leave it out and the engine derives `"<like>#1"`, `"<like>#2"`, … from a counter kept per source id. Both are deterministic: two runs of the same scene making the same calls in the same order get the same ids and the same entity slots, which is what the lockstep critic checks. Throws rather than returning null, so a spawn that did not happen cannot be mistaken for one that did. The error's `name` is `SpawnError` and its message starts with the code: `spawn-no-source`, `spawn-two-sources`, `spawn-unknown-source`, `spawn-unknown-prefab`, `spawn-bad-override`, `spawn-duplicate-id`. The copy's behaviour runs `init` on this tick, after every `update` has returned, and is then handed each event emitted this tick after this call (so an `emit` straight after the spawn reaches its `onEvent` and the listeners its `init` subscribed); its first `update` is next tick. A spawned entity is runtime state, not a scene change. The scene file is untouched, `GET /snapshot` carries the entity and `POST /snapshot` puts it back — and {@link SessionHandle.restart} rebuilds from the scene as loaded, so a restart removes every spawned entity and brings back every authored one. `ts const cone = ctx.world.spawn({ like: "cone-prototype", position: [4, 0, -12] }) cone.set("material", { baseColor: "#ff6600" }) const imp = ctx.world.spawn({ prefab: "prefabs/imp.prefab.json", position: [2, 0, 5],   overrides: { "root/script:chase/props/speed": 5 } })   // imp#1, and imp#1/<child> for each child ``` |

## Example

The tested fixture `fixtures/host/door.ts`.

```ts
import type { Behavior } from "@argus/api"
// docs/API.md, "Joints": a door on a hinge that swings open while the player is near and closes
// behind them. Typechecked by packages/api's tests.
export default {
  update(ctx) {
    const player = ctx.world.find("player")
    const near = player !== null && ctx.entity.distanceTo(player) < 2
    ctx.joint?.setMotor(near ? Math.PI / 2 : 0, { mode: "position", maxForce: 200 })
  },
} satisfies Behavior
```
