Bukkit Tutorial - Events, eggs and explosions

Most Craftbukkit plugins consist of command handlers and event handlers. In this section, we are going to look at event handlers, and show how a simple event handler can be used to create exploding chicken eggs.

Open your project from part 1 and replace the code in PluginTutorial.java with the following

package com.minecraftiplist.tutorials;
import org.bukkit.plugin.java.JavaPlugin;

public class PluginTutorial extends JavaPlugin
{
	private static PluginTutorial instance;
	public static PluginTutorial getInstance()
	{
		return instance;
	}
	
	@Override
	public void onEnable ()
	{
		instance = this;
		EggSplosions eggs = new EggSplosions();
		getServer().getPluginManager().registerEvents(eggs, this);
	}
	@Override
	public void onDisable ()
	{
		/* Clear down static references on disable, to prevent memory leaks on
		 * reload.
		 */
		instance = null;
	}
}

Let's start by looking at the new code in the onEnable method.

    EggSplosions eggs = new EggSplosions();

The above line constructs a new EggSplosions object, and sets the reference eggs to point to the newly constructed object. This is the cause of our first compilation error, we haven't defined what an EggSplosions is. The Eclipse quick fix offers us "create class EggSplosions". If you accept that quick fix it opens up the new class wizard. Accept the defaults in the wizard and a new file EggSplosions.java is created in the same package as PluginTutorial.java. Now onto the next line

    getServer().getPluginManager().registerEvents(eggs, this);

The compiler is complaining here because it does not think that eggs is a suitable type to be passing into registerEvents. Again a quick fix is available: "Let EggSplosions implement Listener". Choose that option and manually save EggSplosions.java.

Let's look at what the quick fix did. You can now see that "EggSplosions implements Listener" and also that Listener was added to the list of imports at the top of EggSplosions.java. Listener is an interface. Normally, there would be more work to do at this point to make the class conform to the interface that it is implementing. As it turns out, the interface definition of Listener is empty, so there is nothing more to do to allow EggSplosions to implement Listener. However this change has now made eggs a suitable parameter for registerEvents, and we can start filling our EggSplosions class with event handlers.

Now add the following empty method to EggSplosions

	@EventHandler
	public void onPlayerThrowEgg (PlayerEggThrowEvent event)
	{
		
	}

Again some imports will be required to get the definitions of EventHandler and PlayerEggThrowEvent. Carefully choose the correct fix. All event handlers follow this pattern. The name of the method is not important, the type of event being handled is determined by the parameter type, ie PlayerEggThrowEvent in this case. Now let's add some debug to check our event handler is being called. Add this line of code to onPlayerThrowEgg

    PluginTutorial.getInstance().getLogger().info ("Egg!");

Log in and start throwing some eggs, watch the console carefully. Did you notice how the event is fired when the egg hits something, and not when it left the player's arm? Did that come as a surprise? It certainly did to me. It turns out that to capture the act of a player throwing an egg we have to handle a PlayerInteractEvent, but more on that later. You might also be surprised to learn that a PlayerEggThrowEvent is generated whenever an egg impacts, regardless of whether or not it was actually thrown by a player (it might have come out of a dispenser, for example). Lesson learned, don't read the Bukkit API too literally, it might not do exactly what you expect. Some trial and error is often involved.

Okay, let's have some fun. How about generating an explosion on impact? Well, looking at the API for PlayerEggThrowEvent we see it has a method getEgg(). Egg, being an Entity has a method getLocation() - and we now know that this will be the location of impact. Location has a method getWorld() and World has a method createExplosions(). Yeah! So here is the new code for our onPlayerThrowEgg method:

		Location impactLocation = event.getEgg().getLocation();
		World world = impactLocation.getWorld();
		world.createExplosion (impactLocation, 3);		


Location, Location, Location!

Did you get the above code to compile without error? Eclipse offers up three different imports for Location and you have to be sure to select the right one (org.bukkit.Location). EggSplosions.java should now look something like this:

EggSplosions.java, with code folding
Firstly, in the createExplosion method call, 3 is the intensity of the explosion. Feel free to experiment with this value. Beware that very large explosions can be extremely destructive to your landscape, and also generate huge lag spikes, and can even crash the server.

Did you see how in the screen shot, (and possibly on your screen) there only appears to be one import statement? Eclipse has squashed them all into one line - this is for display purposes only and is called code folding. Click on the plus sign to the left of the import line and it will expand to show all of the imports. Code folding can be applied to whole sections of your code, such as methods. All this is configurable in Eclipse under Window->Preferences->Java. You will find a whole bunch of settings there. For example "Syntax Coloring", as you can see from the screen shot it is possible to beef up the variety of colours that Eclipse applies to your text. And in case you were wondering, visible tabs, line numbers etc are configured under Window->Preferences->General->Editors->Text Editors.

Okay, what's left to discuss here? Did you understand what was going on with this line?

   PluginTutorial.getInstance().getLogger().info ("Egg!");

or this line?

   instance = this;

If you're already proficient in Java then the answer is probably "yes", and you can move to part 5 where I show you some of the code from my minigame, Goldrush. If you need an in-depth explanation of the code seen so far, move to part 4 first.
Top