You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.3 KiB
93 lines
3.3 KiB
|
|
-- Callback Lib
|
|
-- Dependencies: lib/EventRegistration
|
|
|
|
local _, app = ...;
|
|
|
|
-- Global locals
|
|
local After, max, unpack = C_Timer.After, math.max, unpack;
|
|
|
|
-- Setup the callback tables since they are heavily used
|
|
local __callbacks = {};
|
|
local CallbackMethodCache = setmetatable({}, {
|
|
-- Gets or Creates the actual method which runs as a callback to execute the specified method
|
|
__index = function(t, method)
|
|
-- app.PrintDebug("CB:New",method)
|
|
local callbackMethod = function()
|
|
local args = __callbacks[method];
|
|
__callbacks[method] = nil;
|
|
-- callback with args/void
|
|
if args ~= true then
|
|
-- app.PrintDebug("CB:Run/args",method,unpack(args))
|
|
method(unpack(args));
|
|
else
|
|
-- app.PrintDebug("CB:Run/void",method)
|
|
method();
|
|
end
|
|
-- app.PrintDebug("CB:Done",method)
|
|
end;
|
|
t[method] = callbackMethod;
|
|
return callbackMethod;
|
|
end
|
|
});
|
|
local function Callback(method, ...)
|
|
-- Triggers a timer callback method to run on the next game frame with the provided params; the method can only be set to run once per frame
|
|
if not __callbacks[method] then
|
|
__callbacks[method] = ... and {...} or true;
|
|
After(0, CallbackMethodCache[method]);
|
|
-- else app.PrintDebug("CB:Skip",method)
|
|
end
|
|
end
|
|
local function DelayedCallback(method, delaySec, ...)
|
|
-- Triggers a timer callback method to run after the provided number of seconds with the provided params; the method can only be set to run once per delay
|
|
if not __callbacks[method] then
|
|
__callbacks[method] = ... and {...} or true;
|
|
After(max(0, delaySec or 0), CallbackMethodCache[method]);
|
|
-- else app.PrintDebug("DCB:Skip",method)
|
|
end
|
|
end
|
|
|
|
-- Callbacks to trigger after combat has ended!
|
|
local __combatcallbacks = {};
|
|
local InCombatLockdown = InCombatLockdown;
|
|
local function AfterCombatCallback(method, ...)
|
|
-- Triggers a timer callback method to run on the next game frame or following combat if in combat currently with the provided params; the method can only be set to run once per frame
|
|
if not InCombatLockdown() then Callback(method, ...); return; end
|
|
if not __callbacks[method] then
|
|
__callbacks[method] = ... and {...} or true;
|
|
-- TODO: convert to a CallbackRunner?
|
|
__combatcallbacks[#__combatcallbacks + 1] = CallbackMethodCache[method];
|
|
app:RegisterEvent("PLAYER_REGEN_ENABLED");
|
|
-- else app.PrintDebug("ACCB:Skip",method)
|
|
end
|
|
end
|
|
local function AfterCombatOrDelayedCallback(method, delaySec, ...)
|
|
-- Triggers a timer callback method to run either when current combat ends, or after the provided delay; the method can only be set to run once until it has been run
|
|
if InCombatLockdown() then
|
|
AfterCombatCallback(method, ...);
|
|
else
|
|
DelayedCallback(method, delaySec, ...);
|
|
end
|
|
end
|
|
app:RegisterFuncEvent("PLAYER_REGEN_ENABLED", function()
|
|
app:UnregisterEvent("PLAYER_REGEN_ENABLED");
|
|
-- print("PLAYER_REGEN_ENABLED:Begin")
|
|
local callbacks = __combatcallbacks;
|
|
local count = #callbacks;
|
|
if count > 0 then
|
|
__combatcallbacks = {};
|
|
for i=count,1,-1 do
|
|
-- print(" callback:",i)
|
|
callbacks[i]();
|
|
end
|
|
end
|
|
-- print("PLAYER_REGEN_ENABLED:End")
|
|
end)
|
|
|
|
-- External API
|
|
app.CallbackHandlers = {
|
|
Callback = Callback,
|
|
DelayedCallback = DelayedCallback,
|
|
AfterCombatCallback = AfterCombatCallback,
|
|
AfterCombatOrDelayedCallback = AfterCombatOrDelayedCallback
|
|
};
|