diff --git a/Gladius/Gladius.lua b/Gladius/Gladius.lua index 2d3c5d8..1df94ea 100644 --- a/Gladius/Gladius.lua +++ b/Gladius/Gladius.lua @@ -1,8 +1,8 @@ -Gladius = LibStub("AceAddon-3.0"):NewAddon("Gladius", "AceEvent-3.0", "AceConsole-3.0") +Gladius = LibStub("AceAddon-3.0"):NewAddon("Gladius", "AceEvent-3.0", "AceConsole-3.0", "AceComm-3.0", "AceTimer-3.0", "AceSerializer-3.0") local L = LibStub("AceLocale-3.0"):GetLocale("Gladius", true) local LSM = LibStub("LibSharedMedia-3.0") local LCG = LibStub("LibCustomGlow-1.0") -local LHC = LibStub("LibHealCommArena-4.0") +--[[ local LHC = LibStub("LibHealCommArena-4.0") ]] local LAM = LibStub:GetLibrary("AbsorbsMonitor-1.0", true) local LDB = LibStub ("LibDataBroker-1.1") local LDBIcon = LibStub("LibDBIcon-1.0") @@ -27,13 +27,13 @@ function Gladius:OnInitialize() self.buttons = {} self.currentBracket = nil - LHC.UnregisterAllCallbacks(Gladius); + --[[ LHC.UnregisterAllCallbacks(Gladius); LHC.RegisterCallback(Gladius, "HealCommArena_HealStarted", "HealCommArena_Heal_Update") LHC.RegisterCallback(Gladius, "HealCommArena_HealUpdated", "HealCommArena_Heal_Update") LHC.RegisterCallback(Gladius, "HealCommArena_HealDelayed", "HealCommArena_Heal_Update") LHC.RegisterCallback(Gladius, "HealCommArena_HealStopped", "HealCommArena_Heal_Update") LHC.RegisterCallback(Gladius, "HealCommArena_ModifierChanged", "HealCommArena_Modified") - LHC.RegisterCallback(Gladius, "HealCommArena_GUIDDisappeared", "HealCommArena_Modified") + LHC.RegisterCallback(Gladius, "HealCommArena_GUIDDisappeared", "HealCommArena_Modified") ]] -- Populate the arenaUnits table for i=1, 5 do @@ -270,7 +270,7 @@ function Gladius:JoinedArena() LHC.RegisterCallback(Gladius, "HealCommArena_ModifierChanged", "HealCommArena_Modified") LHC.RegisterCallback(Gladius, "HealCommArena_GUIDDisappeared", "HealCommArena_Modified")]] - -- HealComm Events + -- Absorb Events LAM.UnregisterAllCallbacks(Gladius); LAM.RegisterCallback(Gladius, "EffectApplied"); LAM.RegisterCallback(Gladius, "EffectUpdated"); @@ -1825,7 +1825,7 @@ function Gladius:UpdateAbsorbBar(event, unit, button) local health = UnitHealth(unit) local maxHealth = UnitHealthMax(unit) local _guid = UnitGUID(unit) - local myCurrentHealAbsorb = LAM.Unit_Total(_guid) + local myCurrentHealAbsorb = LAM.Unit_Total(_guid) * 2 -- only enemy -- function CompactUnitFrameUtil_UpdateFillBar(self, frame, previousTexture, health, myCurrentHealAbsorb) @@ -1867,16 +1867,10 @@ function Gladius:UpdateAbsorbBar(event, unit, button) end -- HealComm (Heal Prediction) -local function Update(self) +--[[ local function Update(self) local unit = self.unit local element = self.HealCommBar - --[[ Callback: HealthPrediction:PreUpdate(unit) - Called before the element has been updated. - - * self - the HealthPrediction element - * unit - the unit for which the update has been triggered (string) - --]] if element.PreUpdate then element:PreUpdate(unit) end @@ -1912,27 +1906,9 @@ local function Update(self) element.otherBar:Show() end - --[[ Callback: HealthPrediction:PostUpdate(unit, myIncomingHeal, otherIncomingHeal) - Called after the element has been updated. - - * self - the HealthPrediction element - * unit - the unit for which the update has been triggered (string) - * myIncomingHeal - the amount of incoming healing done by the player (number) - * otherIncomingHeal - the amount of incoming healing done by others (number) - --]] - if element.PostUpdate then - return element:PostUpdate(unit, myIncomingHeal, otherIncomingHeal) - end end local function MultiUpdate(...) for i = 1, select("#", ...) do - --[[ for j = 1, #enabledUF do - local frame = enabledUF[j] - - if frame.unit and frame:IsVisible() and UnitGUID(frame.unit) == select(i, ...) then - Path(frame) - end - end ]] if (UnitGUID('arena1') == select(i, ...)) then local allIncomingHeal = LHC:GetHealAmount(select(i, ...), LHC.ALL_HEALS, nil) or 0 print('updated arena1', allIncomingHeal) @@ -1947,4 +1923,4 @@ function Gladius:HealCommArena_Heal_Update(event, casterGUID, spellID, spellType end function Gladius:HealCommArena_Modified(event, guid) MultiUpdate(guid) -end +end ]] diff --git a/Gladius/Gladius.toc b/Gladius/Gladius.toc index 2bb02d1..3b15139 100644 --- a/Gladius/Gladius.toc +++ b/Gladius/Gladius.toc @@ -4,7 +4,7 @@ ## Version: v1.2.2 ## Author: Proditor, Rinu, Enhanced by Cortes ## SavedVariables: GladiusDB -## OptionalDeps: Ace3, LibStub, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibCustomGlow-1.0, AbsorbsMonitor-1.0, LibDataBroker-1.1, LibDBIcon-1.0, LibHealCommArena-4.0 +## OptionalDeps: Ace3, LibStub, LibSharedMedia-3.0, AceGUI-3.0-SharedMediaWidgets, LibCustomGlow-1.0, AbsorbsMonitor-1.0, LibDataBroker-1.1, LibDBIcon-1.0 ## LoadManagers: AddonLoader ## X-LoadOn-Slash: /gladius ## X-LoadOn-InterfaceOptions: Gladius diff --git a/Gladius/embeds.xml b/Gladius/embeds.xml index 270f514..83c717a 100644 --- a/Gladius/embeds.xml +++ b/Gladius/embeds.xml @@ -12,10 +12,14 @@ + + + - + + \ No newline at end of file diff --git a/Gladius/frame.lua b/Gladius/frame.lua index 582e78b..c324ef3 100644 --- a/Gladius/frame.lua +++ b/Gladius/frame.lua @@ -273,7 +273,7 @@ function Gladius:CreateButton(i) absorbBar.overAbsorbGlow:SetBlendMode("ADD"); absorbBar.overAbsorbGlow:Hide() -- Total absorb - absorbBar.totalAbsorb = absorbBar:CreateTexture(nil, "BORDER") + absorbBar.totalAbsorb = absorbBar:CreateTexture(nil, "BACKGROUND") absorbBar.totalAbsorb:Hide() -- Total absorb overlay absorbBar.totalAbsorbOverlay = absorbBar:CreateTexture(nil, "BORDER") diff --git a/Gladius/libs/AceComm-3.0/AceComm-3.0.lua b/Gladius/libs/AceComm-3.0/AceComm-3.0.lua new file mode 100644 index 0000000..ad5268f --- /dev/null +++ b/Gladius/libs/AceComm-3.0/AceComm-3.0.lua @@ -0,0 +1,309 @@ +--- **AceComm-3.0** allows you to send messages of unlimited length over the addon comm channels. +-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\ +-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server. +-- +-- **AceComm-3.0** can be embeded into your addon, either explicitly by calling AceComm:Embed(MyAddon) or by +-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object +-- and can be accessed directly, without having to explicitly call AceComm itself.\\ +-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you +-- make into AceComm. +-- @class file +-- @name AceComm-3.0 +-- @release $Id: AceComm-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $ + +--[[ AceComm-3.0 + +TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited. + +]] + +local MAJOR, MINOR = "AceComm-3.0", 6 + +local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR) + +if not AceComm then return end + +local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0") +local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib") + +-- Lua APIs +local type, next, pairs, tostring = type, next, pairs, tostring +local strsub, strfind = string.sub, string.find +local tinsert, tconcat = table.insert, table.concat +local error, assert = error, assert + +-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded +-- List them here for Mikk's FindGlobals script +-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler + +AceComm.embeds = AceComm.embeds or {} + +-- for my sanity and yours, let's give the message type bytes some names +local MSG_MULTI_FIRST = "\001" +local MSG_MULTI_NEXT = "\002" +local MSG_MULTI_LAST = "\003" + +AceComm.multipart_origprefixes = AceComm.multipart_origprefixes or {} -- e.g. "Prefix\001"="Prefix", "Prefix\002"="Prefix" +AceComm.multipart_reassemblers = AceComm.multipart_reassemblers or {} -- e.g. "Prefix\001"="OnReceiveMultipartFirst" + +-- the multipart message spool: indexed by a combination of sender+distribution+ +AceComm.multipart_spool = AceComm.multipart_spool or {} + +--- Register for Addon Traffic on a specified prefix +-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent) +-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived" +function AceComm:RegisterComm(prefix, method) + if method == nil then + method = "OnCommReceived" + end + + return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler +end + +local warnedPrefix=false + +--- Send a message over the Addon Channel +-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent) +-- @param text Data to send, nils (\000) not allowed. Any length. +-- @param distribution Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API +-- @param target Destination for some distributions; see SendAddonMessage API +-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL". +-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send. +-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified. +function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callbackFn, callbackArg) + prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery! + if not( type(prefix)=="string" and + type(text)=="string" and + type(distribution)=="string" and + (target==nil or type(target)=="string") and + (prio=="BULK" or prio=="NORMAL" or prio=="ALERT") + ) then + error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2) + end + + if strfind(prefix, "[\001-\009]") then + if strfind(prefix, "[\001-\003]") then + error("SendCommMessage: Characters \\001--\\003 in prefix are reserved for AceComm metadata", 2) + elseif not warnedPrefix then + -- I have some ideas about future extensions that require more control characters /mikk, 20090808 + geterrorhandler()("SendCommMessage: Heads-up developers: Characters \\004--\\009 in prefix are reserved for AceComm future extension") + warnedPrefix = true + end + end + + + local textlen = #text + local maxtextlen = 254 - #prefix -- 254 is the max length of prefix + text that can be sent in one message + local queueName = prefix..distribution..(target or "") + + local ctlCallback = nil + if callbackFn then + ctlCallback = function(sent) + return callbackFn(callbackArg, sent, textlen) + end + end + + if textlen <= maxtextlen then + -- fits all in one message + CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen) + else + maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix + + -- first part + local chunk = strsub(text, 1, maxtextlen) + CTL:SendAddonMessage(prio, prefix..MSG_MULTI_FIRST, chunk, distribution, target, queueName, ctlCallback, maxtextlen) + + -- continuation + local pos = 1+maxtextlen + local prefix2 = prefix..MSG_MULTI_NEXT + + while pos+maxtextlen <= textlen do + chunk = strsub(text, pos, pos+maxtextlen-1) + CTL:SendAddonMessage(prio, prefix2, chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1) + pos = pos + maxtextlen + end + + -- final part + chunk = strsub(text, pos) + CTL:SendAddonMessage(prio, prefix..MSG_MULTI_LAST, chunk, distribution, target, queueName, ctlCallback, textlen) + end +end + + +---------------------------------------- +-- Message receiving +---------------------------------------- + +do + local compost = setmetatable({}, {__mode = "k"}) + local function new() + local t = next(compost) + if t then + compost[t]=nil + for i=#t,3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten + t[i]=nil + end + return t + end + + return {} + end + + local function lostdatawarning(prefix,sender,where) + DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")") + end + + function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender) + local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender + local spool = AceComm.multipart_spool + + --[[ + if spool[key] then + lostdatawarning(prefix,sender,"First") + -- continue and overwrite + end + --]] + + spool[key] = message -- plain string for now + end + + function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender) + local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender + local spool = AceComm.multipart_spool + local olddata = spool[key] + + if not olddata then + --lostdatawarning(prefix,sender,"Next") + return + end + + if type(olddata)~="table" then + -- ... but what we have is not a table. So make it one. (Pull a composted one if available) + local t = new() + t[1] = olddata -- add old data as first string + t[2] = message -- and new message as second string + spool[key] = t -- and put the table in the spool instead of the old string + else + tinsert(olddata, message) + end + end + + function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender) + local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender + local spool = AceComm.multipart_spool + local olddata = spool[key] + + if not olddata then + --lostdatawarning(prefix,sender,"End") + return + end + + spool[key] = nil + + if type(olddata) == "table" then + -- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat + tinsert(olddata, message) + AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender) + compost[olddata] = true + else + -- if we've only received a "first", the spooled data will still only be a string + AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender) + end + end +end + + + + + + +---------------------------------------- +-- Embed CallbackHandler +---------------------------------------- + +if not AceComm.callbacks then + -- ensure that 'prefix to watch' table is consistent with registered + -- callbacks + AceComm.__prefixes = {} + + AceComm.callbacks = CallbackHandler:New(AceComm, + "_RegisterComm", + "UnregisterComm", + "UnregisterAllComm") +end + +function AceComm.callbacks:OnUsed(target, prefix) + AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = prefix + AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = "OnReceiveMultipartFirst" + + AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = prefix + AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = "OnReceiveMultipartNext" + + AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = prefix + AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = "OnReceiveMultipartLast" +end + +function AceComm.callbacks:OnUnused(target, prefix) + AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = nil + AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = nil + + AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = nil + AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = nil + + AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = nil + AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = nil +end + +local function OnEvent(this, event, ...) + if event == "CHAT_MSG_ADDON" then + local prefix,message,distribution,sender = ... + local reassemblername = AceComm.multipart_reassemblers[prefix] + if reassemblername then + -- multipart: reassemble + local aceCommReassemblerFunc = AceComm[reassemblername] + local origprefix = AceComm.multipart_origprefixes[prefix] + aceCommReassemblerFunc(AceComm, origprefix, message, distribution, sender) + else + -- single part: fire it off immediately and let CallbackHandler decide if it's registered or not + AceComm.callbacks:Fire(prefix, message, distribution, sender) + end + else + assert(false, "Received "..tostring(event).." event?!") + end +end + +AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame") +AceComm.frame:SetScript("OnEvent", OnEvent) +AceComm.frame:UnregisterAllEvents() +AceComm.frame:RegisterEvent("CHAT_MSG_ADDON") + + +---------------------------------------- +-- Base library stuff +---------------------------------------- + +local mixins = { + "RegisterComm", + "UnregisterComm", + "UnregisterAllComm", + "SendCommMessage", +} + +-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:.. +-- @param target target object to embed AceComm-3.0 in +function AceComm:Embed(target) + for k, v in pairs(mixins) do + target[v] = self[v] + end + self.embeds[target] = true + return target +end + +function AceComm:OnEmbedDisable(target) + target:UnregisterAllComm() +end + +-- Update embeds +for target, v in pairs(AceComm.embeds) do + AceComm:Embed(target) +end diff --git a/Gladius/libs/AceComm-3.0/AceComm-3.0.xml b/Gladius/libs/AceComm-3.0/AceComm-3.0.xml new file mode 100644 index 0000000..09e8d87 --- /dev/null +++ b/Gladius/libs/AceComm-3.0/AceComm-3.0.xml @@ -0,0 +1,5 @@ + +