User Tools

Site Tools


tutorial:blockentity_modify_data

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_modify_data [2024/08/27 02:28] solidblocktutorial:blockentity_modify_data [2025/04/01 12:48] (current) – [Some notes about NbtCompound] solidblock
Line 3: Line 3:
 In the previous tutorial, we have created a [[blockentity|block entity]]. But they are too boring as they do not have any data. Therefore, we try to add some data to it, and define ways of serializing and deserializing data. In the previous tutorial, we have created a [[blockentity|block entity]]. But they are too boring as they do not have any data. Therefore, we try to add some data to it, and define ways of serializing and deserializing data.
  
 +===== Some notes about NbtCompound =====
 +
 +Since 1.21.5, methods of ''NbtCompound'' have been changed. The getter methods return ''Optional'' objects, unless you specify another parameter as a default value used when the field does not exist. For example:
 +
 +<code java>
 +// no default value specified, returns Optional
 +Optional<Integer> value = nbt.getInt("value"); // not OptionalInt
 +
 +// default value specified, returns the default value when the field does not exist
 +int value = nbt.getInt("value", 1000);
 +</code>
 +
 +For collection types, such as compounds and lists, an empty object can be returned as a default value, for example:
 +<code java>
 +// no default value specified, returns Optional
 +Optional<NbtCompound> config = nbt.getCompound("config");
 +
 +// when the field does not exist, returns an empty compound
 +NbtCompound config = nbt.getCompoundOrEmpty("config");
 +</code>
 +
 +In versions before 1.21.5, they return zero or empty values. If you need to specify a default value, you need to judge with ''contains'' method beforehand. For example:
 +<code java>
 +// returns 0 if the field does not exist:
 +int value = nbt.getInt("value");
 +
 +// returns an empty compound when the field does not exist:
 +NbtCompound config = nbt.getCompound("config");
 +</code>
 +
 +Besides, since 1.21.5, the whole NBT compound and its fields can be decoded directly with [[codec]]s, such as:
 +<code java>
 +NbtCompound nbt = new NbtCompound();
 +nbt.put("Id", Identifier.CODEC, Identifier.of("tutorial", "example_id"));
 +Optional<Identifier> id = nbt.get("Id", Identifier.CODEC);
 +</code>
 +
 +<code java>
 +NbtCompound nbt = new NbtCompound();
 +// have to use the RegistryOps since an item is a registry entry
 +nbt.copyFromCodec(ItemStack.MAP_CODEC, wrapperLookup.getOps(NbtOps.INSTANCE), new ItemStack(Items.WHEAT));
 +Optional<ItemStack> stack = nbt.decode(ItemStack.MAP_CODEC, wrapperLookup.getOps(NbtOps.INSTANCE));
 +</code>
 +
 +Besides, since 1.21.5, lists support mixing elements of different types. In previous versions, mixing elements of different types in a list results in exceptions.
 +
 +More information about NBT changes, see [[https://fabricmc.net/2025/03/24/1215.html|Fabric for Minecraft 1.21.5]].
 ===== Serializing Data ===== ===== Serializing Data =====
  
Line 25: Line 72:
     // Serialize the BlockEntity     // Serialize the BlockEntity
     @Override     @Override
-    public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapper) {+    public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registries) {
         // Save the current value of the number to the nbt         // Save the current value of the number to the nbt
         nbt.putInt("number", number);         nbt.putInt("number", number);
  
-        super.writeNbt(nbt, wrapper);+        super.writeNbt(nbt, registries);
     }     }
 } }
Line 39: Line 86:
     // Deserialize the BlockEntity     // Deserialize the BlockEntity
     @Override     @Override
-    public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapper) { +    public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registries) { 
-        super.readNbt(nbt, wrapper);+        super.readNbt(nbt, registries);
                  
-        number = nbt.getInt("number");+        number = nbt.getInt("number", 0);
     }     }
 </code> </code>
  
-To get the NBT data for the block entity, call ''createNbt(registryLookup)''. It will also handle some data like position and components.+To get the NBT data for the block entity, call ''createNbt(registries)''. It will also handle some data like position and components.
  
 For old versions, calling ''super.readNbt()'' and ''super.writeNbt()'' was essential, because handling data such as positions is required. In old versions, if ''createNbt'' does not exist, try ''writeNbt(new NbtCompound())''. For old versions, calling ''super.readNbt()'' and ''super.writeNbt()'' was essential, because handling data such as positions is required. In old versions, if ''createNbt'' does not exist, try ''writeNbt(new NbtCompound())''.
Line 79: Line 126:
    
     @Override     @Override
-    public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {+    public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registries) {
         nbt.putInt("number", number);         nbt.putInt("number", number);
    
-        super.writeNbt(nbt, registryLookup);+        super.writeNbt(nbt, registries);
     }     }
          
     @Override     @Override
-    public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { +    public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registries) { 
-        super.readNbt(nbt);+        super.readNbt(nbt, registries);
    
-        number = nbt.getInt("number", registryLookup);+        // for versions before 1.21.5, use nbt.getInt("number"); 
 +        number = nbt.getInt("number", 0);
     }     }
 } }
tutorial/blockentity_modify_data.1724725722.txt.gz · Last modified: 2024/08/27 02:28 by solidblock