====== Syncing BlockEntity data with ItemStack ====== ===== Introduction ===== 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 [[tutorial:blocks|Block (with BlockItem)]], a [[tutorial:blockentity|BlockEntity]] and a way to [[tutorial:blockentity_modify_data|modify the BlockEntity's data]] for testing purposes. ===== Block Drops with data ===== 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: * //**source**// is the Tag key String we used in the ''writeNbt'' and ''readNbt'' methods in our ''DemoBlockEntity'' class -- //"number"// * //**target**// is the Tag key hierarchy in the dropped ''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. ===== Reading saved data from ItemStack ===== 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 tooltip, TooltipContext context) { NbtCompound nbt = BlockItem.getBlockEntityNbt(stack); if (nbt == null) return; tooltip.add(Text.literal("Number: "+nbt.getInt("number")) } } ===== Changing ItemStack's BlockEntity data===== 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 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")) } } ===== Placing Block with data ===== **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''. ===== Helpful Reference ===== 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''. ==== Loot Tables ==== More info on Loot tables on [[https://minecraft.wiki/w/Loot_table|Minecraft Wiki]]. Vanilla loot tables: .minecraft\versions\//[version]//\//[version]//.jar\data\minecraft\loot_tables\ Also, this [[https://misode.github.io/loot-table/|Loot Table Generator]] might be useful.