Standards:MUD Client Media Protocol

From Mudlet
Jump to navigation Jump to search
This page contains changes which are not marked for translation.

MUD Client Media Protocol (MCMP)

A Standard for Loading, Playing and Stopping Media Files with MUD Clients over GMCP

Version 2 is a proposal, open for discussion.

  • Everything on this page outside the boxes marked Proposed for version 2 is version 1, which is unchanged. Version 1 clients and servers can keep reading this page as before.
  • Version 2 adds only optional keys and messages, so a version 1 client keeps working with a version 2 game:
    • pan and direction on Client.Media.Play place a sound to the left or right, or in a direction such as north or behind.
    • Client.Media.Update moves a sound that is already playing, or changes its volume.
    • Client.Media.Listener tells the client which way the player faces, for games that have a facing.
  • Please join the discussion in the MUDstandards channel of the MUD Discord server, and see the open questions below.


Status of this Memo

This memo describes the addition of a standardized namespace of the Generic Mud Communication Protocol (GMCP) telnet sub-negotiation protocol (201) that provides syntax and usage guidance for sending JSON formatted messages from game servers to text-based game clients to load, play and stop media files.


Overview and Rationale

With renewed interest in the MUD genre of gaming, expectations are high to provide sight and sound content that competes for audience with other gaming platforms. The purpose of the MUD Client Media Protocol (MCMP) is to establish a method of delivering media, such as game sounds, background music and video snippets, to text-based game clients via their widely accepted messaging platform, GMCP, which uses JSON as its data-interchange format. The intended return for introducing this protocol is to improve the MUD gaming experience and accessibility through standardized messaging between game servers and game clients. MUD Client Media Protocol (MCMP) is inspired by its predecessor Mud Sound Protocol (MSP).


Overview of the GMCP (201) Sub-negotiation Protocol

To recap, the GMCP protocol is a bidirectional telnet sub-negotiation 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.


Update to namespace: Client.* for Client.Media

We are proposing an addition to the Client.* meta-namespace for Client.Media. This serves the purpose of reserving this namespace for handling game client media operations and supporting future expansion and integration.


Video Demonstration of Client.Media

Specification for Client.Media

The Client.Media family of GMCP packages provide a way for games to send sound, music and video events. GMCP media events are sent in one direction: from game server to to game client. Media files may be downloaded manually by the user and/or automatically via the game client. Game clients should advertise to servers that Client.Media is supported with a Core.Supports message from game client to server.

Core.Supports.Set ["Client.Media 1", ...]

Proposed for version 2: advertising and compatibility

  • A client that supports version 2 advertises it with the version number, as other GMCP packages do when they grow:
Core.Supports.Set ["Client.Media 2", ...]
  • A server that checks only for the package name, Client.Media, keeps working with both versions.
  • Version 2 adds only optional keys and new messages. A version 1 client ignores keys it does not know and plays the sound as before, and ignores messages it does not know. So a server may send version 2 keys to every client.
  • A server should check for version 2 before its gameplay depends on hearing where a sound comes from, such as an audio-only puzzle.
  • Version 2 adds no new values for "type". Some version 1 clients drop a whole message whose "type" they do not know.

Commands - Server

Due to the limitations for legacy gaming platforms supporting all JSON data types, such as boolean (true and false), game clients should support parsing of values within the Client.Media namespace also as strings (surrounded by quotes).

Client.Media.Default

  • Package: Client.Media.Default
  • Purpose: Identify to the game client a default URL directory to load media files from an external resource.
  • Guidance: For games that automatically download media files, perform a Client.Media.Default GMCP event once upon player login.

Syntax:

Client.Media.Default {"url": "hxxps://www.example.com/media/"}

Usage:

Required Key Value Purpose
Yes "url" <url>
  • Resource location where the media file may be downloaded.
  • Last character must be a / (slash).


Note Note:

Some examples are shown here.

Client.Media.Load

  • Package: Client.Media.Load
  • Purpose: Load media files from an external source.
  • Guidance: For games that automatically download media files and have the capability to cache with the game client.

Syntax:

Client.Media.Load {
  "name": "sword1.mp3",
  "url": "hxxps://www.example.com/media/"
}

Usage:

Required Key Value Purpose
Yes "name" <file name>
  • Name of the media file.
  • May contain directory information (i.e. weather/lightning.mp3).
Maybe "url" <url>
  • Resource location where the media file may be downloaded.
  • Last character must be a / (slash).
  • Only required if a url was not set with Client.Media.Default.


Note Note:

