我的世界1.20.1模组开发---11.添加自定义的装备

介绍

  最近有点其他事情,鸽了一个月没更新,但是这段时间还是对整个mod开发的流程和了解更深了一步,又学到了一些新的东西,等待后续更新。言归正传,这次我们来新增一下自己的装备,前面介绍过了我们自己的武器和工具,这次的装备和之前的差不多,需要我们新建一个自己的材质,这样就可以自定义我们自己的装备的耐久、韧性、护甲值等,甚至还可以添加以下一般游戏中的全套效果。

  这次我们依旧照着源码学习,找到Items类里面,搜索diamond关键字(这次我们以钻石套为例子),然后就可以找到原版中钻石装备的创建,可以看到四件装备都是由一个叫ArmorItem类创建而来的,我们就顺藤摸瓜,进入这个类里面一探究竟。

  图中下面的红色框里是ArmorItem类的一个构造函数,里面怎么实现的我们不需要太过于关注,我们只需要知道该传什么参数给他就行,我们这是再看上面的红色框框,里面是原版创建装备的代码。第一个参数表示装备的材质第二个参数表示的是这个物品是装备的哪一个部分(头盔,胸甲,护腿,鞋子),最后一个参数就是Item属性了,我们直接新建一个即可。由此可见,最后两个属性照着原版的写就行,我们只需要修改第一个装备材质属性即可。

  同样,这里我们进入到ArmorMaterial类里面一探究竟, 同样可以发现这也是一个枚举类型,里面定义了原版游戏中所有的装备材质(皮革、锁链、铁、金、钻石、下届合金等),里面定义了各种装备的属性(耐久、护甲、韧性等),下面我们来具体介绍一下。

  其实基本上我们只需要把原版的代码复制过来,再修改一下数值就行了,这样具体的介绍就结束了,下面上代码。

代码

  首先我们创建一个枚举类型,模仿一下原版的写法,实现StringRepresentable, ArmorMaterial两个接口,把原版的代码全都复制过来,只保留一部分我们的需要的代码。之后我们只需要仿照原版的写法创建一个新的装备材质,这里我创建了一个RED的装备材质。

public enum ModArmorMaterials implements StringRepresentable, ArmorMaterial {
    //创建一个我们自己的装备材质
    RED("red", 40, Util.make(new EnumMap<>(ArmorItem.Type.class), (pConsumer) -> {
        pConsumer.put(ArmorItem.Type.BOOTS, 2);
        pConsumer.put(ArmorItem.Type.LEGGINGS, 4);
        pConsumer.put(ArmorItem.Type.CHESTPLATE, 6);
        pConsumer.put(ArmorItem.Type.HELMET,8);
    }), 15, SoundEvents.ARMOR_EQUIP_LEATHER, 1.0F, 0.0F, () -> {
        return Ingredient.of(ModItems.JIUCHANZHIYUAN.get());
    });

    private static final EnumMap<ArmorItem.Type, Integer> HEALTH_FUNCTION_FOR_TYPE = Util.make(new EnumMap<>(ArmorItem.Type.class), (p_266653_) -> {
        p_266653_.put(ArmorItem.Type.BOOTS, 13);
        p_266653_.put(ArmorItem.Type.LEGGINGS, 15);
        p_266653_.put(ArmorItem.Type.CHESTPLATE, 16);
        p_266653_.put(ArmorItem.Type.HELMET, 11);
    });
    private final String name;
    private final int durabilityMultiplier;
    private final EnumMap<ArmorItem.Type, Integer> protectionFunctionForType;
    private final int enchantmentValue;
    private final SoundEvent sound;
    private final float toughness;
    private final float knockbackResistance;
    private final LazyLoadedValue<Ingredient> repairIngredient;

     ModArmorMaterials(String pName, int pDurabilityMultiplier, EnumMap<ArmorItem.Type, Integer> pProtectionFunctionForType, int pEnchantmentValue, SoundEvent pSound, float pToughness, float pKnockbackResistance, Supplier<Ingredient> pRepairIngredient) {
        this.name = pName;
        this.durabilityMultiplier = pDurabilityMultiplier;//耐久乘数
        this.protectionFunctionForType = pProtectionFunctionForType;// 护甲值
        this.enchantmentValue = pEnchantmentValue;//附魔时可获得稀有附魔的能力
        this.sound = pSound;//穿戴时声音
        this.toughness = pToughness;//韧性
        this.knockbackResistance = pKnockbackResistance;//击退抗性
        this.repairIngredient = new LazyLoadedValue<>(pRepairIngredient);//修复所用材料
    }

