I'm having some rather odd problems, and I'm not sure what's going on. I'm using my ATCP plugin, which broadcasts to other plugins to ask if they need any modules enabled, then sends the resulting 'hello' ATCP message to the server. I have four plugins that use this functionality currently, each requesting one module: room_brief, char_vitals, and two requests for room_exits.
When I load up MUSHclient and connect, the message sends for char_vitals and room_brief, but not room_exits. Disabling one of the room_exits plugins fixes this problem, but I'm not sure why. (The code that sets the modules is located in EnableModule())
The second problem that I'm experiencing is, when I disconnect and then reconnect, sometimes (pretty frequently) no modules are enabled even though I know the broadcast is being responded to. I have -no- idea what's causing this.
Help would be majorly appreciated! =/
MUSHclient version is 4.40.
codes = {
["IAC WILL ATCP"] = "\255\251\200", -- server-sent
["IAC WONT ATCP"] = "\255\252\200", -- server-sent
["IAC DO ATCP"] = "\255\253\200", -- client-sent, enables ATCP
["IAC SB ATCP"] = "\255\250\200", -- begins an ATCP packet
["IAC SE"] = "\255\240", -- ends an ATCP packet
["IAC WILL EOR"] = "\255\251\025", -- ???
}
client_id = "MUSHclient " .. Version()
nexus_opts = {}
commands = {}
mods = {auth = {version = "1"},
char_name = {version = "1"},
char_vitals = {version = "1"},
room_brief = {version = "1"},
room_exits = {version = "1"},
map_display = {version = "1"},
composer = {version = "1"},
keepalive = {version = "1"},
topvote = {version = "1"},
ping = {version = "1"},
}
OnPluginConnect = function()
-- alert other plugins to EnableModule now.
BroadcastPlugin(0, "")
local msg = "hello " .. client_id .. "\10"
local line = ""
for k, v in pairs(nexus_opts) do
line = line .. k .. ", "
msg = msg .. k .. " " .. v .. "\10"
end
Note(line:sub(1, line:len() - 2))
SendPkt(codes["IAC DO ATCP"] .. codes["IAC SB ATCP"] .. msg .. codes["IAC SE"])
end
OnPluginDisconnect = function()
nexus_opts = {}
commands = {}
end
OnPluginPacketReceived = function(packet)
if string.find (packet, codes["IAC WILL ATCP"]) then
packet = string.gsub (packet, "(.-)" .. codes["IAC WILL ATCP"] .. "(.-)", "%1%2")
end
if string.find (packet, codes["IAC WONT ATCP"]) then
packet = string.gsub (packet, "(.-)" .. codes["IAC WONT ATCP"] .. "(.-)", "%1%2")
end
if string.find (packet, codes["IAC WILL EOR"]) then
packet = string.gsub (packet, "(.-)" .. codes["IAC WILL EOR"] .. "(.-)", "%1%2")
end
local packet, atcp, parsed = parseATCP(packet)
-- pack up the messages and send them to listeners
for msg, line in pairs(parsed) do
BroadcastPlugin(1, msg .. "|" .. line)
end
return packet
end
-- splits an ATCP message into header and content lines
split_atcp = function(msg)
-- find a Something.Something marker
-- (i.e. Room.Brief, Char.Vitals)
-- match1
local start, en, head = string.find(msg, "^(%w+%.%w+)")
-- PCRE: ^(\w+\.\w+)
local cont = string.sub(msg, en+2)
-- make sure we got anything at all
if start then
return head, cont
else
-- was a dud message (nothing between the begin/end bytes)
return nil
end
end
leftovers = ""
PAT = codes["IAC SB ATCP"] .. "(.-)" .. codes["IAC SE"]
parseATCP = function(packet)
-- tacks on any remainder from the last packet
local packet = leftovers .. packet
leftovers = ""
local atcp, parsed = {}, {}
-- passed to string.gsub() below
-- used to handle each capture
local replace_func = function(cap)
head, cont = split_atcp(cap, parsed)
-- make sure we got something
if head ~= nil then
parsed[head] = cont
table.insert(atcp, cap)
end
return ""
end
-- catch atcp messages, remove inline
packet = string.gsub (packet, PAT, replace_func)
-- finds any leftovers from an unfinished ATCP message
local s,e,msg = string.find (packet, "(\255[^\255]-\255?)$")
if s then
if (#msg == 1) or ( (#msg > 2) and string.find (msg, "^\255\250\200") )
or ( (#msg > 1) and string.find (msg, "^\255\250") ) then
leftovers = msg
packet = string.sub (packet, 1, s-1)
end
end
return packet, atcp, parsed
end
EnableModule = function(lines)
if type(lines) == "string" then
lines = utils.split(lines, ",")
elseif type(lines) ~= "table" then
error("Invalid argument to EnableModule: " .. lines .. "\10")
end
-- lines should be a table at this point
for _, m in ipairs(lines) do
Note(m)
v = mods[m]
if v then
nexus_opts[m] = v.version
-- import module commands
v.version = nil
for i, j in pairs(v) do
Note("Loading command " .. i .. ": " .. j)
commands[i] = j
end
end
end
end
|