Crafting and Smelting

From Minecraft Forge
Jump to: navigation, search

So, you've successfuly set up a base mod, and are ready to start modifying the game? Chances are, you'll have a recipe or two added to the game, and recipes are easy. There are three classes of recipes: Shaped, Shapeless, and Smelting recipes.

Contents

General Crafting Knowledge

Adding recipes usually happens within the "preInit" method of the generic mod (tutorial.generic.Generic) to ensure that recipes are loaded after all the blocks, however anywhere in the three @EventHandler annotated methods will work. For this tutorial, I will be using the preInit method.

ItemStacks

Blocks and items in Minecraft don't have multiple instances per block/item type. Instead, these blocks and items are stored in inventory in ItemStacks. You can find all of the vanilla (unmodded) Minecraft blocks and items in net.minecraft.block.Block and net.minecraft.item.Item, usually at the top. As such, if you are playing with recipes, it might be a good idea to grab those lists.

An ItemStack has a couple of constructors, depending on the quantity and damage value of the item used.

The ItemStack takes the following Syntax

ItemStack stack = new ItemStack((Object)ItemType,[(int)Stack Size],[(Object) Metadata]

Parameters (A fancy word for the thing you put in the circular 'brackets' (also called Parenthesis)) in the above statement marked with Square Brackets ([]) are Optional

Which means:

If we wanted to create a "stack" of 1 Cobblestone:

ItemStack cobbleStack = new ItemStack(Blocks.cobblestone);

For a stack of 15 Cobblestone:

ItemStack cobbleStack = new ItemStack(Blocks.cobblestone,15);

And now for that third parameter: Metadata

Let's say you had an item like Wool, which has several "colors", but is held as a single type, we'd have to use the Metadata parameter (which unfortunately requires us to also use the size parameter too) in order to access the alternative colors of wool:


ItemStack woolStack = new ItemStack(Blocks.Cloth,1,15);

Where "15" in the above example is the metadata value for "Black" wool, this will give you a single item of "Black Wool"

However, let's say we only have the ID (Example ID of 1) of an item and want to use it to create a stack of one; (Note, this is not reccomended).

ItemStack itemId1Stack = new ItemStack(Item.getItemById(1),1);

Shapeless Crafting

Shapeless Crafting is crafting recipes where the order of items doesn't matter. Some common examples of this include Mushroom Soup and Books. The Syntax of adding a shapeless recipe is:

GameRegistry.addShapelessRecipe(ItemStack result, Object... recipe)

Not sure what that "..." is doing in this method signature? It's an actual part of Java saying "and the rest of the parameters are Objects, which should be in an Object[] called recipe." It basically allows you to not have to type new Object[] { } in every recipe, though that is also possible.

The common vanilla recipe for explaining recipes is trading in nothing for something. In this case, we will trade in dirt for diamonds.

GameRegistry.addShapelessRecipe(new ItemStack(Item.diamond,64), new ItemStack(Block.Dirt));


Mod 200 diamond from dirt.png

Microoptimization
A microoptimization is to create any ItemStack you use multiple times outside of the recipes and just use the reference to it.

If you want multiple items required, put in more ItemStacks. If you want more of the same item, just put the ItemStack in again. For an example, here's a slightly more expensive recipe that uses sand, gravel, cobblestone, and six dirt.

ItemStack dirtStack = new ItemStack(Block.dirt);
ItemStack gravelStack = new ItemStack(Block.gravel);
ItemStack cobbleStack = new ItemStack(Block.cobblestone);

GameRegistry.addShapelessRecipe(new ItemStack(Item.diamond,64,
    dirtStack ,dirtStack ,dirtStack ,
    dirtStack ,dirtStack ,dirtStack ,
    new ItemStack(Block.sand),gravelStack,cobbleStack);
);

Shaped Crafting

Shaped recipes come in all sizes from 1x1 to 3x3. Strings are used for the recipe shape and values. The method signature is roughly as follows:

GameRegistry.addRecipe(String row1, [String row2[, String row3]]char itemType1, ItemStack itemStackType1[, ... char itemTypeN, ItemStack itemStackTypeN]);

That's probably confusing, so a couple of examples should clear this up. Let's say that we want a 2x2 recipe where two dirt and two gravel in the corners gives you one cobblestone. To do that, we use the following snippet:

ItemStack gravelStack = new ItemStack(Block.gravel);
ItemStack dirtStack = new ItemStack(Block.dirt);

GameRegistry.addRecipe(new ItemStack(Block.cobblestone),
    "AB",
    "AB",
    'A',dirtStack, 'B', gravelStack);

What this is basically saying is: to give us a single Cobblestone, We need the top left, Top Center, Bottom left and Bottom Center of the grid to be used, where A is then substituted for a Dirt and B is substituted for a gravel.

Error creating thumbnail:
Symmetric Recipes
If you have symmetric recipes like the two demonstrated in this section, it will help your players if you add the recipe with the recipe items switched. The simplest way to do that is to copy the recipe, and switch dirtStack and gravelStack around.

I find that the newline after the shape helps readability of the recipe.

So, what do you do when you want an empty space in your recipe? Well, the space character (" ") is already designated to do that. To demonstrate this, the following recipe takes alternating gravel and dirt in a circle to make stone.

GameRegistry.addRecipe(
    new ItemStack(Block.stone),
    "xyx",
    "y y",
    "xyx",
    'x', dirtStack, 'y', gravelStack);

Mod 200 stone.png

NOTE: If you need help with shaped recipes, check out this video tutorial: http://www.youtube.com/watch?v=Yt99TNIMuHs

Smelting

Smelting recipes are the easiest of the three. This is mainly because it is a one-for-one transfer of items and the only configurable value is the experience given. The method signature for smelting is as follows.

GameRegistry.addSmelting(int inputItemID, ItemStack result, float experience);

There are two values that need explaining here: itemID and experience.

The itemID is, as you might have guessed, the id of the item in the game. Blocks have a field blockID that gives this. Items have the field itemID.

For experience, the value given is the direct amount of experience given. In vanilla Minecraft, these values range between 0.1f and 1.0f and can be seen at the Minecraft Wiki's smelting article. You may use any positive value you want.

The example smelting recipe is smelting stone for stone bricks.

1.6

GameRegistry.addSmelting(Block.stone.blockID, new ItemStack(Block.stoneBrick), 0.1f);

1.7

// Note not only Block -> Blocks but stoneBrick -> stonebrick
GameRegistry.addSmelting(Blocks.stone, new ItemStack(Blocks.stonebrick), 0.1f);

With Metadata

1.6

You may have noticed that the input does not accept a metadata or damage value. This is quite silly, but the GameRegistry doesn't have an addSmelting variant that takes metadata. For that, we will need to input FurnaceRecipes, get its instance, and then use its addSmelting method.

The example here is burning black wool to get white wool.

FurnaceRecipes.smelting().addSmelting(Block.cloth.blockID, 15, new ItemStack(Block.cloth, 1, 0), 0.1f);

1.7

GameRegistry can handle ItemStacks now, which CAN have metadata/damage values

ItemStack woolStackBlack = new ItemStack(Blocks.wool);
ItemStack woolStackWhite = new ItemStack(Blocks.wool);
woolStackBlack.setItemDamage(15);
woolStackWhite.setItemDamage(1);
GameRegistry.addSmelting(woolStackBlack, woolStackWhite, 0.1f);

NOTE: If you need help with smelting recipes, check out this video tutorial: http://www.youtube.com/watch?v=nbqTc-xu82Q NOTE: This won't work on 1.7.2.

Finished Product

With all the recipes added, and avoiding the creation of any unnecessary Objects, here is what tutorial.generic.Generic looks like with all these recipes added. Take note that the following are added to the import list:

  • cpw.mods.fml.common.registry.GameRegistry
  • net.minecraft.block.Block
  • net.minecraft.item.Item
  • net.minecraft.item.ItemStack
  • net.minecraft.item.crafting.FurnaceRecipes
package tutorial.generic;

// This Import list will grow longer with each additional tutorial.
// It's not pruned between full class postings, unlike other tutorial code.
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.Mod;
//import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.Instance;  //1.6.X
//import cpw.mods.fml.common.Mod.PostInit;
//import cpw.mods.fml.common.Mod.PreInit;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;

@Mod(modid = "Generic", name = "Generic", version = "0.0.0")
@NetworkMod(clientSideRequired = true, serverSideRequired = false, channels = { "GenericRandom" })
public class Generic {

    @Instance("Generic")
    public static Generic instance;

    @SidedProxy(clientSide = "tutorial.generic.client.ClientProxy", serverSide = "tutorial.generic.CommonProxy")
    public static CommonProxy proxy;

    @EventHandler
    public void preInit (FMLPreInitializationEvent event) {
        // Stub Method
    }

    @EventHandler
    public void load (FMLInitializationEvent event) {
        proxy.registerRenderers();

        ItemStack dirtStack            = new ItemStack(Block.dirt);
        ItemStack diamondsStack  = new ItemStack(Item.diamond, 64);
        ItemStack blackWoolStack  = new ItemStack(Block.cloth, 42, 15);
        ItemStack gravelStack        = new ItemStack(Block.gravel);
        ItemStack cobbleStack       = new ItemStack(Block.cobblestone);

        GameRegistry.addShapelessRecipe(diamondsStack, dirtStack);

        GameRegistry.addShapelessRecipe(diamondsStack, dirtStack, dirtStack,
                dirtStack, dirtStack, dirtStack, dirtStack, new ItemStack(
                        Block.sand), gravelStack, cobbleStack);

        GameRegistry.addRecipe(new ItemStack(Block.cobblestone), "xy", "yx",
                'x', dirtStack, 'y', gravelStack);

        GameRegistry.addRecipe(new ItemStack(Block.stone), "xyx", "y y", "xyx",
                'x', dirtStack, 'y', gravelStack);

        GameRegistry.addSmelting(Block.stone.blockID, new ItemStack(
                Block.stoneBrick), 0.1f);

        FurnaceRecipes.smelting().addSmelting(Block.cloth.blockID, 15,
                new ItemStack(Block.cloth, 1, 0), 0.1f);
    }

    @EventHandler
    public void postInit (FMLPostInitializationEvent event) {
        // Stub Method
    }
}

In future tutorials, these recipes will not be shown. The imports will still be there, since it's a pain to clean out unused imports in the master source. Unless the code is required for another tutorial, you can expect each tutorial to start at a clean slate.

What's Next

Next up is creating blocks and items.

Personal tools
Namespaces
Variants
Actions
Navigation
tutorials
Toolbox