Jump to content

  • Curse Sites
Become a Premium Member! Help
Latest News Article

[TUTORIAL] Learning to mod Minecraft


  • Please log in to reply
6 replies to this topic

#1

cheechako
    cheechako

    Lapis Lazuli Collector

  • Members
  • 1163 posts

Posted 05 August 2011 - 09:52 PM

Step one: Learn Java.

It’s that simple. Well, maybe it is not simple. But honestly, if you put as much time and effort into learning Java as you did playing Minecraft or other games, you may not become a multi-millionaire game-author like Notch, but a lot of this stuff will be so damn simple. I see so many “modding” questions in these threads that have absolutely nothing to do with Minecraft or modding. They are basic Java questions. Let’s take the following examples. The first file has no bugs - trust me.
Spoiler:
If you look at the inherited class, you can see that this class doesn’t really do anything beyond what Block does other than set a specific material. In fact, we could do this by just instantiating a Block with:
Block mySimpleBlock = new Block(blockID,  textureID, Material.ground);
Let’s assume our custom block does a little more, or at lease we’ll get there eventually. But also take note of the fact that we have not overridden the idDropped or quantityDropped methods from the base class. If you look at those methods, it is obvious that they return 1 of the specific block. So if that is good enough for your block, there is no need to override these with custom methods.

By the way, if you use Eclipse (or another Java IDE) instead of Notepad++, all you have to do is right click the word Block, select Open Declaration, and then you can easily skim through the code or look through the list of methods and properties in the Outline panel as shown in this image:
Spoiler:

Now the real example:
Spoiler:

First of all, note my preferred style of vertically aligning brackets most of the time. This can make it easier to spot one of the errors, which I’ll get to in a bit. Let’s take the errors one by one:

package net,minecraft,src;
The dot (or period or full stop) is a very important and basic character in Java code. Generally, it is used to indicate a hierarchy of elements and child elements. In this case, src in minecraft in net, whatever that is. You don’t even have to understand package to know that you cannot substitute a comma.

public class mod_buggy extends BaseMod
Eclispe will tell you that the public type mod_buggy must be defined in its own file. This is true; the file we have is not named mod_Buggy.java. The class must use the same name without the java extension. Java is case sensitive.

public final static Block MyFinalBlock;
This is not an error. It is not even a warning. But it will cause problems in a bit, especially if you don’t know what final or static mean.

public static Block MyStaticBlock = new BlockNotBuggy(9997,0).setBlockName("myStaticBlock");
/* Generates this error (or something similar):
 * Caused by: java.lang.ArrayIndexOutOfBoundsException: 997
 * at net.minecraft.src.Block.<init>(Block.java:46)
 * at net.minecraft.src.Block.<init>(Block.java:75)
 * at net.minecraft.src.BlockNotBuggy.<init>(BlockNotBuggy.java:4)
 */
At first glance, we might think that figuring out this error requires some knowledge of how Minecraft handles blocks and block ID. However, understanding the error message and some trial and error would allow anyone to figure it out. 997 is not valid for some array. The error message eventually suggests a file and line number that should be recognizable by whomever wrote the code. Trying smaller numbers until you stumble upon the fact that valid IDs (the limits of some array) range 0-255. Knowing that about Minecraft makes this error easier to spot.

public static Item MyItem = new Item(MyFinalBlock.blockID + 1000);
Again, there is no error here were it not for the fact that we’ve already declared MyFinalBlock as final. Eclipse will warn you with a squiggly red line and the message, “The blank final field MyFinalBlock may not have been initialized.” Final values are basically constants, and should not be used before they have been initialized. In fact, it is probably best to initialize any static value before use, although statics at least have a default of null, 0, or whatever.

You should normally work top-down. All the declarations you see at the ends of example files are due to how the classes are decompiled. Most programming languages prefer declarations first, and if you stick to that rule-of-thumb, you will be less likely to run into problems like this one.

MyFinalBlock = new BlockNotBuggy(99).setName("myFinalBlock");
Eclipse tells you that the constructor BlockNotBuggy(int) is undefined, and so it is. Look at the constructors in BlockNotBuggy. (The word constructor is not techno-geek. It is a basic concept of Java and other OOP languages.) There are no constructors in BlockNotBuggy that take one integer as an argument. The only constructor takes two integers.

