Talos docs

EventBus

Since 0.6

The global event bus.

Plain text

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

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

MemberSignatureDescription
emitemit(name: string, data?: unknown): voidEmit to every behavior's onEvent, every on listener, and the observability log. data must be JSON-serialisable.
onon<N extends string>(name: N, handler: (ev: GameEvent<BusPayload<N>>) => void): voidSubscribe. The engine's own names ({@link BusEventMap}) narrow ev.data to their payloads; every other name carries whatever emit was given, as unknown.
onceonce<N extends string>(name: N, handler: (ev: GameEvent<BusPayload<N>>) => void): voidLike on but removed after the first delivery.
offoff<N extends string>(name: N, handler?: (ev: GameEvent<BusPayload<N>>) => void): voidRemove one handler, or all handlers for name.

Example

The tested fixture fixtures/app/agent.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