Overview
On top of the standard GMCP packages it relays to plugins, Mallard defines one client-specific package that it acts on itself: mallard.plugin. It lets a game server suggest one of its companion marketplace plugins — a mapper, a vitals HUD, a comms panel — so a player on that world doesn't have to find and install it by hand.
This page is the wire spec for server developers. It assumes you already speak GMCP (telnet option 201, IAC SB GMCP <Package> <json> IAC SE frames). For the client side — how a plugin reads and sends GMCP from Lua — see Plugin development §5.9.
The package is a single server → client message, mallard.plugin.install, gated by an advertise token and by explicit user consent.
Renamed in v0.25.0 — action required
This package was introduced in v0.24.0 under a different name. As of Mallard v0.25.0 the message is mallard.plugin.install and the advertise token is mallard.plugin 1. The earlier spellings are gone, with no alias — a server still sending one gets no prompt and no error.
| Sent by your server | Status |
|---|---|
Client.Plugin.Install (v0.24.0) | Removed. Update to mallard.plugin.install. |
Client.GUI with a mallard:// url (pre-release) | Removed. Never load-bearing; update to mallard.plugin.install. |
mallard.plugin.install (v0.25.0) | Current. |
The rename moves Mallard's own client-specific package out of the conventional Client.* namespace, where it risked colliding with other clients' meanings for the same name. Nothing else changed: the payload, the consent flow, the marketplace-only restriction, and the per-world enablement are all identical to v0.24.0. Because support is feature-detected, a server can send the new message unconditionally — older clients simply never advertise the token.
Detecting support
When the feature is enabled on the client — it ships on by default; the user can turn it off with the allow-world-plugin-install global setting — Mallard lists mallard.plugin 1 in the Core.Supports.Set it sends during the GMCP handshake:
Core.Supports.Set ["...", "mallard.plugin 1"]
Its presence is your signal that an install suggestion will be honoured. If mallard.plugin 1 is absent, either the client predates v0.25.0 or the user has opted out — don't send mallard.plugin.install; it will be ignored. Treat any later Core.Supports.Set as the authoritative replacement, since the user can toggle the setting mid-session and Mallard re-sends the union whenever it changes.
The same setting gates both halves: with it off Mallard neither advertises the token nor honours an inbound frame, so the advertise is a truthful signal rather than a hint.
mallard.plugin.install
To suggest a plugin, send a mallard.plugin.install frame whose JSON payload carries the plugin's marketplace id:
IAC SB GMCP mallard.plugin.install {"id":"net.discworld.mapper"} IAC SE
| Field | Type | Notes |
|---|---|---|
id | string | Required. The plugin's marketplace id — its reverse-DNS slug, e.g. net.discworld.mapper. Leading/trailing whitespace is trimmed; an empty or missing id is ignored. |
No other fields are read. The id must resolve to a published plugin in the Mallard marketplace — a server cannot point Mallard at an arbitrary URL or archive.
Behaviour & consent
What Mallard does with a mallard.plugin.install frame:
- If the user has the feature disabled, the frame is ignored entirely — no prompt, no reply.
- If the plugin is already installed (any version), the request is a silent no-op. Re-sending on every login is harmless.
- If the id isn't in the marketplace catalog, the client is too old for that plugin, or Mallard is offline, the user sees a passive note on the origin world — no dialog.
- Otherwise Mallard downloads and signature-verifies the plugin from the marketplace, then always prompts the user for consent, naming the world that asked and the permissions the plugin requests. There is no silent install path.
- On approval the plugin is enabled only for the world that asked — never globally.
- Rapid duplicate frames for the same id are de-duplicated while one is staging or awaiting consent, so a server can't stack prompts.
Mallard never fetches server-supplied bytes: the payload names a marketplace id, and the archive is downloaded from the marketplace and verified against Mallard's embedded key. A server cannot point the client at an arbitrary URL or archive.
Because the plugin is enabled for your world on accept, its own GMCP advertises then appear in a follow-up Core.Supports.Set — a clean way to confirm the user accepted and to start streaming the packages that plugin wants.
Send suggestions sparingly, and only for plugins genuinely tied to your world. A server that spams install prompts is one users disable the feature for.