📄 applechronos.lua
字号:
--[[
--
-- Chronos
-- Keeper of Time
--
-- By Alexander Brazie
--
-- Chronos manages time. You can schedule a function to be called
-- in X seconds, with or without an id. You can request a timer,
-- which tracks the elapsed duration since the timer was started.
--
-- You can also create Tasks - functions which will perform a
-- complex operation over time, reducing system lag if used properly.
--
-- Please see below or see http://www.wowwiki.com/Chronos for details.
--
-- $LastChangedBy: AlexYoshi $
-- $Date: 2005-03-04 16:52:24 +0100 (Fri, 04 Mar 2005) $
-- $Rev: 927 $
--
--]]
CHRONOS_DEBUG = false;
CH_DEBUG = "CHRONOS_DEBUG";
CHRONOS_DEBUG_WARNINGS = false;
CH_DEBUG_T = "CHRONOS_DEBUG_WARNINGS";
-- Chronos Data
ChronosData = {
-- Initialize the startup time
elaspedTime = 0;
-- Initialize the VariablesLoaded flag
variablesLoaded = false;
-- Last ID
lastID = nil;
-- Initialize the Timers
timers = {};
-- Intialize the anonymous todo list
anonTodo = {};
-- Initialize the named todo list
namedTodo = {};
-- Initialize the perform-over-time task list
tasks = {};
};
-- Prototype Chronos
Chronos = {
-- Online or off
online = true;
-- Maximum items per frame
MAX_TASKS_PER_FRAME = 100;
-- Maximum steps per task
MAX_STEPS_PER_TASK = 300;
-- Maximum time delay per frame
MAX_TIME_PER_STEP = .3;
--[[
-- Scheduling functions
-- Written by Alexander
-- Original by Thott
--
-- Usage: Chronos.schedule(when,handler,arg1,arg2,etc)
--
-- After <when> seconds pass (values less than one and fractional values are
-- fine), handler is called with the specified arguments, i.e.:
-- handler(arg1,arg2,etc)
--
-- If you'd like to have something done every X seconds, reschedule
-- it each time in the handler.
--
-- Also, please note that there is a limit to the number of
-- scheduled tasks that can be performed per xml object at the
-- same time.
--]]
schedule = function (when,handler,...)
if ( not Chronos.online ) then
return;
end
-- Assign an id
local id = "";
if ( not this ) then
id = "Keybinding";
else
id = this:GetName();
end
if ( not id ) then
id = "_DEFAULT";
end
if ( not when ) then
--Sea.io.derror(CH_DEBUG_T, "Chronos Error Detection: ", id , " has sent no interval for this function. ", when );
return;
end
-- Ensure we're not looping ChronosFrame
if ( id == "ChronosFrame" and ChronosData.lastID ) then
id = ChronosData.lastID;
end
-- Create the new task
local todo = {};
todo.time = when + GetTime();
todo.handler = handler;
todo.args = arg;
-- Create a new table if one does not exist
if ( not ChronosData.anonTodo[id] ) then
ChronosData.anonTodo[id] = {};
end
-- Find the correct index within the frame's table
local i = 1;
while(ChronosData.anonTodo[id][i] and
ChronosData.anonTodo[id][i].time < todo.time) do
i = i + 1;
end
-- Add the new task for the current frame
table.insert(ChronosData.anonTodo[id],i,todo);
--
-- Ensure we don't have too many events
-- (For now, we just ignore it and pop a message)
--
if ( table.getn(ChronosData.anonTodo[id] ) > Chronos.MAX_TASKS_PER_FRAME
and not ChronosData.anonTodo[id].errorSent ) then
--Sea.io.derror(CH_DEBUG_T, "Chronos Error Detection: ", id , " has scheduled too many events. Please report this to the Developers, as it may cause your interface to lag. " );
ChronosData.anonTodo[id].errorSent = true;
end
-- Debug print
--MFC.IO.print(CH_DEBUG, "Scheduled ", handler," in ",when," seconds from ", id );
end;
--[[
-- Chronos.scheduleByName(name, delay, function, arg1, ... );
--
-- Same as Chronos.schedule, except it takes a schedule name argument.
-- Only one event can be scheduled with a given name at any one time.
-- Thus if one exists, and another one is scheduled, the first one
-- is deleted, then the second one added.
--
--]]
scheduleByName = function (name, when,handler,...)
if ( not Chronos.online ) then
return;
end
-- Assign an id
if ( not name ) then
--Sea.io.derror(CH_DEBUG_T,"Chronos Error Detection: No name specified to Chronos.scheduleByName");
return;
end
-- Ensure the table exists
if ( not ChronosData.namedTodo ) then
ChronosData.namedTodo = {};
end
-- Check if a named entry already exists
local i;
for i=1, table.getn(ChronosData.namedTodo), 1 do
if(ChronosData.namedTodo[i].name and ChronosData.namedTodo[i].name == name) then
entry = table.remove(ChronosData.namedTodo,i);
-- Allow you to do scheduleByName("name", 12);
if ( not handler ) then
handler = entry.handler;
end
break;
end
end
-- Create the new task
local todo = {};
todo.time = when + GetTime();
todo.handler = handler;
todo.args = arg;
todo.name = name;
-- Find the correct index within the frame's table
local i = 1;
while(ChronosData.namedTodo[i] and
ChronosData.namedTodo[i].time < todo.time) do
i = i + 1;
end
-- Add the new task for the current frame
table.insert(ChronosData.namedTodo,i,todo);
-- Debug print
--MFC.IO.print(CH_DEBUG, "Scheduled by name ",name, ",", handler," in ",when," seconds");
end;
--[[
-- unscheduleByName(name);
--
-- Removes an entry that was created with scheduleByName()
--
-- Args:
-- name - the name used
--
--]]
unscheduleByName = function(name)
if ( not Chronos.online ) then
return;
end
-- Assign an id
if ( not name ) then
--Sea.io.error("No name specified to Chronos.scheduleByName");
return;
end
-- Ensure the table exists
if ( not ChronosData.namedTodo ) then
return;
end
-- Check if a named entry already exists
local i;
for i=1, table.getn(ChronosData.namedTodo), 1 do
if(ChronosData.namedTodo[i].name and ChronosData.namedTodo[i].name == name) then
table.remove(ChronosData.namedTodo,i);
break;
end
end
-- Debug print
--MFC.IO.print(CH_DEBUG, "Cancelled scheduled timer of name ",name);
end;
--[[
-- isScheduledByName(name)
-- Returns the amount of time left if it is indeed scheduled by name!
--
-- returns:
-- number - time remaining
-- nil - not scheduled
--
--]]
isScheduledByName = function (name)
if ( not Chronos.online ) then
return;
end
-- Assign an id
if ( not name ) then
--Sea.io.error("No name specified to Chronos.isScheduledByName ", this:GetName());
return;
end
-- Ensure the table exists
if ( not ChronosData.namedTodo ) then
return;
end
-- Check if a named entry already exists
local i;
for i=1, table.getn(ChronosData.namedTodo), 1 do
if(ChronosData.namedTodo[i].name and ChronosData.namedTodo[i].name == name) then
return (ChronosData.namedTodo[i].time - GetTime());
end
end
-- Debug print
--MFC.IO.print(CH_DEBUG, "Did not find timer of name ",name);
end;
--[[
-- Chronos.startTimer([ID]);
-- Starts a timer on a particular
--
-- Args
-- ID - optional parameter to identify who is asking for a timer.
--
-- If ID does not exist, this:GetName() is used.
--
-- When you want to get the amount of time passed since startTimer(ID) is called,
-- call getTimer(ID) and it will return the number in seconds.
--
--]]
startTimer = function ( id )
if ( not Chronos.online ) then
return;
end
if ( not id ) then
id = this:GetName();
end
-- Create a table for this id's timers
if ( not ChronosData.timers[id] ) then
ChronosData.timers[id] = {};
end
-- Clear out an entry if the table is too big.
if ( table.getn(ChronosData.timers[id]) >= Chronos.MAX_TASKS_PER_FRAME ) then
table.remove(ChronosData.timers[id], 1 );
end
-- Add a new timer entry
table.insert(ChronosData.timers[id], GetTime() );
end;
--[[
-- endTimer([id]);
--
-- Ends the timer and returns the amount of time passed.
--
-- args:
-- id - ID for the timer. If not specified, then ID will
-- be this:GetName()
--
-- returns:
-- (Number delta, Number start, Number end)
--
-- delta - the amount of time passed in seconds.
-- start - the starting time
-- now - the time the endTimer was called.
--]]
endTimer = function( id )
if ( not Chronos.online ) then
return;
end
if ( not id ) then
id = this:GetName();
end
-- Create a table for this id's timers
if ( not ChronosData.timers[id] ) then
ChronosData.timers[id] = {};
end
-- Check to see if there is any timers started
if ( table.getn(ChronosData.timers[id]) == 0 ) then
return 0, GetTime(), GetTime();
end
-- Grab the last timer called
local startTime = table.remove ( ChronosData.timers[id] );
local now = GetTime();
return (now - startTime), startTime, now;
end;
--[[
-- getTimer([id]);
--
-- Gets the timer and returns the amount of time passed.
-- Does not terminate the timer.
--
-- args:
-- id - ID for the timer. If not specified, then ID will
-- be this:GetName()
--
-- returns:
-- (Number delta, Number start, Number end)
--
-- delta - the amount of time passed in seconds.
-- start - the starting time
-- now - the time the endTimer was called.
--]]
getTimer = function( id )
if ( not Chronos.online ) then
return;
end
if ( not id ) then
id = this:GetName();
end
-- Create a table for this id's timers
if ( not ChronosData.timers[id] ) then
ChronosData.timers[id] = {};
end
-- Check to see if there is any timers started
if ( table.getn(ChronosData.timers[id]) == 0 ) then
return 0, GetTime(), GetTime();
end
-- Grab the last timer called
local startTime = ChronosData.timers[id][table.getn(ChronosData.timers[id])];
local now = GetTime();
return (now - startTime), startTime, now;
end;
--[[
-- isTimerActive([id])
-- returns true if the timer exists.
--
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -