Add SetInterval to Timer.
Add tests for Timer. This was SVN commit r8678.
This commit is contained in:
parent
fe5c7cb978
commit
333492b4a9
@ -10,11 +10,54 @@ Timer.prototype.Init = function()
|
||||
this.timers = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns time since the start of the game, in integer milliseconds.
|
||||
*/
|
||||
Timer.prototype.GetTime = function()
|
||||
{
|
||||
return this.time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new timer, which will call the 'funcname' method with arguments (data, lateness)
|
||||
* on the 'iid' component of the 'ent' entity, after at least 'time' milliseconds.
|
||||
* 'lateness' is how late the timer is executed after the specified time (in milliseconds).
|
||||
* Returns a non-zero id that can be passed to CancelTimer.
|
||||
*/
|
||||
Timer.prototype.SetTimeout = function(ent, iid, funcname, time, data)
|
||||
{
|
||||
var id = ++this.id;
|
||||
this.timers[id] = [ent, iid, funcname, this.time + time, 0, data];
|
||||
return id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new repeating timer, which will call the 'funcname' method with arguments (data, lateness)
|
||||
* on the 'iid' component of the 'ent' entity, after at least 'time' milliseconds
|
||||
* and then every 'repeattime' milliseconds thereafter.
|
||||
* It will run multiple times per simulation turn if necessary.
|
||||
* 'repeattime' must be non-zero.
|
||||
* 'lateness' is how late the timer is executed after the specified time (in milliseconds).
|
||||
* Returns a non-zero id that can be passed to CancelTimer.
|
||||
*/
|
||||
Timer.prototype.SetInterval = function(ent, iid, funcname, time, repeattime, data)
|
||||
{
|
||||
if (typeof repeattime != "number" || !(repeattime > 0))
|
||||
error("Invalid repeattime to SetInterval of "+funcname);
|
||||
var id = ++this.id;
|
||||
this.timers[id] = [ent, iid, funcname, this.time + time, repeattime, data];
|
||||
return id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancels an existing timer that was created with SetTimeout/SetInterval.
|
||||
*/
|
||||
Timer.prototype.CancelTimer = function(id)
|
||||
{
|
||||
delete this.timers[id];
|
||||
};
|
||||
|
||||
|
||||
Timer.prototype.OnUpdate = function(msg)
|
||||
{
|
||||
var dt = Math.round(msg.turnLength * 1000);
|
||||
@ -29,8 +72,10 @@ Timer.prototype.OnUpdate = function(msg)
|
||||
if (this.timers[id][3] <= this.time)
|
||||
run.push(id);
|
||||
}
|
||||
for each (var id in run)
|
||||
for (var i = 0; i < run.length; ++i)
|
||||
{
|
||||
var id = run[i];
|
||||
|
||||
var t = this.timers[id];
|
||||
if (!t)
|
||||
continue; // an earlier timer might have cancelled this one, so skip it
|
||||
@ -41,32 +86,27 @@ Timer.prototype.OnUpdate = function(msg)
|
||||
|
||||
try {
|
||||
var lateness = this.time - t[3];
|
||||
cmp[t[2]](t[4], lateness);
|
||||
cmp[t[2]](t[5], lateness);
|
||||
} catch (e) {
|
||||
var stack = e.stack.trimRight().replace(/^/mg, ' '); // indent the stack trace
|
||||
error("Error in timer on entity "+t[0]+", IID "+t[1]+", function "+t[2]+": "+e+"\n"+stack+"\n");
|
||||
}
|
||||
delete this.timers[id];
|
||||
|
||||
// Handle repeating timers
|
||||
if (t[4])
|
||||
{
|
||||
// Add the repeat time to the execution time
|
||||
t[3] += t[4];
|
||||
// Add it to the list to get re-executed if it's soon enough
|
||||
if (t[3] <= this.time)
|
||||
run.push(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-repeating time - delete it
|
||||
delete this.timers[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new timer, which will call the 'funcname' method with arguments (data, lateness)
|
||||
* on the 'iid' component of the 'ent' entity, after at least 'time' milliseconds.
|
||||
* 'lateness' is how late the timer is executed after the specified time (in milliseconds).
|
||||
* Returns a non-zero id that can be passed to CancelTimer.
|
||||
*/
|
||||
Timer.prototype.SetTimeout = function(ent, iid, funcname, time, data)
|
||||
{
|
||||
var id = ++this.id;
|
||||
this.timers[id] = [ent, iid, funcname, this.time + time, data];
|
||||
return id;
|
||||
};
|
||||
|
||||
Timer.prototype.CancelTimer = function(id)
|
||||
{
|
||||
delete this.timers[id];
|
||||
};
|
||||
|
||||
Engine.RegisterComponentType(IID_Timer, "Timer", Timer);
|
||||
|
||||
|
@ -0,0 +1,80 @@
|
||||
Engine.LoadComponentScript("interfaces/Timer.js");
|
||||
Engine.LoadComponentScript("Timer.js");
|
||||
|
||||
Engine.RegisterInterface("Test");
|
||||
|
||||
var cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer");
|
||||
|
||||
var fired = [];
|
||||
|
||||
AddMock(10, IID_Test, {
|
||||
Callback: function(data, lateness) {
|
||||
fired.push([data, lateness]);
|
||||
}
|
||||
});
|
||||
|
||||
var cancelId;
|
||||
AddMock(20, IID_Test, {
|
||||
Callback: function(data, lateness) {
|
||||
fired.push([data, lateness]);
|
||||
cmpTimer.CancelTimer(cancelId);
|
||||
}
|
||||
});
|
||||
|
||||
TS_ASSERT_EQUALS(cmpTimer.GetTime(), 0);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 1/3 });
|
||||
|
||||
TS_ASSERT_EQUALS(cmpTimer.GetTime(), 333);
|
||||
|
||||
cmpTimer.SetTimeout(10, IID_Test, "Callback", 1000, "a");
|
||||
cmpTimer.SetTimeout(10, IID_Test, "Callback", 1200, "b");
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 0.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, []);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 0.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["a",0]]);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 0.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["a",0], ["b",300]]);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 0.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["a",0], ["b",300]]);
|
||||
|
||||
fired = [];
|
||||
|
||||
var c = cmpTimer.SetTimeout(10, IID_Test, "Callback", 1000, "c");
|
||||
var d = cmpTimer.SetTimeout(10, IID_Test, "Callback", 1000, "d");
|
||||
var e = cmpTimer.SetTimeout(10, IID_Test, "Callback", 1000, "e");
|
||||
cmpTimer.CancelTimer(d);
|
||||
cmpTimer.OnUpdate({ "turnLength": 1.0 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["c",0], ["e",0]]);
|
||||
|
||||
fired = [];
|
||||
|
||||
var r = cmpTimer.SetInterval(10, IID_Test, "Callback", 500, 1000, "r");
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 0.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["r",0]]);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 0.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["r",0]]);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 0.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["r",0], ["r",0]]);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 3.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["r",0], ["r",0], ["r",2500], ["r",1500], ["r",500]]);
|
||||
|
||||
cmpTimer.CancelTimer(r);
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 3.5 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["r",0], ["r",0], ["r",2500], ["r",1500], ["r",500]]);
|
||||
|
||||
fired = [];
|
||||
|
||||
cancelId = cmpTimer.SetInterval(20, IID_Test, "Callback", 500, 1000, "s");
|
||||
|
||||
cmpTimer.OnUpdate({ "turnLength": 3.0 });
|
||||
TS_ASSERT_UNEVAL_EQUALS(fired, [["s",2500]]);
|
Loading…
Reference in New Issue
Block a user