User Tools

Site Tools


tutorial:items
This page has been moved, the new location is https://docs.fabricmc.net/develop/items/first-item.

Adding an Item

Introduction

Adding a basic item is one of the first steps in modding. You're going to need to create an Item object, register it, and give it a texture. To add additional behavior to the item you will need a custom Item class. In this tutorial and all future ones, the “tutorial” namespace is used as a placeholder. If you have a separate mod id, feel free to use it instead.

Create an Item instance

:!: If you're in version 1.21.2 or above, please directly read Creating Items in 1.21.2+.

First, create an instance of Item. The constructor takes in an Item.Settings (or a FabricItemSettings unless versions since 1.20.5) instance, which is used to set item properties such as the durability, and stack count. For simplicity, we just do it in ExampleMod class, and store them in static fields.

  1. public class ExampleMod implements ModInitializer {
  2.  
  3. // an instance of our new item
  4. // for versions below 1.20.4
  5. public static final Item CUSTOM_ITEM = new Item(new FabricItemSettings());
  6. // for versions since 1.20.5, below 1.21.2
  7. public static final Item CUSTOM_ITEM = new Item(new Item.Settings());
  8. [...]
  9. }

Register the item

We've create a basic item, but it still does not exist in Minecraft, because it has not been registered. In Minecraft, almost everything has an registry, and items are no exceptions.

You'll use the vanilla registry system for registering new content. The basic syntax is Registry.register(Registry Type, Identifier, Content). Registry types are stored as static fields in the Registries or Registry class, and the identifier is what labels your content. Content is an instance of whatever you're adding. Specifically for item, the syntax is Registry#register(Registries.ITEM, Identifier, Item). This can be called anywhere as long as it occurs during initialization. The method itself also returns the registered content itself.

For versions since 1.21, an Identifier is created through Identifier.of("namespace", "path"). For versions below 1.21, it is created through new Identifier("namespace", "path") or new Identifier("namespace:path"). It will fail if the namespace or path contains illegal characters.

  1. public class ExampleMod implements ModInitializer {
  2.  
  3. // an instance of our new item
  4. public static final Item CUSTOM_ITEM = new Item(new Item.Settings());
  5.  
  6. @Override
  7. public void onInitialize() {
  8. // For versions below 1.21, please replace ''Identifier.of'' with ''new Identifier''
  9. Registry.register(Registries.ITEM, Identifier.of("tutorial", "custom_item"), CUSTOM_ITEM);
  10. }
  11. }
Your new item has now been added to Minecraft. Run the run config Minecraft Client or runClient Gradle task to see it in action, execute the command /give @s tutorial:custom_item in game.

For more simplicity, you can simplify your code by directly registering them when assigning the fields, as Register.register will also return the registered object:

  1. public class ExampleMod implements ModInitializer {
  2.  
  3. // an instance of our new item
  4. public static final Item CUSTOM_ITEM =
  5. // For versions below 1.21, use ''new Identifier("tutorial", "custom_item")''.
  6. Registry.register(Registries.ITEM, Identifier.of("tutorial", "custom_item"),
  7. new Item(new Item.Settings()));
  8.  
  9. @Override
  10. public void onInitialize() {
  11. }
  12. }

Best practice of registering items

In the code above, you simply created one item. However, it is not convenient if you have many items in your mod, as you need to register and create an Identifier instance each time. Therefore, we can create a specific class to store item objects, such as ModItems or TutorialItems, and write a simple register method to conveniently register items. This is quite common in actual mod development. You may also check vanilla Items class to see how Minecraft completes it in a similar way.

In this example, create a TutorialItems class and refer to the class in the ModInitializer.

  1. public final class TutorialItems {
  2.  
  3. private TutorialItems() {}
  4.  
  5. // an instance of our new item
  6. public static final Item CUSTOM_ITEM = register("custom_item", new Item(new Item.Settings()));
  7.  
  8. public static <T extends Item> T register(String path, T item) {
  9. // For versions below 1.21, please replace ''Identifier.of'' with ''new Identifier''
  10. return Registry.register(Registries.ITEM, Identifier.of("tutorial", path), item);
  11. }
  12.  
  13. public static void initialize() {
  14. }
  15. }

Remember to refer to some methods or fields in the mods initializer so as to statically load the class TutorialItems.

  1. public class ExampleMod implements ModInitializer {
  2. @Override
  3. public void onInitialize() {
  4. TutorialItems.initialize();
  5. }
  6. }

Note: Some experienced users may decide to use reflection to automatically register all static fields of a class. This is also a preferable way, but should be used with caution.

Creating Items in 1.21.2+

Since 1.21.2, the item registration is tutally rewrited. You have to store a RegistryKey in your Item.Settings, so the models and translation keys will be correctly stored in item components. Otherwise, you may see the following exceptions and Minecraft does not run:

java.lang.NullPointerException: Item id not set

To make it run correctly, you should write like below:

public final class TutorialItems {
  private TutorialItems() {
  }
 
  public static final Item CUSTOM_ITEM = register("custom_item", Item::new, new Item.Settings());
 
  public static Item register(String path, Function<Item.Settings, Item> factory, Item.Settings settings) {
    final RegistryKey<Item> registryKey = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("tutorial", path));
    return Items.register(registryKey, factory, settings);
  }
 
  public static void initialize() {
  }
}

In the method Items.register, the registry key will be written in the settings first, and then use that settings to create the item.

Adding model and textures

If you registered your item properly in the first step, you can successfully get your item by typing command /give @s tutorial:custom_item. You will find it has missing texture, and Minecraft will complain about a missing texture file in a fashion similar to this:

  [Server-Worker-1/WARN]: Unable to load model: 'tutorial:custom_item#inventory' referenced from: tutorial:custom_item#inventory: java.io.FileNotFoundException: tutorial:models/item/custom_item.json

