关于GMCP协议和MSDP协议的说明

FluffOS v2019 运行时配置文件中增加了以下内容:

# telnet extensions support
; enable mxp : 0
; enable gmcp : 0
; enable zmp : 0
; enable mssp : 1

如果我们enable gmcp : 1即可开启服务器GMCP支持,那么GMCP是什么?有什么用?

GMCP是Generic Mud Communication Protocol的缩写,在通常情况下服务器端发送给客户端的内容都会显示出来,但MUD有时也希望发送一些不需要客户端显示出来的额外数据给客户端,这就是GMCP的作用。最直接的应用就是服务器把数据以变量和值的方式发送给客户端,客户端不需要自己写触发,直接使用收到的数据开发游戏机器人。

GMCP的历史始于2008年cMUD实施的使用Telnet代码200的Achaea Telnet客户端协议(ATCP)。然而,ATCP仅允许发送纯文本。2019年开发了MSDP(Mud服务器数据协议|Mud Server Data Protocol),提供了定义无类型变量、数组、表和命令的标准化方法。2010年,IRE组织推出了mudstandards.org,试图更新ATCP协议。

结果就是推出了使用TELNET代码201的ATCP2协议,该协议后来更名为GMCP。GMCP使用JSON语法定义类型化数据。除了发送结构化数据外,GMCP上的MSDP还提供了标准化的事件处理。通过GMCP实现MSDP的服务器将能够使用MSDP和JSON标准来定义结构化数据,并以任意一种格式执行MSDP事件处理。

GMCP 协议

GMCP作为Telnet RFC854、RFC855 选项的实现。服务器和客户端协商GMCP的使用,就像他们协商任何其他telnet 选项一样。一旦就选项的使用达成协议,即可用于在服务器和客户端之间交换信息。

Server 指令

IAC WILL GMCP    Indicates the server wants to enable GMCP.
IAC WONT GMCP    Indicates the server wants to disable GMCP.

Client 指令

IAC DO   GMCP    Indicates the client accepts GMCP sub-negotiations.
IAC DONT GMCP    Indicates the client refuses GMCP sub-negotiations.

握手(Handshake)

当客户端连接到启用GMCP的服务器时,服务器应发送IAC WILL GMCP。客户应以IAC DO GMCPIAC NOT GMCP响应。一旦服务器收到IAC DO GMCP,客户端和服务器都可以发送GMCP子协商。

客户端不应该发起协商,但是如果发生这种情况,服务器应该遵守状态更改。为了避免触发循环,服务器不应该响应来自客户端的协商,除非它正确地实现了RFC1143中的Q方法。

禁用 GMCP

当MUD服务器执行copyover时,它会丢失所有以前交换的GMCP数据。如果是这种情况,在实际copyover之前,MUD服务器应该发送IAC WONT GMCP,而客户端则应该完全禁用GMCP。copyover完成后,服务器和客户端的行为就像客户端刚刚连接一样,因此服务器应发送IAC WILL GMCP

当MUD客户端断线并重新连接时,它将丢失所有先前交换的GMCP数据。每当客户端重新连接时,服务器应重置其GMCP状态并重新协商GMCP。

GMCP 定义

GMCP             201

在 GMCP 上使用 MSDP

server - IAC WILL GMCP
client - IAC   DO GMCP
client - IAC   SB GMCP 'MSDP {"LIST" : "COMMANDS"}' IAC SE
server - IAC   SB GMCP 'MSDP {"COMMANDS":["LIST","REPORT","RESET","SEND","UNREPORT"]}' IAC SE

示例中单引号字符表示封装的文本是字符串,不应发送单引号本身。

数据格式(Data Format)

每个GMCP数据交换应使用IAC SB GMCP "<package.subpackage.command> <data>" IAC SE格式。

包名称可以不区分大小写。在GMCP上使用MSDP时,包名称视为区分大小写,MSDP必须完全大写。没有子包,因为它们不是必需的。

<data>字段是可选的,应该用空格与package字段隔开。在发送没有数据段的命令时,应省略空格。数据字段必须使用JSON数据语法,关键字使用UTF-8编码区分大小写。

在GMCP上使用MSDP时,必须始终设置<data>字段。如果MUD服务器专门使用MSDP over GMCP,则无需担心如何处理CORE.HELLOCORE.SUPPORTS包,因为只要客户端发送MSDP命令,该包就被视为已启用。

Packages

每个MUD服务器都需要定义和记录自己的包。更多文档可参考:


MSDP

编写和记录GMCP包可能相当麻烦。MSDP是自文档化的,相对来说比较简单,因为它附带了一个用C编写的灵活的事件处理程序。

