EventBus
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
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.
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