diff --git a/build.properties b/build.properties index 4ef2b33..9d6409b 100644 --- a/build.properties +++ b/build.properties @@ -1,2 +1,2 @@ bukkit-version=1.7.2 -scriptcraft-version=2.0 +scriptcraft-version=2.0.1 diff --git a/docs/API-Reference.md b/docs/API-Reference.md index 61cad66..7119a64 100644 --- a/docs/API-Reference.md +++ b/docs/API-Reference.md @@ -49,7 +49,7 @@ Walter Higgins * [Blocks Module](#blocks-module) * [Examples](#examples) * [Fireworks Module](#fireworks-module) - * [Examples](#examples) + * [Examples](#examples-1) * [Http Module](#http-module) * [http.request() function](#httprequest-function) * [Signs Module](#signs-module) @@ -105,20 +105,20 @@ Walter Higgins * [Example Plugin #1 - A simple extension to Minecraft.](#example-plugin-1---a-simple-extension-to-minecraft) * [Usage:](#usage) * [Example Plugin #2 - Making extensions available for all players.](#example-plugin-2---making-extensions-available-for-all-players) - * [Usage:](#usage) + * [Usage:](#usage-1) * [Example Plugin #3 - Limiting use of commands to operators only.](#example-plugin-3---limiting-use-of-commands-to-operators-only) - * [Usage:](#usage) + * [Usage:](#usage-2) * [Example Plugin #4 - Using parameters in commands.](#example-plugin-4---using-parameters-in-commands) - * [Usage:](#usage) + * [Usage:](#usage-3) * [Example Plugin #5 - Re-use - Using your own and others modules.](#example-plugin-5---re-use---using-your-own-and-others-modules) - * [Usage:](#usage) + * [Usage:](#usage-4) * [Example Plugin #6 - Re-use - Using 'utils' to get Player objects.](#example-plugin-6---re-use---using-utils-to-get-player-objects) - * [Usage:](#usage) + * [Usage:](#usage-5) * [Example Plugin #7 - Listening for events, Greet players when they join the game.](#example-plugin-7---listening-for-events-greet-players-when-they-join-the-game) * [Arrows Plugin](#arrows-plugin) - * [Usage:](#usage) + * [Usage:](#usage-6) * [alias Plugin](#alias-plugin) - * [Examples](#examples) + * [Examples](#examples-2) * [Classroom Plugin](#classroom-plugin) * [classroom.allowScripting() function](#classroomallowscripting-function) * [Commando Plugin](#commando-plugin) @@ -131,10 +131,10 @@ Walter Higgins * [Social options](#social-options) * [Administration options](#administration-options) * [NumberGuess mini-game:](#numberguess-mini-game) - * [Description](#description) - * [Example](#example) + * [Description](#description-1) + * [Example](#example-1) * [SnowballFight mini-game](#snowballfight-mini-game) - * [Description](#description) + * [Description](#description-2) ## Modules in Scriptcraft diff --git a/docs/Using-Java-APIs-In-Javascript.md b/docs/Using-Java-APIs-In-Javascript.md new file mode 100644 index 0000000..3166ea6 --- /dev/null +++ b/docs/Using-Java-APIs-In-Javascript.md @@ -0,0 +1,121 @@ +# Using Java APIs in Javascript + +## Using java.lang package classes + +ScriptCraft uses the Javascript Engine bundled with Java 6 and later +versions. This means that all of the core Java classes can be used +from within ScriptCraft. For example, in Java the following code will +print out the `user.dir` and `user.timezone` properties... + + System.out.println( System.getProperty( "user.dir" ) ); + System.out.println( System.getProperty( "user.timezone" ) ); + +... In Java, any classes in the `java.lang` package don't need to be +prefixed with the package so the `java.lang.System` class can simply +be written as `System`. In Javascript you need to write... + + println( java.lang.System.getProperty( "user.dir" ) ); + println( java.lang.System.getProperty( "user.timezone" ) ); + +... the `println()` function is one of the default functions provided +by the JS Engine in Java so there is no need to add the class name +prefix, but for other System class methods you need to explicitly +include the package name e.g. `java.lang.`. If you are using the +System class in a number of statements you can save yourself some +typing by declaring a System variable and using that instead of the +fully-qualified package and class name... + + var System = java.lang.System; + println( System.getProperty( "user.dir" ) ); + println( System.getProperty( "user.timezone" ) ); + +The JS Engine provides an `importPackage()` function which can be used +to import packages. This also saves you having to type full package +names before classes. For example... + + importPackage(java.util); + var hMap = new HashMap(); + hMap.put('name','Walter'); + +... makes all of the classes in the Java Library's `java.util` package +available for use without having to use the `java.util` +prefix. However, importing the `java.lang` package is not recommended +as some of the java.lang classes (e.g. String, Object) conflict with +Javascript Object types. + +## Using Java Beans + +The Javascript Engine bundled with Java comes with a handy notation +for accessing and modifying Java Beans. A Java Bean is any Java class +which uses a `get{Property}()` method to retrieve an object's property +and a `set{Property}()` method to set the object's property. One +example of a Java Bean in the [Bukkit API][bukapi] is the +[org.bukkit.entity.Player][bukpl] Class which has many methods which +conform to the JavaBean specification. + +For example the [Player.getWalkSpeed()][bukplws] can be used to get a +player's walking speed. In Java you would have to write code like this +to obtain the walking speed... + + float walkingSpeed = player.getWalkSpeed(); + +... however, in Javascript you can access the walking-speed property +using the more succinct... + + var walkingspeed = player.walkSpeed; + +... or if you prefer to use Java-style access... + + var walkingspeed = player.getWalkSpeed(); + +... I personally prefer to use the simpler `player.walkSpeed` because +it is easier to read. The important thing to remember when using the +Bukkit (or any Java API) from Javascript is that for any Java Bean, a +property called `propertyName` will have a getter called +`getPropertyName()` and a setter called `setPropertyName`. From this +rule you can infer what any Bukkit class properties are. For example, +the [Bukkit Player][bukpl] object has the following methods... + + * float getWalSpeed() + * void setWalkSpeed(float speed) + +... so from this you can infer that every Player object has a +`walkSpeed` property which can be read and changed. For example you +can triple your own walking speed (from the default 0.2) at the +in-game prompt using the following command... + + /js self.walkSpeed = self.walkSpeed * 3; + +... If we were limited to using Java's notation we would have had to +write `/js self.setWalkSpeed( self.getWalkSpeed() * 3 )` . Since +almost every class in the Bukkit API is also a JavaBean you can access +properties of properties and so on. For example, to get the name of +the world in which a player is located... + + /js self.location.world.name + +... is more concise than `/js self.getLocation().getWorld().getName()`. +If you're new to Java and the [Bukkit API][bukapi] is the first time +you've browsed Java documentation, you may be wondering where the +`location` property came from - the `location` property is "inherited" +by one of the Player classes super-classes. You'll see the +`getLocation()` method listed under a section titled **Methods +inherited from interface org.bukkit.entity.Entity** in the +[Player][bukpl] javadoc page. + +## Summary + +When writing modules or plugins in ScriptCraft, you can access and +change JavaBean properties using a simple .{propertyName} notation +instead of using the Java .get{PropertyName}() and .set{PropertyName() +methods. This results in more concise code. This simpler notation is +provided by the Javascript Engine embedded in Java 6 and later +versions. Javascript does not have access to private members, the +.{propertyName} notation is automagically converted to the appropriate +.get{PropertyName}() or .set{PropertyName}() method by Java. + +[bukapi]: http://jd.bukkit.org/beta/apidocs/ +[bukpl]: http://jd.bukkit.org/beta/apidocs/org/bukkit/entity/Player.html +[bukplws]: http://jd.bukkit.org/beta/apidocs/org/bukkit/entity/Player.html#getWalkSpeed() +[buksrv]: http://jd.bukkit.org/beta/apidocs/org/bukkit/Server.html + diff --git a/src/docs/javascript/generateTOC.js b/src/docs/javascript/generateTOC.js index 4d0b1c9..5724472 100644 --- a/src/docs/javascript/generateTOC.js +++ b/src/docs/javascript/generateTOC.js @@ -13,11 +13,18 @@ while ( (line = br.readLine()) != null){ } br.close(); +var anchors = {}; + var createLink = function(text){ var result = text.replace(/_/g,'_'); result = result.replace(/[^a-zA-Z0-9 _\-]/g,''); result = result.replace(/ /g,'-'); - return result.toLowerCase(); + var result = result.toLowerCase(); + if (anchors[result]){ + result = result + '-' + (anchors[result]++); + } + anchors[result] = 1; + return result; }; println('## Table of Contents'); diff --git a/src/main/javascript/lib/plugin.js b/src/main/javascript/lib/plugin.js index 87d7978..0b8cb47 100644 --- a/src/main/javascript/lib/plugin.js +++ b/src/main/javascript/lib/plugin.js @@ -10,7 +10,7 @@ var PrintWriter = java.io.PrintWriter; var _save = function(object, filename){ var objectToStr = null; try{ - objectToStr = JSON.stringify(object); + objectToStr = JSON.stringify(object,null,2); }catch(e){ print("ERROR: " + e.getMessage() + " while saving " + filename); return; diff --git a/src/main/javascript/lib/tabcomplete-jsp.js b/src/main/javascript/lib/tabcomplete-jsp.js index e2106ed..29490c2 100644 --- a/src/main/javascript/lib/tabcomplete-jsp.js +++ b/src/main/javascript/lib/tabcomplete-jsp.js @@ -3,32 +3,30 @@ var _commands = require('command').commands; /* Tab completion for the /jsp commmand */ -var __onTabCompleteJSP = function( __onTC_result, __onTC_sender, __onTC_cmd, __onTC_alias, __onTC_args) { - var result = __onTC_result; - var args = __onTC_args; - var cmdInput = args[0]; +var __onTabCompleteJSP = function( result, cmdSender, pluginCmd, cmdAlias, cmdArgs) { + var cmdInput = cmdArgs[0]; var cmd = _commands[cmdInput]; if (cmd){ var opts = cmd.options; var len = opts.length; - if (args.length == 1){ + if (cmdArgs.length == 1){ for (var i = 0;i < len; i++) result.add(opts[i]); }else{ // partial e.g. /jsp chat_color dar for (var i = 0;i < len; i++){ - if (opts[i].indexOf(args[1]) == 0){ + if (opts[i].indexOf(cmdArgs[1]) == 0){ result.add(opts[i]); } } } }else{ - if (args.length == 0){ + if (cmdArgs.length == 0){ for (var i in _commands) result.add(i); }else{ - // partial e.g. /jsp al - // should tabcomplete to alias + // partial e.g. /jsp ho + // should tabcomplete to home // for (var c in _commands){ if (c.indexOf(cmdInput) == 0){ diff --git a/src/main/javascript/lib/tabcomplete.js b/src/main/javascript/lib/tabcomplete.js index 2a2d560..92133b3 100644 --- a/src/main/javascript/lib/tabcomplete.js +++ b/src/main/javascript/lib/tabcomplete.js @@ -74,18 +74,18 @@ var _getProperties = function(o) return result.sort(); }; -var onTabCompleteJS = function( __onTC_result, __onTC_sender, __onTC_cmd, __onTC_alias, __onTC_args) { - if (__onTC_cmd.name == 'jsp') - return tabCompleteJSP( __onTC_result, __onTC_sender, __onTC_cmd, __onTC_alias, __onTC_args ); +var onTabCompleteJS = function( result, cmdSender, pluginCmd, cmdAlias, cmdArgs) { - global.self = __onTC_sender; // bring in self just for autocomplete + if (pluginCmd.name == 'jsp') + return tabCompleteJSP( result, cmdSender, pluginCmd, cmdAlias, cmdArgs ); + + global.self = cmdSender; // bring in self just for autocomplete var _globalSymbols = _getProperties(global) - var result = __onTC_result; - var args = __onTC_args; - var lastArg = args.length?args[args.length-1]+'':null; + + var lastArg = cmdArgs.length?cmdArgs[cmdArgs.length-1]+'':null; var propsOfLastArg = []; - var statement = args.join(' '); + var statement = cmdArgs.join(' '); statement = statement.replace(/^\s+/,'').replace(/\s+$/,'');