Recreate a 3D bucket pack
Build a 3D bucket pack with a model and textures of your own: a model part for every bucket, item clips, an in-water condition, sloshing liquid, glowing lava and particles.
-
Blockbench
-
Punchy! Studio
This page has not been translated into Finnish yet, so it is shown in English. Read in English
On this page
This tutorial builds a whole 3D bucket pack from an empty folder. Every bucket gets its own model part: the empty bucket, the water, lava and milk buckets, and the fish buckets. The model and every texture are built here from numbers and flat colors.
It is inspired by the example pack provided by patovskiz, Refined Buckets, and uses the same techniques: contents that change with the item, clips that react to water, liquid that sloshes, lava that glows and particles that fit the moment. It is for pack makers who want to see a full set of model parts built in one go. Choose Blockbench or Punchy! Studio in the tool chooser, and every step shows your tool.
What you will build
One geometry, one clip file and nine definitions. Each definition is one bucket state.
| Bucket | Item | What shows | What it does |
|---|---|---|---|
| Empty | minecraft: | A steel pail with a handle | Air bubbles rise from the opening while you touch water |
| Water | minecraft: | Animated water | The surface sloshes when you turn or move, and splashes when you jump or land |
| Lava | minecraft: | Animated, glowing lava | A smaller, tighter slosh, embers in the air, and the embers stop in water |
| Milk | minecraft: | Milk | Sloshes, puffs when you jump or land, and tilts when you drink |
| Cod, salmon, tropical fish, pufferfish | minecraft: and the other three | A fish at the surface of the water | The fish swims, blows bubbles and reacts when you jump or land |
| Axolotl | minecraft: | The same fish in the color of the axolotl | The color follows the variant of the axolotl inside |
Video coming soon
Before you start
- Punchy! 3.0 or newer. The files and numbers on this page are written for Fabric on Minecraft 26.3.
- Blockbench 5 or Punchy! Studio. The tool chooser follows your choice on every page.
- A plain text editor for the definitions, if you use Blockbench. Studio writes them for you.
- Python 3 is optional. A short script makes every texture in one go.
- A rough idea of what a definition is. The model parts overview and Model part definitions explain it, and this page links to the deeper pages as it goes.
How the pack fits together
All nine buckets share one geometry. It holds the pail and everything that can sit in it: a block of liquid and a fish. Each definition then decides what shows with bone_textures. A bone drawn with a completely transparent texture is invisible, so the empty bucket hides the liquid and the fish, the water bucket shows the liquid, and a fish bucket shows both.
Three more choices keep the pack small:
- Flat colors. Every texture is one color over the whole picture, so it does not matter where a face’s UV points, as long as it stays inside the picture. You never place a UV by hand.
- One clip file. All the clips move bones by name, and a definition only uses the clips it names.
- One definition per state. The item decides which definition applies, so the pack needs no switching of its own. When an empty bucket scoops water, Minecraft hands you a water bucket and Punchy! draws that definition.
The geometry has eight bones. Pixels are model pixels, and 16 of them make one block. The model is centered on the middle, with its base on the floor.
| Bone | Parent | Pivot | Cube | Origin | Size |
|---|---|---|---|---|---|
body | none | 0, 5, 0 | north wall | -5, 1, -5 | 10, 9, 1 |
| south wall | -5, 1, 4 | 10, 9, 1 | |||
| west wall | -5, 1, -4 | 1, 9, 8 | |||
| east wall | 4, 1, -4 | 1, 9, 8 | |||
foot | body | 0, 0, 0 | base | -5, 0, -5 | 10, 1, 10 |
handle | body | 0, 9, 0 | left post | -6, 9, -0.5 | 1, 3, 1 |
| right post | 5, 9, -0.5 | 1, 3, 1 | |||
| bar | -6, 12, -0.5 | 12, 1, 1 | |||
liquid | body | 0, 1, 0 | liquid | -4, 1, -4 | 8, 6, 8 |
surface | body | 0, 7.5, 0 | surface | -3.5, 7, -3.5 | 7, 1, 7 |
fish | body | 0, 8, 0 | fish body | -1.5, 6.5, -3 | 3, 3, 6 |
eyes | fish | 0, 8.6, -2.1 | left eye | -1.7, 8.2, -2.5 | 0.4, 0.8, 0.8 |
| right eye | 1.3, 8.2, -2.5 | 0.4, 0.8, 0.8 | |||
tail | fish | 0, 8, 3 | tail | -0.5, 6.5, 3 | 1, 3, 1 |
Why these shapes:
- The four walls and the base make a hollow pail. The walls are 1 pixel thick, so you can look down into it.
liquidfills the pail up to 3 pixels below the rim.surfaceis a thin slab on top of it, so its top sits 2 pixels below the rim. Because it is its own bone, it can tilt on its own, and that is the slosh.- The
handlepivots at the middle of the pail, one pixel below the top of the walls, so it swings forward and back around the middle of the rim. - The fish floats at the surface, half in the liquid, so you see its back. Its eyes and tail are bones of their own, so the tail can wag.
The files end up in this layout. Studio writes its own copy of the geometry and textures for every state, named after the state, so its folders hold more files. They work the same way.
Bucket pack/
pack.mcmeta
assets/bucketpack/punchy/model_parts_items/
definitions/ bucket_empty.json, bucket_water.json, bucket_lava.json, bucket_milk.json,
bucket_cod.json, bucket_salmon.json, bucket_tropical_fish.json,
bucket_pufferfish.json, bucket_axolotl.json
geo/ bucket.geo.json
animations/ bucket.animation.json
textures/ steel.png, iron.png, clear.png, water.png, lava.png, milk.png, fish_*.png, axolotl_*.png
shading.json optional, next to the folders: lights the lava bucket in the dark
The namespace bucketpack is yours to choose. A namespace other than minecraft keeps your files apart from the game’s.
Set up the pack folder
Studio makes the pack folder and its pack.mcmeta the first time you export, so skip this section if you use Studio.
-
In your game folder, open
resourcepacksand make a folder calledBucket pack. -
Inside it, make
pack.mcmetawith the text below. The numbers are for Minecraft 26.3. Resource packs has the other versions.{ "pack": { "description": "A 3D bucket pack", "pack_format": 97, "min_format": 97, "max_format": 97 } } -
Make these four folders, next to each other:
assets/bucketpack/punchy/model_parts_items/definitions,geo,animationsandtextures.
Model the bucket
The model is the table above: eight bones and fourteen cubes. Build it once. Origins are the file’s corner with the smallest numbers, in pixels.
In Blockbench
Blockbench makes the geometry file. You write the definitions by hand later.
- Choose File > New > Bedrock Entity. Do not pick Bedrock Legacy Model: it writes the old layout that Punchy! cannot read.
- Choose File > Project…. Set Default UV Mode to Per-face UV and Texture Size to 16 and 16, then press Confirm.
- Use Add Group and name the group
body. Every group becomes a bone, and its name is how the definitions refer to it. Set its Pivot Point to 0, 5, 0. - With the group selected, use Add Cube. Set its Position and Size to the north wall row of the table. Add the other three walls the same way.
- Use Add Group for the next bone,
foot, and set its Pivot Point. Drag it ontobodyin the Outliner so it becomes a child. Select it and use Add Cube for its cube. - Do the same for
handle(three cubes),liquid,surfaceandfish, each a child ofbody. Then addeyes(two cubes) andtailand drag them ontofish. - Check the Outliner. Every parent sits above its children, as in the table. Punchy! attaches a bone that the file lists before its parent to the model’s root instead of to the parent, and the complete geometry file below lists every parent first, so compare your export with it.
- Choose File > Export > Export Bedrock Geometry and save the file as
bucket.geo.jsonin the pack’sgeofolder.
Video coming soon
Video coming soon
Two things to know about Blockbench:
- It mirrors the X axis when it writes a file: a cube at Position X 5 is written with an origin of -6. Every cube here is centered or comes in a left and right pair, so place both cubes of a pair and the file comes out right.
- You do not need to touch a UV. Blockbench gives each face one, and the exported numbers will not match the file below. That is fine, because every texture is a flat color. Leave the UVs as Blockbench makes them: they stay inside the 16 by 16 picture you set in the project.
You can also skip the modeling: save the file from the next section and open it with File > Open Model.
In Punchy! Studio
Studio builds the geometry in the Model workspace and shows it in your hand while you work. This first model part is the empty bucket. You will reuse it for the other states later.
- Join a world, hold a bucket, switch to first person and press F6. If the editor opens in the Third Person perspective, pick First Person with the Perspective switch between the menus and the workspace tabs.
- Open the Model workspace and choose File > New Model Part (Ctrl+N).
- Type
bucket_emptyin Name andminecraft:bucketin Held Item, then press Create. The part starts with one bone calledrootand one cube. - Open the Definition tab. In the Project panel, set File Name to
bucket_emptyand Namespace tobucketpack. - Select
rootin the Outliner. In the Bone tab, typebodyin Name and 0, 5, 0 in Pivot. - Select its cube. In the Cube tab, set Origin and Size to the north wall row of the table.
- Select
bodyagain and press Add Cube in the Bone Actions panel. Set Origin and Size to the next wall. Repeat untilbodyhas its four walls. - For each other bone, select its parent and press Add Child Bone. In the Bone tab set Name and Pivot, then press Add Cube for each cube of that bone and set its Origin and Size.
eyesandtailare children offish, so selectfishfirst. - Choose View > Live Link with Punchy (Ctrl+L) and hold the bucket. Punchy! now draws your unsaved model in your hand.
Video coming soon
Video coming soon
Studio leaves the UVs of a new cube as they are, and that is fine here, because every texture is a flat color. Its Lint panel on the Definition tab names anything Punchy! would drop.
The complete geometry file
This is what the model comes to. Save it as geo/bucket.geo.json if you want to skip the modeling or compare your own file. Every face reads the whole 16 by 16 picture.
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": { "identifier": "geometry.bucket", "texture_width": 16, "texture_height": 16 },
"bones": [
{
"name": "body",
"pivot": [0, 5, 0],
"cubes": [
{
"origin": [-5, 1, -5],
"size": [10, 9, 1],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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] }
}
},
{
"origin": [-5, 1, 4],
"size": [10, 9, 1],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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] }
}
},
{
"origin": [-5, 1, -4],
"size": [1, 9, 8],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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] }
}
},
{
"origin": [4, 1, -4],
"size": [1, 9, 8],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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": "foot",
"parent": "body",
"pivot": [0, 0, 0],
"cubes": [
{
"origin": [-5, 0, -5],
"size": [10, 1, 10],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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": "handle",
"parent": "body",
"pivot": [0, 9, 0],
"cubes": [
{
"origin": [-6, 9, -0.5],
"size": [1, 3, 1],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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] }
}
},
{
"origin": [5, 9, -0.5],
"size": [1, 3, 1],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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] }
}
},
{
"origin": [-6, 12, -0.5],
"size": [12, 1, 1],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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": "liquid",
"parent": "body",
"pivot": [0, 1, 0],
"cubes": [
{
"origin": [-4, 1, -4],
"size": [8, 6, 8],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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": "surface",
"parent": "body",
"pivot": [0, 7.5, 0],
"cubes": [
{
"origin": [-3.5, 7, -3.5],
"size": [7, 1, 7],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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": "fish",
"parent": "body",
"pivot": [0, 8, 0],
"cubes": [
{
"origin": [-1.5, 6.5, -3],
"size": [3, 3, 6],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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": "eyes",
"parent": "fish",
"pivot": [0, 8.6, -2.1],
"cubes": [
{
"origin": [-1.7, 8.2, -2.5],
"size": [0.4, 0.8, 0.8],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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] }
}
},
{
"origin": [1.3, 8.2, -2.5],
"size": [0.4, 0.8, 0.8],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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": "tail",
"parent": "fish",
"pivot": [0, 8, 3],
"cubes": [
{
"origin": [-0.5, 6.5, 3],
"size": [1, 3, 1],
"uv": {
"north": { "uv": [0, 0], "uv_size": [16, 16] },
"east": { "uv": [0, 0], "uv_size": [16, 16] },
"south": { "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] }
}
}
]
}
]
}
]
}Make the textures
The pack needs fifteen small PNG files. Each is one flat color over the whole picture.
| File | Size | Used for | Color (hex) | Red, green, blue |
|---|---|---|---|---|
steel.png | 16 by 16 | The walls of the pail | #B9BFC7 | 185, 191, 199 |
iron.png | 16 by 16 | The base, the handle and the eyes | #4A4F57 | 74, 79, 87 |
clear.png | 16 by 16 | Hides a bone | none | fully transparent |
water.png | 16 by 64 | Water, four frames | #2F6FE0, #3A7DEC, #2F6FE0, #2563D0 | 47, 111, 224; 58, 125, 236; 47, 111, 224; 37, 99, 208 |
lava.png | 16 by 64 | Lava, four frames | #E0540A, #F26A10, #FF8A1E, #F26A10 | 224, 84, 10; 242, 106, 16; 255, 138, 30; 242, 106, 16 |
milk.png | 16 by 16 | Milk | #F4F4EE | 244, 244, 238 |
fish_ | 16 by 16 | The cod | #A67C52 | 166, 124, 82 |
fish_ | 16 by 16 | The salmon | #D0685C | 208, 104, 92 |
fish_ | 16 by 16 | The tropical fish | #F58A24 | 245, 138, 36 |
fish_ | 16 by 16 | The pufferfish | #E9C13B | 233, 193, 59 |
axolotl_ | 16 by 16 | The axolotl variant lucy, also the fallback | #F4A6C9 | 244, 166, 201 |
axolotl_ | 16 by 16 | The axolotl variant wild | #8A5A3C | 138, 90, 60 |
axolotl_ | 16 by 16 | The axolotl variant gold | #F2C94C | 242, 201, 76 |
axolotl_ | 16 by 16 | The axolotl variant cyan | #4CC9D6 | 76, 201, 214 |
axolotl_ | 16 by 16 | The axolotl variant blue | #3B63E0 | 59, 99, 224 |
Two of them have more than one frame. An animated texture stacks its frames one under the other, each as tall as the geometry’s texture grid, which is 16 here. Four frames make a picture 16 pixels wide and 64 tall. clear.png has no color at all: every pixel is fully transparent, which makes a bone invisible.
In Blockbench
Blockbench only makes the model, so the textures come from somewhere else. Pick one:
- The script. It writes all fifteen files. Open the next box, save the script as
make_textures.pyin yourresourcepacksfolder and runpython make_textures.py. The files land in the pack’stexturesfolder. - An image editor. Make each file by hand: a 16 by 16 picture filled with the color in the table, and a 16 by 64 picture for
water.pngandlava.pngwith a color of its own in each of the four 16 pixel rows. Save them as PNG, withclear.pngfully transparent, in the pack’stexturesfolder.
In Punchy! Studio
Studio paints the textures in the Model workspace, or takes finished PNG files.
- Select the bone that needs a texture, for example
body. Open the Paint tab (5 switches the stage to Paint mode) and type the red, green, blue and alpha values from the table in the Color panel. Alpha is 255 for every color exceptclear. - Choose Image > New Image…. Type the name in Name, set Width and Height from the table, set Fill to Paint Color (or Transparent for
clear) and press Create. The image becomes the texture of the selected bone. Studio puts your File Name in front of the image’s name when it writes the file. - To give another bone an image you already made, select the bone and pick the image in the Texture list of its Bone tab.
- For
waterandlava, select theliquidbone and make the image 16 wide and 64 high. In the Bone tab, set Frames to 4 and Frame Time to 10 for water or 6 for lava, under Bone Texture Animation. Then, for each frame, set the Frame field of the image editor, set the color of that frame (the table lists the colors from the top frame down) and paint it with the Pencil set to a Square shape and a Size of 32: a stroke stays inside the chosen frame. Givesurfacethe same image in its Texture list, and the same Frames and Frame Time.
Video coming soon
If you ran the script below, dropping a PNG on the game window is quicker. With a bone selected the PNG becomes that bone’s texture.
The texture script
It needs only Python 3. It writes every texture of the table into the folder named in OUT near the top, so change that line if your pack sits somewhere else.
import os
import struct
import sys
import zlib
# Where the PNG files go. Pass another folder as the first argument to change it.
OUT = sys.argv[1] if len(sys.argv) > 1 else "Bucket pack/assets/bucketpack/punchy/model_parts_items/textures"
def png(path, width, height, rows):
"""Write an 8-bit RGBA PNG. rows is a list of height rows, each a list of (r, g, b, a)."""
raw = b"".join(b"\x00" + b"".join(bytes(px) for px in row) for row in rows)
def chunk(kind, data):
body = kind + data
return struct.pack(">I", len(data)) + body + struct.pack(">I", zlib.crc32(body) & 0xFFFFFFFF)
data = b"\x89PNG\r\n\x1a\n"
data += chunk(b"IHDR", struct.pack(">IIBBBBB", width, height, 8, 6, 0, 0, 0))
data += chunk(b"IDAT", zlib.compress(raw, 9))
data += chunk(b"IEND", b"")
with open(path, "wb") as f:
f.write(data)
def hexcolor(text):
text = text.lstrip("#")
return (int(text[0:2], 16), int(text[2:4], 16), int(text[4:6], 16), 255)
def flat(color):
return [[color] * 16 for _ in range(16)]
def strip(colors):
"""One 16 by 16 frame per color, one under the other."""
rows = []
for color in colors:
rows += flat(color)
return rows
os.makedirs(OUT, exist_ok=True)
solid = {
"steel": "#B9BFC7",
"iron": "#4A4F57",
"milk": "#F4F4EE",
"fish_cod": "#A67C52",
"fish_salmon": "#D0685C",
"fish_tropical": "#F58A24",
"fish_pufferfish": "#E9C13B",
"axolotl_lucy": "#F4A6C9",
"axolotl_wild": "#8A5A3C",
"axolotl_gold": "#F2C94C",
"axolotl_cyan": "#4CC9D6",
"axolotl_blue": "#3B63E0",
}
for name, color in solid.items():
png(os.path.join(OUT, name + ".png"), 16, 16, flat(hexcolor(color)))
# Nothing at all: draws as see-through, which hides a bone.
png(os.path.join(OUT, "clear.png"), 16, 16, flat((0, 0, 0, 0)))
# Animated textures: four frames of 16 by 16 pixels, so the files are 16 by 64.
water = ["#2F6FE0", "#3A7DEC", "#2F6FE0", "#2563D0"]
lava = ["#E0540A", "#F26A10", "#FF8A1E", "#F26A10"]
png(os.path.join(OUT, "water.png"), 16, 64, strip([hexcolor(c) for c in water]))
png(os.path.join(OUT, "lava.png"), 16, 64, strip([hexcolor(c) for c in lava]))
print("Wrote", len(solid) + 3, "textures to", OUT)Animate the bucket
The pack has five item clips. They move bones by name, so one file serves every definition. Item clips play at 1x unless a clip sets a speed of its own.
| Clip | What it is for |
|---|---|
bucket_ | The handle swings and the pail rises a little, over 3 seconds, on a loop. |
bucket_ | A faster bob and roll, for when you touch water. Loops. |
bucket_ | The pail tilts and comes back, once. For the milk bucket. |
fish_idle | A handle swing, plus a fish that bobs and turns and a tail that wags. Loops. |
fish_float | The faster version for water. Loops. |
These are the keys, as they are written in the clip file and as Studio shows them. Times are in seconds, and each key is three numbers. Between two keys the motion is a straight line. Punchy! reads a clip with the sign of X rotation, Y rotation and X position flipped, which matters when you key in Blockbench (see below).
| Clip | Bone | Channel | Keys |
|---|---|---|---|
bucket_, 3 s, loop | handle | Rotation | 0: 0, 0, 0; 1.5: 6, 0, 0; 3: 0, 0, 0 |
bucket_, 3 s, loop | body | Position | 0: 0, 0, 0; 1.5: 0, 0.3, 0; 3: 0, 0, 0 |
bucket_, 2.4 s, loop | body | Position | 0: 0, 0, 0; 1.2: 0, 0.8, 0; 2.4: 0, 0, 0 |
bucket_, 2.4 s, loop | body | Rotation | 0: 0, 0, 0; 0.6: 0, 0, 3; 1.2: 0, 0, 0; 1.8: 0, 0, -3; 2.4: 0, 0, 0 |
bucket_, 2.4 s, loop | handle | Rotation | 0: 0, 0, 0; 0.8: 10, 0, 0; 1.6: -6, 0, 0; 2.4: 0, 0, 0 |
bucket_, 1.6 s, once | body | Rotation | 0: 0, 0, 0; 0.5: -35, 0, 0; 1.1: -35, 0, 0; 1.6: 0, 0, 0 |
bucket_, 1.6 s, once | body | Position | 0: 0, 0, 0; 0.5: 0, 2, 1; 1.1: 0, 2, 1; 1.6: 0, 0, 0 |
fish_idle, 1.5 s, loop | handle | Rotation | 0: 0, 0, 0; 0.75: 5, 0, 0; 1.5: 0, 0, 0 |
fish_idle, 1.5 s, loop | fish | Position | 0: 0, 0, 0; 0.5: 0, 0.4, 0; 1: 0, -0.3, 0; 1.5: 0, 0, 0 |
fish_idle, 1.5 s, loop | fish | Rotation | 0: 0, 0, 0; 0.5: 0, 8, 0; 1: 0, -8, 0; 1.5: 0, 0, 0 |
fish_idle, 1.5 s, loop | tail | Rotation | 0: 0, 0, 0; 0.375: 0, 25, 0; 0.75: 0, 0, 0; 1.125: 0, -25, 0; 1.5: 0, 0, 0 |
fish_float, 1.2 s, loop | body | Position | 0: 0, 0, 0; 0.6: 0, 0.8, 0; 1.2: 0, 0, 0 |
fish_float, 1.2 s, loop | body | Rotation | 0: 0, 0, 0; 0.3: 0, 0, 3; 0.6: 0, 0, 0; 0.9: 0, 0, -3; 1.2: 0, 0, 0 |
fish_float, 1.2 s, loop | handle | Rotation | 0: 0, 0, 0; 0.6: 10, 0, 0; 1.2: 0, 0, 0 |
fish_float, 1.2 s, loop | fish | Rotation | 0: 0, 0, 0; 0.3: 0, 12, 0; 0.9: 0, -12, 0; 1.2: 0, 0, 0 |
fish_float, 1.2 s, loop | tail | Rotation | 0: 0, 0, 0; 0.3: 0, 30, 0; 0.6: 0, 0, 0; 0.9: 0, -30, 0; 1.2: 0, 0, 0 |
In Blockbench
Blockbench animates the bones of the model you just made and exports a Bedrock animation file.
- In the same project, press Animate, the mode tab at the top right.
- In the Animations panel, press Add Animation. Type
bucket_idlein Name, set Loop Mode to Loop and press Confirm. Set Animation Length to3. - In the Outliner, select
handle. In the Timeline panel, click the ruler at0and press the + beside Rotation. Type the numbers from the table in the Keyframe panel, with the signs flipped as described below the steps. Add the keys at the other times the same way. - Select
bodyand key its Position the same way. - Add the other four clips with Add Animation. Use Play Once as the Loop Mode for
bucket_drinkand Loop for the rest, and the lengths from the table’s last key time. - Choose Animation > Export Animations…. In Select Animations to Export, tick all five clips and press Confirm. Save the file as
bucket.animation.jsonin the pack’sanimationsfolder.
Video coming soon
Blockbench’s Bedrock export flips the sign of X rotation, Y rotation and X position, and Punchy! flips them back when it reads the file, so a motion keyed in Blockbench plays in the game as it looks in Blockbench. The tables hold the numbers as the file has them, so in Blockbench key each rotation with its first two numbers flipped, and each position with its first number flipped. The handle’s -6, 0, 0 is keyed as 6, 0, 0, the fish’s 0, 8, 0 as 0, -8, 0 and the drink tilt’s -35, 0, 0 as 35, 0, 0. A zero stays zero, and the third number keeps its sign. After the export, compare your file with the complete clip file below.
In Punchy! Studio
Studio keys the clips on a timeline, writes the clip file and adds it to the definition.
- In the Model workspace, open the Animation tab and press Add Clip. A clip named
idleappears under Item Clips in the Outliner. - In the Item Clip panel, type
bucket_idlein Name and3in Length, and choose Loop on the Loop row. The row offers Once, Loop and Hold. - Select the
handlebone in the Outliner and pick its Rotation row in the timeline. Put the playhead on0and press I. Set the key’s values in the key column, then add the other keys of the table at their times the same way. - Select
body, pick its Position row and key it the same way. - Press Add Clip for each of the other four clips. Use Once for
bucket_drinkand Loop for the rest. Key each bone and channel of the table. - Press Space to play a clip on the stage.
Video coming soon
Studio keys the numbers exactly as they are written in the clip file, so type the numbers of the table as they are. It plays every item clip key in a straight line, as Punchy! does. Check the tilt of bucket_drink in the live link: if it goes the wrong way, flip the sign of its keys.
The complete clip file
Save it as animations/bucket.animation.json. These are the numbers as the file holds them. Studio writes the same clips into its own file, named after the part.
{
"format_version": "1.8.0",
"animations": {
"bucket_idle": {
"loop": true,
"animation_length": 3.0,
"bones": {
"handle": { "rotation": { "0.0": [0, 0, 0], "1.5": [6, 0, 0], "3.0": [0, 0, 0] } },
"body": { "position": { "0.0": [0, 0, 0], "1.5": [0, 0.3, 0], "3.0": [0, 0, 0] } }
}
},
"bucket_float": {
"loop": true,
"animation_length": 2.4,
"bones": {
"body": {
"position": { "0.0": [0, 0, 0], "1.2": [0, 0.8, 0], "2.4": [0, 0, 0] },
"rotation": {
"0.0": [0, 0, 0],
"0.6": [0, 0, 3],
"1.2": [0, 0, 0],
"1.8": [0, 0, -3],
"2.4": [0, 0, 0]
}
},
"handle": {
"rotation": { "0.0": [0, 0, 0], "0.8": [10, 0, 0], "1.6": [-6, 0, 0], "2.4": [0, 0, 0] }
}
}
},
"bucket_drink": {
"animation_length": 1.6,
"bones": {
"body": {
"rotation": { "0.0": [0, 0, 0], "0.5": [-35, 0, 0], "1.1": [-35, 0, 0], "1.6": [0, 0, 0] },
"position": { "0.0": [0, 0, 0], "0.5": [0, 2, 1], "1.1": [0, 2, 1], "1.6": [0, 0, 0] }
}
}
},
"fish_idle": {
"loop": true,
"animation_length": 1.5,
"bones": {
"handle": { "rotation": { "0.0": [0, 0, 0], "0.75": [5, 0, 0], "1.5": [0, 0, 0] } },
"fish": {
"position": {
"0.0": [0, 0, 0],
"0.5": [0, 0.4, 0],
"1.0": [0, -0.3, 0],
"1.5": [0, 0, 0]
},
"rotation": { "0.0": [0, 0, 0], "0.5": [0, 8, 0], "1.0": [0, -8, 0], "1.5": [0, 0, 0] }
},
"tail": {
"rotation": {
"0.0": [0, 0, 0],
"0.375": [0, 25, 0],
"0.75": [0, 0, 0],
"1.125": [0, -25, 0],
"1.5": [0, 0, 0]
}
}
}
},
"fish_float": {
"loop": true,
"animation_length": 1.2,
"bones": {
"body": {
"position": { "0.0": [0, 0, 0], "0.6": [0, 0.8, 0], "1.2": [0, 0, 0] },
"rotation": {
"0.0": [0, 0, 0],
"0.3": [0, 0, 3],
"0.6": [0, 0, 0],
"0.9": [0, 0, -3],
"1.2": [0, 0, 0]
}
},
"handle": { "rotation": { "0.0": [0, 0, 0], "0.6": [10, 0, 0], "1.2": [0, 0, 0] } },
"fish": {
"rotation": { "0.0": [0, 0, 0], "0.3": [0, 12, 0], "0.9": [0, -12, 0], "1.2": [0, 0, 0] }
},
"tail": {
"rotation": {
"0.0": [0, 0, 0],
"0.3": [0, 30, 0],
"0.6": [0, 0, 0],
"0.9": [0, -30, 0],
"1.2": [0, 0, 0]
}
}
}
}
}
}The empty bucket
A definition ties the files together. This one covers minecraft:bucket, hides every bit of content and adds one condition: when you touch water, the bucket bobs and blows bubbles.
In Blockbench
Save the text below as definitions/bucket_empty.json. Every definition in this pack is a file of this kind.
{
"items": ["minecraft:bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/clear",
"bones": ["liquid", "surface", "fish", "eyes"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "bucket_idle", "disable_all_particles": true },
{ "type": "idle", "animation": "bucket_float", "in_water": true }
],
"particles": [
{
"type": "minecraft:bubble",
"bone": "body",
"offset": [0, 0.35, 0],
"rate": 3,
"life": 0.9,
"size": 0.03,
"spread": [0.08, 0, 0.08],
"velocity": [0, 0.02, 0]
}
]
} In Punchy! Studio
Studio writes the definition from the forms of the Model workspace. You already have the geometry. Add the rest in this order.
- Make the textures of the empty bucket as in Make the textures:
steelforbody,ironforfootandhandle, andclearforliquid,surface,fishandeyes.tailtakes the texture offishby itself. - Make the five clips of Animate the bucket in this model part. Studio adds them to one clip file.
- In the Animation tab, press Add Entry. Set Type to
idleand Clip tobucket_idle, and tick No Particles. - Press Add Entry again. Set Type to
idleand Clip tobucket_float, and choose Yes on the In Water row. - Choose Add > Add Emitter. In the Particles tab, set Type to
minecraft:bubble, Bone tobody, Rate to 3, Life to 0.9, Size to 0.03, Spread to 0.08, 0, 0.08, Velocity to 0, 0.02, 0 and Offset to 0, 0.35, 0. - Choose File > Export Model Part… (Ctrl+E). In the Export Model Part window, type
Bucket packin Pack, tick Activate the pack and play it now and press Export.
Video coming soon
Each Studio field has a tooltip that names the JSON key it writes. This table shows where the keys of this page live in the Model workspace.
| In the definition | In Studio |
|---|---|
items | Definition tab, Items panel, Items |
bone_ | Bone tab, Texture list |
bone_ | Bone tab, Bone Texture Animation: Frames and Frame Time |
bone_ | Bone tab, Glow Level. Blur Glow is in the Material tab, under Glow Settings |
model | Animation tab: Add Entry, then Type, Clip, In Water, No Particles |
bone_ | Physics tab with a bone selected: Mode, Limit, Camera Sensitivity, Gravity, Motion Sensitivity, Creature Feedback |
particles | Particles tab: Add Emitter, then Type, Bone, Count, Rate and the trigger switches |
dynamic_ | Not edited in Studio. Studio keeps it when you export |
Studio writes the file names itself: the definition, geometry, clips and textures are named after the File Name of the part. With Export First in Order on, the definition goes into a folder called 0_punchy_studio. Punchy! sorts definitions by their full id, so a folder name changes the order among definitions of the same namespace, and this one sorts before other folders of that namespace. Which definition covers an item has the whole rule.
What each part does:
itemsis the item the definition covers.geois the full id of the geometry, with the folder and the.geo.jsonending.textureis the main texture, which any bone without a texture of its own uses. Punchy! adds.pngfor you.bone_textureslists the exceptions as groups of bones.footandhandleare iron.liquid,surface,fishandeyesgetclear, which hides them.tailis a child offish, so it takesfish’s texture and is hidden with it.animationsloads the clip file, with the full id and the.animation.jsonending.- The first
idleentry playsbucket_idleall the time. The second also asksin_water: it passes only while you touch water, and an entry with a condition beats a plain one while it passes. So the bob plays in water and the sway on land.in_wateris true on contact with water around you.inside_wateris true only while your eyes are under water, and it holds for 4 ticks after you leave the water. Conditions covers these and the other checks: weather, blocks, time of day and biomes. disable_all_particleson the dry entry silences the emitters while it plays. The bubbles therefore appear only in water.- The bubble emitter has no triggers, so it runs on its own clock: 3 releases a second.
offsetlifts it to just above the rim. Distances in a particle are in blocks, so 0.35 is 5.6 pixels.
Press F3+T in a world after a change to reload definitions, clips and particle settings. If you change a texture that a particle uses, restart Minecraft, because particle textures stay cached until then. Try the pack in the game tells you what to look for.
The water bucket
The water bucket shows the animated water and makes it slosh. It also adds a splash that fires when you jump or land.
{
"items": ["minecraft:water_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/water",
"bones": ["liquid", "surface"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/clear",
"bones": ["fish", "eyes"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "bucket_idle" },
{ "type": "idle", "animation": "bucket_float", "in_water": true }
],
"bone_texture_anim": {
"liquid": { "frames": 4, "frametime": 10 },
"surface": { "frames": 4, "frametime": 10 }
},
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 10,
"camera_sens": 0.5,
"gravity": 14,
"motion_sens": 0.4
}
},
"particles": [
{
"type": "minecraft:splash",
"bone": "surface",
"count": 4,
"life": 0.5,
"size": 0.05,
"spread": [0.06, 0, 0.06],
"velocity": [0, 0.03, 0],
"gravity": -0.4,
"triggers": { "jump": true, "landing": true },
"trigger_mode": "any"
}
]
}
In Blockbench
Save the file as definitions/bucket_water.json. From here on the Blockbench path is only saving files: each definition below goes into definitions under the name in the layout above (bucket_lava.json, bucket_milk.json, bucket_cod.json, bucket_pufferfish.json and bucket_axolotl.json; the salmon and tropical fish files are named in their own box), and the geometry and the clips stay as they are.
In Punchy! Studio
Make the water bucket from a part you already have. Every other state works the same way.
- Choose File > Open Model Part… (Ctrl+O) to open the Model Parts Library. Pick Resource Packs, select
bucket_emptyand press Open. Studio copies the definition and its files into a new project. The pack you took it from is not changed. - In the Definition tab, set File Name to
bucket_waterand untick Keep Original Paths, so the export writes new files and leaves the empty bucket alone. Change Items tominecraft:water_bucket. - Make the
watertexture as in Make the textures: selectliquid, create the 16 by 64 image, set Frames to 4 and Frame Time to 10, and paint the four frames. Selectsurfaceand pick the same image in its Texture list, with the same Frames and Frame Time. - Select
fishandeyesand keep them onclear. - In the Outliner, select the first entry under Animation Entries. In the Animation tab, untick No Particles.
- Select the
surfacebone and open the Physics tab. Press the Item Pendulum Default preset, which creates the entry. Set Mode to Full, Limit to 10, Camera Sensitivity to 0.5, Gravity to 14 and Motion Sensitivity to 0.4. Studio writes every pendulum setting, the ones you did not change too, at the values Punchy! uses by default. - Choose Add > Add Emitter. Set Type to
minecraft:splash, Bone tosurface, Count to 4, Life to 0.5, Size to 0.05, Spread to 0.06, 0, 0.06, Velocity to 0, 0.03, 0 and Gravity to -0.4. Turn on Jump and Landing, and set Trigger Logic to Any. - Export with Ctrl+E.
Video coming soon
For the other states, change what differs and make the project match the definition file of that state on this page: the Items, the bone textures, the entries, the physics and the emitters. Set File Name to the name of that state in the layout (bucket_lava, bucket_milk, bucket_cod, bucket_salmon, bucket_tropical_fish, bucket_pufferfish or bucket_axolotl), and make the textures the state needs as in Make the textures: lava, milk, the color of the fish or the five axolotl pictures. The water is the model; the lava, the milk and the fish buckets only change a few of these.
What is new:
bone_texturesnow givesliquidandsurfacethewatertexture. Onlyfishandeyesstay hidden.bone_texture_animanimates the water.water.pngis 16 by 64, so it holds 4 frames, and each frame lasts 10 game ticks, half a second. It is set per bone and by the exact bone name, so both liquid bones need an entry. The picture must be exactlyframestimes the frame height tall, or the water does not animate and shows the whole picture squeezed onto each face, without a message.bone_physicsmakes thesurfaceslab slosh. It swings around its pivot like a pendulum, pushed by the way you turn the camera and move.limit_degcaps the swing at 10 degrees.gravityis how hard the slab is pulled back to rest, and 14 is softer than the default of 25. The modefullswings both ways. These numbers are a starting point: raiselimit_degfor a wilder slosh andcamera_sensfor a stronger reaction to the camera.- The splash particle belongs to the
surfacebone. A particle trigger is a pulse, an event that fires once:jumpandlandingare two pulses that never happen at the same moment, sotrigger_modeisany. With the default mode, which needs every trigger at once, it would never fire.countis how many particles one event throws,gravityis negative, which pulls them down gently (particles anchored to the item work in pixels), andvelocitythrows them up.
Video coming soon
The lava bucket
The lava bucket reuses the water recipe with a few changes: the liquid glows, the texture moves faster, the physics are tighter and the embers have their own rule.
{
"items": ["minecraft:lava_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/lava",
"bones": ["liquid", "surface"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/clear",
"bones": ["fish", "eyes"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "bucket_idle" },
{
"type": "idle",
"animation": "bucket_float",
"in_water": true,
"disable_all_particles": true
}
],
"bone_emission": { "liquid": 100, "surface": 100, "blur": true },
"bone_texture_anim": {
"liquid": { "frames": 4, "frametime": 6 },
"surface": { "frames": 4, "frametime": 6 }
},
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 6,
"camera_sens": 0.35,
"gravity": 22,
"motion_sens": 0.25
}
},
"particles": [
{
"type": "minecraft:lava",
"bone": "surface",
"rate": 2,
"life": 0.8,
"size": 0.03,
"spread": [0.06, 0, 0.06],
"velocity": [0, 0.025, 0],
"gravity": -0.3
}
]
}
What is new:
bone_emissionmakesliquidandsurfaceglow. A level from 1 to 15 sets how bright the glow layer is, and 16 to 100 add bloom, which shows only whenbluris on. The glow layer is drawn at full brightness, so the lava stays bright in the dark.bluris a setting of the whole object, not a bone, and so areclampandstrength: a bone with one of those names could not glow.- The lava texture changes every 6 ticks. Because the glow is drawn from the same frame, the glow flickers with the lava.
- The slosh is tighter:
limit_deg6, lower sensitivities and a highergravityof 22 make the lava swing less and snap back sooner. - The
minecraft:lavaparticle uses the picture Punchy! finds for that id. The emitter runs on its own clock, 2 releases a second, and a negativegravitypulls the embers down gently. - The in-water entry carries
disable_all_particles, so the embers stop while you touch water. The glow stays.
The glow above lights the lava and nothing else. To keep the whole lava bucket bright in the dark, the pail and the handle too, add a shading rule. It is a small file of its own, assets/bucketpack/punchy/model_parts_items/shading.json, next to the definitions folder. Write it in a text editor, whichever tool made the rest of the pack. Studio has no form for it and leaves it alone when you export:
{
"rules": [
{ "item": "minecraft:lava_bucket", "fullbright": true }
]
}
fullbright draws a model part item without the light map, so it stays bright at night. The rule changes only items a pack draws as model parts, and it is the same for every bucket you add a rule for. Press F3+T after you change the file. Shading rules lists the other keys, shading and additive.
Video coming soon
The milk bucket
Milk is the only bucket you drink, so its definition adds an entry for the drink moment.
{
"items": ["minecraft:milk_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/milk",
"bones": ["liquid", "surface"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/clear",
"bones": ["fish", "eyes"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "bucket_idle" },
{ "type": "idle", "animation": "bucket_float", "in_water": true },
{ "type": "useDrink", "animation": "bucket_drink" }
],
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 8,
"camera_sens": 0.4,
"gravity": 18,
"motion_sens": 0.3
}
},
"particles": [
{
"type": "minecraft:cloud",
"bone": "surface",
"count": 3,
"life": 0.6,
"size": 0.05,
"spread": [0.06, 0, 0.06],
"velocity": [0, 0.015, 0],
"triggers": { "jump": true, "landing": true },
"trigger_mode": "any"
}
]
}
What is new:
- While you use an item, Punchy! draws the normal item instead of your model, unless the definition has an entry for that use. The
useDrinkentry keeps the model in your hand while you drink, and playsbucket_drink: the pail tilts and comes back. Check the direction in the game. If it tilts the wrong way, flip the sign of the X rotation in that clip. - The
milktexture is a still picture, so there is nobone_texture_anim. - A softer slosh:
limit_deg8 sits between water and lava. - The cloud particle puffs on a jump or a landing, with the same pulse pair as the water splash.
The fish buckets
A fish bucket shows the water and one fish. The fish sits at the surface and has three of its own bones: the body, the eyes and the tail.
{
"items": ["minecraft:cod_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle", "eyes"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/water",
"bones": ["liquid", "surface"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/fish_cod",
"bones": ["fish"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "fish_idle" },
{ "type": "idle", "animation": "fish_float", "in_water": true }
],
"bone_texture_anim": {
"liquid": { "frames": 4, "frametime": 10 },
"surface": { "frames": 4, "frametime": 10 }
},
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 10,
"camera_sens": 0.5,
"gravity": 14,
"motion_sens": 0.4
},
"fish": {
"enableCreaturePhysics": true,
"impactInclinationPercent": 50,
"fallInclinationPercent": 50
}
},
"particles": [
{
"type": "minecraft:bubble",
"bone": "fish",
"rate": 1.5,
"life": 0.8,
"size": 0.025,
"spread": [0.04, 0, 0.04],
"velocity": [0, 0.02, 0]
}
]
}
What is new:
bone_texturesgives the water toliquidandsurface, and the fish’s color tofish.eyesjoinsfootandhandlein the iron group, so they are dark.tailfollowsfish.- The entries play the fish clips:
fish_idleand, in water,fish_float. Each clip also moves the handle, so the pail still sways. - The
fishbone hasenableCreaturePhysics, the feedback Punchy! gives a pufferfish bucket: the bone tilts and squashes as you jump, fall, land, turn and walk. The two percent keys scale the tilt down to half, because 100 is the default and a cod should not wobble like a pufferfish. A bone spec needs a pendulum mode, creature feedback or slime feedback, or Punchy! drops it, and here the creature feedback keeps it. - The bubble emitter belongs to the
fishbone and runs all the time, because a fish in a bucket is always in water.
The pufferfish bucket is the same file with a different item and texture, and with the creature feedback at full strength: a pufferfish is the animal that feedback was made for.
{
"items": ["minecraft:pufferfish_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle", "eyes"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/water",
"bones": ["liquid", "surface"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/fish_pufferfish",
"bones": ["fish"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "fish_idle" },
{ "type": "idle", "animation": "fish_float", "in_water": true }
],
"bone_texture_anim": {
"liquid": { "frames": 4, "frametime": 10 },
"surface": { "frames": 4, "frametime": 10 }
},
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 10,
"camera_sens": 0.5,
"gravity": 14,
"motion_sens": 0.4
},
"fish": { "enableCreaturePhysics": true }
},
"particles": [
{
"type": "minecraft:bubble",
"bone": "fish",
"rate": 1.5,
"life": 0.8,
"size": 0.025,
"spread": [0.04, 0, 0.04],
"velocity": [0, 0.02, 0]
}
]
}
The salmon and the tropical fish buckets differ from the cod in two places: the item and the fish texture. Open the box for both files.
The salmon and tropical fish definitions
Save them as definitions/bucket_salmon.json and definitions/bucket_tropical_fish.json.
{
"items": ["minecraft:salmon_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle", "eyes"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/water",
"bones": ["liquid", "surface"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/fish_salmon",
"bones": ["fish"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "fish_idle" },
{ "type": "idle", "animation": "fish_float", "in_water": true }
],
"bone_texture_anim": {
"liquid": { "frames": 4, "frametime": 10 },
"surface": { "frames": 4, "frametime": 10 }
},
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 10,
"camera_sens": 0.5,
"gravity": 14,
"motion_sens": 0.4
},
"fish": {
"enableCreaturePhysics": true,
"impactInclinationPercent": 50,
"fallInclinationPercent": 50
}
},
"particles": [
{
"type": "minecraft:bubble",
"bone": "fish",
"rate": 1.5,
"life": 0.8,
"size": 0.025,
"spread": [0.04, 0, 0.04],
"velocity": [0, 0.02, 0]
}
]
}{
"items": ["minecraft:tropical_fish_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle", "eyes"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/water",
"bones": ["liquid", "surface"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/fish_tropical",
"bones": ["fish"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "fish_idle" },
{ "type": "idle", "animation": "fish_float", "in_water": true }
],
"bone_texture_anim": {
"liquid": { "frames": 4, "frametime": 10 },
"surface": { "frames": 4, "frametime": 10 }
},
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 10,
"camera_sens": 0.5,
"gravity": 14,
"motion_sens": 0.4
},
"fish": {
"enableCreaturePhysics": true,
"impactInclinationPercent": 50,
"fallInclinationPercent": 50
}
},
"particles": [
{
"type": "minecraft:bubble",
"bone": "fish",
"rate": 1.5,
"life": 0.8,
"size": 0.025,
"spread": [0.04, 0, 0.04],
"velocity": [0, 0.02, 0]
}
]
}Video coming soon
The axolotl bucket
An axolotl has five colors, and the bucket remembers which one it holds. A dynamic texture picks the fish’s texture by that color. The rule asks for axol_variants, and each key of its map must be the variant name exactly as the game reports it. The five names used here are lucy, wild, gold, cyan and blue; confirm each one in the game as described in Try the pack in the game. The first, lucy, is the fallback, which is also what a bucket with no variant shows.
{
"items": ["minecraft:axolotl_bucket"],
"geo": "bucketpack:punchy/model_parts_items/geo/bucket.geo.json",
"texture": "bucketpack:punchy/model_parts_items/textures/steel",
"bone_textures": [
{
"texture": "bucketpack:punchy/model_parts_items/textures/iron",
"bones": ["foot", "handle", "eyes"]
},
{
"texture": "bucketpack:punchy/model_parts_items/textures/water",
"bones": ["liquid", "surface"]
}
],
"animations": ["bucketpack:punchy/model_parts_items/animations/bucket.animation.json"],
"modelPartsAnimation": [
{ "type": "idle", "animation": "fish_idle" },
{ "type": "idle", "animation": "fish_float", "in_water": true }
],
"bone_texture_anim": {
"liquid": { "frames": 4, "frametime": 10 },
"surface": { "frames": 4, "frametime": 10 }
},
"bone_physics": {
"surface": {
"pendulum_mode": "full",
"limit_deg": 10,
"camera_sens": 0.5,
"gravity": 14,
"motion_sens": 0.4
},
"fish": {
"enableCreaturePhysics": true,
"impactInclinationPercent": 50,
"fallInclinationPercent": 50
}
},
"particles": [
{
"type": "minecraft:bubble",
"bone": "fish",
"rate": 1.5,
"life": 0.8,
"size": 0.025,
"spread": [0.04, 0, 0.04],
"velocity": [0, 0.02, 0]
}
],
"dynamic_bone_textures": {
"type": "texture",
"bone": "fish",
"source": "axol_variants",
"fallback": "bucketpack:punchy/model_parts_items/textures/axolotl_lucy",
"map": {
"wild": "bucketpack:punchy/model_parts_items/textures/axolotl_wild",
"gold": "bucketpack:punchy/model_parts_items/textures/axolotl_gold",
"cyan": "bucketpack:punchy/model_parts_items/textures/axolotl_cyan",
"blue": "bucketpack:punchy/model_parts_items/textures/axolotl_blue"
}
}
}
What is new:
dynamic_bone_texturesswaps the texture of one bone,fish, while the game runs.sourcesays what Punchy! asks about the item,maplinks each answer to a texture, andfallbackcovers every other case. The answers are matched exactly, so each key has to be spelled as the game spells the variant. Dynamic textures explains the rule and its other source.fishhas no entry inbone_textures, because the rule gives it a texture.
Try the pack in the game
- Put
Bucket packin yourresourcepacksfolder. If you ticked Activate the pack and play it now in Studio’s export, it is already on and you can skip the rest of this step. In the game, open Options…, Resource Packs…, move the pack from Available to Selected, and press Done. - Join a creative world and switch to first person. Press F3+T after a later change to reload definitions, clips and particle settings. Restart Minecraft after changing a texture a particle uses.
- Give yourself the buckets one at a time, for example
/give @s water_bucket. The ids arebucket,water_bucket,lava_bucket,milk_bucket,cod_bucket,salmon_bucket,tropical_fish_bucket,pufferfish_bucketandaxolotl_bucket. Hold each one in your main hand. - Check each row of the table below. For the water, turn the camera quickly, and walk and jump.
- Stand in a pool of water and check the in-water behavior.
| Hold | You should see |
|---|---|
| Empty bucket | A steel pail with a handle that sways. In water it bobs, and bubbles rise from the opening |
| Water | Moving blue water. The surface tilts when you turn and settles again. A splash when you jump or land |
| Lava | Orange lava that flickers and glows, and embers. The embers stop in water |
| Milk | White milk with a lighter slosh. Drinking tilts the pail and the model stays in your hand |
| Cod, salmon, tropical fish, pufferfish | A colored fish at the surface that bobs and wags its tail, with bubbles. In water it moves faster |
| Axolotl | The same fish in the pink of lucy, or another color for another variant |
To get an axolotl bucket of another variant, catch axolotls of different colors, or use the command on Dynamic textures. Check each color this way: a bucket that shows the lucy pink when its axolotl is another color has a map key that does not match the name the game reports for that variant. Fix the key and reload.
Video coming soon
Keep working on it in Punchy! Studio
You can bring a finished pack into Studio and keep editing it there, whichever tool made it. Build from Pack reads your pack and builds a new one that Studio owns, with the model parts, clips and rules in it. The pack you start from is only read.
- Put
Bucket packin yourresourcepacksfolder. It does not need to be turned on. - Press F6, pick First Person if the editor opens in Third Person, and open the Library workspace (the Library tab in the top bar, or Ctrl+O in the Animation workspace).
- Press Build from Pack…. The menu lists the Packs with Punchy files in your game folder, each marked Active or Not active. Pick
Bucket pack. - In the Build from Pack window, keep or change the New pack name and press Build.
- Read the status bar. It says what was built and that the new pack is being turned on.

