Wednesday, March 4, 2015

Minecraft Tutorials: Crafting And Smelting Recipes

Another Minecraft modding tutorial.  In this tutorial I will discuss adding your own crafting and smelting recipes to a mod.  This tutorial assumes an understanding of block and item creation, as well as the main mod file.  As always, the code I'll be showing is built on code from all the tutorials thus far, and if you haven't been following allow exactly, your code is going to be a little bit different.

Minecraft has three standard types of recipes: Shapeless, Shaped, and Smelting. I'll go over each of them in turn, but first I'll make a class to handle all of them.  Let's call it ModRecipes and place it in the main mod package. All of our recipes will be registered in a new init() method.  Right now my ModRecipes class looks like this:
package me.codasylph.grindermod;

public class ModRecipes
{
       public static void init()
       {
             
       }
}

At this point we should also go ahead and call ModRecipes.init() in the init() method of the main mod class so that we can test the recipes as we go. For reference my main mod class looks like this now:
package me.codasylph.grindermod;

import me.codasylph.grindermod.blocks.CopperOre;
import me.codasylph.grindermod.blocks.ModBlocks;
import me.codasylph.grindermod.items.ModItems;
import cpw.mods.fml.common.Mod;
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.registry.GameRegistry;

@Mod(modid = "grindermod", name = "Grinder Mod", version = "1.0")

public class GrinderMod
{     
       @Mod.EventHandler
       public void preInit(FMLPreInitializationEvent event)
       {
              GameRegistry.registerWorldGenerator(new WorldGenGinderMod(), 0);
              ModBlocks.init();
              ModItems.init();
       }

       @Mod.EventHandler
       public void init(FMLInitializationEvent event)
       {
              ModRecipes.init();
       }

       @Mod.EventHandler
       public void postInit(FMLPostInitializationEvent event)
       {
             
       }
}

Now then, recipes! Actually first: ItemStacks
The way Minecraft works there's only one instance of a given Item.  You register that instance and it is the only instance of that item. What you end up with in your inventory is an ItemStack.  An ItemStack is a separate class with several properties, including what it's a stack of and how big it is. The constructor takes three parameters, an Item, an int that determines the size, and finally an int that determines the damage on the item (also known as the meta data). The constructor is overloaded so you may also pass just the Item for a stack of one undamaged item, or the Item and the size for a stack of the given size in which the items are undamaged. You can have an ItemStack of item. More importantly can and will have many many instances of the ItemStack class, include many stacks with the same item.  ItemStacks have more properties but none we need to understand right now.

So now the recipes!

Shapeless recipes are those that require a amount of certain items to be placed in a crafting grid to produce a given item, but the arrangement doesn't matter.  Vanilla examples of shapeless recipes include turning a block of iron or gold into nine ingots or turning dye and a block of wool into wool of that color.  In this example I will add a shapeless recipe that makes a slime ball out of an egg, some sugar, and lime dye.  The line looks like this:
GameRegistry.addShapelessRecipe(new ItemStack(Items.slime_ball), new ItemStack(Items.dye,1,10), new ItemStack(Items.egg), new ItemStack(Items.sugar));
addShapelessRecipe takes a variable number of parameters of the type ItemStack.  The first parameter dictates the output and all the following parameters dictate the ingredients. If you run your testing environment at this point you should be able to throw lime dye, an egg, and a pile of sugar in to a crafting grid and get yourself a brand spanking new ball o' slime.  Yum! :p

Shaped recipes require items in a specified arrangement on the crafting grid to produce a particular product.  Vanilla examples include all the the tools in Minecraft.  In this example I will add a shaped recipe that uses sticks and the copper ingot we created in A Basic Item to create the pickaxe we created in A Basic Tool. It will look like this:
GameRegistry.addShapedRecipe(new ItemStack(ModItems.copperPickaxe), new Object[]{
       "CCC",
       " S ",
       " S ", 'C', new ItemStack(ModItems.copperIngot), 'S', new ItemStack(Items.stick)});

This takes two parameters (kinda), the first is the output.  The second is an array of Objects with the recipe.  The first three objects are strings of three characters each, that represent each row the the crafting grid. The remaining objects are the characters and what ItemStack they represent. Spaces always mean any empty slot and do not need to be defined. 
Here's another example that makes a vanilla furnace out of sandstone instead of cobblestone.
GameRegistry.addShapedRecipe(new ItemStack(Blocks.furnace), new Object[]{
       "SSS",
       "S S",
       "SSS"'S'new ItemStack(Blocks.sandstone)});
Again you should be able to try either of these recipes out in the testing environment now.

Smelting recipes are those that convert one Item or Block into another inside a furnace.  Presumably by the judicious application of heat.  Most smelting recipes are of the ore into ingot variety, but other vanilla examples include turning logs into charcoal or raw food into cooked food. In this example I will add a smelting recipe to turn the copper ore we created in A Basic Block into the ingot we made in A Basic Item. The line looks like this:
GameRegistry.addSmelting(ModBlocks.copperOre, new ItemStack(ModItems.copperIngot), 0.5F);
This method takes three parameters, unlike the previous methods the first parameter is the input instead of the output, and may be an instance of Block, Item, or ItemStack.  The second parameter is the output and must be and instance of ItemStack.  The final parameter is a float that dictates how much experience the player receives for smelting the item.  0.5 is slightly less than the amount received for smelting iron and a little more than that received for cooking a food item.

A final thought, you'll notice we used ModItems.copperIngot several times, if we went in and added shaped recipes for all the copper tools we'd use it quite a few more times.  It can be beneficial, there for, to declare an instance of ItemStack for each item you'll be using in multiple recipes so you're not calling the constructor over and over again for no reason.  After taking this advice my ModRecipes class looks like this:
package me.codasylph.grindermod;

import me.codasylph.grindermod.blocks.ModBlocks;
import me.codasylph.grindermod.items.ModItems;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.registry.GameRegistry;

public class ModRecipes
{
       private static ItemStack copperIngotStacknew ItemStack(ModItems.copperIngot);
       private static ItemStack stickStacknew ItemStack(Items.stick);
      
       public static void init()
       {
              //Shapeless Recipes
              GameRegistry.addShapelessRecipe(new ItemStack(Items.slime_ball), new ItemStack(Items.dye,1,10), new ItemStack(Items.egg), new ItemStack(Items.sugar));
              //Shaped Recipes
              GameRegistry.addShapedRecipe(new ItemStack(ModItems.copperPickaxe), new Object[]{
                     "CCC",
                     " S ",
                     " S ", 'C'copperIngotStack, 'S', stickStack});
             
              //Smelting Recipes
              GameRegistry.addSmelting(ModBlocks.copperOrecopperIngotStack, 0.5F);
       }
}

That's all folks!  To return to the table of contents click here.

No comments:

Post a Comment