From 8c690452e756c30bd0cbc49535ae8f1b4d44f6bb Mon Sep 17 00:00:00 2001 From: walterhiggins Date: Fri, 24 Jan 2014 23:38:56 +0000 Subject: [PATCH] Added experimental LCDGameClock --- src/main/javascript/lib/command.js | 56 ++-- src/main/javascript/lib/plugin.js | 134 ++++----- src/main/javascript/lib/require.js | 6 +- src/main/javascript/modules/sc-mqtt.js | 156 +++++----- src/main/javascript/plugins/alias/alias.js | 272 +++++++++--------- .../plugins/drone/contrib/lcd-clock.js | 75 +++++ 6 files changed, 390 insertions(+), 309 deletions(-) create mode 100644 src/main/javascript/plugins/drone/contrib/lcd-clock.js diff --git a/src/main/javascript/lib/command.js b/src/main/javascript/lib/command.js index 17928af..61e0c60 100644 --- a/src/main/javascript/lib/command.js +++ b/src/main/javascript/lib/command.js @@ -8,40 +8,40 @@ var _cmdInterceptors = []; execute a JSP command. */ var executeCmd = function(args, player){ - if (args.length === 0) - throw new Error('Usage: jsp command-name command-parameters'); - var name = args[0]; - var cmd = _commands[name]; - if (typeof cmd === 'undefined'){ - // it's not a global command - pass it on to interceptors - var intercepted = false; - for (var i = 0;i < _cmdInterceptors.length;i++){ - if (_cmdInterceptors[i](args,player)) - intercepted = true; - } - if (!intercepted) - console.warn('Command %s is not recognised',name); - }else{ - var result = null; - try { - result = cmd.callback(args.slice(1),player); - }catch (e){ - console.error('Error while trying to execute command: ' + JSON.stringify(args)); - throw e; - } - return result; + if (args.length === 0) + throw new Error('Usage: jsp command-name command-parameters'); + var name = args[0]; + var cmd = _commands[name]; + if (typeof cmd === 'undefined'){ + // it's not a global command - pass it on to interceptors + var intercepted = false; + for (var i = 0;i < _cmdInterceptors.length;i++){ + if (_cmdInterceptors[i](args,player)) + intercepted = true; } + if (!intercepted) + console.warn('Command %s is not recognised',name); + }else{ + var result = null; + try { + result = cmd.callback(args.slice(1),player); + }catch (e){ + console.error('Error while trying to execute command: ' + JSON.stringify(args)); + throw e; + } + return result; + } }; /* define a new JSP command. */ var defineCmd = function(name, func, options, intercepts) { - if (typeof options == 'undefined') - options = []; - _commands[name] = {callback: func, options: options}; - if (intercepts) - _cmdInterceptors.push(func); - return func; + if (typeof options == 'undefined') + options = []; + _commands[name] = {callback: func, options: options}; + if (intercepts) + _cmdInterceptors.push(func); + return func; }; exports.command = defineCmd; exports.commands = _commands; diff --git a/src/main/javascript/lib/plugin.js b/src/main/javascript/lib/plugin.js index fe493f6..a85cbb3 100644 --- a/src/main/javascript/lib/plugin.js +++ b/src/main/javascript/lib/plugin.js @@ -1,8 +1,8 @@ 'use strict'; -var console = require('./console'); -var File = java.io.File; -var FileWriter = java.io.FileWriter; -var PrintWriter = java.io.PrintWriter; +var console = require('./console'), + File = java.io.File, + FileWriter = java.io.FileWriter, + PrintWriter = java.io.PrintWriter; /* plugin management */ @@ -10,22 +10,22 @@ var _plugins = {}; var _plugin = function(/* String */ moduleName, /* Object */ moduleObject, isPersistent) { - // - // don't load plugin more than once - // - if (typeof _plugins[moduleName] != "undefined") - return _plugins[moduleName].module; + // + // don't load plugin more than once + // + if (typeof _plugins[moduleName] != "undefined") + return _plugins[moduleName].module; - var pluginData = {persistent: isPersistent, module: moduleObject}; - if (typeof moduleObject.store == 'undefined') - moduleObject.store = {}; + var pluginData = {persistent: isPersistent, module: moduleObject}; + if (typeof moduleObject.store == 'undefined') + moduleObject.store = {}; - _plugins[moduleName] = pluginData; + _plugins[moduleName] = pluginData; - if (isPersistent){ - moduleObject.store = persist(moduleName, moduleObject.store); - } - return moduleObject; + if (isPersistent){ + moduleObject.store = persist(moduleName, moduleObject.store); + } + return moduleObject; }; exports.plugin = _plugin; @@ -36,59 +36,59 @@ var dataDir = null; exports.autoload = function(dir) { - scriptCraftDir = dir; - pluginDir = new File(dir, "plugins"); - dataDir = new File(dir, "data"); + scriptCraftDir = dir; + pluginDir = new File(dir, "plugins"); + dataDir = new File(dir, "data"); - var _canonize = function(file){ - return '' + file.canonicalPath.replaceAll("\\\\","/"); - }; - /* - recursively walk the given directory and return a list of all .js files - */ - var _listSourceFiles = function(store,dir) - { - var files = dir.listFiles(); - if (!files) - return; - for (var i = 0;i < files.length; i++) { - var file = files[i]; - if (file.isDirectory()){ - _listSourceFiles(store,file); - }else{ - if ( file.canonicalPath.endsWith('.js') ){ - store.push(file); - } - } + var _canonize = function(file){ + return '' + file.canonicalPath.replaceAll("\\\\","/"); + }; + /* + recursively walk the given directory and return a list of all .js files + */ + var _listSourceFiles = function(store,dir) + { + var files = dir.listFiles(); + if (!files) + return; + for (var i = 0;i < files.length; i++) { + var file = files[i]; + if (file.isDirectory()){ + _listSourceFiles(store,file); + }else{ + if ( file.canonicalPath.endsWith('.js') ){ + store.push(file); } - }; - /* - Reload all of the .js files in the given directory - */ - var _reload = function(pluginDir) - { - var sourceFiles = []; - _listSourceFiles(sourceFiles,pluginDir); + } + } + }; + /* + Reload all of the .js files in the given directory + */ + var _reload = function(pluginDir) + { + var sourceFiles = []; + _listSourceFiles(sourceFiles,pluginDir); - var len = sourceFiles.length; - if (config.verbose) - console.info(len + ' scriptcraft plugins found.'); - for (var i = 0;i < len; i++){ - var pluginPath = _canonize(sourceFiles[i]); - var module = {}; - try { - module = require(pluginPath); - for (var property in module){ - /* - all exports in plugins become global - */ - global[property] = module[property]; - } - }catch (e){ - - } + var len = sourceFiles.length; + if (config.verbose) + console.info(len + ' scriptcraft plugins found.'); + for (var i = 0;i < len; i++){ + var pluginPath = _canonize(sourceFiles[i]); + var module = {}; + try { + module = require(pluginPath); + for (var property in module){ + /* + all exports in plugins become global + */ + global[property] = module[property]; } - }; - _reload(pluginDir); + }catch (e){ + + } + } + }; + _reload(pluginDir); }; diff --git a/src/main/javascript/lib/require.js b/src/main/javascript/lib/require.js index 1e3d2ba..64e39e4 100644 --- a/src/main/javascript/lib/require.js +++ b/src/main/javascript/lib/require.js @@ -174,13 +174,13 @@ When resolving module names to file paths, ScriptCraft uses the following rules. wph 20131215 Experimental */ var _loadedModules = {}; - + var _format = java.lang.String.format; var _require = function(parentFile, path) { var file = resolveModuleToFile(path, parentFile); if (!file){ - var errMsg = '' + java.lang.String.format("require() failed to find matching file for module '%s' " + - "in working directory '%s' ", [path, parentFile.canonicalPath]); + var errMsg = '' + _format("require() failed to find matching file for module '%s' " + + "in working directory '%s' ", [path, parentFile.canonicalPath]); if (! ( (''+path).match(/^\./) )){ errMsg = errMsg + ' and not found in paths ' + JSON.stringify(modulePaths); } diff --git a/src/main/javascript/modules/sc-mqtt.js b/src/main/javascript/modules/sc-mqtt.js index 4287523..80b35ab 100644 --- a/src/main/javascript/modules/sc-mqtt.js +++ b/src/main/javascript/modules/sc-mqtt.js @@ -1,3 +1,4 @@ +'use strict'; /************************************************************************* ## sc-mqtt module @@ -62,83 +63,98 @@ library. ***/ var MISSING_MQTT = '\nMissing class org.walterhiggins.scriptcraft.ScriptCraftMqttCallback.\n' + - 'Make sure sc-mqtt.jar is in the classpath.\n' + - 'See http://github.com/walterhiggins/scriptcraft-extras-mqtt for details.\n'; + 'Make sure sc-mqtt.jar is in the classpath.\n' + + 'See http://github.com/walterhiggins/scriptcraft-extras-mqtt for details.\n'; function Client(brokerUrl, clientId){ - var Callback = org.walterhiggins.scriptcraft.ScriptCraftMqttCallback; - var MqttClient = org.eclipse.paho.client.mqttv3.MqttClient; + var Callback = org.walterhiggins.scriptcraft.ScriptCraftMqttCallback; + var MqttClient = org.eclipse.paho.client.mqttv3.MqttClient; - var callback = new Callback( - function(err){ - console.log('connectionLost: ' + err); - }, - function(topic, message){ - console.log('messageArrived ' + topic + '> ' + message); - }, - function(token){ - console.log('deliveryComplete:' + token); - } - ); - - if (!brokerUrl){ - brokerUrl = 'tcp://localhost:1883'; + var callback = new Callback( + function(err){ + console.log('connectionLost: ' + err); + }, + function(topic, message){ + console.log('messageArrived ' + topic + '> ' + message); + }, + function(token){ + console.log('deliveryComplete:' + token); } - if (!clientId){ - clientId = 'scriptcraft'; + ); + + if (!brokerUrl){ + brokerUrl = 'tcp://localhost:1883'; + } + if (!clientId){ + clientId = 'scriptcraft' + new Date().getTime(); + } + var client = new MqttClient(brokerUrl, clientId, null); + client.setCallback(callback); + return { + + connect: function(options){ + if (typeof options === 'undefined'){ + client.connect(); + }else{ + client.connect(options); + } + return client; + }, + + disconnect: function(quiesceTimeout){ + if (typeof quiesceTimeout == 'undefined') + client.disconnect(); + else + client.disconnect(quiesceTimeout); + return client; + }, + + publish: function(topic, message, qos, retained){ + if (typeof message == 'string'){ + message = new java.lang.String(message).bytes; + } + if (typeof qos == 'undefined'){ + qos = 1; + } + if (typeof retained == 'undefined'){ + retained = false; + } + client.publish(topic, message,qos, retained); + return client; + }, + + subscribe: function(topic){ + client.subscribe(topic); + return client; + }, + + unsubscribe: function(topic){ + client.unsubscribe(topic); + return client; + }, + + onMessageArrived: function(fn){ + callback.setMesgArrived(fn); + return client; + }, + + onDeliveryComplete: function(fn){ + callback.setDeliveryComplete(fn); + return client; + }, + + onConnectionLost: function(fn){ + callback.setConnLost(fn); + return client; } - var client = new MqttClient(brokerUrl, clientId, null); - client.setCallback(callback); - return { - connect: function(options){ - if (typeof options === 'undefined'){ - client.connect(); - }else{ - client.connect(options); - } - return client; - }, - publish: function(topic, message, qos, retained){ - if (typeof message == 'string'){ - message = new java.lang.String(message).bytes; - } - if (typeof qos == 'undefined'){ - qos = 1; - } - if (typeof retained == 'undefined'){ - retained = false; - } - client.publish(topic, message,qos, retained); - return client; - }, - subscribe: function(topic){ - client.subscribe(topic); - return client; - }, - unsubscribe: function(topic){ - client.unsubscribe(topic); - return client; - }, - onMessageArrived: function(fn){ - callback.setMesgArrived(fn); - return client; - }, - onDeliveryComplete: function(fn){ - callback.setDeliveryComplete(fn); - return client; - }, - onConnectionLost: function(fn){ - callback.setConnLost(fn); - return client; - } - }; -}; + }; +} exports.client = function(brokerUrl, clientId, options){ - if (typeof org.walterhiggins.scriptcraft.ScriptCraftMqttCallback != 'function'){ - throw MISSING_MQTT; - } - return new Client(brokerUrl, clientId, options); + if (typeof org.walterhiggins.scriptcraft.ScriptCraftMqttCallback != 'function'){ + throw MISSING_MQTT; + } + return new Client(brokerUrl, clientId, options); }; diff --git a/src/main/javascript/plugins/alias/alias.js b/src/main/javascript/plugins/alias/alias.js index 4941de9..e8be545 100644 --- a/src/main/javascript/plugins/alias/alias.js +++ b/src/main/javascript/plugins/alias/alias.js @@ -1,3 +1,4 @@ +'use strict'; /************************************************************************* ## alias Plugin @@ -65,8 +66,8 @@ Execute the alias : \n \ persist aliases */ var _store = { - players: {}, - global: {} + players: {}, + global: {} }; /* turns 'cw = time set {1} ; weather {2}' into {cmd: 'cw', aliases: ['time set {1}', 'weather {2}']} @@ -74,159 +75,148 @@ var _store = { used for the 'set' and 'global' options. */ var _processParams = function(params){ - var paramStr = params.join(' '); - var eqPos = paramStr.indexOf('='); - var aliasCmd = paramStr.substring(0,eqPos).trim(); - var aliasValue = paramStr.substring(eqPos+1).trim(); - return { cmd: aliasCmd, aliases: aliasValue.split(/\s*;\s*/) }; + var paramStr = params.join(' '), + eqPos = paramStr.indexOf('='), + aliasCmd = paramStr.substring(0,eqPos).trim(), + aliasValue = paramStr.substring(eqPos+1).trim(); + return { + cmd: aliasCmd, + aliases: aliasValue.split(/\s*;\s*/) + }; }; var _set = function(params, player){ - var playerAliases = _store.players[player.name]; - if (!playerAliases){ - playerAliases = {}; - } - var o = _processParams(params); - playerAliases[o.cmd] = o.aliases; - _store.players[player.name] = playerAliases; - player.sendMessage("Alias '" + o.cmd + "' created."); + var playerAliases = _store.players[player.name]; + if (!playerAliases){ + playerAliases = {}; + } + var o = _processParams(params); + playerAliases[o.cmd] = o.aliases; + _store.players[player.name] = playerAliases; + player.sendMessage("Alias '" + o.cmd + "' created."); }; var _remove = function(params, player){ - if (_store.players[player.name] && - _store.players[player.name][params[0]]){ - delete _store.players[player.name][params[0]]; - player.sendMessage("Alias '" + params[0] + "' removed."); - } - else{ - player.sendMessage("Alias '" + params[0] + "' does not exist."); - } - if (player.op){ - if (_store.global[params[0]]) - delete _store.global[params[0]]; - } + if (_store.players[player.name] && + _store.players[player.name][params[0]]){ + delete _store.players[player.name][params[0]]; + player.sendMessage("Alias '" + params[0] + "' removed."); + } + else{ + player.sendMessage("Alias '" + params[0] + "' does not exist."); + } + if (player.op){ + if (_store.global[params[0]]) + delete _store.global[params[0]]; + } }; var _global = function(params, player){ - if (!player.op){ - player.sendMessage("Only operators can set global aliases. " + - "You need to be an operator to perform this command."); - return; - } - var o = _processParams(params); - _store.global[o.cmd] = o.aliases; - player.sendMessage("Global alias '" + o.cmd + "' created."); + if (!player.op){ + player.sendMessage("Only operators can set global aliases. " + + "You need to be an operator to perform this command."); + return; + } + var o = _processParams(params); + _store.global[o.cmd] = o.aliases; + player.sendMessage("Global alias '" + o.cmd + "' created."); }; var _list = function(params, player){ - try { - var alias = 0; - if (_store.players[player.name]){ - player.sendMessage("Your aliases:"); - for (alias in _store.players[player.name]){ - player.sendMessage(alias + " = " + - JSON.stringify(_store.players[player.name][alias])); - } - }else{ - player.sendMessage("You have no player-specific aliases."); - } - player.sendMessage("Global aliases:"); - for (alias in _store.global){ - player.sendMessage(alias + " = " + JSON.stringify(_store.global[alias]) ); - } - }catch(e){ - console.error("Error in list function: " + e.message); - throw e; + var alias = 0; + try { + if (_store.players[player.name]){ + player.sendMessage("Your aliases:"); + for (alias in _store.players[player.name]){ + player.sendMessage(alias + " = " + + JSON.stringify(_store.players[player.name][alias])); + } + }else{ + player.sendMessage("You have no player-specific aliases."); } + player.sendMessage("Global aliases:"); + for (alias in _store.global){ + player.sendMessage(alias + " = " + JSON.stringify(_store.global[alias]) ); + } + }catch(e){ + console.error("Error in list function: " + e.message); + throw e; + } }; var _help = function(params, player){ - player.sendMessage('Usage:\n' + _usage); + player.sendMessage('Usage:\n' + _usage); }; + var alias = plugin('alias', { - store: _store, - set: _set, - global: _global, - remove: _remove, - list: _list, - help: _help + store: _store, + set: _set, + global: _global, + remove: _remove, + list: _list, + help: _help }, true ); var aliasCmd = command('alias', function( params, invoker ) { - var operation = params[0], fn; - if (!operation){ - invoker.sendMessage('Usage:\n' + _usage); - return; - } - /* - wph 20140122 this is kind of dumb but Nashorn has some serious problems - accessing object properties by array index notation - in JRE8 alias[operation] returns null - definitely a bug in Nashorn. - */ - if (operation == 'set'){ - alias.set(params.slice(1), invoker); - }else if (operation == 'global'){ - alias.global(params.slice(1), invoker); - }else if (operation == 'remove'){ - alias.remove(params.slice(1), invoker); - }else if (operation == 'list'){ - alias.list(params.slice(1), invoker); - }else if (operation == 'help'){ - alias.help(params.slice(1), invoker); - }else { - invoker.sendMessage('Usage:\n' + _usage); + var operation = params[0], + fn; + if (!operation){ + invoker.sendMessage('Usage:\n' + _usage); + return; + } + /* + wph 20140122 this is kind of dumb but Nashorn has some serious problems + accessing object properties by array index notation + in JRE8 alias[operation] returns null - definitely a bug in Nashorn. + */ + for (var key in alias){ + if (key == operation){ + fn = alias[key]; + fn(params.slice(1),invoker); + return; } + } + invoker.sendMessage('Usage:\n' + _usage); }); var _intercept = function( msg, invoker, exec) { - if (msg.trim().length == 0) - return false; - var msgParts = msg.split(' '); - var command = msg.match(/^\/*([^\s]+)/)[1]; - - var template = [], isAlias = false, cmds = []; - - if (_store.global[command]){ - template = _store.global[command]; - isAlias = true; - }else{ - if (config.verbose){ - var commandObj = server.commandMap.getCommand(command); - if (!commandObj) - console.info('No global alias found for command: ' + command); - } - } - /* - allows player-specific aliases to override global aliases - */ - if (_store.players[invoker] && - _store.players[invoker][command]) - { - template = _store.players[invoker][command]; - isAlias = true; - }else{ - if (config.verbose){ - var commandObj = server.commandMap.getCommand(command); - if (!commandObj) - console.info('No player alias found for command: ' + command); - } - } - for (var i = 0;i < template.length; i++) - { - var filledinCommand = template[i].replace(/{([0-9]+)}/g, function (match,index){ - index = parseInt(index,10); - if (msgParts[index]) - return msgParts[index] - else - return match; - }); - cmds.push(filledinCommand); - } - - for (var i = 0; i< cmds.length; i++){ - exec(cmds[i]); - } - return isAlias; + if (msg.trim().length == 0) + return false; + var msgParts = msg.split(' '), + command = msg.match(/^\/*([^\s]+)/)[1], + template = [], isAlias = false, cmds = [], + commandObj, + filledinCommand; + + if (_store.global[command]){ + template = _store.global[command]; + isAlias = true; + } + /* + allows player-specific aliases to override global aliases + */ + if (_store.players[invoker] && + _store.players[invoker][command]) + { + template = _store.players[invoker][command]; + isAlias = true; + } + for (var i = 0;i < template.length; i++) + { + filledinCommand = template[i].replace(/{([0-9]+)}/g, function (match,index){ + index = parseInt(index,10); + if (msgParts[index]) + return msgParts[index]; + else + return match; + }); + cmds.push(filledinCommand); + } + + for (var i = 0; i< cmds.length; i++){ + exec(cmds[i]); + } + return isAlias; }; /* @@ -234,19 +224,19 @@ var _intercept = function( msg, invoker, exec) command about to be issued matches an alias. */ events.on('player.PlayerCommandPreprocessEvent', function(listener,evt){ - var invoker = evt.player; - var exec = function(cmd){ invoker.performCommand(cmd);}; - var isAlias = _intercept(''+evt.message, ''+invoker.name, exec); - if (isAlias) - evt.cancelled = true; - + var invoker = evt.player; + var exec = function(cmd){ invoker.performCommand(cmd);}; + var isAlias = _intercept(''+evt.message, ''+invoker.name, exec); + if (isAlias) + evt.cancelled = true; }); /* define a 'void' command because ServerCommandEvent can't be canceled */ command('void',function(){}); + events.on('server.ServerCommandEvent', function(listener,evt){ - var invoker = evt.sender; - var exec = function(cmd){ invoker.server.dispatchCommand(invoker, cmd); }; - var isAlias = _intercept(''+evt.command, ''+ invoker.name, exec); - if (isAlias) - evt.command = 'jsp void'; + var invoker = evt.sender; + var exec = function(cmd){ invoker.server.dispatchCommand(invoker, cmd); }; + var isAlias = _intercept(''+evt.command, ''+ invoker.name, exec); + if (isAlias) + evt.command = 'jsp void'; }); diff --git a/src/main/javascript/plugins/drone/contrib/lcd-clock.js b/src/main/javascript/plugins/drone/contrib/lcd-clock.js new file mode 100644 index 0000000..48cf7f2 --- /dev/null +++ b/src/main/javascript/plugins/drone/contrib/lcd-clock.js @@ -0,0 +1,75 @@ +/* + Experimental: + Point at a block and issue the following ... + /js var d = new Drone(); + /js var clock = new LCDClock(d); + /js clock.start24(); + ... start the clock... + /js clock.stop24(); + ... stops the clock... +*/ +var Drone = require('../drone').Drone; +var blocktype = require('../blocktype'); + + +exports.LCDClock = function(drone, fgColor,bgColor,border) { + var lastSecs = [0,0,0,0], + world = drone.world, + intervalId = -1; + + if (typeof bgColor == 'undefined') + bgColor = '35:15'; // black wool + + if (typeof fgColor == 'undefined') + fgColor = 35 ; // white wool + + if (border){ + drone.box(border,21,9,1); + drone.up().right(); + } + drone.blocktype('00:00',fgColor,bgColor); + return { + start24: function(){ + var clock = this; + function tick(){ + var rolloverMins = 24*60; + var timeOfDayInMins = Math.floor(((world.time + 6000) % 24000) / 16.6667); + timeOfDayInMins = timeOfDayInMins % rolloverMins; + console.log('Minecraft time: ' + world.time + ' timeOfDayInMins: ' + timeOfDayInMins); + clock.update(timeOfDayInMins); + }; + intervalId = setInterval(tick, 800); + }, + stop24: function(){ + clearInterval(intervalId); + }, + update: function(secs){ + var digits = [0,0,0,0], + s = secs % 60; + m = (secs - s) / 60; + digits[3] = s%10; + digits[2] = (s-digits[3])/10; + digits[1] = m%10; + digits[0] = (m-digits[1])/10; + // + // updating all 4 digits each time is expensive + // only update digits which have changed (in most cases - just 1) + // + if (digits[3] != lastSecs[3]) + drone.right(14).blocktype(''+digits[3],fgColor,bgColor).left(14); + if (digits[2] != lastSecs[2]) + drone.right(10).blocktype(''+digits[2],fgColor,bgColor).left(10); + if (digits[1] != lastSecs[1]) + drone.right(4).blocktype(''+digits[1], fgColor, bgColor).left(4); + if (digits[0] != lastSecs[0]) + drone.blocktype(''+digits[0], fgColor, bgColor); + + lastSecs[0] = digits[0]; + lastSecs[1] = digits[1]; + lastSecs[2] = digits[2]; + lastSecs[3] = digits[3]; + + } + }; +}; +