Basic Modding - Blocks dropping special Items

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 11.14.1.1334 for Minecraft 1.8. 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. (Note: My constructors here are protected. If your ModBlocks class is in a different package, you need to change them to public)

ModBlockOre.class:
public class ModBlockOre extends Block {

    protected ModBlockOre(String unlocalizedName, Material mat) {
        super(mat);
        this.setHarvestLevel("pickaxe", 1);
        this.setHardness(10.0f);
        this.setResistance(15.0f);
        this.setUnlocalizedName(unlocalizedName);
        this.setCreativeTab(CreativeTabs.tabBlock);
    }
}

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:
public class ModBlockOre extends Block {

    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.setHarvestLevel("pickaxe", 1);
        this.setHardness(10.0f);
        this.setResistance(15.0f);
        this.setUnlocalizedName(unlocalizedName);
        this.setCreativeTab(CreativeTabs.tabBlock);
    }
}

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 that 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. Make sure that you import the right "Random" class: java.util.Random.

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

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

@Override
public int quantityDropped(IBlockState blockstate, 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 from the first tutorial.

Note that this item must be created before you create the ore and add the reference to the item, otherwise it will not work because the item then is a pointer to null.

Blocks 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 need 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.setUnlocalizedName(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(IBlockAccess world, BlockPos pos, IBlockState blockstate, int fortune) {
        return super.getDrops(world, pos, blockstate, 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(IBlockAccess world, BlockPos pos, IBlockState blockstate, 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, the Block class has a builtin randomizer, we can access it with "RANDOM".

ModBlockMultiOre.class:
@Override
public ArrayList getDrops(IBlockAccess world, BlockPos pos, IBlockState blockstate, int fortune) {
    ArrayList drops = new ArrayList();
    drops.add(new ItemStack(Items.coal, RANDOM.nextInt(3) + 1));
    drops.add(new ItemStack(Items.iron_ingot, RANDOM.nextInt(2) + 1));
    drops.add(new ItemStack(Items.gold_ingot, RANDOM.nextInt(2) + 1));
    drops.add(new ItemStack(Items.dye, RANDOM.nextInt(3) + 2, 4));
    drops.add(new ItemStack(Items.redstone, RANDOM.nextInt(2) + 2));
    drops.add(new ItemStack(ModItems.tutorialItem, RANDOM.nextInt(2) + 1));
    if (RANDOM.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

Basic Modding:


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.