ModLoader.RegisterBlock(myStaticBlock);
Again, Java is case sensitive.

Now, on to the recipes. In some cases, the problems might not be obvious to someone that doesn’t know Minecraft or what a crafting recipe is. With a few examples of proper recipes (like a glance at the bottom of Block.java and Item.java), I think any competent coder could spot all the errors.
Let’s take the last recipe first:
ModLoader.AddRecipe(new ItemStack(MyFinalBlock, 1), new Object[] {
	"\  ", "\tt", "\  ", Character.valueOf('d'), Block.dirt, Character.valueOf(“t”), Item.MyItem
	});
This recipe has the purest Java errors - no knowledge of Minecraft crafting required. The backslash is a special character, and should not be used in a string like that. Characters vs. strings is a basic concept in any language that supports strings, and these special characters are common to many of those languages. Usually, backslash-t is the tab character. Also note that Character.valueOf() takes one character as an argument (as explained in the error message), and anything surrounded by double quotes is a String. Always double-check your punctuation, and stick with letters unless you know the special characters.

The other error involves the use of Item.MyItem. Eclipse reports: MyItem cannot be resolved or is not a field. Again, you do not need an understanding of Minecraft - just Java - to know that MyItem was probably never declared in the Item class and, since it was declared near the top of the file, perhaps you meant MyItem without the “Item” reference.

Now, back to the first two recipes:
ModLoader.AddRecipe(new ItemStack(MyItem, 1), new Object[] {
	" d ", "ddd", " d", Character.valueOf('d'), Block.dirt.blockID
	});
ModLoader.AddShapelessRecipe(new ItemStack(MyStaticBlock, 1), new Object[] {
	MyItem, Item.dyePowder, 1, 11
	});
To Java, this code is fine. You will never see an error in Eclipse or when the code is compiled. These recipes could cause Minecraft to crash, though. Yet a coder without any knowledge of Minecraft but with access to a few examples of proper recipes could probably figure out the pattern of the template strings and the array of Objects, and why these are wrong.

A shaped recipe takes equal length strings are the template. Notice that the last string in the first recipe is just a space and a d - two characters instead of the three used by the other strings. Looking at other examples, you can see that the rest of the array is filled with matching pairs of a character and some object. You don’t have to know what that object is - you just need to know that it is an object. So, looking at the Block class, you can find out that the blockID is an integer, and thus not an object.

The next recipe has a similar problem. If we look at some examples, we can see that the Object array for a shapeless recipe is only a list of objects. The numbers 1 and 11 are not objects, and are probably invalid entries based on known examples. The proper entry is:
new ItemStack(Item.dyePowder,1,11)
Important note: This could be the first error in this file that actually requires knowledge of Minecraft code on top of programming knowledge, although if you look at enough examples, you’ll eventually stumble across one that uses an ItemStack. In fact, I would imagine any competent coder would have already noticed the use of an ItemStack as the first argument, and think it might apply in the Object array as well.

public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer)
This method seems valid, and will even compile without errors - except the one described below. However, taking a quick peak at the methods in the BaseMod class via the Java Docs or the Outline, we can see that there is no method being overridden. There is nothing wrong with creating a new method here; but you must consider how and when this method will be called. The name of the method (thanks to the MCP team) implies that it is some sort of event, and is probably called by the game engine. Searching around for this method, which can be narrowed down if you’ve noticed the extensive use of the Item and Item stack classes, will lead you to a method in the Item class. Thus the method belongs to an item. If you need to override this method, you will have to do so by creating a new class based upon the existing Item.

Even if you ignore all of that, you can put this method in this file without errors. It will just never be called. That is as long as you remember to return a value - in this case, an ItemStack object. Now you may think this line:
if (itemstack != null)
will always be true. How can you right click an item stack unless you have an item stack? The problem is that the Java compiler has no idea if this will always be true. Assuming the condition could be false, the program will continue, eventually reaching the end of the method. Something still must be returned. If you don’t care what that is by that point, you could always return a null value as the object. Eclipse even warns you with the message, “This method must return a result of type ItemStack.”

