Plugin Hello world explained

Firstly, have you read and understood Oracle's explanation of Hello World?
OK. Our hello world is a bit different. Let's take a look.

No main method

You might be looking for the following code:

public static void main(String[] args) {

All programs have this method, so where is ours? The answer is that it is within the Minecraft / Craftbukkit code, not within our code. We are writing code that extends an existing application, which already has its main method.

The class definition


public class PluginTutorial extends JavaPlugin
{
  .....
}

Firstly, you may have noticed that this is a public class. Unlike Oracle's HelloWorldApp class, our class needs to be visible from other packages. This is what allows Craftbukkit to access it. Secondly, the class extends JavaPlugin This says that PluginTutorial is a subclass of JavaPlugin. JavaPlugin is something we imported from the Bukkit or Craftbukkit jar file, with the following line:
import org.bukkit.plugin.java.JavaPlugin;
When Craftbukkit loads a plugin, it expects the "main" class of the plugin to be a subclass of JavaPlugin. At this stage, we don't need to know too much about what that means, just that it is important to define our plugin's "main" class in that way. In part 1 of our tutorial, all the code was contained in this one class. Your plugin can consist of more classes, and we will come to that in part 3, but only the "main" class will extend JavaPlugin.
You may have noticed that while the Oracle hello world tutorial gave a class definition like so:

class name {
...
}

Ours looks like this:

class name
{
...
}

The two versions are equivalent. I personally prefer the second form, because the opening bracket lines up with the closing bracket, which improves the readability. Many C programmers like me will use this layout. Oracle's "conventions" prefer the first form. You will encounter many differing styles of white space in Java code. White space is mostly irrelevant to the operation of the code, so our class could look like this

public class PluginTutorial extends JavaPlugin {
  .....
}

Or like this:

public class PluginTutorial extends JavaPlugin
{   .....  }

Or like this:

public
 class
 PluginTutorial
 extends JavaPlugin
{
  .....
}
and so on. Eclipse has buried within it some detailed settings that allow you to control the style of auto-generated code, should you wish to use that feature.

Methods in the madness

So hopefully you will have realised that onEnable and onDisable are methods, like the main method in HelloWorldApp. The Craftbukkit code will call your plugin's onEnable method when the plugin gets enabled. Fairly intuitive really.
Without our own onEnable method, we would inherit the onEnable method that's built in to the JavaPlugin class, because that is our parent class. That is what the @Override is about. It tells the compiler, and other developers, that we expect onEnable to be overriding an inherited version of onEnable. If we were to omit the @Override directive, it would still work exactly the same. However if we were to put an @Override directive in front of a method that doesn't override something, then the compiler would generate an error. So while @Override is not mandatory, it is good practice and it is a self-testing form of documentation (unlike a comment, it can't lie).
So how do we know that our PluginTutorial class was going to inherit these methods? Well for a start because every tutorial in the world about getting started with Bukkit includes an onEnable code sample. And there's lots to learn by reading other people's code, but, in the long run if you're serious about coding plugins you will have to refer to the Bukkit API documentation, which describes all the methods in all of the classes.

Hello World!

So in Oracle's tutorial, we had
    System.out.println("Hello world");
And in our tutorial, we have
    getLogger().info (HELLO_MESSAGE);
So what's the difference? Well, Eclipse can give us some insight into that. Hover the mouse pointer over "getLogger" and you should see some Javadoc, like so:
Javadoc

If this doesn't work for you then check you set up the Javadoc URL correctly as shown in part 1. This feature generally needs the mouse scroll wheel available. If you are on a laptop you might want to consider enabling mouse scroll wheel emulation for your trackpad.
The above screenshot shows us that getLogger is inherited from JavaPlugin. getLogger returns a Logger object, which has been set up to format your messages in the same way as all of the other messages in the system. Try putting the following lines in onEnable
    getLogger().warning (HELLO_MESSAGE);
    System.out.println(HELLO_MESSAGE);
    System.err.println(HELLO_MESSAGE); 
What happens? You should see output like this
2013-06-04 13:52:25 [INFO] [Plugin Tutorial] Hello World
2013-06-04 13:52:25 [WARNING] [Plugin Tutorial] Hello World
2013-06-04 13:52:25 [INFO] Hello World
2013-06-04 13:52:25 [SEVERE] Hello World
Craftbukkit is actually capturing and formatting all console output whether it be through logger (lines 1 and 2), standard output (line 3) or standard error (line 4). (Note that in older versions of Craftbukkit standard output was not processed like this). System.out and System.err are global references to output streams that are usually connected the the process' output console. However Craftbukkit has hijacked these and connected them to its own internal logger, so that all output gets some formatting whether or not you used "getLogger". The formatted output then gets directed through to the actual console, which you as a plugin developer don't have direct access to (unlike in HelloWorldApp).

And finally, Strings

So let's take a look at
private final String HELLO_MESSAGE = "Hello World";
This declares two things:
  • A reference to a String. The reference is called HELLO_MESSAGE
  • A string literal which creates a String object with the text "Hello World"
In HelloWorldApp, the string literal was passed directly into the println method. Here, we used a reference, which keeps the text separate. Both techniques are equally as valid, a reference is more useful in the event that you want to use the same string in a lot of places.
HELLO_MESSAGE is declared private, because nothing outside of the class needs access to it. It is declared final because once we have set its value, we have no need to change it, and any attempt to change it would cause a compilation error.

Strings for C programmers

Note that in Java, Strings cannot be modified, however references to strings can be modified. So if you're a C programmer, read this:
/* This is some C code not Java! For the benefit of C programmers */
void modify_string (char * somestring)
{
   /* This is not possible in Java because Strings are immutable */
   sprintf (somestring, "New value of string");

  /* This is possible in Java, because updating a pointer is equivalent to updating a reference */
  somestring = "New value of string"; // Note that the original buffer is unmodified!
}
The Java declaration
String somestring;
is equivalent to this in C
const char * somestring;
ie the contents of the string cannot be modified, but the reference / pointer can be modified.

The Java declaration
final String somestring = "hello"; 
is equivalent to this in C
const char * const somestring = "hello";
because neither the string nor the pointer can be modified.

Move on to part 3
Top