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

Both sides previous revisionPrevious revision
Next revision
Previous revision
tutorial:blockentity_sync_itemstack [2024/08/26 02:21] – [For versions before 1.20.5] fix typo solidblocktutorial:blockentity_sync_itemstack [2024/08/27 02:37] (current) – [Block drops with data] solidblock
Line 5: Line 5:
 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. 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.
  
-In this tutorial, we assume you have created a [[block]] (and block item) and the [[blockentity|block entity]], and [[blockentity_modifying_data|stored data for it]].+In this tutorial, we assume you have created a [[blocks|block]] (and block item) and 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 ==== ==== For versions since 1.20.5 ====
Line 89: Line 89:
 To save more fields, just add more replace operations (with source, target and op) to the ''%"ops"%%'' array. To save more fields, just add more replace operations (with source, target and op) to the ''%"ops"%%'' array.
  
-===== Reading saved data from ItemStack =====+===== Reading saved data in the tooltip =====
  
-To get the BlockEntity'**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//).+For versions since 1.20.5, to get the BlockEntity'data stored in the item stack, we can use get its data component.
  
-<code java> +**For versions since 1.20.5:** 
-public class DemoBlock extends Block implements BlockEntityProvider {+<code java DemoBlock.class> 
 + 
 +public class DemoBlock extends BlockWithEntity {
    
     [...]     [...]
- +    
     @Override     @Override
-    public void appendTooltip(ItemStack stack, BlockView world, List<Text> tooltip, TooltipContext context) { +    public void appendTooltip(ItemStack stack, Item.TooltipContext context, List<Text> tooltip, TooltipType options) { 
-        NbtCompound nbt BlockItem.getBlockEntityNbt(stack); +        final Integer i stack.get(TutorialDataComponentTypes.NUMBER); 
-        if (nbt == null) return;+        if (== null) return;
  
-        tooltip.add(Text.literal("Number: "+nbt.getInt("number"))+        tooltip.add(Text.literal("Number: " + i));
     }     }
 } }
 </code> </code>
  
-===== Changing ItemStack's BlockEntity data=====+For versions before 1.20.5, we call ''getBlockEntityNbt'', which internally calls ''getSubNbt''.
  
-We can change our tooltip to always display some default value even if the stack does not have any BlockEntity data.+**For versions before 1.20.5:**
  
-<code java> +<code java DemoBlock.class
-public class DemoBlock extends Block implements BlockEntityProvider {+public class DemoBlock extends BlockWithEntity {
    
     [...]     [...]
Line 120: Line 122:
     public void appendTooltip(ItemStack stack, BlockView world, List<Text> tooltip, TooltipContext context) {     public void appendTooltip(ItemStack stack, BlockView world, List<Text> tooltip, TooltipContext context) {
         NbtCompound nbt = BlockItem.getBlockEntityNbt(stack);         NbtCompound nbt = BlockItem.getBlockEntityNbt(stack);
-        if (nbt == null)+        if (nbt == null) return;
-            NbtCompound nbt = new NbtCompound(); +
-            nbt.putInt("number", 0); +
-             +
-            BlockItem.setBlockEntityNbt(stack, ExampleMod.DEMO_BLOCK_ENTITY, nbt); +
-        }+
  
-        tooltip.add(Text.literal("Number: "+nbt.getInt("number"))+        tooltip.add(Text.literal("Number: " + nbt.getInt("number"))
     }     }
 } }
 </code> </code>
  
-===== Placing Block with data =====+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); 
 +  }
  
-**Is automatic!** As long as the data is in the //"BlockEntityTag"// subNbt (e.gby using the ''BlockItem.getBlockEntityNbt'' and ''BlockItem.setBlockEntityNbt'' helper methodsunder tag keys recognized by the ''readNbt'' method of the ''BlockEntity''.+  @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>
  
-===== Helpful Reference =====+===== 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>
  
-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''.+> **Note:** When ''Ctrl'' is not pressed down, pick-stack happend only on client sideTherefore, you should modify ''toUpdatePacket'' and ''toInitialChunkDataNbt''and call ''updateListeners'' when modifying data (see [[blockentity modify data#sync data from server to client]]).
  
-==== Loot Tables ==== +===== Helpful Reference =====
- +
- +
-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\+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:
  
-Also, this [[https://misode.github.io/loot-table/|Loot Table Generator]] might be useful.+  * [[https://minecraft.wiki/w/Loot_table|Loot table page in Minecraft Wiki]] 
 +  * [[datagen_loot|Data generation of loot tables]]
  
tutorial/blockentity_sync_itemstack.1724638899.txt.gz · Last modified: 2024/08/26 02:21 by solidblock