Minecraft 1.12 modding with forge – 3 – custom item

Hello everyone,

Today we are going to make a custom item, I am going to show you how to register your items, register item models, and work with RegistryEvents.

First we are going to create some packages and files.

  1. Create a package in your mod package and call it items. This package will contain all of the custom item classes.
  2. Create another package inside the mod package and call it init. In this package we will put all of our item, block etc. initialization classes.
  3. Inside the items package create a class ItemBasic.
  4. Inside the init package create a class ModItems.

Your package structure should now look a little like this:

The ItemBasic class should extend Item (When importing make sure to import “net.minecraft.item.Item”). Now add a constructor with a String name. Inside of the constructor call the methods: “setUnlocalizedName and setRegistryName” and pass them the name variable. The setUnlocalizedName method will set the unlocalizedName of the item, this will add item. in front of the name (item.name). The setRegistryName will set the registryName of the item. This name is used internally and should never be changed after assigning the item.

This class will be the most basic item possible, it won’t have any special effects.

In the ModItems class we will be instantiating and registring our objects. In the ModItems class create a static variable of type Item, I will call it tutorial_item and a public static method called init. This method will be called in the preInit function of our Main class and initialize all of our items. It will return nothing and it doesn’t need any arguments.
In the init function initialize the tutorial_item variable. I will pass it the name tutorial_item.

Now we need to let forge know we have an item to register, this is done in the RegistryEvent. Add a public static method called registerItems it has to have an argument of type RegistryEvent.Register<Item>. Above the method add an annotation @SubscribeEvent and above the class declaration add an annotation @Mod.EventBusSubscriber and add an modid attribute.
In the registerItems method register your item by calling the register method like this:

In the Main class’ init method call the init method of the ModItems class.


This is technically enough for forge to load the item. When you start the game, and load a world you can give yourself the item with the command: “/give @p modid:itemname”. When you do this you will see that it doesn’t have a model and texture yet. So lets add those right now!

In the ModItems class we will use another event to register the model location of the item. This is done in the ModelRegistryEvent. Add a public static method called registerRenders with as argument ModelRegistryEvent. Don’t forget to add an @SubscribeEvent annotation above the method!

Add another method, this method is also static and takes an Item as argument, I will call it registerRender (without an “s”!). In this method add the following line:

ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation( item.getRegistryName(), "inventory")); 

This line will set the location of the item model.
In the registerRenders method call the registerRender method and pass it your custom item.
Your item will now have a location registered, we haven’t added a model and texture yet so forge will change it with a custom model telling you the location.

To add a model and texture create a new package in the src/main/resources folder called assets.modid and ofcourse replace modid with your modid. In this package we have to create some more packages. Create: models.item and textures.items (make sure you don’t have a “s” behind item after models).
In the textures.items package you can add a texture (make sure its size is a power of 2, 16×16, 32×32, etc.). It doesn’t matter what you call it but it has to be lowercase and you have to remember the name. I will call it tutorial_item.png and I will use this texture:
In the models.item package create a new text file. In the text file add the following json code:


Save it under the same name as your item but make sure it is all lowercase or it won’t work, also remember to save it as NAME.json. You have to replace the words in capslock with the corresponding values. The texture name shouldn’t contain the extension (.png).
You may have noticed that the name isn’t displaying correct. That is because we haven’t added a lang file yet, so lets do that. In the assets.modid package create a new package called lang, in this package create a new text file. In this text file add the following line:

 item.ITEMNAME.name=YOUR NAME 

And again, replace the words in caps with your own values. Save this file in the lang package and call it en_us.lang.
One last thing before we can launch the game and admire our new item, in the src/main/resources folder create a new textfile, give it the following contents and save it as pack.mcmeta:

This will make sure forge uses version 3 of the pack versions. (This is recommended for 1.12)

Now you can start the game and you should have an item with texture and name!

It would probably be smart to add it to a creative tab, in the ModItems class’ init method you can change some simple things about the item. Because of the way forge is made you can chain method calls after eachother. Call the method setCreativeTab on the item, I will put it in the miscellaneous creative tab. So I will pass the method CreativeTabs.MISC. Just to show you how to chain methods I make it stack to 32. I will do this by calling setMaxStackSize. This is the line I have now:

tutorialItem = new ItemBasic("tutorial_item").setCreativeTab(CreativeTabs.MISC).setMaxStackSize(32);

