Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 29 — Custom Item Models and Textures

What You’ll Build

Back in Chapter 22 you wrote a sword that pointed at a custom look with the item_model component, and you packed data into a custom_model_data compound, but the artwork the pointer aimed at didn’t exist yet. This is the chapter where you build it.

By the end you’ll have a flame sword in your resource pack: an item that shows a plain blade most of the time, but swaps to a glowing, flaming blade the moment it carries an enchantment shimmer. You’ll make the picture (a small PNG texture), wrap it in a model, and write the item model definition: the little JSON file that decides, frame by frame, which model the game should draw. You’ll learn the five kinds of model definition and finish by making your sword change its own look based on its components, all without a single command running at play time.

Figure (to be captured). two tooltips side by side — a plain custom sword, and the same sword glowing/flaming once it has an enchantment glint

Concepts

Three folders, three jobs

In Chapter 28 you built a resource pack and learned its assets/<namespace>/ layout. Three of the folders inside it work together to draw a custom item, and keeping them straight is most of the battle:

  • assets/<namespace>/textures/ holds the flat images — .png files in PNG format, which provide the images used as textures for models such as items, blocks and mobs. Item images live in textures/item/.
  • assets/<namespace>/models/ holds the shapes — .json files defining the three-dimensional shapes used to render blocks and items. A model says what form the item takes and which texture it wears.
  • assets/<namespace>/items/ holds the item model definitions — .json files controlling the rendering of items. This is the new system this chapter is about: the file that chooses a model.

So the chain runs: a definition in items/ points at a shape in models/, and that shape wears an image from textures/. One picture, one shape, one chooser.

Modern Minecraft. If you follow an older tutorial, you may see it put everything in the models/ file and use a long overrides list to switch models by custom_model_data. Modern Minecraft splits that job out into the items/ folder you’re learning here. The overrides list is gone: the items/ definition with its model types (below) replaces it. If a video edits an item’s model directly with overrides, it’s describing the old way.

The pointer, from Chapter 22

An item knows which definition to use through the minecraft:item_model component you met in Chapter 22. It is the resource location of the item, which references the item model definition /assets/<namespace>/items/<id> without the .json suffix. So if your sword carries item_model="mypack:flame_sword", the game reads the file assets/mypack/items/flame_sword.json. There’s an important warning here: referencing nonexistent models will cause the missing model to be used, rather than falling back to the item ID’s default model. Spell the path wrong and you get the error model, not your diamond sword back.

The shape of an item model definition

Every file in items/ has the same outer shape. The root object holds:

  • a few optional animation switches (hand_animation_on_swap, oversized_in_gui, swap_animation_scale) we’ll leave at their defaults, and
  • a model field holding one items model object — the actual chooser.

That inner model object always has a type. The possible values for type are: minecraft:model, minecraft:composite, minecraft:condition, minecraft:select, minecraft:range_dispatch, minecraft:empty, minecraft:bundle/selected_item, and minecraft:special. This chapter teaches the first five; they’re the ones you’ll reach for. The last three (an item that draws nothing, the selected stack of a bundle, and “special” hard-coded renders like banners and heads) exist, but we leave them named and move on.

Here’s the simplest possible definition, type: minecraft:model, which renders a plain model from the models directory:

assets/mypack/items/flame_sword.json

{
  "model": {
    "type": "minecraft:model",
    "model": "mypack:item/flame_sword"
  }
}

Read it inside-out. The model field (inner) is the namespaced id of a shape in the models/ folder: it specifies the path to the model file of the item, in the form of a namespaced ID. So mypack:item/flame_sword means assets/mypack/models/item/flame_sword.json. The model object (outer) wraps that and gives it a type. Yes, “model” shows up twice: the outer one is the chooser, the inner one is the shape it chose.

The five model types, at a glance

In plain terms:

  • minecraft:model — draw one fixed model. (You just saw it.)
  • minecraft:composite — “render multiple sub-models in the same space.” Stack several models on top of each other.
  • minecraft:condition — pick between two models based on a yes/no test, like “is this item damaged?”
  • minecraft:select — pick a model from a list of named cases, like “which string is in the item’s data?”
  • minecraft:range_dispatch — pick a model based on a number, like “how damaged, on a scale from 0 to 1?”

The Chapter 22 payoff: custom_model_data ↔ model type

