Tag Archives: Java

Minecraft Mod-Entwickung

Nachdem es in dem letzten Blogpost gelungen ist, das eigene Smart Home mit Minecraft durch die Erweiterung ComputerCraft zu verbinden, geht es nun an eine erste eigene sogenannte Mod. Für die Minecraft-Laien: Eine Mod steht für das englische Modification und beschreibt Erweiterungen (Plug-ins) zur Anpassung von Spielen. So lässt sich Minecraft beinahe beliebig um eigene Ideen ergänzen.

iotworkshop
Connected Worlds and IoT: Digital Crafting Habitat Workshop vom 23. April 2016 gemeinsam mit der rheinjug Düsseldorf.

Diesen Weg geht auch das Digital Crafting Habitat. Hier wird die reale mit der virtuellen Welt verbunden. Zum Einsatz kommen Raspberry Pis, Sensoren, die Datenbank Redis und natürlich Minecraft. Dafür wird eine Minecraft Mod im Rahmen von Workshops weiterentwickelt. Den Java-Code auf Basis von Minecraft Forge 1.7. stellt das Digital Crafting Habitat in ihrem GIT-Repository inklusive zahlreicher Beispiele zur Verfügung.

Einrichten

Wer ganz von vorne anfangen möchte, der benötigt Java-Kenntnisse, ein wenig Gradle und eine Entwicklungsumgebung wie Eclipse IDE oder IntelliJ IDEA. Die wesentliche Zutat ist jedoch Minecraft Forge in Form eines Mod Development Kit, kurz MDK. Dieses kann in der gewünschten Version unter http://files.minecraftforge.net/ heruntergeladen werden. Die Version ist durchaus wichtig, da sich die Programmierschnittstelle (API) häufig verändert. In diesem Beispiel kommt Version 1.8.9 zum Einsatz. Eine eigenständige Version von Minecraft ist übrigens nicht unbedingt erforderlich, da diese schon im MDK enthalten ist.

Für das Setup sollte man sich unbedingt ein wenig Zeit nehmen und über eine ordentliche Internetverbindung verfügen. Als erstes wird nun das MDK heruntergeladen und entpackt – es handelt sich hierbei um ein normales Archiv. Innerhalb des entpackten Ordners fehlt noch eine optionale gradle.properties-Datei mit dem folgenden Inhalt, um die nächsten Schritte zu optimieren:

1
2
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx1024M

Anschließend wird über die Kommandozeile via gradle setupDecompWorkspace ein Arbeitsbereich inklusive einer Minecraft Programmierschnittstelle erzeugt und abschließend durch gradle eclipse bzw. gradle idea für die gewünschte Entwicklungsumgebung eingerichtet. Jetzt kann man schon den Workspace in Eclipse oder das Projekt in IntelliJ öffnen und Minecraft inklusive der Mod über die Kommandozeile gradle runClient bzw. direkt aus der Entwicklungumgebungen heraus starten. In Eclipse findet sich das innerhalb der RunConfiguration unter Java Application, in IntelliJ innerhalb des Gradle-Views unter Tasks/forgegradle.

Programmieren

