cljminecraft
This plugin enables other Clojure plugins on CraftBukkit. This doesn't do much on its own except open up a clojure REPL and add some sample commands.
See http://github.com/CmdrDats/clj-minecraft for most up to date instructions on how to use this plugin.
Also, be sure to look at the wiki for more in-depth instructions on all the moving parts: http://github.com/CmdrDats/clj-minecraft/wiki
cljminecraft has two specific goals:
- Open up support for other clojure plugins on Bukkit
- Provide convenience functions to make writing plugins more idiomatic to clojure.
The first objective is accomplished within the ClojurePlugin.java class and the cljminecraft.core namespace. It will take care of calling the [plugin].core/start function, passing in the Bukkit plugin object for local plugin state handling.
The second objective is accomplished by the various other namespaces in clj-minecraft. I'm keeping the structure fairly flat and concise so that one can write idiomatic code for 80% of the plugin code.
Usage
Install the mod
Download the latest server mod build from http://dev.bukkit.org/server-mods/cljminecraft/files/ or build it yourself by cloning the repo and `lein uberjar`
Copy the jar into the Bukkit plugin folder and fire up your server. Once started, it should have opened a REPL port, by default on port 4005.
If all you wanted was to enable clojure plugins on your server, you're done. If you want to write some code, read on.
Write some code
From now on, you will need leiningen installed - see https://github.com/technomancy/leiningen
On your command shell, run:
lein repl :connect 4005
Now you have an active connection to push code onto the server, let's try some stuff (the part before => is the REPL prompt...):
user=> (in-ns 'cljminecraft.core) #<Namespace cljminecraft.core> cljminecraft.core=> (ev/find-event "break") ("painting.painting-break-by-entity" "hanging.hanging-break" "painting.painting-break" "entity.entity-break-door" "hanging.hanging-break-by-entity" "player.player-item-break" "block.block-break") ;;; block.block-break looks good.. lets see what we can get out of it cljminecraft.core=> (ev/describe-event "block.block-break") #{"setExpToDrop" "isCancelled" "getEventName" "setCancelled" "getExpToDrop" "getPlayer" "getBlock"} ;; Cool, getBlock looks like I can use it.. cljminecraft.core=> (defn mybreakfn [ev] {:msg (format "You broke a %s" (.getBlock ev))}) #'cljminecraft.core/mybreakfn cljminecraft.core=> (ev/register-event @clj-plugin "block.block-break" #'mybreakfn) nil ;; Test breaking a block, I get a crazy message, let's make that more sane cljminecraft.core=> (defn mybreakfn [ev] {:msg (format "You broke a %s" (.getType (.getBlock ev)))}) #'cljminecraft.core/mybreakfn
And that's a quick taste of interactive development.. The Rabbit hole goes rather deep :) enjoy.
Roll your own mod
Once you've got the cljminecraft mod installed on bukkit and you've played a bit with the REPL, you might want to build your own fully capable plugin:
lein new cljminecraft yourplugin
This will create a subfolder called yourplugin with the basics needed to get started, with some sample configuration in src/config.yml and the plugin.yml already setup under src/plugin.yml, ready to roll.
cd yourplugin
lein jar
cp target/*.jar /path/to/bukkit/plugins/
Start up your Bukkit server and go, by default, you'll see a message when you place a sign and there will be a command '/yourplugin.random' which does a dice roll. Very exciting stuff!
Remember to update your details in the plugin.yml and README.md files - and very importantly, commit to github to share with the world.
Time to hack away.
Changelog:
Please see the http://github.com/CmdrDats/clj-minecraft project description there for the up to date changelog.
Contributions
A huge thanks to aiscott and basicsensei for their contributions to clj-minecraft!
Please feel free to fork and make pull requests if you want to contribute, I love code contributions - it makes the whole project that much more well rounded. On that note, we're desperately needing documentation, so if you're keen to contribute to the wiki, let me know.
License
Copyright (C) 2012 Deon Moolman
Distributed under the Eclipse Public License, the same as Clojure.
@jarsen
:) The only caveat to be aware of is that you can't post the resulting plugins on the Bukkit Dev site since clojure relies on bytecode manipulation in java, which the bukkit guys flag as unsafe.
There may be a workaround if you manage to ahead-of-time compile all the code and somehow strip out the bytecode manipulation from the Clojure jar (maybe using something like proguard), but that seems way more effort than it's worth..
But, if you can live with that limitation, it's a whole lot of fun to write plugins interactively on a running server, pushing code live and seeing instant results :D
Also, huge kudos to Roger Allen who has recently brought this project up to speed with the latest version of Bukkit.
Awesome. So excited to write some plugins with clojure.
To be honest with you. I'm to lazy to even read that.
-Cjk25
This is pure unfiltered awesome. Thanks!
@Sahee
Hi Sahee,
I find it a lot more straightforward to write code for Bukkit in Clojure - It might look scary, but when you've learnt Clojure, plugin dev becomes really amazing.
Also, the fact that you get to live code and query the state of the world directly from inside a REPL prompt gives you immediate feedback, so you can test stuff without writing much at all.
The REPL prompt above does look intimidating, but the actual code you type is this:
Here I redefine the mybreakfn function again to update the functionality - no restarts, reloads or anything. It just works.
The minimal code that's needed looks like this:
This is more complicated then normal java plugin O_o