Here’s the connection the last few chapters have been building toward. In Chapter 22 you learned that minecraft:custom_model_data is a compound carrying four lists. It holds a list of values used by items model definitions for model selection and coloring. Each of its four lists feeds one of the model mechanisms you just met:

custom_model_data listfeeds this model typewhat it is
flags (booleans)conditionA list of booleans for the condition model type.
stringsselectA list of strings for the select model type.
floatsrange_dispatchA list of floats for the range_dispatch model type.
colorsmodel (its tints)A list of RGB values for the model model type’s tints.

So the data you stamped onto the item in Chapter 22 and the JSON you’re writing now are two halves of the same machine. The item carries the data; the definition reads it. We’ll wire up one of these linkages in the Practice.

Walkthrough

Step 1 — prove the pipeline with a vanilla model

Before making any art, let’s prove the plumbing works by pointing at a model that already exists. Give yourself a stick that renders as a diamond sword. First the definition:

assets/mypack/items/proof.json

{
  "model": {
    "type": "minecraft:model",
    "model": "minecraft:item/diamond_sword"
  }
}

The inner model is minecraft:item/diamond_sword, a model that ships with the game, so we don’t have to build it. Now hand yourself a stick that uses this definition. Put this in a function in your mypack data pack (commands live in .mcfunction files, no leading /):

data/mypack/function/give_proof.mcfunction

give @s stick[item_model="mypack:proof"]

Reload, run the function, and the stick in your hand looks like a diamond sword. The data pack hands out the item; the resource pack draws it. If you instead see a black-and-purple error cube, the game couldn’t find assets/mypack/items/proof.json, so check the filename and the namespace.

Step 2 — a brand-new texture

Now your own art. A standard item image is 16×16 pixels. You need an image editor that can save a PNG with transparency and edit one pixel at a time. Free options that work well:

  • GIMP or Krita (desktop, full-featured),
  • Aseprite (paid, made for pixel art),
  • any web-based pixel editor (search “online pixel art editor”).

Set the canvas to 16×16, turn the background transparent (so the area around your sword shows the world behind it, not a white box), zoom way in, and draw. Keep colors bold and outlines dark. At 16 pixels there’s no room for subtlety. Save it here:

assets/mypack/textures/item/flame_sword.png

Try It! Make two versions in the same style: flame_sword.png (a plain blade) and flame_sword_glow.png (the same blade with orange flames licking up it). You’ll use both in the Practice to make the sword change look.

Step 3 — a model to wear the texture

A texture is just a flat image; a model is the shape that wears it. The models/ folder holds the three-dimensional shapes used to render blocks and items, and an items model definition’s model field is the namespaced id of one of these files. For a flat item like a sword, the model is tiny: it borrows a standard “flat item” shape and points it at your PNG:

assets/mypack/models/item/flame_sword.json

{
  "parent": "minecraft:item/generated",
  "textures": {
    "layer0": "mypack:item/flame_sword"
  }
}

parent: minecraft:item/generated means “use the game’s standard flat-item shape.” layer0 is the image that shape wears: your assets/mypack/textures/item/flame_sword.png.

Under the Hood (skippable). The full grammar of a models/ file (building custom 3-D shapes out of cuboids, faces, and display transforms) is its own large subject, separate from the items/ definition system this chapter teaches. For flat items you’ll almost always reuse minecraft:item/generated exactly as above and just swap the layer0 texture, so you won’t need that grammar here. When you do want to model a custom 3-D shape from scratch, the wiki’s Model page is the place to go.

Step 4 — point the definition at your model

Now update flame_sword.json from the start of the chapter to use your model instead of a vanilla one:

assets/mypack/items/flame_sword.json

{
  "model": {
    "type": "minecraft:model",
    "model": "mypack:item/flame_sword"
  }
}

And give yourself the sword:

data/mypack/function/give_flame_sword.mcfunction

give @s iron_sword[item_model="mypack:flame_sword"]

You now have a fully custom item: a real iron sword (so it still swings and breaks blocks), wearing your own picture. This is the whole pipeline: image, shape, definition, pointer.

Overriding a vanilla item vs. a new visual

You have two ways to put a custom look in front of a player, and they’re worth telling apart:

  • A new visual, keyed by item_model. This is what you just did. The item keeps its real type (iron_sword) but carries item_model="mypack:flame_sword", so only this item looks custom. Every other iron sword in the world is untouched. This is the safe, normal choice.
  • Overriding a vanilla item. If you name your definition file after a vanilla item (say you create assets/minecraft/items/iron_sword.json in your pack), then the rule that an item’s model is based on the minecraft:item_model component still applies, but every iron sword defaults to that definition. That changes all iron swords for anyone using your pack. Use this only when you really mean “retexture the vanilla item everywhere.”

