I know some of you were expecting me to blog about my recent trip to Lebanon, but it’ll be a long post so I’m blogging about the next best thing, a little sample project I worked on during my trip to Lebanon, I wrote a very simple wrapper for the Minecraft Server in C#
Did I hear Warcraft ?
No, I said “Minecraft” ! If you have never heard about Minecraft before then you’re either dead or you really hate Twitter and YouTube !
But I’ll try to explain it anyways, Minecraft is a creative game were you walk around in a (almost) infinite terrain made of blocks of different kinds, you can place and destroy blocks to create anything you can think of, and in Survival Mode (the beta version) you can “craft” different tools (according to certain recipes) to help you collect (or “mine”) the different kinds of blocks in a game, and unless you’re in “peaceful” difficulty, dangerous monsters spawn in the dark that try to attack you.
This might not sound interesting, but it’s know that NOBODY was able to fully and correctly describe Minecraft, some people don’t even consider it a game at all
So the only way to understand the game is to experience it yourself, and if you need to learn how to play the Alpha/Beta (Survival Mode) you can start with this video and continue with the rest of that great series of videos made by PaulSoaresJr
The development of the game started around May 2009 by a cool guy called Markus Parsons (aka Notch) who later founded “Mojang” with a bunch of other cool people, I started playing the free creative version of the game on the 29th of September and got a pirated copy of the Alpha version on the 7th of October and finally bought it once they allowed direct credit card payments on the 16th of December (right before the Beta was released), I knew about Minecraft from a bunch of videos tweeted by @WindowsGamer, and I’ve been a huge fan of the game from the moment I started playing it !
The Minecraft Server
Minecraft has a multiplayer mode that allows a bunch of people to connect to a server and play the game together and collaborate on building awesome stuff, Mojang doesn’t host any Minecraft Servers so people have to host their own, some famous people/communities host Minecraft Servers so other people can join them, and some normal people just host a server themselves and share their external IP with their friends so they can join them, I personally start my server every now and then so me and friend @Mohab_Elkaref or my brother can join my amazing mining discoveries
You can download the server from http://www.minecraft.net/download.jsp and you either download the .EXE (which has a GUI) or the .JAR (where the GUI is optional) which is the one I chose to be wrapped because I want only my custom GUI to appear.
One of the reasons to create a wrapper for the Minecraft Server is to make your own custom GUI instead of the default one because the default one is just a fancy console window with a box on the side showing the memory consumption and another showing a list of connected players, so you still have to manually type commands to control the server, i.e.: BORING !
The System.Diagnostics.Process Class
I used the Process class found in the System.Diagnostics namespace to allow my application to interact with the Minecraft Server, if you never used it before then you can check its documentation here.
The first time I used that class was back when I was making Asteroids v1.2, I used to it to launch my old website in the users browser when he presses the Spacebar when he’s on the Credits screen
Then a few weeks ago I was searching StackOverflow and stumbled upon a someone’s question, I don’t remember what was his question but I remember that he used the Process class to launch cURL and make an HTTP Request with it then get the HTTP Response that it receives (I think it’s a silly way to do a simple task), this was possible because cURL prints the response on it’s console window through the Standard Output Stream which you can read from your C# application using the Process.StandardOutput field !
Until that time I (naively) thought that the only use for the Process class was to launch applications from your code, I didn’t know that you can access it’s Standard Output, Standard Error and Standard Input Streams along with other info about the process while it’s running !
The moment I understood how it’s done I thought about the Minecraft Server, because you can interact with it through a console window and because I’m wanted to know how people wrote mods and wrappers for it (I’m holding on about the mod part until Mojang release the official Modding API).
Time for some code !
First of all, if you ignore the Minecraft-specific features of the code and do a few small changes, this application can then act as a wrapper for ANY other application that prints and/or reads from the Console
Secondly, I used WPF to make the interface of the Wrapper because it’s easier and better than the old WinForms, but if you’re targeting the .Net Framework 2.0 or older then you can design a WinForms interface and do some modifications to the code.
Thirdly, I’ll just write some parts of the code here, the full source code will be available at the end of this post.
Ok the first thing you need to do is create a ProcessStartupInfo object to specify which file to run and set other related variables:
1: var startInfo = new ProcessStartInfo("java", "-Xmx1024M -Xms1024M -jar " + ServerFile + " nogui");
2: startInfo.WorkingDirectory = ServerPath;
3: startInfo.RedirectStandardInput = startInfo.RedirectStandardError = true;
4: startInfo.UseShellExecute = false;
5: startInfo.CreateNoWindow = true;
In the 1st line I define the file name and arguments of the process, you’ll need to have the Java directory included in the PATH System Variable to be able to just write “java” in the file name, otherwise you’ll have to put something like “%PROGRAMFILES%\Java\jre6\bin\java.exe”, for the arguments I wrote those CrAzY JVM Garbage Collection parameters that the Minecraft Server require to run smoothly followed by “–jar” cause we’re running a JAR file then the JAR file name then “nogui” which is an argument for the Minecraft Server itself so it doesn’t show the GUI.
In the 2nd line, ServerPath is the location of my Minecraft_Server.jar file for the working directory.
Then in the 3rd line I state that I want to Redirect the Standard Input and Standard Error Streams so that I can Write and Read to these streams from my application, notice that the Minecraft Server uses the Standard Error Stream to print to the console instead of the Standard Output Stream, it took me a long time to figure that out on my own
Then in the 4th line I have to set UseShellExecute to false to be able to redirect the Streams, but I don’t understand why
In the 5th line I set CreateNoWindow to true so that the Server’s console window doesn’t show up, you can also achieve the same result if you run “javaw” instead of “java”.
And now to create the Process object:
1: Process ServerProc = new Process();
2: ServerProc.StartInfo = startInfo;
3: ServerProc.EnableRaisingEvents = true;
4: ServerProc.ErrorDataReceived += new DataReceivedEventHandler(ServerProc_ErrorDataReceived);
5: ServerProc.Exited += new EventHandler(ServerProc_Exited);
There are a bunch of ways you can read from the Standard Error/Output Stream of a Process, most of them are asynchronous in some way because if you try to read and there is nothing to read your application will block, the easiest way I found was to use the Process.ErrorDataRecieved event (as you can see in 4th line) because you don’t have to manually handle a new thread that keeps on reading input from the stream.
Line 3 is there to enable the Process.Exited event, so I can do some stuff right after the process has exited.
Then to start the Process (and thus the Minecraft Server) all you need to do is:
1: ServerProc.Start();
2: ServerProc.BeginErrorReadLine();
To be able to see the output of the Server that’s read from it’s Standard Error Stream I wrote this in the ServerProc_ErrorDataReceived method:
1: Dispatcher.Invoke(new Action(() =>
2: {
3: ConsoleTextBlock.Text += e.Data + "\r\n";
4: ConsoleScroll.ScrollToEnd();
5: }));
Notice that the ServerProc_ErrorDataReceived method will be called by a thread different that your main thread so you have to use your WPF Window’s Dispatcher to insert the output text on any WPF control that was created on the main thread (i.e.: almost all of them).
The Dispatcher.Invoke method takes a delegate containing the code that you want to run on your main thread, I tried passing a Lambda Expression directly to it but for some reason it refused to consider it as a delegate, so I had to wrap my Lambda Expression in an Action delegate.
If you’re using a version of the C# compiler earlier than v3.0 or if you’re allergic to Lambda Expressions then you can use and Anonymous Delegate or write a separate method with lines 3 & 4 and encapsulate it in the Action Delegate instead.
Future Plans
In the future I might add a command auto-discovery feature where the application sends the “help” command (which lists all possible commands) to the server and parses the output and display buttons in the GUI for each command and ask for the command’s parameters if it needs any, this is important because more commands might be added when you update your server and because Server Mods also add commands.
I can also add an auto-complete feature for player names and their IP addresses so you don’t have to type them yourself.
Another useful feature might be a history for commands that were previously written so you don’t have to rewrite the whole command when you initially mistype it or when writing a bunch of similar commands.
Another feature that just bumped into my head is to add batch operations, so you can have for example a button that teleports all players to you and another that gives a certain player one of each diamond tool/armor
The main plan I have now and will work on my free time is to make a Web Application wrap the Server instead of a WPF Application, so that I can run a Minecraft Server on my GoDaddy Web Server and have an admin page to interact with the Minecraft Server and monitor it’s status
I just hope that the GoDaddy shared server doesn’t block my web app when it tries to run a new Process
Full Source Code
Here is the link to the whole Visual Studio 2010 solution, if you only have Visual Studio 2010, you can just copy the code from MainWindow.xaml and MainWindow.xaml.cs into a new WPF Application project.
I hope this helps people who wanted to make Minecraft Server wrappers or just wanted to establish a simple communication between your application and another
Update (22 July 2011): A nice dude called “Juri” took my code and added a few features to it like Server Command History (which I wanted to do, but was lazy ), implementing the /list command to all players (not just ops) and the /motd command found in most Mods, he posted it in the comments below but I wanted to put it up here so everyone can see it, here is the link for his code: http://www.megaupload.com/?d=HE7T04KC
(if for any reason the link got expired by mega upload, I’ll put on SkyDrive )
Update (13 March 2012): The feds shutdown MegaUpload, so I re-uploaded Juri's code on skydrive, here is the link.