Using GMCP - fiendish/aardwolfclientpackage GitHub Wiki
If you don't want to read about how GMCP works, skip down to the section GMCP How-To.
GMCP is a special case of something called "subnegotiations" in the Telnet data stream. Any time the server sends you the bytes [0xFF 0xFA]
1 and then some special number and then some data and then the bytes [0xFF 0xF0]
1, that is called a subnegotiation and the data is treated as an instruction for your client instead of being printed on the screen. GMCP is just2 what we call it when the server uses 201 for the special number and then formats the embedded data using the JSON data transmission format.
1 We call these bytes IAC SB
and IAC SE
, or Interpret As Command - Subnegotiation Begin
and Interpret As Command - Subnegotiation End
2 There are a few other rules, but they're not very important. (For a more detailed technical discussion of GMCP, see https://www.mushclient.com/gmcp)
MUSHclient enables us to write plugins to handle arbitrary subnegotiations, but it does not natively understand the GMCP number or the JSON formatting. To add that functionality we have the GMCP Handler plugin, which is provided with the Aardwolf MUSHclient Package. One of the results of not having true native support is that you cannot just add a "Trigger" for GMCP data through the MUSHclient GUI. You can access existing information using the methods shown below, but you can only get notified of new data via special messages which are only sent to plugins.
(If, after reading the rest of this, you strongly dislike the described approach, you can always petition for native GMCP trigger support on the MUSHclient forums at http://mushclient.com/forum/)
All "subnegotiation" messages in MUSHclient get read by the GMCP Handler plugin, which analyzes them for GMCP content and then announces to other plugins that it got a new GMCP message and which message it got. It doesn't announce the message contents, just which message arrived. You can then later inspect the latest received values for the announced message type.
When a char.status comes through, for example, it says "Hey everyone I got a new char.status". Then any script that is interested can request char.status values after that.
There are two ways to interact with GMCP.
- Ask the GMCP Handler plugin for existing data. This can be done from anywhere.
- Get notified when new GMCP data has arrived. This can only be done inside plugins because of the aforementioned technical limitation in MUSHclient's ability to natively handle GMCP.
All GMCP data is managed for you by the GMCP Handler plugin. To look at any of the values, you can ask the handler for them using the gmcp() helper function included in the lua/gmcphelper.lua Lua script file.
Note: You do not need to be working in a plugin to access GMCP data. You can do this in any of your triggers or aliases.
require "gmcphelper" -- adds the gmcp() function for simplifying data access
charstatus = gmcp("char.status") -- fetch char.status and return it as a Lua table
myState = tonumber(charstatus.state)
myLevel = tonumber(charstatus.level)
You could also fetch individual values directly like:
require "gmcphelper" -- adds the gmcp() function for simplifying data access
myState = tonumber(gmcp("char.status.state"))
myLevel = tonumber(gmcp("char.status.level"))
The GMCP handler plugin notifies other plugins of new data using the BroadcastPlugin function which runs the (optional) OnPluginBroadcast functions in all other plugins. In any plugin that wants to know when GMCP data has arrived, you can add function OnPluginBroadcast(msg, id, name, text) ... end
and look specifically for messages from the GMCP handler as described below.
A typical OnPluginBroadcast for GMCP messages using the gmcp() function given above might look like this...
require "gmcphelper" -- adds the gmcp() function for simplifying data access
function OnPluginBroadcast(msg, id, name, text)
if id == "3e7dedbe37e44942dd46d264" then -- message from the GMCP Handler
if (text == "char.status") then -- the GMCP Handler plugin says "I got a new char.status!"
charstatus = gmcp("char.status")
myLevel = tonumber(charstatus.level)
myState = tonumber(charstatus.state)
print("myLevel", myLevel, "myState", myState)
elseif (text == "comm.channel") then -- the GMCP Handler plugin says "I got a new chat!"
chat = gmcp("comm.channel")
print("got message from player", chat.player, ":", chat.msg)
end
end
end
Putting that into a basic plugin might look like this:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<muclient>
<plugin
name="TestReceiveGMCP"
author="Fiendish"
id="187e186c839d447cf932493e"
language="Lua"
purpose="Tests receiving new GMCP in the OnPluginBroadcast callback."
date_written="2016-08-25 17:26:00"
requires="4.70"
version="1.0"
>
</plugin>
<script>
<![CDATA[
require "gmcphelper" -- adds the gmcp() function for simplifying data access
function OnPluginBroadcast(msg, id, name, text)
if id == "3e7dedbe37e44942dd46d264" then -- message from the GMCP Handler
if (text == "char.status") then -- the GMCP Handler plugin says "I got a new char.status!"
charstatus = gmcp("char.status")
myLevel = tonumber(charstatus.level)
myState = tonumber(charstatus.state)
print("myLevel", myLevel, "myState", myState)
elseif (text == "comm.channel") then -- the GMCP Handler plugin says "I got a new chat!"
chat = gmcp("comm.channel")
print("got message from player", chat.player, ":", chat.msg)
end
end
end
function OnPluginInstall()
print("You've installed the GMCP test plugin.")
end
]]>
</script>
</muclient>
GMCP data is normally invisible, so the GMCP handler plugin provides a command for inspecting your incoming GMCP messages and the stored GMCP data.
-
gmcpdebug 1
will print the contents of each new GMCP message that arrives. -
gmcpdebug 2
will print the entire contents of your stored GMCP data when a new message arrives. -
gmcpdebug 0
disables debug messages.
For a description of all data sent by GMCP in Aardwolf, see: http://www.aardwolf.com/wiki/index.php/Clients/GMCP