Table of Contents
GMCP
Generated from smudgy v0.4.2-dev (smudgy-core.d.ts @ 5110ac599715). Index: scriptref.
Read structured GMCP messages as shared state, check protocol status, and react to connection lifecycle events.
import gmcp from "smudgy:state/gmcp"; const hp = gmcp.value?.Char?.Vitals?.hp; gmcp.watch("Char.Vitals", vitals => console.log(vitals));
GMCP names and payloads vary by game. The contracts below describe common shapes without hiding unrecognized messages. For negotiation, sending messages, game-specific typing, and MSDP, see Read GMCP and MSDP.
Default export
The module's default export (gmcp).
const gmcp: StateConsumer<GmcpTree>;
The live GMCP tree, one entry per message name (see GmcpTree):
read the latest value with gmcp.value, subscribe with
gmcp.watch(path, ...), and wire widgets with gmcp.bind(path).
Each message the server sends is committed as its own update, so a
watcher at or under the message's path runs once per message, repeats
included.
The message shapes
GmcpTree
export interface GmcpTree { Char?: { Vitals?: { hp?: number; maxhp?: number; mp?: number; maxmp?: number; [field: string]: unknown }; Status?: { level?: number; [field: string]: unknown }; Name?: { name?: string; fullname?: string; [field: string]: unknown }; [message: string]: unknown; }; Room?: { Info?: { num?: number; name?: string; area?: string; zone?: string; environment?: string; terrain?: string; exits?: Record<string, number>; [field: string]: unknown; }; [message: string]: unknown; }; Comm?: { Channel?: { chan?: string; player?: string; msg?: string; [field: string]: unknown }; [message: string]: unknown; }; [pkg: string]: unknown; }
Everything the server has sent over GMCP, one entry per message name.
import gmcp from "smudgy:state/gmcp" serves the live tree:
gmcp.value.Char.Vitals.hp is the latest reading, and
gmcp.watch("Char.Vitals", ...) runs on each vitals message.
Paths reach inside payloads too: gmcp.watch("Char.Vitals.hp", ...)
hands the handler just the number. It runs on every message that
covers the path, so a vitals update that left hp unchanged still
fires; compare against gmcp.previousValue to react to change alone.
Message names are matched case-insensitively, so Char.Vitals finds the
data whether the server spells it Char.Vitals or char.vitals.
The declared entries are a widely-implemented set of GMCP state
objects. Games send others, and every message the server sends appears
in the tree whether or not it is declared here; an undeclared message
reads as unknown. A script can type the messages of the game it
supports by extending this interface and casting the handle. A game
that adds a Room.Weather message keeps the declared Room.Info
typing by intersecting:
import gmcp from "smudgy:state/gmcp"; import type { StateConsumer, GmcpTree } from "smudgy:core"; interface FenworldGmcp extends GmcpTree { Room?: NonNullable<GmcpTree['Room']> & { Weather?: { temp?: number; rain?: boolean }; }; } const fenGmcp = gmcp as StateConsumer<FenworldGmcp>; const temp = fenGmcp.value?.Room?.Weather?.temp; // number | undefined
Protocol status
gmcp
export const gmcp: { readonly enabled: boolean; onReady(callback: () => void): void; send(name: string, data?: unknown): void; enableModule(name: string, version?: number): void; disableModule(name: string): void; mergeKeys(...names: string[]): void; };
GMCP protocol status and control for the current session.
enabled— Whether GMCP is active on the current connection.onReady— Runscallbackonce GMCP is ready. When GMCP is already active, the callback is called immediately, beforeonReadyreturns; otherwise it runs once when the server next completes GMCP negotiation. Code that runs at load time gets its callback whether it loads before or after the connection.send— Sends a GMCP message to the game. Callgmcp.send("Char.Items.Inv")with only a name, or pass JSON-serializable data as the second argument. Messages are dropped (with a one-time notice) while GMCP is not active; useonReadyto wait for it.enableModule— Asks the server to turn a GMCP module on —gmcp.enableModule("IRE.Rift")— so its messages start arriving.versiondefaults to 1. Modules are shared: the server keeps a module on while anything still uses it, and turning one on that another script already enabled costs nothing. A module enabled before the connection is requested as part of the GMCP handshake.disableModule— Releases this script's use of a GMCP module. The server is asked to turn the module off only when no other script still uses it.mergeKeys— Marks message names whose payloads merge into the retained value instead of replacing it — for servers that send only the changed fields after an initial full send.Char.Statusis always treated this way;gmcp.mergeKeys("Char.Defences")adds more.
Lifecycle events: smudgy:events/gmcp
ready
export const ready: EventConsumer<Record<string, never>>;
Fires once GMCP negotiation completes and the handshake has been sent;
GMCP data starts flowing from this moment. For code that may load after
the connection, gmcp.onReady from smudgy:core covers both orders.
closed
export const closed: EventConsumer<Record<string, never>>;
Fires when GMCP stops on a live connection: the server withdrew it, or
the connection dropped while it was active. The last-received data stays
readable through smudgy:state/gmcp.
Script API reference · ← smudgy:core — Shared state & events · MSDP (experimental) → · Scripting manual
