Custom Blocks & Ores

The next thing we will need is a Red Diamond Ore block to drop our Red Diamond Item, when it is mined.  However, before rushing off and creating a new ore block, let’s take a step back and learn about blocks in general.  Block and Ores are really very similar to each other.  In fact, in terms of Minecraft, they are really the same thing.  Ores are just blocks that do a couple of additional things.  However, from a programming perspective there is not really a big difference between them.  Since we need an ore block, we will talk about ores, and everything will apply to blocks as well. 

Similar to items, blocks will need to extend a block related superclass, such as Block, BlockOre or BlockOreStorage.  Further, blocks have a set of properties that need to be initialized to give our block its unique characteristics.  In fact, some of the properties will be familiar, but then others are very different.  The most common set of properties are explained below.  In adition, blocks also need to have an associated Material, which be explained in the next section. 

Block ID (blockID) will be a number from 0 to 4095.  However, the ids from 0 to 173 have already been used by Minecraft and are not available.  The astute reader may be wondering why block ids are limited to 4095.  It does seem a bit odd.  Well, the reason is because internally Minecraft is using a blockList array to store all of the blocks indexed by their ids, and that array was sized to 4096 cells, thus only giving the range of 0 to 4095.  In addition, for the block id we need to be careful with the numbers used, because items and blocks will share the same number set.  By default Minecraft uses 0-173 for blocks and 256-2267 for items.  Thus it is a good idea for you to segment your custom items and blocks into different ranges.  For example, 3000-4000 for your blocks and 5000-6000 for your items. 

The Icon (blockIcon) or texture files are used to render how the block will appear.  These are just 16×16 pixel PNG files, with a transparent background, very similar to items.  However, there is one big difference with block textures, you are able to use multi-textures for your blocks.  This means that you can have different textures for the different views of your block.  Currently, Minecraft supports a bottom view, a top view and a side view for all four sides. 

The Material (blockMaterial) will be the type of material.  This will be a Material object, and it is generally best to use one of the predefined material types in net.minecraft.block.material.Material.  There is a long list, but a few examples would be ground, wood, rock, water, etc…

The Step Sound (stepSound) will be the sound that is made when the block is stepped on.  This will be StepSound object that models a “.ogg” file, but these will not be discussed.  In general, it is best to use one the predefined sounds in net.minecraft.block.Block.  There is a long list, but a few examples would be soundWoodFootstep, soundGravelFootstep, soundGrassFootstep, etc…

Hardness (blockHardness) will affect how many hits it takes to mine the block.  It is a float number from 0.0 (tall grass) to 50.0 (obsidian) with bedrock being indestructible.  Technically, the limit is only the size of a float variable, but you should keep this to reasonable values.  If you would like to make your block indestructible, then set the Hardness to -1.0 or use the setBlockUnbreakable() method.  Caution, when you set Hardness it will also reset the BlastResistance to a factor of 5 times the Hardness. 

Blast Resistance (blockResistance) will affect how the block is damaged by explosions.  This is also a float number with default values that range from 0.0 (tall grass) to 6000000.0 (bedrock).  If being set via the setter, it will be set to 3 times the input value.  However, it might also be set by the Hardness, so if you need this to have a specific value, then it will be necessary to set it after setting the Hardness. 

Light Value (lightValue[]) will affect how much light is generated from a block.  It will be a float number from 0.0 to 1.0, with 1.0 being the brightest.  This is another place where the 4095 limitation is imposed upon blocks, because this is an array of integers, indexed by the block Id.  Internally, Minecraft will convert the float number into an integer between 0 and 15. 

The Internal Name, the External Name, and Creative Tab are exactly the same as with the items. 

Finally, there are two methods that are not properties, but these two methods are critical to the character of a block.  They will determine what gets dropped and how much of it gets dropped.  These are the idDropped() and quantityDropped() methods.  They are both defined in the Block superclass, with the default behavior of dropping the item itself as a quantity of one.  So if anything else is needed, then these methods will need to be overridden in the subclass. 

Material Properties