    public int getDurabilityForType(ArmorItem.Type pType) {
        return HEALTH_FUNCTION_FOR_TYPE.get(pType) * this.durabilityMultiplier;
    }

    public int getDefenseForType(ArmorItem.Type pType) {
        return this.protectionFunctionForType.get(pType);
    }

    public int getEnchantmentValue() {
        return this.enchantmentValue;
    }

    public SoundEvent getEquipSound() {
        return this.sound;
    }

    public Ingredient getRepairIngredient() {
        return this.repairIngredient.get();
    }

    public String getName() {
        return this.name;
    }

    public float getToughness() {
        return this.toughness;
    }

    public float getKnockbackResistance() {
        return this.knockbackResistance;
    }

    public String getSerializedName() {
        return this.name;
    }
}

  因为我们想实现全套装备有特殊效果,需要继承原版的ArmorItem类,实现我们的功能。我们在item/custom目录下新建一个ModArmor类,这个类继承ArmorItem类。在这个类里面我们要想实现玩家全套效果功能必须重写一个叫onArmorTick方法(前面说过的,想实现什么功能就要重写父类里面的某个方法),这个方法可以每个tick都执行一次,因此我们可以在里面每个tick都对玩家身上的装备进行检查,如果穿的是全套的我们的装备,就给玩家一些能力(夜视、摔落保护等)。具体的可以看注释,整体逻辑并不复杂,照着敲一遍应该就好了。

public class ModArmor extends ArmorItem {

    //用来存放从玩家身上获取到附魔效果
    private Collection<MobEffectInstance> activeEffects;

    public ModArmor(ArmorMaterial pMaterial, Type pType, Properties pProperties) {
        super(pMaterial, pType, pProperties);
        activeEffects=null;
    }

