The new lock field on container block entities stores an item predicate, but when placed as a block, the block entity decoding fails when the item predicate contains any registry/holder information.
How to reproduce:
Give yourself a chest with the lock component
/give @s chest[lock={items:"minecraft:anvil"}]Inspect the given item
/data get entity @s SelectedItem✔ Notice that the command was valid and that the full lock component is present on the item
Place the chest down
✔ Notice that at this point you can only open the chest when holding an anvil, as expected
Inspect the chest's block entity data
/data get block <coords>❌ Notice that the lock field is not present on the block entity
Re-enter singleplayer for the block entity to lose its lock data during deserialization
❌ Notice that you can open the chest even when not holding an anvil
Repeat the same experiment with a lock predicate that isn't using registry access
/give @s chest[lock={count:4}]✔ Notice that after placing this chest, even after relogging, you can only open it when holding an item stack with count 4
Code analysis:
The reason that decoding the lock field fails is that LockCode#fromTag uses CODEC.decode(NbtOps.INSTANCE, ..), specifically it uses the default NbtOps instance. In contrast, the vault block entity for example constructs a DynamicOps using holderLookupProvider.createSerializationContext(NbtOps.INSTANCE).
Attachments
Comments 3
Added half a step for re-entering singleplayer to actually go through the broken deserialization. An alternative that'll already go through serialization before a world save is
/data merge block ~ ~ ~1 {lock:{items:"minecraft:anvil"}}
Yep, I have this too.