Skip to content

Utilities

Matthiesen Lib provides several utility classes and abstractions to simplify common tasks in mod development. These utilities help reduce boilerplate code and provide cross-platform implementations.

The ItemBuilder class provides a fluent API for creating and modifying ItemStack instances with custom properties.

import dev.matthiesen.common.matthiesen_lib.utility.ItemBuilder;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
ItemStack customItem = new ItemBuilder(Items.DIAMOND_SWORD)
.setCustomName(Component.literal("Legendary Sword"))
.addLore(new Component[] {
Component.literal("A powerful weapon"),
Component.literal("Deals extra damage")
})
.build();

Create a new ItemStack from an Item:

ItemStack stack = new ItemBuilder(Items.GOLDEN_APPLE)
.setCustomName(Component.literal("Enchanted Apple"))
.build();

Modify an existing ItemStack:

ItemStack existingStack = new ItemStack(Items.BOOK);
ItemStack modified = new ItemBuilder(existingStack)
.setCustomName(Component.literal("Spell Book"))
.addLore(new Component[] {
Component.literal("Contains ancient spells")
})
.build();

Add lore (tooltip text) to the item:

new ItemBuilder(Items.DIAMOND)
.addLore(new Component[] {
Component.literal("A precious gem"),
Component.literal("Very rare!")
})
.build();

Features:

  • Appends to existing lore if any
  • Automatically disables italic formatting
  • Returns the builder for method chaining

Set custom NBT data on the item:

import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.component.CustomData;
CompoundTag tag = new CompoundTag();
tag.putString("owner", "PlayerName");
tag.putInt("power", 100);
new ItemBuilder(Items.STICK)
.setCustomData(CustomData.of(tag))
.build();

Features:

  • Merges with existing custom data
  • Sets max stack size to 1 automatically
  • Returns the builder for method chaining

Hide additional tooltip information:

new ItemBuilder(Items.DIAMOND_SWORD)
.hideAdditionalTooltip()
.build();

This hides enchantments, attributes, and other default tooltip information.

Set a custom display name for the item:

new ItemBuilder(Items.IRON_SWORD)
.setCustomName(Component.literal("Excalibur")
.withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD))
.build();

Set custom model data for resource pack support:

new ItemBuilder(Items.STICK)
.setCustomModelData(1) // References custom model #1
.build();

This is commonly used with resource packs to display different models for the same item.

Finalize and return the ItemStack:

ItemStack result = new ItemBuilder(Items.DIAMOND)
.setCustomName(Component.literal("Super Diamond"))
.build();

Important: After calling build(), do not use the ItemBuilder instance anymore.

import dev.matthiesen.common.matthiesen_lib.utility.ItemBuilder;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.CustomData;
public class CustomItems {
public static ItemStack createLegendarySword() {
CompoundTag tag = new CompoundTag();
tag.putString("tier", "legendary");
tag.putInt("damage_bonus", 50);
return new ItemBuilder(Items.DIAMOND_SWORD)
.setCustomName(Component.literal("Dragonslayer")
.withStyle(ChatFormatting.DARK_RED, ChatFormatting.BOLD))
.addLore(new Component[] {
Component.literal("Forged in dragon fire")
.withStyle(ChatFormatting.GRAY),
Component.literal("+50 Damage")
.withStyle(ChatFormatting.RED),
Component.literal("Legendary Tier")
.withStyle(ChatFormatting.GOLD)
})
.setCustomData(CustomData.of(tag))
.setCustomModelData(1)
.hideAdditionalTooltip()
.build();
}
public static ItemStack createEnchantedBook() {
return new ItemBuilder(Items.BOOK)
.setCustomName(Component.literal("Ancient Tome")
.withStyle(ChatFormatting.DARK_PURPLE))
.addLore(new Component[] {
Component.literal("Contains forbidden knowledge"),
Component.literal("Use with caution")
.withStyle(ChatFormatting.ITALIC, ChatFormatting.RED)
})
.build();
}
}

The AbstractSimpleScreen class provides a simple abstraction for creating custom container screens with minimal boilerplate.

AbstractSimpleScreen is useful for custom GUIs that:

  • Only need a background texture
  • Don’t need default labels (container title, “Inventory” text)
  • Want simplified rendering logic

Extend AbstractSimpleScreen and implement the required methods:

import dev.matthiesen.common.matthiesen_lib.screen.AbstractSimpleScreen;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
public class CustomScreen extends AbstractSimpleScreen<CustomMenu> {
private static final ResourceLocation TEXTURE =
ResourceLocation.fromNamespaceAndPath("mymod", "textures/gui/custom.png");
public CustomScreen(CustomMenu menu, Inventory inventory, Component title) {
super(menu, inventory, title);
}
@Override
protected int getBgWidth() {
return 176; // Standard chest width
}
@Override
protected int getBgHeight() {
return 166; // Standard chest height
}
@Override
protected ResourceLocation getBackgroundTexture() {
return TEXTURE;
}
}

Return the width of your background texture in pixels:

@Override
protected int getBgWidth() {
return 176; // Standard inventory width
}

Return the height of your background texture in pixels:

@Override
protected int getBgHeight() {
return 166; // Standard inventory height
}

Return the ResourceLocation pointing to your GUI texture:

@Override
protected ResourceLocation getBackgroundTexture() {
return ResourceLocation.fromNamespaceAndPath("mymod", "textures/gui/my_gui.png");
}
  • Automatic background rendering - No need to manually render the background
  • No default labels - Container title and “Inventory” labels are suppressed
  • Tooltip support - Built-in tooltip rendering

Override the render() method to add custom elements:

@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
super.render(guiGraphics, mouseX, mouseY, partialTick);
// Draw custom text
guiGraphics.drawString(
this.font,
"Custom Text",
this.leftPos + 8,
this.topPos + 8,
0x404040
);
// Draw custom icons/images
// guiGraphics.blit(...);
}
package com.example.mymod.client;
import com.mojang.blaze3d.systems.RenderSystem;
import dev.matthiesen.common.matthiesen_lib.screen.AbstractSimpleScreen;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
public class MachineScreen extends AbstractSimpleScreen<MachineMenu> {
private static final ResourceLocation TEXTURE =
ResourceLocation.fromNamespaceAndPath("mymod", "textures/gui/machine.png");
private static final ResourceLocation ICONS =
ResourceLocation.fromNamespaceAndPath("mymod", "textures/gui/icons.png");
public MachineScreen(MachineMenu menu, Inventory inventory, Component title) {
super(menu, inventory, title);
}
@Override
protected int getBgWidth() {
return 176;
}
@Override
protected int getBgHeight() {
return 166;
}
@Override
protected ResourceLocation getBackgroundTexture() {
return TEXTURE;
}
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
super.render(guiGraphics, mouseX, mouseY, partialTick);
// Render custom title
guiGraphics.drawString(
this.font,
"Machine Status",
this.leftPos + 8,
this.topPos + 6,
0x404040,
false
);
// Render progress bar
int progress = menu.getProgress();
if (progress > 0) {
int progressPixels = (progress * 24) / 100;
guiGraphics.blit(ICONS,
this.leftPos + 79,
this.topPos + 35,
0, 0, // Source X, Y in texture
progressPixels, 17, // Width, height to render
256, 256 // Total texture size
);
}
// Render tooltips
if (mouseX >= this.leftPos + 79 && mouseX <= this.leftPos + 103 &&
mouseY >= this.topPos + 35 && mouseY <= this.topPos + 52) {
guiGraphics.renderTooltip(
this.font,
Component.literal("Progress: " + progress + "%"),
mouseX,
mouseY
);
}
}
}

Check if a specific mod is loaded:

import dev.matthiesen.common.matthiesen_lib.MatthiesenLib;
if (MatthiesenLib.isModLoaded("jei")) {
// JEI is loaded, enable integration
}
if (MatthiesenLib.isModLoaded("create")) {
// Create mod is loaded
}

Determine if running in a development environment:

import dev.matthiesen.common.matthiesen_lib.MatthiesenLib;
if (MatthiesenLib.isDevelopmentEnvironment()) {
// Enable debug features
enableDebugLogging();
}

This is useful for:

  • Enabling extra logging in development
  • Showing debug information
  • Loading development-only features
  • Testing and debugging
  • Always call build() when finished
  • Don’t reuse an ItemBuilder after calling build()
  • Chain methods for cleaner code
  • Use meaningful component styling
  • Keep texture dimensions standard (176x166 for inventory-style GUIs)
  • Provide proper texture resources in your mod’s assets
  • Override render() for custom elements, not renderBg()
  • Use leftPos and topPos for positioning custom elements
  • Check for mod compatibility early (during initialization)
  • Use development checks to avoid debug code in production
  • Cache the results of platform checks if used frequently
Learn how to set up Matthiesen Lib in your development environment with the Installation Guide.
Explore the Registry Builder API to see how to register content from common code.
Check out the Commands page to learn how to create cross-platform commands.
Find out how to implement permissions with the Permissions system.
Discover how to register client-side features like screens and renderers in the Client-Side Features section.
Integrate with the Embers Text API for immersive messaging with the Embers Integration guide.