    //每个tick都会执行
    @Override
    public void onArmorTick(ItemStack stack, Level level, Player player) {
        this.activeEffects=player.getActiveEffects();
        //服务端执行逻辑,客户端会被直接拒绝执行移除效果代码
        if(!level.isClientSide()){
            Inventory inventory = player.getInventory();//获取玩家的库存(即背包状态)
            if(isAllEquiped(inventory) && isCorrectEquipment(inventory)){
                //如果玩家身上的效果消失了就再加一次,实现全套一直都有能力的效果
                if(isEffect(player)){
                    //给玩家新增一个能力,需要创建一个能力的实例,第一个参数是能力的类型,第二个是持续时间(tick),第三个就是能力等级(从0开始)
                    player.addEffect(new MobEffectInstance(MobEffects.JUMP,400,2));
                    player.addEffect(new MobEffectInstance(MobEffects.REGENERATION,400,2));
                    player.addEffect(new MobEffectInstance(MobEffects.ABSORPTION,400,2));
                }
            }
        }
    }
    //判断是不是穿上了四件衣服
    private boolean isAllEquiped(Inventory inventory){
        //获得玩家装备槽的所有装备
        ItemStack armor = inventory.getArmor(0);
        ItemStack armor1 = inventory.getArmor(1);
        ItemStack armor2 = inventory.getArmor(2);
        ItemStack armor3= inventory.getArmor(3);
        //判断是不是穿了全套
        return !armor.isEmpty() &&
                !armor1.isEmpty()&&
                !armor2.isEmpty()&&
                !armor3.isEmpty();
    }
    //判断穿的一身衣服是不是我们定义的完整一套
    private boolean isCorrectEquipment(Inventory inventory){
        ArmorItem armor = (ArmorItem) inventory.getArmor(0).getItem();
        ArmorItem armor1 = (ArmorItem)inventory.getArmor(1).getItem();
        ArmorItem armor2 = (ArmorItem)inventory.getArmor(2).getItem();
        ArmorItem armor3= (ArmorItem)inventory.getArmor(3).getItem();
        //判断穿的一套是不是我们自己新加的装备
        return armor.getMaterial()== ModArmorMaterials.RED&&
                armor1.getMaterial()== ModArmorMaterials.RED&&
                armor2.getMaterial()== ModArmorMaterials.RED&&
                armor3.getMaterial()== ModArmorMaterials.RED;
    }
    //判断玩家身上有没有效果
    private boolean isEffect(Player player){
        Map<MobEffect, MobEffectInstance> activeEffectsMap = player.getActiveEffectsMap();
        return activeEffectsMap.isEmpty();
    }
}

   这样我们的准备工作就都结束了,之后就是和前面一样的创建Item的步骤了。

    //ModItems类中注册物品
    //添加盔甲(new的是我们新建的ModArmor类,材质选择新建的RED)
    //头盔
    public static final RegistryObject<Item>RED_HELMET=ITEMS.register("red_helmet",
            //装备材质,装备类型,物品属性
            ()->new ModArmor(ModArmorMaterials.RED, ArmorItem.Type.HELMET,new Item.Properties().stacksTo(1)));
    //胸甲
    public static final RegistryObject<Item>RED_CHESTPLATE=ITEMS.register("red_chestplate",
            ()->new ModArmor(ModArmorMaterials.RED, ArmorItem.Type.CHESTPLATE,new Item.Properties().stacksTo(1)));
    //裤子
    public static final RegistryObject<Item>RED_LEGGINGS=ITEMS.register("red_leggings",
            ()->new ModArmor(ModArmorMaterials.RED, ArmorItem.Type.LEGGINGS,new Item.Properties().stacksTo(1)));

    //鞋子
    public static final RegistryObject<Item>RED_BOOTS=ITEMS.register("red_boots",
            ()->new ModArmor(ModArmorMaterials.RED, ArmorItem.Type.BOOTS,new Item.Properties().stacksTo(1)));
    



    //在ModItemModelGen类添加装备的模型文件
        //盔甲
        itemGenerateModel(ModItems.RED_CHESTPLATE.get(),resourceItem(itemName(ModItems.RED_CHESTPLATE.get())));
        itemGenerateModel(ModItems.RED_HELMET.get(),resourceItem(itemName(ModItems.RED_HELMET.get())));
        itemGenerateModel(ModItems.RED_LEGGINGS.get(),resourceItem(itemName(ModItems.RED_LEGGINGS.get())));
        itemGenerateModel(ModItems.RED_BOOTS.get(),resourceItem(itemName(ModItems.RED_BOOTS.get())));



    //添加语言文件
        //盔甲
        add(ModItems.RED_BOOTS.get(),"Red Boots");
        add(ModItems.RED_CHESTPLATE.get(),"Red Chestplate");
        add(ModItems.RED_HELMET.get(),"Red Helmet");
        add(ModItems.RED_LEGGINGS.get(),"Red Leggings");



    //添加到创造模式物品栏
    //盔甲
    pOutput.accept(ModItems.RED_BOOTS.get());
    pOutput.accept(ModItems.RED_CHESTPLATE.get());
    pOutput.accept(ModItems.RED_HELMET.get());
    pOutput.accept(ModItems.RED_LEGGINGS.get());

  然后把四个装备的贴图放到对应位置即可。

  到目前为止,我们已经完成了四件装备的item的添加,但是有一个问题就是目前我们只设置了装备作为一个item时的材质(即拿在手上,丢在地上,物品栏时),但是我们的装备是需要穿在身上的,所以我们还需要为穿在身上时的装备添加渲染的贴图,不然穿在身上只是一堆马赛克而已。在下图中的目录下把贴图放进去就行,这个贴图我不会画,只好把原版钻石套的拿了过来。

  

  大致是这样命名的,名字可千万别随便起,尽量符合原版代码的命名风格。

  然后RunData一下我们就可以启动游戏了。

  这样就可以看到我们的装备了,我直接用的钻石套的贴图,所以和原版的长得一样,可以看到护甲值和韧性都是我们定义的数值,测试一下也能发现耐久度也会发生改变。

  穿上全套装备后也可以看到玩家身上成功的添加了我们设置的能力,到此为止我们的装备就添加完成了。

  下期预告:下期会试着制作一个模组中的小东西,有指定的功能和耐久,敬请期待吧!

 

posted @ 2023-11-26 17:53  小明同学404  阅读(98)  评论(0编辑  收藏  举报