diff --git a/MythicPlusDrop/Libs/AceAddon-3.0/AceAddon-3.0.lua b/MythicPlusDrop/Libs/AceAddon-3.0/AceAddon-3.0.lua index a7f7279..00e4e48 100644 --- a/MythicPlusDrop/Libs/AceAddon-3.0/AceAddon-3.0.lua +++ b/MythicPlusDrop/Libs/AceAddon-3.0/AceAddon-3.0.lua @@ -6,31 +6,31 @@ -- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present. -- * **OnDisable**, which is only called when your addon is manually being disabled. -- @usage --- -- A small (but complete) addon, that doesn't do anything, +-- -- A small (but complete) addon, that doesn't do anything, -- -- but shows usage of the callbacks. -- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon") --- +-- -- function MyAddon:OnInitialize() --- -- do init tasks here, like loading the Saved Variables, +-- -- do init tasks here, like loading the Saved Variables, -- -- or setting up slash commands. -- end --- +-- -- function MyAddon:OnEnable() -- -- Do more initialization here, that really enables the use of your addon. --- -- Register Events, Hook functions, Create Frames, Get information from +-- -- Register Events, Hook functions, Create Frames, Get information from -- -- the game that wasn't available in OnInitialize -- end -- -- function MyAddon:OnDisable() -- -- Unhook, Unregister Events, Hide frames that you created. --- -- You would probably only use an OnDisable if you want to +-- -- You would probably only use an OnDisable if you want to -- -- build a "standby" mode, or be able to toggle modules on/off. -- end -- @class file -- @name AceAddon-3.0.lua --- @release $Id: AceAddon-3.0.lua 1084 2013-04-27 20:14:11Z nevcairiel $ +-- @release $Id$ -local MAJOR, MINOR = "AceAddon-3.0", 12 +local MAJOR, MINOR = "AceAddon-3.0", 13 local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR) if not AceAddon then return end -- No Upgrade needed. @@ -49,10 +49,6 @@ local select, pairs, next, type, unpack = select, pairs, next, type, unpack local loadstring, assert, error = loadstring, assert, error local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget --- 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, IsLoggedIn, geterrorhandler - --[[ xpcall safecall implementation ]] @@ -62,43 +58,12 @@ local function errorhandler(err) return geterrorhandler()(err) end -local function CreateDispatcher(argCount) - local code = [[ - local xpcall, eh = ... - local method, ARGS - local function call() return method(ARGS) end - - local function dispatch(func, ...) - method = func - if not method then return end - ARGS = ... - return xpcall(call, eh) - end - - return dispatch - ]] - - local ARGS = {} - for i = 1, argCount do ARGS[i] = "arg"..i end - code = code:gsub("ARGS", tconcat(ARGS, ", ")) - return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler) -end - -local Dispatchers = setmetatable({}, {__index=function(self, argCount) - local dispatcher = CreateDispatcher(argCount) - rawset(self, argCount, dispatcher) - return dispatcher -end}) -Dispatchers[0] = function(func) - return xpcall(func, errorhandler) -end - local function safecall(func, ...) -- we check to see if the func is passed is actually a function here and don't error when it isn't -- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not -- present execution should continue without hinderance if type(func) == "function" then - return Dispatchers[select('#', ...)](func, ...) + return xpcall(func, errorhandler, ...) end end @@ -106,7 +71,7 @@ end local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype -- used in the addon metatable -local function addontostring( self ) return self.name end +local function addontostring( self ) return self.name end -- Check if the addon is queued for initialization local function queuedForInitialization(addon) @@ -119,14 +84,14 @@ local function queuedForInitialization(addon) end --- Create a new AceAddon-3.0 addon. --- Any libraries you specified will be embeded, and the addon will be scheduled for +-- Any libraries you specified will be embeded, and the addon will be scheduled for -- its OnInitialize and OnEnable callbacks. -- The final addon object, with all libraries embeded, will be returned. -- @paramsig [object ,]name[, lib, ...] -- @param object Table to use as a base for the addon (optional) -- @param name Name of the addon object to create -- @param lib List of libraries to embed into the addon --- @usage +-- @usage -- -- Create a simple addon object -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0") -- @@ -146,10 +111,10 @@ function AceAddon:NewAddon(objectorname, ...) if type(name)~="string" then error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end - if self.addons[name] then + if self.addons[name] then error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2) end - + object = object or {} object.name = name @@ -159,7 +124,7 @@ function AceAddon:NewAddon(objectorname, ...) for k, v in pairs(oldmeta) do addonmeta[k] = v end end addonmeta.__tostring = addontostring - + setmetatable( object, addonmeta ) self.addons[name] = object object.modules = {} @@ -167,7 +132,7 @@ function AceAddon:NewAddon(objectorname, ...) object.defaultModuleLibraries = {} Embed( object ) -- embed NewModule, GetModule methods self:EmbedLibraries(object, select(i,...)) - + -- add to queue of addons to be initialized upon ADDON_LOADED tinsert(self.initializequeue, object) return object @@ -178,7 +143,7 @@ end -- Throws an error if the addon object cannot be found (except if silent is set). -- @param name unique name of the addon object -- @param silent if true, the addon is optional, silently return nil if its not found --- @usage +-- @usage -- -- Get the Addon -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon") function AceAddon:GetAddon(name, silent) @@ -233,7 +198,7 @@ end -- @paramsig name[, silent] -- @param name unique name of the module -- @param silent if true, the module is optional, silently return nil if its not found (optional) --- @usage +-- @usage -- -- Get the Addon -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon") -- -- Get the Module @@ -256,23 +221,23 @@ local function IsModuleTrue(self) return true end -- @param name unique name of the module -- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional) -- @param lib List of libraries to embed into the addon --- @usage +-- @usage -- -- Create a module with some embeded libraries -- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0") --- +-- -- -- Create a module with a prototype -- local prototype = { OnEnable = function(self) print("OnEnable called!") end } -- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0") function NewModule(self, name, prototype, ...) if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end - + if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end - + -- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well. -- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is. local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name)) - + module.IsModule = IsModuleTrue module:SetEnabledState(self.defaultModuleState) module.moduleName = name @@ -287,24 +252,24 @@ function NewModule(self, name, prototype, ...) if not prototype or type(prototype) == "string" then prototype = self.defaultModulePrototype or nil end - + if type(prototype) == "table" then local mt = getmetatable(module) mt.__index = prototype setmetatable(module, mt) -- More of a Base class type feel. end - + safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy. self.modules[name] = module tinsert(self.orderedModules, module) - + return module end --- Returns the real name of the addon or module, without any prefix. -- @name //addon//:GetName --- @paramsig --- @usage +-- @paramsig +-- @usage -- print(MyAddon:GetName()) -- -- prints "MyAddon" function GetName(self) @@ -316,8 +281,8 @@ end -- and enabling all modules of the addon (unless explicitly disabled).\\ -- :Enable() also sets the internal `enableState` variable to true -- @name //addon//:Enable --- @paramsig --- @usage +-- @paramsig +-- @usage -- -- Enable MyModule -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon") -- MyModule = MyAddon:GetModule("MyModule") @@ -337,8 +302,8 @@ end -- and disabling all modules of the addon.\\ -- :Disable() also sets the internal `enableState` variable to false -- @name //addon//:Disable --- @paramsig --- @usage +-- @paramsig +-- @usage -- -- Disable MyAddon -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon") -- MyAddon:Disable() @@ -351,7 +316,7 @@ end -- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object. -- @name //addon//:EnableModule -- @paramsig name --- @usage +-- @usage -- -- Enable MyModule using :GetModule -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon") -- MyModule = MyAddon:GetModule("MyModule") @@ -369,7 +334,7 @@ end -- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object. -- @name //addon//:DisableModule -- @paramsig name --- @usage +-- @usage -- -- Disable MyModule using :GetModule -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon") -- MyModule = MyAddon:GetModule("MyModule") @@ -388,7 +353,7 @@ end -- @name //addon//:SetDefaultModuleLibraries -- @paramsig lib[, lib, ...] -- @param lib List of libraries to embed into the addon --- @usage +-- @usage -- -- Create the addon object -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon") -- -- Configure default libraries for modules (all modules need AceEvent-3.0) @@ -407,7 +372,7 @@ end -- @name //addon//:SetDefaultModuleState -- @paramsig state -- @param state Default state for new modules, true for enabled, false for disabled --- @usage +-- @usage -- -- Create the addon object -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon") -- -- Set the default state to "disabled" @@ -427,7 +392,7 @@ end -- @name //addon//:SetDefaultModulePrototype -- @paramsig prototype -- @param prototype Default prototype for the new modules (table) --- @usage +-- @usage -- -- Define a prototype -- local prototype = { OnEnable = function(self) print("OnEnable called!") end } -- -- Set the default prototype @@ -459,8 +424,8 @@ end --- Return an iterator of all modules associated to the addon. -- @name //addon//:IterateModules --- @paramsig --- @usage +-- @paramsig +-- @usage -- -- Enable all modules -- for name, module in MyAddon:IterateModules() do -- module:Enable() @@ -469,13 +434,13 @@ local function IterateModules(self) return pairs(self.modules) end -- Returns an iterator of all embeds in the addon -- @name //addon//:IterateEmbeds --- @paramsig +-- @paramsig local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end --- Query the enabledState of an addon. -- @name //addon//:IsEnabled --- @paramsig --- @usage +-- @paramsig +-- @usage -- if MyAddon:IsEnabled() then -- MyAddon:Disable() -- end @@ -520,20 +485,20 @@ end -- - Initialize the addon after creation. -- This function is only used internally during the ADDON_LOADED event --- It will call the **OnInitialize** function on the addon object (if present), +-- It will call the **OnInitialize** function on the addon object (if present), -- and the **OnEmbedInitialize** function on all embeded libraries. --- +-- -- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing. -- @param addon addon object to intialize function AceAddon:InitializeAddon(addon) safecall(addon.OnInitialize, addon) - + local embeds = self.embeds[addon] for i = 1, #embeds do local lib = LibStub:GetLibrary(embeds[i], true) if lib then safecall(lib.OnEmbedInitialize, lib, addon) end end - + -- we don't call InitializeAddon on modules specifically, this is handled -- from the event handler and only done _once_ end @@ -541,7 +506,7 @@ end -- - Enable the addon after creation. -- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED, -- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons. --- It will call the **OnEnable** function on the addon object (if present), +-- It will call the **OnEnable** function on the addon object (if present), -- and the **OnEmbedEnable** function on all embeded libraries.\\ -- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled. -- @@ -551,12 +516,12 @@ end function AceAddon:EnableAddon(addon) if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end if self.statuses[addon.name] or not addon.enabledState then return false end - + -- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable. self.statuses[addon.name] = true - + safecall(addon.OnEnable, addon) - + -- make sure we're still enabled before continueing if self.statuses[addon.name] then local embeds = self.embeds[addon] @@ -564,7 +529,7 @@ function AceAddon:EnableAddon(addon) local lib = LibStub:GetLibrary(embeds[i], true) if lib then safecall(lib.OnEmbedEnable, lib, addon) end end - + -- enable possible modules. local modules = addon.orderedModules for i = 1, #modules do @@ -576,24 +541,24 @@ end -- - Disable the addon -- Note: This function is only used internally. --- It will call the **OnDisable** function on the addon object (if present), +-- It will call the **OnDisable** function on the addon object (if present), -- and the **OnEmbedDisable** function on all embeded libraries.\\ -- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled. -- --- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing. +-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing. -- Use :Disable on the addon itself instead. -- @param addon addon object to enable function AceAddon:DisableAddon(addon) if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end if not self.statuses[addon.name] then return false end - + -- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable. self.statuses[addon.name] = false - + safecall( addon.OnDisable, addon ) - + -- make sure we're still disabling... - if not self.statuses[addon.name] then + if not self.statuses[addon.name] then local embeds = self.embeds[addon] for i = 1, #embeds do local lib = LibStub:GetLibrary(embeds[i], true) @@ -605,12 +570,12 @@ function AceAddon:DisableAddon(addon) self:DisableAddon(modules[i]) end end - + return not self.statuses[addon.name] -- return true if we're disabled end --- Get an iterator over all registered addons. --- @usage +-- @usage -- -- Print a list of all installed AceAddon's -- for name, addon in AceAddon:IterateAddons() do -- print("Addon: " .. name) @@ -618,7 +583,7 @@ end function AceAddon:IterateAddons() return pairs(self.addons) end --- Get an iterator over the internal status registry. --- @usage +-- @usage -- -- Print a list of all enabled addons -- for name, status in AceAddon:IterateAddonStatus() do -- if status then @@ -632,10 +597,20 @@ function AceAddon:IterateAddonStatus() return pairs(self.statuses) end function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end +-- Blizzard AddOns which can load very early in the loading process and mess with Ace3 addon loading +local BlizzardEarlyLoadAddons = { + Blizzard_DebugTools = true, + Blizzard_TimeManager = true, + Blizzard_BattlefieldMap = true, + Blizzard_MapCanvas = true, + Blizzard_SharedMapDataProviders = true, + Blizzard_CombatLog = true, +} + -- Event Handling local function onEvent(this, event, arg1) - -- 2011-08-17 nevcairiel - ignore the load event of Blizzard_DebugTools, so a potential startup error isn't swallowed up - if (event == "ADDON_LOADED" and arg1 ~= "Blizzard_DebugTools") or event == "PLAYER_LOGIN" then + -- 2020-08-28 nevcairiel - ignore the load event of Blizzard addons which occur early in the loading process + if (event == "ADDON_LOADED" and (arg1 == nil or not BlizzardEarlyLoadAddons[arg1])) or event == "PLAYER_LOGIN" then -- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration while(#AceAddon.initializequeue > 0) do local addon = tremove(AceAddon.initializequeue, 1) @@ -644,7 +619,7 @@ local function onEvent(this, event, arg1) AceAddon:InitializeAddon(addon) tinsert(AceAddon.enablequeue, addon) end - + if IsLoggedIn() then while(#AceAddon.enablequeue > 0) do local addon = tremove(AceAddon.enablequeue, 1) diff --git a/MythicPlusDrop/Libs/AceBucket-3.0/AceBucket-3.0.lua b/MythicPlusDrop/Libs/AceBucket-3.0/AceBucket-3.0.lua new file mode 100644 index 0000000..d89dcee --- /dev/null +++ b/MythicPlusDrop/Libs/AceBucket-3.0/AceBucket-3.0.lua @@ -0,0 +1,260 @@ +--- A bucket to catch events in. **AceBucket-3.0** provides throttling of events that fire in bursts and +-- your addon only needs to know about the full burst. +-- +-- This Bucket implementation works as follows:\\ +-- Initially, no schedule is running, and its waiting for the first event to happen.\\ +-- The first event will start the bucket, and get the scheduler running, which will collect all +-- events in the given interval. When that interval is reached, the bucket is pushed to the +-- callback and a new schedule is started. When a bucket is empty after its interval, the scheduler is +-- stopped, and the bucket is only listening for the next event to happen, basically back in its initial state. +-- +-- In addition, the buckets collect information about the "arg1" argument of the events that fire, and pass those as a +-- table to your callback. This functionality was mostly designed for the UNIT_* events.\\ +-- The table will have the different values of "arg1" as keys, and the number of occurances as their value, e.g.\\ +-- { ["player"] = 2, ["target"] = 1, ["party1"] = 1 } +-- +-- **AceBucket-3.0** can be embeded into your addon, either explicitly by calling AceBucket: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 AceBucket itself.\\ +-- It is recommended to embed AceBucket, otherwise you'll have to specify a custom `self` on all calls you +-- make into AceBucket. +-- @usage +-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("BucketExample", "AceBucket-3.0") +-- +-- function MyAddon:OnEnable() +-- -- Register a bucket that listens to all the HP related events, +-- -- and fires once per second +-- self:RegisterBucketEvent({"UNIT_HEALTH", "UNIT_MAXHEALTH"}, 1, "UpdateHealth") +-- end +-- +-- function MyAddon:UpdateHealth(units) +-- if units.player then +-- print("Your HP changed!") +-- end +-- end +-- @class file +-- @name AceBucket-3.0.lua +-- @release $Id$ + +local MAJOR, MINOR = "AceBucket-3.0", 4 +local AceBucket, oldminor = LibStub:NewLibrary(MAJOR, MINOR) + +if not AceBucket then return end -- No Upgrade needed + +AceBucket.buckets = AceBucket.buckets or {} +AceBucket.embeds = AceBucket.embeds or {} + +-- the libraries will be lazyly bound later, to avoid errors due to loading order issues +local AceEvent, AceTimer + +-- Lua APIs +local tconcat = table.concat +local type, next, pairs, select = type, next, pairs, select +local tonumber, tostring, rawset = tonumber, tostring, rawset +local assert, loadstring, error = assert, loadstring, error + +local bucketCache = setmetatable({}, {__mode='k'}) + +--[[ + xpcall safecall implementation +]] +local xpcall = xpcall + +local function errorhandler(err) + return geterrorhandler()(err) +end + +local function safecall(func, ...) + if func then + return xpcall(func, errorhandler, ...) + end +end + +-- FireBucket ( bucket ) +-- +-- send the bucket to the callback function and schedule the next FireBucket in interval seconds +local function FireBucket(bucket) + local received = bucket.received + + -- we dont want to fire empty buckets + if next(received) ~= nil then + local callback = bucket.callback + if type(callback) == "string" then + safecall(bucket.object[callback], bucket.object, received) + else + safecall(callback, received) + end + + for k in pairs(received) do + received[k] = nil + end + + -- if the bucket was not empty, schedule another FireBucket in interval seconds + bucket.timer = AceTimer.ScheduleTimer(bucket, FireBucket, bucket.interval, bucket) + else -- if it was empty, clear the timer and wait for the next event + bucket.timer = nil + end +end + +-- BucketHandler ( event, arg1 ) +-- +-- callback func for AceEvent +-- stores arg1 in the received table, and schedules the bucket if necessary +local function BucketHandler(self, event, arg1) + if arg1 == nil then + arg1 = "nil" + end + + self.received[arg1] = (self.received[arg1] or 0) + 1 + + -- if we are not scheduled yet, start a timer on the interval for our bucket to be cleared + if not self.timer then + self.timer = AceTimer.ScheduleTimer(self, FireBucket, self.interval, self) + end +end + +-- RegisterBucket( event, interval, callback, isMessage ) +-- +-- event(string or table) - the event, or a table with the events, that this bucket listens to +-- interval(int) - time between bucket fireings +-- callback(func or string) - function pointer, or method name of the object, that gets called when the bucket is cleared +-- isMessage(boolean) - register AceEvent Messages instead of game events +local function RegisterBucket(self, event, interval, callback, isMessage) + -- try to fetch the librarys + if not AceEvent or not AceTimer then + AceEvent = LibStub:GetLibrary("AceEvent-3.0", true) + AceTimer = LibStub:GetLibrary("AceTimer-3.0", true) + if not AceEvent or not AceTimer then + error(MAJOR .. " requires AceEvent-3.0 and AceTimer-3.0", 3) + end + end + + if type(event) ~= "string" and type(event) ~= "table" then error("Usage: RegisterBucket(event, interval, callback): 'event' - string or table expected.", 3) end + if not callback then + if type(event) == "string" then + callback = event + else + error("Usage: RegisterBucket(event, interval, callback): cannot omit callback when event is not a string.", 3) + end + end + if not tonumber(interval) then error("Usage: RegisterBucket(event, interval, callback): 'interval' - number expected.", 3) end + if type(callback) ~= "string" and type(callback) ~= "function" then error("Usage: RegisterBucket(event, interval, callback): 'callback' - string or function or nil expected.", 3) end + if type(callback) == "string" and type(self[callback]) ~= "function" then error("Usage: RegisterBucket(event, interval, callback): 'callback' - method not found on target object.", 3) end + + local bucket = next(bucketCache) + if bucket then + bucketCache[bucket] = nil + else + bucket = { handler = BucketHandler, received = {} } + end + bucket.object, bucket.callback, bucket.interval = self, callback, tonumber(interval) + + local regFunc = isMessage and AceEvent.RegisterMessage or AceEvent.RegisterEvent + + if type(event) == "table" then + for _,e in pairs(event) do + regFunc(bucket, e, "handler") + end + else + regFunc(bucket, event, "handler") + end + + local handle = tostring(bucket) + AceBucket.buckets[handle] = bucket + + return handle +end + +--- Register a Bucket for an event (or a set of events) +-- @param event The event to listen for, or a table of events. +-- @param interval The Bucket interval (burst interval) +-- @param callback The callback function, either as a function reference, or a string pointing to a method of the addon object. +-- @return The handle of the bucket (for unregistering) +-- @usage +-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceBucket-3.0") +-- MyAddon:RegisterBucketEvent("BAG_UPDATE", 0.2, "UpdateBags") +-- +-- function MyAddon:UpdateBags() +-- -- do stuff +-- end +function AceBucket:RegisterBucketEvent(event, interval, callback) + return RegisterBucket(self, event, interval, callback, false) +end + +--- Register a Bucket for an AceEvent-3.0 addon message (or a set of messages) +-- @param message The message to listen for, or a table of messages. +-- @param interval The Bucket interval (burst interval) +-- @param callback The callback function, either as a function reference, or a string pointing to a method of the addon object. +-- @return The handle of the bucket (for unregistering) +-- @usage +-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceBucket-3.0") +-- MyAddon:RegisterBucketEvent("SomeAddon_InformationMessage", 0.2, "ProcessData") +-- +-- function MyAddon:ProcessData() +-- -- do stuff +-- end +function AceBucket:RegisterBucketMessage(message, interval, callback) + return RegisterBucket(self, message, interval, callback, true) +end + +--- Unregister any events and messages from the bucket and clear any remaining data. +-- @param handle The handle of the bucket as returned by RegisterBucket* +function AceBucket:UnregisterBucket(handle) + local bucket = AceBucket.buckets[handle] + if bucket then + AceEvent.UnregisterAllEvents(bucket) + AceEvent.UnregisterAllMessages(bucket) + + -- clear any remaining data in the bucket + for k in pairs(bucket.received) do + bucket.received[k] = nil + end + + if bucket.timer then + AceTimer.CancelTimer(bucket, bucket.timer) + bucket.timer = nil + end + + AceBucket.buckets[handle] = nil + -- store our bucket in the cache + bucketCache[bucket] = true + end +end + +--- Unregister all buckets of the current addon object (or custom "self"). +function AceBucket:UnregisterAllBuckets() + -- hmm can we do this more efficient? (it is not done often so shouldn't matter much) + for handle, bucket in pairs(AceBucket.buckets) do + if bucket.object == self then + AceBucket.UnregisterBucket(self, handle) + end + end +end + + + +-- embedding and embed handling +local mixins = { + "RegisterBucketEvent", + "RegisterBucketMessage", + "UnregisterBucket", + "UnregisterAllBuckets", +} + +-- Embeds AceBucket into the target object making the functions from the mixins list available on target:.. +-- @param target target object to embed AceBucket in +function AceBucket:Embed( target ) + for _, v in pairs( mixins ) do + target[v] = self[v] + end + self.embeds[target] = true + return target +end + +function AceBucket:OnEmbedDisable( target ) + target:UnregisterAllBuckets() +end + +for addon in pairs(AceBucket.embeds) do + AceBucket:Embed(addon) +end diff --git a/MythicPlusDrop/Libs/AceBucket-3.0/AceBucket-3.0.xml b/MythicPlusDrop/Libs/AceBucket-3.0/AceBucket-3.0.xml new file mode 100644 index 0000000..43c6bee --- /dev/null +++ b/MythicPlusDrop/Libs/AceBucket-3.0/AceBucket-3.0.xml @@ -0,0 +1,4 @@ + +