Standards:Discord GMCP

From Mudlet
Jump to navigation Jump to search

A Standard for the GMCP Namespace for Discord Rich Presence

Status of this Memo

This memo describes the addition of a standardised method of communication by the GMCP telnet subnegotiation protocol (201) for the encapsulation of rich presence information meant for the Discord chat client. This data, however, should in most cases be generic enough to be used for statuses in other unlisted clients.

Overview and Rationale

With the inclusion of rich presence in chat clients, the ability for MUDs to transmit player information to the MUD client is necessary to make use of this. The purpose of this is to provide a channel in an existing side protocol which provides reasonable defaults as set by the game, which can be overridden by a player or disabled for privacy, customisation, or other purposes, without the need for each MUD to individually provide a package for each client or the players to do so.

Overview of the GMCP (201) Subnegotiation Protocol

To recap, the GMCP protocol is a bidirectional telnet subnegotiation protocol (See RFC 854) which fulfills the following conditions:

  • GMCP is separated into several ‘namespaces’, which may be enabled or disabled by the client at any time. The ‘Core’ namespace is always enabled and may not be disabled. Namespaces should consist of case-insensitive alphabetical characters and stop characters (. - ASCII 46/0x2E), representable as [A-Za-z.].
  • GMCP messages consist of the namespace and a command (case insensitive alpha characters) delineated by a stop character, and optionally a space character and JSON-encoded payload.
  • GMCP messages may be sent by both the client or server at any time with no warning.

Proposal of new namespace: External.*

For the purposes of all future external application support protocols, we would like to propose the creation of an External.* meta-namespace. This serves the dual-purpose of 1) avoiding polluting the global GMCP namespaces, and 2) distinctly denoting the purpose of any namespace within it as used for an external application, allowing for future expansion and integration.

Note Note: See quick rundown on implementing the spec

Specification for External.Discord

External.Discord should allow for full integration with the game if necessary, but at the same time allow for fields to be ignored or nulled by both the server and client for both support and privacy reasons as necessary. NOTE: Sending/receiving messages is not supported. If you wish to support this, use an in-game communication channel.

Commands - Server

External.Discord.Info

  • Sent as a reply to External.Discord.Hello
  • If no keys, send empty object.
  • applicationid is a custom application id for the game to use instead of the client’s. This allows the use of custom icons, a custom game name, etc.
  • Body: { inviteurl: "https://discord.gg/#####", applicationid: "…" }

External.Discord.Status

  • Icon name should be an array of strings to allow for multiple options, so as not to lock multiple clients into the same iconset or icon names. Clients should use the first icon named which is available. All icon names MUST be sent in lowercase.
  • Details will very often be disused by the client in favour of "Playing <Game Name>"
  • Discord rich presence party variables should be disused if both size and max are set to 0.
  • The starttime and endtime fields should be unix timestamps (seconds since epoch). The starttime field will show time as time elapsed since this time. The endtime field will show a countdown.
  • This should send a full state rather than a delta.
  • Body: { smallimage: ["iconname", "iconname2", iconname3"], smallimagetext: "Icon hover text", details: "Details String", state: "State String", partysize: 0, partymax: 10, game: "Achaea", starttime: "timestamp for start" }

Commands - Client

External.Discord.Hello

  • Sent to announce one’s Discord information from the MUD and receive an official server invite URL (if any).
  • User strings, if supplied, should be in the form of <username>#<identifier> as per Discord standard.
  • The ‘private’ field exists for the case that a game decides to provide a directory, but the user still wishes to provide their username for bot integrations or other purposes. This MUST be respected by the game.
  • Body: { user: "person#1234", private: true }

External.Discord.Get

  • Retrieves an External.Discord.Status from the server.
  • Body is empty.

Authors

  • Nicholas Guarino (Iron Realms Entertainment, Lusternia, Assistant Producer) <ianir@lusternia.com>;
  • Iron Realms Entertainment <support@ironrealms.com>

Extra Notes for Testers

Core.Supports.Add ["External.Discord 1"]