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