I made a Minecraft mod!

After 10 years of not touching Java I somehow made a Minecraft mod. The reason? I wanted to see if I could turn on my IoT living room light with a switch inside Minecraft. Great success!

The mod is called Breakoutbox and is available on my github page: https://github.com/rheide/breakoutbox.

Breakoutbox is a very basic mod that lets you 'break out of Minecraft' by calling external scripts on the serverside. Once you're out, anything's possible. Controlling IoT lights as mentioned above, pulling in cryptocurrency prices into your Minecraft world, pushing a button to make a Tweet, you name it. And building all those things is a hell of a lot easier in an ad-hoc external script than it is to publish a dedicated Minecraft mod every time. Anything and everything, all of the time.

It was interesting to experience the Java ecosystem again after such a long time away. Some observations:

  • The build system for Minecraft mods is really nice. The Forge MDK (mod development kit) comes with good documentation to get you started, and a gradle build file that makes it super easy to compile a mod jar or run a dev Minecraft server.
  • That said, the Minecraft code itself is closed-source, so from there on you're walking through decompiled, de-obfuscated bytecode, guessing at what things are ok to call, hoping the arguments you've provided make sense. This could've been an absolute nightmare, but thanks to the fact that Java is a strongly typed language, and community efforts at deobfuscating the code every time a new release comes out, it's surprisingly not that painful.
  • It's so difficult/terse to do simple things in Java, compared to Python. The Java standard library featureset is still a joke. No json or yaml parser in the standard lib? Bah.
  • I gave up trying to figure out how to bundle a third party library with my jar. Couldn't figure out if it's just not standard practice or if I then had to burden everyone who downloads the mod with also figuring out how to download the dependency. Either way seemed bad.
  • It's veerrry easy to get Minecraft to misbehave. The redstone behavior has a 'contract' in that running a redstone command should finish quickly, e.g. in less than .1 second. External scripts can easily take any amount of time, and I had to guard against that. I found it quite interesting how easily I could get a 'professional' game to break just by adding a few lines of code in a tiny jar file.
  • I managed to get around the long-running script issue by queueing the tasks in the Minecraft server object's internal threadpool, but I wasted hours trying to figure out why it wouldn't just work from my own threadpool. I had created a separate threadpool for my own tasks, but somehow the commands never executed if I ran them from my own threadpool. Queueing them in the threadpool that was kept in the server object fixed things. Without looking at the actual source code, which is impossible, it's very difficult to say why. My guess is that the internal threadpool had some kind of hooks attached to it that updated the game state at the end of each task, whereas with my own pool stuff just disappeared into nowhere and was ignored by the game loop. But who knows.

Anyway, it was a fun little exercise. It was a project I started in spite of wanting to finish other projects I had already started. I had no particular need for it, but having it available on github in the form of a downloadable jar that anyone can stick into their Minecraft server, and source code available for anyone who feels like forking it, does feel good. I will endeavor to finish more things this year.

(I think I finally have an idea in my head to reintroduce comments to this blog without incurring massive maintenance or financial costs. More to come.)

Posted in Games , Tech | Tagged , ,

A genetic algorithm in Python

Here's a genetic algorithm I wrote in 36 lines of Python. It can be shorter still, but the readability, which is already suffering, would suffer too much.

Posted in Tech | Tagged ,

Fun with Square Codes

This is a qr code:

It's used to embed data inside of it, which can then be scanned by a large variety of devices. It's widely used in Japan to advertise links to web pages, which are otherwise difficult to type on a small device like a mobile phone. But they can be used for all kinds of things. All in all it's a very cool technology, so I wanted to experiment with it.

Python and Django are my server of choice, so I started looking for a library to generate square codes in Python. I soon wandered upon pyqrnative, which is a port from a javascript version, apparently. It's very compact and easy to use. Generating images was a piece of cake. I had Django serve dynamically generated images in no-time.