Next, we move on to the closing brackets. By lining them up, you should quickly spot the mismatched one. The one directly in-line with the if actually closes the one that opens the method. Eventually, we wind up with one too many closing brackets.

Finally, we come to
public String Version()
This method must be present in any class derived from BaseMod. That is because the method is abstracted, so it is up to the derived class to define it. (Abstraction may not be Java-101, but it is still an important concept to grasp as you start to derive your own classes.) However, since it is outside of the closing bracket (even if we fix the problem explained above), it is not present in the class.

Anyone well-versed in Java, C++, or many other languages could have found most of the errors in mod_Buggy.java. With the Java Docs and maybe a few recipe examples, they probably would have found them all, without any knowledge of Minecraft or how to mod Minecraft. If you couldn’t find the errors because you don’t know how to mod, you are wrong. Nearly all of the errors involve basic Java and programming knowledge, and have nothing to do with the game, ModLoader, or anything else.

And yes, this is a tutorial. Hopefully I’ve taught you to go to the Oracle Java Tutorials, or the New Boston Java Video Tutorials, or some other tutorial, book, or site to learn the basics of programming before you start to program.

Consider this a quick overview of programming in Java, and a kick in the pants to get motivated in the right direction.

Register or log in to remove.

#2

MinistryofGamess
  • Location: Holland
  • Minecraft: MinistryofGamess

Posted 05 August 2011 - 09:54 PM

seems descend. Good job!

Posted Image


#3

JustCallMeCloud

Posted 05 August 2011 - 10:12 PM

This tutorial does very little to actually teach how to mod in Minecraft. Its more of a list common errors that may be done in Java. Thanks though.

#4

cheechako
    cheechako

    Lapis Lazuli Collector

  • Members
  • 1163 posts

Posted 05 August 2011 - 10:21 PM

View PostJustCallMeCloud, on 05 August 2011 - 10:12 PM, said:

This tutorial does very little to actually teach how to mod in Minecraft. Its more of a list common errors that may be done in Java. Thanks though.

And if you don't understand learning to code before starting to code, then I cannot help. Anyone is welcome to find some tutorial that shows you how to create a green block and turn it to an orange one. That is not how you learn to code, ignoring the brute force method. IMHO, knowing how to program is as crucial having a compiler/decompiler the JDK, and Minecraft.

I've only written this to stress the point about learning Java (or another preferred language.) I realize that many will ignore this, and we will still see no end to questions like, "what does symbol not found mean?"

#5

docj98
    docj98

    Redstone Miner

  • Members
  • 661 posts
  • Minecraft: Doctorj98

Posted 06 August 2011 - 12:41 AM

Ok, I understand what you mean to "Learn Java Terms" on the other post. I will go on to one of the websites you have on there, before I continue to attempt to make the mod.
Posted Image
Spoiler:

#6

cheechako
    cheechako

    Lapis Lazuli Collector

  • Members
  • 1163 posts

Posted 06 August 2011 - 04:29 AM

I think the first step (learn Java or at least some programming) is an important step that many people skip.

Again, I want to stress this fact: Some people who have mastered the basics of some language like C++ but don't know a thing about modding MC will spot most or all of the errors in my sample code. Some people with little to no programming experience but who have created a block in Minecraft by following a tutorial could easily miss most of the errors.

Once you get a good base of programming knowledge under your belt, it will be easier to focus on modding Minecraft and not tracking down and fixing minor newbie mistakes. As you try to do more advanced things with your mod, tutorials will help less and less. The only help you'll have is digging into the code, and the only way to do that is to understand what it is that you are reading. I don't know the Aether team, but I would bet money that they had prior programming experience and did not follow some "dimension tutorial".

This programming knowledge will also carry on to future game modding, projects, or whatever. Maybe you'll even move on to phone apps and get rich. :)

#7

Virgoth098

Posted 12 November 2011 - 06:55 AM

So...if i get the error The blank final field <block name here> may not have been initialized, how do i fix that?
Posted Image
Posted Image Posted ImagePosted Image  Posted Image