The model parts come along with their geometry, textures and clips. A shading.json does not: if your pack has one, copy it from Bucket pack into the same folder of the new pack. Open each in the Model workspace with File > Open Model Part… (Ctrl+O) and edit it. Punchy! Studio covers Build from Pack in full.
Keys this pack uses
These are the keys of the definitions above. Model part definitions has all of them. Key names in one row are aliases.
| Key | Type | What it does | Example |
|---|---|---|---|
itemsRequired | string array | The items the definition covers. A bare id gets the minecraft namespace, and #tag covers an item tag. When items is there, item is not read, and an empty list drops the definition. | ["minecraft: |
geoRequired | resource id | The geometry file, used as written. Write the folders and the .geo.json ending. A missing file leaves the vanilla bucket in your hand. | bucketpack: |
textureRequired | resource id | The main texture. A path under punchy/ gets .png added when it is missing. | bucketpack: |
bone_ | object or list | Gives bones their own texture. The object form maps a bone name to a texture. The list form takes entries of texture and bones, and a later entry wins for a bone. A bone without an entry uses its parent's texture, then the main texture. | |
bone_ | object | Animates the texture of a bone, by the exact bone name. Each bone takes frames, frametime and frame_. A bone's entry does not copy anything from the whole-model texture_. | { "liquid": { "frames": 4, "frametime": 10 } } |
bone_ | object | Glow. Each bone name takes a level from 0 to 100, and blur adds a bloom layer. The names blur, clamp, strength, intensity and brightness are reserved. | { "liquid": 100, "blur": true } |
animations | resource id array | The item clip files. Write each id in full with the . ending. Every clip is loaded, and a later file replaces a clip of the same name. | ["bucketpack: |
model | object array | The entries that say which clip plays at which moment. See the next table. | |
bone_ | object | Physics for single bones: a pendulum, creature feedback or slime squash. See the table after next. | |
particles | list | Particle emitters. Each can be an object, a script string or a bare particle id. particle, particle_, particle_ and particle are read too, and the lists are joined. | |
dynamic_ | object or list | Swaps one bone's texture, or the whole geometry, by what the held item reports. type (default texture), bone, source (default sulfur_, or axol_), map and fallback. |
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
typeRequired | string | The moment: idle, useDrink and the others on the definitions page. Case, underscores, hyphens and spaces are ignored. | "idle" | |
animation | string | The clip to play. name and var_1 mean the same. If no clip of that name exists, the idle clip plays. | "bucket_ | |
in_water | boolean | The player touching water must equal this. It is true when the player is in water, the eyes are in water or any of 27 points around the body is water. An entry that has the condition scores higher than one that has none. | ||
disable_ | boolean | false | While this entry plays, no particle emitter of that hand emits. |
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
pendulum_ | string or boolean | none | full swings the bone both ways. forward swings it along the view only. A spec needs a mode, enable or enable, or Punchy! drops it. | "full" |
limit_deg | number | 55 | How far the pendulum may swing, in degrees, in both directions. | |
camera_ | number | 0.3 | How strongly turning the camera moves it. | |
gravity | number | 25 | The spring that pulls the pendulum back to rest. It is also part of the damping, so a lower number is softer and a higher one snaps back sooner. | |
motion_ | number | 0.2 | How strongly walking, jumping and landing move it. | |
force | number | 0.75 | Scales the push of the camera. This pack leaves it at the default. | |
speed | number | 16 | Part of the damping. This pack leaves it at the default. | |
enable | boolean | false | Creature style feedback on this bone, like the feedback Punchy! gives a pufferfish bucket: it tilts and squashes with your movement. Also read as creature and puffer. | |
impact | number | 100 | Scales the creature's tilt on the side it leans while you fall or tilt the camera down, from 0 to 100. A value above 100 cannot amplify. | |
fall | number | 100 | Scales the creature's tilt on the other side, the punch of a landing or the camera tilted up, from 0 to 100. |
| Key | Type | Default | What it does | Example |
|---|---|---|---|---|
type | particle id | minecraft: | The particle's name. Punchy! draws its own picture for it, and the type picks the picture. A missing type uses crit; an id with no picture of its own draws the flame picture. | "minecraft: |
bone | string | none | The bone the particle starts at, at the bone's pivot. With no match, it starts at your hand. | |
offset | vector | 0, 0, 0 | Moves the start from the bone, in blocks. 16 pixels make one block. | |
count | integer | 1 | Particles per release, 0 to 120. | |
rate | number | 0 | Releases per second for a steady emitter, 0 to 120. With no triggers and no rate, an emitter releases once per game tick. | |
life | number | 1.1 | How long a particle lives, in seconds, 0.05 to 60. | |
size | number | 0.028 | The starting half width of the particle, 0.001 to 2. | |
spread | vector | 0, 0, 0 | A random scatter of the start, up to this far either way on each axis. | |
velocity | vector | 0, 0, 0 | The starting push, in blocks per tick. | |
gravity | number | 0 | Changes the vertical speed by this much per second, from -2 to 2. A positive number pushes up and a negative one pulls down. Particles anchored to the item work in pixels, so it acts 16 times weaker. | |
triggers | object | Flags such as jump and landing. They must be written as an object. By default every trigger must be true at the same moment. | ||
trigger_ | string | all | any (or or) fires when one trigger is true. Any other value means all. |
Things that drop a whole file
Punchy! prints no message for any of these.
- A definition with a value of the wrong kind. A text where a list belongs, such as
"items": "minecraft:bucket", or a list where one value belongs, such as"in_water": [true], drops the whole definition, and the vanilla bucket shows. A file that is not valid JSON, a missing comma, or noitems,geoortexturedoes the same. - A geometry that cannot load. A file with no
minecraft:geometrylist, a bone without aname, or a number list that holds text, leaves the vanilla bucket in your hand. - A clip that cannot be read. A key with fewer than three numbers, or a key time that is not a number, stops the file at that clip. The clips before it load, and the clips after it do not.
- A wrong id. An id with a capital letter is not valid. A
geoid that points at nothing leaves the vanilla bucket in your hand, and ananimationsid that points at nothing gives a bucket with no motion.
Studio’s Lint panel on the Definition tab names most of these, and the export window counts the errors.
Some smaller mistakes keep the file and fail quietly. A texture animation whose picture is not exactly frames times the frame height tall does not animate and shows the whole picture squeezed onto each face. A definition whose geo points at a missing file still covers its items, so it hides later definitions for them and draws the vanilla bucket.
Why my bucket does not look right
- The vanilla bucket shows. Check that the pack is in Selected, that the files are under
assets/bucketpack/punchy/model_parts_items/, and that the ids in the definition match the folders. Check that Resource Pack Model Parts is on in the Items & World tab of Punchy’s F8 menu, because turning it off turns the whole model parts system off after the next resource reload. In the settings file the key isdisableResourcePackModelParts, which reads the other way round:trueturns model parts off. Press F3+T and wait a second. Model parts draw in your own first person hands only. - The liquid and the fish show in the empty bucket. A bone without an entry in
bone_texturestakes its parent’s texture, then the main texture.liquid,surfaceandfishneed an entry, andclearis the texture that hides them.eyesandtailfollowfish. - The liquid is steel colored. The bone name in
bone_textureshas a typo, or the entry is missing for one of the two liquid bones. - The water does not move.
water.pngis not 64 pixels tall,framesis 1, or only one ofliquidandsurfacehas abone_texture_animentry. The animation uses the exact bone name. - The surface does not slosh. The spec in
bone_physicshas nopendulum_mode, so Punchy! dropped it, or the bone name is notsurface. Turn the camera fast and raiselimit_degto see it. - The lava does not glow. The bone names in
bone_emissionmust match exactly, andstrengthmust not be 0. Check it at night. - No particles. Enable Particle System is off in the Effects tab of Punchy’s F8 menu. Or the entry that is playing has
disable_all_particles, which the empty bucket’s dry entry and the lava’s in-water entry do on purpose. - A splash never fires. A jump and a landing cannot be true together. The emitter needs
"trigger_mode": "any", or two separate emitters. - The model vanishes while I drink. The milk bucket needs its
useDrinkentry. - The clip plays the wrong way. Flip the sign of the rotation keys. In Studio the numbers you key are the numbers in the file. In Blockbench the signs of X and Y rotation and X position are flipped on export, as described in Animate the bucket.
- A clip does not play at all. The name in the entry has a typo, so the idle clip plays instead, or the clip file did not load. See Item clips.
- Another pack’s bucket wins. For unnamed definitions, the one whose id sorts first wins for an item. A definition with a
customNamethat matches the held stack beats any unnamed one, whatever its position. Studio’s Export First in Order puts yours first among the definitions of its namespace. See Which definition covers an item.
Make it your own
- Change the shapes and the colors. Replace a flat texture with a painted one and give the faces real UVs, as in Geometry and textures.
- Add
powder_snow_bucketandtadpole_bucketthe same way, with a texture of your own for each. - Move the bucket in your hand with
display, or shrink it. Model part definitions shows the numbers. - Keep several looks of one bucket and let players choose. Variants and presets shows how.
- Look at how a flame and a torch do the same tricks in Recreate a 3D torch pack.
Related pages
- Model parts overview for how a definition, its files and its extras fit together.
- Model part definitions for every field of a definition.
- Geometry and textures for the Bedrock file, UVs, animated textures and glow.
- Item clips for the clip file and the entries that play it.
- Conditions for water, weather, blocks, time and biomes.
- Particles for every emitter key and trigger.
- Dynamic textures for the axolotl and sulfur cube rules.
- Item physics for pendulum settings in depth.
- Punchy! Studio for the Model workspace and Build from Pack.
- Resource packs for pack order,
pack.mcmetaand reloading.
Last checked against the mod on 30 October 2026.