Some examples are shown here.


Client.Media.Play

  • Package: Client.Media.Play
  • Purpose: Play media files.
  • Guidance: Game clients could choose whether to play only one media file at one time or multiple files at one time.

Syntax:

Client.Media.Play {
  "name": "80_Blacksmith_Shoppe.mp3",
  "url": "hxxps://www.example.com/media/",
  "type": "music",
  "tag": "environment",
  "volume": 25,
  "fadein": 5000,
  "fadeout": 7000,
  "start": 1000,
  "finish": 20000,
  "loops": 3,
  "priority": 60,
  "continue": true,
  "key": "area-background-music",
  "caption": "Blacksmith Hammering"
}

Usage:

Required Key Value Default Purpose
Yes "name" <file name>  
  • Name of the media file.
  • May contain directory information (i.e. weather/lightning.mp3).
Maybe "url" <url>  
  • Resource location where the media file may be downloaded.
  • Last character must be a / (slash).
  • Only required if the file is to be downloaded remotely and a url was not set above with Client.Media.Default or Client.Media.Load.
No "type" "sound", "music" or "video" "sound"
  • Identifies the type of media.
No "tag" <tag>  
  • Helps categorize media.
No "volume" 1 to 100 50
  • Relative to the volume set on the player's client.
No "fadein" <msec>  
  • Volume increases, or fades in, ranged across a linear pattern from one to the volume set with the "volume" key.
  • Start position: Start of media.
  • End position: Start of media plus the number of milliseconds (msec) specified.
  • 1000 milliseconds = 1 second.
No "fadeout" <msec>  
  • Volume decreases, or fades out, ranged across a linear pattern from the volume set with the "volume" key to one.
  • Start position: End of the media minus the number of milliseconds (msec) specified.
  • End position: End of the media.
  • 1000 milliseconds = 1 second.
No "start" <msec> 0
  • Begin play at the specified position in milliseconds.
  • 1000 milliseconds = 1 second.
No "finish" <msec> 0
  • End play at the specified position in milliseconds.
  • 1000 milliseconds = 1 second.
No "loops" -1, or >= 1 1
  • Number of iterations that the media plays.
  • A value of -1 allows the sound or music to loop indefinitely.
No "priority" 1 to 100  
  • Halts the play of current or future played media files with a lower priority while this media plays.
No "continue" true or false true
  • Continues playing matching new music files when true.
  • Restarts matching new music files when false.
No "key" <key>  
  • Uniquely identifies media files with a "key" that is bound to their "name" or "url".
  • Halts the play of current media files with the same "key" that have a different "name" or "url" while this media plays.
No "caption" <text>  
  • Caption-friendly textual representation of the media, such as onomatopoeia or sound cues (e.g., `thunderclap`, `whoosh`), enabling accessibility.


Note Note:

To support players with hearing impairments or who prefer captioned media, the caption field may be used to provide contextual and caption-style text. For best practices, see Captioning Key: Sound Effects and Music.

Note Note:

Some examples are shown here.

Proposed for version 2: where a sound comes from

Two new optional keys on Client.Media.Play. A version 1 client ignores them and plays the sound as it always has.

Syntax:

Client.Media.Play {
  "name": "door-creak.wav",
  "key": "north-door",
  "volume": 60,
  "direction": "north",
  "caption": "a door creaks"
}

Usage:

Required Key Value Default Purpose
No "direction" a direction word, or degrees from 0 to 359 none: the sound plays as recorded, as in version 1
  • Where the sound comes from.
  • Compass words are the ones MUD exits use: "north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest", "up" and "down", and the short forms "n", "ne", "e", "se", "s", "sw", "w", "nw", "u" and "d".
  • Relative words are "ahead", "behind", "left" and "right".
  • In degrees, 0 is north and 90 is east.
