2015-01-25 20:10:51 +01:00
|
|
|
'use strict';
|
|
|
|
/*global events, module, require, __plugin, setInterval, clearInterval, setTimeout, addUnloadHandler*/
|
|
|
|
var utils = require('utils');
|
|
|
|
/************************************************************************
|
|
|
|
## The at Module
|
|
|
|
|
|
|
|
The at module provides a single function `at()` which can be used to schedule
|
|
|
|
repeating (or non-repeating) tasks to be done at a particular time.
|
|
|
|
|
|
|
|
### at() function
|
|
|
|
|
|
|
|
The utils.at() function will perform a given task at a given time in the
|
|
|
|
(minecraft) day.
|
|
|
|
|
|
|
|
#### Parameters
|
|
|
|
|
|
|
|
* time24hr : The time in 24hr form - e.g. 9:30 in the morning is '09:30' while
|
|
|
|
9:30 pm is '21:30', midnight is '00:00' and midday is '12:00'
|
|
|
|
* callback : A javascript function which will be invoked at the given time.
|
|
|
|
* worlds : (optional) An array of worlds. Each world has its own clock. If no array of worlds is specified, all the server's worlds are used.
|
|
|
|
* repeat : (optional) true or false, default is true (repeat the task every day)
|
|
|
|
|
|
|
|
#### Example
|
|
|
|
|
|
|
|
To warn players when night is approaching:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
var utils = require('utils'),
|
|
|
|
at = require('at');
|
|
|
|
function warning(){
|
|
|
|
utils.players(function( player ) {
|
|
|
|
echo( player, 'The night is dark and full of terrors!' );
|
|
|
|
});
|
|
|
|
}
|
|
|
|
at('19:00', warning);
|
|
|
|
```
|
|
|
|
To run a task only once at the next given time:
|
|
|
|
```javascript
|
|
|
|
var utils = require('utils'),
|
|
|
|
at = require('at');
|
|
|
|
function wakeup(){
|
|
|
|
utils.players(function( player ) {
|
|
|
|
echo( player, "Wake Up Folks!" );
|
|
|
|
});
|
|
|
|
}
|
|
|
|
at('06:00', wakeup, null, false);
|
|
|
|
```
|
|
|
|
|
|
|
|
***/
|
2015-03-01 14:52:23 +01:00
|
|
|
var SECOND = 1000;
|
|
|
|
var POLLING_INTERVAL = 3 * SECOND; // this is probably precise enough
|
|
|
|
|
2015-01-25 20:10:51 +01:00
|
|
|
function at(time24hr, callback, pWorlds, repeat) {
|
2015-03-01 14:52:23 +01:00
|
|
|
if (arguments.length === 0){
|
|
|
|
// TODO: Document this behaviour
|
|
|
|
console.log(tasksToString());
|
|
|
|
return;
|
|
|
|
}
|
2015-01-25 20:10:51 +01:00
|
|
|
var timeParts = time24hr.split( ':' );
|
|
|
|
var timeMins = (timeParts[0] * 60) + (timeParts[1] * 1);
|
2015-03-01 00:54:59 +01:00
|
|
|
if (!pWorlds || pWorlds === undefined ) {
|
2015-01-25 20:10:51 +01:00
|
|
|
pWorlds = utils.worlds();
|
|
|
|
}
|
|
|
|
if (repeat === undefined){
|
|
|
|
repeat = true;
|
|
|
|
}
|
|
|
|
utils.foreach( pWorlds, function ( world ) {
|
|
|
|
atAddTask( timeMins, callback, world, repeat);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
var atTasks = {};
|
2015-03-01 14:52:23 +01:00
|
|
|
|
|
|
|
function tasksToString(){
|
|
|
|
var result = '';
|
|
|
|
for (var world in atTasks){
|
|
|
|
result += 'world: ' + world +'\n';
|
|
|
|
for (var time in atTasks[world]){
|
|
|
|
var scheduledFuncs = atTasks[world][time];
|
|
|
|
for (var i = 0;i < scheduledFuncs.length; i++){
|
|
|
|
result += ' ' + time + ': ' + scheduledFuncs[i].constructor + '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result += '(current world time: ' + utils.time24(world) + ')\n';
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2015-01-25 20:10:51 +01:00
|
|
|
/*
|
|
|
|
constructs a function which will be called every x ticks to
|
|
|
|
track the schedule for a given world
|
|
|
|
*/
|
|
|
|
function atMonitorFactory(world){
|
|
|
|
var worldName = ''+ world.name;
|
|
|
|
var lastRun = null;
|
2015-03-01 14:52:23 +01:00
|
|
|
|
2015-03-01 00:54:59 +01:00
|
|
|
return function atMonitorForWorld(){
|
|
|
|
var timeMins = utils.time24(world);
|
2015-01-25 20:10:51 +01:00
|
|
|
if (timeMins === lastRun){
|
|
|
|
return;
|
|
|
|
}
|
2015-03-01 14:52:23 +01:00
|
|
|
if (lastRun === null ){
|
|
|
|
lastRun = timeMins - 1;
|
|
|
|
}else {
|
|
|
|
lastRun = lastRun % 1440;
|
|
|
|
}
|
2015-01-25 20:10:51 +01:00
|
|
|
var worldSchedule = atTasks[worldName];
|
|
|
|
if (!worldSchedule){
|
|
|
|
return;
|
|
|
|
}
|
2015-03-01 14:52:23 +01:00
|
|
|
while ( lastRun > timeMins ? (lastRun <= 1440) : ( lastRun < timeMins ) ){
|
|
|
|
|
|
|
|
var tasks = worldSchedule[lastRun++];
|
|
|
|
if (!tasks){
|
|
|
|
continue;
|
2015-01-25 20:10:51 +01:00
|
|
|
}
|
2015-03-01 14:52:23 +01:00
|
|
|
utils.foreach(tasks, function(task, i){
|
|
|
|
if (!task){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setTimeout(task.callback.bind(null, timeMins, world), 1);
|
|
|
|
if (!task.repeat){
|
|
|
|
tasks[i] = null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-01-25 20:10:51 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
function atAddTask( timeMins, callback, world, repeat){
|
|
|
|
var worldName = ''+world.name;
|
|
|
|
if (!atTasks[worldName]){
|
|
|
|
atTasks[worldName] = {};
|
|
|
|
}
|
|
|
|
if (!atTasks[worldName][timeMins]){
|
|
|
|
atTasks[worldName][timeMins] = [];
|
|
|
|
}
|
|
|
|
atTasks[worldName][timeMins].push({callback: callback, repeat: repeat});
|
|
|
|
}
|
|
|
|
var atMonitors = [];
|
|
|
|
function onLoadStartMonitor(event){
|
2015-03-01 14:52:23 +01:00
|
|
|
var monitor = setInterval( atMonitorFactory(event.world), POLLING_INTERVAL);
|
2015-01-25 20:10:51 +01:00
|
|
|
atMonitors.push( monitor );
|
|
|
|
}
|
|
|
|
if (__plugin.canary){
|
|
|
|
events.loadWorld( onLoadStartMonitor );
|
|
|
|
}
|
|
|
|
if (__plugin.bukkit){
|
|
|
|
events.worldLoad( onLoadStartMonitor );
|
|
|
|
}
|
|
|
|
|
|
|
|
addUnloadHandler(function(){
|
|
|
|
utils.foreach(atMonitors, function(atInterval){
|
|
|
|
clearInterval(atInterval);
|
|
|
|
});
|
|
|
|
});
|
2015-03-01 00:54:59 +01:00
|
|
|
|
|
|
|
module.exports = at;
|