Skip to content

Clojure on Bukkit minecraft server

December 12, 2011

 

This morning, I finally managed to get the basic skeleton of the bukkit clojure plugin “host” working correctly. Clojure doesn’t like having to straddle across classloaders in order to find the resources it needs! I can’t say I blame it :)

It’s a fantastic feeling being able to code plugin stuff on the fly – and as a glimpse into that world, I’ve created a small timelapse video demo’ing some basic possibilities. Apply some imagination though, I’m sure you’ll come up with some awesome stuff..

Most importantly for me is the exploratory nature of Clojure – It fits very well into the nature of Minecraft. It’s thrilling to be able to discover and tweak code for your plugin on the fly.. But see for yourself: Make it full screen btw.

And yes. I get killed by a spider.

Check out the code that makes this little thing tick:

The Clojure plugin source is at : https://github.com/CmdrDats/clj-minecraft

The code (memorystone v2) used in this video: https://github.com/CmdrDats/clj-memorystone

I’m planning to build a leiningen template so that starting a new clojure bukkit plugin is as simple as lein new bukkit-plugin [plugin-name]. I’m also re-implementing my MemoryStone plugin just so that I have a base to work from in order to really flesh out the shared clojure library.

One idea I’m toying with is making a more intuitive way of registering listeners to Bukkit. I’m not sure if I’ll actually end up with anything other than a convenience wrapper function for .registerEvent, but it’s worth messing with.

As you can see in the clj-minecraft project, I’m wanting to provide a fairly solid set of basic plugin building blocks so that you have simple access to the fundemental building blocks of plugins. My goal is also to implement and wrap some common plugins, such as SpoutCraft and the various Economy managers.

I would like the 3rd party libraries to be supported in a way that automatically “switches off” when the plugins aren’t present, so that plugin developers don’t have to worry about it besides actually making sure they have alternative methods of using their plugins.. But we’ll see as I thresh this out.

Feedback will be hugely appreciated and I always welcome a helping hand! So please, contact me, fork my repo’s and make pull requests!

 

About these ads

From → Everything Else

5 Comments
  1. THANK YOU.

    Last week I did a google search on Clojure plugins for Bukkit, and found an old post on the forum, and started working on it myself. Being a bit of a clojure (but not a lisp) newb, I was given the opportunity to learn a lot about leiningen, AOT compiling, and gen-class. I was just about to dive into the scary world of classloading and bukkit when I thought I would do another google search, and saw some VASTLY different results. (namely yours!)

    Here is my somewhat unsucessful attempt if you are interested: https://github.com/jonnay/Watership-Down

    Anyway, nice one. and thanks again!

    • Hi Jonnay,

      Awesome, I’m glad you found the plugin useful before you needed to dive into the hairy mechanics of classloading :) I’ve got some cool ideas for making plugin development nice and simple, but it’s all brewing in my head waiting for me to have a nice free evening or three to hash it out!

      I like the idea of your Watership Down! I love achievements! It would be quite nice to have a plugin that specializes in providing achievements – I wonder if there’s a way you could make it have an API that other mods can easily hook into to unlock their own custom achievements?

      My idea is that i want to make event listening super simple and lightweight so that your actual plugin code that provides actual real functionality will be almost purely stuff that your plugin provides, but still give you flexibility to leverage every part of the bukkit architecture even if the api’s change in the future.

      Anyhow – please feel free to build your plugin using the clj-minecraft as a dependancy, and then add any extra functionality you think will be useful for plugins across the board and make a pull request – I’ll be sure to pull it in!

      PS. I desperately need to change the way the def clj-plugin*, clj-server*, etc works – I don’t think it’s a very idiomatic clojure implementation. :/ Suggestions welcomed!

    • Jonnay,

      I’ve been developing a one-off clojure plugin for my server, for use in occasional events for the server I play/mod on. I was having the same classloader issue as you did, due clojure’s default *use-context-classloader* and the wrong context classloader being used. I found that in Bukkit’s JavaPluginLoader if I called Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()) prior to the call to Class.forName (restoring the classloader afterwards), this issue went away. As this is what clj-minecraft does in its ClojurePlugin class when loading clojure files, I ended up specifying cljminecraft.ClojurePlugin as the main class. See CmdrDats’ clj-memorystone as an example.

      As an aside, finding clojure’s conversion of dashes to underscores a pain. Renamed my plugin as ClojurePlugin didn’t handle “xp-decay” as a plugin name too well.

      Thanks, CmdrDats! As I’m still new to clojure, your plugin’s saved me many, many hours of trial and error :)

  2. I am such a clojure newb that I cannot give you any kind of input there. Sorry. :(

    Speaking of API changes, does the auto-proxy macro provide annotations a-la the new event system?

  3. Oh yea, and about achievements, I want the server admin to be able to set their own custom achievements based on what is entered in a config file. I need to actually write some code to see if it will work, but I’d like the format of the yaml file to basically mirror the event system, so a block break event on block ID 1 would map to block-break:stone in the yaml configuration.

    And of course, gaining an achievement would trigger an event, which means you could have meta-achievements!

    So essentially, as long as a plugin provides events for when things happen, then Watership Down could listen for it. A great example is crafting events, which isn’t normally provided by Bukkit proper, but Spout DOES provide them.

    If there is a significant difference in execution speed on AOT code, I guess one could write a ClojureAotPlugin class easily enough.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: