MultiLoader 26.1+ · Part 3

Creating Items (MultiLoader 26.1+)

BEGINNER MULTILOADER 26.1-26.1.2 18 min read · Jun 12, 2026
MultiLoader 26.1+ · 17 parts
1 Getting Started with MultiLoader 26.1+ 2 Setting Up RegistrationUtils (MultiLoader 26.1+) 3 Creating Items (MultiLoader 26.1+) 4 Creating Blocks (MultiLoader 26.1+) 5 Data Generation: Block & Item Models (MultiLoader 26.1+) 6 Data Generation: Block Loot Tables (MultiLoader 26.1+) 7 Data Generation: Crafting Recipes (MultiLoader 26.1+) 8 Data Generation: Block & Item Tags (MultiLoader 26.1+) 9 Data Generation: Language Files (MultiLoader 26.1+) 10 Data Generation: Advancements (MultiLoader 26.1+) 11 Data Generation: Sound Definitions (MultiLoader 26.1+) 12 Data Generation: Particle Descriptions (MultiLoader 26.1+) 13 Data Generation: Enchantments (MultiLoader 26.1+) 14 Custom Food Items (MultiLoader 26.1+) 15 Custom Tools (MultiLoader 26.1+) 16 Custom Armour (MultiLoader 26.1+) 17 Block Entities (MultiLoader 26.1+)

Creating new items is one of the key starting points for most mods. In this tutorial we will create a basic item with a model and texture, add it to a custom creative tab, and give it a display name, all from the shared common module.

NOTE
Make sure you have completed the Setting Up RegistrationUtils tutorial before continuing. We rely on RegistrationProvider throughout this guide.

Creating the Item Registry

Create a new class called ItemRegistry inside a registry package in your common project. The full class path will look something like com.example.examplemod.registry.ItemRegistry.

Inside the class, define an empty public static void init() method. We will call this later from CommonClass to ensure the class is loaded and all items registered at the right time. Then declare a RegistrationProvider for the item registry:

java
public class ItemRegistry {
public static final RegistrationProvider<Item> ITEMS =
RegistrationProvider.get(Registries.ITEM, Constants.MOD_ID);
public static Item.Properties getItemProperties(String name) {
return new Item.Properties().setId(
ResourceKey.create(Registries.ITEM,
Identifier.fromNamespaceAndPath(Constants.MOD_ID, name)));
}
public static void init() {}
}

In 26.1, every item must be given an explicit registry key via Item.Properties.setId(). Without it the game throws at startup when it tries to look up the item's key. The key is a ResourceKey<Item> built from your mod ID and the item's registry name, and it must match the name you pass to ITEMS.register(). Passing the name as a parameter to the helper keeps them in sync automatically.

NOTE
Identifier is the 26.1 rename of the class previously called ResourceLocation. The method signatures are identical, only the class name changed. Your IDE's auto-import will resolve it to net.minecraft.resources.Identifier.

Registering an Item

Add a public static final field for your first item. For this tutorial we will create a simple item called Iron Stick. Pass the registry name to getItemProperties so the ID is set automatically:

java
public static final RegistryObject<Item, Item> IRON_STICK = ITEMS.register("iron_stick",
() -> new Item(getItemProperties("iron_stick")));

Next, call ItemRegistry.init() from your CommonClass so the field is resolved when the mod initialises:

java
public class CommonClass {
public static void init() {
ItemRegistry.init();
}
}

Item Model and Texture

26.1 introduces a new items/ directory alongside the existing models/item/ directory. The game now reads an item definition from items/ first and uses it to decide which model to render. For a basic item this definition simply points at a model, but the layer exists so that more complex items can switch models based on conditions (damage level, NBT data, and so on) without needing a custom item subclass.

Create the item definition at src/main/resources/assets/examplemod/items/iron_stick.json:

json
{
"model": {
"type": "minecraft:model",
"model": "examplemod:item/iron_stick"
}
}

The type field selects the model resolver. minecraft:model is the simplest resolver: it unconditionally renders the model named by the model field. The value points to the model JSON you create next.

Now create the model itself at src/main/resources/assets/examplemod/models/item/iron_stick.json:

json
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "examplemod:item/iron_stick"
}
}

The item/generated parent is the standard flat 2D item model. The layer0 texture key points to your texture file. Both files are required: the item definition in items/ tells the game which model to use, and the model in models/item/ tells the game how to build the mesh and where to find the texture.

Finally, create a 16x16 PNG texture and save it at src/main/resources/assets/examplemod/textures/item/iron_stick.png. Replace examplemod throughout with your own mod ID if you changed it.

TIP
You can use any image editor that exports PNG at 16x16. Keeping it at 32-bit RGBA works reliably across all platforms.

Language File

Create (or open) the English language file at src/main/resources/assets/examplemod/lang/en_us.json and add a display name for your item:

json
{
"item.examplemod.iron_stick": "Iron Stick"
}

For any further entries you add to this file, remember to place a comma after each entry except the last. To support other languages, copy this file and rename it with the appropriate Minecraft language code.

Access Transformer & Class Tweaker

Two of the types used inside the creative tab builder are not public in the merged Minecraft jar, even though they appear public in the decompiled source. CreativeModeTab$Output is a protected interface (the type of the output lambda parameter) and CreativeModeTab$TabVisibility is a protected static enum. Without widening their visibility, the compiler rejects any reference to them from mod code.

NeoForge widens access through an access transformer file. Create common/src/main/resources/META-INF/accesstransformer.cfg:

text
public net.minecraft.world.item.CreativeModeTab$Output
public net.minecraft.world.item.CreativeModeTab$TabVisibility

Fabric uses a class tweaker file (new in 26.1, replacing the older access widener for this purpose). Create common/src/main/resources/examplemod.classtweaker:

text
accessWidener v2 official
accessible class net/minecraft/world/item/CreativeModeTab$Output
accessible class net/minecraft/world/item/CreativeModeTab$TabVisibility
NOTE
The file extension is .classtweaker but the format is still Access Widener v2 syntax. The namespace is official because 26.1 ships with official Mojang mappings rather than obfuscated names. See the Fabric class tweaker documentation for the full syntax reference.

Your Fabric subproject's fabric.mod.json must declare the class tweaker file so Loom picks it up at compile time:

json
"accessWidener": "examplemod.classtweaker"

The template project may already include this line pointing at an .accesswidener file. If so, rename the file to .classtweaker and update the fabric.mod.json entry to match. Once both files are in place, click Refresh Gradle before your next build so the widening takes effect.

Adding a Creative Tab

Rather than cluttering ItemRegistry, create a dedicated CreativeTabRegistry class in the same package:

java
public class CreativeTabRegistry {
public static final RegistrationProvider<CreativeModeTab> CREATIVE_MODE_TABS =
RegistrationProvider.get(Registries.CREATIVE_MODE_TAB, Constants.MOD_ID);
public static final RegistryObject<CreativeModeTab> TAB =
CREATIVE_MODE_TABS.register(Constants.MOD_ID + "_tab", () ->
CreativeModeTab.builder(CreativeModeTab.Row.TOP, 0)
.icon(() -> new ItemStack(ItemRegistry.IRON_STICK.get()))
.displayItems((params, output) -> {
output.accept(ItemRegistry.IRON_STICK.get());
})
.title(Component.translatable("itemGroup." + Constants.MOD_ID + ".tab"))
.build()
);
public static void init() {}
}
NOTE
The new ItemStack(...) call here is safely inside a lambda that runs after registries have loaded, so there is no issue with the 26.1 requirement that ItemStack construction must happen post-registry. Static field initialisers and class constructors are where you need to be careful; lambdas passed to builders are always fine.

Call CreativeTabRegistry.init() from CommonClass.init() alongside your item registry call. Then add the tab's translation key to your language file:

json
{
"item.examplemod.iron_stick": "Iron Stick",
"itemGroup.examplemod.tab": "Example Mod Items"
}

Testing In-Game

Run either the Fabric Client or NeoForge Client run configuration. Open creative mode, find your new tab, and check that your Iron Stick appears. You can also use the give command to test it directly:

shell
/give @s examplemod:iron_stick

You can find the source for this tutorial here:

View Source on GitHub
NEXT IN SERIES

Creating Blocks (MultiLoader 26.1+)

Create a BlockRegistry with registerBlock helpers that auto-register a BlockItem, define a custom block using vanilla property copying, set up block models, textures, blockstates, and a creative tab.

Continue →