But how to read these images client-side? Since I recently dabbled in OpenCV and JavaCV I learned of an easy way to access the webcam in Java, so I made a Java implementation. This step was not very difficult, so I decided to make things harder on myself by embedding the webcam part in a Java applet, so it could run from a website.

I had a bit of trouble here, as accessing native libraries (using Java Native Access) proved quite difficult. I had a lot of trouble figuring out where JavaCV was loading its dll files from, and it took me a good half hour to debug it. A list of paths to OpenCV are hardcoded in the JavaCV source code. I wanted to include the dll files dynamically, which seemed near impossible. What's worse, removing or adding paths did not seem to make any difference as to whether JNA could find the dlls or not. I finally tracked it down to one folder: /usr/local/lib was the folder where my libraries were being loaded from. Which is damn peculiar, because that's a Linux folder and I'm running Windows 7. I suspected cygwin at first, but the problem was not that: When specifying the /usr/local/lib folder, jna looks for all folders in the system variable called jna.library.path, which contains the system path by default. Very obscure...

Having figured that out I could continue building the applet. I had jump through a bunch of hoops to get it to work, namely signing the applet (which is a very good thing considering I'm running native code that accesses a webcam!) and figuring the right tags to put in the HTML. HTML tags for applets are a big bloody mess, there's no standard at all. There's a deprecated applet tag, an object tag for IE and an embed tag for Mozilla (which also works in Chrome). I chose the embed tag for now.

There's a nice method in Java's AppletContext class which lets you change the browser's document's URL. It also allows you to execute arbitrary Javascript, so you can call a javascript function that does an ajax call back to the server that can update the web page! It's all very roundabout and takes three languages and a whole bunch of libraries to get going, but it's quite cool once it works. Here's a video of the result:

Posted in Tech | Tagged , , , , ,

Sucky

As you may have heard I'm working on this website idea for a ratings site. I started the project in Java/J2EE last year and never finished it, tried Spring, gave up on Java completely and I'm now using Python and Django. I've already made more progress this way than I ever did in Java, and so far I'm quite happy with the switch. There are, however, some things that annoyed me to no end this week.

Starting from (near) scratch is a great feeling. You get to design all the cool stuff and make huge leaps of progress. But then there comes a time when the crude work is done and you need to do the finer points. That's pretty much where my frustrations began. Django is an absolutely joy to work with especially because it lets you make great leaps in the beginning. Then, once the rough sketch is complete, you have to fill it in, and for that you need knowledge of Python.

Frustration number one: Python documentation. I haven't worked with Python a lot, so I was looking for a quick cheat sheet on string operations. The official documentation is overcomplete and confusing, in my obviously humble opinion. The official Javadoc is great and even if you can't find the right info in the official documents you'll soon find a very properly maintained home page of some Java fanboy who has written down exactly the code example you needed. Not so for Python. Admittedly I made the mistake of going about it from a Java perspective first, which meant that I was using the wrong way of thinking. After 'fixing' that I came across several helpful pages with examples, none of which worked. Then I came across a page that worked, but only with a version of Python that my hoster does not use. Frustration. Were I of mischievous mind I'd say that it's a little bit like going to a third-world country and finding out that they use donkeys instead of cars. But that would be trolling. I'm just kidding though, and despite my starter troubles I'm still quite happy to use Python. It's always worth it to expand your way of thinking by learning a new language.

Second frustration: IMDB noooooooo. Why is there not a more elegant way of scraping the movie ID (the tt9395359 part in the URL) and getting the name and year of the movie? There's an unofficial API which only has name and year lookup, whereas I want to look up the movie information by using the ID. Geh. There's also data files but they don't have the ids. Oh well, I guess I'll have to do it the hard way.

Which leads to my third frustration: regular expressions.. Regexes are so quick to tempt you to make the perfect regex, making you believe that you're on the path of righteousness whereas you're really drowning in a swamp. I spent half an hour trying to think of the bestest regex that could accomplish everything I wanted in one line of code. Finally I gave up and wrote five lines of code in five minutes that did the same thing.

Posted in Tech | Tagged , ,