rune.gmcp
GMCP carries structured out-of-band data — vitals, room info, comm channels — over telnet option 201. For a task-oriented introduction, see GMCP.
Quick reference
Section titled “Quick reference”rune.gmcp.on(package, handler, opts?) -- handle a package (case-insensitive)rune.gmcp.send(package, value?) -- send a JSON-able valuerune.gmcp.send_raw(package, raw_json) -- send pre-encoded JSON (debugging)rune.gmcp.subscribe(package, version?) -- declare interest (Core.Supports.Set)rune.gmcp.unsubscribe(package) -- withdraw interestrune.gmcp.is_enabled() -- true while GMCP is negotiatedrune.gmcp.list() -- all handlers, as /gmcp shows themrune.gmcp.on returns a handle and accepts
the common options.
rune.gmcp.on
Section titled “rune.gmcp.on”rune.gmcp.on(package, handler, opts?) -> handlepackage(string) — the package to match, exactly ("Char.Vitals"does not catch"Char.Vitals.Max"). Matching is case-insensitive, per the spec.handler(function) —function(data, package).datais the decoded JSON value — a table, string, number, or boolean, ornilwhen the message had no body.packageis the name as the server sent it.opts(table, optional) — common options (name,group,priority).
Handlers are registry items like triggers, so quarantine and source attribution apply.
rune.gmcp.on("Char.Vitals", function(data) hp, maxhp = data.hp, data.maxhp rune.ui.refresh_bars()end, { name = "vitals" })For every message regardless of package, the "gmcp"
hook event fires with
(package, data, raw) — raw JSON text included. Malformed JSON from
the server is reported and dropped before any handler runs.
rune.gmcp.send
Section titled “rune.gmcp.send”rune.gmcp.send(package, value?) -> true | nil, errpackage(string) — the message name ("Char.Skills.Get").value(optional) — a string, number, boolean, or JSON-able table;nilsends the bare package name.
Returns true, or nil plus an error when the send cannot happen —
not connected, GMCP not negotiated, or the value cannot be encoded.
Failures are also echoed to the screen.
rune.gmcp.send("Char.Skills.Get", { group = "combat" })rune.gmcp.send("Core.Ping")send_raw(package, raw_json) skips encoding and validation entirely —
a debugging tool (/gmcp send uses it).
Subscriptions and the handshake
Section titled “Subscriptions and the handshake”subscribe(package, version?) declares interest in a server package
("Char", "Room", …); version defaults to 1. Subscriptions
maintain Core.Supports.Set — the full set is re-sent on every
change, per the spec — taking effect immediately when GMCP is up,
otherwise at the next handshake. This holds across /reload too:
is_enabled() reflects the live connection, so a subscription added
to init.lua reaches the server as soon as the reloaded script
declares it.
When the server negotiates GMCP, the "gmcp_enabled" event fires and
the core handler named gmcp-hello sends
Core.Hello {client, version} plus the current subscription set.
Subscribe at load time; the handshake picks it up on connect. Disable
or replace gmcp-hello like any named hook.
rune.gmcp.subscribe("Char")rune.gmcp.subscribe("Room", 2)Managing
Section titled “Managing”rune.gmcp.enable/disable/remove(name) manage handlers by name;
rune.gmcp.list() returns them — see
Registries. /gmcp shows negotiation
state, subscriptions, and handlers; /gmcp send <package> [json]
sends a raw message for debugging.
Related: GMCP guide · rune.hooks · Protocols