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
FieldRequiredDescription
nameYesMust match a name already registered in block-config.yaml.
texture-overrideNoFull name of another block whose stored texture data this entry replaces, guarded by a variant-count check. See Overrides.
overrideNoFull name of another block this entry’s texture is bound to instead of name — an unguarded overwrite. See Overrides. Prefer texture-override.
tiledNoEnables auto-tiling (see Auto-Tiling). Default: false.
fluid-variationsNoNumber of fill-level frames for a fluid block (see Fluids). Default: 0.
animation-phase-jitterNoIf true, each placed instance of this block animates on its own deterministic phase offset instead of all instances staying in lockstep. Default: false.
tiles-withNoOther block names (this mod’s or another’s) this block tiles seamlessly against. Tiling must be declared on both sides to take effect.
spritesYesOne or more variation entries. At least one required.
sprites[].nameYesVariation name (informational; not currently used to key anything at render time).
sprites[].frame-countYesNumber of animation frames in this variation. 1 for a non-animated block.
sprites[].variation-countYesNumber 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-msNoMilliseconds per frame for uniform timing. Default: 100.
sprites[].block-stateNoWhich block-state this variation is used for (see Block States). Default: 0.
sprites[].loopNotrue (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-msNoPer-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-count wide.
  • Rows — positional sub-variants, stacked top to bottom, variation-count tall, 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.

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.

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
  • name is 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 all sprites fields 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