GMCP之上的MSDP将JSON的流行与MSDP的多功能命令系统结合起来。它还允许客户端在使用MSDP、GMCP或两者之间进行选择。虽然JSON对于人类来说更容易阅读,但是MSDP对于机器来说更容易阅读,这使得MSDP更适合于创建动态生成的表。在客户端同时启用MSDP和GMCP的情况下,客户端应能够以可交换方式处理MSDP和GMCP数据,类似地,服务器应以可交换方式处理MSDP和GMCP数据,如MTH 1.5中的情况。

请记住,JSON不允许发送控制代码,而MSDP允许。与GMCP相比,MSDP的另一个优点是GMCP不是一个合适的协议,它基本上只告诉您使用JSON,但没有做要求和规定,如果您在Google上搜索,您会发现一些不一致的包定义。MSDP是一种真正的协议,它试图明确发送哪些数据、如何发送以及何时发送。

MSDP协议和GMCP协议的实现基本一样:

Server 指令

IAC WILL MSDP    Indicates the server wants to enable MSDP.
IAC WONT MSDP    Indicates the server wants to disable MSDP.

Client 指令

IAC DO   MSDP    Indicates the client accepts MSDP sub-negotiations.
IAC DONT MSDP    Indicates the client refuses MSDP sub-negotiations.

MSDP 定义

MSDP              69

MSDP_VAR           1
MSDP_VAL           2

MSDP_TABLE_OPEN    3
MSDP_TABLE_CLOSE   4

MSDP_ARRAY_OPEN    5
MSDP_ARRAY_CLOSE   6

MSDP 握手示例

server - IAC WILL MSDP
client - IAC   DO MSDP
client - IAC   SB MSDP MSDP_VAR "LIST" MSDP_VAL "COMMANDS" IAC SE
server - IAC   SB MSDP MSDP_VAR "COMMANDS" MSDP_VAL MSDP_ARRAY_OPEN MSDP_VAL "LIST" MSDP_VAL "REPORT" MSDP_VAL "SEND" MSDP_ARRAY_CLOSE IAC SE
client - IAC   SB MSDP MSDP_VAR "LIST" MSDP_VAL "REPORTABLE_VARIABLES" IAC SE
server - IAC   SB MSDP MSDP_VAR "REPORTABLE_VARIABLES" MSDP_VAL "HINT" IAC SE
client - IAC   SB MSDP MSDP_VAR "SEND" MSDP_VAL "HINT" IAC SE
server - IAC   SB MSDP MSDP_VAR "HINT" MSDP_VAL "THE GAME" IAC SE

示例中双引号字符表示封装的文本是字符串,不应发送双引号本身。

和GMCP只要求发送JSON数据相比,MSDP明确的规定了数据格式(变量、数组和表)。

变量(VAR)和值(VAL)

发送变量和值的标准格式: IAC SB MSDP MSDP_VAR <VARIABLE> MSDP_VAL <VALUE> IAC SE。为便于分析,变量和值不能包含NUL、MSDP_VAL、MSDP_VAR、MSDP_TABLE_OPEN、MSDP_TABLE_CLOSE、MSDP_ARRAY_OPEN、MSDP_ARRAY_CLOSE或IAC字节。

示例:

IAC SB MSDP MSDP_VAR "SEND" MSDP_VAL "HEALTH" IAC SE

引号字符表示封装的单词是字符串,不应发送引号本身。

表(Tables)

有时把数据以表的方式发送很有用,在MSDP中MSDP_VAL后使用MSDP_TABLE_OPENMSDP_TABLE_CLOSE,然后再在MSDP_TABLE_OPENMSDP_TABLE_CLOSE之间使用MSDP_VARMSDP_VAL定义变量和值,具体格式示例如下:

IAC SB MSDP MSDP_VAR "ROOM" MSDP_VAL MSDP_TABLE_OPEN MSDP_VAR "VNUM" MSDP_VAL "6008" MSDP_VAR "NAME" MSDP_VAL "The forest clearing" MSDP_VAR "AREA" MSDP_VAL "Haon Dor" MSDP_VAR "TERRAIN" MSDP_VAL "forest" MSDP_VAR "EXITS" MSDP_VAL MSDP_TABLE_OPEN MSDP_VAR "n" MSDP_VAL "6011" MSDP_VAR "e" MSDP_VAL "6007" MSDP_TABLE_CLOSE MSDP_TABLE_CLOSE IAC SE

引号字符表示封装的单词是字符串,不应发送引号本身。

