Clean up ChatThrottle (Not currently used?)

main
jeffi 10 months ago
parent 49b1a92252
commit 2ee8f47827
  1. 715
      DiesalComm-1.0/ChatThrottleLib.lua

@ -25,45 +25,40 @@
local CTL_VERSION = 23 local CTL_VERSION = 23
local _G = _G if ChatThrottleLib then
if ChatThrottleLib.version >= CTL_VERSION then
if _G.ChatThrottleLib then -- There's already a newer (or same) version loaded. Buh-bye.
if _G.ChatThrottleLib.version >= CTL_VERSION then return
-- There's already a newer (or same) version loaded. Buh-bye. elseif not ChatThrottleLib.securelyHooked then
return print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, <v16) in an addon somewhere. Get the addon updated or copy in a newer ChatThrottleLib.lua (>=v16) in it!")
elseif not _G.ChatThrottleLib.securelyHooked then -- ATTEMPT to unhook; this'll behave badly if someone else has hooked...
print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, <v16) in an addon somewhere. Get the addon updated or copy in a newer ChatThrottleLib.lua (>=v16) in it!") -- ... and if someone has securehooked, they can kiss that goodbye too... >.<
-- ATTEMPT to unhook; this'll behave badly if someone else has hooked... SendChatMessage = ChatThrottleLib.ORIG_SendChatMessage
-- ... and if someone has securehooked, they can kiss that goodbye too... >.< if ChatThrottleLib.ORIG_SendAddonMessage then
_G.SendChatMessage = _G.ChatThrottleLib.ORIG_SendChatMessage SendAddonMessage = ChatThrottleLib.ORIG_SendAddonMessage
if _G.ChatThrottleLib.ORIG_SendAddonMessage then end
_G.SendAddonMessage = _G.ChatThrottleLib.ORIG_SendAddonMessage end
end ChatThrottleLib.ORIG_SendChatMessage = nil
end ChatThrottleLib.ORIG_SendAddonMessage = nil
_G.ChatThrottleLib.ORIG_SendChatMessage = nil
_G.ChatThrottleLib.ORIG_SendAddonMessage = nil
end end
if not _G.ChatThrottleLib then if not ChatThrottleLib then
_G.ChatThrottleLib = {} ChatThrottleLib = {}
end end
ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh) ChatThrottleLib = ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh)
local ChatThrottleLib = _G.ChatThrottleLib local ChatThrottleLib = ChatThrottleLib
ChatThrottleLib.version = CTL_VERSION ChatThrottleLib.version = CTL_VERSION
------------------ TWEAKABLES ----------------- ------------------ TWEAKABLES -----------------
ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800. ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now. ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
local setmetatable = setmetatable local setmetatable = setmetatable
local table_remove = table.remove local table_remove = table.remove
@ -75,9 +70,8 @@ local next = next
local strlen = string.len local strlen = string.len
local GetFramerate = GetFramerate local GetFramerate = GetFramerate
local strlower = string.lower local strlower = string.lower
local unpack,type,pairs,wipe = unpack,type,pairs,wipe local unpack, type, pairs, wipe = unpack, type, pairs, wipe
local UnitInRaid,UnitInParty = UnitInRaid,UnitInParty local UnitInRaid, UnitInParty = UnitInRaid, UnitInParty
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Double-linked ring implementation -- Double-linked ring implementation
@ -86,199 +80,186 @@ local Ring = {}
local RingMeta = { __index = Ring } local RingMeta = { __index = Ring }
function Ring:New() function Ring:New()
local ret = {} local ret = {}
setmetatable(ret, RingMeta) setmetatable(ret, RingMeta)
return ret return ret
end end
function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position) function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
if self.pos then if self.pos then
obj.prev = self.pos.prev obj.prev = self.pos.prev
obj.prev.next = obj obj.prev.next = obj
obj.next = self.pos obj.next = self.pos
obj.next.prev = obj obj.next.prev = obj
else else
obj.next = obj obj.next = obj
obj.prev = obj obj.prev = obj
self.pos = obj self.pos = obj
end end
end end
function Ring:Remove(obj) function Ring:Remove(obj)
obj.next.prev = obj.prev obj.next.prev = obj.prev
obj.prev.next = obj.next obj.prev.next = obj.next
if self.pos == obj then if self.pos == obj then
self.pos = obj.next self.pos = obj.next
if self.pos == obj then if self.pos == obj then
self.pos = nil self.pos = nil
end end
end end
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Recycling bin for pipes -- Recycling bin for pipes
-- A pipe is a plain integer-indexed queue of messages -- A pipe is a plain integer-indexed queue of messages
-- Pipes normally live in Rings of pipes (3 rings total, one per priority) -- Pipes normally live in Rings of pipes (3 rings total, one per priority)
ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
local PipeBin = setmetatable({}, {__mode="k"}) local PipeBin = setmetatable({}, { __mode = "k" })
local function DelPipe(pipe) local function DelPipe(pipe)
PipeBin[pipe] = true PipeBin[pipe] = true
end end
local function NewPipe() local function NewPipe()
local pipe = next(PipeBin) local pipe = next(PipeBin)
if pipe then if pipe then
wipe(pipe) wipe(pipe)
PipeBin[pipe] = nil PipeBin[pipe] = nil
return pipe return pipe
end end
return {} return {}
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Recycling bin for messages -- Recycling bin for messages
ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
local MsgBin = setmetatable({}, {__mode="k"}) local MsgBin = setmetatable({}, { __mode = "k" })
local function DelMsg(msg) local function DelMsg(msg)
msg[1] = nil msg[1] = nil
-- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them. -- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
MsgBin[msg] = true MsgBin[msg] = true
end end
local function NewMsg() local function NewMsg()
local msg = next(MsgBin) local msg = next(MsgBin)
if msg then if msg then
MsgBin[msg] = nil MsgBin[msg] = nil
return msg return msg
end end
return {} return {}
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- ChatThrottleLib:Init -- ChatThrottleLib:Init
-- Initialize queues, set up frame for OnUpdate, etc -- Initialize queues, set up frame for OnUpdate, etc
function ChatThrottleLib:Init() function ChatThrottleLib:Init()
-- Set up queues
-- Set up queues if not self.Prio then
if not self.Prio then self.Prio = {}
self.Prio = {} self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 } self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 } self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 } end
end
-- v4: total send counters per priority
-- v4: total send counters per priority for _, Prio in pairs(self.Prio) do
for _, Prio in pairs(self.Prio) do Prio.nTotalSent = Prio.nTotalSent or 0
Prio.nTotalSent = Prio.nTotalSent or 0 end
end
if not self.avail then
if not self.avail then self.avail = 0 -- v5
self.avail = 0 -- v5 end
end if not self.nTotalSent then
if not self.nTotalSent then self.nTotalSent = 0 -- v5
self.nTotalSent = 0 -- v5 end
end
-- Set up a frame to get OnUpdate events
if not self.Frame then
-- Set up a frame to get OnUpdate events self.Frame = CreateFrame("Frame")
if not self.Frame then self.Frame:Hide()
self.Frame = CreateFrame("Frame") end
self.Frame:Hide() self.Frame:SetScript("OnUpdate", self.OnUpdate)
end self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
self.Frame:SetScript("OnUpdate", self.OnUpdate) self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds self.OnUpdateDelay = 0
self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD") self.LastAvailUpdate = GetTime()
self.OnUpdateDelay = 0 self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
self.LastAvailUpdate = GetTime()
self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup -- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
if not self.securelyHooked then
-- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7) -- Use secure hooks as of v16. Old regular hook support yanked out in v21.
if not self.securelyHooked then self.securelyHooked = true
-- Use secure hooks as of v16. Old regular hook support yanked out in v21. --SendChatMessage
self.securelyHooked = true hooksecurefunc("SendChatMessage", function(...)
--SendChatMessage return ChatThrottleLib.Hook_SendChatMessage(...)
hooksecurefunc("SendChatMessage", function(...) end)
return ChatThrottleLib.Hook_SendChatMessage(...) --SendAddonMessage
end) hooksecurefunc("SendAddonMessage", function(...)
--SendAddonMessage return ChatThrottleLib.Hook_SendAddonMessage(...)
hooksecurefunc("SendAddonMessage", function(...) end)
return ChatThrottleLib.Hook_SendAddonMessage(...) end
end) self.nBypass = 0
end
self.nBypass = 0
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage -- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
local bMyTraffic = false local bMyTraffic = false
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...) function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...)
if bMyTraffic then if bMyTraffic then
return return
end end
local self = ChatThrottleLib local self = ChatThrottleLib
local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
self.avail = self.avail - size self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic self.nBypass = self.nBypass + size -- just a statistic
end end
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...) function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...)
if bMyTraffic then if bMyTraffic then
return return
end end
local self = ChatThrottleLib local self = ChatThrottleLib
local size = tostring(text or ""):len() + tostring(prefix or ""):len(); local size = tostring(text or ""):len() + tostring(prefix or ""):len()
size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD
self.avail = self.avail - size self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic self.nBypass = self.nBypass + size -- just a statistic
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- ChatThrottleLib:UpdateAvail -- ChatThrottleLib:UpdateAvail
-- Update self.avail with how much bandwidth is currently available -- Update self.avail with how much bandwidth is currently available
function ChatThrottleLib:UpdateAvail() function ChatThrottleLib:UpdateAvail()
local now = GetTime() local now = GetTime()
local MAX_CPS = self.MAX_CPS; local MAX_CPS = self.MAX_CPS
local newavail = MAX_CPS * (now - self.LastAvailUpdate) local newavail = MAX_CPS * (now - self.LastAvailUpdate)
local avail = self.avail local avail = self.avail
if now - self.HardThrottlingBeginTime < 5 then if now - self.HardThrottlingBeginTime < 5 then
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5) avail = math_min(avail + (newavail * 0.1), MAX_CPS * 0.5)
self.bChoking = true self.bChoking = true
elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
avail = math_min(MAX_CPS, avail + newavail*0.5) avail = math_min(MAX_CPS, avail + newavail * 0.5)
self.bChoking = true -- just a statistic self.bChoking = true -- just a statistic
else else
avail = math_min(self.BURST, avail + newavail) avail = math_min(self.BURST, avail + newavail)
self.bChoking = false self.bChoking = false
end end
avail = math_max(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. avail = math_max(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.
self.avail = avail self.avail = avail
self.LastAvailUpdate = now self.LastAvailUpdate = now
return avail return avail
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Despooling logic -- Despooling logic
-- Reminder: -- Reminder:
@ -287,225 +268,215 @@ end
-- - and each pipe contains messages -- - and each pipe contains messages
function ChatThrottleLib:Despool(Prio) function ChatThrottleLib:Despool(Prio)
local ring = Prio.Ring local ring = Prio.Ring
while ring.pos and Prio.avail > ring.pos[1].nSize do while ring.pos and Prio.avail > ring.pos[1].nSize do
local msg = table_remove(ring.pos, 1) local msg = table_remove(ring.pos, 1)
if not ring.pos[1] then -- did we remove last msg in this pipe? if not ring.pos[1] then -- did we remove last msg in this pipe?
local pipe = Prio.Ring.pos local pipe = Prio.Ring.pos
Prio.Ring:Remove(pipe) Prio.Ring:Remove(pipe)
Prio.ByName[pipe.name] = nil Prio.ByName[pipe.name] = nil
DelPipe(pipe) DelPipe(pipe)
else else
Prio.Ring.pos = Prio.Ring.pos.next Prio.Ring.pos = Prio.Ring.pos.next
end end
local didSend=false local didSend = false
local lowerDest = strlower(msg[3] or "") local lowerDest = strlower(msg[3] or "")
if lowerDest == "raid" and not UnitInRaid("player") then if lowerDest == "raid" and not UnitInRaid("player") then
-- do nothing -- do nothing
elseif lowerDest == "party" and not UnitInParty("player") then elseif lowerDest == "party" and not UnitInParty("player") then
-- do nothing -- do nothing
else else
Prio.avail = Prio.avail - msg.nSize Prio.avail = Prio.avail - msg.nSize
bMyTraffic = true bMyTraffic = true
msg.f(unpack(msg, 1, msg.n)) msg.f(unpack(msg, 1, msg.n))
bMyTraffic = false bMyTraffic = false
Prio.nTotalSent = Prio.nTotalSent + msg.nSize Prio.nTotalSent = Prio.nTotalSent + msg.nSize
DelMsg(msg) DelMsg(msg)
didSend = true didSend = true
end end
-- notify caller of delivery (even if we didn't send it) -- notify caller of delivery (even if we didn't send it)
if msg.callbackFn then if msg.callbackFn then
msg.callbackFn (msg.callbackArg, didSend) msg.callbackFn(msg.callbackArg, didSend)
end end
-- USER CALLBACK MAY ERROR -- USER CALLBACK MAY ERROR
end end
end end
function ChatThrottleLib.OnEvent(this, event)
function ChatThrottleLib.OnEvent(this,event) -- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too.
-- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too. local self = ChatThrottleLib
local self = ChatThrottleLib if event == "PLAYER_ENTERING_WORLD" then
if event == "PLAYER_ENTERING_WORLD" then self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning self.avail = 0
self.avail = 0 end
end
end end
function ChatThrottleLib.OnUpdate(this, delay)
function ChatThrottleLib.OnUpdate(this,delay) local self = ChatThrottleLib
local self = ChatThrottleLib
self.OnUpdateDelay = self.OnUpdateDelay + delay
self.OnUpdateDelay = self.OnUpdateDelay + delay if self.OnUpdateDelay < 0.08 then
if self.OnUpdateDelay < 0.08 then return
return end
end self.OnUpdateDelay = 0
self.OnUpdateDelay = 0
self:UpdateAvail()
self:UpdateAvail()
if self.avail < 0 then
if self.avail < 0 then return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu. end
end
-- See how many of our priorities have queued messages (we only have 3, don't worry about the loop)
-- See how many of our priorities have queued messages (we only have 3, don't worry about the loop) local n = 0
local n = 0 for prioname, Prio in pairs(self.Prio) do
for prioname,Prio in pairs(self.Prio) do if Prio.Ring.pos or Prio.avail < 0 then
if Prio.Ring.pos or Prio.avail < 0 then n = n + 1
n = n + 1 end
end end
end
-- Anything queued still?
-- Anything queued still? if n < 1 then
if n<1 then -- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
-- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing for prioname, Prio in pairs(self.Prio) do
for prioname, Prio in pairs(self.Prio) do self.avail = self.avail + Prio.avail
self.avail = self.avail + Prio.avail Prio.avail = 0
Prio.avail = 0 end
end self.bQueueing = false
self.bQueueing = false self.Frame:Hide()
self.Frame:Hide() return
return end
end
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues local avail = self.avail / n
local avail = self.avail/n self.avail = 0
self.avail = 0
for prioname, Prio in pairs(self.Prio) do
for prioname, Prio in pairs(self.Prio) do if Prio.Ring.pos or Prio.avail < 0 then
if Prio.Ring.pos or Prio.avail < 0 then Prio.avail = Prio.avail + avail
Prio.avail = Prio.avail + avail if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then self:Despool(Prio)
self:Despool(Prio) -- Note: We might not get here if the user-supplied callback function errors out! Take care!
-- Note: We might not get here if the user-supplied callback function errors out! Take care! end
end end
end end
end
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Spooling logic -- Spooling logic
function ChatThrottleLib:Enqueue(prioname, pipename, msg) function ChatThrottleLib:Enqueue(prioname, pipename, msg)
local Prio = self.Prio[prioname] local Prio = self.Prio[prioname]
local pipe = Prio.ByName[pipename] local pipe = Prio.ByName[pipename]
if not pipe then if not pipe then
self.Frame:Show() self.Frame:Show()
pipe = NewPipe() pipe = NewPipe()
pipe.name = pipename pipe.name = pipename
Prio.ByName[pipename] = pipe Prio.ByName[pipename] = pipe
Prio.Ring:Add(pipe) Prio.Ring:Add(pipe)
end end
pipe[#pipe + 1] = msg pipe[#pipe + 1] = msg
self.bQueueing = true self.bQueueing = true
end end
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg) function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not self.Prio[prio] then if not self or not prio or not prefix or not text or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2) error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
end end
if callbackFn and type(callbackFn)~="function" then if callbackFn and type(callbackFn) ~= "function" then
error('ChatThrottleLib:ChatMessage(): callbackFn: expected function, got '..type(callbackFn), 2) error("ChatThrottleLib:ChatMessage(): callbackFn: expected function, got " .. type(callbackFn), 2)
end end
local nSize = text:len() local nSize = text:len()
if nSize>255 then if nSize > 255 then
error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2) error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2)
end end
nSize = nSize + self.MSG_OVERHEAD nSize = nSize + self.MSG_OVERHEAD
-- Check if there's room in the global available bandwidth gauge to send directly -- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize self.avail = self.avail - nSize
bMyTraffic = true bMyTraffic = true
_G.SendChatMessage(text, chattype, language, destination) _G.SendChatMessage(text, chattype, language, destination)
bMyTraffic = false bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then if callbackFn then
callbackFn (callbackArg, true) callbackFn(callbackArg, true)
end end
-- USER CALLBACK MAY ERROR -- USER CALLBACK MAY ERROR
return return
end end
-- Message needs to be queued -- Message needs to be queued
local msg = NewMsg() local msg = NewMsg()
msg.f = _G.SendChatMessage msg.f = _G.SendChatMessage
msg[1] = text msg[1] = text
msg[2] = chattype or "SAY" msg[2] = chattype or "SAY"
msg[3] = language msg[3] = language
msg[4] = destination msg[4] = destination
msg.n = 4 msg.n = 4
msg.nSize = nSize msg.nSize = nSize
msg.callbackFn = callbackFn msg.callbackFn = callbackFn
msg.callbackArg = callbackArg msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg) self:Enqueue(prio, queueName or (prefix .. (chattype or "SAY") .. (destination or "")), msg)
end end
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg) function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2) error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2)
end end
if callbackFn and type(callbackFn)~="function" then if callbackFn and type(callbackFn) ~= "function" then
error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2) error("ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got " .. type(callbackFn), 2)
end end
local nSize = text:len(); local nSize = text:len()
if RegisterAddonMessagePrefix then if RegisterAddonMessagePrefix then
if nSize>255 then if nSize > 255 then
error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2) error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2)
end end
else else
nSize = nSize + prefix:len() + 1 nSize = nSize + prefix:len() + 1
if nSize>255 then if nSize > 255 then
error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2) error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
end end
end end
nSize = nSize + self.MSG_OVERHEAD; nSize = nSize + self.MSG_OVERHEAD
-- Check if there's room in the global available bandwidth gauge to send directly -- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize self.avail = self.avail - nSize
bMyTraffic = true bMyTraffic = true
_G.SendAddonMessage(prefix, text, chattype, target) _G.SendAddonMessage(prefix, text, chattype, target)
bMyTraffic = false bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then if callbackFn then
callbackFn (callbackArg, true) callbackFn(callbackArg, true)
end end
-- USER CALLBACK MAY ERROR -- USER CALLBACK MAY ERROR
return return
end end
-- Message needs to be queued -- Message needs to be queued
local msg = NewMsg() local msg = NewMsg()
msg.f = _G.SendAddonMessage msg.f = _G.SendAddonMessage
msg[1] = prefix msg[1] = prefix
msg[2] = text msg[2] = text
msg[3] = chattype msg[3] = chattype
msg[4] = target msg[4] = target
msg.n = (target~=nil) and 4 or 3; msg.n = (target ~= nil) and 4 or 3
msg.nSize = nSize msg.nSize = nSize
msg.callbackFn = callbackFn msg.callbackFn = callbackFn
msg.callbackArg = callbackArg msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg) self:Enqueue(prio, queueName or (prefix .. chattype .. (target or "")), msg)
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Get the ball rolling! -- Get the ball rolling!
@ -520,5 +491,3 @@ if(WOWB_VER) then
ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY") ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
end end
]] ]]

Loading…
Cancel
Save