Skip to content

Creating an Animated Trim

Nihal "Ent" M edited this page Sep 21, 2026 · 5 revisions

Creating an Animated Trim

This walkthrough builds a complete animated trim material, Raw Copper, from scratch, using a data pack and a resource pack. Follow it top to bottom and you will have a working animated trim you can apply in a smithing table.

Everything here is in the example repository; clone it to see the finished files.

Prerequisite: Ent's Armor Trim Expanded must be installed (it is the engine that plays the animation).

This guide covers three Minecraft versions. A few files differ between them; each step below shows the variant for your version. When a step has no version note, it is the same on all three.

Label Minecraft
1.21.1 1.21.1 (before 1.21.5)
26.2 1.21.5 through 26.2
26.3 26.3 and later

What we are making

  • Material id: example:raw_copper. Replace example everywhere with your own namespace.
  • Applied with: a Raw Copper item (minecraft:raw_copper) in a smithing table, like any vanilla trim.
  • Look: 4 frames that slowly cross-fade, a base plus raw_copper_1, raw_copper_2, raw_copper_3.

Folder layout

You will create two packs. They can be two separate folders, or one folder containing both data/ and assets/ (Minecraft accepts a combined pack).

raw_copper_datapack/
├── pack.mcmeta
└── data/
    ├── example/
    │   ├── trim_material/raw_copper.json
    │   └── entate/trim_providers/raw_copper.json     # 26.2 and 26.3 only
    └── minecraft/tags/item/trim_materials.json

raw_copper_resourcepack/
├── pack.mcmeta
└── assets/
    ├── example/
    │   ├── lang/en_us.json
    │   ├── trim_animations/raw_copper.json
    │   └── textures/<PALETTE_FOLDER>/               # see 2.2 (differs by version)
    │       ├── raw_copper.png
    │       ├── raw_copper_1.png
    │       ├── raw_copper_2.png
    │       └── raw_copper_3.png
    └── minecraft/atlases/<ATLAS>.json               # see 2.3 (differs by version)

The palette folder and the atlas files differ by version (steps 2.2 and 2.3). Everything else is the same.


Part 1: The data pack

The data pack registers the material and makes it usable in a smithing table.

1.1 pack.mcmeta

{
  "pack": {
    "description": "Raw Copper Trim (data)",
    "pack_format": <DATA_PACK_FORMAT>
  }
}

Set pack_format to the data pack number for your version:

Version Data pack_format
1.21.1 48
26.2 107
26.3 121

1.2 The trim material: data/example/trim_material/raw_copper.json

The fields changed across versions. Use the one that matches your target.

1.21.1 (before 1.21.5): the material carries its own ingredient and item_model_index, so no provider file is needed.

{
  "asset_name": "raw_copper",
  "description": {
    "translate": "trim_material.example.raw_copper",
    "color": "#B86A3C"
  },
  "ingredient": "minecraft:raw_copper",
  "item_model_index": 0.35
}

26.2 (1.21.5 through 26.2): ingredient moved out of the material, so this is just asset_name plus the description. You add a provider file in 1.4.

{
  "asset_name": "raw_copper",
  "description": {
    "translate": "trim_material.example.raw_copper",
    "color": "#B86A3C"
  }
}

26.3: asset_name was replaced by palette_id, which points directly at the base palette.

{
  "palette_id": "example:trim/raw_copper",
  "description": {
    "translate": "trim_material.example.raw_copper",
    "color": "#B86A3C"
  }
}
  • asset_name (1.21.1 and 26.2) is the name the game uses to find your trim sprites; keep it the same as the file name (raw_copper). palette_id (26.3) does the same job but is a full id: example:trim/raw_copper reads assets/example/textures/palettes/trim/raw_copper.png. This is the single most important value to get right; it links the data pack to the resource pack.
  • description is the tooltip name. translate points at a lang key (added in Part 2.5). Prefer this over hard-coded text so it can be localised. color is the tooltip colour.

Do not want a lang file? Use plain text instead: "description": { "text": "Raw Copper Material", "color": "#B86A3C" }.

1.3 The ingredient tag: data/minecraft/tags/item/trim_materials.json

This tag tells the smithing table which items are trim materials. Adding minecraft:raw_copper makes a Raw Copper item work as the "addition" in a trim recipe. Same on all versions.

{
  "replace": false,
  "values": [
    "minecraft:raw_copper"
  ]
}

"replace": false is essential; it adds to the vanilla tag instead of wiping it. Never set it to true here.

1.4 The provider: data/example/entate/trim_providers/raw_copper.json

26.2 and 26.3 only. On 1.21.1 skip this step; the ingredient field in the material (1.2) already tells the game what to apply.

