# EventBus

> Talos 0.6 · Since 0.6

The global event bus.

Events emitted during a tick are delivered at the end of that tick, in order. Four names are published by the engine rather than by a behavior: `"trigger"` and `"collision"`, described here, `"ui-activated"` ({@link BusUiActivated}), which is a button press and has rules of its own, and `"hold-broken"` ({@link BusHoldBroken}), a hold ending, which follows the same rules as `"ui-activated"`. The first two carry {@link BusTriggerEvent} and {@link BusCollision}, with `by` always null because no behavior emitted them. They exist so a referee — a course brain, a scorer, a replay recorder — can watch contacts it is not a participant in. Two things about them are worth knowing before you rely on them: - The entity-targeted {@link Behavior.onTrigger} and {@link Behavior.onCollision} hooks run first and are unchanged. Subscribing here neither replaces nor suppresses them. - The published form does **not** reach {@link Behavior.onEvent}. Only an explicit `on`/`once` sees it, which is what keeps a scene that never subscribes from paying for it at all.

Reached in a behaviour as `ctx.events`.

## Signature

```ts
export interface EventBus {
  /** Emit to every behavior's `onEvent`, every `on` listener, and the observability log. `data` must be JSON-serialisable. */
  emit(name: string, data?: unknown): void
  /**
   * Subscribe. The engine's own names ({@link BusEventMap}) narrow `ev.data` to their payloads;
   * every other name carries whatever `emit` was given, as `unknown`.
   */
  on<N extends string>(name: N, handler: (ev: GameEvent<BusPayload<N>>) => void): void
  /** Like `on` but removed after the first delivery. */
  once<N extends string>(name: N, handler: (ev: GameEvent<BusPayload<N>>) => void): void
  /** Remove one handler, or all handlers for `name`. */
  off<N extends string>(name: N, handler?: (ev: GameEvent<BusPayload<N>>) => void): void
}
```

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

## Members

| Member | Signature | Description |
|---|---|---|
| `emit` | `emit(name: string, data?: unknown): void` | Emit to every behavior's `onEvent`, every `on` listener, and the observability log. `data` must be JSON-serialisable. |
| `on` | `on<N extends string>(name: N, handler: (ev: GameEvent<BusPayload<N>>) => void): void` | Subscribe. The engine's own names ({@link BusEventMap}) narrow `ev.data` to their payloads; every other name carries whatever `emit` was given, as `unknown`. |
| `once` | `once<N extends string>(name: N, handler: (ev: GameEvent<BusPayload<N>>) => void): void` | Like `on` but removed after the first delivery. |
| `off` | `off<N extends string>(name: N, handler?: (ev: GameEvent<BusPayload<N>>) => void): void` | Remove one handler, or all handlers for `name`. |

## 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
```
