When you create a Block
with BlockEntity
, you might want to place the block with predefined Nbt data from an ItemStack
(of your BlockItem
), or save the BlockEntity
data in the ItemStack
after breaking the block.
Before proceeding, you will need a Block (with BlockItem), a BlockEntity and a way to modify the BlockEntity's data for testing purposes.
For a block to drop an ItemStack
with the Nbt from the BlockEntity
of the broken block, we only need to change the loot table:
{ "type": "minecraft:block", "pools": [ { "rolls": 1.0, "entries": [ { "type": "minecraft:item", "name": "tutorial:demo_block", "functions": [ { "function": "minecraft:copy_nbt", "source": "block_entity", "ops": [ { "source": "number", "target": "BlockEntityTag.number", "op": "replace" } ] } ] } ] } ] }
Where:
writeNbt
and readNbt
methods in our DemoBlockEntity
class – “number”ItemStack
(source prefixed with the “BlockEntityTag” key, which is needed for placing the block back with the saved data) – “BlockEntityTag.number”To save more fields, just add more replace operations (with source, target and op) to the “ops” array.
To get the BlockEntity's Nbt, we can use the helper BlockItem.getBlockEntityNbt(stack)
method, which just calls stack.getSubNbt(BLOCK_ENTITY_TAG_KEY)
internally. (BLOCK_ENTITY_TAG_KEY being “BlockEntityTag”, already mentioned in the loot table).
public class DemoBlock extends Block implements BlockEntityProvider { [...] @Override public void appendTooltip(ItemStack stack, BlockView world, List<Text> tooltip, TooltipContext context) { NbtCompound nbt = BlockItem.getBlockEntityNbt(stack); if (nbt == null) return; tooltip.add(Text.literal("Number: "+nbt.getInt("number")) } }
We can change our tooltip to always display some default value even if the stack does not have any BlockEntity data.
public class DemoBlock extends Block implements BlockEntityProvider { [...] @Override public void appendTooltip(ItemStack stack, BlockView world, List<Text> tooltip, TooltipContext context) { NbtCompound nbt = BlockItem.getBlockEntityNbt(stack); if (nbt == null){ NbtCompound nbt = new NbtCompound(); nbt.putInt("number", 0); BlockItem.setBlockEntityNbt(stack, ExampleMod.DEMO_BLOCK_ENTITY, nbt); } tooltip.add(Text.literal("Number: "+nbt.getInt("number")) } }
Is automatic! As long as the data is in the “BlockEntityTag” subNbt (e.g. by using the BlockItem.getBlockEntityNbt
and BlockItem.setBlockEntityNbt
helper methods) under tag keys recognized by the readNbt
method of the BlockEntity
.
If something still isn't clear or you want more examples, I highly recommend looking at the Minecraft implementation of ShulkerBoxBlock
and ShulkerBoxBlockEntity
. That for example also implements Nameable
interface and has code to save custom names through ItemStack
and BlockEntity
.
More info on Loot tables on Minecraft Wiki.
Vanilla loot tables: .minecraft\versions\[version]\[version].jar\data\minecraft\loot_tables\
Also, this Loot Table Generator might be useful.