The tag above only makes the item accepted in the slot. From 1.21.5 on it does not tell the smithing table which trim material to apply. Vanilla reads that from the item's built-in minecraft:provides_trim_material component, which only vanilla materials (iron, copper ingot, diamond, and so on) have and a data pack cannot add on its own.

This file is how Ent's Armor Trim Expanded bridges that gap: it maps your ingredient item to your material.

{
  "item": "minecraft:raw_copper",
  "material": "example:raw_copper"
}
  • item is the ingredient placed in the smithing table (must also be in the tag from 1.3).
  • material is your trim material id (<namespace>:<name>, matching the trim_material file from 1.2).

Without this file (on 26.2 and 26.3) the material works via /give but not in a smithing table; the recipe produces no result. This is the most common reason a new trim "will not apply". The file name can be anything; only the item and material values inside matter.

That is the whole data pack. The material now exists, is accepted in the smithing table, and knows what to apply, but it will look like a blank trim until the resource pack gives it colours.


Part 2: The resource pack

The resource pack provides the colours (palettes) and defines the animation. On 1.21.1 and 26.2 it also builds the trim sprites with an atlas; on 26.3 worn armor needs no atlas.

2.1 pack.mcmeta

{
  "pack": {
    "description": "Raw Copper Trim (resources)",
    "pack_format": <RESOURCE_PACK_FORMAT>
  }
}

The resource pack number is different from the data pack one:

Version Resource pack_format
1.21.1 34
26.2 88
26.3 97

2.2 The palettes (colours)

Each frame is one tiny 8x1 pixel PNG: a horizontal strip of 8 colours, brightest on the left to darkest on the right. This is the palette that gets mapped onto the trim. See Making Palettes for how to build them.

Version Put the PNGs in
1.21.1 assets/example/textures/trims/color_palettes/
26.2 assets/example/textures/trims/color_palettes/
26.3 assets/example/textures/palettes/trim/
File Role
raw_copper.png frame 0, the base look (also the static fallback)
raw_copper_1.png frame 1
raw_copper_2.png frame 2
raw_copper_3.png frame 3

Naming is up to you for frames 1 and up. The only rule: frame 0 must be named exactly the material's base name (raw_copper, that is the asset_name, or on 26.3 the last segment of palette_id). The names you pick must match the atlas (2.3, on 1.21.1 and 26.2) and the animation (2.4).

2.3 The atlas

This turns your palettes into trim sprites. It differs the most across versions.

1.21.1: two atlases. assets/minecraft/atlases/armor_trims.json builds the worn-armor sprites, and assets/minecraft/atlases/blocks.json builds the inventory-icon sprites.

armor_trims.json (worn armor):

{
  "sources": [
    {
      "type": "minecraft:paletted_permutations",
      "palette_key": "minecraft:trims/color_palettes/trim_palette",
      "permutations": {
        "raw_copper":   "example:trims/color_palettes/raw_copper",
        "raw_copper_1": "example:trims/color_palettes/raw_copper_1",
        "raw_copper_2": "example:trims/color_palettes/raw_copper_2",
        "raw_copper_3": "example:trims/color_palettes/raw_copper_3"
      },
      "textures": [
        "minecraft:trims/models/armor/coast",
        "minecraft:trims/models/armor/coast_leggings"
      ]
    }
  ]
}

