Thursday, May 12, 2011

Purugin

Announcing Purugin (プルギン)!
http://www.github.com/enebo/Purugin

Purugin is a Ruby-based plugin framework for Minecraft which is written on top of Bukkit.

Motivation

Minecraft is a fun game by itself. If it stayed the way it is today, then people would continue enjoying Minecraft for a long time to come. However, all players are critics and all players love the ability to change things in a game here and there. Since Minecraft is written in Java, many plugin initiatives have sprung up to allow just that. The sheer number of mods available for the game is staggering. In looking at the source of several of these mods one thing which struck me was....Damn! I would rather write these things in Ruby. Fortunately, JRuby exists...

Purugin is written using JRuby and it layers on top of Bukkit. Bukkit is an API which maps to the obfuscated Minecraft APIs and it also provides many conveniences for writing server-side plugins. The Bukkit API by itself is not particularly tough to use, but because it is Java and because it cannot make use of blocks/closures it ends up having more syntax/ceremony than what you can do in a Ruby syntax. Purugin is a Bukkit plugin which allows you to register plugins written in Ruby. Yay....

Getting Started

(Note: This assumes you have purchased and installed Minecraft already...kind of tough to mod a game you don’t actually have ;) )

In order to install Purugin you must first get CraftBukkit. CraftBukkit is a companion piece to the Bukkit library which manages Minecraft servers. Install CraftBukkit (instructions) and then get a copy of Purugin.jar and place it in your CraftBukkit plugins directory. Now also put in an example Purugin plugin player_joined.rb into the plugins directory as well. Finally, you need a copy of jruby-complete.jar (http://www.jruby.org/download) at the root of your CraftBukkit directory. Once you have did all this your CraftBukkit dir should now have these things added to it:


CraftBukkit/plugins/Purugin.jar
/player_joined.rb
/jruby-complete-1.6.1.jar


Now startup CraftBukkit:

java  -Xms1024M -Xmx1024M -cp jruby-complete-1.6.1.jar:craftbukkit-0.0.1-SNAPSHOT.jar org.bukkit.craftbukkit.Main


When it starts you should see the console come up and you will see a couple of noteworthy lines:


17:38:36 [INFO] [PuruginPlugin] version 0.1 ENABLED
17:38:36 [INFO] [PlayerJoined] version 0.1 ENABLED


So, at this point if you run Minecraft and enter the Multiplayer game at localhost (or whatever host you are running your server), you should see the message: Player {your_name} has joined.

player_joined-2011-05-12-08-42.jpg

Let’s look at the source for the player_joined.rb plugin:


purugin('PlayerJoined', 0.1) do
def on_enable
# Tell everyone in players world that they have joined
event(:player_join) do |e|
e.player.world.players.each do |p|
p.send_message "Player #{e.player.name} has joined"
end
end

# Tell everyone in players world that they have quit
event(:player_quit) do |e|
e.player.world.players.each do |p|
p.send_message "Player #{e.player.name} has quit"
end
end
end
end


Just scanning down this source I think it is fairly obvious how your were sent the Player joined message. Let’s example a few other aspects of writing any plugin. For starters there is a purugin method. This method contains the name of the plugin and the version along with a block which is the logic for the plugin. Using a block-based method for this stuff is sometimes inadequate since block scoping is a little more limiting than defining a class. For a more traditional definition using a class look at https://github.com/enebo/Purugin/blob/master/examples/player_joined_full_class.rb. I prefer using the short method-based definition up until the point it becomes a pain. For short plugins like this the method-based definition makes the plugin that much more concise. To each their own...

The next interesting bit is the lifecycle method on_enable. There are three lifecycle methods you will be concerned with: on_load, on_enable, and on_disable. You can refer to Bukkit documentation for the exact definition, but I think they are fairly intuitive. For most people you probably will only use on_enable. on_load will sometimes be used if you want something loaded before any plugin in the system has been enabled.

Inside of on_enable you will typically register events. In this case, we register listeners for :player_joined and :player_quit, but there are many many many events that you can register. You can monitor virtually anything. See the examples directory in Purugin’s source for more. [Note: :player_joined or any event name is not actually a symbol in Bukkit. This is Purugin trying to make the API look a little cleaner. At this point the documentation for Purugin is lacking, but the source is fairly small and tables for events or block types will not take long to find. Please consider helping me document things via rdoc patches of documentation on the wiki associated with this project].

Early Days

At this point, I have made a small collection of examples that are included with the source. I recommend looking at these as a way to get started. commands.rb is a plugin for registering commands. locs_plus.rb is a plugin which uses commands.rb for registering it’s own commands. ports.rb is a simple teleporter plugin (out of specially marked signs) which shows how to look at blocks.

Over time, I (someone) will make some more guides and help flush out the API better. This is a very humble start with an API I knew very little about. Expect change and perhaps help facilitate that change via Github issues and pull requests (or editing the wiki).

2 comments:

  1. This. Is. So. Awesome.

    I had wished for quite a while that there was a ruby API to build minecraft plugins.

    This is spectacular, and I'm so glad you've done the work to make it possible.

    Thank you so much for this :D

    ReplyDelete
  2. Any recommendations for hosting companies? I'd rather not run the whole thing myself as I already have a full time job...

    ReplyDelete