mojira.dev
MC-310816

Default block states are not stored in their shorthand string format in structure palettes

26.3-snapshot-7 introduces a string format for representing certain block states, which essentially represents a block in its default block state (“The default Block State of a Block can now be referred to in a compact form directly by the Block id“ – snapshot log). This is the code for this new codec:

public class BlockState
extends BlockBehaviour.BlockStateBase {
    private static final Codec<Either<Block, BlockState>> CONSTANT_OR_DISPATCH_CODEC = Codec.either(BuiltInRegistries.BLOCK.byNameCodec(), (Codec)BlockState.codec(BuiltInRegistries.BLOCK.byNameCodec(), Block::defaultBlockState, Block::getStateDefinition).stable());
    public static final Codec<BlockState> CODEC = CONSTANT_OR_DISPATCH_CODEC.xmap(either -> (BlockState)either.map(Block::defaultBlockState, f -> f), state -> state == state.getBlock().defaultBlockState() ? Either.left((Object)state.getBlock()) : Either.right((Object)state));
    // ...
}

The last parameter of xmap suggests that, when writing a block state, it attempts to match the block state with the default block state, and write the compact (string) form in this case. Or at least this is what the piece of code (hopefully) intends to do.

Well, This does not happen.

Presumably something about Java object equality messed up the conditional? Edit: This conjecture is false. Check out the comment by tryashtar for the exact reason.

Steps to Reproduce

  1. Check out any nbt file any structure template file that contains some block states in its definition (e.g. structures/abandoned_camp/camp/camp/bamboo_jungle/campsite_bamboo_jungle_1.nbt)

  2. Check out the block states that are its default block state and their format (e.g. palette[0] and palette[2] for equal-to-default and no properties respectively)

Expected Result

The block states are represented in the compact string format.

Actual Result

The block states are represented in the object format.

Attachments

Comments 4

I should point out that only structure file palettes do not use the shorthand (I updated the issue summary).

All other places do. For example:

/summon minecart ~ ~ ~ {DisplayState:{id:"stone"}}
/data get entity @n[type=minecart] DisplayState

The DisplayState is serialized as merely "stone".

Palettes in region files also use the shorthand (although when serialized, mixed string-compound lists are forced to use the single-entry empty-key compound structure).

Structure templates do not use this codec when writing (or reading), they use NbtUtils.writeBlockState instead.

Palettes in region files also use the shorthand (although when serialized, mixed string-compound lists are forced to use the single-entry empty-key compound structure).

I’m not sure I totally understand the issue but is the single-entry empty-key structure intended? That feels to me like it makes parsing region files more complicated. Here are block states palettes from 2 different y-level sections in the same chunk. One palette has the empty key structure while another does not. Why not be consistent? And why have empty keys?

Screenshot from 2026-08-06 12-02-04.png
Screenshot from 2026-08-06 12-02-19.png

It is intended and is required because binary NBT lists must be homogenous; that is, all values must have the same type

A compliant parser would be expected to detect this case and lift the list into a heterogenous form, then load the values into whatever desired form per the codec.

Cool. Thanks for clarifying. I will update my parser.

dovisutu

(Unassigned)

Confirmed

Platform EC

Low

Save Data

26.3 Snapshot 7, 26.3

Retrieved