Flandre923
972 words
5 minutes
34 能力提供附加

参考#

https://boson.v2mcdev.com/capability/attachcapabilityprovider.html

能力附加提供器#

我们在之前已经讲解了关于Capability的知识,我们也使用了provider不过之前的使用,我们并没有直接处理provider,我们是通过一个lammbd来做的。现在我们要使用这个provider了。

这次的例子是给我们的玩家添加一个新的速度的能力,不过这个能力目前并不以什么实际效果哦,知识为了展示怎么样使用provider,以及怎么给实体添加能力,我们添加一个物品,将玩家的速度的能力等级显示出来。

首先我们来看能力的接口,没什么特别的行为,只有一个方法,要求返回对应的level,这个接口继承了INBTSerializable,代表这个能力需要实现序列化和反序列化的方法。

public interface ISpeedUpCapability extends INBTSerializable<CompoundTag> {
    int getLevel();
}

这是能力的实现类,你应该注意到了我们实现了序列化接口用于将能力的level存储起来,不过这里并不能存起来,我们要在provider中调用这里的方法才行。


/**
 SpeedUpCapability类实现了ISpeedUpCapability接口,用于表示加速能力。
 该类包含一个整数类型的级别(level)属性,表示加速能力的级别。
 */
public class SpeedUpCapability implements ISpeedUpCapability {
    private int level;
    /**
     构造函数,用于创建SpeedUpCapability对象。
     @param level 加速能力的级别
     */
    public SpeedUpCapability(int level) {
        this.level = level;
    }

    /**
     获取加速能力的级别。
     @return 加速能力的级别
     */
    @Override
    public int getLevel() {
        return level;
    }

    /**
     将加速能力序列化为NBT(Named Binary Tag)格式的数据。
     @return 包含加速能力级别的CompoundTag对象
     */
    @Override
    public CompoundTag serializeNBT() {
        CompoundTag compoundNBT = new CompoundTag();
        compoundNBT.putInt("level", this.level);
        return compoundNBT;
    }
    /**
     从NBT格式的数据中反序列化加速能力。
     @param nbt 包含加速能力级别的CompoundTag对象
     */
    @Override
    public void deserializeNBT(CompoundTag nbt) {
        this.level = nbt.getInt("level");
    }

}

这里是创建我们的能力,和我们之前讲解的并没有什么区别。

public class ModCapabilities {
    public static final EntityCapability<ISpeedUpCapability,Void> SPEED_CAPABILITY_HANDLER =
            EntityCapability.createVoid(new ResourceLocation(ExampleMod.MODID,"speed_capability_handler"),
                    ISpeedUpCapability.class);
}

这里是我们的provider实现类。我们还需要实现INBTSerializable接口,真正数据存储在这里。


public class SpeedUpCapabilityProvider implements ICapabilityProvider<Player,Void,ISpeedUpCapability>, INBTSerializable<CompoundTag> {
    /**
    SpeedUpCapabilityProvider类实现了ICapabilityProvider和INBTSerializable接口,
    用于提供和管理玩家的加速能力。
    */
    private ISpeedUpCapability speedUpCapability;
    /**
    获取玩家的加速能力。
    @param entity 玩家实体
    @param context 上下文(未使用)
    @return 玩家的加速能力,如果不存在则创建一个新的加速能力
    */
    @Nullable
    @Override
    public ISpeedUpCapability getCapability(Player Entity, Void context) {
        return this.getOrCreateCapability();
    }
    /**
    获取或创建玩家的加速能力。
    @return 玩家的加速能力
    */
    @Nonnull
    ISpeedUpCapability getOrCreateCapability() {
        if (speedUpCapability == null) {
            Random random = new Random();
            this.speedUpCapability = new SpeedUpCapability(random.nextInt(99) + 1);
        }
        return this.speedUpCapability;
    }
    /**
    将玩家的加速能力序列化为NBT格式的数据。
    @return 包含玩家加速能力的CompoundTag对象
    */
    @Override
    public CompoundTag serializeNBT() {
        return this.getOrCreateCapability().serializeNBT();
    }
    /**
    从NBT格式的数据中反序列化玩家的加速能力。
    @param nbt 包含玩家加速能力的CompoundTag对象
    */
    @Override
    public void deserializeNBT(CompoundTag nbt) {
        this.getOrCreateCapability().deserializeNBT(nbt);
    }
}

好了我们给玩家注册我们的能力了。和之前类似,我们给玩家提供了Speed能力,provider就是我们的那个SpeedUpCapabilityProvider



    @Mod.EventBusSubscriber(modid = ExampleMod.MODID,bus = Mod.EventBusSubscriber.Bus.MOD)
    public static class ModEventBus{

        @SubscribeEvent
        private static void registerCapabilities(RegisterCapabilitiesEvent event) {
            event.registerEntity(ModCapabilities.SPEED_CAPABILITY_HANDLER,
                    EntityType.PLAYER,
                    new SpeedUpCapabilityProvider());
        }
    }

下面我们来看怎么从实体上获得能力,以及使用


public class SpeedUpShowItem extends Item {
    public SpeedUpShowItem() {
        super(new Properties());
    }
    // 很简单,从玩家身上获得能力,调用能力的方法,然后给玩家发送消息。
    @Override
    public InteractionResultHolder<ItemStack> use(Level pLevel, Player pPlayer, InteractionHand pUsedHand) {
        if (!pLevel.isClientSide && pUsedHand == InteractionHand.MAIN_HAND) {
            ISpeedUpCapability capability = pPlayer.getCapability(ModCapabilities.SPEED_CAPABILITY_HANDLER);
            if(capability!=null){
                int level = capability.getLevel();
                pPlayer.sendSystemMessage(Component.literal("speed level:" + level));
            }
        }
        return super.use(pLevel, pPlayer, pUsedHand);
    }
}

好了可以进入游戏拿到物品测试以下了。你也可以退出游戏从进入看看是否正常的level

34 能力提供附加
https://fuwari.vercel.app/posts/minecraft1_20_4/out_34-能力提供附加/
Author
Flandre923
Published at
2024-04-14