Each block needs to have an associated Material object, which is used to provide additional characteristics to blocks.  There is a large set of predefined materials, and generally speaking you should be able to find what you need in the existing ones.  However, you could create a custom one, if there is a need.  Creating a custom block material will not be discussed, but you will be provided with enough information to be able to create one, if needed.  The block materials will have the following properties:

  • Flammability (canBurn) – ability for the block to burn
  • Replace-ability (replaceable) – ability to be replaced (eg: tall grass can be replaced)
  • Translucent status (isTranslucent) – ability to allow light to pass through the block
  • Mobility (mobilityFlag) – ability to be pushed
  • Requires tool (requiresNoTool) – needs a tool to be able to harvest the block
  • Map Color (materialMapColor) – the color the material will appear on the map

Note: The Material object should not be confused with the EnumToolMaterial which is an enumeration and only used for tools. 

Custom Red Diamond Ore

Now that we are armed with a general understanding of blocks and ores, we can work on the custom Red Diamond Ore.  The basic steps that we will need to follow are outlined below.  We will use the Block superclass, instead of one of the alternatives, for the sake of demonstrating interesting concepts. 

  • Create new class block.RedDiamondOre that extends Block
  • Define the id, internalName & externalName for item
  • Create a constructor and set properties
  • Override registerIcons(), getIcon(), idDropped() & quantityDropped() methods
  • Register the block in base class
  • Create the icons & make them available

These steps will be broken up into smaller pieces to make them easier to understand.  Let’s start with the first part of the the RedDiamondOre class. 

 

package reddiamond.block;

 

mport java.util.Random;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

import reddiamond.RedDiamondInfo;
import reddiamond.RedDiamondMod;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.util.Icon;

public class RedDiamondOre extends Block {
    
    public static int id = 3000;
    public static String internalName = "redDiamondOre";
    public static String externalName = "Red Diamond Ore";
    
    @SideOnly(Side.CLIENT)
    protected Icon topIcon;
    @SideOnly(Side.CLIENT)
    protected Icon bottomIcon;

    public RedDiamondOre(int id, Material material) {
        super(id, material);
        setHardness(3.5F);
        setStepSound(Block.soundStoneFootstep);
        setUnlocalizedName(internalName);
        setCreativeTab(CreativeTabs.tabBlock);
    }

 

Here we are giving our new ore block an id of 3000, which is well above the Minecraft range, and should avoid conflicts.  We give it the internal name similar to that of the class, except the first letter is lowercase.  The external name is easy to read and makes sense for our ore block.  This is what players will see when in the game. 

We need to create two new class properties for the top and bottom icons.  These are in addition to the default blockIcon, which is defined in the Block superclass.  These three icons will be used to make our block multi-textured.  Notice that these have the client side only annotation, so they don’t get used on the server side. 

Finally, in the constructor we are calling the Block superclass constructor.  Then we set the hardness to 3.5, which 0.5 harder than diamond ore, and will by default set the blockResistance to 3.5 * 5 = 16.5.  For the sound, we just use the same sound as stone, which should be fine.  We remember to set the unLocalizedName, because f you don’t the game will not be able to properly find your new ore.  And we place our new ore in the tab with the other blocks, which makes perfect sense. 

Next, we need to override idDropped() and quantityDropped() methods to be able to change what gets dropped and how much of it gets dropped. 

 

    @Override
    public int idDropped(int metadata, Random random, int fortune) {
        return RedDiamondMod.redDiamondItem.itemID;
    }
    