No "pan" -100 to 100 none: the sound plays as recorded
  • Left (-100) to right (100), for games that think in speakers rather than compass points, or want a fixed placement.
  • 0 places the sound in the centre, which is not the same as giving no pan.
  • With no facing, north is ahead and east is to the right, like a map with north at the top. A game whose player has a facing can say so with Client.Media.Listener.
  • Relative words are always relative to the player and ignore the facing: "ahead" is 0°, "right" 90°, "behind" 180° and "left" 270°. They are for games without compass exits.
  • A word the client does not recognise is ignored, and the sound plays as with no direction, so a game can pass any exit name. For a sound through an exit with no compass direction, such as "in" or a portal, say where it comes from in "caption", e.g. "footsteps from the shop".
  • Each client renders as much as it can:
    • A client with 3D audio, such as on headphones, places the sound in its direction, including behind, above and below. A compass direction's angle from the player is its bearing minus the facing.
    • A stereo client turns a direction into pan = 100 × sin(direction): east is fully right, west fully left, and north and south are centred. "up" and "down" stay centred.
    • A client with no panning plays the sound centred, as in version 1.
  • A placed sound is heard from one point: a stereo recording is mixed to one point first. A sound with neither "direction" nor "pan" plays as recorded, stereo image included.
  • When a message has both "pan" and "direction", a 3D client uses "direction" and a stereo client uses "pan". That lets a game tune the result for each kind of client.
  • Captions: a version 2 client adds the direction to the caption it shows, e.g. "a door creaks (north)", so that where a sound comes from never depends on hearing it.
  • Music and video: these keys are for sounds. Clients may ignore "direction" and "pan" on "music" and "video".
  • "pan" uses the same -100 to 100 scale as MUSHclient's PlaySound, and the same key as the Mongoose MOO web client's MCMP extension, so a game sending "pan" today is understood by more than one client.

Client.Media.Update

Proposed for version 2: a new message

  • Package: Client.Media.Update
  • Purpose: Move a sound that is already playing, or change its volume, without restarting it.
  • Guidance: Covers sounds that travel, such as footsteps coming up from behind or an arrow in flight: send a few updates as the sound moves. A version 1 client ignores this message, so the sound stays where it started.

Syntax:

Client.Media.Update {
  "key": "dragon",
  "direction": "south",
  "volume": 80,
  "duration": 2000
}

Usage:

Required Key Value Default Purpose
Maybe "key" <key>  
  • Selects the playing media to change by key.
  • At least one of "key", "name" or "tag" is required.
  • To move several copies of one sound separately, give each its own key when it is played, e.g. "arrow-1" and "arrow-2".
Maybe "name" <file name>  
  • Selects the playing media to change by name, the same way Client.Media.Stop does. Every playing copy of that file changes.
Maybe "tag" <tag>  
  • Selects the playing media to change by tag, the same way Client.Media.Stop does.
No "type" "sound", "music" or "video" any
  • Narrows the selection to one type.
  • On its own it selects nothing, as it would otherwise change every sound of that type.
No "volume" 1 to 100 unchanged
  • The new volume.
No "direction" as on Client.Media.Play unchanged
  • The new direction.
No "pan" -100 to 100 unchanged
  • The new pan.
No "duration" <msec> 0
  • How long the change takes: the sound glides from its old values to the new ones over this many milliseconds. A travelling sound gives the time it takes to get there.
  • 0 makes the change at once. A client may take up to 20 milliseconds over it, so that the jump does not click.
  • Straight after a Play: an update may follow its Play at once, before the file has loaded or downloaded. It applies once the sound plays.
  • Captions: a client does not caption an update. The Play was captioned, and an update only changes how that sound is heard.

Client.Media.Listener

Proposed for version 2: a new, optional message

  • Package: Client.Media.Listener
  • Purpose: Tell the client which way the player faces, so that compass directions are heard relative to it.
  • Guidance: Most games never send it. Ships, vehicles and games that say "to your left" would. A version 1 client ignores it.

Syntax:

Client.Media.Listener {"facing": "east"}

Usage:

Required Key Value Default Purpose
Yes "facing" a compass word, or degrees from 0 to 359 "north"
  • Turns the compass: facing "east", a sound from the east is ahead and one from the north is to the left.
  • Relative words ("ahead", "behind", "left" and "right") are unaffected: they are always relative to the player.
  • A facing lasts for the connection: after a reconnect the client faces north again, or the player's own choice where the client offers one, until the game sends Client.Media.Listener again.

Client.Media.Stop

  • Package: Client.Media.Stop
  • Purpose: Stop playing media files.
  • Guidance: An empty body will stop all media.

Syntax:

Client.Media.Stop {
  "name": "city.mp3",
  "type": "music",
  "tag": "environment",
  "priority": 60,
  "key": "area-background-music",
  "fadeaway": true,
  "fadeout": 7000
}

Usage:

Required Key Value Purpose
No "name" <file name>
  • Stops playing media by name matching the value specified.
No "type" "sound", "music" or "video"
  • Stops playing media by type matching the value specified.
No "tag" <tag>
  • Stops playing media by tag matching the value specified.
No "priority" 1 to 100
  • Stops playing media with priority less than or equal to the value.