Tinting a model

A model type of minecraft:model can recolor parts of its texture without you drawing new art, using a tint source. The tints field is an optional list of tint sources to apply to the elements of the rendered model (the first entry applies to tintindex 0, the second to tintindex 1, and so on). Each entry is a tint source object with its own type. The tint source types are: minecraft:constant, minecraft:dye, minecraft:firework, minecraft:grass, minecraft:map_color, minecraft:potion, minecraft:team, and minecraft:custom_model_data.

The simplest is constant, which returns a constant RGB color:

assets/mypack/items/red_blade.json

{
  "model": {
    "type": "minecraft:model",
    "model": "mypack:item/flame_sword",
    "tints": [
      {
        "type": "minecraft:constant",
        "value": 16711680
      }
    ]
  }
}

value is a packed RGB number, the same decimal-color trick you saw with colors in Chapter 22 (16711680 is pure red). For this to do anything, the model’s texture needs a part marked with tintindex 0; untinted parts stay their original color. Elements with no tintindex specified remain untinted.

The most useful tint source for our purposes is minecraft:custom_model_data, which returns a value from the colors list in the minecraft:custom_model_data component. That’s the fourth row of our table: the colors list on the item feeds a model tint. Its shape:

assets/mypack/items/dyeable_blade.json

{
  "model": {
    "type": "minecraft:model",
    "model": "mypack:item/flame_sword",
    "tints": [
      {
        "type": "minecraft:custom_model_data",
        "index": 0,
        "default": 16777215
      }
    ]
  }
}

Both fields are simple: index is the index for the field in colors (default 0), and default is an RGB value used when the item has no color there (16777215 is white). Now one definition can render in any color you stamp into the item’s colors list: no extra art, no extra files.

Conditional models: changing look by component state

This is where item definitions earn their keep. Three of the five types choose a model based on the item’s own state at render time.

condition — a yes/no switch

The condition shape is: a type of minecraft:condition, a property (the yes/no test), and two models, on_true (the items model object used when the property is true) and on_false (used when the property is false). There are many boolean property values; the handy ones for items include:

  • minecraft:damaged — “true if the item is damageable and has been used at least once.”
  • minecraft:broken — “true if the item is damageable and has only one use remaining before breaking.”
  • minecraft:using_item — “true if player is currently using this item.”
  • minecraft:selected — “true if item is selected on a hotbar.”
  • minecraft:has_component — “true if the given component is present on the item” (needs an extra component field naming it).
  • minecraft:custom_model_data — returns the value from the flags list in the minecraft:custom_model_data component (this is the flags row of our table; it takes an optional index).

Here’s a sword that looks battered once it’s been used at all:

assets/mypack/items/worn_blade.json

{
  "model": {
    "type": "minecraft:condition",
    "property": "minecraft:damaged",
    "on_true": {
      "type": "minecraft:model",
      "model": "mypack:item/flame_sword_glow"
    },
    "on_false": {
      "type": "minecraft:model",
      "model": "mypack:item/flame_sword"
    }
  }
}

Notice on_true and on_false each hold a whole items model object, a type: minecraft:model with its own model field. Model definitions nest: a chooser’s branches are themselves choosers (or plain models).

select — pick by a named case

A select renders an items model based on a discrete property. Its shape: a type of minecraft:select, a property, a list of cases, and a fallback. Each case has a when (the value to match against the property; if it’s a list, it will match any value in it) and a model. Watch out: fallback is optional, but the game will render a “missing” error model if it’s not present, so always include one.

The property we care about is minecraft:custom_model_data, which returns the value from the strings list in the minecraft:custom_model_data component, the strings row of our table. So the string you put in the item’s data picks the model:

assets/mypack/items/team_blade.json

{
  "model": {
    "type": "minecraft:select",
    "property": "minecraft:custom_model_data",
    "index": 0,
    "cases": [
      {
        "when": "red",
        "model": {
          "type": "minecraft:model",
          "model": "mypack:item/flame_sword_glow"
        }
      },
      {
        "when": "blue",
        "model": {
          "type": "minecraft:model",
          "model": "mypack:item/flame_sword"
        }
      }
    ],
    "fallback": {
      "type": "minecraft:model",
      "model": "mypack:item/flame_sword"
    }
  }
}

