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
Check out
any nbt fileany 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)Check out the block states that are its default block state and their format (e.g.
palette[0]andpalette[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
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?
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.
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:
The
DisplayStateis 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.writeBlockStateinstead.