scriptref:core:events

smudgy:core — Events

Generated from smudgy v0.3.5 (smudgy-core.d.ts @ cfcea3b156f6). Index: scriptref.

Events fire when something happens (the session connects or disconnects, a command goes out, the map location changes) or when a package broadcasts one. Subscribe with on, broadcast with emit. Import from smudgy:core.

export function on<K extends keyof SmudgyEventMap>(
  event: K,
  handler: (payload: SmudgyEventMap[K], eventName: string) => void,
): EventSubscription;
 
export function on<T>(
  event: SmudgyEvent<T>,
  handler: (payload: T, eventName: string) => void,
): EventSubscription;
 
export function on(
  event: string,
  handler: (payload: unknown, eventName: string) => void,
): EventSubscription;

Run a handler whenever an event fires. event is the event's name, like "sys:connect"; handler is called with the event's payload each time it fires.

import { on, echo } from "smudgy:core";
on("sys:connect", () => echo("Connected!"));
on("map:room", ({ roomNumber }) => echo(`Now in room ${roomNumber}`));

Returns an EventSubscription; call its off() to stop listening.

TypeScript detail: when event is a known key of SmudgyEventMap, the payload type is inferred from the map; a SmudgyEvent token infers its branded payload; any other string is accepted with payload: unknown. The handler's second argument is the full event name that fired.

export function once<K extends keyof SmudgyEventMap>(
  event: K,
  handler: (payload: SmudgyEventMap[K], eventName: string) => void,
): EventSubscription;
 
export function once<T>(
  event: SmudgyEvent<T>,
  handler: (payload: T, eventName: string) => void,
): EventSubscription;
 
export function once(
  event: string,
  handler: (payload: unknown, eventName: string) => void,
): EventSubscription;

Like on, but the handler fires at most once. The returned EventSubscription can still cancel it before it ever fires.

export function emit<K extends keyof SmudgyEventMap>(event: K, payload: SmudgyEventMap[K]): void;
 
export function emit<T>(event: SmudgyEvent<T>, payload: T): void;
 
export function emit(event: string, payload?: unknown): void;

Broadcast an event to every subscriber. Events go out under your own name, so you can only emit events you own. Returns nothing; for request/response, emit a request event and subscribe to a reply event.

Payloads travel as JSON: properties whose value is undefined are dropped, and a NaN arrives as null.

export interface SmudgyEventMap {
  // ---- Built-ins ----------------------------------------------------------
 
  "sys:connect": Record<string, never>;
 
  "sys:disconnect": Record<string, never>;
 
  "sys:send": { command: string };
 
  "map:room": { areaId: string; roomNumber: number | null };
}

The catalog of event names and their payload types: the built-in sys:* / map:* events below, plus any events declared by installed packages.

You rarely name this type yourself: write on("sys:connect", ...) and your handler's payload is typed from this map automatically.

For package authors: SmudgyEventMap is an open interface; a package publishes its own events by declaration-merging into it, from any of its modules (a file with at least one top-level import/export):

// in your package's index.ts
export interface PromptData { hp?: number; mp?: number }
 
declare module "smudgy:core" {
  interface SmudgyEventMap {
    "smudgy://kapusniak/arctic-prompt#prompt": PromptData;
  }
}

Anyone with the package installed then gets a typed handler by name alone:

import { on } from "smudgy:core";
on("smudgy://kapusniak/arctic-prompt#prompt", ({ hp }) => { ... }); // hp: number | undefined

You can only emit events you own; other packages' events you can only subscribe to.

  • "sys:connect" — Fires when the session connects to the MUD. Empty payload.
  • "sys:disconnect" — Fires when the session disconnects from the MUD. Empty payload.
  • "sys:send" — Fires just before a command goes to the MUD. command is the final outgoing line, after alias expansion and command splitting.
  • "map:room" — Fires when your current map location changes, whether or not a mapper package is installed. areaId is the area's UUID as a string; roomNumber is the room number, or null when the location has no specific room. Careful: this string areaId is a different representation from the AreaId [number, number] pair the mapper API uses; the two are not interchangeable.
export type SmudgyEvent<T> = string & { readonly __smudgyPayload?: T };

A typed event-name constant (mostly seen in older packages). At runtime it is just a string; its type carries the payload T. Kept for back-compat with packages that publish events as exported SmudgyEvent<…> constants:

export const PROMPT_EVENT =
  "smudgy://kapusniak/arctic-prompt#prompt" as SmudgyEvent<PromptData>;

Prefer the SmudgyEventMap pattern for new code.

export interface EventSubscription {
  off(): void;
}

A subscription returned by on. Call EventSubscription.off to stop listening.

import { on } from "smudgy:core";
const sub = on("sys:connect", () => { ... });
// later, when you no longer care:
sub.off();
  • off — Cancel this subscription: the handler stops receiving the event. Safe to call more than once. (A script reload drops every subscription on its own.)

Script API reference · smudgy:core — Sessions & output · smudgy:core — Lines & buffer · smudgy:core — Automations · smudgy:core — Saved automations · smudgy:core — Panes · smudgy:widgets · Mapper · smudgy:params