Hey everyone, I just wanted to make this thread to help people with making mods Enjoy these tuts and give feedback, they should be able to take you from the basics to some fairly advanced work.
PLEASE: Make sure you have at least a basic java knowledge before beginning on minecraft modding, you'll just get confused and find it hard to make interesting content. I recommend TheNewBoston, yes, it is a lot of tutorials, but he is a VERY good teacher
To see the code used for this tutorial, visit the github, and also, don't try to change stuff, I'm a major github noob and I'll probably freak out xD
I'm not just going to solve any problems you give me, if you have a legitimate problem, ask around elsewhere on the forums, I'm not here to write your mod for you. Note that you can also ask for help at the forge forums, the community over there is cool. I will, btw, help with requests for how to add content, suggestions for tutorials, and things I should add to my tutorials.
To start open your zip with winrar / 7zip, and do the same with the minecraft forge zip. From minecraft forge, copy over the forge folder into mcp742.
When you have that, you'll need to make a folder to keep your mod in, note that this can be in a github folder GIve the folder the name of your mod.
From there, copy everything from mcp742 into your mod folder, and navigate to */forge, * being the name of your mod folder. Innside of that, run install.bat, or .sh if you're not on windows. With that running, sit back and relax, this could take a while depending on your system.
Finally, once that finishes, you can open the minecraft code by opening */eclipse with eclipse. Note that if you are using a different IDE, you'll have to check on the MCP page for tutorials on how to open with it
And with that, we're done here. In the next tutorial we can set up the framework for our mod, and then finally get to some more interesting things, I hope you enjoyed this tutorial, and remember to keep an eye on the thread!
1.4.7:
Starting you mod:
Now that you have a decompiled Minecraft, you can open it by opening mod/eclipse inside of eclipse, this is where you'll spend most of your time modding...
When it's open, navigate to Minecraft/src, and make a new package, name this package anything you want, preferably your username, which will help to avoid conflicts with other mods, just in case, this will be a global package that will hold all of you mods inside of MC (eg. deverionx.mineTech or deverionx.baitedFishing).
Inside of that, make another package, the name of your mod, for this tutorial, I'll be working inside of deverionx.tutorial, but you can name it whatever you're working on. For the sake of neatness, I'll be organising the mod into deverionx.tutorial.common for everything based in the serverside, and deverionx.tutorial.client, for everything clientside, like GUI's and everything else to do with rendering, though this isn't actually necessary, it makes the mod easier to look at, if other people were to look at your code for some reason .
Now, inside your common package, make your mod class, unlike old 1.2 modding, this doesn't have to be mod_***, it can be anything you want. This is the code you need, keep in mind that you should change the names to fit your own mod:
package deverionx.tutorial.common; //The package your mod is in
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
import cpw.mods.fml.common.network.NetworkMod.SidedPacketHandler;
import cpw.mods.fml.common.SidedProxy;
import deverionx.tutorial.client.core.handlers.ClientPacketHandler;
import deverionx.tutorial.common.core.CommonProxy;
@NetworkMod(clientSideRequired=true,serverSideRequired=false, //Whether client side and server side are needed
clientPacketHandlerSpec = @SidedPacketHandler(channels = {"TutorialGeneral" }, packetHandler = ClientPacketHandler.class), //For clientside packet handling
serverPacketHandlerSpec = @SidedPacketHandler(channels = {}, packetHandler = ServerPacketHandler.class)) //For serverside packet handling
@Mod(modid="DeverionXTutorial",name="DeverionXTutorial",version="1.0") //Gives Forge extra info about your mod
public class TutorialMain { //The class file
@Instance("DeverionXTutorial") //The instance, this is very important later on
public static TutorialMain instance = new TutorialMain();
@SidedProxy(clientSide = "deverionx.tutorial.client.core.ClientProxy", serverSide = "deverionx.tutorial.common.core.CommonProxy") //Tells Forge the location of your proxies
public static CommonProxy proxy;
@Init
public void InitCobaltCraft(FMLInitializationEvent event){ //Your main initialization method
NetworkRegistry.instance().registerGuiHandler(this, proxy); //Registers the class that deals with GUI data
}
}
You'll get some errors, but these will be resolved shortly. For the @Mod, modID is an incode name for you mod, and also appears in the server console when players log in with the mod, name and version are extra info that appear in the mod list ingame. Now though, you need to make your proxy classes:
First, make a new package: deverionx.tutorial.common.core in my case
CommonProxy:
package deverionx.tutorial.common.core;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.world.World;
import cpw.mods.fml.common.network.IGuiHandler;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
import deverionx.tutorial.common.TutorialMain;
public class CommonProxy implements IGuiHandler{ //THIS IS IMPORTANT, CANNOT BE A PROXY/GUI HANDLER WITHOUT THIS!!
public void registerRenderInformation() //Client side texture registering
{
}
@Override
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { //For GUI's
return null;
}
@Override
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { //For GUI's
return null;
}
public void registerTiles(){ //For registering TileEntities
}
public void registerBlocks(){ //For registering Blocks
}
public void addNames(){ //For adding Item's ingame names
}
public void addRecipes(){ //For adding your Item's recipes
}
}
And now the ClientProxy:
package deverionx.tutorial.client.core;
import deverionx.tutorial.common.core.CommonProxy;
import net.minecraftforge.client.MinecraftForgeClient;
public class ClientProxy extends CommonProxy {
public void registerRenderInformation(){
}
}
Finally, add the packet handlers for later on:
ServerPacketHandler:
package deverionx.tutorial.common.core.handlers;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet250CustomPayload;
import cpw.mods.fml.common.network.IPacketHandler;
import cpw.mods.fml.common.network.Player;
public class ServerPacketHandler implements IPacketHandler{
@Override
public void onPacketData(INetworkManager manager, Packet250CustomPayload payload, Player player){
DataInputStream data = new DataInputStream(new ByteArrayInputStream(payload.data)); //Handles incoming data
EntityPlayer sender = (EntityPlayer) player;
}
}
ClientPacketHandler:
package deverionx.tutorial.client.core.handlers;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet250CustomPayload;
import cpw.mods.fml.common.network.IPacketHandler;
import cpw.mods.fml.common.network.Player;
import cpw.mods.fml.relauncher.*;
@SideOnly(Side.CLIENT)
public class ClientPacketHandler implements IPacketHandler{
@Override
public void onPacketData(INetworkManager manager, Packet250CustomPayload payload, Player player){
DataInputStream data = new DataInputStream(new ByteArrayInputStream(payload.data)); //Handles incoming data
}
}
And with that, you have the foundation of a working mod! The next step is to start adding some items and blocks, and then we can get into more interesting stuff!
Creating your first basic item:
In this tutorial, I'm going to explain how to make a basic item in your mod. To start with, we need a texture! Put the texture inside a new file in the Minecraft/common folder named *yourMod*GFX.
When you have the texture, add this line to ClientProxys' registerRenderInformation method:
This will allow you to use your texture for items, but now we need to make our item class:
We need a new package for items, for me it is: deverionx.tutorial.common.item. Now add the class:
ItemRuby:
package deverionx.tutorial.client.core.item;
import net.minecraft.item.Item;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
import net.minecraft.creativetab.CreativeTabs;
public class ItemRuby extends Item {
public ItemRuby(int par1) {
super(par1); //Returns super constructor: par1 is ID
setTextureFile("/TutorialGFX/Items.png"); //Sets the item texture file
setItemName("DeverionXItemRuby"); //Sets the incode name of the item, make sure it doesn't clash with other items, weird stuff happens
setCreativeTab(CreativeTabs.tabMaterials); //Tells the game what creative mode tab it goes in
}
@SideOnly(Side.CLIENT) //Marks a method as client side only, typically for graphics and rendering
public int getItemIconFromDamage(int i){
return 0; //The first icon on the spritesheet
}
}
Everything in there is fairly self-explanatory, but I explained it in comments anyway. Now we need to make out item's object in the mod, so add this line:
public static Item ruby = new ItemRuby(15000); //The ruby object
Don't forget to import ItemRuby. Next, we should add an ingame name for it, go to addNames() in CommonProxy and add:
LanguageRegistry.addName(TutorialMain.ruby, "Ruby"); //Adds the name for the ruby item
And then call it in your mod class:
proxy.addNames();
And with that, your item should be working! Feel free to check it out in game, and keep an eye on this thread for more tutorials!
Creating Metadata items:
In this tutorial, I will be teaching you how to make more than one item in one ID, also called metadata. For this tutorial, you need this texture.
Now that you have that (making sure it's in the TutorialGFX folder), you can make your item's class in the item package:
ItemMetaGem:
package deverionx.tutorial.client.core.item;
import java.util.List;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
import net.minecraft.creativetab.CreativeTabs;
public class ItemMetaGem extends Item {
public ItemMetaGem(int par1) {
super(par1); //Returns super constructor: par1 is ID
setTextureFile("/TutorialGFX/Items.png"); //Sets the item texture file
setItemName("DeverionXItemMetaGem"); //Sets the incode name of the item, make sure it doesn't clash with other items, weird stuff happens
setCreativeTab(CreativeTabs.tabMaterials); //Tells the game what creative mode tab it goes in
setHasSubtypes(true); //Marks item as having metadata
setMaxDamage(0);
}
@SideOnly(Side.CLIENT) //Marks a method as client side only, typically for graphics and rendering
public int getIconFromDamage(int i){
switch(i){ //Checks what the damage is
case 0:return 1; //If damage equals 0 then return second icon
case 1:return 2; //^
case 2:return 3; //^
}
return 0; //If icon not already returned, just return 0
}
public String getItemNameIS(ItemStack is){ //Gets the metadata sensitive item name
switch(is.getItemDamage()){ //Checks what damage is
case 0:return "DeverionXItemSapphire"; //If damage is one, return name
case 1:return "DeverionXItemAmethyst"; //^
case 2:return "DeverionXItemTopaz"; //^
}
return "itemUnknown";
}
@SideOnly(Side.CLIENT)
public void getSubItems(int itemID, CreativeTabs tab, List itemList) //Adds the metadata items to the creative inventory
{
for(int i=0;i<3;i++){
itemList.add(new ItemStack(itemID,1,i)); //Adds all the metadatas
}
}
}
Then add the object to your mod class:
public static Item metaGem = new ItemMetaGem(15001);
Once again, don't forget to import it. Next we need to add their ingame names:
LanguageRegistry.addName(new ItemStack(TutorialMain.metaGem,1,0), "Sapphire"); //Adds the sapphire gem name (metadata sensitive)
LanguageRegistry.addName(new ItemStack(TutorialMain.metaGem,1,1), "Amethyst"); //Adds the amethyst gem name (metadata sensitive)
LanguageRegistry.addName(new ItemStack(TutorialMain.metaGem,1,2), "Topaz"); //Adds the topaz gem name (metadata sensitive)
Depending on how many metadata values you have, you may or may not want to use a for loop for it, but I decided not to for this tutorial.
With that, you can check out your item ingame, and feel free to follow this thread to get updates on tutorials
Recipes, smelting and fuel:
In this tutorial, I will be explaining how to add recipes, shapeless recipes, smelting recipes and custom fuels.
To start, let's make a recipe for the ruby, this goes in CommonProxy addRecipes() method:
GameRegistry.addRecipe(new ItemStack(TutorialMain.ruby,1), "XAX", Character.valueOf('X'), new ItemStack(Item.dyePowder,1,1), Character.valueOf('A'),
Block.glass); //Adds the ruby recipe
This recipe will be one glass in between two red dye gives ruby. I'll go through this step by step:
1: GameRegistry.addRecipe is the method used to add a regular recipe
2: The first parameter is the ouput, in this case 1 ruby
3: Then you put a string with letters, these indicate the location and type of item to be used
4: Character.valueOf follows that, it tells what letter you'll describe
5: This is followed by an Item/Block/ItemStack, you only really use itemstacks for adding metadata
ingredients
In this case, I use dye, the dye metadatas are as follows:
For wool blocks, it is reversed. Anyway, now to add a shapeless recipe:
GameRegistry.addShapelessRecipe(new ItemStack(TutorialMain.metaGem,1,0), new ItemStack(Item.dyePowder,1,4), Block.glass); //Adds a shapeless recipe for sapphire
GameRegistry.addShapelessRecipe(new ItemStack(TutorialMain.metaGem,1,1), TutorialMain.ruby, new ItemStack(TutorialMain.metaGem,1,0)); //Adds a shapeless recipe for amethyst
The first recipe is one glass and one lapis anywhere on the table for a sapphire, and the second is one ruby and one sapphire anywhere on the table for an amethyst. If you look at the method, you'll see that there are no strings and no Character.valueOf's, this is because the items can be anywhere on the table. Now for the smelting recipe:
GameRegistry.addSmelting(TutorialMain.ruby.itemID, new ItemStack(TutorialMain.metaGem,1,2), 5); //A non-metadata sensitive smelting recipe
This is the main way to add a smelting recipe, the first parameter is the itemID of the input, the second is the output itemstack and the third is the xp reward. This recipe is that you put in one ruby and take out one topaz. Now for a meta-sensitive version:
FurnaceRecipes.smelting().addSmelting(TutorialMain.metaGem.itemID, 1, new ItemStack(TutorialMain.metaGem,1,2), 5); //Metadata sensitive
This makes it meta-sensitive. The first parameter is the itemID, the second is metadata, the third is output and the fourth is xp reward. The final thing left to do is add a custom fuel:
To do this, first make the FuelHandler class in your common.core.handlers package:
package deverionx.tutorial.common.core.handlers;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.IFuelHandler;
import deverionx.tutorial.common.TutorialMain;
public class FuelHandler implements IFuelHandler{
@Override
public int getBurnTime(ItemStack fuel) { //This method sets burn time
if(fuel.itemID == TutorialMain.ruby.itemID){
return 150; //1/4 of coal
}
return 0;
}
}
Don't forget to call CommonProxy.addRecipes(), otherwise your recipes won't work!:
proxy.addRecipes();
And with that, everything should be working! Feel free to check it out ingame, and keep an eye out for new tutorials
Custom creative mode tabs:
In this tutorial, I will be teaching you how to make a custom creative inventory tab. The first thing we need is out tab class, which is as follows (put it in a new package, for me: deverionx.tutorial.common.tabs):
TabGems:
package deverionx.tutorial.common.tabs;
import net.minecraft.creativetab.CreativeTabs;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
public class TabGems extends CreativeTabs {
public TabGems(int position, String tabID) {
super(position, tabID); //The constructor for your tab
}
@SideOnly(Side.CLIENT)
public int getTabIconItemIndex() //The item it displays for your tab
{
return TutorialMain.ruby.itemID; //For this we'll use the ruby
}
public String getTranslatedTabLabel()
{
return "Gems"; //The name of the tab ingame
}
}
I've explained everything in there in the comments, so now what we need to do is add the object to our mod class. Keep in mind that for this to work, you NEED to create the constructor before your items and blocks, otherwise they don't appear inside. This is our object's line:
public static CreativeTabs tabGems = new TabGems(CreativeTabs.getNextID(),"DeverionXTabGems"); //Our custom creative tab's object
Fairly simple, the first parameter is the position, in this case 12: on page 2 of the inventory. The reason that we use that method is because without it, we would have incompatibility problems. With this we have a working creative inventory tab, all you have to do now is go to your item classes and add them to the tab by changing the setCreativeTab(CreativeTabs.tabMaterial) method to setCreativeTab(TutorialMain.tabGems). Feel free to check it out ingame, and keep an eye on this thread for more updates
Creating your first basic block:
In this tutorial I will show you how to make your first basic block with forge:
To start, let's make our block class:
package deverionx.tutorial.common.blocks; //The location of the class
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
public class BlockRuby extends Block {
public BlockRuby(int ID) {
super(ID, Material.iron); //The ID and material (The material defines what tools are better on it)
setTextureFile("/TutorialGFX/Blocks.png"); //The texture file
setBlockName("DeverionXBlockRuby"); //The incode name of the block
setHardness(5.0F); //How hard the block is to break
setResistance(10.0F); //How well the block resists explosions
setStepSound(super.soundMetalFootstep); //The sound the block makes when you walk on it as well as place or break it
setCreativeTab(TutorialMain.tabGems); //The tab it appears in
}
@SideOnly(Side.CLIENT)
public int getBlockTextureFromSide(int i){ //What texture it uses
return 1;
}
}
I've explained it all in the code and apart from that it really is very simple. Next we need an object for it in the mod class:
public static Block blockRuby = new BlockRuby(250); //The block object
And then we need to register the block, which allows it to render without crashing the game. Put this line before the other proxy calls:
proxy.registerBlocks(); //Calls the registerBlocks method
When that's done, we need to register the block in the proxy method like this:
GameRegistry.registerBlock(TutorialMain.blockRuby, "DevXTutorialRuby"); //Register the block
And with that, feel free to check it out ingame and keep an eye out for new tutorials
Creating blocks with metadata:
In this tutorial I will be explaining how to make metadata blocks with forge:
To start, we once again need our block class, which is slightly longer than the last one:
package deverionx.tutorial.common.blocks;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
public class BlockMetaGem extends Block{
public BlockMetaGem(int ID){
super(ID,Material.rock); //The ID and material
setBlockName("DeverionXOdedBlockOre"); //The incode name
setHardness(3.0F); //How hard the block is
setResistance(5.0F); //How well the block resists explosions
setStepSound(Block.soundStoneFootstep); //The sounds the block makes
setCreativeTab(TutorialMain.tabGems); //The tab it appears in
setTextureFile("/TutorialGFX/Blocks.png"); //The texture file
}
public int getBlockTextureFromSideAndMetadata(int i, int j){ //The different textures fo different metadatas
switch(j){
case 0:return 2; //For sapphire
case 1:return 3; //For amethyst
case 2:return 4; //For topaz
default:return 0;
}
}
public int damageDropped(int i){ //Tells it what block it drops and also for creative mode pick block
return i;
}
@SideOnly(Side.CLIENT)
public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List) //Adds the metadata blocks to the creative inventory
{
for (int var4 = 0; var4 < 3; ++var4)
{
par3List.add(new ItemStack(par1, 1, var4));
}
}
}
Everything is explained in the comments like always. For metadata blocks, just having the block class isn't enough, we also need an item for it:
package deverionx.tutorial.common.item;
import java.util.List;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
public class ItemBlockMetaGem extends ItemBlock
{
public ItemBlockMetaGem(int par1)
{
super(par1);
this.setMaxDamage(0); //Stops bad things from happening
this.setHasSubtypes(true); //Tells it that it has metadata versions
}
@SideOnly(Side.CLIENT)
public int getIconFromDamage(int par1) //Gets the texture
{
return TutorialMain.metaBlock.getBlockTextureFromSideAndMetadata(2, par1);
}
public int getMetadata(int par1) //Returns the metadata value
{
return par1;
}
public String getItemNameIS(ItemStack is) //Get's the item incode name from an itemstack
{
String[] types = {"Sapphire","Amethyst","Topaz"};
return "DeverionXBlock" + types[is.getItemDamage()];
}
}
With that done, we can make the block object in the mod class:
public static Block metaBlock = new BlockMetaGem(251);
And then we need to register it, this is slightly different from a basic block:
for(int i = 0;i < 3;i++){
GameRegistry.addRecipe(new ItemStack(TutorialMain.metaBlock,1,i), "XXX","XXX","XXX", Character.valueOf('X'), new ItemStack(TutorialMain.metaGem,1,i));
}
And with that, you can check out your block's ingame and keep an eye out for new tutorials
Ore Generation:
In this tutorial, I will be showing you how to generate custom ores in the world:
To start, download this texture. Once that's done, we need a block class:
package deverionx.tutorial.common.blocks;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import deverionx.tutorial.common.TutorialMain;
public class BlockOre extends Block {
public BlockOre(int ID){
super(ID,Material.rock); //Parameters: Block ID, Block material
setTextureFile("/TutorialGFX/Blocks.png"); //The texture file used
setBlockName("DeverionXBlockOre"); //The incode block name
setHardness(3.0F); //The block hardness
setResistance(5.0F); //The explosion resistance
setCreativeTab(TutorialMain.tabGems); //The tab it appears in
}
public int getBlockTextureFromSideAndMetadata(int i,int j){ //Gets the texture from metadata
switch(j){
case 0:return 5;
case 1:return 6;
case 2:return 7;
case 3:return 8;
default:return 0;
}
}
public int damageDropped(int i){ //Makes sure pick block works right
return i;
}
public void getSubBlocks(int i, CreativeTabs tab, List l){ //Puts all sub blocks into the creative inventory
l.add(new ItemStack(i,1,0));
l.add(new ItemStack(i,1,1));
l.add(new ItemStack(i,1,2));
l.add(new ItemStack(i,1,3));
}
public ArrayList<ItemStack> getBlockDropped(World w, int x, int y, int z, int meta, int fortune){ //Specifies the block drop
ArrayList<ItemStack> list = new ArrayList<ItemStack>(); //The list of items
list.add(new ItemStack(meta == 0 ? TutorialMain.ruby : TutorialMain.metaGem,1,meta == 0 ? 0 : meta-1)); //One guaranteed
for(int i=0;i<2+fortune;i++){ //A loop for drops, increased by fortune enchant
if(w.rand.nextInt(101) > 49){ //50% chance
list.add(new ItemStack(meta == 0 ? TutorialMain.ruby : TutorialMain.metaGem,1,meta == 0 ? 0 : meta-1)); //Adds the gem
}
}
return list; //Returns the finished list
}
}
Then make the item block:
package deverionx.tutorial.common.item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import deverionx.tutorial.common.TutorialMain;
public class ItemBlockOre extends ItemBlock {
public ItemBlockOre(int i){
super(i);
}
public int getMetadata(int i){
return i;
}
public String getItemNameIS(ItemStack is){
switch(is.getItemDamage()){
case 0:return "DeverionXBlockRubyOre";
case 1:return "DeverionXBlockSapphireOre";
case 2:return "DeverionXBlockAmethystOre";
case 3:return "DeverionXBlockTopazOre";
default:return "";
}
}
public int getIconFromDamage(int i){
return TutorialMain.ore.getBlockTextureFromSideAndMetadata(2,i);
}
}
We're nearly at the world gen part, first we need to make the block object:
First, make the class WorldGenHandle in deverionx.tutorial.common.core.handlers, implementing IWorldGenerator:
package deverionx.tutorial.common.core.handlers;
import java.util.Random;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenMinable;
import cpw.mods.fml.common.IWorldGenerator;
import deverionx.tutorial.common.TutorialMain;
public class WorldGenHandler implements IWorldGenerator { //Implements IWorldGenerator
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, //This is the base generate method
IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
if (world.provider.isSurfaceWorld()){
generateSurface(random,chunkX*16,chunkZ*16,world); //This makes it gen overworld (the *16 is important)
}
}
public void generateSurface(Random random, int x, int z, World w){
for(int i = 0;i<4;i++){ //This goes through the ore metadata
for(int ii=0;ii<20;ii++){ //This makes it gen multiple times in each chunk
int posX = x + random.nextInt(16); //X coordinate to gen at
int posY = random.nextInt(40); //Y coordinate less than 40 to gen at
int posZ = z + random.nextInt(16); //Z coordinate to gen at
new WorldGenMinable(TutorialMain.ore.blockID,i,random.nextInt(9)).generate(w, random, posX, posY, posZ); //The gen call
}
}
}
}
Let me explain in more detail:
The generate method is an override from the interface, and inside it we get what world type it is. If we do it this way, we'll achieve Mystcraft compatibility, which is a good thing , if it's one: We generate the overworld, and call generateSurface
In generate surface, the first for loop makes it go through the different metas
The second loop is rarity, the number of veins in a chunk
The x variable is the exact x coordinate for the ore
The y variable is a random number less than 40
The z variable is the exact z coordinate for the ore
WorldGenMinable is the prewritten world gen for ores:
The first parameter is the block ID
The second parameter is the metadata
The third parameter is the vein size
Then we tell our GenMinable to generate with our three coordinates, our world object and our random
Finally, all we have to do is register the world gen handler in our mod class:
And with that, the ores will generate in the world, so feel free to check it out ingame and keep an eye out for new tutorials
Updating past 1.4.5
In this tutorial, I will be helping you update your mod to 1.4.6:
With the 1.4.6 update, the code in Minecraft has been completely reorganized into separate packages, which has killed imports, so to start we have to fix them:
First move your code from your 1.4.5 mod to your 1.4.6 folder, and receive a lot of errors. Then you need to go through all of your classes fixing imports:
The MC code was organized into packages like net.minecraft.block and net.minecraft.client.render, much like our mod, so the fixing shouldn't be too hard, it'll just take a while, and I personally recommend *erasing all of your imports and let eclipse help you import the new classes
*Most of the *Forge imports should still be fine **The Side and SideOnly classes have been moved to cpw.mods.fml.relauncher.*'; **The GameRegistry.registerBlock method has changed, give it a String parameter at the end for the mod specific name, this helps the block avoid conflicts (Do the same for metadata block registers)
When your imports are fixed, just go ingame and see if everything still works, if it doesn't just ask for help here and I'll do my best to help!
Special item effects: In this tutorial, I will be showing you how to add special effects to your items:
First, get this texture, then we need an item class:
ItemRubyStaff:
package deverionx.tutorial.common.item;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import deverionx.tutorial.common.TutorialMain;
public class ItemRubyStaff extends Item {
public ItemRubyStaff(int par1) {
super(par1);
setTextureFile("/TutorialGFX/Items.png"); //Texture File
setItemName("DeverionXRubyStaff"); //Incode item name
setCreativeTab(TutorialMain.tabGems); //Tab it appears in
}
public int getIconFromDamage(int i){ //Gets the icon to display
return 4;
}
public boolean onItemUse(ItemStack is, EntityPlayer player, World w, int x, int y, int z, int l, float f, float f1, float f3){ //Called when an item is right clicked on a block
if(w.getBlockId(x, y, z) == Block.planks.blockID){ //If blockId at x y z is planks:
w.setBlockMetadataWithNotify(x, y, z, w.getBlockMetadata(x, y, z)+1); //Increase the metadata
if(w.getBlockMetadata(x, y, z) == 4){ //If metadata is 4
w.setBlockMetadata(x, y, z, 0); //Reset to 0
}
}else if(w.getBlockId(x, y, z) == Block.plantRed.blockID){ //If block id is red plant
w.setBlockWithNotify(x, y, z, Block.plantYellow.blockID); //Changing block to yellow plant
}else if(w.getBlockId(x, y, z) == Block.plantYellow.blockID){ //Vice Versa
w.setBlockWithNotify(x, y, z, Block.plantRed.blockID);
}else if(w.getBlockId(x, y, z) == Block.cobblestone.blockID){ //If block is cobble
w.setBlockWithNotify(x, y, z, Block.cobblestoneMossy.blockID); //Set to mossy
}else if(w.getBlockId(x, y, z) == Block.cobblestoneMossy.blockID){ //Vice versa
w.setBlockWithNotify(x, y, z, Block.cobblestone.blockID);
}
return false;
}
@Override
public void addInformation(ItemStack is, EntityPlayer player, List l, boolean B){ //Additional info (eg. the names of music discs)
l.add("This staff is magical!");
}
public EnumRarity getRarity(ItemStack is){ //The colour of the item name (eg. with golden apples)
return EnumRarity.epic;
}
@Override
public int getDamageVsEntity(Entity e){ //The amount of damage dealt to an entity when using this item as a weapon
return 0;
}
public boolean hasEffect(ItemStack is){ //Adds an effect to the item (eg. golden apples)
return true;
}
}
Everything is explained in the comments, mostly:
In onItemUse:
Parameter one is itemstack
two is player
three is world
four to six are coordinates
seven is block side
In addInformation:
Parameter one is itemstack
two is player
three is the info list
In getRarity:
Parameter one is the itemstack
In getDamageVsEntity:
Parameter one is the entity being hit
In hasEffect:
Parameter one is the itemstack
Note that the itemstack parameters can be used to add different info/effects depending on metadata
After that, we just need the usual, an object, name and recipe:
public static Item rubyStaff = new ItemRubyStaff(15002);
GameRegistry.addRecipe(new ItemStack(TutorialMain.rubyStaff,1), " X"," X ","X ", Character.valueOf('X'), TutorialMain.ruby);
And with that, you can go ingame and try out the item, keep an eye out for new tutorials, and I hope you enjoyed!
Using the ore dictionary: In this tutorial, I will be showing you how to use the ore dictionary on your items and blocks:
To start, I will explain the ore dictionary: The ore dictionary is a tool added by forge that allows your items to be used in recipes from other mods. For example, say you have a copper item, and another mod using the ore dictionary adds a recipe with their own copper bar, your copper will be able to be used in that recipe alongside the other mod's copper, so the ore dictionary provides basic integration between mods.
To start, add the registerOre method to your commonproxy:
OreDictionary.registerOre("gemSapphire", new ItemStack(TutorialMain.metaGem,1,0)); //Metadata item registration
OreDictionary.registerOre("gemAmethyst", new ItemStack(TutorialMain.metaGem,1,1)); //^
OreDictionary.registerOre("gemTopaz", new ItemStack(TutorialMain.metaGem,1,2)); //^
Just like with names and recipes, you need to use itemstacks for metadata items.
To register blocks to the ore dictionary, it is identical, just with the blocks instead.
Remember this though: When you name something in the ore dictionary, it should always have this format so as to match other mods:
"typeItem", eg: "gemRuby", or "ingotSteel"
The last thing we need to do before we're done is call the method in our mod class after all the other's in our init method:
proxy.registerOre();
And with that, you can try recompiling your mod and testing it alongside another mod, I recommend Redpower, because it adds rubies and sapphires. Keep an eye out for new tutorials, and I hope you enjoyed!
Distributing your mod!:
In this tutorial, I will be showing you everything you need to do to distribute your mod:
Step 1: Open your mod folder
Step 2: Run the recompile.bat there (if on windows)
Step 3: When that finishes, run reobfuscate.bat
Step 4: Navigate to reobf/Minecraft
Step 5: Copy your mod package (for me deverionx)
Step 6: Create a zip file back in your mod folder named *yourmod*
Step 7: Paste the mod package inside it
Step 8: Paste your GFX folder inside it
Step 9: Upload the zip file to Mediafire/Your preferred cloud storage site
Step 10: If you want to, create an adf.ly link
Step 11: Create your mod thread! Keep in mind to refer to the following rules:
Your thread title must include the following in square brackets:
Minecraft version for mod
Forge
Mod version (optional) (I recommend putting this one after mod name)
Download count (optional)
Then put the name of your mod.
In the thread, you need:
A full description of what the mod contains
You NEED to have pictures
You NEED a direct link for download
You can have an adf.ly link
Installation instructions
A todo list (optional)
If you get mod spotlights from youtubers, you can show them on your page like this:
[media]thespotlight[/media]
Remember to put screenshots and videos in spoilers most of the time
I recommend having a changelog as well as an archive of previous mod versions.
NOTE: If your mod is incomplete (below version 1) It belongs in the WIP forum. If it is an addon for other mods, it belongs in content packs, otherwise, just put it in the general mod section
And with that, your mod has been distributed and is available to the public, make sure to take critiscm as you should, and keep an eye out for more tutorials If you have any questions, send me a PM
Using metadata items for tab icon:
In this tutorial I will show you how to use metadata items for creative tab icons:
To do this, simply replace the getTabIconIndex method with this:
@SideOnly(Side.CLIENT)
public ItemStack getIconItemStack(){
return new ItemStack(TutorialMain.metaGem,1,2);
}
This will make the gem tab icon become the topaz
I hope you enjoyed this quick tutorial, and remember to keep an eye out for more
Using the ore dictionary, pt 2:
In this tutorial, I will show you how to finish adding compatibility through the ore dictionary,
This is fairly simple, so far, with what we've implemented, our items that are registered will be usable in other mod's recipes, but not the other way round. To fix this, we need to change our recipes:
As you can see, it's pretty similar to the regular shaped recipe, but instead of giving a item, block, or Itemstack, you give a string, that string being the ore dictionary name of your item. For shapeless recipes, it's pretty much the same:
And with that, you can begin converting your recipes to ore recipes, and remember to keep an eye out for new tutorials
Updating to 1.4.7
In this short tutorial, I will be showing you what to do to update to 1.4.7:
To start, update your forge and your MCP, and when they're set up, copy your code over to the new workspace.
When that's done, there's minor tweaking to do:
you have to do is change every shiftedIndex to itemID.
Change the getItemIconFromDamage methods to getIconFromDamage
Change the getTabIconItemStack methods to getIconItemStack
With that,you can go ingame and check if everything works, if it doesn't, send me a message and I'll help you out
Using the ore dictionary pt.3:Other methods:
In this very short tutorial, I will be showing you other methods in the forge ore dictionary:
The first is the getOres method, which looks like this:
OreDictionary.getOres("gemRuby"); //Gets an arraylist of valid items
The parameter is the ore name, and as the comment explains, the method returns an arraylist of items and blocks matching that name. You can use this for adding compatible recipes in custom machines/tile entities
The second is the getOreNames method, which looks like this:
OreDictionary.getOreNames(); //Returns an arraylist of ore names
This method takes no parameters, and as the comment explains, returns an arraylist of all the ore names, an example of uses for this is the mod Twilight Forest, which uses this to find ores to generate in that dimension.
The third is the getOreID method, like so:
OreDictionary.getOreID("gemRuby"); //Gets a unique int ID for the ore type
OreDictionary.getOreID(new ItemStack(xxx,1)); //Gets the unique ore ID from an itemstack, returns -1 if there isn't one
This method can either use the ore name or an itemstack, and returns a unique int ID for the ore name.
The fourth is the getOres method, which uses the unique int ID to return an arraylist of valid items:
OreDictionary.getOres(0); //Returns an arraylist of valid items from the ore ID
And there you have it, a few special methods using the ore dictionary that you can use for adding compatibility, hope you enjoyed and keep an eye out for new tutorials
Making items get damaged when used in crafting:
In this tutorial, I will be showing you how to make items that get damaged when used in crafting. To start, we need our textures:
When you have that, we need to make the item we'll be using as a tool:
package deverionx.tutorial.common.item;
import net.minecraft.item.Item;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
public class ItemFirestone extends Item {
public ItemFirestone(int par1) {
super(par1);
setTextureFile("/TutorialGFX/Items.png");
setItemName("DeverionXItemFireStone");
setCreativeTab(TutorialMain.tabGems);
setMaxDamage(30); //Sets the item's max damage
setMaxStackSize(1); //Sets the maximum size of an itemstack for this item
}
@SideOnly(Side.CLIENT)
public int getIconFromDamage(int i){
return 5;
}
}
As you can see, pretty much identical to a basic item, but for the setMaxDamage and setMaxStackSize, which you'll see in use later.
Now we need to set up the other basics for the item:
In the mod class:
public static Item firestone = new ItemFirestone(15003);
You will get an error, but we'll fix that in a moment:
Create the class CraftingHandler in yourmod.common.core.handlers:
package deverionx.tutorial.common.core.handlers;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.ICraftingHandler;
public class CraftingHandler implements ICraftingHandler {
@Override
public void onCrafting(EntityPlayer player, ItemStack item,
IInventory craftMatrix) {
}
@Override
public void onSmelting(EntityPlayer player, ItemStack item) {
}
}
The onCrafting method is called when you take stuff out of a crafting table
The onSmelting method is called when an item gets smelted
Then add this to the onCrafting method:
for(int i=0; i < craftMatrix.getSizeInventory(); i++) //Checks all the slots
{
if(craftMatrix.getStackInSlot(i) != null) //If there is an item
{
ItemStack j = craftMatrix.getStackInSlot(i); //Gets the item
if(j.getItem() != null && j.getItem() == TutorialMain.firestone) //If it's a firestone
{
ItemStack k = new ItemStack(TutorialMain.firestone, 2, (j.getItemDamage() + 1)); //Makes a new itemstack that's been damaged and has 2 items
if(k.getItemDamage() >= k.getMaxDamage()){ //If it is destroyed
k.stackSize--; //Removes the added item
}
craftMatrix.setInventorySlotContents(i, k); //Sets the slot to the new item
}
}
}
This may seem complicated at first, but it's actually really simple:
What it does is it looks through the crafting slots, and if one of the items is the firestone, then it makes the itemstack be larger and be damaged.
Then we can make another item, which will be the different things we can craft:
package deverionx.tutorial.common.item;
import java.util.List;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.relauncher.*;
import deverionx.tutorial.common.TutorialMain;
public class ItemFiredGem extends Item {
public ItemFiredGem(int par1) {
super(par1);
setTextureFile("/TutorialGFX/Items.png");
setItemName("DeverionXItemFiredGem");
setCreativeTab(TutorialMain.tabGems);
setHasSubtypes(true);
}
@SideOnly(Side.CLIENT)
public int getIconFromDamage(int i){
switch(i){
case 0:return 6;
case 1:return 7;
}
return 0;
}
public String getItemNameIS(ItemStack is){
switch(is.getItemDamage()){
case 0:return "DeverionXItemStormStone";
case 1:return "DeverionXItemLushStone";
}
return "itemUnknown";
}
@SideOnly(Side.CLIENT)
public void getSubItems(int itemID, CreativeTabs tab, List itemList) //Adds the metadata items to the creative inventory
{
for(int i=0;i<2;i++){
itemList.add(new ItemStack(itemID,1,i)); //Adds all the metadatas
}
}
}
Then make the object in your mod class. When that's done, add the names:
The recipes are, despite what you might expect, completely normal, ish:
GameRegistry.addShapelessRecipe(new ItemStack(TutorialMain.firedGem,1,0), new ItemStack(TutorialMain.metaGem,1,1), new ItemStack(TutorialMain.firestone,1,-1));
As you can see, the only difference is the the firestone uses the metadata -1. which basically means that any metadata can be used. Then just do the same for the other gem:
GameRegistry.addShapelessRecipe(new ItemStack(TutorialMain.firedGem,1,1), Item.emerald, new ItemStack(TutorialMain.firestone,1,-1));
And with that, you should be done! Feel free to check it out ingame, and keep an eye out for new tutorial
Creating transparent blocks:
In this tutorial I will be showing you how to create transparent blocks, so to start, download this texture
When you have that, we can make our first block class:
BlockRubyGlass:
package deverionx.tutorial.common.blocks;
import java.util.Random;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import deverionx.tutorial.common.TutorialMain;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.world.IBlockAccess;
public class BlockRubyGlass extends Block {
public BlockRubyGlass(int i){
super(i,Material.glass);
setStepSound(soundGlassFootstep);
setTextureFile("/TutorialGFX/Blocks.png");
setHardness(0.3F);
setResistance(0.0F);
setCreativeTab(TutorialMain.tabGems);
setBlockName("DeverionXBlockRubyGlass");
}
public int getBlockTextureFromSideAndMetadata(int i,int j){
return 9;
}
public int quantityDropped(Random r){ //This will stop the block from dropping
return 0;
}
@SideOnly(Side.CLIENT)
public int getRenderBlockPass() //Put 0 for fully transparent or opaque blocks, and 1 for semi-transparent
{
return 1;
}
public boolean isOpaqueCube() //Tells the game if the block is transparent
{
return false;
}
public boolean renderAsNormalBlock() //Tells the game how to render the block
{
return false;
}
protected boolean canSilkHarvest() //Tells the game if silk touch can harvest the block
{
return true;
}
public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) //Renders neighbouring blocks
{
int i = par1IBlockAccess.getBlockId(par2, par3, par4);
return i == blockID ? false:true;
}
}
Quite a few different methods from normal, but everything is explained in the comments
Next, we need to do the normal stuff:
In the mod class:
public static Block rubyGlass = new BlockRubyGlass(253);
And with that, you can test it out ingame I have included a fully clear texture, so if you want to try that just change the settings as explained in the comments, and change the texture
I hope you enjoyed, and remember to keep an eye out for new tutorials
Creating custom swords
In this tutorial, I will be showing you how to create a basic custom sword:
To start, get this texture. When you have that, we can make our material, which goes in your mod class:
public static EnumToolMaterial rubyMat = EnumHelper.addToolMaterial("Ruby", 3, 64, 100.0F, 3, 15); //The material
When you have that, we need our item class, like so:
package deverionx.tutorial.common.item;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import deverionx.tutorial.common.TutorialMain;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.EnumToolMaterial;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class ItemTutorialSword extends Item
{
private int weaponDamage;
private final EnumToolMaterial toolMaterial;
public ItemTutorialSword(int ID, EnumToolMaterial material, int tex, String name)
{
super(ID); //The super constructor
this.toolMaterial = material; //The material to be used
this.maxStackSize = 1; //The max size of the itemstack
this.setMaxDamage(material.getMaxUses()); //The durability
this.setCreativeTab(TutorialMain.tabGems);
this.weaponDamage = 4 + toolMaterial.getDamageVsEntity(); //How strong it is on enemies
setTextureFile("/TutorialGFX/Items.png");
this.setIconIndex(tex); //Sets the texture
setItemName(name);
}
public int func_82803_g()
{
return this.toolMaterial.getDamageVsEntity();
}
//Gets how well it works on the block
public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block)
{
if (par2Block.blockID == Block.web.blockID)
{
return 15.0F;
}
else
{
Material var3 = par2Block.blockMaterial;
return var3 != Material.plants && var3 != Material.vine && var3 != Material.coral && var3 != Material.leaves && var3 != Material.pumpkin ? 1.0F : 1.5F;
}
}
//What must happen when you hit an entity
public boolean hitEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving)
{
par1ItemStack.damageItem(1, par3EntityLiving);
return true;
}
//Called when you break a block
public boolean onBlockDestroyed(ItemStack par1ItemStack, World par2World, int par3, int par4, int par5, int par6, EntityLiving par7EntityLiving)
{
if ((double)Block.blocksList[par3].getBlockHardness(par2World, par4, par5, par6) != 0.0D)
{
par1ItemStack.damageItem(2, par7EntityLiving);
}
return true;
}
//How much damage the sword deals
public int getDamageVsEntity(Entity par1Entity)
{
return this.weaponDamage;
}
@SideOnly(Side.CLIENT)
//Makes it render nicely
public boolean isFull3D()
{
return true;
}
//Allows you to block on right click
public EnumAction getItemUseAction(ItemStack par1ItemStack)
{
return EnumAction.block;
}
//The max use time of the action
public int getMaxItemUseDuration(ItemStack par1ItemStack)
{
return 72000;
}
//Called on right clicking anywhere
public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer)
{
par3EntityPlayer.setItemInUse(par1ItemStack, this.getMaxItemUseDuration(par1ItemStack));
return par1ItemStack;
}
//Can it harvest the block type?
public boolean canHarvestBlock(Block par1Block)
{
return par1Block.blockID == Block.web.blockID;
}
//How easy it is to enchant
public int getItemEnchantability()
{
return this.toolMaterial.getEnchantability();
}
//Returns the java name of the material
public String func_77825_f()
{
return this.toolMaterial.toString();
}
//If it can be repaired
public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack)
{
return TutorialMain.ruby.itemID == par2ItemStack.itemID ? true : super.getIsRepairable(par1ItemStack, par2ItemStack);
}
}
The same as a normal item, except for all the methods that handle the speed on different blocks, how much damage it does and what is used to repair it in an anvil If you want to figure out what everything does, you can go through at your own speed.
When that's done, we just need the basics:
In your mod class:
public static Item rubySword = new ItemTutorialSword(16001, rubyMat, 8, "DeverionXRubySword");
And with that, you can try it out ingame It should do the same damage as a diamond sword, and have 64 durability. You should also be able to repair it in an anvil using rubies.
If you enjoyed the tutorial, remember to follow and keep an eye on the thread
Creating custom tools:
In this tutorial, I will be showing you how to create custom tools.
NOTE: You need to have the material from the sword tutorial for this!
To start, get this texture. When you have that, we'll create our base tool class:
package deverionx.tutorial.common.item;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import deverionx.tutorial.common.EnumToolTutorial;
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.item.EnumToolMaterial;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
public class ItemToolTutorial extends Item
{
private Block[] blocksEffectiveAgainst; //What it's good against
public float efficiencyOnProperMaterial = 4.0F; //How fast it is
public int damageVsEntity;
//The material
protected EnumToolMaterial toolMaterial;
protected ItemToolTutorial(int ID, int Damage, EnumToolMaterial m, Block[] ea)
{
super(ID);
this.toolMaterial = m; //The material
this.blocksEffectiveAgainst = ea; //What it's good against
this.maxStackSize = 1; //The max stack size
this.setMaxDamage(m.getMaxUses()); //The max damage
this.efficiencyOnProperMaterial = m.getEfficiencyOnProperMaterial();
this.damageVsEntity = Damage + m.getDamageVsEntity();
this.setCreativeTab(CreativeTabs.tabTools);
}
//How well it mines a block
public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block)
{
for (int var3 = 0; var3 < this.blocksEffectiveAgainst.length; ++var3)
{
if (this.blocksEffectiveAgainst[var3] == par2Block)
{
return this.efficiencyOnProperMaterial;
}
}
return 1.0F;
}
//What happens when you hit an entity
public boolean hitEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving)
{
par1ItemStack.damageItem(2, par3EntityLiving);
return true;
}
//What happens when you break a block
public boolean onBlockDestroyed(ItemStack par1ItemStack, World par2World, int par3, int par4, int par5, int par6, EntityLiving par7EntityLiving)
{
if ((double)Block.blocksList[par3].getBlockHardness(par2World, par4, par5, par6) != 0.0D)
{
par1ItemStack.damageItem(1, par7EntityLiving);
}
return true;
}
//How much damage it does
public int getDamageVsEntity(Entity par1Entity)
{
return this.damageVsEntity;
}
@SideOnly(Side.CLIENT)
//Makes it have a slightly different render
public boolean isFull3D()
{
return true;
}
//How well it enchants
public int getItemEnchantability()
{
return this.toolMaterial.getEnchantability();
}
//Java name of the material
public String getToolMaterialName()
{
return this.toolMaterial.toString();
}
//Allows for repair in an anvil
public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack)
{
return this.toolMaterial.getToolCraftingMaterial() == par2ItemStack.itemID ? true : super.getIsRepairable(par1ItemStack, par2ItemStack);
}
//How fast it mines a block (Compatibility edition)
@Override
public float getStrVsBlock(ItemStack stack, Block block, int meta)
{
if (ForgeHooks.isToolEffective(stack, block, meta))
{
return efficiencyOnProperMaterial;
}
return getStrVsBlock(stack, block);
}
}
It's fairly self explanatory, which is good, because now we can make the shovel:
package deverionx.tutorial.common.item;
import deverionx.tutorial.common.EnumToolTutorial;
import deverionx.tutorial.common.TutorialMain;
import net.minecraft.block.Block;
import net.minecraft.item.EnumToolMaterial;
public class ItemShovel extends ItemToolTutorial
{
public static final Block[] blocksEffectiveAgainst = new Block[] {Block.grass, Block.dirt, Block.sand, Block.gravel, Block.snow, Block.blockSnow, Block.blockClay, Block.tilledField, Block.slowSand, Block.mycelium};
public ItemShovel(int ID, EnumToolMaterial m, int tex, String name)
{
super(ID, 1, m, blocksEffectiveAgainst);
setTextureFile("/TutorialGFX/Items.png");
this.setCreativeTab(TutorialMain.tabGems);
setIconIndex(tex);
setItemName(name);
}
public boolean canHarvestBlock(Block par1Block)
{
return par1Block == Block.snow ? true : par1Block == Block.blockSnow;
}
}
And then the object in our mod class:
public static Item rubyShovel = new ItemShovel(16002, rubyMat, 9, "DeverionXRubyShovel");
And when you have those setup, you have a full set of working tools
I hope you enjoyed, and don't forget to keep an eye out for new tutorials
Making your ores get broken by a specific mining level:
In this short tutorial, I will be showing you how to make your ores only get broken by a certain mining level and above.
What this means, is that you'll be able to stop your ores from getting mined by wood level, stone level, iron level, or even diamond level if you've made a higher one.
To do this, add these lines to proxy.registerBlocks():
MinecraftForge.setBlockHarvestLevel(TutorialMain.ore, 0, "pickaxe", 2); //Sets the required harvest level and tool
MinecraftForge.setBlockHarvestLevel(TutorialMain.ore, 1, "pickaxe", 2); //0 is wood, 1 is stone
MinecraftForge.setBlockHarvestLevel(TutorialMain.ore, 2, "pickaxe", 2); //2 is iron
MinecraftForge.setBlockHarvestLevel(TutorialMain.ore, 3, "pickaxe", 2); //3 is diamond
This is the metadata sensitive version, and the parameters are as so:
The first is the block.
The second is the metadata.
The third is the tool type, which can be "pickaxe"; "axe"; or "shovel"
The last parameter is the harvest level, the different vanilla levels are explained in the comments.
And with that, your ores will only be mineable be iron or higher. If you enjoyed this tutorial, remember to follow the thread, and keep an eye out for new tutorials
Creating configuration files:
In this tutorial, I will be showing you how to create your own configuration files
To start, we'll be making our class. For the sake of this tutorial, ConfigCore:
package deverionx.tutorial.common;
import net.minecraftforge.common.Configuration;
import net.minecraftforge.common.Property;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
public class ConfigCore {
//Items
public static int itemRubyID;
public static int itemMetagemID;
public static int itemRubystaffID;
public static int itemFirestoneID;
public static int itemFiredgemID;
//Tools
public static int toolRubyShovelID;
public static int toolRubyPickID;
public static int toolRubyAxeID;
public static int toolRubySwordID;
public static int toolRubyHoeID;
//Blocks
public static int blockRubyID;
public static int blockMetablockID;
public static int blockOreID;
public static int blockRubyGlassID;
//General
public static boolean isAwesome;
public static void loadConfig(FMLPreInitializationEvent e){
Configuration config = new Configuration(e.getSuggestedConfigurationFile()); //Gets the file
config.load(); //Loads it
Property rubyItem; //This is a property, see below
rubyItem = config.getItem("Ruby", 15000); //This gets the property
rubyItem.comment = "The base ruby item"; //This adds a comment
itemRubyID = rubyItem.getInt(); //This gets the value
//Item ID's
itemMetagemID = config.getItem("Meta Gem", 15001).getInt();
itemRubystaffID = config.getItem("Ruby Staff", 15002).getInt();
itemFirestoneID = config.getItem("Firestone", 15003).getInt();
itemFiredgemID = config.getItem("Firedgem", 15004).getInt();
//Tool ID's
toolRubyShovelID = config.getItem("Ruby Shovel", 16001).getInt();
toolRubyPickID = config.getItem("Ruby Pick", 16002).getInt();
toolRubyAxeID = config.getItem("Ruby Axe", 16003).getInt();
toolRubySwordID = config.getItem("Ruby Sword", 16004).getInt();
toolRubyHoeID = config.getItem("Ruby Hoe", 16005).getInt();
//Block ID's
blockRubyID = config.getBlock("Ruby Block", 300).getInt();
blockMetablockID = config.getBlock("Meta Block", 301).getInt();
blockOreID = config.getBlock("Ore Block", 302).getInt();
blockRubyGlassID = config.getBlock("Ruby Glass Block", 303).getInt();
//General
isAwesome = config.get(config.CATEGORY_GENERAL, "Is the mod awesome", true).getBoolean(true);
config.save(); //Saves the file
}
}
What we do is make an int for every ID, then, in loadConfig, which has FMLPreInitializationEvent as a parameter, we retrieve them. For that, we get the file from the event, and then load it. The first parameter of the config.getItem is the name that appears in the file, the second is the default ID. This method returns a property object, so we call getInt() to get the ID.
If you getting an item, call config.getItem, this will group it with other items.
If you are getting a block, call config.getBlock, this will group it with other blocks
If you are getting something other than an ID, call config.get, with the first parameter as config.CATAGORY_GENERAL, the second as the name, and the third as the default. We then need to call getBoolean in this case, give that a default for if it gets an invalid boolean.
Note that unless you are generating your block before the chunk is generated, ie. with biomes, make sure your ID is less than 256 with the config.getTerrainBlock method.
We then need to remake all of our items' and blocks' objects in the preinit method like so, in the mod class:
First, we change our objects to this:
public static Item ruby;
public static Item metaGem;
public static Item rubyStaff;
public static Item firestone;
public static Item firedGem;
public static EnumToolMaterial rubyMat = EnumHelper.addToolMaterial("Ruby", 3, 64, 100.0F, 3, 15); //The material
public static Item rubySword;
public static Item rubyShovel;
public static Item rubyPickaxe;
public static Item rubyAxe;
public static Item rubyHoe;
public static Block blockRuby;
public static Block metaBlock;
public static Block ore;
public static Block rubyGlass;
And then we add the preinit method, which gets called before the init:
@PreInit()
public void PreInitTutorial(FMLPreInitializationEvent e){
ConfigCore cc = new ConfigCore();
ConfigCore.loadConfig(e);
ruby = new ItemRuby(cc.itemRubyID);
metaGem = new ItemMetaGem(cc.itemMetagemID);
rubyStaff = new ItemRubyStaff(cc.itemRubystaffID);
firestone = new ItemFirestone(cc.itemFirestoneID);
firedGem = new ItemFiredGem(cc.itemFiredgemID);
rubySword = new ItemTutorialSword(cc.toolRubySwordID, rubyMat, 8, "DeverionXRubySword");
rubyShovel = new ItemShovel(cc.toolRubyShovelID, rubyMat, 9, "DeverionXRubyShovel");
rubyPickaxe = new ItemPickaxe(cc.toolRubyPickID, rubyMat, 10, "DeverionXRubyPickaxe");
rubyAxe = new ItemAxe(cc.toolRubyAxeID, rubyMat, 11, "DeverionXRubyAxe");
rubyHoe = new ItemHoe(cc.toolRubyHoeID, rubyMat, 12, "DeverionXRubyHoe");
blockRuby = new BlockRuby(cc.blockRubyID);
metaBlock = new BlockMetaGem(cc.blockMetablockID);
ore = new BlockOre(cc.blockOreID);
rubyGlass = new BlockRubyGlass(cc.blockRubyGlassID);
}
This is fairly simple, but it's also the reason why you should have a config going from the beginning, because changing everything when you have hundreds of items can be tedious.
Also note that this can be used to disable sets of items, if you are diligent with all of your registering.
And with that, you have a working config file, I hope you enjoyed, and remember to keep an eye out for new tutorials
Great tutorial so far! I managed to get your example mod to compile and I'm able to see the item in game. I did notice a couple things though that could have stopped people less experienced with Eclipse.
When I loaded the Eclipse folder for the first time, all the imports were messed up. I believe the build path variable "MCP_LOC" was not set and it defaulted to my home directory. (I'm using Linux so I'm not sure if it does that in other systems.) Since I couldn't figure out how to set the build path variable correctly, I ended up hard-coding all the relative paths to absolute ones.
(In Eclipse's Java Build Path, there is a tab named "Source" and "Libraries". Everything listed in those two tabs were not pointing to the right path.)
Rollback Post to RevisionRollBack
I know but one freedom, and that is the freedom of the mind. - Antoine de Saint-Exupery
Great tutorial so far! I managed to get your example mod to compile and I'm able to see the item in game. I did notice a couple things though that could have stopped people less experienced with Eclipse.
When I loaded the Eclipse folder for the first time, all the imports were messed up. I believe the build path variable "MCP_LOC" was not set and it defaulted to my home directory. (I'm using Linux so I'm not sure if it does that in other systems.) Since I couldn't figure out how to set the build path variable correctly, I ended up hard-coding all the relative paths to absolute ones.
(In Eclipse's Java Build Path, there is a tab named "Source" and "Libraries". Everything listed in those two tabs were not pointing to the right path.)
OK, that is very strange, right now I can't do much, but I'll investigate it more later on a Linux system
OK, that is very strange, right now I can't do much, but I'll investigate it more later on a Linux system
EDIT: I can't actually find an MCP_LOC...
Don't worry about it, it must have been an error on my part.
Edit: I was wondering, I noticed that I was able to stack Sapphire, Amethyst and Topaz in the same pile. Is that because they share the same id number? and is it the downside with "Items with Metadata"?
Also, what does "better compatibility" mean in "Metadata allows you to have multiple items/blocks in one ID, which allows for better compatibility"?
Rollback Post to RevisionRollBack
I know but one freedom, and that is the freedom of the mind. - Antoine de Saint-Exupery
I tested everything in tutorial 4 and 5 and it all works in game. Kudo for making a written tutorial that's easy to follow.
Don't worry about it, it must have been an error on my part.
Edit: I was wondering, I noticed that I was able to stack Sapphire, Amethyst and Topaz in the same pile. Is that because they share the same id number? and is it the downside with "Items with Metadata"?
Also, what does "better compatibility" mean in "Metadata allows you to have multiple items/blocks in one ID, which allows for better compatibility"?
The gems stacking is something I forgot to add in the tutorial, but I've put it in now, just add setHasSubtypes(true); in the constructor
By better compatibility I mean that it will take up less ID's used by other mods, this isn't really such a big issue with items considering how many available item ID's there are, but it is a problem with the very limited number of block ID's (though forge does add 4096 block id fix, they still run out pretty quick) and also if you don't have a config file (tutorial coming soon )
Hey following your forge modding tutorials, looking great! Its great to see someone do a forge modding tutorial instead of just mod loader. 1 Question, for the meta-data tutorial, the instructions there are different than the source from tutorials 5 and 6 which have the same class's. There is no "Private string" line in the source's of tutorials 5 and 6 and a couple of other different things. Which should I follow the code from, the source from tutorials 5 and 6 or the tutorial itself, since the source from 5 and 6 is more recent than tutorial 4 i'm going to assume the source from the more recent tutorials is correct unless you reply to this.
Hey following your forge modding tutorials, looking great! Its great to see someone do a forge modding tutorial instead of just mod loader. 1 Question, for the meta-data tutorial, the instructions there are different than the source from tutorials 5 and 6 which have the same class's. There is no "Private string" line in the source's of tutorials 5 and 6 and a couple of other different things. Which should I follow the code from, the source from tutorials 5 and 6 or the tutorial itself, since the source from 5 and 6 is more recent than tutorial 4 i'm going to assume the source from the more recent tutorials is correct unless you reply to this.
Thanks again,
Brennan
It doesn't really matter which one you do, I'll take it out of the tutorial for consistency's sake, but it doesn't really matter, I just prefer the method that I've used in the 5+6 source code
Modding Tutorials:
Hey everyone, I just wanted to make this thread to help people with making mods Enjoy these tuts and give feedback, they should be able to take you from the basics to some fairly advanced work.
PLEASE: Make sure you have at least a basic java knowledge before beginning on minecraft modding, you'll just get confused and find it hard to make interesting content. I recommend TheNewBoston, yes, it is a lot of tutorials, but he is a VERY good teacher
To see the code used for this tutorial, visit the github, and also, don't try to change stuff, I'm a major github noob and I'll probably freak out xD
I'm not just going to solve any problems you give me, if you have a legitimate problem, ask around elsewhere on the forums, I'm not here to write your mod for you. Note that you can also ask for help at the forge forums, the community over there is cool. I will, btw, help with requests for how to add content, suggestions for tutorials, and things I should add to my tutorials.
Required programs:
1.5:
1.5:
Setting up MCP:
When you have that, you'll need to make a folder to keep your mod in, note that this can be in a github folder GIve the folder the name of your mod.
From there, copy everything from mcp742 into your mod folder, and navigate to */forge, * being the name of your mod folder. Innside of that, run install.bat, or .sh if you're not on windows. With that running, sit back and relax, this could take a while depending on your system.
Finally, once that finishes, you can open the minecraft code by opening */eclipse with eclipse. Note that if you are using a different IDE, you'll have to check on the MCP page for tutorials on how to open with it
And with that, we're done here. In the next tutorial we can set up the framework for our mod, and then finally get to some more interesting things, I hope you enjoyed this tutorial, and remember to keep an eye on the thread!
1.4.7:
Starting you mod:
When it's open, navigate to Minecraft/src, and make a new package, name this package anything you want, preferably your username, which will help to avoid conflicts with other mods, just in case, this will be a global package that will hold all of you mods inside of MC (eg. deverionx.mineTech or deverionx.baitedFishing).
Inside of that, make another package, the name of your mod, for this tutorial, I'll be working inside of deverionx.tutorial, but you can name it whatever you're working on. For the sake of neatness, I'll be organising the mod into deverionx.tutorial.common for everything based in the serverside, and deverionx.tutorial.client, for everything clientside, like GUI's and everything else to do with rendering, though this isn't actually necessary, it makes the mod easier to look at, if other people were to look at your code for some reason .
Now, inside your common package, make your mod class, unlike old 1.2 modding, this doesn't have to be mod_***, it can be anything you want. This is the code you need, keep in mind that you should change the names to fit your own mod:
You'll get some errors, but these will be resolved shortly. For the @Mod, modID is an incode name for you mod, and also appears in the server console when players log in with the mod, name and version are extra info that appear in the mod list ingame. Now though, you need to make your proxy classes:
First, make a new package: deverionx.tutorial.common.core in my case
CommonProxy:
And now the ClientProxy:
Finally, add the packet handlers for later on:
ServerPacketHandler:
ClientPacketHandler:
And with that, you have the foundation of a working mod! The next step is to start adding some items and blocks, and then we can get into more interesting stuff!
Creating your first basic item:
When you have the texture, add this line to ClientProxys' registerRenderInformation method:
This will allow you to use your texture for items, but now we need to make our item class:
We need a new package for items, for me it is: deverionx.tutorial.common.item. Now add the class:
ItemRuby:
Everything in there is fairly self-explanatory, but I explained it in comments anyway. Now we need to make out item's object in the mod, so add this line:
Don't forget to import ItemRuby. Next, we should add an ingame name for it, go to addNames() in CommonProxy and add:
And then call it in your mod class:
And with that, your item should be working! Feel free to check it out in game, and keep an eye on this thread for more tutorials!
Creating Metadata items:
Now that you have that (making sure it's in the TutorialGFX folder), you can make your item's class in the item package:
ItemMetaGem:
Then add the object to your mod class:
Once again, don't forget to import it. Next we need to add their ingame names:
Depending on how many metadata values you have, you may or may not want to use a for loop for it, but I decided not to for this tutorial.
With that, you can check out your item ingame, and feel free to follow this thread to get updates on tutorials
Recipes, smelting and fuel:
To start, let's make a recipe for the ruby, this goes in CommonProxy addRecipes() method:
This recipe will be one glass in between two red dye gives ruby. I'll go through this step by step:
1: GameRegistry.addRecipe is the method used to add a regular recipe
2: The first parameter is the ouput, in this case 1 ruby
3: Then you put a string with letters, these indicate the location and type of item to be used
4: Character.valueOf follows that, it tells what letter you'll describe
5: This is followed by an Item/Block/ItemStack, you only really use itemstacks for adding metadata
ingredients
In this case, I use dye, the dye metadatas are as follows:
0=Black
1=Red
2=Green
3=Brown
4=Blue(lapis lazuli)
5=Purple
6=Cyan
7=Silver(light grey)
8=Grey
9=pink
10=Lime
11=Yellow
12=Light Blue
13=Magenta
14=Orange
15=White
For wool blocks, it is reversed. Anyway, now to add a shapeless recipe:
The first recipe is one glass and one lapis anywhere on the table for a sapphire, and the second is one ruby and one sapphire anywhere on the table for an amethyst. If you look at the method, you'll see that there are no strings and no Character.valueOf's, this is because the items can be anywhere on the table. Now for the smelting recipe:
This is the main way to add a smelting recipe, the first parameter is the itemID of the input, the second is the output itemstack and the third is the xp reward. This recipe is that you put in one ruby and take out one topaz. Now for a meta-sensitive version:
This makes it meta-sensitive. The first parameter is the itemID, the second is metadata, the third is output and the fourth is xp reward. The final thing left to do is add a custom fuel:
To do this, first make the FuelHandler class in your common.core.handlers package:
Then add this to your mod class:
Don't forget to call CommonProxy.addRecipes(), otherwise your recipes won't work!:
And with that, everything should be working! Feel free to check it out ingame, and keep an eye out for new tutorials
Custom creative mode tabs:
TabGems:
I've explained everything in there in the comments, so now what we need to do is add the object to our mod class. Keep in mind that for this to work, you NEED to create the constructor before your items and blocks, otherwise they don't appear inside. This is our object's line:
Fairly simple, the first parameter is the position, in this case 12: on page 2 of the inventory. The reason that we use that method is because without it, we would have incompatibility problems. With this we have a working creative inventory tab, all you have to do now is go to your item classes and add them to the tab by changing the setCreativeTab(CreativeTabs.tabMaterial) method to setCreativeTab(TutorialMain.tabGems). Feel free to check it out ingame, and keep an eye on this thread for more updates
Creating your first basic block:
To start, let's make our block class:
I've explained it all in the code and apart from that it really is very simple. Next we need an object for it in the mod class:
And then we need to register the block, which allows it to render without crashing the game. Put this line before the other proxy calls:
When that's done, we need to register the block in the proxy method like this:
Simple enough, then add the block ingame name:
And the recipe:
And with that, feel free to check it out ingame and keep an eye out for new tutorials
Creating blocks with metadata:
To start, we once again need our block class, which is slightly longer than the last one:
Everything is explained in the comments like always. For metadata blocks, just having the block class isn't enough, we also need an item for it:
With that done, we can make the block object in the mod class:
And then we need to register it, this is slightly different from a basic block:
This time it registers the block together with the itemblock. Now all we need are the names and recipes:
For the names, we need to use itemstacks like when we made metadata items:
And then for the recipes I'll use a for loop:
And with that, you can check out your block's ingame and keep an eye out for new tutorials
Ore Generation:
To start, download this texture. Once that's done, we need a block class:
Then make the item block:
We're nearly at the world gen part, first we need to make the block object:
Register the block:
And name the blocks:
With that, we can start on the world gen part:
First, make the class WorldGenHandle in deverionx.tutorial.common.core.handlers, implementing IWorldGenerator:
Let me explain in more detail:
The generate method is an override from the interface, and inside it we get what world type it is. If we do it this way, we'll achieve Mystcraft compatibility, which is a good thing , if it's one: We generate the overworld, and call generateSurface
In generate surface, the first for loop makes it go through the different metas
The second loop is rarity, the number of veins in a chunk
The x variable is the exact x coordinate for the ore
The y variable is a random number less than 40
The z variable is the exact z coordinate for the ore
WorldGenMinable is the prewritten world gen for ores:
The first parameter is the block ID
The second parameter is the metadata
The third parameter is the vein size
Then we tell our GenMinable to generate with our three coordinates, our world object and our random
Finally, all we have to do is register the world gen handler in our mod class:
And with that, the ores will generate in the world, so feel free to check it out ingame and keep an eye out for new tutorials
Updating past 1.4.5
With the 1.4.6 update, the code in Minecraft has been completely reorganized into separate packages, which has killed imports, so to start we have to fix them:
First move your code from your 1.4.5 mod to your 1.4.6 folder, and receive a lot of errors. Then you need to go through all of your classes fixing imports:
The MC code was organized into packages like net.minecraft.block and net.minecraft.client.render, much like our mod, so the fixing shouldn't be too hard, it'll just take a while, and I personally recommend *erasing all of your imports and let eclipse help you import the new classes
*Most of the *Forge imports should still be fine
**The Side and SideOnly classes have been moved to cpw.mods.fml.relauncher.*';
**The GameRegistry.registerBlock method has changed, give it a String parameter at the end for the mod specific name, this helps the block avoid conflicts (Do the same for metadata block registers)
When your imports are fixed, just go ingame and see if everything still works, if it doesn't just ask for help here and I'll do my best to help!
Special item effects:
In this tutorial, I will be showing you how to add special effects to your items:
First, get this texture, then we need an item class:
ItemRubyStaff:
Everything is explained in the comments, mostly:
In onItemUse:
Parameter one is itemstack
two is player
three is world
four to six are coordinates
seven is block side
In addInformation:
Parameter one is itemstack
two is player
three is the info list
In getRarity:
Parameter one is the itemstack
In getDamageVsEntity:
Parameter one is the entity being hit
In hasEffect:
Parameter one is the itemstack
Note that the itemstack parameters can be used to add different info/effects depending on metadata
After that, we just need the usual, an object, name and recipe:
And with that, you can go ingame and try out the item, keep an eye out for new tutorials, and I hope you enjoyed!
Using the ore dictionary:
In this tutorial, I will be showing you how to use the ore dictionary on your items and blocks:
To start, I will explain the ore dictionary: The ore dictionary is a tool added by forge that allows your items to be used in recipes from other mods. For example, say you have a copper item, and another mod using the ore dictionary adds a recipe with their own copper bar, your copper will be able to be used in that recipe alongside the other mod's copper, so the ore dictionary provides basic integration between mods.
To start, add the registerOre method to your commonproxy:
Then add this line to the method:
For metadata items, do this:
Just like with names and recipes, you need to use itemstacks for metadata items.
To register blocks to the ore dictionary, it is identical, just with the blocks instead.
Remember this though: When you name something in the ore dictionary, it should always have this format so as to match other mods:
"typeItem", eg: "gemRuby", or "ingotSteel"
The last thing we need to do before we're done is call the method in our mod class after all the other's in our init method:
And with that, you can try recompiling your mod and testing it alongside another mod, I recommend Redpower, because it adds rubies and sapphires. Keep an eye out for new tutorials, and I hope you enjoyed!
Distributing your mod!:
Step 1: Open your mod folder
Step 2: Run the recompile.bat there (if on windows)
Step 3: When that finishes, run reobfuscate.bat
Step 4: Navigate to reobf/Minecraft
Step 5: Copy your mod package (for me deverionx)
Step 6: Create a zip file back in your mod folder named *yourmod*
Step 7: Paste the mod package inside it
Step 8: Paste your GFX folder inside it
Step 9: Upload the zip file to Mediafire/Your preferred cloud storage site
Step 10: If you want to, create an adf.ly link
Step 11: Create your mod thread! Keep in mind to refer to the following rules:
Your thread title must include the following in square brackets:
Minecraft version for mod
Forge
Mod version (optional) (I recommend putting this one after mod name)
Download count (optional)
Then put the name of your mod.
In the thread, you need:
A full description of what the mod contains
You NEED to have pictures
You NEED a direct link for download
You can have an adf.ly link
Installation instructions
A todo list (optional)
If you get mod spotlights from youtubers, you can show them on your page like this:
Remember to put screenshots and videos in spoilers most of the time
I recommend having a changelog as well as an archive of previous mod versions.
You can get copyrights here.
NOTE: If your mod is incomplete (below version 1) It belongs in the WIP forum. If it is an addon for other mods, it belongs in content packs, otherwise, just put it in the general mod section
And with that, your mod has been distributed and is available to the public, make sure to take critiscm as you should, and keep an eye out for more tutorials If you have any questions, send me a PM
Using metadata items for tab icon:
To do this, simply replace the getTabIconIndex method with this:
This will make the gem tab icon become the topaz
I hope you enjoyed this quick tutorial, and remember to keep an eye out for more
Using the ore dictionary, pt 2:
This is fairly simple, so far, with what we've implemented, our items that are registered will be usable in other mod's recipes, but not the other way round. To fix this, we need to change our recipes:
For shaped recipes, you need to do this:
As you can see, it's pretty similar to the regular shaped recipe, but instead of giving a item, block, or Itemstack, you give a string, that string being the ore dictionary name of your item. For shapeless recipes, it's pretty much the same:
And with that, you can begin converting your recipes to ore recipes, and remember to keep an eye out for new tutorials
Updating to 1.4.7
To start, update your forge and your MCP, and when they're set up, copy your code over to the new workspace.
When that's done, there's minor tweaking to do:
Using the ore dictionary pt.3: Other methods:
In this very short tutorial, I will be showing you other methods in the forge ore dictionary:
The first is the getOres method, which looks like this:
The parameter is the ore name, and as the comment explains, the method returns an arraylist of items and blocks matching that name. You can use this for adding compatible recipes in custom machines/tile entities
The second is the getOreNames method, which looks like this:
This method takes no parameters, and as the comment explains, returns an arraylist of all the ore names, an example of uses for this is the mod Twilight Forest, which uses this to find ores to generate in that dimension.
The third is the getOreID method, like so:
This method can either use the ore name or an itemstack, and returns a unique int ID for the ore name.
The fourth is the getOres method, which uses the unique int ID to return an arraylist of valid items:
And there you have it, a few special methods using the ore dictionary that you can use for adding compatibility, hope you enjoyed and keep an eye out for new tutorials
Making items get damaged when used in crafting:
When you have that, we need to make the item we'll be using as a tool:
As you can see, pretty much identical to a basic item, but for the setMaxDamage and setMaxStackSize, which you'll see in use later.
Now we need to set up the other basics for the item:
In the mod class:
In proxy.addNames:
In proxy.addRecipes:
Now for the special part, in your mod class, add this line to your init method:
You will get an error, but we'll fix that in a moment:
Create the class CraftingHandler in yourmod.common.core.handlers:
The onCrafting method is called when you take stuff out of a crafting table
The onSmelting method is called when an item gets smelted
Then add this to the onCrafting method:
This may seem complicated at first, but it's actually really simple:
What it does is it looks through the crafting slots, and if one of the items is the firestone, then it makes the itemstack be larger and be damaged.
Then we can make another item, which will be the different things we can craft:
Then make the object in your mod class. When that's done, add the names:
The recipes are, despite what you might expect, completely normal, ish:
As you can see, the only difference is the the firestone uses the metadata -1. which basically means that any metadata can be used. Then just do the same for the other gem:
And with that, you should be done! Feel free to check it out ingame, and keep an eye out for new tutorial
Creating transparent blocks:
When you have that, we can make our first block class:
BlockRubyGlass:
Quite a few different methods from normal, but everything is explained in the comments
Next, we need to do the normal stuff:
In the mod class:
In proxy.registerBlocks():
In proxy.addNames():
In proxy.addRecipes():
And with that, you can test it out ingame I have included a fully clear texture, so if you want to try that just change the settings as explained in the comments, and change the texture
I hope you enjoyed, and remember to keep an eye out for new tutorials
Creating custom swords
To start, get this texture. When you have that, we can make our material, which goes in your mod class:
When you have that, we need our item class, like so:
The same as a normal item, except for all the methods that handle the speed on different blocks, how much damage it does and what is used to repair it in an anvil If you want to figure out what everything does, you can go through at your own speed.
When that's done, we just need the basics:
In your mod class:
In proxy.addNames():
In proxy.addRecipes():
And with that, you can try it out ingame It should do the same damage as a diamond sword, and have 64 durability. You should also be able to repair it in an anvil using rubies.
If you enjoyed the tutorial, remember to follow and keep an eye on the thread
Creating custom tools:
NOTE: You need to have the material from the sword tutorial for this!
To start, get this texture. When you have that, we'll create our base tool class:
It's fairly self explanatory, which is good, because now we can make the shovel:
And then the object in our mod class:
In proxy.addNames():
In proxy.addRecipes():
And when that's done you can check out the shovel ingame
The other's are basically the same, so all you really need are the classes:
Pickaxe:
Axe:
And the hoe:
And when you have those setup, you have a full set of working tools
I hope you enjoyed, and don't forget to keep an eye out for new tutorials
Making your ores get broken by a specific mining level:
What this means, is that you'll be able to stop your ores from getting mined by wood level, stone level, iron level, or even diamond level if you've made a higher one.
To do this, add these lines to proxy.registerBlocks():
This is the metadata sensitive version, and the parameters are as so:
The first is the block.
The second is the metadata.
The third is the tool type, which can be "pickaxe"; "axe"; or "shovel"
The last parameter is the harvest level, the different vanilla levels are explained in the comments.
And with that, your ores will only be mineable be iron or higher. If you enjoyed this tutorial, remember to follow the thread, and keep an eye out for new tutorials
Creating configuration files:
To start, we'll be making our class. For the sake of this tutorial, ConfigCore:
What we do is make an int for every ID, then, in loadConfig, which has FMLPreInitializationEvent as a parameter, we retrieve them. For that, we get the file from the event, and then load it. The first parameter of the config.getItem is the name that appears in the file, the second is the default ID. This method returns a property object, so we call getInt() to get the ID.
If you getting an item, call config.getItem, this will group it with other items.
If you are getting a block, call config.getBlock, this will group it with other blocks
If you are getting something other than an ID, call config.get, with the first parameter as config.CATAGORY_GENERAL, the second as the name, and the third as the default. We then need to call getBoolean in this case, give that a default for if it gets an invalid boolean.
Note that unless you are generating your block before the chunk is generated, ie. with biomes, make sure your ID is less than 256 with the config.getTerrainBlock method.
We then need to remake all of our items' and blocks' objects in the preinit method like so, in the mod class:
First, we change our objects to this:
And then we add the preinit method, which gets called before the init:
This is fairly simple, but it's also the reason why you should have a config going from the beginning, because changing everything when you have hundreds of items can be tedious.
Also note that this can be used to disable sets of items, if you are diligent with all of your registering.
And with that, you have a working config file, I hope you enjoyed, and remember to keep an eye out for new tutorials
[represent]
I have no plans of stopping any time soon
When I loaded the Eclipse folder for the first time, all the imports were messed up. I believe the build path variable "MCP_LOC" was not set and it defaulted to my home directory. (I'm using Linux so I'm not sure if it does that in other systems.) Since I couldn't figure out how to set the build path variable correctly, I ended up hard-coding all the relative paths to absolute ones.
(In Eclipse's Java Build Path, there is a tab named "Source" and "Libraries". Everything listed in those two tabs were not pointing to the right path.)
I know but one freedom, and that is the freedom of the mind. - Antoine de Saint-Exupery
OK, that is very strange, right now I can't do much, but I'll investigate it more later on a Linux system
EDIT: I can't actually find an MCP_LOC...
Sure thing Putting up a tutorial now
Don't worry about it, it must have been an error on my part.
Edit: I was wondering, I noticed that I was able to stack Sapphire, Amethyst and Topaz in the same pile. Is that because they share the same id number? and is it the downside with "Items with Metadata"?
Also, what does "better compatibility" mean in "Metadata allows you to have multiple items/blocks in one ID, which allows for better compatibility"?
I know but one freedom, and that is the freedom of the mind. - Antoine de Saint-Exupery
The gems stacking is something I forgot to add in the tutorial, but I've put it in now, just add setHasSubtypes(true); in the constructor
By better compatibility I mean that it will take up less ID's used by other mods, this isn't really such a big issue with items considering how many available item ID's there are, but it is a problem with the very limited number of block ID's (though forge does add 4096 block id fix, they still run out pretty quick) and also if you don't have a config file (tutorial coming soon )
That was fast! And it works!
I know but one freedom, and that is the freedom of the mind. - Antoine de Saint-Exupery
No problem, I noticed a new email in my inbox and checked it out
There is an extra comma after the last "new" keyword:
Otherwise, everything works well and I was able to craft the block.
I know but one freedom, and that is the freedom of the mind. - Antoine de Saint-Exupery
Thanks again,
Brennan
Oops, the forum was doing weird things with displaying the code and I accidentally messed it up, will fix now
It doesn't really matter which one you do, I'll take it out of the tutorial for consistency's sake, but it doesn't really matter, I just prefer the method that I've used in the 5+6 source code
this is god send, i can teach myself java and learn to mod minecraft at the same time, i'll be following your posts.
Thanks I'll do my best, but with exams, I might only manage 1 tutorial a day