    @Override
    public int quantityDropped(Random random) {
        int maximum = 3;
        int minimum = 1;
        int n = maximum – minimum + 1;
        int i = random.nextInt() % n;
        int dropped =  minimum + i;
        if (dropped < 1){
            return 1;
        }
        return dropped;
    }

 

For what gets dropped, by default Minecraft will drop the block itself.  However, for our Red Diamond ore we want to make things interesting and drop at least one Red Diamond.  To do this we need to override the idDropped() method.  Notice: this returns the item or block id that will be dropped, which is one of the places where the id number set needs to be managed carefully. 

For how many of the Red Diamonds will get dropped, we will need to override the quantityDropped() method.  All this returns is an integer with the number.  Here we are generating a random number between 1 and 3. 

Next, we will think about registering the new Red Diamand Ore with the base mod class.  In the RedDiamondMod class, we need to create an instance, which would be done in properties section of the class.  Notice: we make it public and static, which make it easily available to any other class.  Next, we need to insert the registration commands in the load() method.  Not surprisingly, we use the GameRegistry.registerBlock() to add the RedDiamondOre to the set of blocks that MC knows about, using the internal name to identify it.  Then, we give it an in-game name with the LanguageRegistry.addName().  As you can see this is very similar to how we registered our custom item. 

 

public static Block redDiamondOre = new RedDiamondOre(RedDiamondOre.id, Material.rock);

GameRegistry.registerBlock(redDiamondOre, RedDiamondOre.internalName);
LanguageRegistry.addName(redDiamondOre, RedDiamondOre.externalName);
MinecraftForge.setBlockHarvestLevel(redDiamondOre, "pickaxe", 3);

 

Finally, we set the harvest level of our custom Red Diamond Ore to require a diamond pickaxe to be able to harvest our block with the MinecraftForge.setBlockHarvestLevel() method.  The first parameter is the block to be registered.  The second parameter is a string that represents the toolClass.  There are three predefined toolClasses: "pickaxe", "shovel", and "axe“.  However, you can create custome toolClassess.  The third parameter is the tool material tier is 0 for wood/gold, 1 for stone, 2 for iron, and 3 for diamond. If you want to allow for it to be harvested by more than one toolClass, then just need to repeat the command again for that toolClass. 

Custom Red Diamond Ore Textures

Now, let’s create a texture for our Red Diamond Ore.  This will be similar to the texture used for the Red Diamond Item, except this will be a multi-texture.  What that means is that the block will use different textures for the different sides of the block.  There will be one texture for the top view.  There will be a different texture for the bottom view, and yet another texture for the four side views. 

We will need to do the same steps as with the custom item, except want to do it for the three views:

  1. Create a temporary directory, or use the same temporary directory created for the item
  2. Create a copy of the diamond_ore.png to start with from the default Minecraft textures (i.e.: mcp\temp\src\minecraft\assets\minecraft\textures\items)
  3. Edit that to add some red and make the blues darker, this will be used for the side views
  4. Then make a copy and increase the brightness for the top view
  5. Go back to side view, make another copy, and decrease the brightness to make it darker, this will be the bottom view
  6. Ensure that the three PNG files are named appropriately, RedDiamondOre_bottom.png, RedDiamondOre_top.png and RedDiamondOre_side.png
  7. Create an assets subdirectory for blocks and copy the texture file into it (i.e.: src\minecraft\assets\reddiamond\textures\blocks)

 

With the texture files created, we can go back to the Java class and finish up there.  You will need to override the registerIcons() and getIcon() methods as shown below. 

 

@Override
@SideOnly(Side.CLIENT)
public void registerIcons(IconRegister iconRegister){
    this.blockIcon = iconRegister.registerIcon(
    RedDiamondInfo.MOD_ID + ":RedDiamondOre_side");
    this.topIcon = iconRegister.registerIcon(
    RedDiamondInfo.MOD_ID + ":RedDiamondOre_top");
    this.bottomIcon = iconRegister.registerIcon(
    RedDiamondInfo.MOD_ID + ":RedDiamondOre_bottom");
}

@Override
@SideOnly(Side.CLIENT)
public Icon getIcon(int side, int metadata) {
    if (side == 0){
        return this.bottomIcon;
    }
    else if (side == 1){
        return this.topIcon;
    }
    return this.blockIcon;
}

 

The textures need to have been created, and be in the assets/reddiamond/textures/blocks directory, named as RedDiamondOre_side.png, RedDiamondOre_top.png, and RedDiamondOre_bottom.png.  The blockIcon is defined in the Block superclass, but the topIcon and bottomIcon will need to be defined in the RedDiamondOre class.  Notice: here we are setting all three of the views in the registerIcons() method. 

In the getIcon() method, we test the side parameter to tell us what side the player is viewing the block from.  We need to display the correct view depending upon their relative position to the block.  The possible values are:

  • 0 – viewing from the bottom,
  • 1 – viewing from the top, or
  • 2 to 5 – viewing from the side

Notice: the use of the @SideOnly annotation to ensure that both the variable and methods are only used on the client side.

At this point, you should be able to launch Minecraft via the Eclipse Run button and verify that your Red Diamond Ore block is available and will drop a Red Diamond when mined.