Der Programmierung steht nun nichts mehr im Wege, abgesehen von einer etwas verteilten und unvollständigen Dokumentation. Gute Quellen sind der YouTube-Kanal „Minecraft Forge Modding 1.8”. Gamepedia und natürlich die Website von Minecraft Forge (http://www.minecraftforge.net/) sowie dessen GIT-Repository.

Meist benötigt man eine Java-Klasse, um den Mod zu initialisieren und die eigenen Erweiterungen dort zu registrieren. Die Initialisierung erfolgt über die Annotation @Mod unter Angabe eines eindeutigen Bezeichners.

1
2
3
4
5
@Mod(modid = SmartHomeMod.MODID, version = SmartHomeMod.VERSION)
public class SmartHomeMod {
 
	public static final String MODID = "smarthomemod";
	public static final String VERSION = "0.1";

Dazu passend muss noch die mcmod.info-Datei im Ressourcen-Verzeichnis src/main/resources angepasst werden – insbesondere die Bezeichnungen (modid) müssen identisch sein:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
 {
  "modid": "smarthomemod",
  "name": "SmartHome",
  "description": "My Minecraft Smart Home",
  "version": "${version}",
  "mcversion": "${mcversion}",
  "url": "http://wolter.biz",
  "updateUrl": "",
  "authorList": ["Sascha Wolter"],
  "credits": "",
  "logoFile": "",
  "screenshots": [],
  "dependencies": []
 }
]

Innerhalb der Klasse können nun verschiedene Ereignisse verarbeitet werden. Gängig sind

  • FMLPreInitializationEvent für alles vor dem Start,
  • FMLInitializationEvent für alles währen des Starts,
  • FMLPostInitializationEvent für alles nach dem Start und zum Schluss
  • FMLServerStartingEvent während des Starts des Servers (auch lokal ohne expliziten Server).

Der richtige Ort für den eigenen Code hängt davon ab, was genau man in Minecraft verändern möchte. Beispielsweise kann man eigene Kommandos erst während des Starts des Servers registrieren. Die komplette Klasse sieht dann so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package biz.wolter.minecraft;
 
import biz.wolter.minecraft.commands.HelloCommand;
import net.minecraft.command.CommandBase;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
 
/**
 * @author Sascha Wolter
 */
@Mod(modid = SmartHomeMod.MODID, version = SmartHomeMod.VERSION)
public class SmartHomeMod {
 
	public static final String MODID = "smarthomemod";
	public static final String VERSION = "0.1";
 
	/* Commands */
	public static CommandBase HELLO_COMMAND = new HelloCommand();
 
	// FMLPreInitializationEvent happens as #1 right before Minecraft loads. Used for most registration.
	@EventHandler
	public void preInit(FMLPreInitializationEvent event) {
	}
 
	// FMLInitializationEvent happens as #2 when Minecraft loads.
	@EventHandler
	public void init(FMLInitializationEvent event) {
	}
 
	// FMLPostInitializationEvent happens #3 when World generators and alike are loaded.
	@EventHandler
	public void postInit(FMLPostInitializationEvent event) {
		System.out.println("postInit");
 
	}
 
	// FMLServerStartingEvent happens #4 right before starting the server.
	@EventHandler
	public void registerCommands(FMLServerStartingEvent event) {
		event.registerServerCommand(HELLO_COMMAND);
	}	
 
}

Das zugehörige Kommando wird von der CommandBase-Klasse abgeleitet und überschreibt die folgenden Methode:

  • getCommandName, um den eigenen Namen anzugeben,
  • getCommandUsage erklärt die Nutzung und
  • processCommand führt letztendlich das Kommando aus.

Der vollständige Code könnte dann so aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package biz.wolter.minecraft.commands;
 
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
 
/**
 * @author Sascha Wolter
 */
public class HelloCommand extends CommandBase {
 
	public static final String COMMAND_NAME = "hello";
 
	@Override
	public String getCommandName() {
		return COMMAND_NAME;
	}
 
	@Override
	public String getCommandUsage(ICommandSender sender) {
		// TODO
		return String.format("/%s <name>", COMMAND_NAME);
	}
 
	@Override
	public void processCommand(ICommandSender sender, String[] args) throws CommandException {
 
		if (sender instanceof EntityPlayer) {
			sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "Hello " + args[0]));
		} else {
			sender.addChatMessage(new ChatComponentText(
					EnumChatFormatting.RED + "This command is not available inside the console."));
		}
 
	}
 
}

Das Kommando wird in Minecraft nun über den Chat (Taste T) und mit einem führenden Schrägstrich eingegeben. Innerhalb der processCommand-Methode könnten nun natürlich auch komplexerer Anweisungen platziert werden, die beispielsweise ein Smart Home steuern. Oder man erfindet gleich eigene Gegenstände und Blöcke, die mit der Außenwelt kommunizieren…

Maschine-zu-Maschine Kommunikation per GSM (Cinterion EGS5), Teil 1

Die Vernetzung unterschiedlichster Geräte vom Toaster bis zum Auto schreitet voran. So wird unsere Umgebung immer mehr zu einer Art Benutzeroberfläche, bei der die Gesamtheit der intelligenten Geräte die eigentliche Anwendung ausmacht.

Es gibt zahlreiche populäre Plattforme wie I/O-Boards à la Arduino oder Einplatinen-Computer à la Rasperry Pi, die das Erstellen solcher Lösungen bereits für verhältnismäßig kleines Geld erlauben. Auch die Telekommunikationsanbieter wie Telefonica und Deutsche Telekom mischen in diesem Bereich mit und helfen durch Hardware-Bundles, dem Bedarf angepasste SIM-Karten und speziell für diesen Bereich entwickelte Services sowie APIs.

