tutorial:blockentity_modify_data
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tutorial:blockentity_modify_data [2024/08/26 02:04] – [Using data components] solidblock | tutorial:blockentity_modify_data [2025/06/11 16:07] (current) – update 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 '' | ||
| + | |||
| + | <code java> | ||
| + | // no default value specified, returns Optional | ||
| + | Optional< | ||
| + | |||
| + | // default value specified, returns the default value when the field does not exist | ||
| + | int value = nbt.getInt(" | ||
| + | </ | ||
| + | |||
| + | 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< | ||
| + | |||
| + | // when the field does not exist, returns an empty compound | ||
| + | NbtCompound config = nbt.getCompoundOrEmpty(" | ||
| + | </ | ||
| + | |||
| + | 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 '' | ||
| + | <code java> | ||
| + | // returns 0 if the field does not exist: | ||
| + | int value = nbt.getInt(" | ||
| + | |||
| + | // returns an empty compound when the field does not exist: | ||
| + | NbtCompound config = nbt.getCompound(" | ||
| + | </ | ||
| + | |||
| + | 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(" | ||
| + | Optional< | ||
| + | </ | ||
| + | |||
| + | <code java> | ||
| + | NbtCompound nbt = new NbtCompound(); | ||
| + | // have to use the RegistryOps since an item is a registry entry | ||
| + | nbt.copyFromCodec(ItemStack.MAP_CODEC, | ||
| + | Optional< | ||
| + | </ | ||
| + | |||
| + | 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:// | ||
| ===== Serializing Data ===== | ===== Serializing Data ===== | ||
| - | If you want to store any data in your '' | + | If you want to store any data in your '' |
| + | |||
| + | '' | ||
| - | '' | + | In older versions, it was very important to call '' |
| Knowing this, the example below demonstrates saving an integer from your '' | Knowing this, the example below demonstrates saving an integer from your '' | ||
| + | //For versions 1.21.5 and before:// | ||
| <code java DemoBlockEntity.java> | <code java DemoBlockEntity.java> | ||
| public class DemoBlockEntity extends BlockEntity { | public class DemoBlockEntity extends BlockEntity { | ||
| // Store the current value of the number | // Store the current value of the number | ||
| - | private int number = 7; | + | private int number = 0; |
| public DemoBlockEntity(BlockPos pos, BlockState state) { | public DemoBlockEntity(BlockPos pos, BlockState state) { | ||
| Line 23: | Line 73: | ||
| // Serialize the BlockEntity | // Serialize the BlockEntity | ||
| @Override | @Override | ||
| - | public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup | + | public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup |
| // Save the current value of the number to the nbt | // Save the current value of the number to the nbt | ||
| + | super.writeNbt(nbt, | ||
| nbt.putInt(" | nbt.putInt(" | ||
| - | |||
| - | super.writeNbt(nbt, | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | In order to read the data, you will also need to override '' | + | //For versions 1.21.6 and after:// |
| + | <code java> | ||
| + | @Override | ||
| + | public void writeData(WriteView view) { | ||
| + | super.writeData(view); | ||
| + | // Save the current value of the number | ||
| + | view.putInt(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | In order to read the data, you will also need to override '' | ||
| + | |||
| + | //For versions 1.21.5 and before:// | ||
| <code java> | <code java> | ||
| // Deserialize the BlockEntity | // Deserialize the BlockEntity | ||
| @Override | @Override | ||
| - | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup | + | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup |
| - | super.readNbt(nbt, | + | super.readNbt(nbt, |
| | | ||
| - | number = nbt.getInt(" | + | number = nbt.getInt(" |
| } | } | ||
| </ | </ | ||
| - | Once you have implemented the '' | + | //For versions 1.21.6 |
| + | <code java> | ||
| + | @Override | ||
| + | public void readData(ReadView view) { | ||
| + | super.readData(ReadView view); | ||
| + | |||
| + | number = view.getInt(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | To get the NBT data for the block entity, call '' | ||
| + | |||
| + | For old versions, calling | ||
| ===== Sync data from server to client ===== | ===== Sync data from server to client ===== | ||
| Line 60: | Line 133: | ||
| @Override | @Override | ||
| - | public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup | + | public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup |
| - | return createNbt(registryLookup); | + | return createNbt(registries); |
| } | } | ||
| </ | </ | ||
| - | |||
| - | **Warning**: | ||
| <code java DemoBlockEntity.class> | <code java DemoBlockEntity.class> | ||
| Line 76: | Line 147: | ||
| } | } | ||
| + | // The following two methods are changed since 1.21.6, see the examples above. | ||
| @Override | @Override | ||
| - | public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup | + | public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup |
| + | super.writeNbt(nbt, | ||
| nbt.putInt(" | nbt.putInt(" | ||
| - | |||
| - | super.writeNbt(nbt, | ||
| } | } | ||
| | | ||
| @Override | @Override | ||
| - | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup | + | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup |
| - | super.readNbt(nbt); | + | super.readNbt(nbt, registries); |
| - | number = nbt.getInt(" | + | |
| + | | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | Make sure the '' | + | Make sure the '' |
| ===== Modifying the data ===== | ===== Modifying the data ===== | ||
| Line 110: | Line 182: | ||
| demoBlockEntity.number++; | demoBlockEntity.number++; | ||
| player.sendMessage(Text.literal(" | player.sendMessage(Text.literal(" | ||
| + | demoBlockEntity.markDirty(); | ||
| } | } | ||
| } | } | ||
| | | ||
| - | return ActionResult.success(world.isClient); | + | return ActionResult.SUCCESS; |
| } | } | ||
| } | } | ||
| + | </ | ||
| + | |||
| + | The method '' | ||
| + | |||
| + | If you want clients to know the update (for example, they may be need to render, or pick-stack without holding '' | ||
| + | <code java> | ||
| + | world.updateListeners(pos, | ||
| </ | </ | ||
| ===== Using data components ===== | ===== Using data components ===== | ||
| - | Since 1.20.5, you can also use data components to store data. In this case, as data components have codecs that can serialize and deserialize themselves, | + | Since 1.20.5, you can also use data components to store data. This is required if you want to write the data into item stacks. You still need to write '' |
| - | If you want to have a try, //remove// the '' | + | Create |
| <code java TutorialDataComponentTypes.java> | <code java TutorialDataComponentTypes.java> | ||
| Line 155: | Line 235: | ||
| <code java DemoBlockEntity.java> | <code java DemoBlockEntity.java> | ||
| - | // removed the `readNbt` and `writeNbt` methods. | ||
| - | |||
| @Override | @Override | ||
| protected void readComponents(ComponentsAccess components) { | protected void readComponents(ComponentsAccess components) { | ||
| Line 168: | Line 246: | ||
| componentMapBuilder.add(ExampleMod.NUMBER, | componentMapBuilder.add(ExampleMod.NUMBER, | ||
| } | } | ||
| - | </ | ||
| - | Now these components can also be stored normally. If you pick stack (which means press the mouse wheel to the block write pressing '' | + | // For versions 1.21.5 and before: |
| + | @Override | ||
| + | public void removeFromCopiedStackNbt(NbtCompound nbt) { | ||
| + | nbt.remove(" | ||
| + | } | ||
| + | |||
| + | // For versions 1.21.6 and after: | ||
| + | @Override | ||
| + | public void removeFromCopiedStackData(WriteView view) { | ||
| + | view.remove(" | ||
| + | } | ||
| + | </ | ||
| - | In some cases, you can also retain the '' | + | The usage of '' |
tutorial/blockentity_modify_data.1724637858.txt.gz · Last modified: 2024/08/26 02:04 by solidblock