Block Texture Configuration
Configure block sprite sheets, positional variation, animation, auto-tiling, and fluid fill levels.
Block textures are the most involved texture format in the game: beyond simple sprite animation, they support random positional variants (e.g. a few slightly different grass tiles), animated block-states (e.g. a glow rock that changes appearance), auto-tiling against neighboring blocks (e.g. dirt/grass edges), and fluid fill-level variants. The block itself must already be registered in Block Configuration — texture loading looks it up by name and fails if it isn’t found.
File Location
Config file:
mods/<your-mod>/assets/textures/blocks/blocks.yaml
Texture images go in the same folder:
mods/<your-mod>/assets/textures/blocks/<name>.png
The file name must match the name field exactly (case-sensitive), with spaces kept as spaces in the file name.
Minimal Example
textures:
- name: my_block
sprites:
- name: my_block
frame-count: 1
variation-count: 1
This registers the texture for my_block (a block that must already exist in block-config.yaml) from my_block.png, as a single, non-animated, non-tiled 16×16px tile.
Full Field Reference
textures:
- name: my_block # Required. Must match a name already registered in block-config.yaml
texture-override: Creation:dirt # Optional. Redirect this entry's pixels onto another block (see below)
tiled: false # Optional. Auto-tile against neighboring blocks (see below). Default: false
fluid-variations: 0 # Optional. Number of fill-level variants for a fluid block. Default: 0
animation-phase-jitter: false # Optional. Desync animation timing per-position. Default: false
tiles-with: # Optional. Other block names this block tiles seamlessly with
- other_block
sprites: # Required. One or more variation entries (see below)
- name: my_block # Required. Variation name
frame-count: 1 # Required. Animation frames in this variation
variation-count: 1 # Required. Number of random positional sub-variants
frame-time-ms: 100 # Optional. Milliseconds per frame. Default: 100
block-state: 0 # Optional. Block-state index this variation maps to. Default: 0
loop: true # Optional. Loop the animation? Default: true
frame-durations-ms: # Optional. Per-frame timing override (see below)
- 100
| Field | Required | Description |
|---|---|---|
name | Yes | Must match a name already registered in block-config.yaml. |
emission-strength | No | Finite emission multiplier, 0 to 64; default 0. Seeds bloom with source RGB times this value. Lit materials approach their authored color up to strength 1; higher values strengthen the halo. Independent of point-light strength/radius. Applies to all frames/states; inventory icons and UI do not emit. |
texture-override | No | Full name of another block whose stored texture data this entry replaces, guarded by a variant-count check. See Overrides. |
override | No | Full name of another block this entry’s texture is bound to instead of name — an unguarded overwrite. See Overrides. Prefer texture-override. |
tiled | No | Enables auto-tiling (see Auto-Tiling). Default: false. |
terrain-contour | No | Boolean, default false. Retains the existing 4-by-4 sheet cells for the inward 8px contour band and corners. Requires tiled: true, collidable solid layer-1 terrain, fluid-variations: 0, emission-strength: 0, and exactly one frame with positive positional variants in every sprite entry. Unsupported combinations warn and use ordinary texture rendering. Ordinary rendering uses joined bands with perpendicular thickness in shaped neighborhoods. Square-only neighborhoods retain the original blob tiles. Source data follows both override forms. Cross-cell band transfer requires both materials to opt in and the owner to list the receiver in tiles-with. |
fluid-variations | No | Number of fill-level frames for a fluid block (see Fluids). Default: 0. |
animation-phase-jitter | No | If true, each placed instance of this block animates on its own deterministic phase offset instead of all instances staying in lockstep. Default: false. |
tiles-with | No | Other block names (this mod’s or another’s) this block tiles seamlessly against, or a #tag matching every block carrying that tag. Tiling must be declared on both sides to take effect. |
sprites | Yes | One or more variation entries. At least one required. |
sprites[].name | Yes | Variation name (informational; not currently used to key anything at render time). |
sprites[].frame-count | Yes | Number of animation frames in this variation. 1 for a non-animated block. |
sprites[].variation-count | Yes | Number of random positional sub-variants sharing this animation (e.g. two slightly different-looking dirt tiles). Each placed instance of the block picks one at random. |
sprites[].frame-time-ms | No | Milliseconds per frame for uniform timing. Default: 100. |
sprites[].block-state | No | Which block-state this variation is used for (see Block States). Default: 0. |
sprites[].loop | No | true (default) repeats continuously; false plays a single pass after the block enters this state, then holds the last frame. The same loop boolean the UI button/icon animations use. |
sprites[].frame-durations-ms | No | Per-frame timing override. See Per-Frame Timing. |
Sprite Sheet Format (Non-Tiled)
For a non-tiled block, the sprite sheet is a grid of 16×16px tiles:
- Columns — frames, read left to right,
frame-countwide. - Rows — positional sub-variants, stacked top to bottom,
variation-counttall, in the order variations are declared.
A block with multiple sprites entries stacks each entry’s variation-count rows beneath the previous entry’s, in declaration order — e.g. red_glass (three variation-count: 1 entries, one per block-state) is three single rows stacked directly on top of each other, one per block-state.
Positional Variants
variation-count gives a block several random-looking sub-variants without needing separate block-states or scripting — each time the block is placed, one row is picked at random. This is how DIRT, GRASS, and snowy_grass get slight visual variety:
- name: grass
tiled: true
sprites:
- name: grass
frame-count: 1
variation-count: 2
tiles-with:
- dirt
- snowy_grass
Block States
A single block entry can define multiple sprites, each tagged with a different block-state index. This lets a block change its entire appearance (including its own animation) based on state, driven from Lua/script logic rather than being a fixed animation:
- name: glow_rock
animation-phase-jitter: true
sprites:
- name: glow_rock
frame-count: 3
variation-count: 1
block-state: 0
frame-durations-ms:
- count: 2
duration-ms: 450
- count: 1
duration-ms: 2000
- name: glow_rock_state_1
frame-count: 3
variation-count: 1
frame-time-ms: 300
block-state: 1
- name: glow_rock_state_2
frame-count: 3
variation-count: 1
frame-time-ms: 250
block-state: 2
loop: false
Each block-state value keys its own independent animation timing and frame count.
Per-Frame Timing
Same flat/batch frame-durations-ms format as Mob Texture Configuration, applied per-variation. If the total entries (after expanding batches) don’t equal frame-count exactly, the override is ignored and frame-time-ms is used for all frames instead.
Auto-Tiling
Setting tiled: true makes a block automatically pick a different edge/corner sprite based on which neighboring blocks it’s touching, so blocks like dirt and grass blend into each other without hard seams. The texture for a tiled block is a fixed-layout auto-tile atlas (multiple 16×16px tiles per frame, covering the corner/edge/interior combinations), rather than a single flat tile per frame.
The atlas is a 4×4 grid of 16×16px cells per frame:
| Column 0 | Column 1 | Column 2 | Column 3 | |
|---|---|---|---|---|
| Row 0 | top-left outer corner | top edge | top-right outer corner | vertical strip, top end |
| Row 1 | left edge | centre | right edge | vertical strip, middle |
| Row 2 | bottom-left outer corner | bottom edge | bottom-right outer corner | vertical strip, bottom end |
| Row 3 | top-left inner corner | top-right inner corner | bottom-left inner corner | bottom-right inner corner |
The game builds every neighbour combination (47 shapes, including a lone block, 1-wide strips and any mix of inner corners) from 8×8 quarters of these cells. Each quarter of a placed block is copied from the same quarter of one cell, so the art has to join cleanly along each cell’s horizontal and vertical midlines — a quarter of the top edge must sit next to a quarter of the top-left corner without a seam. Horizontal 1-wide strips are built this way too (top half from the top edge, bottom half from the bottom edge, ends from the outer corners), so directional art such as grass on top stays the right way up. Vertical 1-wide strips use the column-3 cells whole.
Getting this pixel layout exactly right by hand is error-prone — the safest way to build a new tiled block texture is to start from an existing shipped tiled block’s PNG (e.g. DIRT.png, GRASS.png, snowy_grass.png, or the animated anim_dirt.png/water_8.png) as a template and edit the art in place, rather than constructing the tile layout from scratch.
Two blocks only tile seamlessly against each other if both list the other under tiles-with — it’s not automatic in one direction:
- name: dirt
tiled: true
sprites:
- name: dirt
frame-count: 1
variation-count: 2
tiles-with:
- grass
- snowy_grass
- stone
- anim_dirt
A block’s own id is always implicitly included in its own tile-friend set, so identical adjacent blocks always tile together without needing to self-reference.
An entry may also be a #tag reference — tiles-with: ["#ore"] tiles against every block carrying the ore tag, so you don’t have to enumerate each ore block (and it picks up ores added later, or by other mods). Tiling is still two-sided: each of those blocks must also list a tag or name that matches back.
Animated tiled blocks (like anim_dirt) work the same way — the auto-tile atlas is simply repeated once per animation frame.
Fluids
fluid-variations gives a fluid block a number of fill-level frames (e.g. a water block rendered fuller or emptier depending on how much fluid occupies that cell), combined with tiled: true for edge blending against solid ground:
- name: water
fluid-variations: 8
tiled: true
tiles-with:
- dirt
- stone
- grass
sprites:
- name: water_8
frame-count: 2
variation-count: 1
frame-time-ms: 500
Overrides
texture-override redirects this entry’s loaded pixel data and animation data onto another already-registered block’s texture slot, instead of the block named by name. This is how a mod can restyle an existing block (from any mod) without touching that block’s own files:
- name: my_dirt_reskin
texture-override: Creation:dirt
sprites:
- name: my_dirt_reskin
frame-count: 1
variation-count: 2
nameis still required (it locates your replacement PNG in your mod’s folder).- The target block (
texture-override’s value) must already have texture data loaded with at least as many positional variants as your replacement — if your replacement has fewer, the override is skipped. tiled,tiles-with,fluid-variations, and allspritesfields on this entry describe your replacement texture, not the original block’s.
There is also a lower-level override key. Where texture-override keeps this entry bound to its own name block and additionally stamps your pixels onto the target, override rebinds the whole entry to the target block: your PNG (still located by name) is written straight into the named block’s texture slot unconditionally — there is no variant-count guard, so it applies even when your replacement has fewer positional variants than the target (which can leave the target’s extra variants pointing at stale pixels). The override value must be an already-registered block, or the entry is skipped. Prefer texture-override for restyling another block; reach for override only when you specifically want the unguarded overwrite.
Complete Example
Based on the real shipped block textures:
textures:
- name: dirt
tiled: true
sprites:
- name: dirt
frame-count: 1
variation-count: 2
tiles-with:
- grass
- snowy_grass
- stone
- anim_dirt
- name: glow_rock
animation-phase-jitter: true
sprites:
- name: glow_rock
frame-count: 3
variation-count: 1
block-state: 0
frame-durations-ms:
- count: 2
duration-ms: 450
- count: 1
duration-ms: 2000
- name: glow_rock_state_1
frame-count: 3
variation-count: 1
frame-time-ms: 300
block-state: 1
- name: glow_rock_state_2
frame-count: 3
variation-count: 1
frame-time-ms: 250
block-state: 2
loop: false
- name: water
fluid-variations: 8
tiled: true
tiles-with:
- dirt
- stone
- grass
sprites:
- name: water_8
frame-count: 2
variation-count: 1
frame-time-ms: 500
Last updated