zh_cn:tutorial:blockentity_modify_data
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
zh_cn:tutorial:blockentity_modify_data [2024/08/27 02:28] – solidblock | zh_cn:tutorial:blockentity_modify_data [2025/04/01 12:48] (current) – [关于 NbtCompound 的注意事项] solidblock | ||
---|---|---|---|
Line 3: | Line 3: | ||
在之前的教程,我们创建了[[blockentity|方块实体]],但是这些方块实体太无聊了,没有任何数据。所以我们尝试给它添加一些数据,并定义了序列化和反序列化数据的方块。 | 在之前的教程,我们创建了[[blockentity|方块实体]],但是这些方块实体太无聊了,没有任何数据。所以我们尝试给它添加一些数据,并定义了序列化和反序列化数据的方块。 | ||
+ | ===== 关于 NbtCompound 的注意事项 ===== | ||
+ | |||
+ | 自从 1.21.5 开始,'' | ||
+ | |||
+ | <code java> | ||
+ | // 没有指定默认值,将返回 Optional | ||
+ | Optional< | ||
+ | |||
+ | // 指定默认值,当对应字段不存在时返回这个默认值 | ||
+ | int value = nbt.getInt(" | ||
+ | </ | ||
+ | |||
+ | 对于集合类型,如复合标签和列表,可以返回一个空的对象作为默认值,例如: | ||
+ | <code java> | ||
+ | // 没有指定默认值,将返回 Optional | ||
+ | Optional< | ||
+ | |||
+ | // 当对应字段不存在时,返回空复合标签 | ||
+ | NbtCompound config = nbt.getCompoundOrEmpty(" | ||
+ | </ | ||
+ | |||
+ | 而在 1.21.5 之前,默认都会返回零值或者空白,如果需要指定默认值需要先自行用 '' | ||
+ | <code java> | ||
+ | // 当对应字段不存在时返回 0。 | ||
+ | int value = nbt.getInt(" | ||
+ | |||
+ | // 当对应字段不存在时返回空复合标签。 | ||
+ | NbtCompound config = nbt.getCompound(" | ||
+ | </ | ||
+ | |||
+ | 此外,自从 1.21.5 开始,整个 NBT 复合标签以及里面的字段,可以直接使用 [[codec]] 进行解码,例如: | ||
+ | <code java> | ||
+ | NbtCompound nbt = new NbtCompound(); | ||
+ | nbt.put(" | ||
+ | Optional< | ||
+ | </ | ||
+ | |||
+ | <code java> | ||
+ | NbtCompound nbt = new NbtCompound(); | ||
+ | // 需要使用 RegistryOps,因为物品堆在编码解码时需要访问注册表内容 | ||
+ | nbt.copyFromCodec(ItemStack.MAP_CODEC, | ||
+ | Optional< | ||
+ | </ | ||
+ | |||
+ | 此外,从 1.21.5 开始,列表支持混合不同类型的元素,而在之前的版本中,混入不同类型的元素会导致报错。 | ||
+ | |||
+ | 关于 NBT 变化的更多信息,请参见 [[https:// | ||
===== 序列化数据 ===== | ===== 序列化数据 ===== | ||
Line 25: | Line 72: | ||
// 序列化方块实体 | // 序列化方块实体 | ||
@Override | @Override | ||
- | public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup | + | public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup |
// 将数字的当前值保存到 nbt | // 将数字的当前值保存到 nbt | ||
nbt.putInt(" | nbt.putInt(" | ||
- | super.writeNbt(nbt, | + | super.writeNbt(nbt, |
} | } | ||
} | } | ||
Line 39: | Line 86: | ||
// 反序列化方块实体 | // 反序列化方块实体 | ||
@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(" |
} | } | ||
</ | </ | ||
- | 要获取方块实体的 NBT 数据,调用 '' | + | 要获取方块实体的 NBT 数据,调用 '' |
旧有版本中必须调用 '' | 旧有版本中必须调用 '' | ||
Line 79: | Line 126: | ||
@Override | @Override | ||
- | public void writeNbt(NbtCompound nbt) { | + | public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registries) { |
nbt.putInt(" | nbt.putInt(" | ||
- | super.writeNbt(nbt); | + | super.writeNbt(nbt, registries); |
} | } | ||
| | ||
@Override | @Override | ||
- | public void readNbt(NbtCompound nbt) { | + | public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registries) { |
- | super.readNbt(nbt); | + | super.readNbt(nbt, registries); |
- | number = nbt.getInt(" | + | |
+ | | ||
} | } | ||
} | } | ||
Line 127: | Line 175: | ||
world.updateListeners(pos, | world.updateListeners(pos, | ||
</ | </ | ||
+ | |||
+ | ===== 使用数据组件 ===== | ||
+ | |||
+ | 自从 1.20.5 开始,还可以使用数据组件来存储数据,如果要将数据写入到物品堆,则有必要。你还是需要写 '' | ||
+ | |||
+ | 在单独的 '' | ||
+ | |||
+ | <code java TutorialDataComponentTypes.java> | ||
+ | public class TutorialDataComponentTypes { | ||
+ | public static final ComponentType< | ||
+ | .codec(Codec.INT) | ||
+ | .packetCodec(PacketCodecs.INTEGER)); | ||
+ | |||
+ | public static <T> ComponentType< | ||
+ | return Registry.register(Registries.DATA_COMPONENT_TYPE, | ||
+ | } | ||
+ | |||
+ | public static void initialize() { | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 记得有 '' | ||
+ | <code java ExampleMod.java> | ||
+ | public class ExampleMod implements ModInitializer { | ||
+ | [...] | ||
+ | | ||
+ | @Override | ||
+ | public static void onInitialize() { | ||
+ | [..] | ||
+ | TutorialDataComponentTypes.initialize(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 然后在方块实体中: | ||
+ | |||
+ | <code java DemoBlockEntity.java> | ||
+ | @Override | ||
+ | protected void readComponents(ComponentsAccess components) { | ||
+ | super.readComponents(components); | ||
+ | this.number = components.getOrDefault(ExampleMod.NUMBER, | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | protected void addComponents(ComponentMap.Builder componentMapBuilder) { | ||
+ | super.addComponents(componentMapBuilder); | ||
+ | componentMapBuilder.add(ExampleMod.NUMBER, | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void removeFromCopiedStackNbt(NbtCompound nbt) { | ||
+ | nbt.remove(" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | '' |
zh_cn/tutorial/blockentity_modify_data.1724725724.txt.gz · Last modified: 2024/08/27 02:28 by solidblock