Hmm. I'm not sure how I feel about this variant of the GMCP handler plugin. The one I use for Aardwolf does the JSON parsing for you. That one leaves it up to the receiver, which means that ever receiver needs to re-parse the message again if multiple plugins want to use the same messages.
I think you might be happier using my version. Here is the one I use for Aardwolf with some minor edits to remove anything overtly Aardwolf-specific (hopefully it still works!):
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<muclient>
<plugin
name="GMCP_handler"
author="Fiendish"
id="3e7dedbe37e44942dd46d264"
language="Lua"
purpose="Handle GMCP messages and broadcast data"
save_state="y"
date_written="2010-08-02 14:16:26"
requires="4.59"
version="1.0"
>
<description trim="y">
Aardwolf-style GMCP Handler
Purpose is to process incoming GMCP messages, notify other plugins
of arrival of new data, and make that data accessible.
For Mushclient specific information on how to access GMCP data, see:
https://github.com/fiendish/aardwolfclientpackage/wiki/Using-GMCP
</description>
</plugin>
<aliases>
<alias
script="gmcpdebug"
match="^gmcpdebug (.*)?$"
enabled="y"
regexp="y"
sequence="100"
ignore_case="y"
></alias>
<alias
match="sendgmcp *"
script="GMCP_Alias"
enabled="y"
send_to="12"
sequence="100"
></alias>
</aliases>
<!-- Get our standard constants -->
<script>
<![CDATA[
require "json"
require "serialize"
require "gmcphelper"
local IAC, SB, SE, DO = 0xFF, 0xFA, 0xF0, 0xFD
local GMCP = 201
local GMCPDebug = tonumber(GetVariable("GMCPDebug")) or 0
-- You can use CallPlugin to access any gmcp data via this function.
-- example:
-- local ret, datastring = CallPlugin("3e7dedbe37e44942dd46d264", "gmcpdata_as_string", "char.status")
-- pcall(loadstring("status_table = "..datastring))
-- for k,v in pairs(status_table) do
-- print(k,":",v)
-- end
function gmcpdata_as_string(what)
return serialize.save_simple(gmcpdata_at_level(what) or "")
end
-- toggle debug output
function gmcpdebug(name, line, wildcards)
local newval = tonumber(wildcards[1])
if not newval or newval > 2 or newval < 0 then
ColourNote("#FFAF00", "", "GMCPDebug valid values are: 0 - off, 1 - simple, 2 - verbose")
return
end
GMCPDebug = newval
local msg = "off"
if GMCPDebug == 1 then
msg = "simple"
elseif GMCPDebug == 2 then
msg = "verbose"
end
ColourNote ("#FFAF00", "", "GMCPDebug: " .. msg)
end
function GMCP_send(what)
if what == nil then
print("GMCP_send passed a nil message.")
return
end
SendPkt (string.char (IAC, SB, GMCP) ..
(string.gsub (what, "\255", "\255\255")) .. -- IAC becomes IAC IAC
string.char (IAC, SE))
end
function GMCP_Alias (name, line, wildcards)
GMCP_send(wildcards[1])
end
function OnPluginTelnetSubnegotiation (msg_type, data)
if msg_type ~= GMCP then
return
end -- if not GMCP
if GMCPDebug > 0 then ColourNote ("#FFAF00", "", utils.utf8convert(data)) end
message, params = string.match (data, "([%a.]+)%s+(.*)")
if not message then
return
end -- if
if not string.match (params, "^[%[{]") then
params = "[" .. params .. "]" -- JSON hack, make msg first element of an array. (I don't think this is needed - fiendish)
end -- if
local succ, t = pcall(json.decode,params)
if succ and type(t) == "table" then
gmcpdata = gmcpdata or {}
-- find where to insert the new data
local node = gmcpdata
local prev_node = nil
local prev_item = ""
for next_item in string.gmatch(message,"%a+") do
node[next_item] = node[next_item] or {}
prev_node = node
prev_item = next_item
node = node[next_item]
end
-- A loveletter.
-- Some GMCP messages are just messages, not state. The "current" comm.channel message isn't a meaningful
-- concept except in the exact moment it arrives, for example (though most recent might be).
-- Since room.area is not sent automatically, and is only ever sent in response to a request,
-- having seen a room.area message tells you only what the area details were for the area your
-- character was in at the time the request was processed, but has no relation to where you are
-- after or even to the area your character was in when the request was sent and especially not
-- to the actual transition from one area to the next. If you run 5e through an area entrance,
-- you would be 5 rooms deep into a new area before that area info arrives back to you, with
-- mismatching area info the whole way in.
-- (You send run 5e, you go e, new area in room.info triggers sending request for room.area, you go 4e,
-- room.area request seen by game, room.area response sent back, room.area response seen by client)
-- If you had also run back out of the area, then you'd also be receiving room.area information
-- after five moves for an area you are no longer in.
-- I do this next part for your own good.
if (message == "room.info") then
gmcpdata["room"] = {}
prev_node = gmcpdata["room"]
end
prev_node[prev_item] = t
if GMCPDebug > 1 then
print ("gmcpdata serialized: " .. gmcpdata_as_string(""))
end
BroadcastPlugin(1, message)
else
ColourNote("white","red","GMCP DATA ERROR: "..t)
end -- if
end -- function OnPluginTelnetSubnegotiation
function gmcpdata_at_level(what)
local node = gmcpdata
for level in string.gmatch(what, "%a+") do
if (type(node) ~= "table" or node[level] == nil) then return end
node = node[level]
end
return node
end
function OnPluginSaveState()
SetVariable("GMCPDebug", GMCPDebug)
end
function OnPluginTelnetRequest (msg_type, data)
if msg_type == GMCP and data == "WILL" then
return true
end -- if
if msg_type == GMCP and data == "SENT_DO" then
-- This hard-coded block may need to be made into a config table as we add more message types.
Send_GMCP_Packet (string.format ('Core.Hello { "client": "MUSHclient", "version": "%s" }', Version()))
Send_GMCP_Packet ('Core.Supports.Set [ "Char 1", "Comm 1", "Room 1" ]')
return true
end -- if GMCP login needed (just sent DO)
return false
end -- function OnPluginTelnetRequest
function OnPluginDisable()
EnablePlugin(GetPluginID(), true)
ColourNote("white", "blue", "You are not allowed to disable the "..
GetPluginInfo(GetPluginID(), 1).." plugin. It is necessary for other plugins.")
end
]]>
</script>
</muclient>
If you use that along with this helper file (it goes in your MUSHclient/lua folder) https://raw.githubusercontent.com/fiendish/aardwolfclientpackage/MUSHclient/MUSHclient/lua/gmcphelper.lua
Then you'll be able to follow my instructions for how to use GMCP: https://github.com/fiendish/aardwolfclientpackage/wiki/Using-GMCP |