User Tools

Site Tools


tutorial:blockentity_sync_itemstack

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
tutorial:blockentity_sync_itemstack [2023/06/18 11:15] – created terratutorial:blockentity_sync_itemstack [2024/08/27 02:37] (current) – [Block drops with data] solidblock
Line 3: Line 3:
 ===== Introduction ===== ===== 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.+When you create a block with block entity, 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)]] and [[tutorial:blockentity|BlockEntity]].+In this tutorialwe assume you have created a [[blocks|block]] (and block itemand the [[blockentity|block entity]]and [[blockentity_modify_data|stored data for it]].
  
-===== Block Drops with data =====+===== 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//:+For a block to drop an ''ItemStack'' with the NBT or data components from the ''BlockEntity'' of the broken block, we only need to change the //loot table//
 + 
 +==== For versions since 1.20.5 ==== 
 +As data components have been introduced, you need to store the block entity data in the data components of the block item. This requires you to store nbt data as data components. See [[blockentity_modify_data#using_data_components]] about it. 
 + 
 +**If you'are using versions before 1.21**, replace the word **''loot_table''** with **''loot_tables''** in the path. 
 + 
 +<code JavaScript src/main/resources/data/tutorial/loot_table/blocks/demo_block.json> 
 +
 +  "pools"
 +    { 
 +      "rolls": 1.0, 
 +      "bonus_rolls": 0.0, 
 +      "entries":
 +        { 
 +          "name": "tutorial:demo_block", 
 +          "type": "minecraft:item" 
 +        } 
 +      ], 
 +      "conditions":
 +        { 
 +          "condition": "minecraft:survives_explosion" 
 +        } 
 +      ] 
 +    } 
 +  ], 
 +  "functions":
 +    { 
 +      "source": "block_entity", 
 +      "include":
 +        "tutorial:number" 
 +      ], 
 +      "function": "minecraft:copy_components" 
 +    } 
 +  ] 
 +
 +</code> 
 + 
 +where: 
 +  * ''%%"include"%%'': the IDs of the data component types. 
 + 
 +==== For versions before 1.20.5 ==== 
 +Before version 1.20.5, data components were not introduced. Therefore, just copy nbt.
  
 <code JavaScript src/main/resources/data/tutorial/loot_tables/blocks/demo_block.json> <code JavaScript src/main/resources/data/tutorial/loot_tables/blocks/demo_block.json>
Line 41: Line 83:
 </code> </code>
  
-Where+where
-  * //**source**// is the Tag key String we used in the ''writeNbt'' and ''readNbt'' methods in our ''DemoBlockEntity'' class -- //"number"// +  * ''%%"source"%%'' is the key of the nbt 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"//+  * ''%%"target"%%'' is the hierarchy in the nbt of 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 in the tooltip ===== 
 + 
 +For versions since 1.20.5, to get the BlockEntity's data stored in the item stack, we can use get its data component. 
 + 
 +**For versions since 1.20.5:** 
 +<code java DemoBlock.class> 
 + 
 +public class DemoBlock extends BlockWithEntity { 
 +  
 +    [...] 
 +     
 +    @Override 
 +    public void appendTooltip(ItemStack stack, Item.TooltipContext context, List<Text> tooltip, TooltipType options) { 
 +        final Integer i = stack.get(TutorialDataComponentTypes.NUMBER); 
 +        if (i == null) return; 
 + 
 +        tooltip.add(Text.literal("Number: " + i)); 
 +    } 
 +
 +</code> 
 + 
 +For versions before 1.20.5, we call ''getBlockEntityNbt'', which internally calls ''getSubNbt''
 + 
 +**For versions before 1.20.5:** 
 + 
 +<code java DemoBlock.class> 
 +public class DemoBlock extends BlockWithEntity { 
 +  
 +    [...] 
 +  
 +    @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")) 
 +    } 
 +
 +</code> 
 + 
 +Similarly, you can also modify the ''getName'' method so the data can be displayed directly in the name. In this case, you have to modify how your block item is registered to create ''DemoBlockItem'' instead of ''BlockItem''
 +<code java DemoBlockItem.class> 
 +public class DemoBlockItem extends BlockItem { 
 +  public DemoBlockItem(Block block, Settings settings) { 
 +    super(block, settings); 
 +  } 
 + 
 +  @Override 
 +  public Text getName(ItemStack stack) { 
 +    final MutableText name = Text.translatable(stack.getTranslationKey()); 
 +    if (stack.contains(TutorialDataComponentTypes.NUMBER)) { 
 +      name.append(" - number=" + stack.get(TutorialDataComponentTypes.NUMBER)); 
 +    } 
 +    return name; 
 +  } 
 +
 +</code> 
 + 
 +===== Pick item with data ===== 
 +In Creative Mode, when you pick item (by pressing the mouse wheel) while holding ''Ctrl'', you can get an item stack with all block entity data. However, if you don't press ''Ctrl'', you can only get one without data, unless you modify ''getPickStack'' method in the ''DemoBlock'' class: 
 +<code java> 
 +  @Override 
 +  public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) { 
 +    final ItemStack pickStack = super.getPickStack(world, pos, state); 
 +    final BlockEntity blockEntity = world.getBlockEntity(pos); 
 +    if (blockEntity instanceof DemoBlockEntity demoBlockEntity) { 
 +      pickStack.applyComponentsFrom(demoBlockEntity.createComponentMap()); 
 +    } 
 +    return pickStack; 
 +  } 
 +</code>
  
-To save more fieldsjust add more replace operations (with sourcetarget and op) to the //"ops"// array.+> **Note:** When ''Ctrl'' is not pressed downpick-stack happend only on client side. Thereforeyou should modify ''toUpdatePacket'' and ''toInitialChunkDataNbt'', and call ''updateListeners'' when modifying data (see [[blockentity modify data#sync data from server to client]]).
  
-===== Reading saved data from ItemStack =====+===== Helpful Reference =====
  
 +More examples can bee seen in vanilla codes, such as ''ShulkerBoxBlock'' and ''ShulkerBoxBlockEntity'', which implements ''Nameable'' interface and has code to **save custom names** through ''ItemStack'' and ''BlockEntity''. There are also other useful information:
  
 +  * [[https://minecraft.wiki/w/Loot_table|Loot table page in Minecraft Wiki]]
 +  * [[datagen_loot|Data generation of loot tables]]
  
tutorial/blockentity_sync_itemstack.1687086938.txt.gz · Last modified: 2023/06/18 11:15 by terra