# Ctx

> Talos 0.7 · Since 0.6; changed in 0.7

Everything a behavior can reach.

One Ctx per behavior instance; `state` and `props` are per instance, `nav`/`input`/`controller`/`animator` are null when the entity lacks that component. @typeParam S shape of `state` (persisted across hot reloads) @typeParam P shape of `props` (the script component's `props` in the scene)

Reached in a behaviour as `ctx`.

## Signature

```ts
export interface Ctx<S = Record<string, any>, P = Record<string, any>> {
  entity: EntityHandle
  world: WorldQuery
  nav: NavAgent | null
  input: InputState | null
  controller: Controller | null
  animator: Animator | null
  /** The entity's physics body; null while it has none. Read live, like `controller`. */
  body: RigidBody | null
  /** The entity's joint while it is in force; null otherwise. Read live, like `body`. */
  joint: Joint | null
  /** The entity's vehicle while it is running; null otherwise. Read live, like `body`. */
  vehicle: Vehicle | null
  /** The entity's wheel while it is running; null otherwise. Read live, like `body`. */
  wheel: Wheel | null
  /** The entity's sprite; null when it has no `sprite` component. Read live, like `body`. */
  sprite: Sprite | null
  /** The entity's tilemap; null when it has no `tilemap` component. Read live, like `body`. */
  tilemap: Tilemap | null
  /** Values this behaviour publishes for a data recording. Always present. */
  data: DataHandle
  events: EventBus
  hud: HudHandle
  ui: UiHandle
  time: TimeInfo
  /** The sky, read-only. */
  environment: EnvironmentInfo
  /** The scene's water, read-only. */
  water: WaterHandle
  /** The scene's wind, read-only. */
  wind: WindHandle
  camera: CameraHandle
  /** The local players and the entity each drives. Always present. */
  players: PlayersHandle
  /** Split screen for local multiplayer; view 1 is `camera`. */
  views: ViewsHandle
  audio: AudioHandle
  particles: ParticlesHandle
  labels: LabelsHandle
  /** Shader parameters. */
  render: RenderHandle
  strings: StringsHandle
  save: SaveHandle
  /** The project's `data/**` files, read-only. */
  files: FilesHandle
  session: SessionHandle
  /** Diagnostics for the behavior itself: `wallMs()`, the one wall clock, not for gameplay state. */
  debug: DebugHandle
  /**
   * Plain object owned by this instance; survives `reload`. Must stay JSON-serialisable. A snapshot
   * restore (the critic's playtester restores between its probes) puts the snapshot's values back
   * into this same object, and into the objects under it, so `const st = ctx.state` kept from
   * `init` is still the live state afterwards.
   */
  state: S
  /** Read-only copy of the script component's props. Always an object: `{}` when the component has none, never null. */
  props: P
  /** Structured log line for the observability layer; `data` is JSON round-tripped. */
  log(msg: string, data?: unknown): void
}
```

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

## Members

| Member | Signature | Description |
|---|---|---|
| `entity` | `entity: EntityHandle` |  |
| `world` | `world: WorldQuery` |  |
| `nav` | `nav: NavAgent \| null` |  |
| `input` | `input: InputState \| null` |  |
| `controller` | `controller: Controller \| null` |  |
| `animator` | `animator: Animator \| null` |  |
| `body` | `body: RigidBody \| null` | The entity's physics body; null while it has none. Read live, like `controller`. |
| `joint` | `joint: Joint \| null` | The entity's joint while it is in force; null otherwise. Read live, like `body`. |
| `vehicle` | `vehicle: Vehicle \| null` | The entity's vehicle while it is running; null otherwise. Read live, like `body`. |
| `wheel` | `wheel: Wheel \| null` | The entity's wheel while it is running; null otherwise. Read live, like `body`. |
| `sprite` | `sprite: Sprite \| null` | The entity's sprite; null when it has no `sprite` component. Read live, like `body`. |
| `tilemap` | `tilemap: Tilemap \| null` | The entity's tilemap; null when it has no `tilemap` component. Read live, like `body`. |
| `data` | `data: DataHandle` | Values this behaviour publishes for a data recording. Always present. |
| `events` | `events: EventBus` |  |
| `hud` | `hud: HudHandle` |  |
| `ui` | `ui: UiHandle` |  |
| `time` | `time: TimeInfo` |  |
| `environment` | `environment: EnvironmentInfo` | The sky, read-only. |
| `water` | `water: WaterHandle` | The scene's water, read-only. |
| `wind` | `wind: WindHandle` | The scene's wind, read-only. |
| `camera` | `camera: CameraHandle` |  |
| `players` | `players: PlayersHandle` | The local players and the entity each drives. Always present. |
| `views` | `views: ViewsHandle` | Split screen for local multiplayer; view 1 is `camera`. |
| `audio` | `audio: AudioHandle` |  |
| `particles` | `particles: ParticlesHandle` |  |
| `labels` | `labels: LabelsHandle` |  |
| `render` | `render: RenderHandle` | Shader parameters. |
| `strings` | `strings: StringsHandle` |  |
| `save` | `save: SaveHandle` |  |
| `files` | `files: FilesHandle` | The project's `data/**` files, read-only. |
| `session` | `session: SessionHandle` |  |
| `debug` | `debug: DebugHandle` | Diagnostics for the behavior itself: `wallMs()`, the one wall clock, not for gameplay state. |
| `state` | `state: S` | Plain object owned by this instance; survives `reload`. Must stay JSON-serialisable. A snapshot restore (the critic's playtester restores between its probes) puts the snapshot's values back into this same object, and into the objects under it, so `const st = ctx.state` kept from `init` is still the live state afterwards. |
| `props` | `props: P` | Read-only copy of the script component's props. Always an object: `{}` when the component has none, never null. |
| `log` | `log(msg: string, data?: unknown): void` | Structured log line for the observability layer; `data` is JSON round-tripped. |

## Example

The tested fixture `fixtures/app/agent.ts`.

```ts
import type { Behavior } from "@argus/api"

// Sends a nav agent to `props.target` once, then reports arrival through ctx.state so the
// test can read it without polling the crowd directly.
export default {
  init(ctx) {
    ctx.state.arrived = false
    ctx.nav?.goTo(ctx.props.target as [number, number, number])
  },
  update(ctx) {
    if (ctx.nav?.arrived) ctx.state.arrived = true
  },
} satisfies Behavior
```
