Model part definitions
The fields of a model part definition: which items it matches, how it displays, and the settings that tie its model to your animations.
-
Punchy! Studio
This page has not been translated into Polish yet, so it is shown in English. Read in English
On this page
A definition is one .json file that tells Punchy! which held items get their own 3D model in first person, which geometry and texture that model uses, and which clips move it. This page lists the fields of that file that choose the items, files, display, animation entries, model settings, physics and particles, how Punchy! picks one definition for an item, how the model sits in the hand, and what makes Punchy! throw a file away. It is for pack makers who have a model and want it in the hand, and for anyone whose definition does not show.
Before you start
- Install Punchy! 3.0 or newer from Modrinth or CurseForge. The fields on this page were checked against Punchy! 3.0 for Fabric on Minecraft 26.3.
- You need a resource pack to put the files in. Resource packs explains how to make one and turn it on.
- A definition points at a geometry file and a texture. This page gives you a tiny pair to test with. Geometry and textures shows how to make your own.
- For the Studio steps you need Punchy! Studio, from Modrinth or CurseForge.
What a definition is made of
A model part is a small set of files. Only the definition is found by its folder. Punchy! loads every other file by the exact id you write in the definition, so their folders are your choice. These are the names Studio uses, and the ones this page uses too.
assets/minecraft/punchy/model_parts_items/
definitions/lantern.json the definition (this page)
geo/lantern.geo.json the geometry: bones and cubes
textures/lantern.png the texture
animations/lantern.animation.json item clips that move the bones
| File | Required | What it holds |
|---|---|---|
| Definition | Yes | The items it covers, the files it uses, and every setting below. |
| Geometry | Yes | The bones and cubes of the model, in Bedrock geometry format. |
| Texture | Yes | A PNG for the whole model. Single bones can take their own. |
| Item clips | No | Animations for the model’s own bones, played by the animation entries of the definition. |
The folder is named model_parts_items, and the namespace folder above it can be any name. A definition can sit at any depth under definitions/.
Definitions are not rp_geo_map files. rp_geo_map is a separate resource pack item model path, and this page does not cover it.
Make your first definition
You will make a lantern with a swaying flame that smokes, goes still under water, and swings when you attack. First the four files, then where they go.
Write the files
The geometry has two bones: lantern and its child flame. Every cube lists all six faces, so every face is drawn. This geometry file is saved as geo/lantern.geo.json.
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": { "identifier": "geometry.lantern", "texture_width": 16, "texture_height": 16 },
"bones": [
{
"name": "lantern",
"pivot": [0, 0, 0],
"cubes": [
{
"origin": [-3, 0, -3],
"size": [6, 6, 6],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"west": { "uv": [0, 0], "uv_size": [16, 16] },
"up": { "uv": [0, 0], "uv_size": [16, 16] },
"down": { "uv": [0, 0], "uv_size": [16, 16] }
}
}
]
},
{
"name": "flame",
"parent": "lantern",
"pivot": [0, 6, 0],
"cubes": [
{
"origin": [-1, 6, -1],
"size": [2, 3, 2],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"west": { "uv": [0, 0], "uv_size": [16, 16] },
"up": { "uv": [0, 0], "uv_size": [16, 16] },
"down": { "uv": [0, 0], "uv_size": [16, 16] }
}
}
]
}
]
}
]
}
The item clips are three small animations. They are saved as animations/lantern.animation.json.
{
"format_version": "1.8.0",
"animations": {
"lantern_sway": {
"loop": true,
"animation_length": 2,
"bones": {
"lantern": {
"rotation": { "0": [0, 0, -3], "1": [0, 0, 3], "2": [0, 0, -3] }
}
}
},
"lantern_still": {
"loop": true,
"animation_length": 1,
"bones": {
"lantern": { "rotation": [0, 0, 0] }
}
},
"lantern_swing": {
"animation_length": 0.6,
"bones": {
"lantern": {
"rotation": { "0": [0, 0, 0], "0.3": [-40, 0, 0], "0.6": [0, 0, 0] }
}
}
}
}
}
The texture is a 16 by 16 PNG saved as textures/lantern.png. In any image editor, make a new 16 by 16 pixel image, fill every pixel with one orange such as #E8861C, and export it as a PNG. Every face of both cubes shows the whole image, so a flat square is enough to see the model, and any other 16 by 16 picture works too.
The definition ties them together. It is saved as definitions/lantern.json.
{
"items": ["minecraft:lantern", "minecraft:soul_lantern"],
"geo": "minecraft:punchy/model_parts_items/geo/lantern.geo.json",
"texture": "minecraft:punchy/model_parts_items/textures/lantern",
"animations": [
"minecraft:punchy/model_parts_items/animations/lantern.animation.json"
],
"modelPartsAnimation": [
{ "type": "idle", "name": "lantern_sway" },
{
"type": "idle",
"name": "lantern_still",
"inside_water": true,
"disable_all_particles": true,
"skip_blend_in": true,
"skip_blend_out": true
},
{ "type": "attack", "name": "lantern_swing" }
],
"bone_emission": { "strength": 100, "blur": true, "flame": 100 },
"particles": [
{ "type": "minecraft:smoke", "bone": "flame", "rate": 3 }
]
}
What each part does:
itemscovers the lantern and the soul lantern.geo,textureandanimationsname the three other files by their full ids.- The first
idleentry playslantern_swayall the time. The secondidleentry is more specific: when your eyes are under water it playslantern_stillinstead, cuts to it without blending, and silences the particles. - The
attackentry playslantern_swingwhen you attack with the lantern. bone_emissionmakes theflamebone glow at full level, with a blur glow around it.particleslets smoke rise from theflamebone, three times a second.
Put them in a pack
-
In your game’s
resourcepacksfolder, make a folder calledLantern pack. Inside it, makepack.mcmetawith the text below. The numbers are for Minecraft 26.3; Resource packs has the other versions.{ "pack": { "description": "A lantern with a swaying flame", "pack_format": 97, "min_format": 97, "max_format": 97 } } -
Beside
pack.mcmeta, create the foldersassets/minecraft/punchy/model_parts_items/definitions,geo,texturesandanimations, so that the four folders sit side by side undermodel_parts_items. -
Save the geometry, the item clips, the texture and the definition in their folders, with the names above.
-
Turn the pack on under Options…, then Resource Packs…. Move it to Selected, and press Done.
-
Join a creative world and run
/give @s lantern. Hold it and switch to first person. -
If you edited the files while the world was open, press F3+T to reload the resources. Punchy! reads the definition again, so you do not restart the game.
You should see a small block with a glowing top, swaying in your hand. If you do not, go to Things that drop a whole definition.
Or build it in Punchy! Studio
Studio writes the geometry, the clips and the definition for you, and shows the model in your hand while you edit it.
- Join a world, hold a lantern, switch to first person and press F6. If the editor opens in the Third Person perspective, pick First Person with the switch between the menus and the workspace tabs.
- Open the Model workspace.
- Choose File > New Model Part (Ctrl+N). Type
Lanternin Name andminecraft:lanternin Held Item, then press Create. You start with one bone and one textured cube. - Open the Definition tab. In the Items panel, the Items field holds the item ids and
#tagsof the definition, separated by commas. Addminecraft:soul_lantern. - Choose View > Live Link with Punchy (Ctrl+L). Punchy! now draws your unsaved model in your hand.
- Open the Animation tab and use the Add menu to add an item clip with Add Clip and an animation entry with Add Entry. Set the entry’s Type and Clip. For the water entry, set Under Water to Yes, and tick No Particles, Skip Blend In and Skip Blend Out.
- Check the Lint panel on the Definition tab. Nothing to report. means Punchy! will load the definition.
- Choose File > Export Model Part… (Ctrl+E), pick the Pack, and press Export. Export First in Order is on for a new model part, so the definition is written into
0_punchy_studioand sorts first. Untick it if you do not want that.
Video coming soon
Video coming soon
The smallest definition
Three keys are enough: the items, the geometry and the texture.
{
"item": "minecraft:lantern",
"geo": "minecraft:punchy/model_parts_items/geo/lantern.geo.json",
"texture": "minecraft:punchy/model_parts_items/textures/lantern"
}
Everything else on this page is optional. Without display, Punchy! uses the item’s usual first person transform for each hand.
Which definition covers an item
Punchy! reads every .json file under definitions/ in every active pack and every namespace, at any depth. For each held stack it picks one definition. The rules, in order:
- The definitions are sorted by their full id as text, ignoring case, namespace first. Folder and file names therefore decide who wins.
- A definition whose
itemslists the held item is a candidate. The first unnamed candidate in the sorted order wins. - A definition with a
customNameis a named definition. It wins over every unnamed one when the stack carries that name. - If a named definition covers the item and the held stack does not carry that name, no unnamed definition is used for it. The vanilla model draws.
a_pack:punchy/model_parts_items/definitions/lantern.json tried first
minecraft:punchy/model_parts_items/definitions/0_first/lantern.json
minecraft:punchy/model_parts_items/definitions/lantern.json
The order of your resource packs does not matter between different ids. If two packs have a definition at the same path in the same namespace, only the one from the higher pack loads. To make a definition win, give its id an early sort: put it in a folder such as definitions/0_first/. Studio’s Export First in Order option does this with a folder named 0_punchy_studio. Resource packs shows the same rule next to the other pack-order rules.
Video coming soon
Match a renamed item
Add customName to cover only stacks that carry a name, such as one renamed on an anvil.
{
"items": ["minecraft:lantern"],
"customName": "Sun Lantern",
"geo": "minecraft:punchy/model_parts_items/geo/sun_lantern.geo.json",
"texture": "minecraft:punchy/model_parts_items/textures/sun_lantern"
}
A lantern renamed sun lantern or SUN LANTERN matches. The text compared is the stack’s custom name, not its hover text or lore. A plain lantern gets no model part at all, because a named definition now covers lanterns. To keep the plain lantern model as well, you cannot add an unnamed definition for it. Name every variant you want instead.
Fields that choose the item
| Key | Type | What it does | Example |
|---|---|---|---|
items | string array | The items the definition covers. Either items or item is required. minecraft: and lantern mean the same item. #minecraft: covers every item in that item tag. Each entry is trimmed, and an entry that is not a valid id is skipped. When items is present, item is not read, and an empty list drops the definition. | ["minecraft: |
item | string | One item id. Read only when items is missing. Use items once you have more than one. | minecraft: |
customName | string | Makes this a named definition. The held stack must carry a custom name equal to this text, ignoring case and the spaces at both ends. A blank value is ignored, and name is not tried then. | Sun Lantern |
name | string | The same as customName. Read only when the customName key is missing. |
A stack matches by its item, or by a tag it belongs to. Nothing else about the stack counts, apart from the custom name.
Fields that name the files
| Key | Type | What it does | Example |
|---|---|---|---|
geoRequired | resource id | The geometry file. Punchy! uses it exactly as written, so write the whole id with the folder and the .geo.json ending. A bad id drops the definition. A file that does not exist does not: the definition stays, draws nothing, and the vanilla model shows. | minecraft: |
textureRequired | resource id | The main texture of the whole model. A path under punchy/ gets .png added when it is missing. Any other path gets textures/ put in front unless it already starts with textures/, and .png added, so minecraft: and minecraft: both mean minecraft:. | minecraft: |
animations | resource id array | Item clip files. Write each id in full, with the . ending. All files are loaded into one set of clips, and a later file replaces a clip with the same name. When animations is present, animation is not read. | ["minecraft: |
animation | resource id | One clip file. Read only when animations is missing. | |
model | object array | The animation entries: which clip plays at which moment. See Animation entries. |
Ids use lowercase letters, digits, _, -, . and /, with at most one : after the namespace. A capital letter makes the id invalid. Without a namespace, minecraft is used.
Display
display places the model in your hand. Without it, Punchy! uses the vanilla first person transform of the held item for each hand. With it, you write the transform yourself, one entry per hand.
{
"items": ["minecraft:lantern"],
"geo": "minecraft:punchy/model_parts_items/geo/lantern.geo.json",
"texture": "minecraft:punchy/model_parts_items/textures/lantern",
"display": {
"firstperson_righthand": {
"rotation": [0, 20, 0],
"translation": [0, -16, 32],
"scale": [1, 1, 1]
},
"firstperson_lefthand": {
"rotation": [0, 20, 0],
"translation": [0, -16, 32],
"scale": [1, 1, 1]
}
}
}
| Key | Type | What it does |
|---|---|---|
firstperson_ | object | The transform for the right hand. Used when the object has no thirdperson_. |
firstperson_ | object | The transform for the left hand. Used when the object has no thirdperson_. |
thirdperson_ | object | If it is there, Punchy! uses it for the right hand and ignores firstperson_. |
thirdperson_ | object | If it is there, Punchy! uses it for the left hand and ignores firstperson_. |
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
rotation | 3 numbers | [0, 0, 0] | Degrees around X, Y and Z. For the left hand, Y and Z are negated. | [0, 20, 0] |
translation | 3 numbers | [0, 0, 0] | Moves the model. 16 units move it one pixel of the model, which is 1/16 of a block, so one unit is 1/256 of a block. For the left hand, X is negated. | [0, -16, 32] |
scale | 3 numbers | [1, 1, 1] | Multiplies the model along each axis. | [1.2, 1.2, 1.2] |
Some things to know:
- Write both hands. A hand with no entry uses the vanilla transform, not the other hand’s.
- Use the same numbers for both hands. Punchy! mirrors the model for the left arm and flips the signs above, so the left hand looks like the right.
- An array with fewer than three numbers is read as the default. A value that is not an array drops the whole definition.
- Model parts draw only in your own first person hands. The inventory, the other players’ hands and third person still show the vanilla item, so
displayonly changes what you see in your hands.
Video coming soon
In Studio, the Display tab has a Right Arm and a Left Arm panel. When the definition has no display entry for an arm, that panel shows only Use Vanilla First Person, ticked. Untick it to add an entry, and the Rotation, Translation and Scale rows appear. Ticking it again removes the entry for that arm.
Animation entries
modelPartsAnimation is a list of entries. Each entry says: at this moment, in these conditions, play this clip from the item clip files. Item clips move the model’s bones. They play next to the first person clip that moves the arms.
{
"modelPartsAnimation": [
{ "type": "idle", "name": "lantern_sway" },
{ "type": "idle", "name": "lantern_rain", "weather_detection": { "raining": true } },
{ "type": "attack", "name": "lantern_swing", "items": ["minecraft:lantern"] },
{ "type": "hand_in", "name": "lantern_raise", "skip_blend_in": true }
]
}
If a moment has no entry, Punchy! plays the idle entry instead. With no idle entry either, the model stays in its rest pose.
Types
The type of an entry says which moment it is for. Case, underscores, hyphens and spaces are ignored, so useItem, use_item and Use-Item are the same.
| Type | Punchy! asks for it when | Loops |
|---|---|---|
idle | Nothing else is happening. It is also the fallback when a moment has no entry or no clip. | Yes |
attack | You attack. | No |
mining | You mine a block. | Yes |
useItem | You use the item: draw a bow, charge a crossbow, throw a trident, use a spear, or use another item such as a bucket or a goat horn. | While you hold the use key on an item that stays in use, such as a bow, crossbow, trident or spear. A bucket or a goat horn plays once per use. |
useDrink | You drink. | No |
useEat | You eat. | No |
fishingrod | You cast or reel in a fishing rod. throw names the clip of the cast and pull the clip of the reel. | No |
falling | You fall. | Yes |
hand_in | The item comes up into your hand (equip). | No |
hand_out | The item goes away (put away). | No |
inspect | You press the Inspect key. | No |
triggerable | You press a custom animation key. | No |
in_water | Nothing asks for it directly. An entry of this type is only a candidate when idle is asked for. To tie a clip to water, give an idle entry the in_water or inside_ key instead. | Yes |
When several of these start at the same time, the higher one wins: attack, triggerable, inspect, hand_out, hand_in, mining, the cast and reel of fishingrod, useItem, then useDrink and useEat, then any other type, then idle.
While you use an item, Punchy! lets the vanilla model draw it, unless the definition has an entry of a use or consume type, such as useItem, useDrink or useEat, or a using state model. If you want your model to stay while you eat or draw a bow, add an entry of the matching type.
Keys of an entry
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
typeRequired | string | The moment this entry is for. See the table above. An entry with no type never matches. | idle | |
name | string | The clip to play, as named in the item clip file. Punchy! also reads animation and var_1, and takes the first of animation, name, var_1 that is not blank. For the right hand it tries <name>_ first, for the left hand <name>_, then the bare name, then the name with the definition's namespace in front. If no clip is found, Punchy! plays the idle clip. When the left hand plays a clip whose name ends in _left, the pose is mirrored on X. | lantern_ | |
throw, pull | string | Only in a fishingrod entry: the clip that plays when you cast and the clip that plays when you reel in. Also read as throw_, cast, start_cast, pull_, reel and reel_in. Left out, the clip named by animation, name or var_1 plays for both. | "rod_cast" | |
items | string array | every item of the definition | Limits the entry to stacks that match this list of ids or #tags. Use it when one definition covers several items that need different clips. | ["minecraft: |
in_water | boolean | The player touching water must equal this. True when the player is in water, the eyes are in water, or any of 27 points around the body is water. false means not touching water. | true | |
inside_ | boolean | The eyes being under water must equal this. When true, the entry also stays matched for a tick or two after you leave the water. | true | |
block_ | object | A block near the player. See Conditions. | ||
weather_ | object | Rain, thunder or clear sky. See Conditions. | ||
time_ | object | A window of the day. See Conditions. | ||
biome_ | object | A biome or biome tag. See Conditions. | ||
keep_ | string | The name of a clip that loops after this entry's clip ends. The entry also stays matched for a few ticks when its conditions flicker (weather entries excepted). | lantern_ | |
skip_ | boolean | false | Cut into this clip with no blend. Without it, Punchy! blends over 0.4 seconds when a clip takes over from a clip that is still playing, and over 0.6 seconds when the idle clip starts after a clip has ended or replaces another idle clip. | true |
skip_ | boolean | false | On the entry that is playing: when another entry takes over or the clip stops, cut with no blend out. | true |
blend_ | boolean | false | Starts the blend into this clip from the pose the model shows at that moment. Also read as blend, rebase_ and rebase. | |
disable_ | boolean | false | While you hold a stack this entry's items filter matches, Punchy! does not play the swim pose on that hand. It works even when this entry is not the one playing. | |
disable_ | boolean | false | While this entry plays, no particle emitter of that hand emits. | |
disable_ | string array | Bones that ignore pendulum physics while this entry plays. When the key is there, even as an empty list, it replaces the definition's own disable_ list. Also read as disable_. | ["flame"] |
A list field given as text, such as "items": "minecraft:lantern" inside an entry, drops the whole definition.
Conditions
An entry can ask about the world around the player. All conditions on an entry must pass. These objects go in the entry, next to type.
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
block_ | string array | Block ids or #tags. One of them must be in the search area. With no target at all, the condition passes. | ["minecraft: | |
block_ | string | One block id or tag. Read only when blocks is empty or missing. | ||
block_ | integer | 0 | A cube around the search origin, in every direction. 0 checks one block. A negative value counts as 0. | |
block_ | integer | 0 | Moves the search origin from the player's block position. | |
weather_ | boolean | Must match rain: true when the world is raining or rain falls on the player. When true, rain keeps counting for about two seconds after it stops. | true | |
weather_ | boolean | Must match thunder. Thunder counts only while it rains. | ||
weather_ | boolean | true means not raining and not thundering. | ||
time_ | integer | -1 | Start of the window, on the day clock from 0 to 23999. -1 means no lower bound. | 13000 |
time_ | integer | -1 | End of the window. -1 means no upper bound. When min is above max, the window runs through midnight. | 23000 |
time_ | two integers | A shorter way to write min and max. When it has two values, it replaces both. | [13000, 23000] | |
biome_ | string array | Biome ids or #tags. One of them must be in the search area. With no target at all, the condition passes. | ["#minecraft: | |
biome_ | string | One biome id or tag. Read only when biomes is empty or missing. | ||
biome_ | integer | 0 | A cube around the search origin, as for blocks. | |
biome_ | integer | 0 | Moves the search origin, as for blocks. |
An id with no : gets the minecraft namespace. A leading # makes it a tag.
{
"type": "idle",
"name": "lantern_night_swamp",
"time_detection": { "range": [13000, 23000] },
"biome_detection": { "biomes": ["minecraft:swamp", "minecraft:mangrove_swamp"] }
}
Conditions goes through each check with more examples.
Which entry plays
When Punchy! asks for a moment, it goes through the list like this:
- It keeps the entries whose
typeis that moment, whoseitemsfilter matches the stack and whose conditions all pass. - Each kept entry gets a score:
inside_wateris worth 3,in_water2, and each ofblock_detection,weather_detection,time_detectionandbiome_detection1. The score adds up the conditions the entry writes. Only entries whose conditions pass are scored. - The entry with the highest score wins. Equal scores keep the order of the file, so the first one wins. Entries with no conditions have a score of 0 and are used only when no scored entry passes. Among those, the first in the file wins.
So an idle that asks for rain beats a plain idle while it rains, and an idle that asks for water beats both. You can list several idle entries side by side.
Model settings
These keys change how the model looks. Each one is optional. Names of bones must match the bones of the geometry exactly, capital letters included. Only bone_textures also accepts a name that differs in capitals. Every snippet below is a complete JSON object so you can check it on its own. To use one, copy the key and its value into your definition.
Glow
bone_emission makes bones glow. It is an object of bone names to levels, plus a few settings.
{
"bone_emission": { "strength": 100, "blur": true, "clamp": false, "flame": 100, "wick": 12 }
}
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
<bone> | number 0 to 100 | 0 | The glow level of that bone, from a JSON number. Values from 1 to 15 set how bright the glow overlay is. Values above 15 add bloom, and the bloom shows only when blur is on. 0 is no glow. The name must match exactly, and child bones do not inherit it. | 100 |
blur | boolean | false | Adds a second, larger glow pass around glowing bones, and filters the glow texture smoothly. | true |
clamp | boolean | false | Samples the glow texture clamped to its edge instead of repeating it. | |
strength | integer 0 to 100 | 100 | One multiplier for every bone's glow. Also read as intensity and brightness; they are the same setting. The key names blur, clamp, strength, intensity and brightness are reserved, so a bone with one of those names cannot glow. |
Bone textures
bone_textures gives single bones their own texture. Use the object form for a few bones, or the list form to give one texture to many.
{
"bone_textures": { "flame": "minecraft:punchy/model_parts_items/textures/flame_lit" }
}
{
"bone_textures": [
{ "texture": "minecraft:punchy/model_parts_items/textures/glass", "bones": ["window_left", "window_right"] }
]
}
The texture ids are written like texture. Punchy! finds a bone’s texture by its exact name, then by a match that ignores case, then up through the parent bones, and falls back to the main texture. In the list form, a later entry replaces an earlier one for the same bone.
Texture animation
An animated texture is one PNG with the frames stacked from top to bottom.
{
"texture_anim": { "frames": 4, "frametime": 3, "frame_height": 16 },
"bone_texture_anim": {
"flame": { "frames": 6, "frametime": 2, "frame_height": 16 }
}
}
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
frames | integer | 1 | How many frames are stacked in the PNG. It is at least 1. With 1, nothing animates. | 4 |
frametime | integer | 1 | Game ticks each frame lasts. It is at least 1. | 3 |
frame_ | integer | 0 | The height of one frame in pixels. 0 means the geometry's texture height. It is at least 1 when written. | 16 |
texture_anim animates every bone texture that has no animation of its own. bone_texture_anim is an object of bone names to the same three keys, and applies to that bone only. A bone entry does not inherit values from texture_anim: a value you leave out becomes 1, 1 and 0.
The PNG must be exactly frames times the frame height tall. When it is not, the texture stays still and Punchy! says nothing.
Dynamic textures
dynamic_bone_textures swaps one bone’s texture, or the whole geometry, by what the held item holds. It is an object or a list of specs. The alias dynamicBoneTextures is read only when dynamic_bone_textures is missing.
{
"dynamic_bone_textures": {
"type": "texture",
"bone": "contents",
"source": "axol_variants",
"fallback": "minecraft:punchy/model_parts_items/textures/axolotl_pink",
"map": { "blue": "minecraft:punchy/model_parts_items/textures/axolotl_blue" }
}
}
| Key | Type | Default | What it does |
|---|---|---|---|
type | string | texture | texture swaps the texture of one bone. geo swaps the whole geometry. Any other value counts as texture. |
bone | string | The bone to retexture. Required for texture, ignored for geo. | |
source | string | sulfur_ | What picks the map entry. sulfur_ uses the item id of the block a sulfur cube has absorbed. axol_ uses the variant of the bucketed axolotl. Case does not matter. Any other value matches nothing, so only the fallback applies. |
map | object | Maps what the source reports to a texture id, or a geometry id for geo. A texture id is written like texture. A geometry id is not read the way the top-level geo is: when it does not start with punchy/, geo/ is put in front unless it already starts with geo/, and .geo.json is added when it is missing. Writing the full id works only when it starts with punchy/ or geo/, so keep the geometry files you swap in under one of those two folders. | |
fallback | resource id | Used when the map has no entry for what the source reports. It is written the same way as the ids in map. |
Dynamic textures has the full walk-through.
Mirroring
bone_mirror flips the animation keys of a bone in every item clip of the definition. Each bone takes a boolean, or an object with position and rotation booleans.
{
"bone_mirror": { "flame": { "position": false, "rotation": true } }
}
Only false does something. It negates the X position of the keys, and the X and Y rotation. true does nothing. A plain false does both. A position or rotation that is an object drops the whole definition.
Camera transparent bones
{
"camera_transparent_bones": ["glass"]
}
The faces of these bones, and of the bones under them, that turn away from you are not drawn. It helps glass and flames that you look at from inside. It does not apply to a bone that has physics. The alias inside_visible_bones is read only when camera_transparent_bones is missing.
State models
A state model changes the definition for one situation, most often only its geometry. Every key you leave out of a state stays as the definition has it.
{
"state_models": {
"using": { "geo": "minecraft:punchy/model_parts_items/geo/lantern_raised.geo.json" },
"fishing_rod_cast": { "geo": "minecraft:punchy/model_parts_items/geo/rod_cast.geo.json" }
}
}
| State | Punchy! draws it when |
|---|---|
using | You use this item with this hand. |
fishing_ | You are fishing with this item in this hand. It wins over using. |
The state names are not case sensitive. The geo is used as written, like the main geo. A state can also hold other keys of a definition, such as texture. Particle lists in a state are added to the definition’s own, bone_emission, bone_textures, bone_texture_anim, bone_physics and display are merged key by key with the definition’s, and any other key replaces the definition’s. A using state model also keeps the model visible while you use the item. In Studio, the State Models panel on the Definition tab edits these, and the State switch in the stage header previews them.
Fishing rod line
Two keys help a fishing rod whose model draws its own line. They matter only for minecraft:fishing_rod. Punchy! reads them from the definition that draws the rod in your hand, chosen as in Which definition covers an item, so a named definition can carry its own.
{
"items": ["minecraft:fishing_rod"],
"geo": "mypack:punchy/model_parts_items/geo/fishing_rod.geo.json",
"texture": "mypack:punchy/model_parts_items/textures/fishing_rod",
"fishing_line_anchor": { "bone": "rod_tip", "position": [0, 9.5, 0.85] },
"hide_bones_while_cast": ["hanging_line"]
}
| Key | Type | What it does | Example |
|---|---|---|---|
fishing_ | object | Where the cast fishing line starts in first person. bone is a bone of the geometry. position is exactly three numbers, in pixels inside that bone, as Blockbench shows them. Any other position means no anchor, and the line keeps its normal start. | { "bone": "rod_ |
hide_ | string array | Bones hidden, together with every bone under them, while your hook is out and that hand holds the rod. Use it to hide a line that is drawn into the model. | ["hanging_ |
Neither key has a default: with no anchor the line starts where it normally does, and with no list nothing is hidden. Both keys work on every Minecraft version and loader. Studio has no fields for these keys and keeps them as you wrote them.
Axolotl feedback
{
"physicsFeedback": true
}
Turns on the axolotl style feedback pose. It does something only for geometry shaped like an axolotl: a head bone, a body or body_root bone, and a legs_front or leg1 bone. The aliases fallingFeedBack and fallingFeedback are read when the key before them is missing. Studio calls it Axolotl Feedback.
Physics keys
Pendulums, creature feedback and slime squash are set per bone in bone_physics. The alias bonePhysics is read only when bone_physics is missing. The value is an object of bone names to specs, or a list of such objects; the specs for one bone are merged. A spec can also be a list of specs, or just true, which turns on creature feedback and slime squash for that bone with no pendulum.
{
"bone_physics": {
"flame": { "pendulum_mode": "full", "limit_deg": 25, "gravity": 0.8 },
"contents": { "enableSlimePhysics": true, "slimeImpactPercent": 60 }
},
"disable_physics_bones": ["lantern"]
}
A spec needs a pendulum_mode, or enableCreaturePhysics, or enableSlimePhysics (or one of their aliases, listed below). Without one of them, Punchy! drops that spec.
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
pendulum_ | string or boolean | none | How the bone swings. full (also pendulum_, full_, or true) swings freely. forward (also pendulum_, forward_) swings along the view. Hyphens and spaces count as underscores. Also read as pendulum, pendulum and physics_. | full |
enable | boolean | false | Creature style feedback on this bone. Also read as creature and puffer. | |
enable | boolean | false | Slime squash on this bone. Also read as slime and slimeBlock. | |
limit_deg | number | How far the pendulum may swing, in degrees. Also read as limitDeg, pendulum_ and pendulum. Left out, Punchy! uses its own default. | ||
limit_ | number | The upper limit. Also limitDegUp, pendulum_, pendulum. | ||
limit_ | number | The lower limit. Also limit, pendulum_, pendulum. | ||
force | number | The pendulum force. Also pendulum_, pendulum. | ||
speed | number | The pendulum speed. Also pendulum_, pendulum. | ||
camera_ | number | How much turning the camera moves it. Also cameraSens, pendulum_, pendulum. | ||
gravity | number | The pendulum gravity. Also pendulum_, pendulum. | ||
motion_ | number | How much walking moves it. Also motionSens, pendulum_, pendulum. | ||
invert | boolean | Inverts the swing. Also pendulum_, pendulum. | ||
impact | number 0 to 100 | 100 | Scales the tilt on the side it leans while you fall or tilt the camera down, from 0 to 100. A bigger value counts as 100. Also impact_, impact, impact_, landing, landing_, landing, landing_. | |
fall | number 0 to 100 | 100 | Scales the tilt on the other side, which is the punch of a landing and the lean when you tilt the camera up. Also fall_, fall, fall_, upward, upward_, upward, upward_. | |
impact | number 0 to 100 | 100 | Scales the vertical and depth (Y and Z) shift during the lean of impact. Also impact_, landing, landing_, impact, impact_, landing, landing_. | |
fall | number 0 to 100 | 100 | Scales the same shift during the lean of fall. Also fall_, upward, upward_, fall, fall_, upward, upward_. | |
slime | number 0 to 100 | 100 | Scales the slime squash at take-off and landing. Also slime_, impact, impact_, slime, slime_. | |
slime | number 0 to 100 | 100 | Scales the slime stretch while falling. Also slime_, fall, fall_, slimeFall, slime_fall. |
When you merge several specs for one bone, a percentage of exactly 100 never replaces an earlier value, because 100 is the default.
disable_physics_bones takes bones out of the item’s pendulum physics, along with the bones under them. The alias disable_pendulum_bones is read only when disable_physics_bones is missing. An animation entry that sets its own disable_physics_bones replaces this list while it plays. A bone with physics takes the nearest parent’s spec, not a merge of all of them.
Item physics explains the tuning side of the same effects, and Studio’s Physics tab has presets and a test rig.
Particles
particles lists emitters that spawn from a bone. The keys particle, particle_effects, particle_emission and particleEmission are read too, and all five are added together. Each emitter is written in one of three forms.
{
"particles": [
"minecraft:smoke",
"type=minecraft:flame,bone=flame,rate=4",
{ "type": "minecraft:smoke", "bone": "flame", "rate": 3, "enabled": true }
]
}
- A bare particle id emits that particle with its defaults.
- Text with
=is a list ofkey=valuepairs separated by commas.particle(...)around the pairs is optional. - An object writes the same keys as JSON. Numbers, booleans and text work. A list of three numbers is read as
x:y:z.
Two object keys are about the emitter itself. enabled set to false turns the emitter off. triggers must be an object of flags such as jump, landing, walking, sprinting, swimming, attacking and mining. A list there is not read. Particles lists every key and trigger, and the settings that switch particles and their glow off for the whole game are below.
Settings that affect every definition
These are Punchy!‘s own settings, not keys of a definition.
| Setting | Where | Effect |
|---|---|---|
| Resource Pack Model Parts | Items & World | When it is off, no model part loads or draws. A change shows after you press F3+T. |
| Enable Particle System | Effects | When it is off, no model part emits particles. |
| Enable Model Parts Glow | Effects | When it is off, the particles of model parts lose their glow and full brightness. The particles still appear. The glow of bone_ does not depend on it. |
| Enable Boat/ | Items & World | Punchy! draws its own models for these held items, before it looks at model parts. Turn the matching option off to let a definition draw the item instead. |
Open the F8 menu to reach them. Settings and controls shows where they are.
Things that drop a whole definition
Punchy! checks a definition when it loads the resources. If anything below is wrong, it removes the whole file and writes no message. The items stay vanilla.
| What is wrong | Example |
|---|---|
| The file is not valid JSON, or its top level is not an object. | A missing comma. A list [ ... ] at the top. |
| No item. | No items and no item. items is an empty list. items holds only blank text. |
No geo, or the id is not valid. | geo missing. A capital letter in the id. |
No texture, or the id is not valid. | texture missing. |
| A value of the wrong JSON type. | items, animations or model that is not a list. display, or one of its hand entries, that is not an object. rotation, translation or scale that is not an array. Text that is not a whole number where a number belongs in texture_ or a bone_ entry. A field of an animation entry that holds a list or an object where one value belongs, or one value where a list or an object belongs, such as "items": "minecraft:. |
Fix the file and press F3+T. In Studio, the Lint panel on the Definition tab names the reason: Punchy drops this definition, followed by what it found.
Things that keep a definition but draw nothing
These leave the definition in place. It still covers its items, so it hides later definitions for the same items, and the vanilla model draws.
- The geometry file is missing or broken. Punchy! does not check that the file exists when it reads the definition. A geometry with no
minecraft:geometrylist, nobones, or a bone without anamedoes not load. - The item is drawn by another renderer. Held chests, boats, rafts, minecarts, pistons and the enchanting table use Punchy!‘s own models first. See the settings above.
- You are using the item. While you eat, drink or draw a bow, the vanilla model draws, unless the definition has a matching entry or a
usingstate model. - A named definition covers the item. A stack without that name gets no model part. See Match a renamed item.
- Another definition sorts earlier. Your definition is shadowed. See Which definition covers an item.
If Resource Pack Model Parts is off, no definition loads at all. Turn it on under Items & World in the F8 menu, then press F3+T.
The texture id is not checked when the definition loads. If the model shows wrong or not at all, open the pack and check that a file sits at the id you wrote.
A few smaller things are skipped without a message. An entry names a clip that is not in the file, so the idle clip plays. A physics spec has no mode, so it is dropped. An item clip file with a broken clip keeps the clips before it and loses the clips after it. A texture animation whose PNG is not frames times frame height tall stays still.
Related pages
- Model parts overview for the whole system.
- Geometry and textures to make the model and texture a definition names.
- Item clips to animate the bones of the model.
- Conditions to choose a clip by water, weather, blocks, time or biome.
- Particles for the emitters and their triggers.
- Dynamic textures to change a texture by what the item holds.
- Variants and presets to ship several versions of one model.
- Item physics for pendulum and feedback settings.
- Resource packs for pack order and where files go.
Last checked against the mod on 29 October 2026.