-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Libs: Embedded some dependencies for testing purposes
These are added by the CurseForge packager before creating a release archive, but that doesn't allow testing them locally or pinning their versions. It might be worth embedding some of the smaller dependencies that rarely ever change just to make things more reproducible. Example: LibStub is tiny and hasn't been updated in 7 years.
- Loading branch information
1 parent
68df836
commit 90edc79
Showing
31 changed files
with
4,795 additions
and
822 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
# Embedded libraries that are used for local testing only | ||
Libs/ | ||
*.CMD | ||
*.suo | ||
*.json | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||
..\FrameXML\UI.xsd"> | ||
<Script file="AceAddon-3.0.lua"/> | ||
</Ui> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: AceBucket-3.0.lua 1284 2022-09-25 09:15:30Z nevcairiel $ | ||
|
||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||
..\FrameXML\UI.xsd"> | ||
<Script file="AceBucket-3.0.lua"/> | ||
</Ui> |
Oops, something went wrong.