An item carrying custom_model_data={strings:["red"]} draws the glowing blade; ["blue"] draws the plain one; anything else falls back to plain. (index here is the optional field for the custom_model_data property, naming which slot of the strings list to read, default 0.)

range_dispatch — pick by a number

A range_dispatch renders an items model based on a numeric property. It selects the last entry whose threshold is less than or equal to the property value. Its shape: a type of minecraft:range_dispatch, a property, a list of entries (each an object with a threshold float and a model), and an optional fallback. A great property here is minecraft:damage, which returns a value from the minecraft:damage component and, with the default normalize: true, divides it by the minecraft:max_damage component, clamped to 0.0 to 1.0. So 0.0 is a fresh tool and 1.0 is about to break:

assets/mypack/items/wear_stages.json

{
  "model": {
    "type": "minecraft:range_dispatch",
    "property": "minecraft:damage",
    "entries": [
      {
        "threshold": 0.0,
        "model": {
          "type": "minecraft:model",
          "model": "mypack:item/flame_sword"
        }
      },
      {
        "threshold": 0.5,
        "model": {
          "type": "minecraft:model",
          "model": "mypack:item/flame_sword_glow"
        }
      }
    ],
    "fallback": {
      "type": "minecraft:model",
      "model": "mypack:item/flame_sword"
    }
  }
}

When the sword is below half-damaged it shows the plain blade; cross 50% wear and it switches to the glow model. The matching custom_model_data source here would be floats (the custom_model_data numeric property returns the value from the floats list), which is the last row of our table.

Practice — the enchanted flame sword

Goal: a sword that looks plain normally and glows once it carries an enchantment shimmer. In Chapter 22 you learned the enchantment_glint_override component forces that shimmer on. We’ll have the model switch on the presence of that component, using condition with the has_component property (true if the given component is present on the item), with a component field naming which one.

First, the definition:

assets/mypack/items/flame_sword.json

{
  "model": {
    "type": "minecraft:condition",
    "property": "minecraft:has_component",
    "component": "minecraft:enchantment_glint_override",
    "on_true": {
      "type": "minecraft:model",
      "model": "mypack:item/flame_sword_glow"
    },
    "on_false": {
      "type": "minecraft:model",
      "model": "mypack:item/flame_sword"
    }
  }
}

Then two ways to hand out the sword, plain then glowing:

data/mypack/function/give_plain.mcfunction

give @s iron_sword[item_model="mypack:flame_sword"]

data/mypack/function/give_enchanted.mcfunction

give @s iron_sword[item_model="mypack:flame_sword",enchantment_glint_override=true]

The first sword shows flame_sword.png; the second carries the glint component, so has_component is true and the definition draws flame_sword_glow.png instead. The model changed itself, from data alone.

Figure (to be captured). the give_enchanted sword in hand — glint shimmer plus the flaming glow texture

Try It! Rebuild this using the Chapter 22 linkage instead of has_component. Set the condition’s property to minecraft:custom_model_data (which reads the item’s flags list), and give the sword with custom_model_data={flags:[true]}. Same visible result, but now you control the switch with your own data instead of relying on a vanilla component.

What Can Go Wrong

You get a black-and-purple error model. The game couldn’t find the definition the item_model component named. Minecraft is blunt about this: a nonexistent model will cause the missing model to be used, rather than falling back to the item ID’s default model. Check that assets/<namespace>/items/<id>.json exists, that the namespace in item_model matches the folder, and remember the pointer omits the .json suffix: item_model="mypack:flame_sword", not "mypack:flame_sword.json".

A select or range_dispatch shows the error model for some items. You forgot the fallback. It’s optional, but the game will render a “missing” error model if it’s not present, so any item whose value doesn’t match a case/entry has nothing to draw. Always include a fallback.

Your tint does nothing. A tint source only recolors model parts marked with the matching tintindex; elements with no tintindex specified remain untinted. A standard minecraft:item/generated flat item has no tint index unless the model adds one, so a plain custom texture won’t change color from a tint alone.

You changed every iron sword by accident. You put your definition in assets/minecraft/items/iron_sword.json instead of under your own namespace. That overrides the vanilla item for everyone. For a one-off custom look, give your definition its own id under your namespace and point item_model at it.