No "key" <key>
  • Stops playing media by key matching the value specified.
No "fadeaway" true or false
  • Decrease volume from the current position for a given duration, then stops the track.
  • Given duration is the lesser of the remaining track duration or the fadeout specified in Client.Media.Play.
  • If fadeout was not specified in Client.Media.Play, then the optional fadeout parameter from Client.Media.Stop or a default of 5000 milliseconds will be applied.
No "fadeout" <msec>
  • Default duration in milliseconds to decrease volume to the end of the track.
  • Only used if fadeout was not defined in Client.Media.Play.


Note Note:

Some examples are shown here.

Open questions for version 2

These are open for discussion in the MUDstandards channel of the MUD Discord server:

  1. Height in 3D: at what angle should a 3D client place "up" and "down"? Directly overhead and underfoot (90°) are hard to hear on headphones; audio games usually use 45° to 60°.
  2. Left out on purpose:
    • "distance": "volume" stays the one control of loudness, so a sound is never made quieter twice.
    • Separate ids for each playing sound: a key already names one sound, so each copy that should move on its own is given its own key.
    • Attaching a position to a later Play: a game can add "direction" to the Play it sends.
    • Height in degrees: "up" and "down" are how MUDs describe height.
    • A separate package wrapping Client.Media.Play: a version 1 client ignores the new keys, so a game sends one message to every client.
    • Coordinates, rooms and reverb: these need an agreed frame of reference (which axis is north, which way is up, and what the units are), and clients that already use coordinates disagree on it. They could be a later version.

Best Practices for Server Implementors

In keeping with best practices widely adopted in modern web applications and browsers, server-side implementors of the `Client.Media` protocol are advised to consider the following:

  • Avoid Autoplay Before User Interaction: Media files should not be played immediately upon client connection, especially before the user has had an opportunity to interact with the game environment. Autoplaying media without user initiation may be blocked or suppressed by some clients, particularly web-based ones, and can create a disruptive experience for players.
  • Use Secure Media URLs: Whenever possible, media files should be served via secure HTTPS URLs. Serving media over insecure HTTP links may trigger mixed content security warnings or result in blocked requests in web-based clients or modern operating systems with strict security policies.

Notes for Web Client Developers

Developers of web-based Mud clients should be aware of the following constraints that may impact media playback behavior:

  • Most browsers impose restrictions on media autoplay unless the user has interacted with the page. This may prevent `Client.Media.Play` messages sent immediately after connection from functioning as intended.
  • Serving media over non-HTTPS URLs may result in blocked requests or mixed content warnings, depending on the browser and hosting setup.

These limitations are imposed by browser security models and are not under the control of the game server or client developers. Where possible, client developers may want to inform users or log these situations for debugging.

Proposed for version 2: panning in a browser

  • A browser can pan media from another site only when that site sends CORS headers; otherwise the panned sound comes out silent. This is one reason clients may ignore "pan" and "direction" on music, which is often streamed from elsewhere.

Versions

  • Version 1.0: Initial specification.
  • Version 1.0.1: fadein, fadeout and start added to Client.Media.Play by Mike Conley (mike.conley[at]stickmud.com) on 22-DEC-2021.
  • Version 1.0.2: finish added to Client.Media.Play and fadeaway and fadeout added to Client.Media.Stop by Mike Conley (mike.conley[at]stickmud.com) on 10-DEC-2023.
  • Version 1.0.3: caption added to Client.Media.Play for improved accessibility by Mike Conley (mike.conley[at]stickmud.com) on 10-MAY-2025.
  • Version 2 (proposed, under discussion): direction and pan added to Client.Media.Play; Client.Media.Update and Client.Media.Listener added; "Client.Media 2" advertised in Core.Supports. Proposed by Mike Conley (mike.conley[at]stickmud.com) in October 2026.

Consider advertising your games support of MCMP (and GMCP) to mud lists via the Mud Server Status Protocol, MSSP, by providing a MSSP variable of "MCMP" and value of "1".

Proposed for version 2: a game that sends version 2 messages would give "MCMP" the value "2".

Authors

  • Mike Conley (Tamarindo, Co-Administrator at StickMUD and Mudlet contributor) mike.conley[at]stickmud.com
  • Eric Oestrich (Developer of ExVenture and Grapevine) eric[at]oestrich.org

Clients

  • Known clients implementing this specification:
    • Mudlet version 4.4+. See documentation.
    • BeipMU version 4.00.298 implements basic load/play/stop commands.
    • LociTerm version 2.5.1 and beyond.