Basic Modding - Block dropping customized Item

Goal

I want to show you how to create Blocks which can drop custom Items.

Difficulty

3/10 - Relatively Easy

Prerequisites

Forge Version

This Tutorial was created with Forge 10.13.0.1180 for Minecraft 1.7.10. If anything doesn't work with other versions, please contact me!


Blocks dropping a customized Item

If we want our Block to drop something special, we need to create a new class for the block. We can already add the normal methods for initializing the Block correctly.

ModBlockOre.class:
public class ModBlockOre extends Block {

    protected ModBlockOre(String unlocalizedName, Material mat) {
        super(mat);
        this.setBlockName(unlocalizedName);
        this.setBlockTextureName(Main.MODID + ":" + unlocalizedName);
        this.setCreativeTab(CreativeTabs.tabBlock);
        this.setStepSound(soundTypeStone);
        this.setHardness(10.0f);
        this.setResistance(20.0f);
        this.setHarvestLevel("pickaxe", 2);
    }
}

Now we need to add some fields to store the Item the Block should drop.

ModBlockOre.class:
private Item drop;
private int meta;
private int least_quantity;
private int most_quantity;

These values should be set by the Constructor of the Block, so we add some arguments to it:

ModBlockOre.class:
protected ModBlockOre(String unlocalizedName, Material mat, Item drop, int meta, int least_quantity, int most_quantity) {
    super(mat);
    this.drop = drop;
    this.meta = meta;
    this.least_quantity = least_quantity;
    this.most_quantity = most_quantity;
    this.setBlockName(unlocalizedName);
    this.setBlockTextureName(Main.MODID + ":" + unlocalizedName);
    this.setCreativeTab(CreativeTabs.tabBlock);
    this.setStepSound(soundTypeStone);
    this.setHardness(10.0f);
    this.setResistance(20.0f);
    this.setHarvestLevel("pickaxe", 2);
}

We also can add two new Constructors which have less arguments and use default values:

ModBlockOre.class:
protected ModBlockOre(String unlocalizedName, Material mat, Item drop, int least_quantity, int most_quantity) {
    this(unlocalizedName, mat, drop, 0, least_quantity, most_quantity);
}

protected ModBlockOre(String unlocalizedName, Material mat, Item drop) {
    this(unlocalizedName, mat, drop, 1, 1);
}

Now everything is ready to create the block, but we still need to set up the methods to make the block drop what it is supposed to drop.

When a block gets destroyed the method dropBlockAsItemWithChance(…) is called. This method gets all the drops from the method getDrops(…) and calls dropBlockAsItem(…) for each of them. The name of this method is a bit weird, because it does not drop the Block itself but spawns an EntityItem at the position of the Block. The Item which should be spawned is an argument of the method.

Ok, so the Items are spawned with dropBlockAsItem(…) after the List of Items is fetched via getDrops(…).

getDrops(…) itself calls three methods to generate the list of ItemStacks to be dropped:

  • getItemDropped(…)
  • quantityDropped(…)
  • damageDropped(…)

These are the methods we have to override.

ModBlockOre.class:
@Override
public Item getItemDropped(int meta, Random random, int fortune) {
    return this.drop;
}

@Override
public int damageDropped(int metadata) {
    return this.meta;
}

@Override
public int quantityDropped(int meta, int fortune, Random random) {
    if (this.least_quantity >= this.most_quantity)
        return this.least_quantity;
    return this.least_quantity + random.nextInt(this.most_quantity - this.least_quantity + fortune + 1);
}

The method getItem(…) now returns the Item we set in the Constructor. The method damageDropped(…) does exactly the same with the metadata.

Only the method for the quantity is a bit different, because we are using a randomizer here.

We have two values: the minimum and the maximum amount of Items. The method calculates the difference of those values and adds the fortune level of the used tool plus one. This value is used as a maximum for the randomizer, to whose result we add the minimum value. I'll show you this calculation in a example:

least_quantity = 2;

most_quantity = 5;

fortune = 0; // No fortune Pickaxe equipped

 

(most_quantity - least_quantity) == 3

(3 + fortune + 1) == 4

rand.nextInt(4) // returns a random value between 0 (inclusive) and 4 (exclusive). Thats why I added one, otherwise we wouldn't reach the maximum quantity.

least_quantity + rand.nextInt(4) // is a random number between 2 and 5.

 

If we equip a fortune pickaxe, the maximum drop level rises along with the level of fortune. Minecraft uses a different calculation for this, you can take a look at it in the class "BlockOre".

 

 

