Minecraft Modding: Fabric + Kotlin – Items

This entry is part 2 of 3 in the series Minecraft Modding: Fabric + Kotlin

Layout and Structure

Now that we have the mod set up, it’s time to actually start adding items! You’ll see that in our src folder, we have two sub-folders: client and main. These folders both have three sub-folders each: java, kotlin, and resources.

The java folder contains mixins, which you can read more about here (currently, mixins do not support Kotlin). We don’t need that folder right now.

The kotlin folder contains our mod’s Kotlin code. This is the folder most of our mod’s code will go in.

The last folder is resources. The content of the resources folder will change depending on if it’s in the client or main folder. In both folders, it contains a JSON file for the mixins (either modid.client.mixins.json or modid.mixins.json). The client folder has only that one file inside resources. However, the main folder will also have fabric.mod.json and assets/modid/icon.png. The file fabric.mod.json describes the metadata of the mod, and reading through it, you will see that it references files in other folders, including mod entrypoints. I recommend reading through it, as we will be editing it later. icon.png, on the other hand, is the icon of our mod. The default is a drawing of “Mod ID”. You can change the icon if you want to.

You can collapse client, as we won’t be doing anything with it right now. Now, let’s take a look through main/kotlin. You can see that there are two files: ExampleMod.kt and ExampleModDataGenerator.kt. The first is our mod’s entrypoint, and the second is where our datagen code will live.

Go ahead and rename both files to whatever you want. I’ll be using Stuff.kt and StuffDataGenerator.kt, since my mod is called Stuff (in practice, you’ll obviously want to choose a better mod name, but this is just a tutorial, so I went with that). Now, you’ll need to edit fabric.mod.json. Change entrypoints.main[0].value to the mod entrypoint file (again, Stuff in my case) and entrypoints.fabric-datagen[0].value to the datagen entrypoint file (for me, StuffDataGenerator).

Now run the Minecraft client (remember, using the runClient Gradle task) to make sure you did everything correct. If you did, it should launch successfully. If it did, great! You can stop the client, and we can get to actually making our mod.

Adding the Item

Now, create a new package named items in the same directory as the entrypoints. Right click on it and go to New > Minecraft Class, and click Item. Give it the name IceCube. A new Java class should be generated at items.IceCube:

public class IceCube extends Item {
  public IceCube(Settings settings) {
    super(settings);
  }
}

We’re using Kotlin, so right-click on the file in IntelliJ and select Convert Java File to Kotlin File.

Now, go back to the mod entrypoint file. We need to register this item so that Minecraft can see it. Add the following property to the class:

val ICE_CUBE = Registry.register(
  Registries.ITEM,
  Identifier("modid", "ice_cube"),
  IceCube(FabricItemSettings()),
)

Make sure you have the right imports, namely net.minecraft.util.Identifier and net.minecraft.registry.Registry, since the Java standard library exports classes with the same name.

The code is registering the IceCube item with the identifier modid:ice_cube. As always, remember to replace modid with your mod ID.

Now, run the Minecraft client. If you haven’t already, create a Creative mode world with cheats enabled. Use the command /give @s modid:ice_cube to give yourself the item. If you did everything correctly, you should have the item. However, it’s show the default no-texture texture, since we never gave it a texture. Let’s fix that.

Textures

Download ice_cube.png from here. In assets/modid, create the folders textures/item, and copy ice_cube.png into item. Now, in assets/modid, create the folders models/item, and create a file called ice_cube.json. This file will contain the model for the item. Add this:

{
  "parent": "item/generated",
  "textures": {
    "layer0": "modid:item/ice_cube"
  }
}

Notice that it references the ice cube texture you copied earlier, through modid:item/ice_cube. Now, run the client. The modid:ice_cube item should have the new texture!

If we want our item to have a certain stack size, like 16, we can use the methods on FabricItemSettings. Go to the mod entrypoint file, and where you registered the ice cube as an item, you’ll see that you passed an instance of that class with FabricItemSettings(). Replace FabricItemSettings() with FabricItemSettings().maxCount(16). You can use methods to add properties like this. In addition to the stack size, let’s try making it fireproof with the fireproof() method.

Run the client again, and use the command /give @s modid:ice_cube 64. You should have 4 stacks of ice cubes, 16 ice cubes in each stack. Now, place down some lava. Throwing most vanilla items in should cause them to burn and be destroyed. But if you throw an ice cube in, nothing will happen, and you can pick it back up again!

Creating an ItemGroup

As we add more items to our mod, especially those that don’t fit into any of the creative tabs in the inventory, we’ll want to create a creative tab for our mod. As the Fabric tutorial says: “Before you create an item group, determine whether it would have enough content to warrant its own group. Your item group will be placed on a separate page of tabs, impacting its discoverability, and users may be confused if the item is not where similar items are in the creative inventory.” Since this is a tutorial mod, we’ll go ahead and add it regardless, but you should consider this before adding it in your own mods.

Add the follow property to your mod entrypoint class:

private val MODID_GROUP = RegistryKey.of(RegistryKeys.ITEM_GROUP, Identifier("modid", "modid_group"))

Then, add this to the end of the onInitialize method:

Registry.register(
  Registries.ITEM_GROUP,
  MODID_GROUP,
  FabricItemGroup.builder().icon { ItemStack(ICE_CUBE) }
    .displayName(
      Text.translatable("itemGroup.modid.modid_group")
    )
    .build(),
)

As always, remember to substitute modid for your mod ID. This code is registering an item group, and setting the ice cube we created earlier as its tab icon. However, this item group doesn’t have any items yet. To do that, we need to add items in the onInitialize method. At the end of the method, add this:

ItemGroupEvents.modifyEntriesEvent(MODID_GROUP).register(ModifyEntries { content ->
  content.add(ICE_CUBE)
})

This code is taking the group we just created and adding the ice cube item to it. Now, run the client. In your creative inventory, you should be able to see a tab with the ice cube icon (you might need to click arrows to show overflowed tabs in other pages).

That’s it for this post! In the next post, we’ll look at internationalization/strings and do some basic refactoring.

Series Navigation<< Minecraft Modding: Fabric + Kotlin – Introduction and SetupMinecraft Modding: Fabric + Kotlin – Strings and Refactoring >>

Leave a Reply

Your email address will not be published. Required fields are marked *