Apropos SIM-Karte und GSM basierter Vernetzung: Interessant ist hier beispielsweise das auf dem Cinterion EGS5 basierende Developer-Kit der Firma MC Technologies. Dieses zeichnet sich außerdem dadurch aus, dass es Java als Entwicklungssprache unterstützt.

Setup und Modem-Treiber

Nach dem Zusammenbau inkl. SIM-Karte wird das Cinterion basierte Board im einfachsten Fall per USB mit dem Entwicklerrechner verbunden, das Stromkabel angeschlossen und anschließend durch die unter Cinterion EGS5\Treiber mitgelieferten Treiber als Modem verfügbar gemacht. Um die nicht mehr ganz taufrischen Treiber auch unter Windows 8 ins System zu bekommen habe ich mich dem Trick aus diesem Video hier bedient. Als nächstes benötigt man den zugewiesenen seriellen Port – diesen ermittelt man beispielsweise im Gerätemanager (bei mir ist es COM8). Außerdem ist im Developer Kit auch gleich noch ein passendes Konfigurationsprogramm Cinterion EGS5\SDK\CCFG_00-01-00-33\CCfg.exe enthalten, mit dem man die Funktionsfähigkeit des Setups gleich testen kann, indem der COM-Port eingetragen und die rote Read-Schaltfläche unten links zum Auslesen der Eigenschaften betätigt wird.

AT-Befehlssatz

Einmal eingerichtet, kann das Board als Modem per AT-Befehlsatz gesteuert werden. Hierfür nutze ich das Terminalprogramm PuTTY. Auch dort muss natürlich der COM-Port eingetragen werden. Außerdem ist es hilfreich in der Kategorie Terminal die Option „Local echo“ per „Force on“ zu erzwingen. Anschließend kann man das Modem nun per Kommandozeile steuern. Ein guter Start ist das Abrufen von Statusinformationen wie der aktuellen Signalstärke via AT+CSQ oder des aktiven Profils via AT&V.

SMS senden und empfangen

Eine schöne Fingerübung für den AT-Befehlsatz ist der Versand einer SMS. Nach dem Aktivieren der PIN (sofern erforderlich) über AT+CPIN=1234 (natürlich mit der passenden PIN) und dem Festlegen des Textmodus via AT+CMGF=1 wird der Versand durch den AT-Befehl AT+CMGS=03212345 (natürlich mit der passenden Rufnummer) eingeleitet. Jetzt erfolgt die Eingabe der Nachricht, die mit der Tastenkombination Strg+Z abgeschlossen wird. Der eigentliche Versand geschieht automatisch. Übrigens können Textnachrichten auch empfangen und z. B. per AT+CMGL="ALL" aufgelistet werden. Die Details einer empfangenen Nachricht zeigt der Befehl AT+CMGR=1, wobei die 1 dem Index der Nachricht entspricht.

The voice controlled coffee machine

I recently had a DiY workshop together with my Developer Garden colleague and firefighter Frank Zimmer and the great guys from Oracle. Oracle is working on M2M devices – obviously based on Java. After some Java experiments with a Cinterion driven embedded device this was my first time playing with the famous Raspberry PI and Java. Raspberry PI is a very small Linux PC similar in size to embedded boards like Arduino or .Net Gadgeteer. Our approach was controlling a coffee machine with a phone to serve George Clooney a coffee (sorry, in this case I was George Clooney´s lame replacement, but the Nespresso is real).


We hacked a Nespresso coffee machine, connected it to a Raspberry Pi and controlled it via phone. Please note, the video is just a rough cut to illustrate our proof of concept.

First of all we start the machine and need to wait until the machine is ready. But you can spend your time for so many things better than waiting: say writing Java. So we hacked the machine and connected it to the Raspberry PI running a small Java program. This program initiates a phone call via the Telekom Tropo API once the coffee machine is heated up. Now we need the way back from the phone to the Raspberry PI to finally start the coffee making. This is handled by Telekom Tropo which translates a phone call into a parameterized request which than writes a token. This token is handled by the Raspberry PI to start or stop the coffee making process.

I hope I can convince my friends from Oracle to publish the hardware specs and the Java code. And if you want to learn more about M2M and IVR-Systems (interactive voice response), feel free to come to our TechTalk at the 13th of December in Berlin.

Update: Some people asked how we did connect the Raspberry Pi and the coffee machine: Therefore we use the GPIOs and the Java library Pi4J.