LCOV - code coverage report
Current view: top level - simulation/components - Timer.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 44 47 93.6 %
Date: 2023-04-02 12:52:40 Functions: 9 9 100.0 %

          Line data    Source code
       1             : function Timer() {}
       2             : 
       3          16 : Timer.prototype.Schema =
       4             :         "<a:component type='system'/><empty/>";
       5             : 
       6          16 : Timer.prototype.Init = function()
       7             : {
       8          45 :         this.id = 0;
       9          45 :         this.time = 0;
      10          45 :         this.timers = new Map();
      11          45 :         this.turnLength = 0;
      12             : };
      13             : 
      14             : /**
      15             :  * @returns {number} - The elapsed time in milliseconds since the game was started.
      16             :  */
      17          16 : Timer.prototype.GetTime = function()
      18             : {
      19           9 :         return this.time;
      20             : };
      21             : 
      22             : /**
      23             :  * @returns {number} - The duration of the latest turn in milliseconds.
      24             :  */
      25          16 : Timer.prototype.GetLatestTurnLength = function()
      26             : {
      27           1 :         return this.turnLength;
      28             : };
      29             : 
      30             : /**
      31             :  * Create a new timer, which will call the 'funcname' method with arguments (data, lateness)
      32             :  * on the 'iid' component of the 'ent' entity, after at least 'time' milliseconds.
      33             :  * 'lateness' is how late the timer is executed after the specified time (in milliseconds).
      34             :  * @param {number} ent - The entity id to which the timer will be assigned to.
      35             :  * @param {number} iid - The component iid of the timer.
      36             :  * @param {string} funcname - The name of the function to be called in the component.
      37             :  * @param {number} time - The delay before running the function for the first time.
      38             :  * @param {any} data - The data to pass to the function.
      39             :  * @returns {number} - A non-zero id that can be passed to CancelTimer.
      40             :  */
      41          16 : Timer.prototype.SetTimeout = function(ent, iid, funcname, time, data)
      42             : {
      43          11 :         return this.SetInterval(ent, iid, funcname, time, 0, data);
      44             : };
      45             : 
      46             : /**
      47             :  * Create a new repeating timer, which will call the 'funcname' method with arguments (data, lateness)
      48             :  * on the 'iid' component of the 'ent' entity, after at least 'time' milliseconds.
      49             :  * 'lateness' is how late the timer is executed after the specified time (in milliseconds)
      50             :  * and then every 'repeattime' milliseconds thereafter.
      51             :  * @param {number} ent - The entity the timer will be assigned to.
      52             :  * @param {number} iid - The component iid of the timer.
      53             :  * @param {string} funcname - The name of the function to be called in the component.
      54             :  * @param {number} time - The delay before running the function for the first time.
      55             :  * @param {number} repeattime - If non-zero, the interval between each execution of the function.
      56             :  * @param {any} data - The data to pass to the function.
      57             :  * @returns {number} - A non-zero id that can be passed to CancelTimer.
      58             :  */
      59          16 : Timer.prototype.SetInterval = function(ent, iid, funcname, time, repeattime, data)
      60             : {
      61          80 :         let id = ++this.id;
      62             : 
      63          80 :         this.timers.set(id, {
      64             :                 "entity": ent,
      65             :                 "iid": iid,
      66             :                 "functionName": funcname,
      67             :                 "time": this.time + time,
      68             :                 "repeatTime": repeattime,
      69             :                 "data": data
      70             :         });
      71             : 
      72          80 :         return id;
      73             : };
      74             : 
      75             : /**
      76             :  * Updates the repeat time of a timer.
      77             :  * Note that this will take only effect after the next update.
      78             :  *
      79             :  * @param {number} timerID - The timer to update.
      80             :  * @param {number} newRepeatTime - The new repeat time to use.
      81             :  */
      82          16 : Timer.prototype.UpdateRepeatTime = function(timerID, newRepeatTime)
      83             : {
      84           3 :         let timer = this.timers.get(timerID);
      85           3 :         if (timer)
      86           3 :                 this.timers.set(timerID, {
      87             :                         "entity": timer.entity,
      88             :                         "iid": timer.iid,
      89             :                         "functionName": timer.functionName,
      90             :                         "time": timer.time,
      91             :                         "repeatTime": newRepeatTime,
      92             :                         "data": timer.data
      93             :                 });
      94             : };
      95             : 
      96             : /**
      97             :  * Cancels an existing timer that was created with SetTimeout/SetInterval.
      98             :  * @param {number} id - The timer's ID returned by either SetTimeout or SetInterval.
      99             :  */
     100          16 : Timer.prototype.CancelTimer = function(id)
     101             : {
     102          52 :         this.timers.delete(id);
     103             : };
     104             : 
     105             : /**
     106             :  * @param {{ "turnLength": number }} msg - A message containing the turn length in seconds.
     107             :  */
     108          16 : Timer.prototype.OnUpdate = function(msg)
     109             : {
     110         206 :         this.turnLength = Math.round(msg.turnLength * 1000);
     111         206 :         this.time += this.turnLength;
     112             : 
     113             :         // Collect the timers that need to run
     114             :         // (We do this in two stages to avoid deleting from the timer list while
     115             :         // we're in the middle of iterating through it)
     116         206 :         let run = [];
     117         206 :         for (let [id, timer] of this.timers)
     118         168 :                 if (timer.time <= this.time)
     119         156 :                         run.push(id);
     120             : 
     121         206 :         for (let id of run)
     122             :         {
     123         516 :                 let timer = this.timers.get(id);
     124             : 
     125             :                 // An earlier timer might have cancelled this one, so skip it
     126         516 :                 if (!timer)
     127           8 :                         continue;
     128             : 
     129             :                 // The entity was probably destroyed; clean up the timer
     130         508 :                 let timerTargetComponent = Engine.QueryInterface(timer.entity, timer.iid);
     131         508 :                 if (!timerTargetComponent)
     132             :                 {
     133           0 :                         this.timers.delete(id);
     134           0 :                         continue;
     135             :                 }
     136             : 
     137         508 :                 try
     138             :                 {
     139         508 :                         timerTargetComponent[timer.functionName](timer.data, this.time - timer.time);
     140             :                 }
     141             :                 catch (e)
     142             :                 {
     143           0 :                         error(
     144             :                                 "Error in timer on entity " + timer.entity + ", " +
     145             :                                 "IID" + timer.iid + ", " +
     146             :                                 "function " + timer.functionName + ": " +
     147             :                                 e + "\n" +
     148             :                                 // Indent the stack trace
     149             :                                 e.stack.trimRight().replace(/^/mg, '  ') + "\n");
     150             :                 }
     151             : 
     152         508 :                 if (!timer.repeatTime)
     153             :                 {
     154          11 :                         this.timers.delete(id);
     155          11 :                         continue;
     156             :                 }
     157             : 
     158         497 :                 timer.time += timer.repeatTime;
     159             : 
     160             :                 // Add it to the list to get re-executed if it's soon enough
     161         497 :                 if (timer.time <= this.time)
     162         360 :                         run.push(id);
     163             :         }
     164             : };
     165             : 
     166          16 : Engine.RegisterSystemComponentType(IID_Timer, "Timer", Timer);

Generated by: LCOV version 1.14