表其实就类似于JSON、映射等数据类型在MSDP中的实现。

数组(Arrays)

当你需要在MSDP中发送数组时,使用以下方式:在MSDP中MSDP_VAL后使用MSDP_ARRAY_OPENMSDP_ARRAY_CLOSE,然后再在MSDP_ARRAY_OPENMSDP_ARRAY_CLOSE之间使用MSDP_VAL列出值。具体格式示例如下:

IAC SB MSDP MSDP_VAR "REPORTABLE_VARIABLES" MSDP_VAL MSDP_ARRAY_OPEN MSDP_VAL "HEALTH" MSDP_VAL "HEALTH_MAX" MSDP_VAL "MANA" MSDP_VAL "MANA_MAX" MSDP_ARRAY_CLOSE IAC SE

引号字符表示封装的单词是字符串,不应发送引号本身。

可报告的MSDP变量

相比GMCP对包和变量没有任何要求,MSDP则有一些约定,这些变量只是对想要实现MSDP的MUD的建议。通过使用这些可报告变量,可以更轻松地创建MSDP脚本,这些脚本只需很少或不需要修改即可跨MUD工作。如果您除了这些变量之外还创建了自己的变量集,建议您创建一个扩展的在线规范来描述您的变量及其行为。SPECIFICATION变量可用于将用户链接到网页。

General

"ACCOUNT_NAME"         Name of the player account.
"CHARACTER_NAME"       Name of the player character.
"SERVER_ID"            Name of the MUD, or an otherwise unique ID.
"SERVER_TIME"          The time on the server using either military or civilian time.
"SPECIFICATION"        URL to the MUD's online MSDP specification, if any.

Character

"AFFECTS"              Current affects in array format.
"ALIGNMENT"            Current alignment.
"EXPERIENCE"           Current total experience points. Use 0-100 for percentages.
"EXPERIENCE_MAX"       Current maximum experience points. Use 100 for percentages.
"EXPERIENCE_TNL"       Current total experience points Till Next Level. Use 0-100 for percentages.
"EXPERIENCE_TNL_MAX"   Current maximum experience points Till Next Level. Use 100 for percentages.
"HEALTH"               Current health points.
"HEALTH_MAX"           Current maximum health points.
"LEVEL"                Current level.
"MANA"                 Current mana points.
"MANA_MAX"             Current maximum mana points.
"MONEY"                Current amount of money.
"MOVEMENT"             Current movement points.
"MOVEMENT_MAX"         Current maximum movement points.

Combat

"OPPONENT_LEVEL"       Level of opponent.
"OPPONENT_HEALTH"      Current health points of opponent. Use 0-100 for percentages.
"OPPONENT_HEALTH_MAX"  Current maximum health points of opponent. Use 100 for percentages.
"OPPONENT_NAME"        Name of opponent.
"OPPONENT_STRENGTH"    Relative strength of opponent, like the consider mud command.

Mapping

Indentation indicates the variable is nested within the parent variable using a table.

"ROOM"
  "VNUM"               A number uniquely identifying the room.
  "NAME"               The name of the room.
  "AREA"               The area the room is in.
  "COORDS"
    "X"                The X coordinate of the room.
    "Y"                The Y coordinate of the room.
    "Z"                The Z coordinate of the room.
  "TERRAIN"            The terrain type of the room. Forest, Ocean, etc.
  "EXITS"              Nested abbreviated exit directions (n, e, w, etc) and corresponding destination VNUMs.

World

"WORLD_TIME"           The in game time on the MUD using either military or civilian time.

Configurable MSDP Variables

Configurable variables are variables on the server that can be altered by the client. Implementing configurable variable support is optional.

General

"CLIENT_NAME"          Name of the MUD client.
"CLIENT_VERSION"       Version of the MUD client.
"PLUGIN_ID"            Unique ID of the MSDP plugin/script.

Generic MSDP Commands

These are variables that behave as commands for more complex server - client interaction. Implementing the following 5 MSDP commands correctly is essential.

LIST

The LIST command can be used by either side, but should typically be used by the client. To request a list of commands use IAC SB MSDP MSDP_VAR "LIST" MSDP_VAL "COMMANDS" IAC SE. The receiver in turn should send back the "COMMANDS" variable with an array of values containing supported commands, for example:

IAC SB MSDP MSDP_VAR "COMMANDS" MSDP_VAL MSDP_ARRAY_OPEN MSDP_VAL "LIST" MSDP_VAL "REPORTABLE_VARIABLES" MSDP_ARRAY_CLOSE IAC SE

The following list options are suggested:

