# Rendering and Models


> **Documentation baseline:** VoxelCore `main` at `452b569` · 14 September 2026.  
> **Repository:** [https://github.com/VoxelHorizons/VoxelCore](https://github.com/VoxelHorizons/VoxelCore)


Rendering metadata is **presentation state**, not item identity. A ContentID should remain stable even when its model, Custom Model Data allocation or client representation changes.

## Common render metadata

```yaml
render:
  model: mypack:item/ruby
  unbreakable: true
  durability: 4
  attributes:
    hide_attributes: true
  custom_model_data: 1001
```

### Durability and CMD are independent

`render.durability` is not an alias for Custom Model Data. For 1.12/1.13 legacy pack generation, explicit durability drives damage predicates. Runtime Custom Model Data has no representation on those versions and is ignored there rather than being repurposed.

### Item flags

`render.attributes` currently maps author-facing keys to Bukkit `ItemFlag` values; it is **not** the future combat `AttributeModifier` system. Names are normalised to enum-style constants and unsupported flags on an older runtime are ignored. Compatibility aliases remain for historically different Bukkit names such as enchantment/destroyable/placeable hiding.

## Structured Custom Model Data

Minecraft 1.21.4 and 26.2 use the modern item adapter and can represent structured Custom Model Data:

```yaml
render:
  model: mypack:item/ruby
  custom_model_data:
    variant: red
    powered: true
    intensity: 0.75
    tint: '#ff0000'
```

Value type inference:

| YAML value | Allocated component kind |
|---|---|
| number | float |
| boolean | flag |
| ordinary string | string |
| `#RRGGBB` | color |

VoxelCore stores stable semantic-key → typed-index allocation in `render-allocations.yml`; authors do not manually manage list indices.

## Modern render rules

`render.rule` defines the generated modern item-model decision graph. Supported node types are `select`, `condition`, `range` and `model`.

```yaml
render:
  model: mypack:item/ruby
  custom_model_data:
    variant: red
    powered: true
    intensity: 0.75
    tint: '#ff0000'
  rule:
    select:
      key: variant
      cases:
        red:
          condition:
            key: powered
            true:
              range:
                key: intensity
                entries:
                  0.75:
                    model:
                      id: mypack:item/ruby_powered
                      tint: tint
                fallback: mypack:item/ruby
            false: mypack:item/ruby
      fallback: mypack:item/ruby
```

Pre-1.21.4 pack targets reject `render.rule` instead of silently discarding it.

## Asset resolution

`mypack:item/ruby` resolves to `assets/mypack/models/item/ruby.json`. A texture reference with the same logical path resolves beneath `assets/mypack/textures/item/ruby.png`. Cross-pack model references are dependency checked.
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9