That's because we haven't provided the item with textures and models. Therefore, you need to define the item model json and provide a texture image. You're going to need to add these to your resource directory. The direct path of each is:

  • Item model: …/resources/assets/tutorial/models/item/custom_item.json
  • Item texture: …/resources/assets/tutorial/textures/item/custom_item.png

Our example texture can be found here.

A basic item model template is:

{
  "parent": "item/generated",
  "textures": {
    "layer0": "tutorial:item/custom_item"
  }
}

The parent of your item model changes how it's rendered in the hand and comes in useful for things like block items in the inventory. item/generated is used for many simple items. item/handheld is used for tools that are held from the bottom left of the texture. In the json, textures/layer0 is the location of your image file.

Creating an Item class

You have created a simple item, and learned how to change some basic properties. But maybe you want it to have more behaviors. Therefore, you will need to create an item class. The default constructor requires an Item.Settings object.

  1. public class CustomItem extends Item {
  2. public CustomItem(Settings settings) {
  3. super(settings);
  4. }
  5. }

A practical use-case for a custom item class would be making the item play a sound when you use it:

  1. public class CustomItem extends Item {
  2. public CustomItem(Settings settings) {
  3. super(settings);
  4. }
  5.  
  6. // write this if the version is below 1.21.2:
  7. @Override
  8. public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
  9. user.playSound(SoundEvents.BLOCK_WOOL_BREAK, 1.0F, 1.0F);
  10. return TypedActionResult.success(user.getStackInHand(hand));
  11. }
  12.  
  13. // write this if the version is 1.21.2 or higher:
  14. @Override
  15. public ActionResult use(World world, PlayerEntity user, Hand hand) {
  16. user.playSound(SoundEvents.BLOCK_WOOL_BREAK, 1.0F, 1.0F);
  17. return ActionResult.SUCCESS;
  18. }
  19. }

Replace the old Item object with an instance of your new item class:

  1. public final class TutorialItems {
  2. [...]
  3.  
  4. // an instance of our new item
  5.  
  6. // For versions below 1.21.2:
  7. public static final CustomItem CUSTOM_ITEM = register("custom_item", new CustomItem(new Item.Settings()));
  8.  
  9. // For versions since 1.21.2:
  10. public static final CustomItem CUSTOM_ITEM = register("custom_item", CustomItem::new, new Item.Settings());
  11. [...]
  12. }
If you did everything correctly, using the item should now play a sound. You can also add some tooltips for the item based on your item class.

Item components

Sometimes you may need to add some default components for the item, such as max stack size or fire durability. This can be done by calling component method in Item.Settings. Detailed information about item components can be found in the tutorial in Fabric docs.

In this example, the item will be unbreakable by default, while hiding tooltips about it.

    // For versions below 1.21.2:
    public static final CustomItem CUSTOM_ITEM = register("custom_item", new CustomItem(new Item.Settings()
        .component(DataComponentTypes.UNBREAKABLE, new UnbreakableComponent(true))));
    // For versions since 1.21.2:
    public static final Item CUSTOM_ITEM = register("custom_item", CustomItem::new, new Item.Settings()
        .component(DataComponentTypes.UNBREAKABLE, new UnbreakableComponent(true)));

Specifically, max stack size can be simply set by calling maxCount method (which is valid also before 1.20.5). Note that if your item is damageable you cannot specify a maximum stack size or the game will throw a RuntimeException.

  1. public class ExampleMod implements ModInitializer {
  2. // An instance of our new item, where the maximum stack size is 16
  3.  
  4. // For versions below 1.21.2:
  5. public static final CustomItem CUSTOM_ITEM = register("custom_item", new CustomItem(new Item.Settings().maxCount(16)));
  6. // For versions since 1.21.2:
  7. public static final Item CUSTOM_ITEM = register("custom_item", CustomItem::new, new Item.Settings().maxCount(16));
  8. [...]
  9. }

Make your item become fuel, or compostable

If you want to make it a fuel so that it can be used in a furnace, you can register in FuelRegistry when initializing the mod, for example:

public class ExampleMod implements ModInitializer {
    [...]
 
    // For versions below 1.21.2
    @Override
    public void onInitialize() {
        [...]
        FuelRegistry.INSTANCE.add(TutorialItems.CUSTOM_ITEM, 300);
    }
}

However, in practice, when you have many items to register, as registering quantities of items may be effort-consuming and messy, you can consider placing the codes in a separate method, instead of writing like above.

In versions below 1.21.2, you need to use Fabric API's FuelRegistry.INSTANCE.

public final class TutorialItems {
    [...]
 
    // For versions below 1.21.2
    public static void registerFuels() {
        FuelRegistry.INSTANCE.add(CUSTOM_ITEM, 300);
    }
}

In versions since 1.21.2, use Fabric API's FuelRegistryEvents:

public final class TutorialItems {
    [...]
 
    // For versions since 1.21.2
    public static void registerFuels() {
        FuelRegistryEvents.BUILD.register((builder, context) -> {
            // You can add multiple items at once in this lambda.
            builder.add(CUSTOM_ITEM, 300);
        });
    }
}

And then refer to this method in your ModInitializer:

public class ExampleMod implements ModInitializer {
    [...]
 
    @Override
    public void onInitialize() {
        [...]
        TutorialItems.registerFuels();
    }
}

Similarly, you can use a CompostingChanceRegistry to make it compostable in a composter.

Next Steps

tutorial/items.txt · Last modified: 2024/10/27 14:45 by solidblock