The textures list must include every vanilla pattern as trims/models/armor/<pattern> and <pattern>_leggings (the two coast lines above are just a sample). blocks.json uses the same palette_key, one permutation "raw_copper": "example:trims/color_palettes/raw_copper", and the four trims/items/*_trim textures.

26.2: also two atlases, but the worn armor_trims.json uses the new pattern paths trims/entity/humanoid/<pattern> and trims/entity/humanoid_leggings/<pattern>, and inventory icons move to assets/minecraft/atlases/items.json.

armor_trims.json (worn armor, 26.2):

{
  "sources": [
    {
      "type": "minecraft:paletted_permutations",
      "palette_key": "minecraft:trims/color_palettes/trim_palette",
      "permutations": {
        "raw_copper":   "example:trims/color_palettes/raw_copper",
        "raw_copper_1": "example:trims/color_palettes/raw_copper_1",
        "raw_copper_2": "example:trims/color_palettes/raw_copper_2",
        "raw_copper_3": "example:trims/color_palettes/raw_copper_3"
      },
      "textures": [
        "minecraft:trims/entity/humanoid/coast",
        "minecraft:trims/entity/humanoid_leggings/coast"
      ]
    }
  ]
}

items.json (26.2, inventory icons): same palette_key, one permutation "raw_copper": "example:trims/color_palettes/raw_copper", textures minecraft:trims/items/{helmet,chestplate,leggings,boots}_trim.

Full worn-armor textures list (all 18 patterns x 2 slots)

1.21.1 uses trims/models/armor/:

"textures": [
  "minecraft:trims/models/armor/sentry",    "minecraft:trims/models/armor/sentry_leggings",
  "minecraft:trims/models/armor/dune",      "minecraft:trims/models/armor/dune_leggings",
  "minecraft:trims/models/armor/coast",     "minecraft:trims/models/armor/coast_leggings",
  "minecraft:trims/models/armor/wild",      "minecraft:trims/models/armor/wild_leggings",
  "minecraft:trims/models/armor/ward",      "minecraft:trims/models/armor/ward_leggings",
  "minecraft:trims/models/armor/eye",       "minecraft:trims/models/armor/eye_leggings",
  "minecraft:trims/models/armor/vex",       "minecraft:trims/models/armor/vex_leggings",
  "minecraft:trims/models/armor/tide",      "minecraft:trims/models/armor/tide_leggings",
  "minecraft:trims/models/armor/snout",     "minecraft:trims/models/armor/snout_leggings",
  "minecraft:trims/models/armor/rib",       "minecraft:trims/models/armor/rib_leggings",
  "minecraft:trims/models/armor/spire",     "minecraft:trims/models/armor/spire_leggings",
  "minecraft:trims/models/armor/wayfinder", "minecraft:trims/models/armor/wayfinder_leggings",
  "minecraft:trims/models/armor/shaper",    "minecraft:trims/models/armor/shaper_leggings",
  "minecraft:trims/models/armor/silence",   "minecraft:trims/models/armor/silence_leggings",
  "minecraft:trims/models/armor/raiser",    "minecraft:trims/models/armor/raiser_leggings",
  "minecraft:trims/models/armor/host",      "minecraft:trims/models/armor/host_leggings",
  "minecraft:trims/models/armor/flow",      "minecraft:trims/models/armor/flow_leggings",
  "minecraft:trims/models/armor/bolt",      "minecraft:trims/models/armor/bolt_leggings"
]

26.2 uses trims/entity/humanoid/ and trims/entity/humanoid_leggings/:

"textures": [
  "minecraft:trims/entity/humanoid/sentry",    "minecraft:trims/entity/humanoid_leggings/sentry",
  "minecraft:trims/entity/humanoid/dune",      "minecraft:trims/entity/humanoid_leggings/dune",
  "minecraft:trims/entity/humanoid/coast",     "minecraft:trims/entity/humanoid_leggings/coast",
  "minecraft:trims/entity/humanoid/wild",      "minecraft:trims/entity/humanoid_leggings/wild",
  "minecraft:trims/entity/humanoid/ward",      "minecraft:trims/entity/humanoid_leggings/ward",
  "minecraft:trims/entity/humanoid/eye",       "minecraft:trims/entity/humanoid_leggings/eye",
  "minecraft:trims/entity/humanoid/vex",       "minecraft:trims/entity/humanoid_leggings/vex",
  "minecraft:trims/entity/humanoid/tide",      "minecraft:trims/entity/humanoid_leggings/tide",
  "minecraft:trims/entity/humanoid/snout",     "minecraft:trims/entity/humanoid_leggings/snout",
  "minecraft:trims/entity/humanoid/rib",       "minecraft:trims/entity/humanoid_leggings/rib",
  "minecraft:trims/entity/humanoid/spire",     "minecraft:trims/entity/humanoid_leggings/spire",
  "minecraft:trims/entity/humanoid/wayfinder", "minecraft:trims/entity/humanoid_leggings/wayfinder",
  "minecraft:trims/entity/humanoid/shaper",    "minecraft:trims/entity/humanoid_leggings/shaper",
  "minecraft:trims/entity/humanoid/silence",   "minecraft:trims/entity/humanoid_leggings/silence",
  "minecraft:trims/entity/humanoid/raiser",    "minecraft:trims/entity/humanoid_leggings/raiser",
  "minecraft:trims/entity/humanoid/host",      "minecraft:trims/entity/humanoid_leggings/host",
  "minecraft:trims/entity/humanoid/flow",      "minecraft:trims/entity/humanoid_leggings/flow",
  "minecraft:trims/entity/humanoid/bolt",      "minecraft:trims/entity/humanoid_leggings/bolt"
]

26.3: no worn-armor atlas. The game builds the trim texture on the fly from the palette (via palette_id), so you delete armor_trims.json entirely. The only atlas left is the optional inventory-icon one, and its format changed: palette_key is now minecraft:trim_base and permutation values are <ns>:trim/<name>.

assets/minecraft/atlases/items.json (26.3, inventory icons, optional):

{
  "sources": [
    {
      "type": "minecraft:paletted_permutations",
      "palette_key": "minecraft:trim_base",
      "permutations": {
        "raw_copper": "example:trim/raw_copper"
      },
      "textures": [
        "minecraft:trims/items/helmet_trim",
        "minecraft:trims/items/chestplate_trim",
        "minecraft:trims/items/leggings_trim",
        "minecraft:trims/items/boots_trim"
      ]
    }
  ]
}

On 26.3 the inventory icon also needs item-model overrides (see Part 3). If you only care about worn armor, you can skip the atlas entirely on 26.3.

2.4 The animation: assets/example/trim_animations/raw_copper.json

This is the file this mod reads. It is the same on all versions. It says which frames play, how fast, and whether to smooth between them.

{
  "frametime": 4,
  "interpolate": true,
  "frames": [
    "raw_copper",
    "raw_copper_1",
    "raw_copper_2",
    "raw_copper_3"
  ]
}
  • frames are the palette names in play order. Frame 0 (raw_copper) must be the material's base name (asset_name, or on 26.3 the last segment of palette_id).
  • frametime is game ticks per frame (20 ticks = 1 second). 4 is 5 frames per second.
  • interpolate set to true smoothly cross-fades between frames; false swaps instantly.

The file name (raw_copper.json) must match your material's path: example:raw_copper becomes assets/example/trim_animations/raw_copper.json. Full details and tricks are on the Animation Format page.

2.5 The name: assets/example/lang/en_us.json

Same on all versions.

{
  "trim_material.example.raw_copper": "Raw Copper Material"
}

This matches the translate key from the material JSON (1.2).


Try it

  1. Put the data pack in your world's datapacks/ folder (or /datapack enable), and the resource pack in resourcepacks/ (enable it in Options, Resource Packs).

  2. Reload: /reload for the data pack, and F3+T for the resource pack.

  3. Give yourself a trimmed piece to test quickly:

    /give @s minecraft:iron_chestplate[minecraft:trim={pattern:"minecraft:coast",material:"example:raw_copper"}]
    

    Or do it survival-style: smithing template + armor + a Raw Copper item in a smithing table.

The trim should animate through your copper frames on the worn armor.


Part 3: Inventory icon overlay (advanced)

The 2D item icon in your inventory is a separate system from worn armor, and it is optional.

  • 1.21.1 and 26.2 build the icon sprites from the atlas in 2.3 (blocks.json on 1.21.1, items.json on 26.2). Nothing more is needed for those versions if you listed the trims/items/* textures there.
  • 26.3 also needs, per armor item: an overlay model assets/<ns>/models/item/<armor>_raw_copper_trim.json (base item plus minecraft:trims/items/<piece>_trim_raw_copper) and a select-model override assets/minecraft/items/<armor>.json that adds a "when": "example:raw_copper" case. Because the item-definition files are full overrides, only one pack can own them, so this is best generated rather than hand-written.

The generator tool with --client-jar writes all of these for you, and the example resource pack ships them.


Recap checklist (worn armor)

  • data/<ns>/trim_material/raw_copper.json (1.21.1/26.2 asset_name, 26.3 palette_id)
  • data/<ns>/entate/trim_providers/raw_copper.json (26.2 and 26.3 only)
  • data/minecraft/tags/item/trim_materials.json adding your ingredient ("replace": false)
  • Palette PNGs raw_copper.png, raw_copper_1..3.png (8x1 each) in the version's palette folder
  • Atlas: armor_trims.json (1.21.1/26.2) or none for worn armor (26.3)
  • assets/<ns>/trim_animations/raw_copper.json with matching frame names
  • assets/<ns>/lang/en_us.json for the tooltip name
  • Both pack.mcmeta files with the right formats for your version

Stuck? See Troubleshooting.


Version quick reference

Thing 1.21.1 26.2 26.3
Data pack_format 48 107 121
Resource pack_format 34 88 97
Material field asset_name + ingredient + item_model_index asset_name palette_id
Provider file no (inline ingredient) yes yes
Palette folder textures/trims/color_palettes/ textures/trims/color_palettes/ textures/palettes/trim/
Worn-armor atlas armor_trims.json (trims/models/armor/) armor_trims.json (trims/entity/humanoid/) none (built on the fly)
Icon atlas blocks.json items.json items.json + model overrides
Atlas palette_key trims/color_palettes/trim_palette trims/color_palettes/trim_palette trim_base