Skip to content

Item Models

Minetrio1256 edited this page Jun 17, 2026 · 2 revisions

Item Models API

The Item Models API provides a version-independent way to create modern Minecraft item model definitions and item model graphs.

The API is intentionally split into two layers:

  • Resource Layer (resource.items.*) — mirrors Mojang's JSON structure.
  • API Layer (api.items.*) — convenience builders and helpers.

This design allows advanced users to work directly with the underlying model graph while still providing easy-to-use presets for common item types.


Creating Standard Item Models

Most items use one of Minecraft's built-in parents.

Generated Item

Used for regular items such as gems, ingots, food, and materials.

ItemModelDefinition ruby =
        Models.generated()
                .texture(
                        "layer0",
                        "pantheon:item/ruby"
                )
                .build();

Equivalent to:

{
  "parent": "minecraft:item/generated",
  "textures": {
    "layer0": "pantheon:item/ruby"
  }
}

Handheld Item

Used for swords, tools, and weapons.

ItemModelDefinition sword =
        Models.handheld()
                .texture(
                        "layer0",
                        "pantheon:item/steel_sword"
                )
                .build();

Equivalent to:

{
  "parent": "minecraft:item/handheld",
  "textures": {
    "layer0": "pantheon:item/steel_sword"
  }
}

Handheld Rod

Used for fishing rods and rod-like items.

ItemModelDefinition rod =
        Models.handheldRod()
                .texture(
                        "layer0",
                        "pantheon:item/magic_rod"
                )
                .build();

Building Item Model Graphs

Minecraft 1.21+ item models are represented as a graph of nodes.

A graph always starts with a root node.

ItemModels model =
        Models.model()
                .root(
                        Nodes.model(
                                ResourceLocation.fromString(
                                        "pantheon:item/ruby"
                                )
                        )
                )
                .build();

Model Nodes

Simple Model

ModelNode node =
        Nodes.model(
                ResourceLocation.fromString(
                        "pantheon:item/ruby"
                )
        );

Empty Model

EmptyNode node =
        Nodes.empty();

Equivalent to:

{
  "type": "minecraft:empty"
}

Tints

Tints can be applied directly to model nodes.

ModelNode node =
        Nodes.model(
                ResourceLocation.fromString(
                        "pantheon:item/ruby"
                ),
                Tints.constant(0xFF0000)
        );

Multiple Tints

ModelNode node =
        Nodes.model(
                ResourceLocation.fromString(
                        "pantheon:item/armor"
                ),
                Tints.dye(0xFFFFFF),
                Tints.team(0xFFFFFF)
        );

Composite Models

Composite nodes render multiple models together.

CompositeNode composite =
        Nodes.composite(
                Nodes.model(
                        ResourceLocation.fromString(
                                "pantheon:item/base"
                        )
                ),
                Nodes.model(
                        ResourceLocation.fromString(
                                "pantheon:item/overlay"
                        )
                )
        );

Equivalent to:

{
  "type": "minecraft:composite",
  "models": [
    {},
    {}
  ]
}

Condition Nodes

Condition nodes select one of two models.

ConditionNode node =
        Nodes.condition(
                "minecraft:selected",
                Nodes.model(
                        ResourceLocation.fromString(
                                "pantheon:item/selected"
                        )
                ),
                Nodes.model(
                        ResourceLocation.fromString(
                                "pantheon:item/default"
                        )
                )
        );

Select Nodes

Select nodes allow switching between multiple values.

SelectNode node =
        Selects.select(
                "minecraft:charge_type",

                Nodes.empty(),

                Selects.when(
                        "rocket",
                        Nodes.model(
                                ResourceLocation.fromString(
                                        "pantheon:item/rocket_launcher"
                                )
                        )
                ),

                Selects.when(
                        "shell",
                        Nodes.model(
                                ResourceLocation.fromString(
                                        "pantheon:item/shotgun"
                                )
                        )
                )
        );

Range Dispatch Nodes

Range dispatch selects a model based on a numeric value.

RangeDispatchNode node =
        Ranges.range(
                "minecraft:damage",

                Ranges.entry(
                        0.25f,
                        Nodes.model(
                                ResourceLocation.fromString(
                                        "pantheon:item/damage_1"
                                )
                        )
                ),

                Ranges.entry(
                        0.75f,
                        Nodes.model(
                                ResourceLocation.fromString(
                                        "pantheon:item/damage_2"
                                )
                        )
                )
        );

Combining Nodes

Nodes can be nested indefinitely.

Example:

  • Select by charge type
  • Then check if selected
  • Then render multiple overlays
ItemModelNode root =
        Selects.select(
                "minecraft:charge_type",

                Nodes.empty(),

                Selects.when(
                        "rocket",

                        Nodes.condition(
                                "minecraft:selected",

                                Nodes.composite(
                                        Nodes.model(
                                                ResourceLocation.fromString(
                                                        "pantheon:item/rocket"
                                                )
                                        ),

                                        Nodes.model(
                                                ResourceLocation.fromString(
                                                        "pantheon:item/glow"
                                                )
                                        )
                                ),

                                Nodes.model(
                                        ResourceLocation.fromString(
                                                "pantheon:item/rocket"
                                        )
                                )
                        )
                )
        );

Registering Models

Models are registered into a ResourcePackItems container.

ResourcePackItems items =
        new ResourcePackItems();

items.register(
        ResourceLocation.fromString(
                "pantheon:ruby"
        ),

        Models.model()
                .root(
                        Nodes.model(
                                ResourceLocation.fromString(
                                        "pantheon:item/ruby"
                                )
                        )
                )
                .build()
);

Raw Access

The API layer is entirely optional.

Advanced users may construct nodes directly.

new SelectNode(
        property,
        cases,
        fallback
);
new CompositeNode(
        models
);
new RangeDispatchNode(
        property,
        entries
);

The API helpers exist only to reduce boilerplate and improve readability. The underlying resource model classes remain fully accessible.