This repository has been archived on 2021-07-14. You can view files and clone it, but cannot push or open issues or pull requests.
scriptcraft/docs/Using-Java-APIs-In-Javascri...

5.4 KiB

Using Java APIs in Javascript

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. In addition, all of the Bukkit API can be used from Javascript too. There are some things to consider when using Java classes in Javascript...

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 is the org.bukkit.entity.Player Class which has many methods which conform to the JavaBean specification.

For example the Player.getWalkSpeed() 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 object has the following methods...

  • float getWalkSpeed()
  • 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 is the first time you've browsed Java documentation, you may be wondering where the location property came from - the location property is "inherited" from one of the Player class's super-classes (it's ancestors). You'll see the getLocation() method listed under a section titled Methods inherited from interface org.bukkit.entity.Entity in the Player javadoc page.

Using java.lang package classes

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. However, in Javascript classes in the java.lang package need to be fully qualified so 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.

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.