Creating your first item & block - shauncjones/Community-Mod GitHub Wiki
Note: This tutorial is created on windows and commands may vary on other systems.
We are going to be covering a lot in this tutorial, we will start with adding an item, a block, before moving into JSON model files and localization.
For our first item we are going to be creating a Copper Ingot. This has been done time and time again and there are many mods that add copper, so in a later tutorial we will be showing you how to interact with the Ore Dictionary and turn off your version of copper if another version exist.
We're going to begin by creating a package to store our items, and an ItemBase
class that will just make it a little easier to make items. We're going to be creating a package named items so the new package will be com.shauncjones.communitymod.items
. In this package create a new class named ItemBase
this class will need to extend Item
much like our ClientProxy
extended our CommonProxy
. The new class should look like this:
package com.shauncjones.communitymod.items;
public class ItemBase extends Item{
}
Next we are going to add a String & a constructor to the class like below:
protected String name;
public ItemBase(String name){
this.name = name;
setUnlocalizedName(name);
setRegistryName(name);
}
The constructor simply sets the name of the item. We're also going to be adding a method to register models like below:
public void registerItemModel(){
CommunityMod.proxy.registerItemRenderer(this, 0, name);
}
This will produce an error because registerItemRenderer
does not exist in our proxy. We will fix this later, but first we are going to override a method from Item
like below:
@Override
public ItemBase setCreativeTab(CreativeTabs tab){
super.setCreativeTab(tab);
return this;
}
We overrode this so it returns an ItemBase
instead of Item
so we can use it easier later.
We are going to simply add a method to both our CommonProxy
& our ClientProxy
to fix the error that we got.
In your CommonProxy
you'll insert the following method:
public void registerItemRenderer(Item item, int meta, String id){
}
We are leaving this empty because we are going to override it in our ClientProxy
like below:
@Override
public void registerItemRenderer(Item item, int meta, String id){
ModelLoader.setCustomModelResourceLocation(item, meta, new ModelResourceLocation(Reference.MODID + ":" + id, "inventory"));
}
This calls ModelLoader.setCustomModelResourceLocation
which tells Minecraft which item model to use for our item.
We are going to be creating another package inside of our util
package it will be named handlers
so we should now have a package like the following: com.shauncjones.communitymod.util.handlers
. We are also going to be creating a class inside of this package named RegistrationHandler
. We've created a good amount of new classes now so I am not gonna get into what the empty one should look like, we are instead going to jump right into editing it. First we are going to add an annotation the class like this:
@Mod.EventBusSubscriber
public static class RegistrationHandler{
}
The event bus if Forge's way of allowing mods to register handler methods to be run when Minecraft is being loaded. We are going to be adding two methods which will also have an annotation to indicate that the methods handle an event. Specifically the RegistryEvent
& ModelRegistryEvent
like below:
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event){
CommunityModItems.register(event.getRegistry());
}
@SubscribeEvent
public static void registerItems(ModelRegistryEvent event){
CommunityModItems.registerModels();
}
This is going to create an error because the class CommunityModItems
does not exist. We are going to create that now in the com.shauncjones.communitymod.items
package. In the new class we are going to create two methods they are responsible for registering our item, and registering our item's model the methods are the following:
public static void register(IForgeRegistry<Item> registry){
}
public static void registerModels(){
}
For now they are gonna stay empty. Now we will move on to creating our actual item. Above the methods we created we are going to add a single line and this is what actually creates our item. It will look like this:
public static ItemBase ingotCopper = new ItemBase("ingot_copper").setCreativeTab(CreativeTabs.MISC);
public static void register(IForgeRegistry<Item> registry){
registry.registerAll(
ingotCopper
);
}
public static void registerModels(){
ingotCopper.registerItemModel();
}
This does the following:
Creates a new
ItemBase
with the nameingot_copper
Set the creative tab to the Misc tab (We will create our own later) Register our item with theGameRegistry
Now if you load up the game you will see our item. Without a model but we will cover that for both our item and block later.
Now we are going to basically recreate everything from our item setup and adapt it to a block. So we are going to create another package like we did for items but instead we will name it blocks so it will be like this. com.shauncjones.communitymod.blocks
. In this package go ahead a create a new class called BlockBase
. The new class will look like the following, I will explain it after:
package com.shauncjones.communitymod.blocks;
import net.minecraft.block.Block;
import net.minecraft.material.Material
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemBlock;
import com.shauncjones.communitymod.CommunityMod;
public class BlockBase extends Block{
protected String name;
public BlockBase(Material material, String name){
super(material);
this.name = name;
setUnlocalizedName(name);
setRegistryName(name);
}
public void registerItemModel(Item itemBlock){
CommunityMod.proxy.registerItemRenderer(itemBlock, 0, name);
}
public void createItemBlock(){
return new ItemBlock(this).setRegistryName(getRegistryName());
}
@Override
public BlockBase setCreativeTab(CreativeTabs tab){
super.setCreativeTab(tab);
return this;
}
}
If you notice this is exactly the same as our ItemBase
class we created earlier with one additional method, createItemBlock
this makes dealing with the ItemBlock a little easier. When you have a block in your inventory you don't have a block you have the ItemBlock.
package com.shauncjones.communitymod.blocks;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraftforge.registries.IForgeRegistry;
public class CommunityModBlocks {
public static void register(IForgeRegistry<Block> registry){
}
public static void registerItemBlocks(IForgeRegistry<Item> registry){
}
public static void registerModels(){
}
}
If you notice this is exactly the same as our CommunityModItems
class except we replaced the <Item>
with <Block>
we also added another method, registerItemBlocks
, which is doing exactly as it is named.
Now we are going to update our RegistrationHandler
you're going to add another method to the class as follows:
@SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event){
CommunityModBlocks.register(event.getRegistry());
}
We're also going to be updating the other two methods in the class as follows:
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event){
CommunityModItems.register(event.getRegistry());
CommunityModBlocks.registerItemBlocks(event.getRegistry());
}
@SubscribeEvent
public static void registerItems(ModelRegistryEvent event){
CommunityModItems.registerModels();
CommunityModBlocks.registerModels();
}
Now that we have all the other methods created we can simply create our block inside of our CommunityModBlocks
class. Like below:
package com.shauncjones.communitymod.blocks;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraftforge.registries.IForgeRegistry;
public class CommunityModBlocks {
public static BlockBase blockCopper = new BlockBase(Material.IRON,"block_copper").setCreativeTab(CreativeTabs.MISC);
public static void register(IForgeRegistry<Block> registry){
registry.registerAll(
blockCopper
);
}
public static void registerItemBlocks(IForgeRegistry<Item> registry){
registry.registerAll(
blockCopper.createItemBlock()
);
}
public static void registerModels(){
blockCopper.registerItemModel(Item.getItemFromBlock(blockCopper));
}
}
That's it, we now have our block and if you load the game it should be under the Misc tab.
DISCLAIMER: I am terrible at making textures, and I recommend making your own but I will provide textures for all items and blocks we create in the mod.
Models for blocks and items are created using Mojang's JSON format. We are going to be creating a model for both our Copper Ingot and Copper Block. Before we get into the JSON files you're going to want to download the Copper Ingot texture from here, and save it to src/main/resources/assets/communitymod/textures/items/ingot_copper.png
. You'll also want to download the Copper Block texture from here, and save it to src/main/resources/assets/communitymod/textures/blocks/block_copper.png
.
Now we will create a JSON file and save it to src/main/resources/assets/communitymod/models/item/ingot_copper.json
. We will populate the new JSON file with the following:
{
"parent": "item/generated",
"textures": {
"layer0": "communitymod:items/ingot_copper"
}
}
Now let's break it down.
"parent"
specifies which Minecraft model to use as a parent, this parent generates the 3D look Minecraft items have."textures"
specifies all textures for this model."layer0"
Our model only has one later so we specify our texture here."communitymod:items/ingot_copper"
This line specifies where Forge can find our texture.communitymod
lets Forge know that it is part of our mod and the textures are stored in thecommunitymod
domain."items/ingot_copper"
simply specifies the path the texture is located at.
If you load the game our ingot will now have a nice texture.
Now we will texture the block. We are going to create a new JSON file and save it to src/main/resources/assets/communitymod/blockstates/block_copper.json
. We will populated the new file with the following:
{
"forge_marker": 1,
"defaults": {
"textures": {
"all": "communitymod:blocks/block_copper"
}
},
"variants": {
"normal": {
"model": "cube_all"
},
"inventory": {
"model": "cube_all"
}
}
}
Now let's break it down.
"forge_marker"
Tells Forge to use its custom blockstate parser."defaults"
Things that apply for all variants."textures"
This specifies which texture to use for the model."variants"
This is where all of our variants would good but we don't have any."model"
This uses the cube all mode to make MInecraft load the same texture for all of our sides.
You should now have a model for your Copper Block when you load up the game.
Language files are created using a .lang
extension. For a US English file it would be stored at src/main/resources/assets/communitymod/lang/en_US.lang
we will populate our new file with the following:
#Items
item.ingot_copper.name=Copper Ingot
#Blocks
tile.block_copper.name=Copper Block
You will notice the simplicity. Items are specified using item.UNLOCALIZED-NAME.name
. We set our unlocalized name when we create our block in your CommunityModBlocks
file. Blocks are specified similarly using tile.UNLOCALIZED-NAME.name
.
Now if you load the game both of our created items will have names!
You now have a mod that adds a simple item and block. You can find the next tutorials here.