Difference between revisions of "Standards:Discord GMCP"

From Mudlet
Jump to navigation Jump to search
m (→‎External.Discord.Info: formatting tweak)
m (Add missing double-quote in smallimage array.)
 
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
= A Standard for the GMCP Namespace for Discord Rich Presence =
+
<languages/>
 +
{{TOC right}}
 +
= <translate><!--T:1--> A Standard for the GMCP Namespace for Discord Rich Presence</translate> =
  
== 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.
+
== <translate><!--T:2--> Status of this Memo</translate> ==
  
== Overview and Rationale ==
+
<translate><!--T:3--> 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.</translate>
  
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 ==
+
== <translate><!--T:4--> Overview and Rationale</translate> ==
  
 +
<translate><!--T:5--> 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.</translate>
 +
 +
 +
== <translate><!--T:6--> Overview of the GMCP (201) Subnegotiation Protocol</translate> ==
 +
 +
<translate><!--T:7-->
 
To recap, the GMCP protocol is a bidirectional telnet subnegotiation protocol (See RFC 854) which fulfills the following conditions:
 
To recap, the GMCP protocol is a bidirectional telnet subnegotiation protocol (See RFC 854) which fulfills the following conditions:
  
 +
<!--T:8-->
 
* 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 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 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.
+
* GMCP messages may be sent by both the client or server at any time with no warning.</translate>
  
== 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.
+
== <translate><!--T:9--> Proposal of new namespace: External.*</translate> ==
  
== Specification for External.Discord ==
+
<translate><!--T:10--> 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.</translate>
  
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.
+
{{note}} <translate><!--T:11--> See [[Special:MyLanguage/Manual:Scripting#GMCP|quick rundown]] on implementing the specification.</translate>
  
=== Commands - Server ===
 
  
==== External.Discord.Info ====
+
== <translate><!--T:12--> Specification for External.Discord</translate> ==
  
 +
<translate><!--T:13--> 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.</translate>
 +
 +
 +
=== <translate><!--T:14--> Commands - Server</translate> ===
 +
 +
 +
==== <translate><!--T:15--> External.Discord.Info</translate> ====
 +
 +
<translate>
 +
<!--T:16-->
 
* Sent as a reply to External.Discord.Hello
 
* Sent as a reply to External.Discord.Hello
 
* If no keys, send empty object.
 
* 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.
+
* 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. It is a long number held in a quoted string.
* Body: <code>{ inviteurl: "https://discord.gg/#####", applicationid: "…" }<code>
+
* Body: <code>{ inviteurl: "https://discord.gg/#####", applicationid: "…" }</code></translate>
  
==== External.Discord.Status ====
 
  
 +
==== <translate><!--T:17--> External.Discord.Status</translate> ====
 +
 +
<translate>
 +
<!--T:18-->
 +
* Send this whenever you need to send new status data to the client
 
* 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.
 
* 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>"
 
* Details will very often be disused by the client in favour of "Playing <Game Name>"
Line 41: Line 60:
 
* 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.
 
* 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.
 
* 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" }
+
* Body: <code>{ smallimage: ["iconname", "iconname2", "iconname3"], smallimagetext: "Icon hover text", details: "Details String", state: "State String", partysize: 0, partymax: 10, game: "Achaea", starttime: "timestamp for start" }</code></translate>
  
=== Commands - Client ===
 
  
==== External.Discord.Hello ====
+
=== <translate><!--T:19--> Commands - Client</translate> ===
  
 +
 +
==== <translate><!--T:20--> External.Discord.Hello</translate> ====
 +
 +
<translate>
 +
<!--T:21-->
 
* Sent to announce one’s Discord information from the MUD and receive an official server invite URL (if any).
 
* 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.
 
* 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.
 
* 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 }
+
* Body: <code>{ user: "person#1234", private: true }</code></translate>
 +
 
  
==== External.Discord.Get ====
+
==== <translate><!--T:22--> External.Discord.Get</translate> ====
  
 +
<translate>
 +
<!--T:23-->
 
* Retrieves an External.Discord.Status from the server.
 
* Retrieves an External.Discord.Status from the server.
* Body is empty.
+
* Body is empty.</translate>
 +
 
  
== Authors ==
+
== <translate><!--T:24--> Authors</translate> ==
  
 +
<translate>
 +
<!--T:25-->
 
* Nicholas Guarino (Iron Realms Entertainment, Lusternia, Assistant Producer) <ianir@lusternia.com>;
 
* Nicholas Guarino (Iron Realms Entertainment, Lusternia, Assistant Producer) <ianir@lusternia.com>;
 
* Iron Realms Entertainment <support@ironrealms.com>
 
* Iron Realms Entertainment <support@ironrealms.com>
 +
* Vadim Peretokin <vadim.peretokin@mudlet.org></translate>
 +
 +
 +
== <translate><!--T:26--> Extra Notes</translate> ==
  
== Extra Notes for Testers ==
+
<translate><!--T:27-->
 +
Testers: make sure you enable GMCP:
  
 +
<!--T:28-->
 
<code>Core.Supports.Add ["External.Discord 1"]</code>
 
<code>Core.Supports.Add ["External.Discord 1"]</code>
 +
 +
<!--T:29-->
 +
Developers:
 +
 +
<!--T:30-->
 +
See [[Special:MyLanguage/Manual:Scripting#Discord_Rich_Presence|documentation]] for implementing this in Mudlet.
 +
</translate>

Latest revision as of 14:49, 2 January 2024

Other languages:
Deutsch • ‎English • ‎Nederlands • ‎Türkçe • ‎français • ‎italiano • ‎polski • ‎suomi • ‎Ελληνικά • ‎русский • ‎العربية • ‎한국어

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 specification.


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. It is a long number held in a quoted string.
  • Body: { inviteurl: "https://discord.gg/#####", applicationid: "…" }


External.Discord.Status

  • Send this whenever you need to send new status data to the client
  • 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>
  • Vadim Peretokin <vadim.peretokin@mudlet.org>


Extra Notes

Testers: make sure you enable GMCP:

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

Developers:

See documentation for implementing this in Mudlet.