Well that was it for this part! In the next part we will add a custom block. By clicking here you will be send to the code of this part.
As always if you have any question don’t hesitate to ask in the comments! Also if you saw any errors in the tutorial please let me know so I can fix it!

~suppergerrie2

Posted in Forge tutorial, Forge Tutorial 1.12.

40 Comments

  1. I put all the GitHub files you uploaded into eclipse. It runs but the textures are black and purple. what could cause this? I have spent two days trying to figure this out, and I am out of ideas. I am trying to make it work so I can exchange the names and textures to begin my first mod.

    • There is probably an error in the log, if you can post the log on a site like pastebin and send it I could take a look.

  2. When you have an issue with your mod the most helpful thing you can do when asking for help is to provide your code to those helping you. The most convenient way to do this is via GitHub or another source control hub.

  3. {
    “parent”: “item/generated”,
    “textures”: {
    “layer0”: “carson01:items/wurzite”
    },

    “display”: {
    “thirdperson”: {
    “rotation”: [-90,0,0],
    “translation”: [0,1,-3],
    “scale”: [0.55,0.55,0.55]
    },
    “firstperson”: {
    “rotation”: [0,-135,25],
    “translation”: [0,4,2],
    “scale”: [1.7,1.7,1.7]
    }
    }
    }
    is this correct? whenever i run java it dosent show the object texture and places it in the center of the screen next to the crosshair

  4. The texture isn’t showing up for me. Did i do something wrong.
    ModItems.java:

    package modpackage.init;

    import modpackage.Reference;
    import modpackage.items.ItemBasic;
    import net.minecraft.client.renderer.block.model.ModelResourceLocation;
    import net.minecraft.item.Item;
    import net.minecraftforge.client.event.ModelRegistryEvent;
    import net.minecraftforge.client.model.ModelLoader;
    import net.minecraftforge.event.RegistryEvent;
    import net.minecraftforge.fml.common.Mod;
    import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

    @Mod.EventBusSubscriber(modid=Reference.MODID)
    public class ModItems {

    static Item tutorialItem;

    public static void init() {
    tutorialItem = new ItemBasic(“tutorialItem”);
    }

    @SubscribeEvent
    public static void registerItems(RegistryEvent.Register event) {
    event.getRegistry().registerAll(tutorialItem);
    }

    @SubscribeEvent
    public static void registerRenders(ModelRegistryEvent event) {
    registerRender(tutorialItem);
    }

    private static void registerRender(Item item) {
    ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation( item.getRegistryName(), “inventory”));
    }

    }
    ——————————————–
    tutorialitem.json:

    {
    “parent”: “item/generated”,
    “textures”: {
    “layer0”: “carson01:items/tutorialitem”
    },

    “display”: {
    “thirdperson”: {
    “rotation”: [-90,0,0],
    “translation”: [0,1,-3],
    “scale”: [0.55,0.55,0.55]
    },
    “firstperson”: {
    “rotation”: [0,-135,25],
    “translation”: [0,4,2],
    “scale”: [1.7,1.7,1.7]
    }
    }
    }

    • Any errors in the log? I think you should rename your json to tutorialItem with a capital I in item if the name you posted here is the same as you actually used.

  5. So, I am trying to make some simple item with this tutorial, and when on the step where you add the registry event stuff, the “tutorialItem” is being underlined in red, demanding that “tutorialItem cannot be resolved to a variable”. I am a total noob when it comes to java, so I could use some help. Thanks in advance!

    • You should probably learn java first, but without code I cant really help.
      You are trying to refer to a variable named “tutorialItem” but havent made that anywhere.

  6. I saw two different ways to register item. One of that is what you are teaching in this tutorial.
    Call the init method of the ModItems class in the main class’ preInit method.
    But in other’s tutorial are using the different to register item. Here is the code.
    @Mod.EventBusSubscriber
    public static class RegistrationHandler {

    @SubscribeEvent
    public static void registerItems(RegistryEvent.Register event) {
    ModItems.register(event.getRegistry());
    }

    }
    I want to know what is the different between this two ways. Is there have advantage or disadvantage?
    Look forward to your kind reply, THX 🙂

    • With the code you pushed nothing happens, so i’m not sure how they do it. But it seems like their way is to initialize the items when the registry event is fired, which better and is what I do in the tutorials from 1.13+

      • Is seems that you are right. After a check, I found that there are a comment say,
        “This is a special class that listens to registry events, to allow creation of mod blocks and items at the proper time.’
        Thanks for your reply.

  7. The game crashes when I try to run it from Eclipse. my mod is called “eekfastfood”, so you can ctrl+f for that. The problem is in this class.

    package com.example.eeksfastfood;

    import net.minecraft.item.Item;
    import net.minecraftforge.event.RegistryEvent;
    import net.minecraftforge.fml.common.Mod;
    import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
    import com.example.eeksfastfood.items.*;
    @Mod.EventBusSubscriber(modid=EeksFastFood.MODID)
    public class ModItems {

    public static Item TestItem;

    public static void init()
    {
    TestItem = new TestItem(“test_item”);
    }

    @SubscribeEvent
    public static void registerItems(RegistryEvent.Register event)
    {
    event.getRegistry().registerAll(TestItem);
    }
    }

    Here is the crash report:

    —- Minecraft Crash Report —-
    // You’re mean.

    Time: 8/29/19 1:57 PM
    Description: Initializing game

    java.lang.NullPointerException: Can’t use a null-name for the registry, object null.
    at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:864)
    at net.minecraftforge.registries.ForgeRegistry.add(ForgeRegistry.java:295)
    at net.minecraftforge.registries.ForgeRegistry.add(ForgeRegistry.java:289)
    at net.minecraftforge.registries.ForgeRegistry.register(ForgeRegistry.java:122)
    at net.minecraftforge.registries.ForgeRegistry.registerAll(ForgeRegistry.java:163)
    at com.example.eeksfastfood.ModItems.registerItems(ModItems.java:21)
    at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_4_ModItems_registerItems_Register.invoke(.dynamic)
    at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
    at net.minecraftforge.fml.common.eventhandler.EventBus$1.invoke(EventBus.java:144)
    at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:182)
    at net.minecraftforge.registries.GameData.fireRegistryEvents(GameData.java:782)
    at net.minecraftforge.fml.common.Loader.preinitializeMods(Loader.java:628)
    at net.minecraftforge.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:252)
    at net.minecraft.client.Minecraft.init(Minecraft.java:513)
    at net.minecraft.client.Minecraft.run(Minecraft.java:421)
    at net.minecraft.client.main.Main.main(Main.java:118)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
    at GradleStart.main(GradleStart.java:25)

    A detailed walkthrough of the error, its code path and all known details is as follows:
    —————————————————————————————

    — Head —
    Thread: Client thread
    Stacktrace:
    at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:864)
    at net.minecraftforge.registries.ForgeRegistry.add(ForgeRegistry.java:295)
    at net.minecraftforge.registries.ForgeRegistry.add(ForgeRegistry.java:289)
    at net.minecraftforge.registries.ForgeRegistry.register(ForgeRegistry.java:122)
    at net.minecraftforge.registries.ForgeRegistry.registerAll(ForgeRegistry.java:163)
    at com.example.eeksfastfood.ModItems.registerItems(ModItems.java:21)
    at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_4_ModItems_registerItems_Register.invoke(.dynamic)
    at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90)
    at net.minecraftforge.fml.common.eventhandler.EventBus$1.invoke(EventBus.java:144)
    at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:182)
    at net.minecraftforge.registries.GameData.fireRegistryEvents(GameData.java:782)
    at net.minecraftforge.fml.common.Loader.preinitializeMods(Loader.java:628)
    at net.minecraftforge.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:252)
    at net.minecraft.client.Minecraft.init(Minecraft.java:513)

    — Initialization —
    Details:
    Stacktrace:
    at net.minecraft.client.Minecraft.run(Minecraft.java:421)
    at net.minecraft.client.main.Main.main(Main.java:118)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
    at GradleStart.main(GradleStart.java:25)

    — System Details —
    Details:
    Minecraft Version: 1.12.2
    Operating System: Windows 10 (amd64) version 10.0
    Java Version: 1.8.0_191, Oracle Corporation
    Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
    Memory: 778693904 bytes (742 MB) / 1037959168 bytes (989 MB) up to 1037959168 bytes (989 MB)
    JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M
    IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0
    FML: MCP 9.42 Powered by Forge 14.23.5.2768 5 mods loaded, 5 mods active
    States: ‘U’ = Unloaded ‘L’ = Loaded ‘C’ = Constructed ‘H’ = Pre-initialized ‘I’ = Initialized ‘J’ = Post-initialized ‘A’ = Available ‘D’ = Disabled ‘E’ = Errored

    | State | ID | Version | Source | Signature |
    |:—– |:———— |:———— |:——————————– |:——— |
    | UCH | minecraft | 1.12.2 | minecraft.jar | None |
    | UCH | mcp | 9.42 | minecraft.jar | None |
    | UCH | FML | 8.0.99.99 | forgeSrc-1.12.2-14.23.5.2768.jar | None |
    | UCH | forge | 14.23.5.2768 | forgeSrc-1.12.2-14.23.5.2768.jar | None |
    | UCH | eeksfastfood | 1.0.0 | bin | None |

    Loaded coremods (and transformers):
    GL info: ‘ Vendor: ‘ATI Technologies Inc.’ Version: ‘4.6.13570 Compatibility Profile Context 19.7.3 26.20.13001.18009’ Renderer: ‘AMD Radeon(TM) RX Vega 11 Graphics’
    Launched Version: 1.12.2
    LWJGL: 2.9.4
    OpenGL: AMD Radeon(TM) RX Vega 11 Graphics GL version 4.6.13570 Compatibility Profile Context 19.7.3 26.20.13001.18009, ATI Technologies Inc.
    GL Caps: Using GL 1.3 multitexturing.
    Using GL 1.3 texture combiners.
    Using framebuffer objects because OpenGL 3.0 is supported and separate blending is supported.
    Shaders are available because OpenGL 2.1 is supported.
    VBOs are available because OpenGL 1.5 is supported.

    Using VBOs: Yes
    Is Modded: Definitely; Client brand changed to ‘fml,forge’
    Type: Client (map_client.txt)
    Resource Packs:
    Current Language: English (US)
    Profiler Position: N/A (disabled)
    CPU: 8x AMD Ryzen 5 2400G with Radeon Vega Graphics

    • You forgot to call setRegistryName (and also setTranslationKey // setUnlocalizedName both are the same)

    • registerItem is called by forge, we listen to the register event and forge fires that event. Forge finds the method using some java magic.

  8. Hi I’ve followed this tutorial in IntelliJ and for some reason Minecraft won’t load showing this error:
    Error:(16, 41) java: cannot find symbol
    symbol: variable ruby
    location: class com.elky.mingems.Items.ItemBasic
    I have changed every single tutorial_mod for ruby but it still shows this error, please help.

    Elky

  9. It does not work! I’ve did what you did and it does not! The Modid “tm” doesn’t work, modid “graka” doesn’t work! What am i doing wrong!

    • Please post your code. And explain what doesn’t work. You should use whatever modid you use. I’d not recommend using tm

        • Oopsie! Nevermind! I missed some codes and i fixed it! BTW, what do i must do to add more item? There’s alot of codes that only respond to tutorialItem though.

          • Every item needs at least a model file. (They can use the same texture file tho if you want them to look the same). You also need to register a new item for each item type you want. But you can re use the class made here.

  10. I have created the item but I cant get the texture to show up. My code matches what is posted on GitHub.
    Any ideas?

    • Post your code on github, make sure your names are correct and that your file is in the right location. (Also some IDEs like intellij like to create folders with the name assets.modid.blablabla instead of a folder structure like assets/modid/blablabla, make sure your folder structure is correct).

      ~suppergerrie2

    • Make sure you have the right names and they are in the right folder, if you want to you can join the discord (By clicking connect on the discord widget on the right), it is easier to help on the discord server and other people will also be available to help.

  11. Hey suppergerrie2,

    great tutorial so far 🙂

    I got stuck for a while on rendering the texture, because I didn’t save my tutorialitem file with an .json extension. So my request to you is if you can specify this more clearly in the text.

    Also there is a tiny typo in the sentence “One last thing before we can launch the game and admire our new item, in the src/main/resources folder create a new textile, give it the following contents and save it as pack.mcmeta:”

    Anyway, I’ll be making my first block now. Keep up the good work!

    • Thank you!
      I fixed the typo and added a line to tell you have to save it as NAME.json. I hope that helps!
      Good luck with making a block!

      ~suppergerrie2

Comments are closed.