With the future/career day coming up I was wrecking my brains on what to do on the day my son visits me at my workplace. There will be stuff organized for him in the morning but I will have to entertain him for about four hours in the afternoon.
I was thinking I would bring my laptop and let him do some Scratch programming, something he already did and enjoyed. Thinking further I thought I could bring my Arduino Uno and he could blink some LEDs. The most important thing for me is to bring him into programming and not to bore him so I searched further. I thought connecting Arduino and programming to something he is really into… like Minecraft!
I came across this blog post where Rozz decompiles, hacks and recompiles Minecraft to output the health status via a connected Arduino! DONE! This project had all the ingredients I was looking for!
But instead of adding a Arduino Uno and an array of LEDs I wanted to hook up a Digispark with a RGB shield. The RGB led would change its color according to the player’s health status in the Minecraft game.
Even better for me, the guys from Digistump already created an example with which a Windows client could send color commands to the Digispark over USB. So all I did was uploading the DigiBlink example sketch to the Digispark and downloaded the DigiRGB.exe from GitHub. Firing up a command line, I could change the Digispark’s LED’s color with DigiRGB.exe and providing either a color or a RGB value as parameter. From the readme file:
Load DigiBlink example onto your DigisparkRun “DigiRGB R G B”Where R,G and B are values 0-255 for each color LEDor Run “DigiRGB Red”Where red is a valid css3 color
I tested that and it worked like a charm. Now I was wondering if I could just write a tiny Java program that executes this exe. This because Minecraft is written in Java too. This is what I did and again, worked like a charm:
package digiRGB;
public class DigiRgb {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
String[] cmd = new String[2];
cmd[0] = "C:/tmp/DigisparkExamplePrograms-master/Python/DigiBlink/windows/DigiRGB.exe";
//cmd[1] = "Red"; // first hard coded
cmd[1] = args[0]; // then using a parameter
try {
Process proc = runtime.exec(cmd);
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now, off to hacking Minecraft! We need the Minecraft Coder Pack (MCP) as this brings all the tools to de- and recompile Minecraft’s code.
I downloaded MCP v8.11 from here. This is the newest version available, but compatible only to Minecraft 1.6.4. The newest Minecraft version is 1.7.2 but the guys reckon that it will take some more time to have a MCP available that can handle this version. However, this is not really relevant for us as we are happy with Minecraft 1.6.4.
I extracted the MCP in a folder on my disk. Then I started the Minecraft client on my comp and created a new profile where I defined that I wanted to play with version 1.6.4. What happens then is that it downloads the jar file to %appdata%\Roaming\.minecraft\versions\1.6.4
Going back to the MCP folder I started the decompile.bat
file. It will take a few moments and then complaining about a missing server jar file. Just ignore that as we are not interested in the server code.
Let’s say you extracted MCP to a folder like mcp811 then the decompiled sources will be in mcp811\src\minecraft\net\minecraft\src
. Locate the file EntityPlayer.java
and open it with a notepad like application – I used Notepad++.
At the end I added the following code:
// added by roman public void setHealth(float par1) { super.setHealth(par1); arduinoOutput(par1); } // added by roman public void arduinoOutput(float par1){ String[] cmd = new String[2]; cmd[0] = "C:/tmp/DigisparkExamplePrograms-master/Python/DigiBlink/windows/DigiRGB.exe"; int healthPercent = ((int)par1)/2; /* System.out.print("[Arduino] par1: " + Float.toString(par1)); System.out.print(" / healthPercent: " + Integer.toString(healthPercent)); System.out.println(" / getMaxHealth: " + Float.toString(this.getMaxHealth())); */ if (healthPercent <= 2) { cmd[1] = "Red"; } else if (healthPercent > 2 && healthPercent <= 5) { cmd[1] = "Orange"; } else if (healthPercent > 5 && healthPercent <= 7) { cmd[1] = "Yellow"; } else { cmd[1] = "Green"; } Runtime runtime = Runtime.getRuntime(); try { Process proc = runtime.exec(cmd); proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } }
It’s necessary to override the setHealth()
method. I called its super method and then did the call that actually sends the color code to the DigiSpark/Arduino.
Also note the System.out.print
statements. They will be displayed in Minecraft Launcher’s development console. Quite handy when debugging. But don’t forget to comment them out / remove after debugging as these calls hit Minecraft’s performance big time!
I saved the class file and then recompiled the source using the file recompile.bat
. At the end this complains too about missing server sources… just ignore it.
After that we need to obfuscate it again using reobfuscate.bat
. This will create the file uf.class
in folder mcp811\reobf\minecraft
.
Now we have to mod Minecraft. Go back to %appdata%\Roaming\.minecraft\versions\
and copy the folder 1.6.4
. Place the copy in the same folder (versions) but rename it. I renamed it to 1.6.4.1
. Note: You can name it to whatever you want, just make sure it’s not an existing Minecraft version number! Just be consistent with the naming.
Go into that folder and rename 1.6.4.jar
to 1.6.4.1.jar
and 1.6.4.json
to 1.6.4.1.json
. Open 1.6.4.1.json
in a notepad and edit the 2nd line from
"id": "1.6.4",
to
"id": "1.6.4.1",
and save it.
Open 1.6.4.1.jar
with WinRAR. Delete the folder META-INF
! You will get a black screen when trying to start the game otherwise.
Update the obfuscated file uf.class
: Drag it from folder mcp811\reobf\minecraft
and drop it into the 1.6.4.1.jar
file you still have open in WinRAR. Then close WinRAR.
Start the Minecraft client again and create a new profile:
Here you can see that we have our mod 1.6.4.1 as an option. Choose it and then start the game. Once in Minecraft all I did was looking for the nearest lake to get drowned:
Sorry, but i can ‘ t understand. Where is the class uf?.