· 6 years ago · Sep 03, 2019, 01:16 PM
1gmcpchat = gmcpchat or {}
2
3-- SETTINGS THAT CAN BE CHANGED...
4
5gmcpchat.disablenamedb = false
6gmcpchat.ignoredenizens = false
7gmcpchat.gagmainwindow = false
8
9-- This is where you map the gmcp based channel names to your demonnic tabs...
10-- Note: this is for example purposes, if you have tabs that match these names it will work, if not
11-- I will check if the demonic tab exists, if not it will send to the All tab.
12-- Clans are a special case, if you do clt<ID> you can create a tab for a specific clan, if I cant
13-- find a specific clan, I will send all clans to the default tab mabbed to by clt
14gmcpchat.demonnicmap = {
15 party = "Party",
16 tell = "Tells",
17 ct = "City",
18 ht = "House",
19 hts = "House",
20 hnt = "House",
21 ot = "Order",
22 newbie = "Newbie",
23 market = "Market",
24 ldt = "Leaders",
25 clt = "Clans",
26 says = "Says",
27 clt99 = "Specific Clan Name"
28}
29
30
31
32
33
34
35
36-- CHANGE NOTHING BELOW THIS POINT (unless you know what your doing)
37
38gmcpchat.enabled = gmcpchat.enabled or false
39
40color_table = color_table or {}
41color_table.a_cyan = color_table.a_cyan or {0,255,255}
42color_table.a_darkred = color_table.a_darkred or {128,0,0}
43color_table.a_darkgreen = color_table.a_darkgreen or {0,179,0}
44color_table.a_brown = color_table.a_brown or {128,128,0}
45color_table.a_darkblue = color_table.a_darkblue or {0,0,128}
46color_table.a_darkmagenta = color_table.a_darkmagenta or {128,0,128}
47color_table.a_darkcyan = color_table.a_darkcyan or {0,128,128}
48color_table.a_darkwhite = color_table.a_darkwhite or {192,192,192}
49color_table.a_darkgrey = color_table.a_darkgrey or {128,128,128}
50color_table.a_red = color_table.a_red or {255,0,0}
51color_table.a_green = color_table.a_green or {0,255,0}
52color_table.a_yellow = color_table.a_yellow or {255,255,0}
53color_table.a_magenta = color_table.a_magenta or {255,0,255}
54color_table.a_white = color_table.a_white or {255,255,255}
55
56-- Table we use to map the color codes to cecho strings.
57
58gmcpchat.lookup = { { 0, 0, 0 }, { 128, 0, 0 }, { 0, 179, 0 }, { 128, 128, 0 }, { 0, 0, 128 },
59 { 128, 0, 128 }, { 0, 128, 128 }, { 192, 192, 192 }, { 128, 128, 128 },
60 { 255, 0, 0 }, { 0, 255, 0 }, { 255, 255, 0 }, { 0, 0, 255 }, { 255, 0, 255 },
61 { 0, 255, 255 }, { 255, 255, 255 }, { 0, 0, 0 }, { 0, 0, 95 }, { 0, 0, 135 },
62 { 0, 0, 175 }, { 0, 0, 215 }, { 0, 0, 255 }, { 0, 95, 0 }, { 0, 95, 95 },
63 { 0, 95, 135 }, { 0, 95, 175 }, { 0, 95, 215 }, { 0, 95, 255 }, { 0, 135, 0 },
64 { 0, 135, 95 }, { 0, 135, 135 }, { 0, 135, 175 }, { 0, 135, 215 }, { 0, 135, 255 },
65 { 0, 175, 0 }, { 0, 175, 95 }, { 0, 175, 135 }, { 0, 175, 175 }, { 0, 175, 215 },
66 { 0, 175, 255 }, { 0, 215, 0 }, { 0, 215, 95 }, { 0, 215, 135 }, { 0, 215, 175 },
67 { 0, 215, 215 }, { 0, 215, 255 }, { 0, 255, 0 }, { 0, 255, 95 }, { 0, 255, 135 },
68 { 0, 255, 175 }, { 0, 255, 215 }, { 0, 255, 255 }, { 95, 0, 0 }, { 95, 0, 95 },
69 { 95, 0, 135 }, { 95, 0, 175 }, { 95, 0, 215 }, { 95, 0, 255 }, { 95, 95, 0 },
70 { 95, 95, 95 }, { 95, 95, 135 }, { 95, 95, 175 }, { 95, 95, 215 }, { 95, 95, 255 },
71 { 95, 135, 0 }, { 95, 135, 95 }, { 95, 135, 135 }, { 95, 135, 175 }, { 95, 135, 215 },
72 { 95, 135, 255 }, { 95, 175, 0 }, { 95, 175, 95 }, { 95, 175, 135 }, { 95, 175, 175 },
73 { 95, 175, 215 }, { 95, 175, 255 }, { 95, 215, 0 }, { 95, 215, 95 }, { 95, 215, 135 },
74 { 95, 215, 175 }, { 95, 215, 215 }, { 95, 215, 255 }, { 95, 255, 0 }, { 95, 255, 95 },
75 { 95, 255, 135 }, { 95, 255, 175 }, { 95, 255, 215 }, { 95, 255, 255 }, { 135, 0, 0 },
76 { 135, 0, 95 }, { 135, 0, 135 }, { 135, 0, 175 }, { 135, 0, 215 }, { 135, 0, 255 },
77 { 135, 95, 0 }, { 135, 95, 95 }, { 135, 95, 135 }, { 135, 95, 175 }, { 135, 95, 215 },
78 { 135, 95, 255 }, { 135, 135, 0 }, { 135, 135, 95 }, { 135, 135, 135 }, { 135, 135, 175 },
79 { 135, 135, 215 }, { 135, 135, 255 }, { 135, 175, 0 }, { 135, 175, 95 }, { 135, 175, 135 },
80 { 135, 175, 175 }, { 135, 175, 215 }, { 135, 175, 255 }, { 135, 215, 0 }, { 135, 215, 95 },
81 { 135, 215, 135 }, { 135, 215, 175 }, { 135, 215, 215 }, { 135, 215, 255 }, { 135, 255, 0 },
82 { 135, 255, 95 }, { 135, 255, 135 }, { 135, 255, 175 }, { 135, 255, 215 }, { 135, 255, 255 },
83 { 175, 0, 0 }, { 175, 0, 95 }, { 175, 0, 135 }, { 175, 0, 175 }, { 175, 0, 215 },
84 { 175, 0, 255 }, { 175, 95, 0 }, { 175, 95, 95 }, { 175, 95, 135 }, { 175, 95, 175 },
85 { 175, 95, 215 }, { 175, 95, 255 }, { 175, 135, 0 }, { 175, 135, 95 }, { 175, 135, 135 },
86 { 175, 135, 175 }, { 175, 135, 215 }, { 175, 135, 255 }, { 175, 175, 0 }, { 175, 175, 95 },
87 { 175, 175, 135 }, { 175, 175, 175 }, { 175, 175, 215 }, { 175, 175, 255 }, { 175, 215, 0 },
88 { 175, 215, 95 }, { 175, 215, 135 }, { 175, 215, 175 }, { 175, 215, 215 }, { 175, 215, 255 },
89 { 175, 255, 0 }, { 175, 255, 95 }, { 175, 255, 135 }, { 175, 255, 175 }, { 175, 255, 215 },
90 { 175, 255, 255 }, { 215, 0, 0 }, { 215, 0, 95 }, { 215, 0, 135 }, { 215, 0, 175 },
91 { 215, 0, 215 }, { 215, 0, 255 }, { 215, 95, 0 }, { 215, 95, 95 }, { 215, 95, 135 },
92 { 215, 95, 175 }, { 215, 95, 215 }, { 215, 95, 255 }, { 215, 135, 0 }, { 215, 135, 95 },
93 { 215, 135, 135 }, { 215, 135, 175 }, { 215, 135, 215 }, { 215, 135, 255 }, { 215, 175, 0 },
94 { 215, 175, 95 }, { 215, 175, 135 }, { 215, 175, 175 }, { 215, 175, 215 }, { 215, 175, 255 },
95 { 215, 215, 0 }, { 215, 215, 95 }, { 215, 215, 135 }, { 215, 215, 175 }, { 215, 215, 215 },
96 { 215, 215, 255 }, { 215, 255, 0 }, { 215, 255, 95 }, { 215, 255, 135 }, { 215, 255, 175 },
97 { 215, 255, 215 }, { 215, 255, 255 }, { 255, 0, 0 }, { 255, 0, 95 }, { 255, 0, 135 },
98 { 255, 0, 175 }, { 255, 0, 215 }, { 255, 0, 255 }, { 255, 95, 0 }, { 255, 95, 95 },
99 { 255, 95, 135 }, { 255, 95, 175 }, { 255, 95, 215 }, { 255, 95, 255 }, { 255, 135, 0 },
100 { 255, 135, 95 }, { 255, 135, 135 }, { 255, 135, 175 }, { 255, 135, 215 }, { 255, 135, 255 },
101 { 255, 175, 0 }, { 255, 175, 95 }, { 255, 175, 135 }, { 255, 175, 175 }, { 255, 175, 215 },
102 { 255, 175, 255 }, { 255, 215, 0 }, { 255, 215, 95 }, { 255, 215, 135 }, { 255, 215, 175 },
103 { 255, 215, 215 }, { 255, 215, 255 }, { 255, 255, 0 }, { 255, 255, 95 }, { 255, 255, 135 },
104 { 255, 255, 175 }, { 255, 255, 215 }, { 255, 255, 255 }, { 0, 0, 0 }, { 18, 18, 18 },
105 { 28, 28, 28 }, { 38, 38, 38 }, { 48, 48, 48 }, { 58, 58, 58 }, { 68, 68, 68 },
106 { 78, 78, 78 }, { 88, 88, 88 }, { 98, 98, 98 }, { 108, 108, 108 }, { 118, 118, 118 },
107 { 128, 128, 128 }, { 138, 138, 138 }, { 148, 148, 148 }, { 158, 158, 158 }, { 168, 168, 168 },
108 { 178, 178, 178 }, { 188, 188, 188 }, { 198, 198, 198 }, { 208, 208, 208 }, { 218, 218, 218 },
109 { 228, 228, 228 }, { 238, 238, 238 } }
110
111
112
113-- function to enable GMCP Communications messages
114gmcpchat.enableCommChannel = function ()
115 sendGMCP([[Core.Supports.Add ["Comm.Channel 1"] ]])
116 gmcpchat.enabled = true
117 if gmcpchat.startTrig then
118 killTrigger(gmcpchat.startTrig)
119 end
120end
121
122-- function to disable GMCP Communications messages
123gmcpchat.disableCommChannel = function ()
124 if not gmcpchat.enabled then return end
125 sendGMCP([[Core.Supports.Remove ["Comm.Channel"] ]])
126 gmcpchat.enabled = false
127end
128
129-- Temporary storage for a channel lookup table (auto populated on first use)
130gmcpchat.clanlookup = gmcpchat.clanlookup or {}
131
132gmcpchat.channels = function ()
133 display(gmcp.Comm.Channel.List)
134end
135
136-- Finds the long name for the given channel
137-- if no short name is passed it finds the long name of the last Communication.
138gmcpchat.getchannelname = function (short)
139 if gmcpchat.clanlookup[(short or gmcp.Comm.Channel.Text.channel)] then
140 -- if its already been indexed... just return it
141 return gmcpchat.clanlookup[(short or gmcp.Comm.Channel.Text.channel)]
142 end
143 -- this can happen at startup, or if we did the lookup but then joined a clan..
144 -- redo the lookup table..
145 gmcpchat.clanlookup={}
146 for _,v in ipairs(gmcp.Comm.Channel.List) do
147 gmcpchat.clanlookup[v.name]=v.caption
148 end
149 return gmcpchat.clanlookup[(short or gmcp.Comm.Channel.Text.channel)]
150end
151
152gmcpchat.getcolor = function (index)
153 return table.concat(gmcpchat.lookup[index+1], ",")
154end
155
156gmcpchat.getcolorfromname = function (colorname)
157 return "<"..table.concat(color_table[colorname] or color_table.black, ",")..">"
158end
159
160-- function which we use to translate ascii color codes from in the message using our lookup table
161gmcpchat.translatecode16 = function (highlight, fgnum, bgnum)
162 return string.format("<%s:%s>", gmcpchat.getcolor(((tonumber(highlight) or 0)*8)+(tonumber(fgnum) or 30)-30), gmcpchat.getcolor((tonumber(bgnum) or 40)-40))
163end
164
165gmcpchat.translatecode256 = function (fgnum, bgnum)
166 return string.format("<%s:%s>", gmcpchat.getcolor((tonumber(fgnum) or 0)), gmcpchat.getcolor((tonumber(bgnum) or 0)))
167
168end
169
170if ansi2decho then
171 gmcpchat.escapefix = ansi2decho
172else
173
174 local colours = {
175 [0] = {0,0,0}, -- black
176 [1] = {128,0,0}, -- red
177 [2] = {0,179,0}, -- green
178 [3] = {128,128,0}, -- yellow
179 [4] = {0,0,128}, --blue
180 [5] = {128,0,128}, -- magenta
181 [6] = {0,128,128}, -- cyan
182 [7] = {192,192,192}, -- white
183 }
184
185 local lightColours = {
186 [0] = {128,128,128}, -- black
187 [1] = {255,0,0}, -- red
188 [2] = {0,255,0}, -- green
189 [3] = {255,255,0}, -- yellow
190 [4] = {0,0,255}, --blue
191 [5] = {255,0,255}, -- magenta
192 [6] = {0,255,255}, -- cyan
193 [7] = {255,255,255}, -- white
194 }
195
196 local ansiPattern = rex.new("\\e\\[([0-9;]+?)m")
197 -- function for converting raw ANSI string into something decho can process
198 -- bold, italics, underline not currently supported since decho doesn't support them
199 gmcpchat.escapefix = function(text)
200 local result = rex.gsub(text, ansiPattern, function(s)
201 local output = {} -- assemble the output into this table
202
203 local t = string.split(s, ";") -- split the codes into an indexed table
204
205 -- given an xterm256 index, returns an rgb string for decho use
206 local function convertindex(tag)
207 local floor = math.floor
208 -- code from Mudlets own decoding in TBuffer::translateToPlainText
209
210 local rgb
211 if tag < 8 then
212 rgb = colours[tag]
213 elseif tag < 16 then
214 rgb = lightColours[tag-8]
215 elseif tag < 232 then
216 tag = tag - 16 -- because color 1-15 behave like normal ANSI colors
217
218 r = floor(tag / 36)
219 g = floor((tag-(r*36)) / 6)
220 b = floor((tag-(r*36))-(g*6))
221 rgb = {r*42, g*42, b*42}
222 else
223 -- black + 23 tone grayscale from dark to light gray
224 tag = tag - 232
225 rgb = {tag*10, tag*10, tag*10}
226 end
227
228 return rgb
229 end
230
231 -- since fg/bg can come in different order and we need them as fg:bg for decho, collect
232 -- the data first, then assemble it in the order we need at the end
233 local fg,bg
234 local i = 1
235 local floor = math.floor
236 local coloursToUse = colours
237 while i <= #t do
238 local code = t[i]
239
240 if code == '0' then -- reset attributes
241 output[#output+1] = "<r>"
242 fg,bg = nil,nil
243 coloursToUse = colours
244 elseif code == "1" then -- light or bold
245 coloursToUse = lightColours
246 elseif code == "22" then -- not light or bold
247 coloursToUse = colours
248 else
249 local layerCode = floor(code / 10) -- extract the "layer": 3 is fore
250 -- 4 is back
251 local cmd = code - (layerCode * 10) -- extract the actual "command"
252 -- 0-7 is a colour, 8 is xterm256
253 local colour = nil
254 if cmd == 8 and t[i+1] == '5' then -- xterm256, colour indexed
255 colour = convertindex(tonumber(t[i+2]))
256 i = i + 2
257
258 elseif cmd == 8 and t[i+1] == '2' then -- xterm256, rgb
259 colour = {t[i+2] or '', t[i+3] or '', t[i+4] or ''}
260 i = i + 4
261
262 elseif layerCode == 9 or layerCode == 10 then --light colours
263 colour = lightColours[cmd]
264 elseif layerCode == 4 then -- background colours know no "bright" for
265 colour = colours[cmd] -- mudlet
266 else -- usual ANSI colour index
267 colour = coloursToUse[cmd]
268 end
269
270 if layerCode == 3 or layerCode == 9 then
271 fg = colour
272 elseif layerCode == 4 or layerCode == 10 then
273 bg = colour
274 end
275
276 end
277 i = i + 1
278 end
279 -- assemble and return the data
280 if fg or bg then
281 output[#output+1] = '<'
282 if fg then
283 output[#output+1] = table.concat(fg, ",")
284 end
285 output[#output+1] = ':'
286 if bg then
287 output[#output+1] = table.concat(bg, ",")
288 end
289 output[#output+1] = '>'
290 end
291
292 return table.concat(output)
293 end)
294
295 return result
296 end
297
298end
299
300-- tie in nameDB highlighting.. just because we can.
301-- NOTE: I'm sure theres a better way of doing this, I just couldnt find it in the API.
302-- suprised there wasnt a ndb.highlightnames type function.
303gmcpchat.highlight = function (text)
304
305 -- no namedb, no highlighting..
306 if gmcpchat.disablenamedb or not ndb then return text end
307
308 local names = ndb.findnames(text)
309 -- no names to highlight, just return it as is..
310 if not names then return text end
311
312 -- find our lines base color.. (note this is non greedy so it doesnt match the whole string)
313 -- note: defaults to <reset> if we cant find any color matching for simple white on black clans
314 -- otherwise the namedb highlights wont reset at the end of each name and we get bleeding.
315 local basecolor = string.match(text, "<.->") or "<reset>"
316 local color = nil
317 local result = text
318 for _,v in ipairs(names) do
319 color = ndb.getcolorp(v)
320 if color then
321 -- this is ugly, just required to anchor to non word characters
322 -- this stops us highlighting sub sections of bigger words..
323 result = string.gsub(result, "(%W)("..v..")(%W)", "%1"..(gmcpchat.getcolorfromname(color) or "")..v..(basecolor or "").."%3")
324 end
325 end
326 return result
327end
328
329gmcpchat.aminparty = function ()
330 for _,v in ipairs(gmcp.Comm.Channel.List) do
331 if v.name=="party" then
332 return true
333 end
334 end
335 return false
336end
337
338gmcpchat.demonnicredirect = function ()
339 if gmcpchat.demonnicmap[gmcp.Comm.Channel.Text.channel] and table.contains(demonnic.chat.config.channels, gmcpchat.demonnicmap[gmcp.Comm.Channel.Text.channel]) then
340 -- direct map exists... and so does the destination tab
341 demonnic.chat:decho(gmcpchat.demonnicmap[gmcp.Comm.Channel.Text.channel], gmcpchat.highlight(gmcpchat.escapefix(gmcp.Comm.Channel.Text.text)).."\n")
342 elseif gmcp.Comm.Channel.Text.channel:starts("tell") and gmcpchat.demonnicmap.tell and table.contains(demonnic.chat.config.channels, gmcpchat.demonnicmap.tell) then
343 -- this is a tell (they contain the tellers name, so need a special case for them)
344 demonnic.chat:decho(gmcpchat.demonnicmap.tell, gmcpchat.highlight(gmcpchat.escapefix(gmcp.Comm.Channel.Text.text)).."\n")
345 elseif gmcp.Comm.Channel.Text.channel:starts("clt") and gmcpchat.demonnicmap.clt and table.contains(demonnic.chat.config.channels, gmcpchat.demonnicmap.clt) then
346 -- is a clan, and there is a generic clan link that is valid..
347 demonnic.chat:decho(gmcpchat.demonnicmap.clt, gmcpchat.highlight(gmcpchat.escapefix(gmcp.Comm.Channel.Text.text)).."\n")
348 else
349 demonnic.chat:decho("all", gmcpchat.highlight(gmcpchat.escapefix(gmcp.Comm.Channel.Text.text)).."\n")
350 end
351end
352
353-- this is our event handler
354gmcpchat.textevent = function ()
355 -- lazy attempt at ignoring denizen says to cut down on hunting spam...
356 if gmcpchat.ignoredenizens and gmcp.Comm.Channel.Text.talker:match(" ") or gmcp.Comm.Channel.Text.talker:match("-") then
357 return
358 end
359 -- auto detect if demonnic tabbed chat in use..
360 if demonnic and demonnic.chat then
361 if gmcpchat.demonnicmap[gmcp.Comm.Channel.Text.channel]=="none" then
362 -- this channel is preconfigured not to go to any chat window... just bail
363 return
364 else
365 gmcpchat.demonnicredirect()
366 end
367 else
368 -- if we cant detect a tabbed chat, just echo, this is what you want to
369 chat:decho(gmcpchat.highlight(gmcpchat.escapefix(gmcp.Comm.Channel.Text.text)).."\n")
370 end
371 if gmcpchat.gagmainwindow then
372 deleteFull()
373 end
374end
375
376-- register our event handler function
377registerAnonymousEventHandler("gmcp.Comm.Channel.Text", "gmcpchat.textevent")
378
379gmcpchat.enabletrigger = function ()
380 gmcpchat.startTrig = tempRegexTrigger("^Your last login was from domain\: .+\.$", [[gmcpchat.enableCommChannel()]])
381end
382
383registerAnonymousEventHandler("sysConnectionEvent", "gmcpchat.enabletrigger")