We can now create a Block from our new class:

ModBlocks.class:
GameRegistry.registerBlock(tutorial_ore = new ModBlockOre("tutorial_ore", Material.rock, ModItems.tutorial_item, 2, 4), "tutorial_ore");

This Tutorial Ore will drop two to four Tutorial Items, a new kind of Item I just created with this line of code (or you can use the item we created in the first tutorial. I use the same texture anyway):

ModItems.class:
GameRegistry.registerItem(tutorial_item = new Item()
        .setUnlocalizedName("tutorial_item")
        .setTextureName(Main.MODID + ":" + "tutorial_item")
        .setCreativeTab(CreativeTabs.tabMaterials)
        , "tutorial_item);

Note that this Item must be created before you create the Ore and add the reference to the Item, otherwise it will not work.

Block dropping multiple different Items

Now we have created a Block which can drop a special Item, but what do we do if we want our block to drop multiple Items?

Well, thats nearly as easy as before: We just nees to override getItems(…).

To do this, we should create a new Block class first. This time I won't recommend placing everything in the Constructor, unless you want to create a lot of Blocks which drop multiple Items. If you only need a few you should create a new class for each one.

ModBlockMultiOre.class:
public class ModBlockMultiOre extends Block {

    protected ModBlockMultiOre(String unlocalizedName, Material material) {
        super(material);
        this.setBlockName(unlocalizedName);
        this.setBlockTextureName(Main.MODID + ":" + unlocalizedName);
        this.setCreativeTab(CreativeTabs.tabBlock);
        this.setStepSound(soundTypeStone);
        this.setHardness(10.0f);
        this.setResistance(20.0f);
        this.setHarvestLevel("pickaxe", 2);
    }

    @Override
    public ArrayList <ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) {
        return super.getDrops(world, x, y, z, metadata, fortune);
    }
}

Now we take a look at the method getDrops(…).

As a return value, this method expects a ArrayList of ItemStacks. No problem, we just create one:

ModBlockMultiOre.class:
@Override
public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) {
    ArrayList<ItemStack> drops = new ArrayList<ItemStack>();
    return drops;
}

An ArrayList is a list of Objects, determined by the class name between < and >, so in this case its an ArrayList of ItemStacks. A list has several useful methods to change it. The method we will use is the .add(…) method.


Our ore should drop everything you can get from Vanilla Ores, except emeralds. Each Item is dropped at least once, except diamond which is dropped with a propability of 50%.


You may worry where we can get our randomizer from. Luckily, each world object contains a randomizer, we can access it with world.rand.

ModBlockMultiOre.class:
@Override
public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) {
    ArrayList<ItemStack> drops = new ArrayList<ItemStack>();
    drops.add(new ItemStack(Items.coal, world.rand.nextInt(3) + 1));
    drops.add(new ItemStack(Items.iron_ingot, world.rand.nextInt(2) + 1));
    drops.add(new ItemStack(Items.gold_ingot, world.rand.nextInt(2) + 1));
    drops.add(new ItemStack(Items.dye, world.rand.nextInt(3) + 2, 4));
    drops.add(new ItemStack(Items.redstone, world.rand.nextInt(2) + 2));
    drops.add(new ItemStack(ModItems.tutorial_item, world.rand.nextInt(2) + 1));
    if (world.rand.nextFloat() < 0.5F)
        drops.add(new ItemStack(Items.diamond));
    return drops;
}

So what does our ore drop now?

You can get

  • 1-3 Coal Items
  • 1-2 Iron Ingots
  • 1-2 Gold Ingots
  • 2-4 Lapis Lazuli Items (Dye with meta 4)
  • 2-3 Redstone Items
  • 1-2 Tutorial Items
  • 0-1 Diamond with a propability of 50%


Here is the registration of the multiore:

ModBlocks.class:
GameRegistry.registerBlock(tutorial_multi_ore = new ModBlockMultiOre("tutorial_multi_ore", Material.rock), "tutorial_multi_ore");

If you want to recreate this, you can get the textures I used right here:

Tutorial Ore
Multi Ore
Tutorial Item

You can download the code used in this tutorial as a .zip file from here.


Recommended Tutorials to continue with

Take a look at the tutorial overview and find out what you want to do next!


Comments and Questions:

If you want to report modding problems, please make sure to include the code in a pastebin link or something else! Don't just write "It doesn't work", otherwise your post will be deleted. For more complicated problems, please use the troubleshooter form.