User Tools

Site Tools


tutorial:items

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
tutorial:items [2024/07/02 23:31] – [Make your item become fuel, or compostable] solidblocktutorial:items [2024/10/27 14:45] (current) – [Item components] solidblock
Line 1: Line 1:
 +~~REDIRECT>https://docs.fabricmc.net/develop/items/first-item~~
 +
 ====== Adding an Item ====== ====== Adding an Item ======
  
 ===== Introduction ===== ===== Introduction =====
  
-Adding a basic item is one of the first steps in modding. You're going to need to create an ''<yarn class_1792>'' object, register it, and give it a texture. To add additional behavior to the item you will need a custom <yarn class_1792> class. In this tutorial and all future ones, the “tutorial” namespace is used as a placeholder. If you have a separate modid, feel free to use it instead.+Adding a basic item is one of the first steps in modding. You're going to need to create an ''<yarn class_1792>'' object, register it, and give it a texture. To add additional behavior to the item you will need a custom <yarn class_1792> 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 =====
  
-===== Registering an Item =====+:!: If you're in version 1.21.2 or above, please directly read [[#Creating Items in 1.21.2+]].
  
 First, create an instance of ''<yarn class_1792>''. The constructor takes in an ''<yarn class_1792>.<yarn class_1793>'' (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. First, create an instance of ''<yarn class_1792>''. The constructor takes in an ''<yarn class_1792>.<yarn class_1793>'' (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.
Line 15: Line 19:
     // for versions below 1.20.4     // for versions below 1.20.4
     public static final class_1792 CUSTOM_ITEM = new class_1792(new FabricItemSettings());     public static final class_1792 CUSTOM_ITEM = new class_1792(new FabricItemSettings());
-    // for versions since 1.20.5+    // for versions since 1.20.5, below 1.21.2
     public static final class_1792 CUSTOM_ITEM = new class_1792(new class_1792.class_1793());     public static final class_1792 CUSTOM_ITEM = new class_1792(new class_1792.class_1793());
     [...]     [...]
Line 21: Line 25:
 </yarncode> </yarncode>
  
-You'll use the vanilla registry system for registering new content. The basic syntax is ''<yarn class_2378>#<yarn method_10230>(Registry Type, <yarn class_2960>, Content)''. Registry types are stored as static fields in the ''<yarn class_7923>'' or ''<yarn class_2378>'' class, and the identifier is what labels your content. Content is an instance of whatever you're adding. This can be called anywhere as long as it occurs during initialization.+===== Register the item =====
  
-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.+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 ''<yarn class_2378>.<yarn method_10230>(Registry Type, <yarn class_2960>, Content)''. Registry types are stored as static fields in the ''<yarn class_7923>'' or ''<yarn class_2378>'' class, and the identifier is what labels your content. Content is an instance of whatever you're adding. Specifically for item, the syntax is ''<yarn class_2378>#<yarn method_10230>(<yarn class_7923>.<yarn field_41178>, <yarn class_2960>, <yarn class_1792>)''. 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.
  
 <yarncode java [enable_line_numbers="true"]> <yarncode java [enable_line_numbers="true"]>
Line 39: Line 47:
 </yarncode> </yarncode>
 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. 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.
- 
-{{:tutorial:2019-02-17_16.50.44.png?400|}} 
  
 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: 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:
Line 59: Line 65:
  
 ===== Best practice of registering items ===== ===== Best practice of registering items =====
-In the code above, you simply created //one// item. However, it is not convenient if you have //many// items, as you need to register and create an ''Identifier'' instance each time. Therefore, if you have many items in the mod, 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. You may also check vanilla ''Items'' class to see how Minecraft completes it in a similar way.+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''.
  
 <yarncode java [enable_line_numbers="true"]> <yarncode java [enable_line_numbers="true"]>
Line 67: Line 75:
          
     // an instance of our new item     // an instance of our new item
-    public static final class_1792 CUSTOM_ITEM = register(new class_1792(new class_1792.class_1793()), "custom_item");+    public static final class_1792 CUSTOM_ITEM = register("custom_item", new class_1792(new class_1792.class_1793()));
  
-    public static Item register(Item instance, String path) {+    public static <T extends Item> T register(String path, T item) {
         // For versions below 1.21, please replace ''Identifier.of'' with ''new Identifier''         // For versions below 1.21, please replace ''Identifier.of'' with ''new Identifier''
         return class_2378.method_10230(class_7923.field_41178, Identifier.of("tutorial", path), item);         return class_2378.method_10230(class_7923.field_41178, Identifier.of("tutorial", path), item);
Line 79: Line 87:
 </yarncode> </yarncode>
  
-Remember to refer to some method methods or fields in the mods initializes so as to statically load the class ''TutorialItems''.+Remember to refer to some methods or fields in the mods initializer so as to statically load the class ''TutorialItems''.
 <yarncode java [enable_line_numbers="true"]> <yarncode java [enable_line_numbers="true"]>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
Line 89: Line 97:
 </yarncode> </yarncode>
  
-> **Note:** Some experienced users may decide to use reflection to automatically all static fields of a class. This is also a preferable way, but should be used with caution. +> **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.
-===== Adding Item textures =====+
  
-Registering a texture for an item requires an item model json file and a texture imageYou're going to need to add these to your resource directoryThe direct path of each is:+===== Creating Items in 1.21.2+ =====
  
-    Item model: .../resources/assets/tutorial/models/item/custom_item.json +Since 1.21.2, the item registration is tutally rewritedYou have to store a ''RegistryKey'' in your ''Item.Settings'', so the models and translation keys will be correctly stored in item componentsOtherwise, you may see the following exceptions and Minecraft does not run:
-    Item texture: .../resources/assets/tutorial/textures/item/custom_item.png+
  
-Our example texture can be found [[https://i.imgur.com/CqLSMEQ.png|here]].+<code> 
 +java.lang.NullPointerException: Item id not set 
 +</code>
  
-If you registered your item properly in the first step, your game will complain about a missing texture file in a fashion similar to this:+To make it run correctly, you should write like below: 
 + 
 +<code java> 
 +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() { 
 +  } 
 +
 +</code> 
 + 
 +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     [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
-It conveniently tells you exactly where it expects your asset[sto be found-- when in doubt, check the log.+ 
 +That'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 [[https://i.imgur.com/CqLSMEQ.png|here]].
  
 A basic item model template is: A basic item model template is:
Line 113: Line 150:
 } }
 </code> </code>
-The parent of your item changes how it's rendered in the hand and comes in useful for things like block items in the inventory. "item/handheldis used for tools that are held from the bottom left of the texture. textures/layer0 is the location of your image file. +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.
- +
-Final textured result: +
- +
-{{:tutorial:item_texture.png?400|}}+
  
 ===== Creating an Item class ===== ===== Creating an Item class =====
  
-To add additional behavior to the item you will need to create an Item class. The default constructor requires an ''Item.Settings'' object.+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.
 <yarncode java [enable_line_numbers="true"]> <yarncode java [enable_line_numbers="true"]>
 public class CustomItem extends class_1792 { public class CustomItem extends class_1792 {
- 
     public CustomItem(class_1793 settings) {     public CustomItem(class_1793 settings) {
         super(settings);         super(settings);
Line 134: Line 166:
 <yarncode java [enable_line_numbers="true"]> <yarncode java [enable_line_numbers="true"]>
 public class CustomItem extends class_1792 { public class CustomItem extends class_1792 {
- 
     public CustomItem(class_1793 settings) {     public CustomItem(class_1793 settings) {
         super(settings);         super(settings);
     }     }
  
 +    // write this if the version is below 1.21.2:
     @Override     @Override
     public class_1271<class_1799> method_7836(class_1937 world, class_1657 user, class_1268 hand) {     public class_1271<class_1799> method_7836(class_1937 world, class_1657 user, class_1268 hand) {
         user.method_5783(class_3417.field_14983, 1.0F, 1.0F);         user.method_5783(class_3417.field_14983, 1.0F, 1.0F);
         return class_1271.method_22427(user.method_5998(hand));         return class_1271.method_22427(user.method_5998(hand));
 +    }
 +    
 +    // write this if the version is 1.21.2 or higher:
 +    @Override
 +    public ActionResult use(World world, PlayerEntity user, Hand hand) {
 +        user.playSound(SoundEvents.BLOCK_WOOL_BREAK, 1.0F, 1.0F);
 +        return ActionResult.SUCCESS;
     }     }
 } }
Line 150: Line 189:
 <yarncode java [enable_line_numbers="true"]> <yarncode java [enable_line_numbers="true"]>
 public final class TutorialItems { public final class TutorialItems {
- 
     [...]     [...]
  
     // an instance of our new item     // an instance of our new item
-    public static final CustomItem CUSTOM_ITEM = new CustomItem(new class_1792.class_1793());+     
 +    // For versions below 1.21.2: 
 +    public static final CustomItem CUSTOM_ITEM = register("custom_item", new CustomItem(new class_1792.class_1793())); 
 +     
 +    // For versions since 1.21.2: 
 +    public static final CustomItem CUSTOM_ITEM = register("custom_item", CustomItem::new, new class_1792.class_1793());
     [...]     [...]
 } }
 </yarncode> </yarncode>
-If you did everything correctly, using the item should now play a sound.+If you did everything correctly, using the item should now play a sound. You can also [[tooltip|add some tooltips]] for the item based on your item class.
  
-===== What if I want to change the stack size of my item? =====+===== 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 [[https://docs.fabricmc.net/develop/items/custom-data-components|the tutorial in Fabric docs]]. 
 + 
 +In this example, the item will be unbreakable by default, while hiding tooltips about it. 
 +<yarncode java> 
 +    // For versions below 1.21.2: 
 +    public static final CustomItem CUSTOM_ITEM register("custom_item", new CustomItem(new class_1792.class_1793() 
 +        .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))); 
 +</yarncode> 
 + 
 +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''.
  
-For this you would use ''maxCount(int size)'' inside ''Item.Settings'' to specify the max stack size. Note that if your item is damageable you cannot specify a maximum stack size or the game will throw a RuntimeException. 
 <yarncode java [enable_line_numbers="true"]> <yarncode java [enable_line_numbers="true"]>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
- 
     // An instance of our new item, where the maximum stack size is 16     // An instance of our new item, where the maximum stack size is 16
-    public static final CustomItem CUSTOM_ITEM = new CustomItem(new class_1792.class_1793().maxCount(16));+     
 +    // For versions below 1.21.2: 
 +    public static final CustomItem CUSTOM_ITEM = register("custom_item", new CustomItem(new class_1792.class_1793().maxCount(16))); 
 +    // For versions since 1.21.2: 
 +    public static final Item CUSTOM_ITEM = register("custom_item", CustomItem::new, new Item.Settings().maxCount(16));
     [...]     [...]
 } }
Line 175: Line 233:
  
 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: 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:
 +<code java>
 +public class ExampleMod implements ModInitializer {
 +    [...]
 +    
 +    // For versions below 1.21.2
 +    @Override
 +    public void onInitialize() {
 +        [...]
 +        FuelRegistry.INSTANCE.add(TutorialItems.CUSTOM_ITEM, 300);
 +    }
 +}
 +</code>
 +
 +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''.
 +<code java>
 +public final class TutorialItems {
 +    [...]
 +    
 +    // For versions below 1.21.2
 +    public static void registerFuels() {
 +        FuelRegistry.INSTANCE.add(CUSTOM_ITEM, 300);
 +    }
 +}
 +</code>
 +
 +In versions since 1.21.2, use Fabric API's ''FuelRegistryEvents'':
 +<code java>
 +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);
 +        });
 +    }
 +}
 +</code>
 +
 +And then refer to this method in your ''ModInitializer'':
 <code java> <code java>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
Line 182: Line 283:
     public void onInitialize() {     public void onInitialize() {
         [...]         [...]
-        FuelRegistry.INSTANCE.add(TutorialItems.CUSTOM_ITEM, 300)+        TutorialItems.registerFuels();
     }     }
 } }
Line 188: Line 289:
  
 Similarly, you can use a ''CompostingChanceRegistry'' to make it compostable in a composter. Similarly, you can use a ''CompostingChanceRegistry'' to make it compostable in a composter.
-==== Next Steps ====+===== Next Steps =====
 [[tutorial:itemgroup|Add your item to your own ItemGroup]]. [[tutorial:itemgroup|Add your item to your own ItemGroup]].
tutorial/items.1719963085.txt.gz · Last modified: 2024/07/02 23:31 by solidblock