Flandre923
644 words
3 minutes
Neoforge 1.21 item Component教程

Minecraft Item Component#

Item#

如何设置一个item上的DataComponentType的数值:

// Item.properties public <T> Properties component(DataComponentType<T> component, T value) { CommonHooks.validateComponent(value); if (this.components == null) { this.components = DataComponentMap.builder().addAll(DataComponents.COMMON_ITEM_COMPONENTS); } this.components.set(component, value); return this; }
// 同Properties的component设置添加DataComponentType的数值 public static final DeferredItem<Item> RUBY_STAFF=registerItem("ruby_staff", ()-> new RubyStuffItem(new Item.Properties().stacksTo(1).component(ModDataComponents.RUBY_STAFF_DES, List.of("123"))));

获得Item的components

public DataComponentMap components() { return this.components; }

ItemStack#

获得对应的ItemStack的下DataComponentType的对应的数值。

Tool tool = (Tool)stack.get(DataComponents.TOOL); // itemstack

判断是否是食物 判断是否有某个DataComponentType

public UseAnim getUseAnimation(ItemStack stack) { return stack.has(DataComponents.FOOD) ? UseAnim.EAT : UseAnim.NONE; // itemstack } // 通过判断是否有Food的DataComponentType类觉得是否是一个食物。

获得ItemStack所有的components

public DataComponentMap getComponents() { return (DataComponentMap)(!this.isEmpty() ? this.components : DataComponentMap.EMPTY); }

获得Item的components

public DataComponentMap getPrototype() { return !this.isEmpty() ? this.getItem().components() : DataComponentMap.EMPTY; }

对于DataComponentMap​的设置方法

@Nullable public <T> T get(DataComponentType<? extends T> component) { // 通过component的获得对应的DataComponentType的数值 Optional<? extends T> optional = (Optional)this.patch.get(component); return optional != null ? optional.orElse((Object)null) : this.prototype.get(component); } @Nullable public <T> T set(DataComponentType<? super T> component, @Nullable T value) { // 给对应的DataComponentType设置数值 CommonHooks.validateComponent(value); this.ensureMapOwnership(); T t = this.prototype.get(component); Optional optional; if (Objects.equals(value, t)) { optional = (Optional)this.patch.remove(component); } else { optional = (Optional)this.patch.put(component, Optional.ofNullable(value)); } return optional != null ? optional.orElse(t) : t; }

注册和使用#

好了我们来看下怎么注册一个自己的DataComponentType

注册DataComponentType的方法

public class ModDataComponents { public static DeferredRegister<DataComponentType<?>> DATA_COMPONENTS = DeferredRegister.create(Registries.DATA_COMPONENT_TYPE, NeoMafishMod.MODID); public static final DeferredHolder<DataComponentType<?>,DataComponentType<List<String>>> RUBY_STAFF_DES = register( "ruby_staff_des", builder -> builder.persistent(Codec.STRING.listOf()) ); // 注册一个自己的DataComponentType public static final DeferredHolder<DataComponentType<?>,DataComponentType<MyCustomData>> MY_CUSTOM_DATA = register( "my_custom_data", builder -> builder.persistent(MyCustomData.CODEC).networkSynchronized(MyCustomData.STREAM_CODEC) ); private static <T> DeferredHolder<DataComponentType<?>,DataComponentType<T>> register(String name, UnaryOperator<DataComponentType.Builder<T>> builder) { return DATA_COMPONENTS.register(name,()-> builder.apply(DataComponentType.builder()).build()); } public static void register(IEventBus eventBus){ DATA_COMPONENTS.register(eventBus); } }
public record MyCustomData (int color, String name, int nutrition){ // codec 用于序列化和反序列化。 public static Codec<MyCustomData> CODEC = RecordCodecBuilder.create(builder-> { return builder.group(Codec.INT.fieldOf("color").forGetter(MyCustomData::color), Codec.STRING.fieldOf("name").forGetter(MyCustomData::name), Codec.INT.fieldOf("nutrition").forGetter(MyCustomData::nutrition)) .apply(builder, MyCustomData::new); }); // stream codec 用于网络传输 public static StreamCodec<RegistryFriendlyByteBuf,MyCustomData> STREAM_CODEC = new StreamCodec<RegistryFriendlyByteBuf, MyCustomData>() { @Override public MyCustomData decode(RegistryFriendlyByteBuf friendlyByteBuf) { return new MyCustomData(friendlyByteBuf.readInt(),friendlyByteBuf.readUtf(),friendlyByteBuf.readInt()); } @Override public void encode(RegistryFriendlyByteBuf o, MyCustomData myCustomData) { o.writeInt(myCustomData.color()); o.writeUtf(myCustomData.name()); o.writeInt(myCustomData.nutrition()); } }; }

通过item properties 添加我们的DataComponentType对应的数值,以及获得对应的DataComponentType对应的数据。

public class ExampleComponent extends Item { public ExampleComponent() { super(new Properties().component(ModDataComponents.MY_CUSTOM_DATA,new MyCustomData(123,"123",123))); } @Override public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand usedHand) { DataComponentMap components = this.components(); MyCustomData myCustomData = components.get(ModDataComponents.MY_CUSTOM_DATA.get()); Logger logger = Logger.getLogger("ExampleComponent"); if (myCustomData != null) { int color = myCustomData.color(); String name = myCustomData.name(); int nutrition = myCustomData.nutrition(); // 检查 color 和 name 是否为 null // 假设 logger.warning 只接受一个 String 参数 String message = "Color: " + color + ", Name: " + name + ", Nutrition: " + nutrition; logger.warning(message); } else { // 如果 myCustomData 为 null,则记录错误信息 logger.warning("myCustomData is null"); } return super.use(level, player, usedHand); } }

打印输出了

8月 11, 2024 6:10:39 下午 com.mafuyu33.neomafishmod.item.custom.ExampleComponent use 警告: Color: 123, Name: 123, Nutrition: 123 8月 11, 2024 6:10:40 下午 com.mafuyu33.neomafishmod.item.custom.ExampleComponent use 警告: Color: 123, Name: 123, Nutrition: 123

代码#

仓库代码:https://github.com/Flandre923/NeoForgeTutorialmod-Minecraft1.21/tree/itemComponent

Neoforge 1.21 item Component教程
https://fuwari.vercel.app/posts/minecraft1_21_0/minecraft-item-component/
Author
Flandre923
Published at
2024-08-11