diff --git a/docs/API-Reference.md b/docs/API-Reference.md index ef1abd4..47068b8 100644 --- a/docs/API-Reference.md +++ b/docs/API-Reference.md @@ -767,7 +767,7 @@ The utils.at() function will perform a given task at a given time every * 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. - * world : (optional) Each world has its own clock. If no world is specified, the server's first world is used. + * 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. #### Example @@ -781,7 +781,7 @@ To warn players when night is approaching... player.chat("The night is dark and full of terrors!"); }); - }, self.world); + }); ### utils.find() function @@ -838,8 +838,8 @@ The following chat-formatting methods are added to the javascript String class.. Example ------- - var boldGoldText = "Hello World".bold().gold(); - self.sendMessage(boldGoldText); + /js var boldGoldText = "Hello World".bold().gold(); + /js self.sendMessage(boldGoldText);

Hello World

diff --git a/docs/release-notes.md b/docs/release-notes.md index f2719ef..afefd0f 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,6 +4,10 @@ Bug Fix: [Can't get Scriptcraft core libraries working][bug103]. [bug103]: https://github.com/walterhiggins/ScriptCraft/issues/103 +Bug Fix; Server console errors when empty commands submitted. + +Added more example modules. + # 2013 12 28 Documented the 'homes' module other tweaks to documentation. diff --git a/src/main/javascript/lib/command.js b/src/main/javascript/lib/command.js new file mode 100644 index 0000000..568bc12 --- /dev/null +++ b/src/main/javascript/lib/command.js @@ -0,0 +1,59 @@ +/* + command management - allow for non-ops to execute approved javascript code. +*/ +var _commands = {}; +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{ + func = cmd.callback; + var params = []; + for (var i =1; i < args.length;i++){ + params.push("" + args[i]); + } + var result = null; + try { + result = func(params,player); + }catch (e){ + console.error("Error while trying to execute command: " + JSON.stringify(params)); + 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; +}; +var _command = function(name, func, options, intercepts) { + if (typeof name == "undefined"){ + // it's an invocation from the Java Plugin! + return executeCmd(__cmdArgs, self); + }else{ + return defineCmd(name, func, options, intercepts); + } +}; +exports.command = _command; +exports.commands = _commands; diff --git a/src/main/javascript/lib/plugin.js b/src/main/javascript/lib/plugin.js index 26e5fa4..c43503c 100644 --- a/src/main/javascript/lib/plugin.js +++ b/src/main/javascript/lib/plugin.js @@ -49,63 +49,8 @@ var _plugin = function(/* String */ moduleName, /* Object */ moduleObject, isPer } return moduleObject; }; -/* - allow for deferred execution (once all modules have loaded) -*/ -var _deferred = []; -var _ready = function( func ){ - _deferred.push(func); -}; -var _cmdInterceptors = []; -/* - command management - allow for non-ops to execute approved javascript code. -*/ -var _commands = {}; -exports.commands = _commands; -var _command = function(name,func,options,intercepts) -{ - if (typeof name == "undefined"){ - // it's an invocation from the Java Plugin! - if (__cmdArgs.length === 0) - throw new Error("Usage: jsp command-name command-parameters"); - var name = __cmdArgs[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](__cmdArgs)) - intercepted = true; - } - if (!intercepted) - self.sendMessage("Command '" + name + "' is not recognised"); - }else{ - func = cmd.callback; - var params = []; - for (var i =1; i < __cmdArgs.length;i++){ - params.push("" + __cmdArgs[i]); - } - var result = null; - try { - result = func(params); - }catch (e){ - console.error("Error while trying to execute command: " + JSON.stringify(params)); - throw e; - } - return result; - } - }else{ - if (typeof options == "undefined") - options = []; - _commands[name] = {callback: func, options: options}; - if (intercepts) - _cmdInterceptors.push(func); - return func; - } -}; exports.plugin = _plugin; -exports.command = _command; exports.save = _save; var scriptCraftDir = null; @@ -172,6 +117,7 @@ exports.autoload = function(dir) { }; _reload(pluginDir); }; + addUnloadHandler(function(){ // // save all plugins which have persistent data diff --git a/src/main/javascript/lib/scriptcraft.js b/src/main/javascript/lib/scriptcraft.js index 1325390..7eecf94 100644 --- a/src/main/javascript/lib/scriptcraft.js +++ b/src/main/javascript/lib/scriptcraft.js @@ -565,11 +565,11 @@ var server = org.bukkit.Bukkit.server; global.require = fnRequire(__plugin.logger, __engine, config.verbose, jsPluginsRootDirName, modulePaths); global.console = require('console'); + global.command = require('command').command; var plugins = require('plugin'); global._onTabComplete = require('tabcomplete'); - + global.plugin = plugins.plugin; - global.command = plugins.command; global.save = plugins.save; var events = require('events'); diff --git a/src/main/javascript/lib/tabcomplete-jsp.js b/src/main/javascript/lib/tabcomplete-jsp.js index 1d3764f..b75e883 100644 --- a/src/main/javascript/lib/tabcomplete-jsp.js +++ b/src/main/javascript/lib/tabcomplete-jsp.js @@ -1,4 +1,4 @@ -var _commands = require('plugin').commands; +var _commands = require('command').commands; /* Tab completion for the /jsp commmand */ diff --git a/src/main/javascript/modules/utils/string-exts.js b/src/main/javascript/modules/utils/string-exts.js index f10810e..8be2180 100644 --- a/src/main/javascript/modules/utils/string-exts.js +++ b/src/main/javascript/modules/utils/string-exts.js @@ -35,8 +35,8 @@ The following chat-formatting methods are added to the javascript String class.. Example ------- - var boldGoldText = "Hello World".bold().gold(); - self.sendMessage(boldGoldText); + /js var boldGoldText = "Hello World".bold().gold(); + /js self.sendMessage(boldGoldText);

Hello World

diff --git a/src/main/javascript/modules/utils/utils.js b/src/main/javascript/modules/utils/utils.js index bc8362b..840c45e 100644 --- a/src/main/javascript/modules/utils/utils.js +++ b/src/main/javascript/modules/utils/utils.js @@ -149,7 +149,7 @@ var _foreach = function(array, callback, object, delay, onCompletion) { if (delay){ var next = function(){ callback(array[i],i,object,array); i++;}; var hasNext = function(){return i < len;}; - utils.nicely(next,hasNext,onCompletion,delay); + _nicely(next,hasNext,onCompletion,delay); }else{ for (;i < len; i++){ callback(array[i],i,object,array); @@ -182,17 +182,18 @@ function and the start of the next `next()` function. See the source code to utils.foreach for an example of how utils.nicely is used. ***/ -exports.nicely = function(next, hasNext, onDone, delay){ +var _nicely = function(next, hasNext, onDone, delay){ if (hasNext()){ next(); server.scheduler.runTaskLater(__plugin,function(){ - utils.nicely(next,hasNext,onDone,delay); + _nicely(next,hasNext,onDone,delay); },delay); }else{ if (onDone) onDone(); } }; +exports.nicely = _nicely; /************************************************************************ ### utils.at() function @@ -204,7 +205,7 @@ The utils.at() function will perform a given task at a given time every * 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. - * world : (optional) Each world has its own clock. If no world is specified, the server's first world is used. + * 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. #### Example @@ -218,10 +219,10 @@ To warn players when night is approaching... player.chat("The night is dark and full of terrors!"); }); - }, self.world); + }); ***/ -exports.at = function(time24hr, callback, world) { +exports.at = function(time24hr, callback, worlds) { var forever = function(){ return true;}; var timeParts = time24hr.split(":"); var hrs = ((timeParts[0] * 1000) + 18000) % 24000; @@ -230,15 +231,17 @@ exports.at = function(time24hr, callback, world) { mins = (timeParts[1] / 60) * 1000; var timeMc = hrs + mins; - if (typeof world == "undefined"){ - world = server.worlds.get(0); + if (typeof worlds == "undefined"){ + worlds = server.worlds; } - utils.nicely(function(){ - var time = world.getTime(); - var diff = timeMc - time; - if (diff > 0 && diff < 100){ - callback(); - } + _nicely(function(){ + _foreach (worlds, function (world){ + var time = world.getTime(); + var diff = timeMc - time; + if (diff > 0 && diff < 100){ + callback(); + } + }); },forever, null, 100); }; diff --git a/src/main/javascript/plugins/alias/alias.js b/src/main/javascript/plugins/alias/alias.js index e5a221f..1d325e1 100644 --- a/src/main/javascript/plugins/alias/alias.js +++ b/src/main/javascript/plugins/alias/alias.js @@ -149,20 +149,22 @@ var alias = plugin('alias', { }, true ); -var aliasCmd = command('alias', function(params){ +var aliasCmd = command('alias', function(params,invoker){ var operation = params[0]; if (!operation){ - self.sendMessage("Usage:\n" + _usage); + invoker.sendMessage("Usage:\n" + _usage); return; } if (alias[operation]) - alias[operation](self, params.slice(1)); + alias[operation](invoker, params.slice(1)); else - self.sendMessage("Usage:\n" + _usage); + 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]; diff --git a/src/main/javascript/plugins/commando/commando.js b/src/main/javascript/plugins/commando/commando.js index 06db221..2943a22 100644 --- a/src/main/javascript/plugins/commando/commando.js +++ b/src/main/javascript/plugins/commando/commando.js @@ -86,14 +86,24 @@ exports.commando = function(name, func, options, intercepts){ events.on('player.PlayerCommandPreprocessEvent', function(l,e){ var msg = "" + e.message; - var command = msg.match(/^\/([^\s]+)/)[1]; + var parts = msg.match(/^\/([^\s]+)/); + if (!parts) + return; + if (parts.length < 2) + return; + var command = parts[1]; if (commands[command]){ e.message = "/jsp " + msg.replace(/^\//,""); } }); events.on('server.ServerCommandEvent', function(l,e){ var msg = "" + e.command; - var command = msg.match(/^\/*([^\s]+)/)[1]; + var parts = msg.match(/^\/*([^\s]+)/); + if (!parts) + return; + if (parts.length < 2) + return; + var command = parts[1]; if (commands[command]){ e.command = "jsp " + msg.replace(/^\//,""); } diff --git a/src/main/javascript/plugins/example-1.js b/src/main/javascript/plugins/example-1.js deleted file mode 100644 index 54a9603..0000000 --- a/src/main/javascript/plugins/example-1.js +++ /dev/null @@ -1,12 +0,0 @@ -/* - A simple minecraft plugin. - Usage: At the in-game prompt type ... - - /js hello() - - ... and a message `Hello {player-name}` will appear (where {player-name} is - replaced by your own name). -*/ -exports.hello = function(){ - echo("Hello " + self.name); -}; diff --git a/src/main/javascript/plugins/examples/example-1-hello-module.js b/src/main/javascript/plugins/examples/example-1-hello-module.js new file mode 100644 index 0000000..af60e75 --- /dev/null +++ b/src/main/javascript/plugins/examples/example-1-hello-module.js @@ -0,0 +1,20 @@ +/* + A simple minecraft plugin. + Usage: At the in-game prompt type ... + + /js hello(self) + + ... and a message `Hello {player-name}` will appear (where {player-name} is + replaced by your own name). + + This example demonstrates the basics of adding new functionality which is only + usable by server operators or users with the scriptcraft.evaluate permission. + By default, only ops are granted this permission. + + The `hello` function below is only usable by players with the scriptcraft.evaluate + permission since it relies on the `/js` command to execute. + +*/ +exports.hello = function(player){ + player.sendMessage('Hello ' + player.name); +}; diff --git a/src/main/javascript/plugins/examples/example-2-hello-command.js b/src/main/javascript/plugins/examples/example-2-hello-command.js new file mode 100644 index 0000000..4ead4ba --- /dev/null +++ b/src/main/javascript/plugins/examples/example-2-hello-command.js @@ -0,0 +1,24 @@ +/* + A simple minecraft plugin. + Usage: At the in-game prompt type ... + + /jsp hello + + ... and a message `Hello {player-name}` will appear (where {player-name} is + replaced by your own name). + + This example demonstrates the basics of adding new functionality + which is usable all players or those with the scriptcraft.proxy + permission. By default, all players are granted this permission. + + This differs from example 1 in that a new 'jsp ' command extension + is defined. Since all players can use the `jsp` command, all players + can use the new extension. Unlike the previous example, the `jsp + hello` command does not evaluate javascript code so this command is + much more secure. + +*/ + +command('hello', function (parameters, player) { + player.sendMessage('Hello ' + player.name); +}); diff --git a/src/main/javascript/plugins/examples/example-3-hello-ops-only.js b/src/main/javascript/plugins/examples/example-3-hello-ops-only.js new file mode 100644 index 0000000..10f0674 --- /dev/null +++ b/src/main/javascript/plugins/examples/example-3-hello-ops-only.js @@ -0,0 +1,30 @@ +/* + A simple minecraft plugin. + Usage: At the in-game prompt type ... + + /jsp op-hello + + ... and a message `Hello {player-name}` will appear (where {player-name} is + replaced by your own name). + + This example demonstrates the basics of adding new functionality + which is usable all players or those with the scriptcraft.proxy + permission. By default, all players are granted this permission. In + this command though, the function checks to see if the player is an + operator and if they aren't will return immediately. + + This differs from example 2 in that the function will only print a + message for operators. + +*/ + +command('op-hello', function (parameters, player) { + /* + this is how you limit based on player privileges + */ + if (!player.op){ + player.sendMessage('Only operators can do this.'); + return; + } + player.sendMessage('Hello ' + player.name); +}); diff --git a/src/main/javascript/plugins/examples/example-4-hello-parameters.js b/src/main/javascript/plugins/examples/example-4-hello-parameters.js new file mode 100644 index 0000000..14c6ec7 --- /dev/null +++ b/src/main/javascript/plugins/examples/example-4-hello-parameters.js @@ -0,0 +1,29 @@ +/* + A simple minecraft plugin. + Usage: At the in-game prompt type ... + + /jsp hello-params Hi + /jsp hello-params Saludos + /jsp hello-params Greetings + + ... and a message `Hi {player-name}` or `Saludos {player-name}` etc + will appear (where {player-name} is replaced by your own name). + + This example demonstrates adding and using parameters in commands. + + This differs from example 3 in that the greeting can be changed from + a fixed 'Hello ' to anything you like by passing a parameter. +*/ + +command('hello-params', function (parameters, player) { + /* + parameters is an array (or list) of strings. parameters[0] + refers to the first element in the list. Arrays in Javascript + are 0-based. That is, the 1st element is parameters[0], the 2nd + element is parameters[1], the 3rd element is parameters[2] and + so on. In this example, parameters[1] refers to the first word + which appears after `jsp hello-params `. + */ + var salutation = parameters[0] ; + player.sendMessage( salutation + ' ' + player.name); +}); diff --git a/src/main/javascript/plugins/examples/example-5-hello-using-module.js b/src/main/javascript/plugins/examples/example-5-hello-using-module.js new file mode 100644 index 0000000..b09d5eb --- /dev/null +++ b/src/main/javascript/plugins/examples/example-5-hello-using-module.js @@ -0,0 +1,29 @@ +/* + A simple minecraft plugin. + Usage: At the in-game prompt type ... + + /jsp hello-module + + ... and a message `Hello {player-name}` will appear (where {player-name} is + replaced by your own name). + + This example demonstrates the use of modules. In + example-1-hello-module.js we created a new javascript module. In + this example, we use that module... + + * We load the module using the `require()` function. Because this + module and the module we require are n the same directory, we + specify `'./example-1-hello-module'` as the path (when loading a + module from the same directory, `./` at the start of the path + indicates that the file should be searched for in the same + directory. + + * We assign the loaded module to a variable (`greetings`) and then + use the module's `hello` method to display the message. + +*/ +var greetings = require('./example-1-hello-module'); + +command('hello-module', function( parameters, player ){ + greetings.hello(player); +});