我的世界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一下我们就可以启动游戏了。
这样就可以看到我们的装备了,我直接用的钻石套的贴图,所以和原版的长得一样,可以看到护甲值和韧性都是我们定义的数值,测试一下也能发现耐久度也会发生改变。
穿上全套装备后也可以看到玩家身上成功的添加了我们设置的能力,到此为止我们的装备就添加完成了。
下期预告:下期会试着制作一个模组中的小东西,有指定的功能和耐久,敬请期待吧!