So, I’ve been exploring and having fun with Minecraft, with Forge and Java – in making new functionality. As I have mentioned earlier there is a great book on the topic, “Minecraft Modding with Forge” by Arun Gupta and Aditya Gupta.
In order to perform mods to Minecraft you need to install Java, Eclipse, Forge and this is covered completely in the book which is only $15 on Kindle. So, I’m not going to cover all that here. Also, you can mostly figure it out yourself and some quick searches of the internet.
This post targets new programmers to Java, Minecraft, and Eclipse.
What I want to cover is creating a mod in Minecraft with a custom command that has several parameters. This is also covered in the book, but I have my own slant on the process, possible errors and the code used.
Once you have Eclipse hooked up to Forge create a new package (if you have to make something up as this is not validated – com.yoururl.forge.mods – or whatever!). Right-click on your package and create a main class. Step by step shown below.
To create a package you have to right-click on the folder src/main/java.
Then enter in the name of your package and click on Finish.
Enter in code as shown above adding to the original package statement and creation of the Main class. For now, we’ll ignore any errors as you type in the code as they should be resolved after everything has been typed and you pressed control+shift+o. You don’t have to type in the import statements if you are properly connected to Forge when you type in your actual executable statements you will hit control-shift-o and they will be added automatically.
Right-click on your package and click on New->Class from the context menu.
In the dialog box enter in the name for your class. Classes always start with a capital letter (by convention although you can violate this) as shown below – our class will be called MakePyramid. Then press Finish and Eclipse will create the class file and fill in the base class stub.
The code will look something like this. Just a reminder that the package at the top will be the package that you created.
Of course, this doesn’t do much at the moment except exist as a file. So we’ll just have to make it do something!
I’m not going to teach anything about OOP. It is a big topic and I can’t treat it properly in a simple example as this. A brief explanation is that there are objects out there that perform similar functions. These functions have a signature of methods and that signature is called an Interface. If all objects that perform similar functions have the same interface it makes it easier for programmers to write code and know what to expect, where to expect it, and it tells the programming some of what functionality is the bare minimum in order for this all to work.
Our MakePyramid class is going to implement the ICommand interface. We would use this for any command that we are going to create. In order to implement an interface you simply add “implements InterfaceName” after the class name separated by a space. In this case, we will type implements ICommand after a MakePyramid as shown below.
That red squiggly line – that is an error being detected by the Eclipse IDE (Integrated Development Environment). So perhaps you might be thinking – “great example man, barely even 1 line of code and we have an error. What am I supposed to do now?
Well, fortunately, this error will be among one of the easiest to clear. Later (in other programming) there will be syntax errors that befuddle you and the last hurdle – logic errors that look like they should work, but don’t. Followed by code that looks hopelessly broken, but hey look at that it is working. Finally, when you are a true coder you’ll say things like, “uh oh” which will scare the nontechnical and “I’m surprised that ever worked.”
To fix our error we’ll just press control+shift+o and the appropriate import will be added to the code as we did in the Main class. At this point I’ll take a little time to explain it in a little more detail.
We build things on the shoulders of giants – or at least other coders, anyway. When we write our code we heavily rely on classes written by other people. Some are a part of Java, others are a part of libraries created for specific purposes. This interface that we are implementing belongs to a library that isn’t referenced (or imported) in to the code. So, it looks like an error.
Now, sometimes the Eclipse environment has a little difficulty. In my case control+shift+o works almost all the time, but not this time. There are other ways to fix the problem. You can know the library where your interface (or class) comes from and manually type in the import statement. Also, you can hover over the error and Eclipse will offer you options on how to fix the problem.
Click on the top line to import the correct library. Note that if you were creating your own new ICommand interface that is one of the options below as well as multiple other libraries that contain Command in the name of an interface. So, if we were using something else we would need to be careful which interface library we imported or changed our code. It is also good to note that if you forgot the interface name but knew part of it you could simply type it and see if Eclipse can find it for you.
Here is what the code looks like after you have clicked on the top link in the help pop-up.
Behold, we have fixed one error only to discover another error! Man the writer of this article writes some bad code.
In reality we are just going through the process of adding an interface. Earlier I indicated that an interface was a signature. This signature is composed of methods that are exposed publicly of specific data types. We haven’t added them yet so our class has an error – it says it implements an interface of ICommand, but it doesn’t contain the interfaces parts – the methods.
In order to fix this we will again hover over the error and click on the link that we need to have performed in the code. We could potentially look up the interface and type in the code for yourself, but programming and coding is about making things easier to do and taking the path of least resistance or least code.
Click on the link “Add unimplemented methods” and Eclipse will automatically add the stub of the interfaces signature in to your code.
Above you see the code that was generated. Automatically, the correct imports are added to the file for any libraries referenced as the data types in the individual methods.
This class and these methods are where we will add our code. First, let’s run Minecraft from Eclipse and see what happens.
To start Minecraft – shown above in Eclipse press the start button. It will take a little while to start up so just be a little patient. If this is the first time going in to Minecraft from Eclipse you will need to create a new world and make it a creative world. A lot of code won’t run if you are not in creative mode (mostly on purpose as you can prevent non-creative mode access to your commands.
Above you see a screen shot of Minecraft with the command entered. To enter commands in Minecraft you press the “/” and then type in the command.
There is another error! Well, not really an error. Even though we have created the class we still have a ways to go before the command will work. We have some code to enter in our new class MakePyramid and one line of code to add in to the Main class. Close out of Minecraft and let’s get coding!
While we implemented the ICommand interface we didn’t put code in any of the methods. In addition, even when this class MakePyramid is working – it doesn’t mean we have to put code in every method of the class that were created by the interface. Some of the methods it is fine just for it to exist.
We have to add one more method – this is called a constructor and it runs every time a class (the code we are creating) it instantiated and made in to an object during run time. A class can have many instances of objects. To create our constructor we are going to add a variable declaration to the class – this is a variable that is available to all the methods inside the class and depending on how we declare it – can be seen outside of the class or not. We are also going to add another variable that we will discuss later and use later. Both of these variables will be visible only internally to our class and usable by all methods of our class.
The code in the red box is what you have to add. private – means that the scope of these variables is private to this class. private is always in reference to the containing object which is the class in this case. Two additional imports are on the top of the screen. You may have to hit control-o to get them to appear. Since I copied and pasted these variables in to place Eclipse automatically added the appropriate import statement.
The first variable is of a List type – and specifically an ArrayList which allows us to add and remove elements from the list. In Minecraft, you can call commands in multiple ways. and sometimes using the long name makepyramid is too much of a bother to the end user and so they might want to just type mp. The problem with this scenario is that likely players might want to install multiple mods. If there are two commands that are mp – what runs when the user types it in? Or does it cause Minecraft to crash? So, personally, I would leave off implementing a smaller name for the command as long as your command isn’t crazy long.
Our next step is to add a line of code using the aliases variable in the getCommandName method. Don’t get too hung up on the names of functions – they can and do change over time. Functionality is deprecated between versions of Forge or Java and replaced with hopefully better functionality or at least more descriptive method names.
This is our constructor – and a single line of code to add “makepyramid” string to the aliases list. If we wanted a second name we would repeat this line of code and change the string being added to the aliases list. Now we can do a lot more in the constructor of a class – just because this one only has one line of code and all it does is add a value to a list – doesn’t mean that is all you can do.
In order of the interface adding the methods is the compareTo method. We don’t need to do anything in this method.
The next method is getCommandName. We change this method – and have it return “makepyramid” – the name of the command we want the end user to type. Code shown below:
You will notice that there is an @Override above the method declaration. This means that we are override the functionality already provided in the interface, if there is any.
The above method is a function. It is a function because it returns a value. The programmer that has written code calling getCommandAliases is expecting to get a list of the ways to call this command. The return statement (the only statement in this method) returns aliases which is of a data type matching List. If the data type didn’t match then the return statement would cause a syntax error. For example: if I had it return “makepyramid” as a string the syntax error would be – could not convert type string to type pyramid / type mismatch. Technically, the constructor method we used earlier is a subroutine – this is a method that does some work but does not return any data to the code calling that method – which in the case of a constructor is the new keyword. When using the new keyword in code you are creating a new instance of a class – which causes the constructor of the class (if present) to be run.
The next method we are going to write code in is the getCommandUsage function. This function is called when the end user enters the command /help makepyramid or generically /help commandname .
A couple of notes here from actually writing code. If you mess up certain methods your /help will stop working in Minecraft. An error is some other sections of code will result in a not authorized message appearing which is misleading when in fact you just have a problem in your code.
In the above getCommandUsage – we return a string – that tells the user the command “makepyramid” and then items inside of less-than and greater-than symbols. These are the parameters that the end user enters that tell the command more specifically what to do. In this case we want the user to type in a name of a material (or number) then the coordinates that they want the pyramid to start from (x,y,z) and then finally the base size of the pyramid – the biggest layer of the pyramid is the bottom and this also indicates how many layers up the pyramid will go.
The next step is to change the code in the getCommandAliases method to return the aliases list that we created in the class and added the value “makepyramid” to in the constructor MakePyramid method. In addition to changing the return statement I typically remove the TODO comment from the method. This means that I know for sure that I changed code in this method of the interface. Code shown below:
Now comes the interesting method. There is a lot of code (well compared to what we have been doing). The code is nested. It isn’t really that hard to understand.
As part of the ICommand interface the processCommand method was created. This is the workhorse of our class. When our command is executed by the user typing it in – this is the code that runs.
First I am going to show you the code, then I will do a walk through.
From top to bottom: The first line of code is the @Override – which indicates to override any existing functionality in the original base class. Next is the declaration of our method – which is a subroutine because it does not return any data (the void tells you that). The scope is public – which means that any other code can see this method. It throws an exception – which then would need to be dealt with in any code calling this function. Unfortunately, I think the only catch they have is to say “There was an unexpected error”, instead of forwarding on the actual error message.
I created a custom method called validArgs(). It returns a boolean (true/false) and passed to it are the args passed to the command. This if statement says “If (The opposite of the return of validArgs) return. So, validArgs returns true if all the arguments are valid. Then the ! sign reverses it and changes that value to false. Only in the case that the if statement is true will return be called. The definition of the validArgs function will be discussed in detail later.
You don’t need braces after an if statement in order for code to execute. You only need them if more than 1 line of code is to be executed. In this case, the only line of code to be executed is return; and so the minimalist approach to coding would be to eliminate the braces.
The next section of code is a series of variable declarations and assignments. Based on the values the user input these values are assigned or through some small mathematical operation.
Of interest here is that there is more than 1 variable declaration per line. Perhaps in other learning techniques it is only directly taught that each line of code is equal to one line of executable code. This isn’t true. Since lines of Java code are delimited (unlike Visual Basic .NET for example) you can have multiple executable lines of code on a single line.
Why would you do this? Well, it does make the code ever so slightly more difficult to read; however, your methods – subroutines or functions – you don’t want them to have an excessive line count. The longer the code in a single routine then reading it and understanding it become much harder. This is also the same reasoning for the validArgs() method. I could have simply validated all the input code right in processCommand(), but this makes the code really long. What the other programmer (or your future self) needs to know is that all the information was validated – and you get this from the if statement containing validArgs(). It is much more important for the future coder (whoever she is) to know the main logic of the processCommand method.
Next we start our for statements and blocks of code. The for statement has 3 major sections.
for (int y = yStart; y < yEnd; y++)
The first section – int y =yStart; // This indicates in the first section that we are declaring a variable y, the variables type int (Integer). Next is what I would call a “while” statement. As long as this section is true, the for block of code will continue to be called. Finally we have y++ // this is the increment for the variable declared in the first section. y++ is also equivalent to y = y + 1; It is a shorthand that is understood by all C#, C++, C, and Java programmers. You can also do a for statement with a decrementing statement y– which is equal to y = y-1;
If we wanted to make a pyramid that was upside down, we’d have some work to do, but you can see from this for statement how to do it. There would have to be a few other changes as well, but nothing too difficult. Now, the trick would be to make a processCommand that both makes pyramids that have the smallest point to the top or bottom without increasing the number of lines of code. Maybe next week.
There are two more for statements following the first one, and they all basically operate the same. Next up of relevance is the statement that actually creates the blocks in Minecraft.
((EntityPlayer)s).worldObj.setBlockState(new BlockPos(x,y,z), block.getBlockState().getBaseState());
The funny things about the above code is that it isn’t what I would expect it to be. Personally, I would have had block = new Block(world,coordinates); – where the block object would already have the attributes/properties necessary for creating the object – or in this case the material. Anyway, moving on to what the code actually is…
(MoreSpecificObject)LessSpecificObject – this is a cast from one object type to another. Objects follow something called inheritance. All objects (no matter what type) inherit from the class object.
Casting can be a dangerous (read – can cause your code to crash) if the object you are casting is not the type you are casting it in to. In the validArgs() method I do a quick check to see if ICommandSender s – is in fact an EntityPlayer class object. If it isn’t it throws an error. If it is then the code continues on.
EntityPlayer extends EntityLivingBase. EntityLivingBase is an extension of the Entity class. ICommandSender could be of type EntityLivingBase. It was described earlier that objects can implement interfaces. The ICommandSender is an interface (hence the I prefix). Therefore; any objects implementing the ICommandSender interface could be sent as the input to processCommand(). It could even be an object that isn’t an Entity base class type.
An object can implement multiple interfaces in Java. While this should be standard in any OO (Object Oriented) model I seem to recall that you couldn’t implement more than one interface in a single class in VB.NET.
So… (EntityPlayer)s – casts object s as EntityPlayer class. After that point a dot operator will bring up the methods and properties of the EntityPlayer class (which should have all the methods and properties of Entity and EntityLivingBase classes and new EntityPlayer methods and properties.
Based on the names of the properties and methods then we are getting the world object that s belongs. Then we are calling the worlds method setBlockState – which apparently creates a block if you send it a new BlockPos and a block object. Not only are we calling the block object, but we are calling getBaseState method of the getBlockstate method. The block object we created some time ago as a global to the class variable of type Block.
It is a little less than intuitive, unfortunately. Once understood, though, you can use this code to make blocks of any type and put them pretty much any place.
After two of the for blocks close there are a few statements increasing or decreasing some values. Each layer higher (increase in y) in a pyramid decreases the end of the x and z lengths and starts the x and z one position over.
After those statements it goes back up to the beginning of the first for loop and off it goes until we don’t go any higher.
Now, our pyramids will end up with a block of 4 blocks as the top of the pyramid. It is a little inelegant. An upgrade would be to create 4 custom blocks that combined look like 1 block centered on the top.
NOTE: if you are a VB coder and haven’t ever coded in C# or Java you may be a bit confused about some of the most minor of statements – the variable declaration. In VB.NET you would write a variable declaration as Dim x as String. However, in C# or Java – you would write this as String x; . In addition, the signature of methods that take parameters contain variable type space variable name.
Now, we wrote code in processCommand that was not defined presently. It is a good idea to keep functions, methods, and subroutines small enough to see their logic in 1 or at most 2 screens. After that it is best to break the functionality in to component pieces and call those pieces in your main function or method.
In processCommand we called a custom function called validArgs. validArgs returns a boolean. It is called in an if statement and if the if statement is true it exits our processCommand function because there is a problem.
NOTE: validArgs returns true if validations are successful. It returns false if there was a problem. This should be standard. However; to make our code clean on the calling side – so that we don’t have to code an empty true evaluation and a return in the false – which adds lines of code and decreases readability – we look for the opposite of validArgs – so if validArgs returns true, then we take the opposite of that false – and code continues down our processCommand method. If validArgs returns false, we take the opposite of that – true – and then execute the return functionality and exit the processCommand method.
validArgs defines some local variables, and then performs a series of if statements. Since most of the information passed to our functionality are numbers, we validate that these values are in fact numbers. If anything fails we return false and show a message to the end user.
In searching the internet I found the NumberUtils.isDigits function which accurately performs what we need it to do. Validating a value to be a number isn’t as easy as you would think. In Visual Basic and even in VB.NET (and therefore C#) the isNumeric functionality will let values pass that are not necessarily numbers but can be interpreted as numbers. Values such as scientific notation can be interpreted as numbers – and contain letters such as e. The problem is that when you try to perform math on these values your code will explode and you will have unhappy users.
I had to add an import – import org.apache.commons.lang3.math.NumberUtils; – in order to use this function. You may find another solution to this – or write your own. Back in my Visual Basic coding time – I had to write my own function in frustration as nothing really performed well in the base Visual Basic library.
Finally, after we do our numeric validations – we call another function. You can tell from the screenshot above that the validArgs function is quite tall. Adding in the functionality for validBlock would have made it longer and less readable. So the related functionality for validating a block is contained in one function – which can then be reused anywhere. Again, we are using the patter of coding of a function that returns a boolean, checking for the opposite of the boolean and exiting our main function (returning false) if there is something wrong. This code is shown below.
This is a fairly simple function and I won’t go in to too much detail. Just note that there is only one error message and we define it in the beginning – no matter what goes wrong in the function. There is also a try…catch utilization here – in case something really goes wrong with our code – we prevent a crash – at a price of some performance. The try… catch – is defined by the try and braces which contains the code that might cause a crash. The catch area with braces is the code that will run in case the code in the try block crashes.
There are three last methods left – but they are small or not changed from the signature of the interface.
canCommandSenderUseCommand – this was definitely changed from the original code. In fact, if you don’t change it nothing will work. In this case we are returning true if a user called this function. The direct implication is that perhaps there is a way to have an NPC call your custom function. Maybe a subject for some later tutorial or article.
The last two functions – addTabCompletionOptions and isUsernameIndex are left completely stock from the original interface.
That’s it. Next article will be able integrating a technology in to Minecraft that you wouldn’t expect.
The code is uploaded on Git – here.
Have fun and ask questions. If I don’t know the answers I’ll do what I can to figure them out.
Arrgggh. As usual for programmers – we rush through things and sometimes forget to put in vital instructions. Or not too vital as another programmer can figure out what we did and fix the problem. In this case, though, this is meant for programmers that don’t know programming yet – and so, figuring out this problem that is minor might actually turn in to a monumental task.
In the file list shown above from Git – there are 4 files. README.md – just a couple lines of text. Not really anything – you can get inventive in your own version and be highly descriptive if you want. There is Main.java file which was discussed in detail. This is what runs in Minecraft and creates your command. MakePyramid.java is the class that is called for your command and referenced in the Main.java/Main class.
So, what is SErr.java? Well, the code is shown below.
This is what I would call a static class in VB.NET or C#, but it isn’t really a static class. It is a class with a static method. What is a static class or method? Well, these are classes/methods that can be called directly that store no data. It gets more complex as you can have classes that have static and non-static methods and properties (well, if it has a property inherently this is not a static part of the class as properties store information).
What does SErr class and the s method do? Well, it is my attempt to reduce the amount of code everywhere in the application. If this class did not exist the line of code s.addChatMessage… would be repeated in our MakePyramid class every time we displayed a message. Not a deal breaker, but it does make the code unnecessarily long and harder to read.
Could the s method have existed in the MakePyramid class? Yes, yes it could. No, no, it shouldn’t.
In the real world you would be making a mod with many commands. Each of these commands would have need to create messaging to the end user indicating errors. If you put the s method in MakePyramid you make that class required for all your other mods. But what if you decide that you don’t want this MakePyramid functionality? Then you might delete the MakePyramid class and then cause errors in the rest of your code. Or just to be clear, if SErr.s – exists outside of any other mods – it can be equally called by the other mods/custom commands – and it will be called the same way in each class.
It is also in a separate class because like functions should be in like classes. Sending an error message isn’t a like function of the MakePyramid class. It is something it does, but it isn’t a direct expectation of the MakePyramid class.
Your code, until this class has been added, won’t compile. Use the instructions earlier to create a new class called SErr – and copy the code in to it. Save it and ensure there are no syntax errors. Now your code should compile.
Enjoy. Unless I find another problem. 🙂 I guess writing instructional content has inherent problems.