Creating Minecraft Plugins In Any Programming Language
This is a bit of a different post from what I usually write about, but hopefully those who are interested in programming, Linux, or Minecraft will enjoy it.
Despite being a building game, Minecraft is often praised for its circuitry features and mods that allow people to learn and apply computer science principles while having fun in the game.
One thing that is often overlooked, is what can be done using only the vanilla game and external programs.
In this post, I will describe a simple method of creating "plugins" using almost any programming language for a Minecraft server/world, including a proof of concept script written in Python.
Unfortunately, this method likely only works on POSIX compliant systems (so Linux, Mac, *BSD, etc) and not Windows. If anyone knows how one would go about this method or a similar one on Windows, let me know.
I had a few goals in mind when I started this project, which I successfully accomplished:
- Full compatibility with an unmodified vanilla jar (files such as world data do not count as the jar)
- Reasonable resource consumption
- Comparable stability to Craftbukkit style plugins and redstone
- No client modifications
Anatomy of a Minecraft server
The vanilla server jar is a single file that runs continually as a daemon. If run with the 'nogui' argument or without a GUI, it outputs information and accepts commands via a simple command line interface.
Traditionally, this has just been used by admins to ban players and as a log system.
POSIX to the rescue
POSIX systems benefit from a well defined standard for various system functions such as consoles and standard i/o.
I realized that since the server accepts consistent i/o, it wouldn't be too difficult to automate a server. I initially thought GNU Screen would be a good choice, but unfortunately GNU Screen has some bugs and quirks that made me instead choose tmux.
So that was it. I now had a good API for sending automated commands to the server. For parsing data back from the server, I opted to pipe the console to a text file for easier development, but the tmux API can read from tmux as well.
Parsing server output
Minecraft server output is consistent, starting with the current time, such as
[02:45:06] [Server thread/INFO]: Preparing level "world"
Due to the consistent log, it was easy to implement a "command" system in chat. Unfortunately this had to be done with "."'s instead of slashes.
Limited log data
A limited amount of information is logged in the server console, so for more complex information such as player inventories, health, entity information, and other data, I used a Python NBT API to extract information from the server.
Sadly, if you update player NBT information while they are still online, changes are not reflected in game. As far as I know, the player needs to be offline for manually modified NBT information to be seen in game. (The NBT can still be indirectly modified using commands in game)
This method of writing plugins is obviously not as powerful as Java modifications or servers implemented from scratch, however some surprising things can be accomplished, such as a virtual currency system, communication to and from a web application, custom commands for teleports, 'home setting', land protection, "McMMO" recreation (a popular Java plugin for rpg-style stats and abilities), and potentially even multi-world teleportation (which I have not tested and believe it would require some network-level hacks).
Perhaps one of the best parts, "plugins" using this method will rarely break between Minecraft versions, allowing communities to instantly switch to the latest version on release date, or even snapshots (which rarely get traditional plugin support).
Compatible programming languages
Any programming language that can interface with tmux or possibly Screen (if you can get past the annoying screen related bugs) can be used to write "plugins" with this method. No longer is server plugin creation restricted to Java or whatever your server software supports.
Proof of concept
I have published a proof of concept (and unfinished/buggy) "plugin" written in Python, under the name Pyckaxe on Github.