"COMMANDS"               Request an array of commands supported by the server.
"LISTS"                  Request an array of lists supported by the server.
"CONFIGURABLE_VARIABLES" Request an array of variables the client can configure.
"REPORTABLE_VARIABLES"   Request an array of variables the server will report.
"REPORTED_VARIABLES"     Request an array of variables currently being reported.
"SENDABLE_VARIABLES"     Request an array of variables the server will send.

client - IAC SB MSDP MSDP_VAR "LIST" MSDP_VAL "CONFIGURABLE_VARIABLES" IAC SE
server - IAC SB MSDP MSDP_VAR "CONFIGURABLE_VARIABLES" MSDP_VAL MSDP_ARRAY_OPEN MSDP_VAL "UTF_8" MSDP_VAL "XTERM_256_COLORS" MSDP_ARRAY_CLOSE IAC SE
client - IAC SB MSDP MSDP_VAR "UTF_8" MSDP_VAL "0" MSDP_VAR "XTERM_256_COLORS" MSDP_VAL "1" IAC SE

REPORT

The REPORT command can be used by either side, but should typically be used by the client. After the client has received a list of reportable variables, or already knows which variables are supported, it can request the server to start reporting those variables. When receiving a REPORT request the server should send the requested variables to the client, and re-send each individual variable whenever it changes. Instead of sending MSDP_VAR "REPORT" MSDP_VAL "HEALTH" MSDP_VAR "REPORT" MSDP_VAL "HEALTH_MAX" it is allowed to string values together for command-like variables, in this case: MSDP_VAR "REPORT" MSDP_VAL "HEALTH" MSDP_VAL "HEALTH_MAX".

client - IAC SB MSDP MSDP_VAR "LIST" MSDP_VAL "REPORTABLE_VARIABLES" IAC SE
server - IAC SB MSDP MSDP_VAR "REPORTABLE VARIABLES" MSDP_VAL MSDP_ARRAY_OPEN MSDP_VAL "MUD_TIME" MSDP_VAL "SERVER_TIME" MSDP_ARRAY_CLOSE IAC SE
client - IAC SB MSDP MSDP_VAR "REPORT" MSDP_VAL "MUD TIME" IAC SE
server - IAC SB MSDP MSDP_VAR "MUD TIME" MSDP_VAL "14:00" IAC SE
server - IAC SB MSDP MSDP_VAR "MUD TIME" MSDP_VAL "15:00" IAC SE

RESET

The RESET command works like the LIST command, and can be used to reset groups of variables to their initial state. Most commonly RESET will be called with REPORTABLE_VARIABLES or REPORTED_VARIABLES as the argument, though any LIST option can be used.

client - IAC SB MSDP MSDP_VAR "RESET" MSDP_VAL "CHESS_MINIGAME" IAC SE

SEND

The SEND command can be used by either side, but should typically be used by the client. After the client has received a list of variables, or otherwise knows which variables exist, it can request the server to send those variables and their values with the SEND command. The value of the SEND command should be a list of variables the client wants returned.

client - IAC SB MSDP MSDP_VAR "SEND" MSDP_VAL "AREA NAME" MSDP_VAL "ROOM NAME" IAC SE
server - IAC SB MSDP MSDP_VAR "AREA NAME" MSDP_VAL "Tower of Entropy" MSDP_VAR "ROOM NAME" MSDP_VAL "Tower Pinnacle" IAC SE

UNREPORT

The UNREPORT command is used to remove the report status of variables after the use of the REPORT command.

client - IAC SB MSDP MSDP_VAR "UNREPORT" MSDP_VAL "MUD TIME" MSDP_VAL "NEWBIE_CHANNEL" IAC SE

客户端脚本开发参考tintin++

    #variable TELNET[IAC]  \xFF;
    #variable TELNET[DONT] \xFE;
    #variable TELNET[DO]   \xFD;
    #variable TELNET[WONT] \xFC;
    #variable TELNET[WILL] \xFB;
    #variable TELNET[SB]   \xFA;
    #variable TELNET[SE]   \xF0;
    #variable TELNET[GMCP] \xC9;
    #variable TELNET[MSDP] \x45;
    #variable MSDP[VAR]   \x01;
    #variable MSDP[VAL]   \x02;
    #variable MSDP[TABLE_OPEN]  \x03;
    #variable MSDP[TABLE_CLOSE] \x04;
    #variable MSDP[ARRAY_OPEN]  \x05;
    #variable MSDP[ARRAY_CLOSE] \x06;

服务端开发游戏相关教程


支持 MSDP 和 GMCP 的客户端

相关文档

京ICP备13031296号-4