flickerstreak@1
|
1 --[[
|
flickerstreak@1
|
2 Name: AceComm-2.0
|
flickerstreak@1
|
3 Revision: $Rev: 18708 $
|
flickerstreak@1
|
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
flickerstreak@1
|
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
flickerstreak@1
|
6 Website: http://www.wowace.com/
|
flickerstreak@1
|
7 Documentation: http://www.wowace.com/index.php/AceComm-2.0
|
flickerstreak@1
|
8 SVN: http://svn.wowace.com/wowace/trunk/Ace2/AceComm-2.0
|
flickerstreak@1
|
9 Description: Mixin to allow for inter-player addon communications.
|
flickerstreak@1
|
10 Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0,
|
flickerstreak@1
|
11 ChatThrottleLib by Mikk (included)
|
flickerstreak@1
|
12 ]]
|
flickerstreak@1
|
13
|
flickerstreak@1
|
14 local MAJOR_VERSION = "AceComm-2.0"
|
flickerstreak@1
|
15 local MINOR_VERSION = "$Revision: 18708 $"
|
flickerstreak@1
|
16
|
flickerstreak@1
|
17 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
flickerstreak@1
|
18 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
flickerstreak@1
|
19
|
flickerstreak@1
|
20 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
flickerstreak@1
|
21
|
flickerstreak@1
|
22 local _G = getfenv(0)
|
flickerstreak@1
|
23
|
flickerstreak@1
|
24 local AceOO = AceLibrary("AceOO-2.0")
|
flickerstreak@1
|
25 local Mixin = AceOO.Mixin
|
flickerstreak@1
|
26 local AceComm = Mixin {
|
flickerstreak@1
|
27 "SendCommMessage",
|
flickerstreak@1
|
28 "SendPrioritizedCommMessage",
|
flickerstreak@1
|
29 "RegisterComm",
|
flickerstreak@1
|
30 "UnregisterComm",
|
flickerstreak@1
|
31 "UnregisterAllComms",
|
flickerstreak@1
|
32 "IsCommRegistered",
|
flickerstreak@1
|
33 "SetDefaultCommPriority",
|
flickerstreak@1
|
34 "SetCommPrefix",
|
flickerstreak@1
|
35 "RegisterMemoizations",
|
flickerstreak@1
|
36 "IsUserInChannel",
|
flickerstreak@1
|
37 }
|
flickerstreak@1
|
38 AceComm.hooks = {}
|
flickerstreak@1
|
39
|
flickerstreak@1
|
40 local AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0")
|
flickerstreak@1
|
41
|
flickerstreak@1
|
42 local string_byte = string.byte
|
flickerstreak@1
|
43
|
flickerstreak@1
|
44 local byte_a = string_byte('a')
|
flickerstreak@1
|
45 local byte_z = string_byte('z')
|
flickerstreak@1
|
46 local byte_A = string_byte('A')
|
flickerstreak@1
|
47 local byte_Z = string_byte('Z')
|
flickerstreak@1
|
48 local byte_fake_s = string_byte('\015')
|
flickerstreak@1
|
49 local byte_fake_S = string_byte('\020')
|
flickerstreak@1
|
50 local byte_deg = string_byte('°')
|
flickerstreak@1
|
51 local byte_percent = string_byte('%') -- 37
|
flickerstreak@1
|
52
|
flickerstreak@1
|
53 local byte_b = string_byte('b')
|
flickerstreak@1
|
54 local byte_B = string_byte('B')
|
flickerstreak@1
|
55 local byte_nil = string_byte('/')
|
flickerstreak@1
|
56 local byte_plus = string_byte('+')
|
flickerstreak@1
|
57 local byte_minus = string_byte('-')
|
flickerstreak@1
|
58 local byte_d = string_byte('d')
|
flickerstreak@1
|
59 local byte_D = string_byte('D')
|
flickerstreak@1
|
60 local byte_e = string_byte('e')
|
flickerstreak@1
|
61 local byte_E = string_byte('E')
|
flickerstreak@1
|
62 local byte_m = string_byte('m')
|
flickerstreak@1
|
63 local byte_s = string_byte('s')
|
flickerstreak@1
|
64 local byte_S = string_byte('S')
|
flickerstreak@1
|
65 local byte_o = string_byte('o')
|
flickerstreak@1
|
66 local byte_O = string_byte('O')
|
flickerstreak@1
|
67 local byte_t = string_byte('t')
|
flickerstreak@1
|
68 local byte_T = string_byte('T')
|
flickerstreak@1
|
69 local byte_u = string_byte('u')
|
flickerstreak@1
|
70 local byte_U = string_byte('U')
|
flickerstreak@1
|
71 local byte_i = string_byte('i')
|
flickerstreak@1
|
72 local byte_inf = string_byte('@')
|
flickerstreak@1
|
73 local byte_ninf = string_byte('$')
|
flickerstreak@1
|
74 local byte_nan = string_byte('!')
|
flickerstreak@1
|
75
|
flickerstreak@1
|
76 local inf = 1/0
|
flickerstreak@1
|
77 local nan = 0/0
|
flickerstreak@1
|
78
|
flickerstreak@1
|
79 local math_floor = math.floor
|
flickerstreak@1
|
80 local math_mod = math.fmod
|
flickerstreak@1
|
81 local math_floormod = function(value, m)
|
flickerstreak@1
|
82 return math_mod(math_floor(value), m)
|
flickerstreak@1
|
83 end
|
flickerstreak@1
|
84 local string_gmatch = string.gmatch
|
flickerstreak@1
|
85 local string_char = string.char
|
flickerstreak@1
|
86 local string_len = string.len
|
flickerstreak@1
|
87 local string_format = string.format
|
flickerstreak@1
|
88 local string_gsub = string.gsub
|
flickerstreak@1
|
89 local string_find = string.find
|
flickerstreak@1
|
90 local table_insert = table.insert
|
flickerstreak@1
|
91 local string_sub = string.sub
|
flickerstreak@1
|
92 local table_concat = table.concat
|
flickerstreak@1
|
93 local table_remove = table.remove
|
flickerstreak@1
|
94
|
flickerstreak@1
|
95 local type = type
|
flickerstreak@1
|
96 local unpack = unpack
|
flickerstreak@1
|
97 local pairs = pairs
|
flickerstreak@1
|
98 local next = next
|
flickerstreak@1
|
99
|
flickerstreak@1
|
100 local player = UnitName("player")
|
flickerstreak@1
|
101
|
flickerstreak@1
|
102 local NumericCheckSum, HexCheckSum, BinaryCheckSum
|
flickerstreak@1
|
103 local TailoredNumericCheckSum, TailoredHexCheckSum, TailoredBinaryCheckSum
|
flickerstreak@1
|
104 do
|
flickerstreak@1
|
105 local SOME_PRIME = 16777213
|
flickerstreak@1
|
106 function NumericCheckSum(text)
|
flickerstreak@1
|
107 local counter = 1
|
flickerstreak@1
|
108 local len = string_len(text)
|
flickerstreak@1
|
109 for i = 1, len, 3 do
|
flickerstreak@1
|
110 counter = math_mod(counter*8257, 16777259) +
|
flickerstreak@1
|
111 (string_byte(text,i)) +
|
flickerstreak@1
|
112 ((string_byte(text,i+1) or 1)*127) +
|
flickerstreak@1
|
113 ((string_byte(text,i+2) or 2)*16383)
|
flickerstreak@1
|
114 end
|
flickerstreak@1
|
115 return math_mod(counter, 16777213)
|
flickerstreak@1
|
116 end
|
flickerstreak@1
|
117
|
flickerstreak@1
|
118 function HexCheckSum(text)
|
flickerstreak@1
|
119 return string_format("%06x", NumericCheckSum(text))
|
flickerstreak@1
|
120 end
|
flickerstreak@1
|
121
|
flickerstreak@1
|
122 function BinaryCheckSum(text)
|
flickerstreak@1
|
123 local num = NumericCheckSum(text)
|
flickerstreak@1
|
124 return string_char(math_floor(num / 65536), math_floormod(num / 256, 256), math_mod(num, 256))
|
flickerstreak@1
|
125 end
|
flickerstreak@1
|
126
|
flickerstreak@1
|
127 function TailoredNumericCheckSum(text)
|
flickerstreak@1
|
128 local hash = NumericCheckSum(text)
|
flickerstreak@1
|
129 local a = math_floor(hash / 65536)
|
flickerstreak@1
|
130 local b = math_floormod(hash / 256, 256)
|
flickerstreak@1
|
131 local c = math_mod(hash, 256)
|
flickerstreak@1
|
132 -- \000, \n, |, °, s, S, \015, \020
|
flickerstreak@1
|
133 if a == 0 or a == 10 or a == 124 or a == 176 or a == 115 or a == 83 or a == 15 or a == 20 or a == 37 then
|
flickerstreak@1
|
134 a = a + 1
|
flickerstreak@1
|
135 -- \t, \255
|
flickerstreak@1
|
136 elseif a == 9 or a == 255 then
|
flickerstreak@1
|
137 a = a - 1
|
flickerstreak@1
|
138 end
|
flickerstreak@1
|
139 if b == 0 or b == 10 or b == 124 or b == 176 or b == 115 or b == 83 or b == 15 or b == 20 or b == 37 then
|
flickerstreak@1
|
140 b = b + 1
|
flickerstreak@1
|
141 elseif b == 9 or b == 255 then
|
flickerstreak@1
|
142 b = b - 1
|
flickerstreak@1
|
143 end
|
flickerstreak@1
|
144 if c == 0 or c == 10 or c == 124 or c == 176 or c == 115 or c == 83 or c == 15 or c == 20 or c == 37 then
|
flickerstreak@1
|
145 c = c + 1
|
flickerstreak@1
|
146 elseif c == 9 or c == 255 then
|
flickerstreak@1
|
147 c = c - 1
|
flickerstreak@1
|
148 end
|
flickerstreak@1
|
149 return a * 65536 + b * 256 + c
|
flickerstreak@1
|
150 end
|
flickerstreak@1
|
151
|
flickerstreak@1
|
152 function TailoredHexCheckSum(text)
|
flickerstreak@1
|
153 return string_format("%06x", TailoredNumericCheckSum(text))
|
flickerstreak@1
|
154 end
|
flickerstreak@1
|
155
|
flickerstreak@1
|
156 function TailoredBinaryCheckSum(text)
|
flickerstreak@1
|
157 local num = TailoredNumericCheckSum(text)
|
flickerstreak@1
|
158 return string_char(math_floor(num / 65536), math_floormod(num / 256, 256), math_mod(num, 256))
|
flickerstreak@1
|
159 end
|
flickerstreak@1
|
160 end
|
flickerstreak@1
|
161
|
flickerstreak@1
|
162 local function GetLatency()
|
flickerstreak@1
|
163 local _,_,lag = GetNetStats()
|
flickerstreak@1
|
164 return lag / 1000
|
flickerstreak@1
|
165 end
|
flickerstreak@1
|
166
|
flickerstreak@1
|
167 local function IsInChannel(chan)
|
flickerstreak@1
|
168 return GetChannelName(chan) ~= 0
|
flickerstreak@1
|
169 end
|
flickerstreak@1
|
170
|
flickerstreak@1
|
171 -- Package a message for transmission
|
flickerstreak@1
|
172 local function Encode(text, drunk)
|
flickerstreak@1
|
173 text = string_gsub(text, "°", "°±")
|
flickerstreak@1
|
174 if drunk then
|
flickerstreak@1
|
175 text = string_gsub(text, "\020", "°\021")
|
flickerstreak@1
|
176 text = string_gsub(text, "\015", "°\016")
|
flickerstreak@1
|
177 text = string_gsub(text, "S", "\020")
|
flickerstreak@1
|
178 text = string_gsub(text, "s", "\015")
|
flickerstreak@1
|
179 -- change S and s to a different set of character bytes.
|
flickerstreak@1
|
180 end
|
flickerstreak@1
|
181 text = string_gsub(text, "\255", "°\254") -- \255 (this is here because \000 is more common)
|
flickerstreak@1
|
182 text = string_gsub(text, "%z", "\255") -- \000
|
flickerstreak@1
|
183 text = string_gsub(text, "\010", "°\011") -- \n
|
flickerstreak@1
|
184 text = string_gsub(text, "\124", "°\125") -- |
|
flickerstreak@1
|
185 text = string_gsub(text, "%%", "°\038") -- %
|
flickerstreak@1
|
186 -- encode assorted prohibited characters
|
flickerstreak@1
|
187 return text
|
flickerstreak@1
|
188 end
|
flickerstreak@1
|
189
|
flickerstreak@1
|
190 local func
|
flickerstreak@1
|
191 -- Clean a received message
|
flickerstreak@1
|
192 local function Decode(text, drunk)
|
flickerstreak@1
|
193 if drunk then
|
flickerstreak@1
|
194 text = string_gsub(text, "^(.*)°.-$", "%1")
|
flickerstreak@1
|
195 -- get rid of " ...hic!"
|
flickerstreak@1
|
196 end
|
flickerstreak@1
|
197 if not func then
|
flickerstreak@1
|
198 func = function(text)
|
flickerstreak@1
|
199 if text == "\016" then
|
flickerstreak@1
|
200 return "\015"
|
flickerstreak@1
|
201 elseif text == "\021" then
|
flickerstreak@1
|
202 return "\020"
|
flickerstreak@1
|
203 elseif text == "±" then
|
flickerstreak@1
|
204 return "°"
|
flickerstreak@1
|
205 elseif text == "\254" then
|
flickerstreak@1
|
206 return "\255"
|
flickerstreak@1
|
207 elseif text == "\011" then
|
flickerstreak@1
|
208 return "\010"
|
flickerstreak@1
|
209 elseif text == "\125" then
|
flickerstreak@1
|
210 return "\124"
|
flickerstreak@1
|
211 elseif text == "\038" then
|
flickerstreak@1
|
212 return "\037"
|
flickerstreak@1
|
213 end
|
flickerstreak@1
|
214 end
|
flickerstreak@1
|
215 end
|
flickerstreak@1
|
216 text = string_gsub(text, "\255", "\000")
|
flickerstreak@1
|
217 if drunk then
|
flickerstreak@1
|
218 text = string_gsub(text, "\020", "S")
|
flickerstreak@1
|
219 text = string_gsub(text, "\015", "s")
|
flickerstreak@1
|
220 end
|
flickerstreak@1
|
221 text = string_gsub(text, drunk and "°([\016\021±\254\011\125\038])" or "°([±\254\011\125\038])", func)
|
flickerstreak@1
|
222 -- remove the hidden character and refix the prohibited characters.
|
flickerstreak@1
|
223 return text
|
flickerstreak@1
|
224 end
|
flickerstreak@1
|
225
|
flickerstreak@1
|
226 local lastChannelJoined
|
flickerstreak@1
|
227
|
flickerstreak@1
|
228 function AceComm.hooks:JoinChannelByName(orig, channel, a,b,c,d,e,f,g,h,i)
|
flickerstreak@1
|
229 lastChannelJoined = channel
|
flickerstreak@1
|
230 return orig(channel, a,b,c,d,e,f,g,h,i)
|
flickerstreak@1
|
231 end
|
flickerstreak@1
|
232
|
flickerstreak@1
|
233 local function JoinChannel(channel)
|
flickerstreak@1
|
234 if not IsInChannel(channel) then
|
flickerstreak@1
|
235 LeaveChannelByName(channel)
|
flickerstreak@1
|
236 AceComm:ScheduleEvent(JoinChannelByName, 0, channel)
|
flickerstreak@1
|
237 end
|
flickerstreak@1
|
238 end
|
flickerstreak@1
|
239
|
flickerstreak@1
|
240 local function LeaveChannel(channel)
|
flickerstreak@1
|
241 if IsInChannel(channel) then
|
flickerstreak@1
|
242 LeaveChannelByName(channel)
|
flickerstreak@1
|
243 end
|
flickerstreak@1
|
244 end
|
flickerstreak@1
|
245
|
flickerstreak@1
|
246 local switches = {}
|
flickerstreak@1
|
247
|
flickerstreak@1
|
248 local function SwitchChannel(former, latter)
|
flickerstreak@1
|
249 if IsInChannel(former) then
|
flickerstreak@1
|
250 LeaveChannelByName(former)
|
flickerstreak@1
|
251 switches[{
|
flickerstreak@1
|
252 former = former,
|
flickerstreak@1
|
253 latter = latter
|
flickerstreak@1
|
254 }] = true
|
flickerstreak@1
|
255 return
|
flickerstreak@1
|
256 end
|
flickerstreak@1
|
257 if not IsInChannel(latter) then
|
flickerstreak@1
|
258 JoinChannelByName(latter)
|
flickerstreak@1
|
259 end
|
flickerstreak@1
|
260 end
|
flickerstreak@1
|
261
|
flickerstreak@1
|
262 local shutdown = false
|
flickerstreak@1
|
263
|
flickerstreak@1
|
264 local zoneCache
|
flickerstreak@1
|
265 local function GetCurrentZoneChannel()
|
flickerstreak@1
|
266 if not zoneCache then
|
flickerstreak@1
|
267 zoneCache = "AceCommZone" .. HexCheckSum(GetRealZoneText())
|
flickerstreak@1
|
268 end
|
flickerstreak@1
|
269 return zoneCache
|
flickerstreak@1
|
270 end
|
flickerstreak@1
|
271
|
flickerstreak@1
|
272 local AceComm_registry
|
flickerstreak@1
|
273
|
flickerstreak@1
|
274 local function SupposedToBeInChannel(chan)
|
flickerstreak@1
|
275 if not string_find(chan, "^AceComm") then
|
flickerstreak@1
|
276 return true
|
flickerstreak@1
|
277 elseif shutdown or not AceEvent:IsFullyInitialized() then
|
flickerstreak@1
|
278 return false
|
flickerstreak@1
|
279 end
|
flickerstreak@1
|
280
|
flickerstreak@1
|
281 if chan == "AceComm" then
|
flickerstreak@1
|
282 return AceComm_registry.GLOBAL and next(AceComm_registry.GLOBAL) and true or false
|
flickerstreak@1
|
283 elseif string_find(chan, "^AceCommZone%x%x%x%x%x%x$") then
|
flickerstreak@1
|
284 if chan == GetCurrentZoneChannel() then
|
flickerstreak@1
|
285 return AceComm_registry.ZONE and next(AceComm_registry.ZONE) and true or false
|
flickerstreak@1
|
286 else
|
flickerstreak@1
|
287 return false
|
flickerstreak@1
|
288 end
|
flickerstreak@1
|
289 else
|
flickerstreak@1
|
290 return AceComm_registry.CUSTOM and AceComm_registry.CUSTOM[chan] and next(AceComm_registry.CUSTOM[chan]) and true or false
|
flickerstreak@1
|
291 end
|
flickerstreak@1
|
292 end
|
flickerstreak@1
|
293
|
flickerstreak@1
|
294 local tmp = {}
|
flickerstreak@1
|
295 local function LeaveAceCommChannels(all)
|
flickerstreak@1
|
296 if all then
|
flickerstreak@1
|
297 shutdown = true
|
flickerstreak@1
|
298 end
|
flickerstreak@1
|
299 local _,a,_,b,_,c,_,d,_,e,_,f,_,g,_,h,_,i,_,j = GetChannelList()
|
flickerstreak@1
|
300 tmp[1] = a
|
flickerstreak@1
|
301 tmp[2] = b
|
flickerstreak@1
|
302 tmp[3] = c
|
flickerstreak@1
|
303 tmp[4] = d
|
flickerstreak@1
|
304 tmp[5] = e
|
flickerstreak@1
|
305 tmp[6] = f
|
flickerstreak@1
|
306 tmp[7] = g
|
flickerstreak@1
|
307 tmp[8] = h
|
flickerstreak@1
|
308 tmp[9] = i
|
flickerstreak@1
|
309 tmp[10] = j
|
flickerstreak@1
|
310 for _,v in ipairs(tmp) do
|
flickerstreak@1
|
311 if v and string_find(v, "^AceComm") then
|
flickerstreak@1
|
312 if not SupposedToBeInChannel(v) then
|
flickerstreak@1
|
313 LeaveChannelByName(v)
|
flickerstreak@1
|
314 end
|
flickerstreak@1
|
315 end
|
flickerstreak@1
|
316 end
|
flickerstreak@1
|
317 for i = 1, 10 do
|
flickerstreak@1
|
318 tmp[i] = nil
|
flickerstreak@1
|
319 end
|
flickerstreak@1
|
320 end
|
flickerstreak@1
|
321
|
flickerstreak@1
|
322 local lastRefix = 0
|
flickerstreak@1
|
323 local function RefixAceCommChannelsAndEvents()
|
flickerstreak@1
|
324 if GetTime() - lastRefix <= 5 then
|
flickerstreak@1
|
325 AceComm:ScheduleEvent(RefixAceCommChannelsAndEvents, 1)
|
flickerstreak@1
|
326 return
|
flickerstreak@1
|
327 end
|
flickerstreak@1
|
328 lastRefix = GetTime()
|
flickerstreak@1
|
329 LeaveAceCommChannels(false)
|
flickerstreak@1
|
330
|
flickerstreak@1
|
331 local channel = false
|
flickerstreak@1
|
332 local whisper = false
|
flickerstreak@1
|
333 local addon = false
|
flickerstreak@1
|
334 if SupposedToBeInChannel("AceComm") then
|
flickerstreak@1
|
335 JoinChannel("AceComm")
|
flickerstreak@1
|
336 channel = true
|
flickerstreak@1
|
337 end
|
flickerstreak@1
|
338 if SupposedToBeInChannel(GetCurrentZoneChannel()) then
|
flickerstreak@1
|
339 JoinChannel(GetCurrentZoneChannel())
|
flickerstreak@1
|
340 channel = true
|
flickerstreak@1
|
341 end
|
flickerstreak@1
|
342 if AceComm_registry.CUSTOM then
|
flickerstreak@1
|
343 for k,v in pairs(AceComm_registry.CUSTOM) do
|
flickerstreak@1
|
344 if next(v) and SupposedToBeInChannel(k) then
|
flickerstreak@1
|
345 JoinChannel(k)
|
flickerstreak@1
|
346 channel = true
|
flickerstreak@1
|
347 end
|
flickerstreak@1
|
348 end
|
flickerstreak@1
|
349 end
|
flickerstreak@1
|
350 if AceComm_registry.WHISPER then
|
flickerstreak@1
|
351 whisper = true
|
flickerstreak@1
|
352 end
|
flickerstreak@1
|
353 if AceComm_registry.GROUP or AceComm_registry.PARTY or AceComm_registry.RAID or AceComm_registry.BATTLEGROUND or AceComm_registry.GUILD then
|
flickerstreak@1
|
354 addon = true
|
flickerstreak@1
|
355 end
|
flickerstreak@1
|
356
|
flickerstreak@1
|
357 if channel then
|
flickerstreak@1
|
358 if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL") then
|
flickerstreak@1
|
359 AceComm:RegisterEvent("CHAT_MSG_CHANNEL")
|
flickerstreak@1
|
360 end
|
flickerstreak@1
|
361 if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LIST") then
|
flickerstreak@1
|
362 AceComm:RegisterEvent("CHAT_MSG_CHANNEL_LIST")
|
flickerstreak@1
|
363 end
|
flickerstreak@1
|
364 if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_JOIN") then
|
flickerstreak@1
|
365 AceComm:RegisterEvent("CHAT_MSG_CHANNEL_JOIN")
|
flickerstreak@1
|
366 end
|
flickerstreak@1
|
367 if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LEAVE") then
|
flickerstreak@1
|
368 AceComm:RegisterEvent("CHAT_MSG_CHANNEL_LEAVE")
|
flickerstreak@1
|
369 end
|
flickerstreak@1
|
370 else
|
flickerstreak@1
|
371 if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL") then
|
flickerstreak@1
|
372 AceComm:UnregisterEvent("CHAT_MSG_CHANNEL")
|
flickerstreak@1
|
373 end
|
flickerstreak@1
|
374 if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LIST") then
|
flickerstreak@1
|
375 AceComm:UnregisterEvent("CHAT_MSG_CHANNEL_LIST")
|
flickerstreak@1
|
376 end
|
flickerstreak@1
|
377 if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_JOIN") then
|
flickerstreak@1
|
378 AceComm:UnregisterEvent("CHAT_MSG_CHANNEL_JOIN")
|
flickerstreak@1
|
379 end
|
flickerstreak@1
|
380 if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LEAVE") then
|
flickerstreak@1
|
381 AceComm:UnregisterEvent("CHAT_MSG_CHANNEL_LEAVE")
|
flickerstreak@1
|
382 end
|
flickerstreak@1
|
383 end
|
flickerstreak@1
|
384
|
flickerstreak@1
|
385 if whisper then
|
flickerstreak@1
|
386 if not AceComm:IsEventRegistered("CHAT_MSG_WHISPER") then
|
flickerstreak@1
|
387 AceComm:RegisterEvent("CHAT_MSG_WHISPER")
|
flickerstreak@1
|
388 end
|
flickerstreak@1
|
389 else
|
flickerstreak@1
|
390 if AceComm:IsEventRegistered("CHAT_MSG_WHISPER") then
|
flickerstreak@1
|
391 AceComm:UnregisterEvent("CHAT_MSG_WHISPER")
|
flickerstreak@1
|
392 end
|
flickerstreak@1
|
393 end
|
flickerstreak@1
|
394
|
flickerstreak@1
|
395 if addon then
|
flickerstreak@1
|
396 if not AceComm:IsEventRegistered("CHAT_MSG_ADDON") then
|
flickerstreak@1
|
397 AceComm:RegisterEvent("CHAT_MSG_ADDON")
|
flickerstreak@1
|
398 end
|
flickerstreak@1
|
399 else
|
flickerstreak@1
|
400 if AceComm:IsEventRegistered("CHAT_MSG_ADDON") then
|
flickerstreak@1
|
401 AceComm:UnregisterEvent("CHAT_MSG_ADDON")
|
flickerstreak@1
|
402 end
|
flickerstreak@1
|
403 end
|
flickerstreak@1
|
404 end
|
flickerstreak@1
|
405
|
flickerstreak@1
|
406
|
flickerstreak@1
|
407 do
|
flickerstreak@1
|
408 local myFunc = function(k)
|
flickerstreak@1
|
409 if not IsInChannel(k.latter) then
|
flickerstreak@1
|
410 JoinChannelByName(k.latter)
|
flickerstreak@1
|
411 end
|
flickerstreak@1
|
412 switches[k] = nil
|
flickerstreak@1
|
413 end
|
flickerstreak@1
|
414
|
flickerstreak@1
|
415 function AceComm:CHAT_MSG_CHANNEL_NOTICE(kind, _, _, deadName, _, _, _, num, channel)
|
flickerstreak@1
|
416 if kind == "YOU_LEFT" then
|
flickerstreak@1
|
417 if not string_find(channel, "^AceComm") then
|
flickerstreak@1
|
418 return
|
flickerstreak@1
|
419 end
|
flickerstreak@1
|
420 for k in pairs(switches) do
|
flickerstreak@1
|
421 if k.former == channel then
|
flickerstreak@1
|
422 self:ScheduleEvent(myFunc, 0, k)
|
flickerstreak@1
|
423 end
|
flickerstreak@1
|
424 end
|
flickerstreak@1
|
425 if channel == GetCurrentZoneChannel() then
|
flickerstreak@1
|
426 self:TriggerEvent("AceComm_LeftChannel", "ZONE")
|
flickerstreak@1
|
427 elseif channel == "AceComm" then
|
flickerstreak@1
|
428 self:TriggerEvent("AceComm_LeftChannel", "GLOBAL")
|
flickerstreak@1
|
429 else
|
flickerstreak@1
|
430 self:TriggerEvent("AceComm_LeftChannel", "CUSTOM", string_sub(channel, 8))
|
flickerstreak@1
|
431 end
|
flickerstreak@1
|
432 if string_find(channel, "^AceComm") and SupposedToBeInChannel(channel) then
|
flickerstreak@1
|
433 self:ScheduleEvent(JoinChannel, 0, channel)
|
flickerstreak@1
|
434 end
|
flickerstreak@1
|
435 if AceComm.userRegistry[channel] then
|
flickerstreak@1
|
436 AceComm.userRegistry[channel] = nil
|
flickerstreak@1
|
437 end
|
flickerstreak@1
|
438 elseif kind == "YOU_JOINED" then
|
flickerstreak@1
|
439 if not string_find(num == 0 and deadName or channel, "^AceComm") then
|
flickerstreak@1
|
440 return
|
flickerstreak@1
|
441 end
|
flickerstreak@1
|
442 if num == 0 then
|
flickerstreak@1
|
443 self:ScheduleEvent(LeaveChannelByName, 0, deadName)
|
flickerstreak@1
|
444 switches[{
|
flickerstreak@1
|
445 former = deadName,
|
flickerstreak@1
|
446 latter = deadName,
|
flickerstreak@1
|
447 }] = true
|
flickerstreak@1
|
448 elseif channel == GetCurrentZoneChannel() then
|
flickerstreak@1
|
449 self:TriggerEvent("AceComm_JoinedChannel", "ZONE")
|
flickerstreak@1
|
450 elseif channel == "AceComm" then
|
flickerstreak@1
|
451 self:TriggerEvent("AceComm_JoinedChannel", "GLOBAL")
|
flickerstreak@1
|
452 else
|
flickerstreak@1
|
453 self:TriggerEvent("AceComm_JoinedChannel", "CUSTOM", string_sub(channel, 8))
|
flickerstreak@1
|
454 end
|
flickerstreak@1
|
455 if num ~= 0 then
|
flickerstreak@1
|
456 if not SupposedToBeInChannel(channel) then
|
flickerstreak@1
|
457 LeaveChannel(channel)
|
flickerstreak@1
|
458 else
|
flickerstreak@1
|
459 ListChannelByName(channel)
|
flickerstreak@1
|
460 end
|
flickerstreak@1
|
461 end
|
flickerstreak@1
|
462 end
|
flickerstreak@1
|
463 end
|
flickerstreak@1
|
464 end
|
flickerstreak@1
|
465
|
flickerstreak@1
|
466 local Serialize
|
flickerstreak@1
|
467 do
|
flickerstreak@1
|
468 local recurse
|
flickerstreak@1
|
469 local function _Serialize(v, textToHash)
|
flickerstreak@1
|
470 local kind = type(v)
|
flickerstreak@1
|
471 if kind == "boolean" then
|
flickerstreak@1
|
472 if v then
|
flickerstreak@1
|
473 return "B" -- true
|
flickerstreak@1
|
474 else
|
flickerstreak@1
|
475 return "b" -- false
|
flickerstreak@1
|
476 end
|
flickerstreak@1
|
477 elseif not v then
|
flickerstreak@1
|
478 return "/"
|
flickerstreak@1
|
479 elseif kind == "number" then
|
flickerstreak@1
|
480 if v == math_floor(v) then
|
flickerstreak@1
|
481 if v <= 127 and v >= -128 then
|
flickerstreak@1
|
482 if v < 0 then
|
flickerstreak@1
|
483 v = v + 256
|
flickerstreak@1
|
484 end
|
flickerstreak@1
|
485 return string_char(byte_d, v)
|
flickerstreak@1
|
486 elseif v <= 32767 and v >= -32768 then
|
flickerstreak@1
|
487 if v < 0 then
|
flickerstreak@1
|
488 v = v + 65536
|
flickerstreak@1
|
489 end
|
flickerstreak@1
|
490 return string_char(byte_D, math_floor(v / 256), math_mod(v, 256))
|
flickerstreak@1
|
491 elseif v <= 2147483647 and v >= -2147483648 then
|
flickerstreak@1
|
492 if v < 0 then
|
flickerstreak@1
|
493 v = v + 4294967296
|
flickerstreak@1
|
494 end
|
flickerstreak@1
|
495 return string_char(byte_e, math_floor(v / 16777216), math_floormod(v / 65536, 256), math_floormod(v / 256, 256), math_mod(v, 256))
|
flickerstreak@1
|
496 elseif v <= 9223372036854775807 and v >= -9223372036854775808 then
|
flickerstreak@1
|
497 if v < 0 then
|
flickerstreak@1
|
498 v = v + 18446744073709551616
|
flickerstreak@1
|
499 end
|
flickerstreak@1
|
500 return string_char(byte_E, math_floor(v / 72057594037927936), math_floormod(v / 281474976710656, 256), math_floormod(v / 1099511627776, 256), math_floormod(v / 4294967296, 256), math_floormod(v / 16777216, 256), math_floormod(v / 65536, 256), math_floormod(v / 256, 256), math_mod(v, 256))
|
flickerstreak@1
|
501 end
|
flickerstreak@1
|
502 elseif v == inf then
|
flickerstreak@1
|
503 return string_char(64 --[[byte_inf]])
|
flickerstreak@1
|
504 elseif v == -inf then
|
flickerstreak@1
|
505 return string_char(36 --[[byte_ninf]])
|
flickerstreak@1
|
506 elseif v ~= v then
|
flickerstreak@1
|
507 return string_char(33 --[[byte_nan]])
|
flickerstreak@1
|
508 end
|
flickerstreak@1
|
509 -- do
|
flickerstreak@1
|
510 -- local s = tostring(v)
|
flickerstreak@1
|
511 -- local len = string_len(s)
|
flickerstreak@1
|
512 -- return string_char(byte_plus, len) .. s
|
flickerstreak@1
|
513 -- end
|
flickerstreak@1
|
514 local sign = v < 0 or v == 0 and tostring(v) == "-0"
|
flickerstreak@1
|
515 if sign then
|
flickerstreak@1
|
516 v = -v
|
flickerstreak@1
|
517 end
|
flickerstreak@1
|
518 local m, exp = math.frexp(v)
|
flickerstreak@1
|
519 m = m * 9007199254740992
|
flickerstreak@1
|
520 local x = exp + 1023
|
flickerstreak@1
|
521 local b = math_mod(m, 256)
|
flickerstreak@1
|
522 local c = math_floormod(m / 256, 256)
|
flickerstreak@1
|
523 m = math_floor(m / 65536)
|
flickerstreak@1
|
524 m = m + x * 137438953472
|
flickerstreak@1
|
525 return string_char(sign and byte_minus or byte_plus, math_floormod(m / 1099511627776, 256), math_floormod(m / 4294967296, 256), math_floormod(m / 16777216, 256), math_floormod(m / 65536, 256), math_floormod(m / 256, 256), math_mod(m, 256), c, b)
|
flickerstreak@1
|
526 elseif kind == "string" then
|
flickerstreak@1
|
527 local hash = textToHash and textToHash[v]
|
flickerstreak@1
|
528 if hash then
|
flickerstreak@1
|
529 return string_char(byte_m, math_floor(hash / 65536), math_floormod(hash / 256, 256), math_mod(hash, 256))
|
flickerstreak@1
|
530 end
|
flickerstreak@1
|
531 local _,_,A,B,C,D,E,F,G,H = string_find(v, "^|cff%x%x%x%x%x%x|Hitem:(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%-?%d+):(%d+)|h%[.+%]|h|r$")
|
flickerstreak@1
|
532 if A then
|
flickerstreak@1
|
533 -- item link
|
flickerstreak@1
|
534
|
flickerstreak@1
|
535 A = A+0 -- convert to number
|
flickerstreak@1
|
536 B = B+0
|
flickerstreak@1
|
537 C = C+0
|
flickerstreak@1
|
538 D = D+0
|
flickerstreak@1
|
539 E = E+0
|
flickerstreak@1
|
540 F = F+0
|
flickerstreak@1
|
541 G = G+0
|
flickerstreak@1
|
542 H = H+0
|
flickerstreak@1
|
543
|
flickerstreak@1
|
544 -- (1-35000):(1-3093):(1-3093):(1-3093):(1-3093):(?):(-57 to 2164):(0-4294967295)
|
flickerstreak@1
|
545
|
flickerstreak@1
|
546 F = nil -- don't care
|
flickerstreak@1
|
547 if G < 0 then
|
flickerstreak@1
|
548 G = G + 65536 -- handle negatives
|
flickerstreak@1
|
549 end
|
flickerstreak@1
|
550
|
flickerstreak@1
|
551 H = math_mod(H, 65536) -- only lower 16 bits matter
|
flickerstreak@1
|
552
|
flickerstreak@1
|
553 return string_char(byte_i, math_floormod(A / 256, 256), math_mod(A, 256), math_floormod(B / 256, 256), math_mod(B, 256), math_floormod(C / 256, 256), math_mod(C, 256), math_floormod(D / 256, 256), math_mod(D, 256), math_floormod(E / 256, 256), math_mod(E, 256), math_floormod(G / 256, 256), math_mod(G, 256), math_floormod(H / 256, 256), math_mod(H, 256))
|
flickerstreak@1
|
554 else
|
flickerstreak@1
|
555 -- normal string
|
flickerstreak@1
|
556 local len = string_len(v)
|
flickerstreak@1
|
557 if len <= 255 then
|
flickerstreak@1
|
558 return string_char(byte_s, len) .. v
|
flickerstreak@1
|
559 else
|
flickerstreak@1
|
560 return string_char(byte_S, math_floor(len / 256), math_mod(len, 256)) .. v
|
flickerstreak@1
|
561 end
|
flickerstreak@1
|
562 end
|
flickerstreak@1
|
563 elseif kind == "function" then
|
flickerstreak@1
|
564 AceComm:error("Cannot serialize a function")
|
flickerstreak@1
|
565 elseif kind == "table" then
|
flickerstreak@1
|
566 if recurse[v] then
|
flickerstreak@1
|
567 for k in pairs(recurse) do
|
flickerstreak@1
|
568 recurse[k] = nil
|
flickerstreak@1
|
569 end
|
flickerstreak@1
|
570 AceComm:error("Cannot serialize a recursive table")
|
flickerstreak@1
|
571 return
|
flickerstreak@1
|
572 end
|
flickerstreak@1
|
573 recurse[v] = true
|
flickerstreak@1
|
574 if AceOO.inherits(v, AceOO.Class) then
|
flickerstreak@1
|
575 if not v.class then
|
flickerstreak@1
|
576 AceComm:error("Cannot serialize an AceOO class, can only serialize objects")
|
flickerstreak@1
|
577 elseif type(v.Serialize) ~= "function" then
|
flickerstreak@1
|
578 AceComm:error("Cannot serialize an AceOO object without the `Serialize' method.")
|
flickerstreak@1
|
579 elseif type(v.class.Deserialize) ~= "function" then
|
flickerstreak@1
|
580 AceComm:error("Cannot serialize an AceOO object without the `Deserialize' static method.")
|
flickerstreak@1
|
581 elseif type(v.class.GetLibraryVersion) ~= "function" or not AceLibrary:HasInstance(v.class:GetLibraryVersion()) then
|
flickerstreak@1
|
582 AceComm:error("Cannot serialize an AceOO object if the class is not registered with AceLibrary.")
|
flickerstreak@1
|
583 end
|
flickerstreak@1
|
584 local classHash = TailoredBinaryCheckSum(v.class:GetLibraryVersion())
|
flickerstreak@1
|
585 local t = { classHash, v:Serialize() }
|
flickerstreak@1
|
586 for i = 2, #t do
|
flickerstreak@1
|
587 t[i] = _Serialize(t[i], textToHash)
|
flickerstreak@1
|
588 end
|
flickerstreak@1
|
589 if not notFirst then
|
flickerstreak@1
|
590 for k in pairs(recurse) do
|
flickerstreak@1
|
591 recurse[k] = nil
|
flickerstreak@1
|
592 end
|
flickerstreak@1
|
593 end
|
flickerstreak@1
|
594 local s = table.concat(t)
|
flickerstreak@1
|
595 t = nil
|
flickerstreak@1
|
596 local len = string_len(s)
|
flickerstreak@1
|
597 if len <= 255 then
|
flickerstreak@1
|
598 return string_char(byte_o, len) .. s
|
flickerstreak@1
|
599 else
|
flickerstreak@1
|
600 return string_char(byte_O, math_floor(len / 256), math_mod(len, 256)) .. s
|
flickerstreak@1
|
601 end
|
flickerstreak@1
|
602 end
|
flickerstreak@1
|
603 local t = {}
|
flickerstreak@1
|
604 local islist = false
|
flickerstreak@1
|
605 local n = #v
|
flickerstreak@1
|
606 if n >= 1 then
|
flickerstreak@1
|
607 islist = true
|
flickerstreak@1
|
608 for k,u in pairs(v) do
|
flickerstreak@1
|
609 if type(k) ~= "number" or k < 1 then
|
flickerstreak@1
|
610 islist = false
|
flickerstreak@1
|
611 break
|
flickerstreak@1
|
612 end
|
flickerstreak@1
|
613 end
|
flickerstreak@1
|
614 end
|
flickerstreak@1
|
615 if islist then
|
flickerstreak@1
|
616 n = n * 4
|
flickerstreak@1
|
617 while v[n] == nil do
|
flickerstreak@1
|
618 n = n - 1
|
flickerstreak@1
|
619 end
|
flickerstreak@1
|
620 for i = 1, n do
|
flickerstreak@1
|
621 t[i] = _Serialize(v[i], textToHash)
|
flickerstreak@1
|
622 end
|
flickerstreak@1
|
623 else
|
flickerstreak@1
|
624 local i = 1
|
flickerstreak@1
|
625 for k,u in pairs(v) do
|
flickerstreak@1
|
626 t[i] = _Serialize(k, textToHash)
|
flickerstreak@1
|
627 t[i+1] = _Serialize(u, textToHash)
|
flickerstreak@1
|
628 i = i + 2
|
flickerstreak@1
|
629 end
|
flickerstreak@1
|
630 end
|
flickerstreak@1
|
631 if not notFirst then
|
flickerstreak@1
|
632 for k in pairs(recurse) do
|
flickerstreak@1
|
633 recurse[k] = nil
|
flickerstreak@1
|
634 end
|
flickerstreak@1
|
635 end
|
flickerstreak@1
|
636 local s = table.concat(t)
|
flickerstreak@1
|
637 t = nil
|
flickerstreak@1
|
638 local len = string_len(s)
|
flickerstreak@1
|
639 if islist then
|
flickerstreak@1
|
640 if len <= 255 then
|
flickerstreak@1
|
641 return string_char(byte_u, len) .. s
|
flickerstreak@1
|
642 else
|
flickerstreak@1
|
643 return "U" .. string_char(math_floor(len / 256), math_mod(len, 256)) .. s
|
flickerstreak@1
|
644 end
|
flickerstreak@1
|
645 else
|
flickerstreak@1
|
646 if len <= 255 then
|
flickerstreak@1
|
647 return "t" .. string_char(len) .. s
|
flickerstreak@1
|
648 else
|
flickerstreak@1
|
649 return "T" .. string_char(math_floor(len / 256), math_mod(len, 256)) .. s
|
flickerstreak@1
|
650 end
|
flickerstreak@1
|
651 end
|
flickerstreak@1
|
652 end
|
flickerstreak@1
|
653 end
|
flickerstreak@1
|
654
|
flickerstreak@1
|
655 function Serialize(value, textToHash)
|
flickerstreak@1
|
656 if not recurse then
|
flickerstreak@1
|
657 recurse = {}
|
flickerstreak@1
|
658 end
|
flickerstreak@1
|
659 local chunk = _Serialize(value, textToHash)
|
flickerstreak@1
|
660 for k in pairs(recurse) do
|
flickerstreak@1
|
661 recurse[k] = nil
|
flickerstreak@1
|
662 end
|
flickerstreak@1
|
663 return chunk
|
flickerstreak@1
|
664 end
|
flickerstreak@1
|
665 end
|
flickerstreak@1
|
666
|
flickerstreak@1
|
667 local Deserialize
|
flickerstreak@1
|
668 do
|
flickerstreak@1
|
669 local tmp = {}
|
flickerstreak@1
|
670 local function _Deserialize(value, position, hashToText)
|
flickerstreak@1
|
671 if not position then
|
flickerstreak@1
|
672 position = 1
|
flickerstreak@1
|
673 end
|
flickerstreak@1
|
674 local x = string_byte(value, position)
|
flickerstreak@1
|
675 if x == byte_b then
|
flickerstreak@1
|
676 -- false
|
flickerstreak@1
|
677 return false, position
|
flickerstreak@1
|
678 elseif x == byte_B then
|
flickerstreak@1
|
679 -- true
|
flickerstreak@1
|
680 return true, position
|
flickerstreak@1
|
681 elseif x == byte_nil then
|
flickerstreak@1
|
682 -- nil
|
flickerstreak@1
|
683 return nil, position
|
flickerstreak@1
|
684 elseif x == byte_i then
|
flickerstreak@1
|
685 -- 14-byte item link
|
flickerstreak@1
|
686 local a1 = string_byte(value, position + 1)
|
flickerstreak@1
|
687 local a2 = string_byte(value, position + 2)
|
flickerstreak@1
|
688 local b1 = string_byte(value, position + 3)
|
flickerstreak@1
|
689 local b2 = string_byte(value, position + 4)
|
flickerstreak@1
|
690 local c1 = string_byte(value, position + 5)
|
flickerstreak@1
|
691 local c2 = string_byte(value, position + 6)
|
flickerstreak@1
|
692 local d1 = string_byte(value, position + 7)
|
flickerstreak@1
|
693 local d2 = string_byte(value, position + 8)
|
flickerstreak@1
|
694 local e1 = string_byte(value, position + 9)
|
flickerstreak@1
|
695 local e2 = string_byte(value, position + 10)
|
flickerstreak@1
|
696 local g1 = string_byte(value, position + 11)
|
flickerstreak@1
|
697 local g2 = string_byte(value, position + 12)
|
flickerstreak@1
|
698 local h1 = string_byte(value, position + 13)
|
flickerstreak@1
|
699 local h2 = string_byte(value, position + 14)
|
flickerstreak@1
|
700 local A = a1 * 256 + a2
|
flickerstreak@1
|
701 local B = b1 * 256 + b2
|
flickerstreak@1
|
702 local C = c1 * 256 + c2
|
flickerstreak@1
|
703 local D = d1 * 256 + d2
|
flickerstreak@1
|
704 local E = e1 * 256 + e2
|
flickerstreak@1
|
705 local G = g1 * 256 + g2
|
flickerstreak@1
|
706 local H = h1 * 256 + h2
|
flickerstreak@1
|
707 if G >= 32768 then
|
flickerstreak@1
|
708 G = G - 65536
|
flickerstreak@1
|
709 end
|
flickerstreak@1
|
710 local s = string.format("item:%d:%d:%d:%d:%d:%d:%d:%d", A, B, C, D, E, 0, G, H)
|
flickerstreak@1
|
711 local _, link = GetItemInfo(s)
|
flickerstreak@1
|
712 return link, position + 14
|
flickerstreak@1
|
713 elseif x == byte_m then
|
flickerstreak@1
|
714 local hash = string_byte(value, position + 1) * 65536 + string_byte(value, position + 2) * 256 + string_byte(value, position + 3)
|
flickerstreak@1
|
715 return hashToText[hash], position + 3
|
flickerstreak@1
|
716 elseif x == byte_s then
|
flickerstreak@1
|
717 -- 0-255-byte string
|
flickerstreak@1
|
718 local len = string_byte(value, position + 1)
|
flickerstreak@1
|
719 return string.sub(value, position + 2, position + 1 + len), position + 1 + len
|
flickerstreak@1
|
720 elseif x == byte_S then
|
flickerstreak@1
|
721 -- 256-65535-byte string
|
flickerstreak@1
|
722 local len = string_byte(value, position + 1) * 256 + string_byte(value, position + 2)
|
flickerstreak@1
|
723 return string.sub(value, position + 3, position + 2 + len), position + 2 + len
|
flickerstreak@1
|
724 elseif x == 64 --[[byte_inf]] then
|
flickerstreak@1
|
725 return inf, position
|
flickerstreak@1
|
726 elseif x == 36 --[[byte_ninf]] then
|
flickerstreak@1
|
727 return -inf, position
|
flickerstreak@1
|
728 elseif x == 33 --[[byte_nan]] then
|
flickerstreak@1
|
729 return nan, position
|
flickerstreak@1
|
730 elseif x == byte_d then
|
flickerstreak@1
|
731 -- 1-byte integer
|
flickerstreak@1
|
732 local a = string_byte(value, position + 1)
|
flickerstreak@1
|
733 if a >= 128 then
|
flickerstreak@1
|
734 a = a - 256
|
flickerstreak@1
|
735 end
|
flickerstreak@1
|
736 return a, position + 1
|
flickerstreak@1
|
737 elseif x == byte_D then
|
flickerstreak@1
|
738 -- 2-byte integer
|
flickerstreak@1
|
739 local a = string_byte(value, position + 1)
|
flickerstreak@1
|
740 local b = string_byte(value, position + 2)
|
flickerstreak@1
|
741 local N = a * 256 + b
|
flickerstreak@1
|
742 if N >= 32768 then
|
flickerstreak@1
|
743 N = N - 65536
|
flickerstreak@1
|
744 end
|
flickerstreak@1
|
745 return N, position + 2
|
flickerstreak@1
|
746 elseif x == byte_e then
|
flickerstreak@1
|
747 -- 4-byte integer
|
flickerstreak@1
|
748 local a = string_byte(value, position + 1)
|
flickerstreak@1
|
749 local b = string_byte(value, position + 2)
|
flickerstreak@1
|
750 local c = string_byte(value, position + 3)
|
flickerstreak@1
|
751 local d = string_byte(value, position + 4)
|
flickerstreak@1
|
752 local N = a * 16777216 + b * 65536 + c * 256 + d
|
flickerstreak@1
|
753 if N >= 2147483648 then
|
flickerstreak@1
|
754 N = N - 4294967296
|
flickerstreak@1
|
755 end
|
flickerstreak@1
|
756 return N, position + 4
|
flickerstreak@1
|
757 elseif x == byte_E then
|
flickerstreak@1
|
758 -- 8-byte integer
|
flickerstreak@1
|
759 local a = string_byte(value, position + 1)
|
flickerstreak@1
|
760 local b = string_byte(value, position + 2)
|
flickerstreak@1
|
761 local c = string_byte(value, position + 3)
|
flickerstreak@1
|
762 local d = string_byte(value, position + 4)
|
flickerstreak@1
|
763 local e = string_byte(value, position + 5)
|
flickerstreak@1
|
764 local f = string_byte(value, position + 6)
|
flickerstreak@1
|
765 local g = string_byte(value, position + 7)
|
flickerstreak@1
|
766 local h = string_byte(value, position + 8)
|
flickerstreak@1
|
767 local N = a * 72057594037927936 + b * 281474976710656 + c * 1099511627776 + d * 4294967296 + e * 16777216 + f * 65536 + g * 256 + h
|
flickerstreak@1
|
768 if N >= 9223372036854775808 then
|
flickerstreak@1
|
769 N = N - 18446744073709551616
|
flickerstreak@1
|
770 end
|
flickerstreak@1
|
771 return N, position + 8
|
flickerstreak@1
|
772 elseif x == byte_plus or x == byte_minus then
|
flickerstreak@1
|
773 local a = string_byte(value, position + 1)
|
flickerstreak@1
|
774 local b = string_byte(value, position + 2)
|
flickerstreak@1
|
775 local c = string_byte(value, position + 3)
|
flickerstreak@1
|
776 local d = string_byte(value, position + 4)
|
flickerstreak@1
|
777 local e = string_byte(value, position + 5)
|
flickerstreak@1
|
778 local f = string_byte(value, position + 6)
|
flickerstreak@1
|
779 local g = string_byte(value, position + 7)
|
flickerstreak@1
|
780 local h = string_byte(value, position + 8)
|
flickerstreak@1
|
781 local N = a * 1099511627776 + b * 4294967296 + c * 16777216 + d * 65536 + e * 256 + f
|
flickerstreak@1
|
782 local sign = x
|
flickerstreak@1
|
783 local x = math.floor(N / 137438953472)
|
flickerstreak@1
|
784 local m = math_mod(N, 137438953472) * 65536 + g * 256 + h
|
flickerstreak@1
|
785 local mantissa = m / 9007199254740992
|
flickerstreak@1
|
786 local exp = x - 1023
|
flickerstreak@1
|
787 local val = math.ldexp(mantissa, exp)
|
flickerstreak@1
|
788 if sign == byte_minus then
|
flickerstreak@1
|
789 return -val, position + 8
|
flickerstreak@1
|
790 end
|
flickerstreak@1
|
791 return val, position + 8
|
flickerstreak@1
|
792 elseif x == byte_u or x == byte_U then
|
flickerstreak@1
|
793 -- numerically-indexed table
|
flickerstreak@1
|
794 local finish
|
flickerstreak@1
|
795 local start
|
flickerstreak@1
|
796 if x == byte_u then
|
flickerstreak@1
|
797 local len = string_byte(value, position + 1)
|
flickerstreak@1
|
798 finish = position + 1 + len
|
flickerstreak@1
|
799 start = position + 2
|
flickerstreak@1
|
800 else
|
flickerstreak@1
|
801 local len = string_byte(value, position + 1) * 256 + string_byte(value, position + 2)
|
flickerstreak@1
|
802 finish = position + 2 + len
|
flickerstreak@1
|
803 start = position + 3
|
flickerstreak@1
|
804 end
|
flickerstreak@1
|
805 local t = {}
|
flickerstreak@1
|
806 local n = 0
|
flickerstreak@1
|
807 local curr = start - 1
|
flickerstreak@1
|
808 while curr < finish do
|
flickerstreak@1
|
809 local v
|
flickerstreak@1
|
810 v, curr = _Deserialize(value, curr + 1, hashToText)
|
flickerstreak@1
|
811 n = n + 1
|
flickerstreak@1
|
812 t[n] = v
|
flickerstreak@1
|
813 end
|
flickerstreak@1
|
814 return t, finish
|
flickerstreak@1
|
815 elseif x == byte_o or x == byte_O then
|
flickerstreak@1
|
816 -- numerically-indexed table
|
flickerstreak@1
|
817 local finish
|
flickerstreak@1
|
818 local start
|
flickerstreak@1
|
819 if x == byte_o then
|
flickerstreak@1
|
820 local len = string_byte(value, position + 1)
|
flickerstreak@1
|
821 finish = position + 1 + len
|
flickerstreak@1
|
822 start = position + 2
|
flickerstreak@1
|
823 else
|
flickerstreak@1
|
824 local len = string_byte(value, position + 1) * 256 + string_byte(value, position + 2)
|
flickerstreak@1
|
825 finish = position + 2 + len
|
flickerstreak@1
|
826 start = position + 3
|
flickerstreak@1
|
827 end
|
flickerstreak@1
|
828 local hash = string_byte(value, start) * 65536 + string_byte(value, start + 1) * 256 + string_byte(value, start + 2)
|
flickerstreak@1
|
829 local curr = start + 2
|
flickerstreak@1
|
830 if not AceComm.classes[hash] then
|
flickerstreak@1
|
831 return nil, finish
|
flickerstreak@1
|
832 end
|
flickerstreak@1
|
833 local class = AceComm.classes[hash]
|
flickerstreak@1
|
834 if type(class.Deserialize) ~= "function" or type(class.prototype.Serialize) ~= "function" then
|
flickerstreak@1
|
835 return nil, finish
|
flickerstreak@1
|
836 end
|
flickerstreak@1
|
837 local n = 0
|
flickerstreak@1
|
838 while curr < finish do
|
flickerstreak@1
|
839 local v
|
flickerstreak@1
|
840 v, curr = _Deserialize(value, curr + 1, hashToText)
|
flickerstreak@1
|
841 n = n + 1
|
flickerstreak@1
|
842 tmp[n] = v
|
flickerstreak@1
|
843 end
|
flickerstreak@1
|
844 local object = class:Deserialize(unpack(tmp))
|
flickerstreak@1
|
845 for i = 1, n do
|
flickerstreak@1
|
846 tmp[i] = nil
|
flickerstreak@1
|
847 end
|
flickerstreak@1
|
848 return object, finish
|
flickerstreak@1
|
849 elseif x == byte_t or x == byte_T then
|
flickerstreak@1
|
850 -- table
|
flickerstreak@1
|
851 local finish
|
flickerstreak@1
|
852 local start
|
flickerstreak@1
|
853 if x == byte_t then
|
flickerstreak@1
|
854 local len = string_byte(value, position + 1)
|
flickerstreak@1
|
855 finish = position + 1 + len
|
flickerstreak@1
|
856 start = position + 2
|
flickerstreak@1
|
857 else
|
flickerstreak@1
|
858 local len = string_byte(value, position + 1) * 256 + string_byte(value, position + 2)
|
flickerstreak@1
|
859 finish = position + 2 + len
|
flickerstreak@1
|
860 start = position + 3
|
flickerstreak@1
|
861 end
|
flickerstreak@1
|
862 local t = {}
|
flickerstreak@1
|
863 local curr = start - 1
|
flickerstreak@1
|
864 while curr < finish do
|
flickerstreak@1
|
865 local key, l = _Deserialize(value, curr + 1, hashToText)
|
flickerstreak@1
|
866 local value, m = _Deserialize(value, l + 1, hashToText)
|
flickerstreak@1
|
867 curr = m
|
flickerstreak@1
|
868 t[key] = value
|
flickerstreak@1
|
869 end
|
flickerstreak@1
|
870 if type(t.n) ~= "number" then
|
flickerstreak@1
|
871 local i = 1
|
flickerstreak@1
|
872 while t[i] ~= nil do
|
flickerstreak@1
|
873 i = i + 1
|
flickerstreak@1
|
874 end
|
flickerstreak@1
|
875 end
|
flickerstreak@1
|
876 return t, finish
|
flickerstreak@1
|
877 else
|
flickerstreak@1
|
878 error("Improper serialized value provided")
|
flickerstreak@1
|
879 end
|
flickerstreak@1
|
880 end
|
flickerstreak@1
|
881
|
flickerstreak@1
|
882 function Deserialize(value, hashToText)
|
flickerstreak@1
|
883 local ret,msg = pcall(_Deserialize, value, nil, hashToText)
|
flickerstreak@1
|
884 if ret then
|
flickerstreak@1
|
885 return msg
|
flickerstreak@1
|
886 end
|
flickerstreak@1
|
887 end
|
flickerstreak@1
|
888 end
|
flickerstreak@1
|
889
|
flickerstreak@1
|
890 local function GetCurrentGroupDistribution()
|
flickerstreak@1
|
891 if MiniMapBattlefieldFrame.status == "active" then
|
flickerstreak@1
|
892 return "BATTLEGROUND"
|
flickerstreak@1
|
893 elseif UnitInRaid("player") then
|
flickerstreak@1
|
894 return "RAID"
|
flickerstreak@1
|
895 elseif UnitInParty("player") then
|
flickerstreak@1
|
896 return "PARTY"
|
flickerstreak@1
|
897 else
|
flickerstreak@1
|
898 return nil
|
flickerstreak@1
|
899 end
|
flickerstreak@1
|
900 end
|
flickerstreak@1
|
901
|
flickerstreak@1
|
902 local function IsInDistribution(dist, customChannel)
|
flickerstreak@1
|
903 if dist == "GROUP" then
|
flickerstreak@1
|
904 return GetCurrentGroupDistribution() and true or false
|
flickerstreak@1
|
905 elseif dist == "BATTLEGROUND" then
|
flickerstreak@1
|
906 return MiniMapBattlefieldFrame.status == "active"
|
flickerstreak@1
|
907 elseif dist == "RAID" then
|
flickerstreak@1
|
908 return UnitInRaid("player") == 1
|
flickerstreak@1
|
909 elseif dist == "PARTY" then
|
flickerstreak@1
|
910 return UnitInParty("player") == 1
|
flickerstreak@1
|
911 elseif dist == "GUILD" then
|
flickerstreak@1
|
912 return IsInGuild() == 1
|
flickerstreak@1
|
913 elseif dist == "GLOBAL" then
|
flickerstreak@1
|
914 return IsInChannel("AceComm")
|
flickerstreak@1
|
915 elseif dist == "ZONE" then
|
flickerstreak@1
|
916 return IsInChannel(GetCurrentZoneChannel())
|
flickerstreak@1
|
917 elseif dist == "WHISPER" then
|
flickerstreak@1
|
918 return true
|
flickerstreak@1
|
919 elseif dist == "CUSTOM" then
|
flickerstreak@1
|
920 return IsInChannel(customChannel)
|
flickerstreak@1
|
921 end
|
flickerstreak@1
|
922 error("unknown distribution: " .. dist, 2)
|
flickerstreak@1
|
923 end
|
flickerstreak@1
|
924
|
flickerstreak@1
|
925 function AceComm:RegisterComm(prefix, distribution, method, a4)
|
flickerstreak@1
|
926 AceComm:argCheck(prefix, 2, "string")
|
flickerstreak@1
|
927 AceComm:argCheck(distribution, 3, "string")
|
flickerstreak@1
|
928 if distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then
|
flickerstreak@1
|
929 AceComm:error('Argument #3 to `RegisterComm\' must be either "GLOBAL", "ZONE", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", or "CUSTOM". %q is not appropriate', distribution)
|
flickerstreak@1
|
930 end
|
flickerstreak@1
|
931 local customChannel
|
flickerstreak@1
|
932 if distribution == "CUSTOM" then
|
flickerstreak@1
|
933 customChannel, method = method, a4
|
flickerstreak@1
|
934 AceComm:argCheck(customChannel, 4, "string")
|
flickerstreak@1
|
935 if string_len(customChannel) == 0 then
|
flickerstreak@1
|
936 AceComm:error('Argument #4 to `RegisterComm\' must be a non-zero-length string.')
|
flickerstreak@1
|
937 elseif string_find(customChannel, "%s") then
|
flickerstreak@1
|
938 AceComm:error('Argument #4 to `RegisterComm\' must not have spaces.')
|
flickerstreak@1
|
939 end
|
flickerstreak@1
|
940 end
|
flickerstreak@1
|
941 if self == AceComm then
|
flickerstreak@1
|
942 AceComm:argCheck(method, customChannel and 5 or 4, "function", "table")
|
flickerstreak@1
|
943 self = method
|
flickerstreak@1
|
944 else
|
flickerstreak@1
|
945 AceComm:argCheck(method, customChannel and 5 or 4, "string", "function", "table", "nil")
|
flickerstreak@1
|
946 end
|
flickerstreak@1
|
947 if not method then
|
flickerstreak@1
|
948 method = "OnCommReceive"
|
flickerstreak@1
|
949 end
|
flickerstreak@1
|
950 if type(method) == "string" and type(self[method]) ~= "function" and type(self[method]) ~= "table" then
|
flickerstreak@1
|
951 AceEvent:error("Cannot register comm %q to method %q, it does not exist", prefix, method)
|
flickerstreak@1
|
952 end
|
flickerstreak@1
|
953
|
flickerstreak@1
|
954 local registry = AceComm_registry
|
flickerstreak@1
|
955 if not registry[distribution] then
|
flickerstreak@1
|
956 registry[distribution] = {}
|
flickerstreak@1
|
957 end
|
flickerstreak@1
|
958 if customChannel then
|
flickerstreak@1
|
959 customChannel = "AceComm" .. customChannel
|
flickerstreak@1
|
960 if not registry[distribution][customChannel] then
|
flickerstreak@1
|
961 registry[distribution][customChannel] = {}
|
flickerstreak@1
|
962 end
|
flickerstreak@1
|
963 if not registry[distribution][customChannel][prefix] then
|
flickerstreak@1
|
964 registry[distribution][customChannel][prefix] = {}
|
flickerstreak@1
|
965 end
|
flickerstreak@1
|
966 registry[distribution][customChannel][prefix][self] = method
|
flickerstreak@1
|
967 else
|
flickerstreak@1
|
968 if not registry[distribution][prefix] then
|
flickerstreak@1
|
969 registry[distribution][prefix] = {}
|
flickerstreak@1
|
970 end
|
flickerstreak@1
|
971 registry[distribution][prefix][self] = method
|
flickerstreak@1
|
972 end
|
flickerstreak@1
|
973
|
flickerstreak@1
|
974 RefixAceCommChannelsAndEvents()
|
flickerstreak@1
|
975 end
|
flickerstreak@1
|
976
|
flickerstreak@1
|
977 function AceComm:UnregisterComm(prefix, distribution, customChannel)
|
flickerstreak@1
|
978 AceComm:argCheck(prefix, 2, "string")
|
flickerstreak@1
|
979 AceComm:argCheck(distribution, 3, "string", "nil")
|
flickerstreak@1
|
980 if distribution and distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "CUSTOM" then
|
flickerstreak@1
|
981 AceComm:error('Argument #3 to `UnregisterComm\' must be either nil, "GLOBAL", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", or "CUSTOM". %q is not appropriate', distribution)
|
flickerstreak@1
|
982 end
|
flickerstreak@1
|
983 if distribution == "CUSTOM" then
|
flickerstreak@1
|
984 AceComm:argCheck(customChannel, 3, "string")
|
flickerstreak@1
|
985 if string_len(customChannel) == 0 then
|
flickerstreak@1
|
986 AceComm:error('Argument #3 to `UnregisterComm\' must be a non-zero-length string.')
|
flickerstreak@1
|
987 end
|
flickerstreak@1
|
988 else
|
flickerstreak@1
|
989 AceComm:argCheck(customChannel, 3, "nil")
|
flickerstreak@1
|
990 end
|
flickerstreak@1
|
991
|
flickerstreak@1
|
992 local registry = AceComm_registry
|
flickerstreak@1
|
993 if not distribution then
|
flickerstreak@1
|
994 for k,v in pairs(registry) do
|
flickerstreak@1
|
995 if k == "CUSTOM" then
|
flickerstreak@1
|
996 for l,u in pairs(v) do
|
flickerstreak@1
|
997 if u[prefix] and u[prefix][self] then
|
flickerstreak@1
|
998 AceComm.UnregisterComm(self, prefix, k, string.sub(l, 8))
|
flickerstreak@1
|
999 if not registry[k] then
|
flickerstreak@1
|
1000 break
|
flickerstreak@1
|
1001 end
|
flickerstreak@1
|
1002 end
|
flickerstreak@1
|
1003 end
|
flickerstreak@1
|
1004 else
|
flickerstreak@1
|
1005 if v[prefix] and v[prefix][self] then
|
flickerstreak@1
|
1006 AceComm.UnregisterComm(self, prefix, k)
|
flickerstreak@1
|
1007 end
|
flickerstreak@1
|
1008 end
|
flickerstreak@1
|
1009 end
|
flickerstreak@1
|
1010 return
|
flickerstreak@1
|
1011 end
|
flickerstreak@1
|
1012 if self == AceComm then
|
flickerstreak@1
|
1013 if distribution == "CUSTOM" then
|
flickerstreak@1
|
1014 error(string_format("Cannot unregister comm %q::%q. Improperly unregistering from AceComm-2.0.", distribution, customChannel), 2)
|
flickerstreak@1
|
1015 else
|
flickerstreak@1
|
1016 error(string_format("Cannot unregister comm %q. Improperly unregistering from AceComm-2.0.", distribution), 2)
|
flickerstreak@1
|
1017 end
|
flickerstreak@1
|
1018 end
|
flickerstreak@1
|
1019 if distribution == "CUSTOM" then
|
flickerstreak@1
|
1020 customChannel = "AceComm" .. customChannel
|
flickerstreak@1
|
1021 if not registry[distribution] or not registry[distribution][customChannel] or not registry[distribution][customChannel][prefix] or not registry[distribution][customChannel][prefix][self] then
|
flickerstreak@1
|
1022 AceComm:error("Cannot unregister comm %q. %q is not registered with it.", distribution, self)
|
flickerstreak@1
|
1023 end
|
flickerstreak@1
|
1024 registry[distribution][customChannel][prefix][self] = nil
|
flickerstreak@1
|
1025
|
flickerstreak@1
|
1026 if not next(registry[distribution][customChannel][prefix]) then
|
flickerstreak@1
|
1027 registry[distribution][customChannel][prefix] = nil
|
flickerstreak@1
|
1028 end
|
flickerstreak@1
|
1029
|
flickerstreak@1
|
1030 if not next(registry[distribution][customChannel]) then
|
flickerstreak@1
|
1031 registry[distribution][customChannel] = nil
|
flickerstreak@1
|
1032 end
|
flickerstreak@1
|
1033 else
|
flickerstreak@1
|
1034 if not registry[distribution] or not registry[distribution][prefix] or not registry[distribution][prefix][self] then
|
flickerstreak@1
|
1035 AceComm:error("Cannot unregister comm %q. %q is not registered with it.", distribution, self)
|
flickerstreak@1
|
1036 end
|
flickerstreak@1
|
1037 registry[distribution][prefix][self] = nil
|
flickerstreak@1
|
1038
|
flickerstreak@1
|
1039 if not next(registry[distribution][prefix]) then
|
flickerstreak@1
|
1040 registry[distribution][prefix] = nil
|
flickerstreak@1
|
1041 end
|
flickerstreak@1
|
1042 end
|
flickerstreak@1
|
1043
|
flickerstreak@1
|
1044 if not next(registry[distribution]) then
|
flickerstreak@1
|
1045 registry[distribution] = nil
|
flickerstreak@1
|
1046 end
|
flickerstreak@1
|
1047
|
flickerstreak@1
|
1048 RefixAceCommChannelsAndEvents()
|
flickerstreak@1
|
1049 end
|
flickerstreak@1
|
1050
|
flickerstreak@1
|
1051 function AceComm:UnregisterAllComms()
|
flickerstreak@1
|
1052 local registry = AceComm_registry
|
flickerstreak@1
|
1053 for k, distribution in pairs(registry) do
|
flickerstreak@1
|
1054 if k == "CUSTOM" then
|
flickerstreak@1
|
1055 for l, channel in pairs(distribution) do
|
flickerstreak@1
|
1056 local j = next(channel)
|
flickerstreak@1
|
1057 while j ~= nil do
|
flickerstreak@1
|
1058 local prefix = channel[j]
|
flickerstreak@1
|
1059 if prefix[self] then
|
flickerstreak@1
|
1060 AceComm.UnregisterComm(self, j)
|
flickerstreak@1
|
1061 if distribution[l] and registry[k] then
|
flickerstreak@1
|
1062 j = next(channel)
|
flickerstreak@1
|
1063 else
|
flickerstreak@1
|
1064 l = nil
|
flickerstreak@1
|
1065 k = nil
|
flickerstreak@1
|
1066 break
|
flickerstreak@1
|
1067 end
|
flickerstreak@1
|
1068 else
|
flickerstreak@1
|
1069 j = next(channel, j)
|
flickerstreak@1
|
1070 end
|
flickerstreak@1
|
1071 end
|
flickerstreak@1
|
1072 if k == nil then
|
flickerstreak@1
|
1073 break
|
flickerstreak@1
|
1074 end
|
flickerstreak@1
|
1075 end
|
flickerstreak@1
|
1076 else
|
flickerstreak@1
|
1077 local j = next(distribution)
|
flickerstreak@1
|
1078 while j ~= nil do
|
flickerstreak@1
|
1079 local prefix = distribution[j]
|
flickerstreak@1
|
1080 if prefix[self] then
|
flickerstreak@1
|
1081 AceComm.UnregisterComm(self, j)
|
flickerstreak@1
|
1082 if registry[k] then
|
flickerstreak@1
|
1083 j = next(distribution)
|
flickerstreak@1
|
1084 else
|
flickerstreak@1
|
1085 k = nil
|
flickerstreak@1
|
1086 break
|
flickerstreak@1
|
1087 end
|
flickerstreak@1
|
1088 else
|
flickerstreak@1
|
1089 j = next(distribution, j)
|
flickerstreak@1
|
1090 end
|
flickerstreak@1
|
1091 end
|
flickerstreak@1
|
1092 end
|
flickerstreak@1
|
1093 end
|
flickerstreak@1
|
1094 end
|
flickerstreak@1
|
1095
|
flickerstreak@1
|
1096 function AceComm:IsCommRegistered(prefix, distribution, customChannel)
|
flickerstreak@1
|
1097 AceComm:argCheck(prefix, 2, "string")
|
flickerstreak@1
|
1098 AceComm:argCheck(distribution, 3, "string", "nil")
|
flickerstreak@1
|
1099 if distribution and distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then
|
flickerstreak@1
|
1100 AceComm:error('Argument #3 to `IsCommRegistered\' must be either "GLOBAL", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", "ZONE", or "CUSTOM". %q is not appropriate', distribution)
|
flickerstreak@1
|
1101 end
|
flickerstreak@1
|
1102 if distribution == "CUSTOM" then
|
flickerstreak@1
|
1103 AceComm:argCheck(customChannel, 4, "nil", "string")
|
flickerstreak@1
|
1104 if customChannel == "" then
|
flickerstreak@1
|
1105 AceComm:error('Argument #4 to `IsCommRegistered\' must be a non-zero-length string or nil.')
|
flickerstreak@1
|
1106 end
|
flickerstreak@1
|
1107 else
|
flickerstreak@1
|
1108 AceComm:argCheck(customChannel, 4, "nil")
|
flickerstreak@1
|
1109 end
|
flickerstreak@1
|
1110 local registry = AceComm_registry
|
flickerstreak@1
|
1111 if not distribution then
|
flickerstreak@1
|
1112 for k,v in pairs(registry) do
|
flickerstreak@1
|
1113 if k == "CUSTOM" then
|
flickerstreak@1
|
1114 for l,u in pairs(v) do
|
flickerstreak@1
|
1115 if u[prefix] and u[prefix][self] then
|
flickerstreak@1
|
1116 return true
|
flickerstreak@1
|
1117 end
|
flickerstreak@1
|
1118 end
|
flickerstreak@1
|
1119 else
|
flickerstreak@1
|
1120 if v[prefix] and v[prefix][self] then
|
flickerstreak@1
|
1121 return true
|
flickerstreak@1
|
1122 end
|
flickerstreak@1
|
1123 end
|
flickerstreak@1
|
1124 end
|
flickerstreak@1
|
1125 return false
|
flickerstreak@1
|
1126 elseif distribution == "CUSTOM" and not customChannel then
|
flickerstreak@1
|
1127 if not registry[distribution] then
|
flickerstreak@1
|
1128 return false
|
flickerstreak@1
|
1129 end
|
flickerstreak@1
|
1130 for l,u in pairs(registry[distribution]) do
|
flickerstreak@1
|
1131 if u[prefix] and u[prefix][self] then
|
flickerstreak@1
|
1132 return true
|
flickerstreak@1
|
1133 end
|
flickerstreak@1
|
1134 end
|
flickerstreak@1
|
1135 return false
|
flickerstreak@1
|
1136 elseif distribution == "CUSTOM" then
|
flickerstreak@1
|
1137 customChannel = "AceComm" .. customChannel
|
flickerstreak@1
|
1138 return registry[distribution] and registry[distribution][customChannel] and registry[distribution][customChannel][prefix] and registry[distribution][customChannel][prefix][self] and true or false
|
flickerstreak@1
|
1139 end
|
flickerstreak@1
|
1140 return registry[distribution] and registry[distribution][prefix] and registry[distribution][prefix][self] and true or false
|
flickerstreak@1
|
1141 end
|
flickerstreak@1
|
1142
|
flickerstreak@1
|
1143 function AceComm:OnEmbedDisable(target)
|
flickerstreak@1
|
1144 self.UnregisterAllComms(target)
|
flickerstreak@1
|
1145 end
|
flickerstreak@1
|
1146
|
flickerstreak@1
|
1147 local id = byte_Z
|
flickerstreak@1
|
1148
|
flickerstreak@1
|
1149 local function encodedChar(x)
|
flickerstreak@1
|
1150 if x == 10 then
|
flickerstreak@1
|
1151 return "°\011"
|
flickerstreak@1
|
1152 elseif x == 0 then
|
flickerstreak@1
|
1153 return "\255"
|
flickerstreak@1
|
1154 elseif x == 255 then
|
flickerstreak@1
|
1155 return "°\254"
|
flickerstreak@1
|
1156 elseif x == 124 then
|
flickerstreak@1
|
1157 return "°\125"
|
flickerstreak@1
|
1158 elseif x == byte_s then
|
flickerstreak@1
|
1159 return "\015"
|
flickerstreak@1
|
1160 elseif x == byte_S then
|
flickerstreak@1
|
1161 return "\020"
|
flickerstreak@1
|
1162 elseif x == 15 then
|
flickerstreak@1
|
1163 return "°\016"
|
flickerstreak@1
|
1164 elseif x == 20 then
|
flickerstreak@1
|
1165 return "°\021"
|
flickerstreak@1
|
1166 elseif x == byte_deg then
|
flickerstreak@1
|
1167 return "°±"
|
flickerstreak@1
|
1168 elseif x == 37 then
|
flickerstreak@1
|
1169 return "°\038"
|
flickerstreak@1
|
1170 end
|
flickerstreak@1
|
1171 return string_char(x)
|
flickerstreak@1
|
1172 end
|
flickerstreak@1
|
1173
|
flickerstreak@1
|
1174 local function soberEncodedChar(x)
|
flickerstreak@1
|
1175 if x == 10 then
|
flickerstreak@1
|
1176 return "°\011"
|
flickerstreak@1
|
1177 elseif x == 0 then
|
flickerstreak@1
|
1178 return "\255"
|
flickerstreak@1
|
1179 elseif x == 255 then
|
flickerstreak@1
|
1180 return "°\254"
|
flickerstreak@1
|
1181 elseif x == 124 then
|
flickerstreak@1
|
1182 return "°\125"
|
flickerstreak@1
|
1183 elseif x == byte_deg then
|
flickerstreak@1
|
1184 return "°±"
|
flickerstreak@1
|
1185 elseif x == 37 then
|
flickerstreak@1
|
1186 return "°\038"
|
flickerstreak@1
|
1187 end
|
flickerstreak@1
|
1188 return string_char(x)
|
flickerstreak@1
|
1189 end
|
flickerstreak@1
|
1190
|
flickerstreak@1
|
1191 local function SendMessage(prefix, priority, distribution, person, message, textToHash)
|
flickerstreak@1
|
1192 if distribution == "CUSTOM" then
|
flickerstreak@1
|
1193 person = "AceComm" .. person
|
flickerstreak@1
|
1194 end
|
flickerstreak@1
|
1195 if not IsInDistribution(distribution, person) then
|
flickerstreak@1
|
1196 return false
|
flickerstreak@1
|
1197 end
|
flickerstreak@1
|
1198 if distribution == "GROUP" then
|
flickerstreak@1
|
1199 distribution = GetCurrentGroupDistribution()
|
flickerstreak@1
|
1200 if not distribution then
|
flickerstreak@1
|
1201 return false
|
flickerstreak@1
|
1202 end
|
flickerstreak@1
|
1203 end
|
flickerstreak@1
|
1204 if id == byte_Z then
|
flickerstreak@1
|
1205 id = byte_a
|
flickerstreak@1
|
1206 elseif id == byte_z then
|
flickerstreak@1
|
1207 id = byte_A
|
flickerstreak@1
|
1208 else
|
flickerstreak@1
|
1209 id = id + 1
|
flickerstreak@1
|
1210 end
|
flickerstreak@1
|
1211 if id == byte_s or id == byte_S then
|
flickerstreak@1
|
1212 id = id + 1
|
flickerstreak@1
|
1213 end
|
flickerstreak@1
|
1214 local id = string_char(id)
|
flickerstreak@1
|
1215 local drunk = distribution == "GLOBAL" or distribution == "WHISPER" or distribution == "ZONE" or distribution == "CUSTOM"
|
flickerstreak@1
|
1216 prefix = Encode(prefix, drunk)
|
flickerstreak@1
|
1217 message = Serialize(message, textToHash)
|
flickerstreak@1
|
1218 message = Encode(message, drunk)
|
flickerstreak@1
|
1219 local headerLen = string_len(prefix) + 6
|
flickerstreak@1
|
1220 local messageLen = string_len(message)
|
flickerstreak@1
|
1221 if distribution == "WHISPER" then
|
flickerstreak@1
|
1222 AceComm.recentWhispers[string.lower(person)] = GetTime()
|
flickerstreak@1
|
1223 end
|
flickerstreak@1
|
1224 local max = math_floor(messageLen / (250 - headerLen) + 1)
|
flickerstreak@1
|
1225 if max > 1 then
|
flickerstreak@1
|
1226 local segment = math_floor(messageLen / max + 0.5)
|
flickerstreak@1
|
1227 local last = 0
|
flickerstreak@1
|
1228 local good = true
|
flickerstreak@1
|
1229 for i = 1, max do
|
flickerstreak@1
|
1230 local bit
|
flickerstreak@1
|
1231 if i == max then
|
flickerstreak@1
|
1232 bit = string_sub(message, last + 1)
|
flickerstreak@1
|
1233 else
|
flickerstreak@1
|
1234 local next = segment * i
|
flickerstreak@1
|
1235 if string_byte(message, next) == byte_deg then
|
flickerstreak@1
|
1236 next = next + 1
|
flickerstreak@1
|
1237 end
|
flickerstreak@1
|
1238 bit = string_sub(message, last + 1, next)
|
flickerstreak@1
|
1239 last = next
|
flickerstreak@1
|
1240 end
|
flickerstreak@1
|
1241 if distribution == "WHISPER" then
|
flickerstreak@1
|
1242 bit = "/" .. prefix .. "\t" .. id .. encodedChar(i) .. encodedChar(max) .. "\t" .. bit .. "°"
|
flickerstreak@1
|
1243 ChatThrottleLib:SendChatMessage(priority, prefix, bit, "WHISPER", nil, person)
|
flickerstreak@1
|
1244 elseif distribution == "GLOBAL" or distribution == "ZONE" or distribution == "CUSTOM" then
|
flickerstreak@1
|
1245 bit = prefix .. "\t" .. id .. encodedChar(i) .. encodedChar(max) .. "\t" .. bit .. "°"
|
flickerstreak@1
|
1246 local channel
|
flickerstreak@1
|
1247 if distribution == "GLOBAL" then
|
flickerstreak@1
|
1248 channel = "AceComm"
|
flickerstreak@1
|
1249 elseif distribution == "ZONE" then
|
flickerstreak@1
|
1250 channel = GetCurrentZoneChannel()
|
flickerstreak@1
|
1251 elseif distribution == "CUSTOM" then
|
flickerstreak@1
|
1252 channel = person
|
flickerstreak@1
|
1253 end
|
flickerstreak@1
|
1254 local index = GetChannelName(channel)
|
flickerstreak@1
|
1255 if index and index > 0 then
|
flickerstreak@1
|
1256 ChatThrottleLib:SendChatMessage(priority, prefix, bit, "CHANNEL", nil, index)
|
flickerstreak@1
|
1257 else
|
flickerstreak@1
|
1258 good = false
|
flickerstreak@1
|
1259 end
|
flickerstreak@1
|
1260 else
|
flickerstreak@1
|
1261 bit = id .. soberEncodedChar(i) .. soberEncodedChar(max) .. "\t" .. bit
|
flickerstreak@1
|
1262 ChatThrottleLib:SendAddonMessage(priority, prefix, bit, distribution)
|
flickerstreak@1
|
1263 end
|
flickerstreak@1
|
1264 end
|
flickerstreak@1
|
1265 return good
|
flickerstreak@1
|
1266 else
|
flickerstreak@1
|
1267 if distribution == "WHISPER" then
|
flickerstreak@1
|
1268 message = "/" .. prefix .. "\t" .. id .. string_char(1) .. string_char(1) .. "\t" .. message .. "°"
|
flickerstreak@1
|
1269 ChatThrottleLib:SendChatMessage(priority, prefix, message, "WHISPER", nil, person)
|
flickerstreak@1
|
1270 return true
|
flickerstreak@1
|
1271 elseif distribution == "GLOBAL" or distribution == "ZONE" or distribution == "CUSTOM" then
|
flickerstreak@1
|
1272 message = prefix .. "\t" .. id .. string_char(1) .. string_char(1) .. "\t" .. message .. "°"
|
flickerstreak@1
|
1273 local channel
|
flickerstreak@1
|
1274 if distribution == "GLOBAL" then
|
flickerstreak@1
|
1275 channel = "AceComm"
|
flickerstreak@1
|
1276 elseif distribution == "ZONE" then
|
flickerstreak@1
|
1277 channel = GetCurrentZoneChannel()
|
flickerstreak@1
|
1278 elseif distribution == "CUSTOM" then
|
flickerstreak@1
|
1279 channel = person
|
flickerstreak@1
|
1280 end
|
flickerstreak@1
|
1281 local index = GetChannelName(channel)
|
flickerstreak@1
|
1282 if index and index > 0 then
|
flickerstreak@1
|
1283 ChatThrottleLib:SendChatMessage(priority, prefix, message, "CHANNEL", nil, index)
|
flickerstreak@1
|
1284 return true
|
flickerstreak@1
|
1285 end
|
flickerstreak@1
|
1286 else
|
flickerstreak@1
|
1287 message = id .. string_char(1) .. string_char(1) .. "\t" .. message
|
flickerstreak@1
|
1288 ChatThrottleLib:SendAddonMessage(priority, prefix, message, distribution)
|
flickerstreak@1
|
1289 return true
|
flickerstreak@1
|
1290 end
|
flickerstreak@1
|
1291 end
|
flickerstreak@1
|
1292 return false
|
flickerstreak@1
|
1293 end
|
flickerstreak@1
|
1294
|
flickerstreak@1
|
1295 local tmp = {}
|
flickerstreak@1
|
1296 function AceComm:SendPrioritizedCommMessage(priority, distribution, person, ...)
|
flickerstreak@1
|
1297 AceComm:argCheck(priority, 2, "string")
|
flickerstreak@1
|
1298 if priority ~= "NORMAL" and priority ~= "BULK" and priority ~= "ALERT" then
|
flickerstreak@1
|
1299 AceComm:error('Argument #2 to `SendPrioritizedCommMessage\' must be either "NORMAL", "BULK", or "ALERT"')
|
flickerstreak@1
|
1300 end
|
flickerstreak@1
|
1301 AceComm:argCheck(distribution, 3, "string")
|
flickerstreak@1
|
1302 local includePerson = true
|
flickerstreak@1
|
1303 if distribution == "WHISPER" or distribution == "CUSTOM" then
|
flickerstreak@1
|
1304 includePerson = false
|
flickerstreak@1
|
1305 AceComm:argCheck(person, 4, "string")
|
flickerstreak@1
|
1306 if string_len(person) == 0 then
|
flickerstreak@1
|
1307 AceComm:error("Argument #4 to `SendPrioritizedCommMessage' must be a non-zero-length string")
|
flickerstreak@1
|
1308 end
|
flickerstreak@1
|
1309 end
|
flickerstreak@1
|
1310 if self == AceComm then
|
flickerstreak@1
|
1311 AceComm:error("Cannot send a comm message from AceComm directly.")
|
flickerstreak@1
|
1312 end
|
flickerstreak@1
|
1313 if distribution and distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then
|
flickerstreak@1
|
1314 AceComm:error('Argument #4 to `SendPrioritizedCommMessage\' must be either nil, "GLOBAL", "ZONE", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", or "CUSTOM". %q is not appropriate', distribution)
|
flickerstreak@1
|
1315 end
|
flickerstreak@1
|
1316
|
flickerstreak@1
|
1317 local prefix = self.commPrefix
|
flickerstreak@1
|
1318 if type(prefix) ~= "string" then
|
flickerstreak@1
|
1319 AceComm:error("`SetCommPrefix' must be called before sending a message.")
|
flickerstreak@1
|
1320 end
|
flickerstreak@1
|
1321
|
flickerstreak@1
|
1322 local message
|
flickerstreak@1
|
1323
|
flickerstreak@1
|
1324 if includePerson and select('#', ...) == 0 and type(person) ~= "table" then
|
flickerstreak@1
|
1325 message = person
|
flickerstreak@1
|
1326 elseif not includePerson and select('#', ...) == 1 and type((...)) ~= "table" then
|
flickerstreak@1
|
1327 message = ...
|
flickerstreak@1
|
1328 else
|
flickerstreak@1
|
1329 message = tmp
|
flickerstreak@1
|
1330 local n = 1
|
flickerstreak@1
|
1331 if includePerson then
|
flickerstreak@1
|
1332 tmp[1] = person
|
flickerstreak@1
|
1333 n = 2
|
flickerstreak@1
|
1334 end
|
flickerstreak@1
|
1335 for i = 1, select('#', ...) do
|
flickerstreak@1
|
1336 tmp[n] = select(i, ...)
|
flickerstreak@1
|
1337 n = n + 1
|
flickerstreak@1
|
1338 end
|
flickerstreak@1
|
1339 end
|
flickerstreak@1
|
1340
|
flickerstreak@1
|
1341 local ret = SendMessage(AceComm.prefixTextToHash[prefix], priority, distribution, person, message, self.commMemoTextToHash)
|
flickerstreak@1
|
1342
|
flickerstreak@1
|
1343 if message == tmp then
|
flickerstreak@1
|
1344 local n = #tmp
|
flickerstreak@1
|
1345 for i = 1, n do
|
flickerstreak@1
|
1346 tmp[i] = nil
|
flickerstreak@1
|
1347 end
|
flickerstreak@1
|
1348 end
|
flickerstreak@1
|
1349
|
flickerstreak@1
|
1350 return ret
|
flickerstreak@1
|
1351 end
|
flickerstreak@1
|
1352
|
flickerstreak@1
|
1353 function AceComm:SendCommMessage(distribution, person, ...)
|
flickerstreak@1
|
1354 AceComm:argCheck(distribution, 2, "string")
|
flickerstreak@1
|
1355 local includePerson = true
|
flickerstreak@1
|
1356 if distribution == "WHISPER" or distribution == "CUSTOM" then
|
flickerstreak@1
|
1357 includePerson = false
|
flickerstreak@1
|
1358 AceComm:argCheck(person, 3, "string")
|
flickerstreak@1
|
1359 if string_len(person) == 0 then
|
flickerstreak@1
|
1360 AceComm:error("Argument #3 to `SendCommMessage' must be a non-zero-length string")
|
flickerstreak@1
|
1361 end
|
flickerstreak@1
|
1362 end
|
flickerstreak@1
|
1363 if self == AceComm then
|
flickerstreak@1
|
1364 AceComm:error("Cannot send a comm message from AceComm directly.")
|
flickerstreak@1
|
1365 end
|
flickerstreak@1
|
1366 if distribution and distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then
|
flickerstreak@1
|
1367 AceComm:error('Argument #2 to `SendCommMessage\' must be either nil, "GLOBAL", "ZONE", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", or "CUSTOM". %q is not appropriate', distribution)
|
flickerstreak@1
|
1368 end
|
flickerstreak@1
|
1369
|
flickerstreak@1
|
1370 local prefix = self.commPrefix
|
flickerstreak@1
|
1371 if type(prefix) ~= "string" then
|
flickerstreak@1
|
1372 AceComm:error("`SetCommPrefix' must be called before sending a message.")
|
flickerstreak@1
|
1373 end
|
flickerstreak@1
|
1374
|
flickerstreak@1
|
1375 if includePerson and select('#', ...) == 0 and type(person) ~= "table" then
|
flickerstreak@1
|
1376 message = person
|
flickerstreak@1
|
1377 elseif not includePerson and select('#', ...) == 1 and type((...)) ~= "table" then
|
flickerstreak@1
|
1378 message = ...
|
flickerstreak@1
|
1379 else
|
flickerstreak@1
|
1380 message = tmp
|
flickerstreak@1
|
1381 local n = 1
|
flickerstreak@1
|
1382 if includePerson then
|
flickerstreak@1
|
1383 tmp[1] = person
|
flickerstreak@1
|
1384 n = 2
|
flickerstreak@1
|
1385 end
|
flickerstreak@1
|
1386 for i = 1, select('#', ...) do
|
flickerstreak@1
|
1387 tmp[n] = select(i, ...)
|
flickerstreak@1
|
1388 n = n + 1
|
flickerstreak@1
|
1389 end
|
flickerstreak@1
|
1390 end
|
flickerstreak@1
|
1391
|
flickerstreak@1
|
1392 local priority = self.commPriority or "NORMAL"
|
flickerstreak@1
|
1393
|
flickerstreak@1
|
1394 local ret = SendMessage(AceComm.prefixTextToHash[prefix], priority, distribution, person, message, self.commMemoTextToHash)
|
flickerstreak@1
|
1395
|
flickerstreak@1
|
1396 if message == tmp then
|
flickerstreak@1
|
1397 local n = #tmp
|
flickerstreak@1
|
1398 for i = 1, n do
|
flickerstreak@1
|
1399 tmp[i] = nil
|
flickerstreak@1
|
1400 end
|
flickerstreak@1
|
1401 end
|
flickerstreak@1
|
1402
|
flickerstreak@1
|
1403 return ret
|
flickerstreak@1
|
1404 end
|
flickerstreak@1
|
1405
|
flickerstreak@1
|
1406 function AceComm:SetDefaultCommPriority(priority)
|
flickerstreak@1
|
1407 AceComm:argCheck(priority, 2, "string")
|
flickerstreak@1
|
1408 if priority ~= "NORMAL" and priority ~= "BULK" and priority ~= "ALERT" then
|
flickerstreak@1
|
1409 AceComm:error('Argument #2 must be either "NORMAL", "BULK", or "ALERT"')
|
flickerstreak@1
|
1410 end
|
flickerstreak@1
|
1411
|
flickerstreak@1
|
1412 if self.commPriority then
|
flickerstreak@1
|
1413 AceComm:error("Cannot call `SetDefaultCommPriority' more than once")
|
flickerstreak@1
|
1414 end
|
flickerstreak@1
|
1415
|
flickerstreak@1
|
1416 self.commPriority = priority
|
flickerstreak@1
|
1417 end
|
flickerstreak@1
|
1418
|
flickerstreak@1
|
1419 function AceComm:SetCommPrefix(prefix)
|
flickerstreak@1
|
1420 AceComm:argCheck(prefix, 2, "string")
|
flickerstreak@1
|
1421
|
flickerstreak@1
|
1422 if self.commPrefix then
|
flickerstreak@1
|
1423 AceComm:error("Cannot call `SetCommPrefix' more than once.")
|
flickerstreak@1
|
1424 end
|
flickerstreak@1
|
1425
|
flickerstreak@1
|
1426 if AceComm.prefixes[prefix] then
|
flickerstreak@1
|
1427 AceComm:error("Cannot set prefix to %q, it is already in use.", prefix)
|
flickerstreak@1
|
1428 end
|
flickerstreak@1
|
1429
|
flickerstreak@1
|
1430 local hash = TailoredBinaryCheckSum(prefix)
|
flickerstreak@1
|
1431 if AceComm.prefixHashToText[hash] then
|
flickerstreak@1
|
1432 AceComm:error("Cannot set prefix to %q, its hash is used by another prefix: %q", prefix, AceComm.prefixHashToText[hash])
|
flickerstreak@1
|
1433 end
|
flickerstreak@1
|
1434
|
flickerstreak@1
|
1435 AceComm.prefixes[prefix] = true
|
flickerstreak@1
|
1436 self.commPrefix = prefix
|
flickerstreak@1
|
1437 AceComm.prefixHashToText[hash] = prefix
|
flickerstreak@1
|
1438 AceComm.prefixTextToHash[prefix] = hash
|
flickerstreak@1
|
1439 end
|
flickerstreak@1
|
1440
|
flickerstreak@1
|
1441 function AceComm:RegisterMemoizations(values)
|
flickerstreak@1
|
1442 AceComm:argCheck(values, 2, "table")
|
flickerstreak@1
|
1443 for k,v in pairs(values) do
|
flickerstreak@1
|
1444 if type(k) ~= "number" then
|
flickerstreak@1
|
1445 AceComm:error("Bad argument #2 to `RegisterMemoizations'. All keys must be numbers")
|
flickerstreak@1
|
1446 elseif type(v) ~= "string" then
|
flickerstreak@1
|
1447 AceComm:error("Bad argument #2 to `RegisterMemoizations'. All values must be strings")
|
flickerstreak@1
|
1448 end
|
flickerstreak@1
|
1449 end
|
flickerstreak@1
|
1450 if self.commMemoHashToText or self.commMemoTextToHash then
|
flickerstreak@1
|
1451 AceComm:error("You can only call `RegisterMemoizations' once.")
|
flickerstreak@1
|
1452 elseif not self.commPrefix then
|
flickerstreak@1
|
1453 AceComm:error("You can only call `RegisterCommPrefix' before calling `RegisterMemoizations'.")
|
flickerstreak@1
|
1454 elseif AceComm.prefixMemoizations[self.commPrefix] then
|
flickerstreak@1
|
1455 AceComm:error("Another addon with prefix %q has already registered memoizations.", self.commPrefix)
|
flickerstreak@1
|
1456 end
|
flickerstreak@1
|
1457 local hashToText = {}
|
flickerstreak@1
|
1458 local textToHash = {}
|
flickerstreak@1
|
1459 for _,text in ipairs(values) do
|
flickerstreak@1
|
1460 local hash = TailoredNumericCheckSum(text)
|
flickerstreak@1
|
1461 if hashToText[hash] then
|
flickerstreak@1
|
1462 AceComm:error("%q and %q have the same checksum. You must remove one of them for memoization to work properly", hashToText[hash], text)
|
flickerstreak@1
|
1463 else
|
flickerstreak@1
|
1464 textToHash[text] = hash
|
flickerstreak@1
|
1465 hashToText[hash] = text
|
flickerstreak@1
|
1466 end
|
flickerstreak@1
|
1467 end
|
flickerstreak@1
|
1468 values = nil
|
flickerstreak@1
|
1469 self.commMemoHashToText = hashToText
|
flickerstreak@1
|
1470 self.commMemoTextToHash = textToHash
|
flickerstreak@1
|
1471 AceComm.prefixMemoizations[self.commPrefix] = hashToText
|
flickerstreak@1
|
1472 end
|
flickerstreak@1
|
1473
|
flickerstreak@1
|
1474 local lastCheck = GetTime()
|
flickerstreak@1
|
1475 local function CheckRefix()
|
flickerstreak@1
|
1476 if GetTime() - lastCheck >= 120 then
|
flickerstreak@1
|
1477 lastCheck = GetTime()
|
flickerstreak@1
|
1478 RefixAceCommChannelsAndEvents()
|
flickerstreak@1
|
1479 end
|
flickerstreak@1
|
1480 end
|
flickerstreak@1
|
1481
|
flickerstreak@1
|
1482 local stack = setmetatable({}, {__mode='k'})
|
flickerstreak@1
|
1483 local function HandleMessage(prefix, message, distribution, sender, customChannel)
|
flickerstreak@1
|
1484 local isGroup = GetCurrentGroupDistribution() == distribution
|
flickerstreak@1
|
1485 local isCustom = distribution == "CUSTOM"
|
flickerstreak@1
|
1486 if (not AceComm_registry[distribution] and (not isGroup or not AceComm_registry.GROUP)) or (isCustom and not AceComm_registry.CUSTOM[customChannel]) then
|
flickerstreak@1
|
1487 return CheckRefix()
|
flickerstreak@1
|
1488 end
|
flickerstreak@1
|
1489 local _, id, current, max
|
flickerstreak@1
|
1490 if not message then
|
flickerstreak@1
|
1491 if distribution == "WHISPER" then
|
flickerstreak@1
|
1492 _,_, prefix, id, current, max, message = string_find(prefix, "^/(...)\t(.)(.)(.)\t(.*)$")
|
flickerstreak@1
|
1493 else
|
flickerstreak@1
|
1494 _,_, prefix, id, current, max, message = string_find(prefix, "^(...)\t(.)(.)(.)\t(.*)$")
|
flickerstreak@1
|
1495 end
|
flickerstreak@1
|
1496 prefix = AceComm.prefixHashToText[prefix]
|
flickerstreak@1
|
1497 if not prefix then
|
flickerstreak@1
|
1498 return CheckRefix()
|
flickerstreak@1
|
1499 end
|
flickerstreak@1
|
1500 if isCustom then
|
flickerstreak@1
|
1501 if not AceComm_registry.CUSTOM[customChannel][prefix] then
|
flickerstreak@1
|
1502 return CheckRefix()
|
flickerstreak@1
|
1503 end
|
flickerstreak@1
|
1504 else
|
flickerstreak@1
|
1505 if (not AceComm_registry[distribution] or not AceComm_registry[distribution][prefix]) and (not isGroup or not AceComm_registry.GROUP or not AceComm_registry.GROUP[prefix]) then
|
flickerstreak@1
|
1506 return CheckRefix()
|
flickerstreak@1
|
1507 end
|
flickerstreak@1
|
1508 end
|
flickerstreak@1
|
1509 else
|
flickerstreak@1
|
1510 _,_, id, current, max, message = string_find(message, "^(.)(.)(.)\t(.*)$")
|
flickerstreak@1
|
1511 end
|
flickerstreak@1
|
1512 if not message then
|
flickerstreak@1
|
1513 return
|
flickerstreak@1
|
1514 end
|
flickerstreak@1
|
1515 local smallCustomChannel = customChannel and string_sub(customChannel, 8)
|
flickerstreak@1
|
1516 current = string_byte(current)
|
flickerstreak@1
|
1517 max = string_byte(max)
|
flickerstreak@1
|
1518 if max > 1 then
|
flickerstreak@1
|
1519 local queue = AceComm.recvQueue
|
flickerstreak@1
|
1520 local x
|
flickerstreak@1
|
1521 if distribution == "CUSTOM" then
|
flickerstreak@1
|
1522 x = prefix .. ":" .. sender .. distribution .. customChannel .. id
|
flickerstreak@1
|
1523 else
|
flickerstreak@1
|
1524 x = prefix .. ":" .. sender .. distribution .. id
|
flickerstreak@1
|
1525 end
|
flickerstreak@1
|
1526 if not queue[x] then
|
flickerstreak@1
|
1527 if current ~= 1 then
|
flickerstreak@1
|
1528 return
|
flickerstreak@1
|
1529 end
|
flickerstreak@1
|
1530 local t = next(stack) or {}
|
flickerstreak@1
|
1531 stack[t] = nil
|
flickerstreak@1
|
1532 queue[x] = t
|
flickerstreak@1
|
1533 end
|
flickerstreak@1
|
1534 local chunk = queue[x]
|
flickerstreak@1
|
1535 chunk.time = GetTime()
|
flickerstreak@1
|
1536 chunk[current] = message
|
flickerstreak@1
|
1537 if current == max then
|
flickerstreak@1
|
1538 message = table_concat(chunk)
|
flickerstreak@1
|
1539 local t = queue[x]
|
flickerstreak@1
|
1540 queue[x] = nil
|
flickerstreak@1
|
1541 for k in pairs(t) do
|
flickerstreak@1
|
1542 t[k] = nil
|
flickerstreak@1
|
1543 end
|
flickerstreak@1
|
1544 stack[t] = true
|
flickerstreak@1
|
1545 else
|
flickerstreak@1
|
1546 return
|
flickerstreak@1
|
1547 end
|
flickerstreak@1
|
1548 end
|
flickerstreak@1
|
1549 message = Deserialize(message, AceComm.prefixMemoizations[prefix])
|
flickerstreak@1
|
1550 local isTable = type(message) == "table"
|
flickerstreak@1
|
1551 local n
|
flickerstreak@1
|
1552 if isTable then
|
flickerstreak@1
|
1553 n = #message * 4
|
flickerstreak@1
|
1554 if n < 40 then
|
flickerstreak@1
|
1555 n = 40
|
flickerstreak@1
|
1556 end
|
flickerstreak@1
|
1557 while message[n] == nil do
|
flickerstreak@1
|
1558 n = n - 1
|
flickerstreak@1
|
1559 end
|
flickerstreak@1
|
1560 end
|
flickerstreak@1
|
1561 if AceComm_registry[distribution] then
|
flickerstreak@1
|
1562 if isTable then
|
flickerstreak@1
|
1563 if isCustom then
|
flickerstreak@1
|
1564 if AceComm_registry.CUSTOM[customChannel][prefix] then
|
flickerstreak@1
|
1565 for k,v in pairs(AceComm_registry.CUSTOM[customChannel][prefix]) do
|
flickerstreak@1
|
1566 local type_v = type(v)
|
flickerstreak@1
|
1567 if type_v == "string" then
|
flickerstreak@1
|
1568 local f = k[v]
|
flickerstreak@1
|
1569 if type(f) == "table" then
|
flickerstreak@1
|
1570 local i = 1
|
flickerstreak@1
|
1571 local g = f[message[i]]
|
flickerstreak@1
|
1572 while g do
|
flickerstreak@1
|
1573 if type(g) ~= "table" then -- function
|
flickerstreak@1
|
1574 g(k, prefix, sender, distribution, smallCustomChannel, unpack(message, i+1, n))
|
flickerstreak@1
|
1575 break
|
flickerstreak@1
|
1576 else
|
flickerstreak@1
|
1577 i = i + 1
|
flickerstreak@1
|
1578 g = g[message[i]]
|
flickerstreak@1
|
1579 end
|
flickerstreak@1
|
1580 end
|
flickerstreak@1
|
1581 else -- function
|
flickerstreak@1
|
1582 f(k, prefix, sender, distribution, smallCustomChannel, unpack(message, 1, n))
|
flickerstreak@1
|
1583 end
|
flickerstreak@1
|
1584 elseif type_v == "table" then
|
flickerstreak@1
|
1585 local i = 1
|
flickerstreak@1
|
1586 local g = v[message[i]]
|
flickerstreak@1
|
1587 while g do
|
flickerstreak@1
|
1588 if type(g) ~= "table" then -- function
|
flickerstreak@1
|
1589 g(prefix, sender, distribution, smallCustomChannel, unpack(message, i+1, n))
|
flickerstreak@1
|
1590 break
|
flickerstreak@1
|
1591 else
|
flickerstreak@1
|
1592 i = i + 1
|
flickerstreak@1
|
1593 g = g[message[i]]
|
flickerstreak@1
|
1594 end
|
flickerstreak@1
|
1595 end
|
flickerstreak@1
|
1596 else -- function
|
flickerstreak@1
|
1597 v(prefix, sender, distribution, smallCustomChannel, unpack(message, 1, n))
|
flickerstreak@1
|
1598 end
|
flickerstreak@1
|
1599 end
|
flickerstreak@1
|
1600 end
|
flickerstreak@1
|
1601 else
|
flickerstreak@1
|
1602 if AceComm_registry[distribution][prefix] then
|
flickerstreak@1
|
1603 for k,v in pairs(AceComm_registry[distribution][prefix]) do
|
flickerstreak@1
|
1604 local type_v = type(v)
|
flickerstreak@1
|
1605 if type_v == "string" then
|
flickerstreak@1
|
1606 local f = k[v]
|
flickerstreak@1
|
1607 if type(f) == "table" then
|
flickerstreak@1
|
1608 local i = 1
|
flickerstreak@1
|
1609 local g = f[message[i]]
|
flickerstreak@1
|
1610 while g do
|
flickerstreak@1
|
1611 if type(g) ~= "table" then -- function
|
flickerstreak@1
|
1612 g(k, prefix, sender, distribution, unpack(message, i+1, n))
|
flickerstreak@1
|
1613 break
|
flickerstreak@1
|
1614 else
|
flickerstreak@1
|
1615 i = i + 1
|
flickerstreak@1
|
1616 g = g[message[i]]
|
flickerstreak@1
|
1617 end
|
flickerstreak@1
|
1618 end
|
flickerstreak@1
|
1619 else -- function
|
flickerstreak@1
|
1620 f(k, prefix, sender, distribution, unpack(message, 1, n))
|
flickerstreak@1
|
1621 end
|
flickerstreak@1
|
1622 elseif type_v == "table" then
|
flickerstreak@1
|
1623 local i = 1
|
flickerstreak@1
|
1624 local g = v[message[i]]
|
flickerstreak@1
|
1625 while g do
|
flickerstreak@1
|
1626 if type(g) ~= "table" then -- function
|
flickerstreak@1
|
1627 g(prefix, sender, distribution, unpack(message, i+1, n))
|
flickerstreak@1
|
1628 break
|
flickerstreak@1
|
1629 else
|
flickerstreak@1
|
1630 i = i + 1
|
flickerstreak@1
|
1631 g = g[message[i]]
|
flickerstreak@1
|
1632 end
|
flickerstreak@1
|
1633 end
|
flickerstreak@1
|
1634 else -- function
|
flickerstreak@1
|
1635 v(prefix, sender, distribution, unpack(message, 1, n))
|
flickerstreak@1
|
1636 end
|
flickerstreak@1
|
1637 end
|
flickerstreak@1
|
1638 end
|
flickerstreak@1
|
1639 end
|
flickerstreak@1
|
1640 else
|
flickerstreak@1
|
1641 if isCustom then
|
flickerstreak@1
|
1642 if AceComm_registry.CUSTOM[customChannel][prefix] then
|
flickerstreak@1
|
1643 for k,v in pairs(AceComm_registry.CUSTOM[customChannel][prefix]) do
|
flickerstreak@1
|
1644 local type_v = type(v)
|
flickerstreak@1
|
1645 if type_v == "string" then
|
flickerstreak@1
|
1646 local f = k[v]
|
flickerstreak@1
|
1647 if type(f) == "table" then
|
flickerstreak@1
|
1648 local g = f[message]
|
flickerstreak@1
|
1649 if g and type(g) == "function" then
|
flickerstreak@1
|
1650 g(k, prefix, sender, distribution, smallCustomChannel)
|
flickerstreak@1
|
1651 end
|
flickerstreak@1
|
1652 else -- function
|
flickerstreak@1
|
1653 f(k, prefix, sender, distribution, smallCustomChannel, message)
|
flickerstreak@1
|
1654 end
|
flickerstreak@1
|
1655 elseif type_v == "table" then
|
flickerstreak@1
|
1656 local g = v[message]
|
flickerstreak@1
|
1657 if g and type(g) == "function" then
|
flickerstreak@1
|
1658 g(k, prefix, sender, distribution, smallCustomChannel)
|
flickerstreak@1
|
1659 end
|
flickerstreak@1
|
1660 else -- function
|
flickerstreak@1
|
1661 v(prefix, sender, distribution, smallCustomChannel, message)
|
flickerstreak@1
|
1662 end
|
flickerstreak@1
|
1663 end
|
flickerstreak@1
|
1664 end
|
flickerstreak@1
|
1665 else
|
flickerstreak@1
|
1666 if AceComm_registry[distribution][prefix] then
|
flickerstreak@1
|
1667 for k,v in pairs(AceComm_registry[distribution][prefix]) do
|
flickerstreak@1
|
1668 local type_v = type(v)
|
flickerstreak@1
|
1669 if type_v == "string" then
|
flickerstreak@1
|
1670 local f = k[v]
|
flickerstreak@1
|
1671 if type(f) == "table" then
|
flickerstreak@1
|
1672 local g = f[message]
|
flickerstreak@1
|
1673 if g and type(g) == "function" then
|
flickerstreak@1
|
1674 g(k, prefix, sender, distribution)
|
flickerstreak@1
|
1675 end
|
flickerstreak@1
|
1676 else -- function
|
flickerstreak@1
|
1677 f(k, prefix, sender, distribution, message)
|
flickerstreak@1
|
1678 end
|
flickerstreak@1
|
1679 elseif type_v == "table" then
|
flickerstreak@1
|
1680 local g = v[message]
|
flickerstreak@1
|
1681 if g and type(g) == "function" then
|
flickerstreak@1
|
1682 g(k, prefix, sender, distribution)
|
flickerstreak@1
|
1683 end
|
flickerstreak@1
|
1684 else -- function
|
flickerstreak@1
|
1685 v(prefix, sender, distribution, message)
|
flickerstreak@1
|
1686 end
|
flickerstreak@1
|
1687 end
|
flickerstreak@1
|
1688 end
|
flickerstreak@1
|
1689 end
|
flickerstreak@1
|
1690 end
|
flickerstreak@1
|
1691 end
|
flickerstreak@1
|
1692 if isGroup and AceComm_registry.GROUP and AceComm_registry.GROUP[prefix] then
|
flickerstreak@1
|
1693 if isTable then
|
flickerstreak@1
|
1694 for k,v in pairs(AceComm_registry.GROUP[prefix]) do
|
flickerstreak@1
|
1695 local type_v = type(v)
|
flickerstreak@1
|
1696 if type_v == "string" then
|
flickerstreak@1
|
1697 local f = k[v]
|
flickerstreak@1
|
1698 if type(f) == "table" then
|
flickerstreak@1
|
1699 local i = 1
|
flickerstreak@1
|
1700 local g = f[message[i]]
|
flickerstreak@1
|
1701 while g do
|
flickerstreak@1
|
1702 if type(g) ~= "table" then -- function
|
flickerstreak@1
|
1703 g(k, prefix, sender, "GROUP", unpack(message, i+1, n))
|
flickerstreak@1
|
1704 break
|
flickerstreak@1
|
1705 else
|
flickerstreak@1
|
1706 i = i + 1
|
flickerstreak@1
|
1707 g = g[message[i]]
|
flickerstreak@1
|
1708 end
|
flickerstreak@1
|
1709 end
|
flickerstreak@1
|
1710 else -- function
|
flickerstreak@1
|
1711 f(k, prefix, sender, "GROUP", unpack(message, 1, n))
|
flickerstreak@1
|
1712 end
|
flickerstreak@1
|
1713 elseif type_v == "table" then
|
flickerstreak@1
|
1714 local i = 1
|
flickerstreak@1
|
1715 local g = v[message[i]]
|
flickerstreak@1
|
1716 while g do
|
flickerstreak@1
|
1717 if type(g) ~= "table" then -- function
|
flickerstreak@1
|
1718 g(prefix, sender, "GROUP", unpack(message, i+1, n))
|
flickerstreak@1
|
1719 break
|
flickerstreak@1
|
1720 else
|
flickerstreak@1
|
1721 i = i + 1
|
flickerstreak@1
|
1722 g = g[message[i]]
|
flickerstreak@1
|
1723 end
|
flickerstreak@1
|
1724 end
|
flickerstreak@1
|
1725 else -- function
|
flickerstreak@1
|
1726 v(prefix, sender, "GROUP", unpack(message, 1, n))
|
flickerstreak@1
|
1727 end
|
flickerstreak@1
|
1728 end
|
flickerstreak@1
|
1729 else
|
flickerstreak@1
|
1730 for k,v in pairs(AceComm_registry.GROUP[prefix]) do
|
flickerstreak@1
|
1731 local type_v = type(v)
|
flickerstreak@1
|
1732 if type_v == "string" then
|
flickerstreak@1
|
1733 local f = k[v]
|
flickerstreak@1
|
1734 if type(f) == "table" then
|
flickerstreak@1
|
1735 local g = f[message]
|
flickerstreak@1
|
1736 if g and type(g) == "function" then
|
flickerstreak@1
|
1737 g(k, prefix, sender, "GROUP")
|
flickerstreak@1
|
1738 end
|
flickerstreak@1
|
1739 else -- function
|
flickerstreak@1
|
1740 f(k, prefix, sender, "GROUP", message)
|
flickerstreak@1
|
1741 end
|
flickerstreak@1
|
1742 elseif type_v == "table" then
|
flickerstreak@1
|
1743 local g = v[message]
|
flickerstreak@1
|
1744 if g and type(g) == "function" then
|
flickerstreak@1
|
1745 g(k, prefix, sender, "GROUP")
|
flickerstreak@1
|
1746 end
|
flickerstreak@1
|
1747 else -- function
|
flickerstreak@1
|
1748 v(prefix, sender, "GROUP", message)
|
flickerstreak@1
|
1749 end
|
flickerstreak@1
|
1750 end
|
flickerstreak@1
|
1751 end
|
flickerstreak@1
|
1752 end
|
flickerstreak@1
|
1753 end
|
flickerstreak@1
|
1754
|
flickerstreak@1
|
1755 function AceComm:CHAT_MSG_ADDON(prefix, message, distribution, sender)
|
flickerstreak@1
|
1756 if sender == player then
|
flickerstreak@1
|
1757 return
|
flickerstreak@1
|
1758 end
|
flickerstreak@1
|
1759 prefix = self.prefixHashToText[prefix]
|
flickerstreak@1
|
1760 if not prefix then
|
flickerstreak@1
|
1761 return CheckRefix()
|
flickerstreak@1
|
1762 end
|
flickerstreak@1
|
1763 local isGroup = GetCurrentGroupDistribution() == distribution
|
flickerstreak@1
|
1764 if not AceComm_registry[distribution] and (not isGroup or not AceComm_registry.GROUP) then
|
flickerstreak@1
|
1765 return CheckRefix()
|
flickerstreak@1
|
1766 end
|
flickerstreak@1
|
1767 prefix = Decode(prefix)
|
flickerstreak@1
|
1768 if (not AceComm_registry[distribution] or not AceComm_registry[distribution][prefix]) and (not isGroup or not AceComm_registry.GROUP or not AceComm_registry.GROUP[prefix]) then
|
flickerstreak@1
|
1769 return CheckRefix()
|
flickerstreak@1
|
1770 end
|
flickerstreak@1
|
1771 message = Decode(message)
|
flickerstreak@1
|
1772 return HandleMessage(prefix, message, distribution, sender)
|
flickerstreak@1
|
1773 end
|
flickerstreak@1
|
1774
|
flickerstreak@1
|
1775 function AceComm:CHAT_MSG_WHISPER(text, sender)
|
flickerstreak@1
|
1776 if not string_find(text, "^/") then
|
flickerstreak@1
|
1777 return
|
flickerstreak@1
|
1778 end
|
flickerstreak@1
|
1779 text = Decode(text, true)
|
flickerstreak@1
|
1780 return HandleMessage(text, nil, "WHISPER", sender)
|
flickerstreak@1
|
1781 end
|
flickerstreak@1
|
1782
|
flickerstreak@1
|
1783 function AceComm:CHAT_MSG_CHANNEL(text, sender, _, _, _, _, _, _, channel)
|
flickerstreak@1
|
1784 if sender == player or not string_find(channel, "^AceComm") then
|
flickerstreak@1
|
1785 return
|
flickerstreak@1
|
1786 end
|
flickerstreak@1
|
1787 text = Decode(text, true)
|
flickerstreak@1
|
1788 local distribution
|
flickerstreak@1
|
1789 local customChannel
|
flickerstreak@1
|
1790 if channel == "AceComm" then
|
flickerstreak@1
|
1791 distribution = "GLOBAL"
|
flickerstreak@1
|
1792 elseif channel == GetCurrentZoneChannel() then
|
flickerstreak@1
|
1793 distribution = "ZONE"
|
flickerstreak@1
|
1794 else
|
flickerstreak@1
|
1795 distribution = "CUSTOM"
|
flickerstreak@1
|
1796 customChannel = channel
|
flickerstreak@1
|
1797 end
|
flickerstreak@1
|
1798 return HandleMessage(text, nil, distribution, sender, customChannel)
|
flickerstreak@1
|
1799 end
|
flickerstreak@1
|
1800
|
flickerstreak@1
|
1801 function AceComm:IsUserInChannel(userName, distribution, customChannel)
|
flickerstreak@1
|
1802 AceComm:argCheck(userName, 2, "string", "nil")
|
flickerstreak@1
|
1803 if not userName then
|
flickerstreak@1
|
1804 userName = player
|
flickerstreak@1
|
1805 end
|
flickerstreak@1
|
1806 AceComm:argCheck(distribution, 3, "string")
|
flickerstreak@1
|
1807 local channel
|
flickerstreak@1
|
1808 if distribution == "GLOBAL" then
|
flickerstreak@1
|
1809 channel = "AceComm"
|
flickerstreak@1
|
1810 elseif distribution == "ZONE" then
|
flickerstreak@1
|
1811 channel = GetCurrentZoneChannel()
|
flickerstreak@1
|
1812 elseif distribution == "CUSTOM" then
|
flickerstreak@1
|
1813 AceComm:argCheck(customChannel, 4, "string")
|
flickerstreak@1
|
1814 channel = "AceComm" .. customChannel
|
flickerstreak@1
|
1815 else
|
flickerstreak@1
|
1816 AceComm:error('Argument #3 to `IsUserInChannel\' must be "GLOBAL", "CUSTOM", or "ZONE"')
|
flickerstreak@1
|
1817 end
|
flickerstreak@1
|
1818
|
flickerstreak@1
|
1819 return AceComm.userRegistry[channel] and AceComm.userRegistry[channel][userName] or false
|
flickerstreak@1
|
1820 end
|
flickerstreak@1
|
1821
|
flickerstreak@1
|
1822 function AceComm:CHAT_MSG_CHANNEL_LIST(text, _, _, _, _, _, _, _, channel)
|
flickerstreak@1
|
1823 if not string_find(channel, "^AceComm") then
|
flickerstreak@1
|
1824 return
|
flickerstreak@1
|
1825 end
|
flickerstreak@1
|
1826
|
flickerstreak@1
|
1827 if not AceComm.userRegistry[channel] then
|
flickerstreak@1
|
1828 AceComm.userRegistry[channel] = {}
|
flickerstreak@1
|
1829 end
|
flickerstreak@1
|
1830 local t = AceComm.userRegistry[channel]
|
flickerstreak@1
|
1831 for k in string_gmatch(text, "[^, @%*#]+") do
|
flickerstreak@1
|
1832 t[k] = true
|
flickerstreak@1
|
1833 end
|
flickerstreak@1
|
1834 end
|
flickerstreak@1
|
1835
|
flickerstreak@1
|
1836 function AceComm:CHAT_MSG_CHANNEL_JOIN(_, user, _, _, _, _, _, _, channel)
|
flickerstreak@1
|
1837 if not string_find(channel, "^AceComm") then
|
flickerstreak@1
|
1838 return
|
flickerstreak@1
|
1839 end
|
flickerstreak@1
|
1840
|
flickerstreak@1
|
1841 if not AceComm.userRegistry[channel] then
|
flickerstreak@1
|
1842 AceComm.userRegistry[channel] = {}
|
flickerstreak@1
|
1843 end
|
flickerstreak@1
|
1844 local t = AceComm.userRegistry[channel]
|
flickerstreak@1
|
1845 t[user] = true
|
flickerstreak@1
|
1846 end
|
flickerstreak@1
|
1847
|
flickerstreak@1
|
1848 function AceComm:CHAT_MSG_CHANNEL_LEAVE(_, user, _, _, _, _, _, _, channel)
|
flickerstreak@1
|
1849 if not string_find(channel, "^AceComm") then
|
flickerstreak@1
|
1850 return
|
flickerstreak@1
|
1851 end
|
flickerstreak@1
|
1852
|
flickerstreak@1
|
1853 if not AceComm.userRegistry[channel] then
|
flickerstreak@1
|
1854 AceComm.userRegistry[channel] = {}
|
flickerstreak@1
|
1855 end
|
flickerstreak@1
|
1856 local t = AceComm.userRegistry[channel]
|
flickerstreak@1
|
1857 if t[user] then
|
flickerstreak@1
|
1858 t[user] = nil
|
flickerstreak@1
|
1859 end
|
flickerstreak@1
|
1860 end
|
flickerstreak@1
|
1861
|
flickerstreak@1
|
1862 function AceComm:AceEvent_FullyInitialized()
|
flickerstreak@1
|
1863 RefixAceCommChannelsAndEvents()
|
flickerstreak@1
|
1864 end
|
flickerstreak@1
|
1865
|
flickerstreak@1
|
1866 function AceComm:PLAYER_LOGOUT()
|
flickerstreak@1
|
1867 LeaveAceCommChannels(true)
|
flickerstreak@1
|
1868 end
|
flickerstreak@1
|
1869
|
flickerstreak@1
|
1870 function AceComm:ZONE_CHANGED_NEW_AREA()
|
flickerstreak@1
|
1871 local lastZone = zoneCache
|
flickerstreak@1
|
1872 zoneCache = nil
|
flickerstreak@1
|
1873 local newZone = GetCurrentZoneChannel()
|
flickerstreak@1
|
1874 if self.registry.ZONE and next(self.registry.ZONE) then
|
flickerstreak@1
|
1875 if lastZone then
|
flickerstreak@1
|
1876 SwitchChannel(lastZone, newZone)
|
flickerstreak@1
|
1877 else
|
flickerstreak@1
|
1878 JoinChannel(newZone)
|
flickerstreak@1
|
1879 end
|
flickerstreak@1
|
1880 end
|
flickerstreak@1
|
1881 end
|
flickerstreak@1
|
1882
|
flickerstreak@1
|
1883 function AceComm:embed(target)
|
flickerstreak@1
|
1884 self.super.embed(self, target)
|
flickerstreak@1
|
1885 if not AceEvent then
|
flickerstreak@1
|
1886 AceComm:error(MAJOR_VERSION .. " requires AceEvent-2.0")
|
flickerstreak@1
|
1887 end
|
flickerstreak@1
|
1888 end
|
flickerstreak@1
|
1889
|
flickerstreak@1
|
1890 local recentNotSeen = {}
|
flickerstreak@1
|
1891 local notSeenString = '^' .. string_gsub(string_gsub(ERR_CHAT_PLAYER_NOT_FOUND_S, "%%s", "(.-)"), "%%1%$s", "(.-)") .. '$'
|
flickerstreak@1
|
1892 local ambiguousString = '^' .. string_gsub(string_gsub(ERR_CHAT_PLAYER_AMBIGUOUS_S, "%%s", "(.-)"), "%%1%$s", "(.-)") .. '$'
|
flickerstreak@1
|
1893 function AceComm.hooks:ChatFrame_MessageEventHandler(orig, event)
|
flickerstreak@1
|
1894 if event == "CHAT_MSG_WHISPER" or event == "CHAT_MSG_WHISPER_INFORM" then
|
flickerstreak@1
|
1895 if string_find(arg1, "^/") then
|
flickerstreak@1
|
1896 return
|
flickerstreak@1
|
1897 end
|
flickerstreak@1
|
1898 elseif event == "CHAT_MSG_AFK" or event == "CHAT_MSG_DND" then
|
flickerstreak@1
|
1899 local t = self.recentWhispers[string.lower(arg2)]
|
flickerstreak@1
|
1900 if t and GetTime() - t <= 15 then
|
flickerstreak@1
|
1901 return
|
flickerstreak@1
|
1902 end
|
flickerstreak@1
|
1903 elseif event == "CHAT_MSG_CHANNEL" or event == "CHAT_MSG_CHANNEL_LIST" then
|
flickerstreak@1
|
1904 if string_find(arg9, "^AceComm") then
|
flickerstreak@1
|
1905 return
|
flickerstreak@1
|
1906 end
|
flickerstreak@1
|
1907 elseif event == "CHAT_MSG_SYSTEM" then
|
flickerstreak@1
|
1908 local _,_,player = string_find(arg1, notSeenString)
|
flickerstreak@1
|
1909 if not player then
|
flickerstreak@1
|
1910 _,_,player = string_find(arg1, ambiguousString)
|
flickerstreak@1
|
1911 end
|
flickerstreak@1
|
1912 if player then
|
flickerstreak@1
|
1913 local t = GetTime()
|
flickerstreak@1
|
1914 if recentNotSeen[player] and recentNotSeen[player] > t then
|
flickerstreak@1
|
1915 recentNotSeen[player] = t + 10
|
flickerstreak@1
|
1916 return
|
flickerstreak@1
|
1917 else
|
flickerstreak@1
|
1918 recentNotSeen[player] = t + 10
|
flickerstreak@1
|
1919 end
|
flickerstreak@1
|
1920 end
|
flickerstreak@1
|
1921 end
|
flickerstreak@1
|
1922 return orig(event)
|
flickerstreak@1
|
1923 end
|
flickerstreak@1
|
1924
|
flickerstreak@1
|
1925 local id, loggingOut
|
flickerstreak@1
|
1926 function AceComm.hooks:Logout(orig)
|
flickerstreak@1
|
1927 if IsResting() then
|
flickerstreak@1
|
1928 LeaveAceCommChannels(true)
|
flickerstreak@1
|
1929 else
|
flickerstreak@1
|
1930 id = self:ScheduleEvent(LeaveAceCommChannels, 15, true)
|
flickerstreak@1
|
1931 end
|
flickerstreak@1
|
1932 loggingOut = true
|
flickerstreak@1
|
1933 return orig()
|
flickerstreak@1
|
1934 end
|
flickerstreak@1
|
1935
|
flickerstreak@1
|
1936 function AceComm.hooks:CancelLogout(orig)
|
flickerstreak@1
|
1937 shutdown = false
|
flickerstreak@1
|
1938 if id then
|
flickerstreak@1
|
1939 self:CancelScheduledEvent(id)
|
flickerstreak@1
|
1940 id = nil
|
flickerstreak@1
|
1941 end
|
flickerstreak@1
|
1942 RefixAceCommChannelsAndEvents()
|
flickerstreak@1
|
1943 loggingOut = false
|
flickerstreak@1
|
1944 return orig()
|
flickerstreak@1
|
1945 end
|
flickerstreak@1
|
1946
|
flickerstreak@1
|
1947 function AceComm.hooks:Quit(orig)
|
flickerstreak@1
|
1948 if IsResting() then
|
flickerstreak@1
|
1949 LeaveAceCommChannels(true)
|
flickerstreak@1
|
1950 else
|
flickerstreak@1
|
1951 id = self:ScheduleEvent(LeaveAceCommChannels, 15, true)
|
flickerstreak@1
|
1952 end
|
flickerstreak@1
|
1953 loggingOut = true
|
flickerstreak@1
|
1954 return orig()
|
flickerstreak@1
|
1955 end
|
flickerstreak@1
|
1956
|
flickerstreak@1
|
1957 function AceComm.hooks:FCFDropDown_LoadChannels(orig, ...)
|
flickerstreak@1
|
1958 local arg = { ... }
|
flickerstreak@1
|
1959 for i = 1, #arg, 2 do
|
flickerstreak@1
|
1960 if not arg[i] then
|
flickerstreak@1
|
1961 break
|
flickerstreak@1
|
1962 end
|
flickerstreak@1
|
1963 if type(arg[i + 1]) == "string" and string_find(arg[i + 1], "^AceComm") then
|
flickerstreak@1
|
1964 table.remove(arg, i + 1)
|
flickerstreak@1
|
1965 table.remove(arg, i)
|
flickerstreak@1
|
1966 i = i - 2
|
flickerstreak@1
|
1967 end
|
flickerstreak@1
|
1968 end
|
flickerstreak@1
|
1969 return orig(unpack(arg))
|
flickerstreak@1
|
1970 end
|
flickerstreak@1
|
1971
|
flickerstreak@1
|
1972 function AceComm:CHAT_MSG_SYSTEM(text)
|
flickerstreak@1
|
1973 if text ~= ERR_TOO_MANY_CHAT_CHANNELS then
|
flickerstreak@1
|
1974 return
|
flickerstreak@1
|
1975 end
|
flickerstreak@1
|
1976
|
flickerstreak@1
|
1977 local chan = lastChannelJoined
|
flickerstreak@1
|
1978 if not chan then
|
flickerstreak@1
|
1979 return
|
flickerstreak@1
|
1980 end
|
flickerstreak@1
|
1981 if not string_find(lastChannelJoined, "^AceComm") then
|
flickerstreak@1
|
1982 return
|
flickerstreak@1
|
1983 end
|
flickerstreak@1
|
1984
|
flickerstreak@1
|
1985 local text
|
flickerstreak@1
|
1986 if chan == "AceComm" then
|
flickerstreak@1
|
1987 local addon = self.registry.GLOBAL and next(AceComm_registry.GLOBAL)
|
flickerstreak@1
|
1988 if not addon then
|
flickerstreak@1
|
1989 return
|
flickerstreak@1
|
1990 end
|
flickerstreak@1
|
1991 addon = tostring(addon)
|
flickerstreak@1
|
1992 text = string_format("%s has tried to join the AceComm global channel, but there are not enough channels available. %s may not work because of this", addon, addon)
|
flickerstreak@1
|
1993 elseif chan == GetCurrentZoneChannel() then
|
flickerstreak@1
|
1994 local addon = AceComm_registry.ZONE and next(AceComm_registry.ZONE)
|
flickerstreak@1
|
1995 if not addon then
|
flickerstreak@1
|
1996 return
|
flickerstreak@1
|
1997 end
|
flickerstreak@1
|
1998 addon = tostring(addon)
|
flickerstreak@1
|
1999 text = string_format("%s has tried to join the AceComm zone channel, but there are not enough channels available. %s may not work because of this", addon, addon)
|
flickerstreak@1
|
2000 else
|
flickerstreak@1
|
2001 local addon = AceComm_registry.CUSTOM and AceComm_registry.CUSTOM[chan] and next(AceComm_registry.CUSTOM[chan])
|
flickerstreak@1
|
2002 if not addon then
|
flickerstreak@1
|
2003 return
|
flickerstreak@1
|
2004 end
|
flickerstreak@1
|
2005 addon = tostring(addon)
|
flickerstreak@1
|
2006 text = string_format("%s has tried to join the AceComm custom channel %s, but there are not enough channels available. %s may not work because of this", addon, chan, addon)
|
flickerstreak@1
|
2007 end
|
flickerstreak@1
|
2008
|
flickerstreak@1
|
2009 StaticPopupDialogs["ACECOMM_TOO_MANY_CHANNELS"] = {
|
flickerstreak@1
|
2010 text = text,
|
flickerstreak@1
|
2011 button1 = CLOSE,
|
flickerstreak@1
|
2012 timeout = 0,
|
flickerstreak@1
|
2013 whileDead = 1,
|
flickerstreak@1
|
2014 hideOnEscape = 1,
|
flickerstreak@1
|
2015 }
|
flickerstreak@1
|
2016 StaticPopup_Show("ACECOMM_TOO_MANY_CHANNELS")
|
flickerstreak@1
|
2017 end
|
flickerstreak@1
|
2018
|
flickerstreak@1
|
2019 local function activate(self, oldLib, oldDeactivate)
|
flickerstreak@1
|
2020 AceComm = self
|
flickerstreak@1
|
2021
|
flickerstreak@1
|
2022 if oldLib then
|
flickerstreak@1
|
2023 self.frame = oldLib.frame
|
flickerstreak@1
|
2024 self.frame:UnregisterAllEvents()
|
flickerstreak@1
|
2025 self.recvQueue = oldLib.recvQueue
|
flickerstreak@1
|
2026 self.registry = oldLib.registry
|
flickerstreak@1
|
2027 self.channels = oldLib.channels
|
flickerstreak@1
|
2028 self.prefixes = oldLib.prefixes
|
flickerstreak@1
|
2029 self.classes = oldLib.classes
|
flickerstreak@1
|
2030 self.prefixMemoizations = oldLib.prefixMemoizations
|
flickerstreak@1
|
2031 self.prefixHashToText = oldLib.prefixHashToText
|
flickerstreak@1
|
2032 self.prefixTextToHash = oldLib.prefixTextToHash
|
flickerstreak@1
|
2033 self.recentWhispers = oldLib.recentWhispers
|
flickerstreak@1
|
2034 self.userRegistry = oldLib.userRegistry
|
flickerstreak@1
|
2035 else
|
flickerstreak@1
|
2036 local old_ChatFrame_MessageEventHandler = ChatFrame_MessageEventHandler
|
flickerstreak@1
|
2037 function ChatFrame_MessageEventHandler(event)
|
flickerstreak@1
|
2038 if self.hooks.ChatFrame_MessageEventHandler then
|
flickerstreak@1
|
2039 return self.hooks.ChatFrame_MessageEventHandler(self, old_ChatFrame_MessageEventHandler, event)
|
flickerstreak@1
|
2040 else
|
flickerstreak@1
|
2041 return old_ChatFrame_MessageEventHandler(event)
|
flickerstreak@1
|
2042 end
|
flickerstreak@1
|
2043 end
|
flickerstreak@1
|
2044 local id
|
flickerstreak@1
|
2045 local loggingOut = false
|
flickerstreak@1
|
2046 local old_Logout = Logout
|
flickerstreak@1
|
2047 function Logout()
|
flickerstreak@1
|
2048 if self.hooks.Logout then
|
flickerstreak@1
|
2049 return self.hooks.Logout(self, old_Logout)
|
flickerstreak@1
|
2050 else
|
flickerstreak@1
|
2051 return old_Logout()
|
flickerstreak@1
|
2052 end
|
flickerstreak@1
|
2053 end
|
flickerstreak@1
|
2054 local old_CancelLogout = CancelLogout
|
flickerstreak@1
|
2055 function CancelLogout()
|
flickerstreak@1
|
2056 if self.hooks.CancelLogout then
|
flickerstreak@1
|
2057 return self.hooks.CancelLogout(self, old_CancelLogout)
|
flickerstreak@1
|
2058 else
|
flickerstreak@1
|
2059 return old_CancelLogout()
|
flickerstreak@1
|
2060 end
|
flickerstreak@1
|
2061 end
|
flickerstreak@1
|
2062 local old_Quit = Quit
|
flickerstreak@1
|
2063 function Quit()
|
flickerstreak@1
|
2064 if self.hooks.Quit then
|
flickerstreak@1
|
2065 return self.hooks.Quit(self, old_Quit)
|
flickerstreak@1
|
2066 else
|
flickerstreak@1
|
2067 return old_Quit()
|
flickerstreak@1
|
2068 end
|
flickerstreak@1
|
2069 end
|
flickerstreak@1
|
2070 local old_FCFDropDown_LoadChannels = FCFDropDown_LoadChannels
|
flickerstreak@1
|
2071 function FCFDropDown_LoadChannels(...)
|
flickerstreak@1
|
2072 if self.hooks.FCFDropDown_LoadChannels then
|
flickerstreak@1
|
2073 return self.hooks.FCFDropDown_LoadChannels(self, old_FCFDropDown_LoadChannels, ...)
|
flickerstreak@1
|
2074 else
|
flickerstreak@1
|
2075 return old_FCFDropDown_LoadChannels(...)
|
flickerstreak@1
|
2076 end
|
flickerstreak@1
|
2077 end
|
flickerstreak@1
|
2078 local old_JoinChannelByName = JoinChannelByName
|
flickerstreak@1
|
2079 function JoinChannelByName(a,b,c,d,e,f,g,h,i,j)
|
flickerstreak@1
|
2080 if self.hooks.JoinChannelByName then
|
flickerstreak@1
|
2081 return self.hooks.JoinChannelByName(self, old_JoinChannelByName, a,b,c,d,e,f,g,h,i,j)
|
flickerstreak@1
|
2082 else
|
flickerstreak@1
|
2083 return old_JoinChannelByName(a,b,c,d,e,f,g,h,i,j)
|
flickerstreak@1
|
2084 end
|
flickerstreak@1
|
2085 end
|
flickerstreak@1
|
2086 end
|
flickerstreak@1
|
2087
|
flickerstreak@1
|
2088 if not self.recvQueue then
|
flickerstreak@1
|
2089 self.recvQueue = {}
|
flickerstreak@1
|
2090 end
|
flickerstreak@1
|
2091 if not self.registry then
|
flickerstreak@1
|
2092 self.registry = {}
|
flickerstreak@1
|
2093 end
|
flickerstreak@1
|
2094 AceComm_registry = self.registry
|
flickerstreak@1
|
2095 if not self.prefixes then
|
flickerstreak@1
|
2096 self.prefixes = {}
|
flickerstreak@1
|
2097 end
|
flickerstreak@1
|
2098 if not self.classes then
|
flickerstreak@1
|
2099 self.classes = {}
|
flickerstreak@1
|
2100 else
|
flickerstreak@1
|
2101 for k in pairs(self.classes) do
|
flickerstreak@1
|
2102 self.classes[k] = nil
|
flickerstreak@1
|
2103 end
|
flickerstreak@1
|
2104 end
|
flickerstreak@1
|
2105 if not self.prefixMemoizations then
|
flickerstreak@1
|
2106 self.prefixMemoizations = {}
|
flickerstreak@1
|
2107 end
|
flickerstreak@1
|
2108 if not self.prefixHashToText then
|
flickerstreak@1
|
2109 self.prefixHashToText = {}
|
flickerstreak@1
|
2110 end
|
flickerstreak@1
|
2111 if not self.prefixTextToHash then
|
flickerstreak@1
|
2112 self.prefixTextToHash = {}
|
flickerstreak@1
|
2113 end
|
flickerstreak@1
|
2114 if not self.recentWhispers then
|
flickerstreak@1
|
2115 self.recentWhispers = {}
|
flickerstreak@1
|
2116 end
|
flickerstreak@1
|
2117 if not self.userRegistry then
|
flickerstreak@1
|
2118 self.userRegistry = {}
|
flickerstreak@1
|
2119 end
|
flickerstreak@1
|
2120
|
flickerstreak@1
|
2121 SetCVar("spamFilter", 0)
|
flickerstreak@1
|
2122
|
flickerstreak@1
|
2123 self:activate(oldLib, oldDeactivate)
|
flickerstreak@1
|
2124
|
flickerstreak@1
|
2125 if oldDeactivate then
|
flickerstreak@1
|
2126 oldDeactivate(oldLib)
|
flickerstreak@1
|
2127 end
|
flickerstreak@1
|
2128 end
|
flickerstreak@1
|
2129
|
flickerstreak@1
|
2130 local function external(self, major, instance)
|
flickerstreak@1
|
2131 if major == "AceEvent-2.0" then
|
flickerstreak@1
|
2132 AceEvent = instance
|
flickerstreak@1
|
2133
|
flickerstreak@1
|
2134 AceEvent:embed(AceComm)
|
flickerstreak@1
|
2135
|
flickerstreak@1
|
2136 self:UnregisterAllEvents()
|
flickerstreak@1
|
2137 self:CancelAllScheduledEvents()
|
flickerstreak@1
|
2138
|
flickerstreak@1
|
2139 if AceEvent:IsFullyInitialized() then
|
flickerstreak@1
|
2140 self:AceEvent_FullyInitialized()
|
flickerstreak@1
|
2141 else
|
flickerstreak@1
|
2142 self:RegisterEvent("AceEvent_FullyInitialized", "AceEvent_FullyInitialized", true)
|
flickerstreak@1
|
2143 end
|
flickerstreak@1
|
2144
|
flickerstreak@1
|
2145 self:RegisterEvent("PLAYER_LOGOUT")
|
flickerstreak@1
|
2146 self:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
flickerstreak@1
|
2147 self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE")
|
flickerstreak@1
|
2148 self:RegisterEvent("CHAT_MSG_SYSTEM")
|
flickerstreak@1
|
2149 else
|
flickerstreak@1
|
2150 if AceOO.inherits(instance, AceOO.Class) and not instance.class then
|
flickerstreak@1
|
2151 self.classes[TailoredNumericCheckSum(major)] = instance
|
flickerstreak@1
|
2152 end
|
flickerstreak@1
|
2153 end
|
flickerstreak@1
|
2154 end
|
flickerstreak@1
|
2155
|
flickerstreak@1
|
2156 AceLibrary:Register(AceComm, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
|
flickerstreak@1
|
2157
|
flickerstreak@1
|
2158
|
flickerstreak@1
|
2159
|
flickerstreak@1
|
2160
|
flickerstreak@1
|
2161
|
flickerstreak@1
|
2162 --
|
flickerstreak@1
|
2163 -- ChatThrottleLib by Mikk
|
flickerstreak@1
|
2164 --
|
flickerstreak@1
|
2165 -- Manages AddOn chat output to keep player from getting kicked off.
|
flickerstreak@1
|
2166 --
|
flickerstreak@1
|
2167 -- ChatThrottleLib.SendChatMessage/.SendAddonMessage functions that accept
|
flickerstreak@1
|
2168 -- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
|
flickerstreak@1
|
2169 --
|
flickerstreak@1
|
2170 -- Priorities get an equal share of available bandwidth when fully loaded.
|
flickerstreak@1
|
2171 -- Communication channels are separated on extension+chattype+destination and
|
flickerstreak@1
|
2172 -- get round-robinned. (Destination only matters for whispers and channels,
|
flickerstreak@1
|
2173 -- obviously)
|
flickerstreak@1
|
2174 --
|
flickerstreak@1
|
2175 -- Will install hooks for SendChatMessage and SendAdd[Oo]nMessage to measure
|
flickerstreak@1
|
2176 -- bandwidth bypassing the library and use less bandwidth itself.
|
flickerstreak@1
|
2177 --
|
flickerstreak@1
|
2178 --
|
flickerstreak@1
|
2179 -- Fully embeddable library. Just copy this file into your addon directory,
|
flickerstreak@1
|
2180 -- add it to the .toc, and it's done.
|
flickerstreak@1
|
2181 --
|
flickerstreak@1
|
2182 -- Can run as a standalone addon also, but, really, just embed it! :-)
|
flickerstreak@1
|
2183 --
|
flickerstreak@1
|
2184
|
flickerstreak@1
|
2185 local CTL_VERSION = 13
|
flickerstreak@1
|
2186
|
flickerstreak@1
|
2187 local MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
|
flickerstreak@1
|
2188 local MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
|
flickerstreak@1
|
2189
|
flickerstreak@1
|
2190 local BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
|
flickerstreak@1
|
2191
|
flickerstreak@1
|
2192 local MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
|
flickerstreak@1
|
2193
|
flickerstreak@1
|
2194 if(ChatThrottleLib and ChatThrottleLib.version>=CTL_VERSION) then
|
flickerstreak@1
|
2195 -- There's already a newer (or same) version loaded. Buh-bye.
|
flickerstreak@1
|
2196 return;
|
flickerstreak@1
|
2197 end
|
flickerstreak@1
|
2198
|
flickerstreak@1
|
2199
|
flickerstreak@1
|
2200
|
flickerstreak@1
|
2201 if(not ChatThrottleLib) then
|
flickerstreak@1
|
2202 ChatThrottleLib = {}
|
flickerstreak@1
|
2203 end
|
flickerstreak@1
|
2204
|
flickerstreak@1
|
2205 local ChatThrottleLib = ChatThrottleLib
|
flickerstreak@1
|
2206 local strlen = strlen
|
flickerstreak@1
|
2207 local setmetatable = setmetatable
|
flickerstreak@1
|
2208 local getn = getn
|
flickerstreak@1
|
2209 local tremove = tremove
|
flickerstreak@1
|
2210 local tinsert = tinsert
|
flickerstreak@1
|
2211 local tostring = tostring
|
flickerstreak@1
|
2212 local GetTime = GetTime
|
flickerstreak@1
|
2213 local format = format
|
flickerstreak@1
|
2214
|
flickerstreak@1
|
2215 ChatThrottleLib.version=CTL_VERSION;
|
flickerstreak@1
|
2216
|
flickerstreak@1
|
2217
|
flickerstreak@1
|
2218 -----------------------------------------------------------------------
|
flickerstreak@1
|
2219 -- Double-linked ring implementation
|
flickerstreak@1
|
2220
|
flickerstreak@1
|
2221 local Ring = {}
|
flickerstreak@1
|
2222 local RingMeta = { __index=Ring }
|
flickerstreak@1
|
2223
|
flickerstreak@1
|
2224 function Ring:New()
|
flickerstreak@1
|
2225 local ret = {}
|
flickerstreak@1
|
2226 setmetatable(ret, RingMeta)
|
flickerstreak@1
|
2227 return ret;
|
flickerstreak@1
|
2228 end
|
flickerstreak@1
|
2229
|
flickerstreak@1
|
2230 function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
|
flickerstreak@1
|
2231 if(self.pos) then
|
flickerstreak@1
|
2232 obj.prev = self.pos.prev;
|
flickerstreak@1
|
2233 obj.prev.next = obj;
|
flickerstreak@1
|
2234 obj.next = self.pos;
|
flickerstreak@1
|
2235 obj.next.prev = obj;
|
flickerstreak@1
|
2236 else
|
flickerstreak@1
|
2237 obj.next = obj;
|
flickerstreak@1
|
2238 obj.prev = obj;
|
flickerstreak@1
|
2239 self.pos = obj;
|
flickerstreak@1
|
2240 end
|
flickerstreak@1
|
2241 end
|
flickerstreak@1
|
2242
|
flickerstreak@1
|
2243 function Ring:Remove(obj)
|
flickerstreak@1
|
2244 obj.next.prev = obj.prev;
|
flickerstreak@1
|
2245 obj.prev.next = obj.next;
|
flickerstreak@1
|
2246 if(self.pos == obj) then
|
flickerstreak@1
|
2247 self.pos = obj.next;
|
flickerstreak@1
|
2248 if(self.pos == obj) then
|
flickerstreak@1
|
2249 self.pos = nil;
|
flickerstreak@1
|
2250 end
|
flickerstreak@1
|
2251 end
|
flickerstreak@1
|
2252 end
|
flickerstreak@1
|
2253
|
flickerstreak@1
|
2254
|
flickerstreak@1
|
2255
|
flickerstreak@1
|
2256 -----------------------------------------------------------------------
|
flickerstreak@1
|
2257 -- Recycling bin for pipes (kept in a linked list because that's
|
flickerstreak@1
|
2258 -- how they're worked with in the rotating rings; just reusing members)
|
flickerstreak@1
|
2259
|
flickerstreak@1
|
2260 ChatThrottleLib.PipeBin = { count=0 }
|
flickerstreak@1
|
2261
|
flickerstreak@1
|
2262 function ChatThrottleLib.PipeBin:Put(pipe)
|
flickerstreak@1
|
2263 for i=getn(pipe),1,-1 do
|
flickerstreak@1
|
2264 tremove(pipe, i);
|
flickerstreak@1
|
2265 end
|
flickerstreak@1
|
2266 pipe.prev = nil;
|
flickerstreak@1
|
2267 pipe.next = self.list;
|
flickerstreak@1
|
2268 self.list = pipe;
|
flickerstreak@1
|
2269 self.count = self.count+1;
|
flickerstreak@1
|
2270 end
|
flickerstreak@1
|
2271
|
flickerstreak@1
|
2272 function ChatThrottleLib.PipeBin:Get()
|
flickerstreak@1
|
2273 if(self.list) then
|
flickerstreak@1
|
2274 local ret = self.list;
|
flickerstreak@1
|
2275 self.list = ret.next;
|
flickerstreak@1
|
2276 ret.next=nil;
|
flickerstreak@1
|
2277 self.count = self.count - 1;
|
flickerstreak@1
|
2278 return ret;
|
flickerstreak@1
|
2279 end
|
flickerstreak@1
|
2280 return {};
|
flickerstreak@1
|
2281 end
|
flickerstreak@1
|
2282
|
flickerstreak@1
|
2283 function ChatThrottleLib.PipeBin:Tidy()
|
flickerstreak@1
|
2284 if(self.count < 25) then
|
flickerstreak@1
|
2285 return;
|
flickerstreak@1
|
2286 end
|
flickerstreak@1
|
2287
|
flickerstreak@1
|
2288 if(self.count > 100) then
|
flickerstreak@1
|
2289 n=self.count-90;
|
flickerstreak@1
|
2290 else
|
flickerstreak@1
|
2291 n=10;
|
flickerstreak@1
|
2292 end
|
flickerstreak@1
|
2293 for i=2,n do
|
flickerstreak@1
|
2294 self.list = self.list.next;
|
flickerstreak@1
|
2295 end
|
flickerstreak@1
|
2296 local delme = self.list;
|
flickerstreak@1
|
2297 self.list = self.list.next;
|
flickerstreak@1
|
2298 delme.next = nil;
|
flickerstreak@1
|
2299 end
|
flickerstreak@1
|
2300
|
flickerstreak@1
|
2301
|
flickerstreak@1
|
2302
|
flickerstreak@1
|
2303
|
flickerstreak@1
|
2304 -----------------------------------------------------------------------
|
flickerstreak@1
|
2305 -- Recycling bin for messages
|
flickerstreak@1
|
2306
|
flickerstreak@1
|
2307 ChatThrottleLib.MsgBin = {}
|
flickerstreak@1
|
2308
|
flickerstreak@1
|
2309 function ChatThrottleLib.MsgBin:Put(msg)
|
flickerstreak@1
|
2310 msg.text = nil;
|
flickerstreak@1
|
2311 tinsert(self, msg);
|
flickerstreak@1
|
2312 end
|
flickerstreak@1
|
2313
|
flickerstreak@1
|
2314 function ChatThrottleLib.MsgBin:Get()
|
flickerstreak@1
|
2315 local ret = tremove(self, getn(self));
|
flickerstreak@1
|
2316 if(ret) then return ret; end
|
flickerstreak@1
|
2317 return {};
|
flickerstreak@1
|
2318 end
|
flickerstreak@1
|
2319
|
flickerstreak@1
|
2320 function ChatThrottleLib.MsgBin:Tidy()
|
flickerstreak@1
|
2321 if(getn(self)<50) then
|
flickerstreak@1
|
2322 return;
|
flickerstreak@1
|
2323 end
|
flickerstreak@1
|
2324 if(getn(self)>150) then -- "can't happen" but ...
|
flickerstreak@1
|
2325 for n=getn(self),120,-1 do
|
flickerstreak@1
|
2326 tremove(self,n);
|
flickerstreak@1
|
2327 end
|
flickerstreak@1
|
2328 else
|
flickerstreak@1
|
2329 for n=getn(self),getn(self)-20,-1 do
|
flickerstreak@1
|
2330 tremove(self,n);
|
flickerstreak@1
|
2331 end
|
flickerstreak@1
|
2332 end
|
flickerstreak@1
|
2333 end
|
flickerstreak@1
|
2334
|
flickerstreak@1
|
2335
|
flickerstreak@1
|
2336 -----------------------------------------------------------------------
|
flickerstreak@1
|
2337 -- ChatThrottleLib:Init
|
flickerstreak@1
|
2338 -- Initialize queues, set up frame for OnUpdate, etc
|
flickerstreak@1
|
2339
|
flickerstreak@1
|
2340
|
flickerstreak@1
|
2341 function ChatThrottleLib:Init()
|
flickerstreak@1
|
2342
|
flickerstreak@1
|
2343 -- Set up queues
|
flickerstreak@1
|
2344 if(not self.Prio) then
|
flickerstreak@1
|
2345 self.Prio = {}
|
flickerstreak@1
|
2346 self.Prio["ALERT"] = { ByName={}, Ring = Ring:New(), avail=0 };
|
flickerstreak@1
|
2347 self.Prio["NORMAL"] = { ByName={}, Ring = Ring:New(), avail=0 };
|
flickerstreak@1
|
2348 self.Prio["BULK"] = { ByName={}, Ring = Ring:New(), avail=0 };
|
flickerstreak@1
|
2349 end
|
flickerstreak@1
|
2350
|
flickerstreak@1
|
2351 -- v4: total send counters per priority
|
flickerstreak@1
|
2352 for _,Prio in pairs(self.Prio) do
|
flickerstreak@1
|
2353 Prio.nTotalSent = Prio.nTotalSent or 0;
|
flickerstreak@1
|
2354 end
|
flickerstreak@1
|
2355
|
flickerstreak@1
|
2356 self.avail = self.avail or 0; -- v5
|
flickerstreak@1
|
2357 self.nTotalSent = self.nTotalSent or 0; -- v5
|
flickerstreak@1
|
2358
|
flickerstreak@1
|
2359
|
flickerstreak@1
|
2360 -- Set up a frame to get OnUpdate events
|
flickerstreak@1
|
2361 if(not self.Frame) then
|
flickerstreak@1
|
2362 self.Frame = CreateFrame("Frame");
|
flickerstreak@1
|
2363 self.Frame:Hide();
|
flickerstreak@1
|
2364 end
|
flickerstreak@1
|
2365 self.Frame.Show = self.Frame.Show; -- cache for speed
|
flickerstreak@1
|
2366 self.Frame.Hide = self.Frame.Hide; -- cache for speed
|
flickerstreak@1
|
2367 self.Frame:SetScript("OnUpdate", self.OnUpdate);
|
flickerstreak@1
|
2368 self.Frame:SetScript("OnEvent", self.OnEvent); -- v11: Monitor P_E_W so we can throttle hard for a few seconds
|
flickerstreak@1
|
2369 self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD");
|
flickerstreak@1
|
2370 self.OnUpdateDelay=0;
|
flickerstreak@1
|
2371 self.LastAvailUpdate=GetTime();
|
flickerstreak@1
|
2372 self.HardThrottlingBeginTime=GetTime(); -- v11: Throttle hard for a few seconds after startup
|
flickerstreak@1
|
2373
|
flickerstreak@1
|
2374 -- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
|
flickerstreak@1
|
2375 if(not self.ORIG_SendChatMessage) then
|
flickerstreak@1
|
2376 --SendChatMessage
|
flickerstreak@1
|
2377 self.ORIG_SendChatMessage = SendChatMessage;
|
flickerstreak@1
|
2378 SendChatMessage = function(a1,a2,a3,a4) return ChatThrottleLib.Hook_SendChatMessage(a1,a2,a3,a4); end
|
flickerstreak@1
|
2379 --SendAdd[Oo]nMessage
|
flickerstreak@1
|
2380 if(SendAddonMessage or SendAddOnMessage) then -- v10: don't pretend like it doesn't exist if it doesn't!
|
flickerstreak@1
|
2381 self.ORIG_SendAddonMessage = SendAddonMessage or SendAddOnMessage;
|
flickerstreak@1
|
2382 SendAddonMessage = function(a1,a2,a3) return ChatThrottleLib.Hook_SendAddonMessage(a1,a2,a3); end
|
flickerstreak@1
|
2383 if(SendAddOnMessage) then -- in case Slouken changes his mind...
|
flickerstreak@1
|
2384 SendAddOnMessage = SendAddonMessage;
|
flickerstreak@1
|
2385 end
|
flickerstreak@1
|
2386 end
|
flickerstreak@1
|
2387 end
|
flickerstreak@1
|
2388 self.nBypass = 0;
|
flickerstreak@1
|
2389 end
|
flickerstreak@1
|
2390
|
flickerstreak@1
|
2391
|
flickerstreak@1
|
2392 -----------------------------------------------------------------------
|
flickerstreak@1
|
2393 -- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
|
flickerstreak@1
|
2394 function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination)
|
flickerstreak@1
|
2395 local self = ChatThrottleLib;
|
flickerstreak@1
|
2396 local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(destination or "")) + 40;
|
flickerstreak@1
|
2397 self.avail = self.avail - size;
|
flickerstreak@1
|
2398 self.nBypass = self.nBypass + size;
|
flickerstreak@1
|
2399 return self.ORIG_SendChatMessage(text, chattype, language, destination);
|
flickerstreak@1
|
2400 end
|
flickerstreak@1
|
2401 function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype)
|
flickerstreak@1
|
2402 local self = ChatThrottleLib;
|
flickerstreak@1
|
2403 local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(prefix or "")) + 40;
|
flickerstreak@1
|
2404 self.avail = self.avail - size;
|
flickerstreak@1
|
2405 self.nBypass = self.nBypass + size;
|
flickerstreak@1
|
2406 return self.ORIG_SendAddonMessage(prefix, text, chattype);
|
flickerstreak@1
|
2407 end
|
flickerstreak@1
|
2408
|
flickerstreak@1
|
2409
|
flickerstreak@1
|
2410
|
flickerstreak@1
|
2411 -----------------------------------------------------------------------
|
flickerstreak@1
|
2412 -- ChatThrottleLib:UpdateAvail
|
flickerstreak@1
|
2413 -- Update self.avail with how much bandwidth is currently available
|
flickerstreak@1
|
2414
|
flickerstreak@1
|
2415 function ChatThrottleLib:UpdateAvail()
|
flickerstreak@1
|
2416 local now = GetTime();
|
flickerstreak@1
|
2417 local newavail = MAX_CPS * (now-self.LastAvailUpdate);
|
flickerstreak@1
|
2418
|
flickerstreak@1
|
2419 if(now - self.HardThrottlingBeginTime < 5) then
|
flickerstreak@1
|
2420 -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
|
flickerstreak@1
|
2421 self.avail = min(self.avail + (newavail*0.1), MAX_CPS*0.5);
|
flickerstreak@1
|
2422 elseif(GetFramerate()<MIN_FPS) then -- GetFrameRate call takes ~0.002 secs
|
flickerstreak@1
|
2423 newavail = newavail * 0.5;
|
flickerstreak@1
|
2424 self.avail = min(MAX_CPS, self.avail + newavail);
|
flickerstreak@1
|
2425 self.bChoking = true; -- just for stats
|
flickerstreak@1
|
2426 else
|
flickerstreak@1
|
2427 self.avail = min(BURST, self.avail + newavail);
|
flickerstreak@1
|
2428 self.bChoking = false;
|
flickerstreak@1
|
2429 end
|
flickerstreak@1
|
2430
|
flickerstreak@1
|
2431 self.avail = max(self.avail, 0-(MAX_CPS*2)); -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
|
flickerstreak@1
|
2432 self.LastAvailUpdate = now;
|
flickerstreak@1
|
2433
|
flickerstreak@1
|
2434 return self.avail;
|
flickerstreak@1
|
2435 end
|
flickerstreak@1
|
2436
|
flickerstreak@1
|
2437
|
flickerstreak@1
|
2438 -----------------------------------------------------------------------
|
flickerstreak@1
|
2439 -- Despooling logic
|
flickerstreak@1
|
2440
|
flickerstreak@1
|
2441 function ChatThrottleLib:Despool(Prio)
|
flickerstreak@1
|
2442 local ring = Prio.Ring;
|
flickerstreak@1
|
2443 while(ring.pos and Prio.avail>ring.pos[1].nSize) do
|
flickerstreak@1
|
2444 local msg = tremove(Prio.Ring.pos, 1);
|
flickerstreak@1
|
2445 if(not Prio.Ring.pos[1]) then
|
flickerstreak@1
|
2446 local pipe = Prio.Ring.pos;
|
flickerstreak@1
|
2447 Prio.Ring:Remove(pipe);
|
flickerstreak@1
|
2448 Prio.ByName[pipe.name] = nil;
|
flickerstreak@1
|
2449 self.PipeBin:Put(pipe);
|
flickerstreak@1
|
2450 else
|
flickerstreak@1
|
2451 Prio.Ring.pos = Prio.Ring.pos.next;
|
flickerstreak@1
|
2452 end
|
flickerstreak@1
|
2453 Prio.avail = Prio.avail - msg.nSize;
|
flickerstreak@1
|
2454 msg.f(msg[1], msg[2], msg[3], msg[4]);
|
flickerstreak@1
|
2455 Prio.nTotalSent = Prio.nTotalSent + msg.nSize;
|
flickerstreak@1
|
2456 self.MsgBin:Put(msg);
|
flickerstreak@1
|
2457 end
|
flickerstreak@1
|
2458 end
|
flickerstreak@1
|
2459
|
flickerstreak@1
|
2460
|
flickerstreak@1
|
2461 function ChatThrottleLib.OnEvent()
|
flickerstreak@1
|
2462 -- v11: We know that the rate limiter is touchy after login. Assume that it's touch after zoning, too.
|
flickerstreak@1
|
2463 self = ChatThrottleLib;
|
flickerstreak@1
|
2464 if(event == "PLAYER_ENTERING_WORLD") then
|
flickerstreak@1
|
2465 self.HardThrottlingBeginTime=GetTime(); -- Throttle hard for a few seconds after zoning
|
flickerstreak@1
|
2466 self.avail = 0;
|
flickerstreak@1
|
2467 end
|
flickerstreak@1
|
2468 end
|
flickerstreak@1
|
2469
|
flickerstreak@1
|
2470
|
flickerstreak@1
|
2471 function ChatThrottleLib.OnUpdate()
|
flickerstreak@1
|
2472 self = ChatThrottleLib;
|
flickerstreak@1
|
2473
|
flickerstreak@1
|
2474 self.OnUpdateDelay = self.OnUpdateDelay + arg1;
|
flickerstreak@1
|
2475 if(self.OnUpdateDelay < 0.08) then
|
flickerstreak@1
|
2476 return;
|
flickerstreak@1
|
2477 end
|
flickerstreak@1
|
2478 self.OnUpdateDelay = 0;
|
flickerstreak@1
|
2479
|
flickerstreak@1
|
2480 self:UpdateAvail();
|
flickerstreak@1
|
2481
|
flickerstreak@1
|
2482 if(self.avail<0) then
|
flickerstreak@1
|
2483 return; -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
|
flickerstreak@1
|
2484 end
|
flickerstreak@1
|
2485
|
flickerstreak@1
|
2486 -- See how many of or priorities have queued messages
|
flickerstreak@1
|
2487 local n=0;
|
flickerstreak@1
|
2488 for prioname,Prio in pairs(self.Prio) do
|
flickerstreak@1
|
2489 if(Prio.Ring.pos or Prio.avail<0) then
|
flickerstreak@1
|
2490 n=n+1;
|
flickerstreak@1
|
2491 end
|
flickerstreak@1
|
2492 end
|
flickerstreak@1
|
2493
|
flickerstreak@1
|
2494 -- Anything queued still?
|
flickerstreak@1
|
2495 if(n<1) then
|
flickerstreak@1
|
2496 -- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
|
flickerstreak@1
|
2497 for prioname,Prio in pairs(self.Prio) do
|
flickerstreak@1
|
2498 self.avail = self.avail + Prio.avail;
|
flickerstreak@1
|
2499 Prio.avail = 0;
|
flickerstreak@1
|
2500 end
|
flickerstreak@1
|
2501 self.bQueueing = false;
|
flickerstreak@1
|
2502 self.Frame:Hide();
|
flickerstreak@1
|
2503 return;
|
flickerstreak@1
|
2504 end
|
flickerstreak@1
|
2505
|
flickerstreak@1
|
2506 -- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
|
flickerstreak@1
|
2507 local avail= self.avail/n;
|
flickerstreak@1
|
2508 self.avail = 0;
|
flickerstreak@1
|
2509
|
flickerstreak@1
|
2510 for prioname,Prio in pairs(self.Prio) do
|
flickerstreak@1
|
2511 if(Prio.Ring.pos or Prio.avail<0) then
|
flickerstreak@1
|
2512 Prio.avail = Prio.avail + avail;
|
flickerstreak@1
|
2513 if(Prio.Ring.pos and Prio.avail>Prio.Ring.pos[1].nSize) then
|
flickerstreak@1
|
2514 self:Despool(Prio);
|
flickerstreak@1
|
2515 end
|
flickerstreak@1
|
2516 end
|
flickerstreak@1
|
2517 end
|
flickerstreak@1
|
2518
|
flickerstreak@1
|
2519 -- Expire recycled tables if needed
|
flickerstreak@1
|
2520 self.MsgBin:Tidy();
|
flickerstreak@1
|
2521 self.PipeBin:Tidy();
|
flickerstreak@1
|
2522 end
|
flickerstreak@1
|
2523
|
flickerstreak@1
|
2524
|
flickerstreak@1
|
2525
|
flickerstreak@1
|
2526
|
flickerstreak@1
|
2527 -----------------------------------------------------------------------
|
flickerstreak@1
|
2528 -- Spooling logic
|
flickerstreak@1
|
2529
|
flickerstreak@1
|
2530
|
flickerstreak@1
|
2531 function ChatThrottleLib:Enqueue(prioname, pipename, msg)
|
flickerstreak@1
|
2532 local Prio = self.Prio[prioname];
|
flickerstreak@1
|
2533 local pipe = Prio.ByName[pipename];
|
flickerstreak@1
|
2534 if(not pipe) then
|
flickerstreak@1
|
2535 self.Frame:Show();
|
flickerstreak@1
|
2536 pipe = self.PipeBin:Get();
|
flickerstreak@1
|
2537 pipe.name = pipename;
|
flickerstreak@1
|
2538 Prio.ByName[pipename] = pipe;
|
flickerstreak@1
|
2539 Prio.Ring:Add(pipe);
|
flickerstreak@1
|
2540 end
|
flickerstreak@1
|
2541
|
flickerstreak@1
|
2542 tinsert(pipe, msg);
|
flickerstreak@1
|
2543
|
flickerstreak@1
|
2544 self.bQueueing = true;
|
flickerstreak@1
|
2545 end
|
flickerstreak@1
|
2546
|
flickerstreak@1
|
2547
|
flickerstreak@1
|
2548
|
flickerstreak@1
|
2549 function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination)
|
flickerstreak@1
|
2550 if(not (self and prio and text and self.Prio[prio] ) ) then
|
flickerstreak@1
|
2551 error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix" or nil, "text"[, "chattype"[, "language"[, "destination"]]]', 2);
|
flickerstreak@1
|
2552 end
|
flickerstreak@1
|
2553
|
flickerstreak@1
|
2554 prefix = prefix or tostring(this); -- each frame gets its own queue if prefix is not given
|
flickerstreak@1
|
2555
|
flickerstreak@1
|
2556 local nSize = strlen(text) + MSG_OVERHEAD;
|
flickerstreak@1
|
2557
|
flickerstreak@1
|
2558 -- Check if there's room in the global available bandwidth gauge to send directly
|
flickerstreak@1
|
2559 if(not self.bQueueing and nSize < self:UpdateAvail()) then
|
flickerstreak@1
|
2560 self.avail = self.avail - nSize;
|
flickerstreak@1
|
2561 self.ORIG_SendChatMessage(text, chattype, language, destination);
|
flickerstreak@1
|
2562 self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize;
|
flickerstreak@1
|
2563 return;
|
flickerstreak@1
|
2564 end
|
flickerstreak@1
|
2565
|
flickerstreak@1
|
2566 -- Message needs to be queued
|
flickerstreak@1
|
2567 msg=self.MsgBin:Get();
|
flickerstreak@1
|
2568 msg.f=self.ORIG_SendChatMessage
|
flickerstreak@1
|
2569 msg[1]=text;
|
flickerstreak@1
|
2570 msg[2]=chattype or "SAY";
|
flickerstreak@1
|
2571 msg[3]=language;
|
flickerstreak@1
|
2572 msg[4]=destination;
|
flickerstreak@1
|
2573 msg.n = 4
|
flickerstreak@1
|
2574 msg.nSize = nSize;
|
flickerstreak@1
|
2575
|
flickerstreak@1
|
2576 self:Enqueue(prio, format("%s/%s/%s", prefix, chattype, destination or ""), msg);
|
flickerstreak@1
|
2577 end
|
flickerstreak@1
|
2578
|
flickerstreak@1
|
2579
|
flickerstreak@1
|
2580 function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype)
|
flickerstreak@1
|
2581 if(not (self and prio and prefix and text and chattype and self.Prio[prio] ) ) then
|
flickerstreak@1
|
2582 error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype")', 0);
|
flickerstreak@1
|
2583 end
|
flickerstreak@1
|
2584
|
flickerstreak@1
|
2585 local nSize = strlen(prefix) + 1 + strlen(text) + MSG_OVERHEAD;
|
flickerstreak@1
|
2586
|
flickerstreak@1
|
2587 -- Check if there's room in the global available bandwidth gauge to send directly
|
flickerstreak@1
|
2588 if(not self.bQueueing and nSize < self:UpdateAvail()) then
|
flickerstreak@1
|
2589 self.avail = self.avail - nSize;
|
flickerstreak@1
|
2590 self.ORIG_SendAddonMessage(prefix, text, chattype);
|
flickerstreak@1
|
2591 self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize;
|
flickerstreak@1
|
2592 return;
|
flickerstreak@1
|
2593 end
|
flickerstreak@1
|
2594
|
flickerstreak@1
|
2595 -- Message needs to be queued
|
flickerstreak@1
|
2596 msg=self.MsgBin:Get();
|
flickerstreak@1
|
2597 msg.f=self.ORIG_SendAddonMessage;
|
flickerstreak@1
|
2598 msg[1]=prefix;
|
flickerstreak@1
|
2599 msg[2]=text;
|
flickerstreak@1
|
2600 msg[3]=chattype;
|
flickerstreak@1
|
2601 msg.n = 3
|
flickerstreak@1
|
2602 msg.nSize = nSize;
|
flickerstreak@1
|
2603
|
flickerstreak@1
|
2604 self:Enqueue(prio, format("%s/%s", prefix, chattype), msg);
|
flickerstreak@1
|
2605 end
|
flickerstreak@1
|
2606
|
flickerstreak@1
|
2607
|
flickerstreak@1
|
2608
|
flickerstreak@1
|
2609
|
flickerstreak@1
|
2610 -----------------------------------------------------------------------
|
flickerstreak@1
|
2611 -- Get the ball rolling!
|
flickerstreak@1
|
2612
|
flickerstreak@1
|
2613 ChatThrottleLib:Init();
|
flickerstreak@1
|
2614
|
flickerstreak@1
|
2615 --[[ WoWBench debugging snippet
|
flickerstreak@1
|
2616 if(WOWB_VER) then
|
flickerstreak@1
|
2617 local function SayTimer()
|
flickerstreak@1
|
2618 print("SAY: "..GetTime().." "..arg1);
|
flickerstreak@1
|
2619 end
|
flickerstreak@1
|
2620 ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer);
|
flickerstreak@1
|
2621 ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY");
|
flickerstreak@1
|
2622 end
|
flickerstreak@1
|
2623 ]]
|