新的附魔
我们试着给剑创建一个叫引爆的附魔。
在 moonfan.mymod.enchantment 包下新建类 EnchantmentIgnite.java
public class EnchantmentIgnite extends Enchantment {
protected EnchantmentIgnite() {
super(Rarity.COMMON, EnumEnchantmentType.WEAPON, new EntityEquipmentSlot[]{EntityEquipmentSlot.MAINHAND});
// 设置非本地化名称
this.setName("ignite_enchantment");
}
}
来看构造器 protected Enchantment(Enchantment.Rarity rarityIn, EnumEnchantmentType typeIn, EntityEquipmentSlot[] slots)
- rarityIn 枚举类,表示附魔的稀有程度,有 COMMON、UNCOMMON、RARE 和 VERY_RARE 四种。
- typeIn 枚举类,表示可以接收该附魔的物品种类,有 ALL、WEAPON、ARMOR 等多种类型。
- slots 枚举类数组,表示被附魔的物品处于何种状态时附魔生效,有 MAINHAND、OFFHAND、FEET、LEGS、CHEST、HEAD 六种。
附魔和物品一样需要注册:
public class EnchantmentLoader {
public static Enchantment ignite = new EnchantmentIgnite();
@SubscribeEvent
public static void registerEnchantment(RegistryEvent.Register<Enchantment> event){
event.getRegistry().register(ignite.setRegistryName("mymod:ignite_enchantment"));
}
}
en_us.lang:
enchantment.ignite_enchantment=Ignite
现在,可以通过 /give 命令或者附魔台得到带有这个附魔的剑了。但附魔本身只规定种类,并不规定其效果,效果的实现需要在需要的地方添加,比如时运和精准采集的效果其实是在 Block 类里判断方块掉落的时候添加的。在进阶部分再作说明。
新的状态效果(药水)
Minecraft 中,状态效果和药水是两个概念,喝了药水可以出现状态效果,而有状态效果不一定要有对应的药水,比如饥饿效果、凋零效果。
我们先创建一个叫类似于中毒的持续扣血效果。
在 moonfan.mymod.potion 包下新建类 PotionInjure.java
public class PotionInjure extends Potion {
protected PotionInjure() {
super(true, 0xffffff);
// 这里是设置的是实际的名称,不是非本地化名称
setPotionName("injured");
}
}
构造器 protected Potion(boolean isBadEffectIn, int liquidColorIn)
- isBadEffectIn 是否是负面效果
- liquidColorIn 状态效果的气泡以及药水瓶(如果有)的RGB颜色值,比如0xffffff
状态效果和物品一样需要注册:
@Mod.EventBusSubscriber
public class PotionLoader {
public static Potion injure = new PotionInjure();
@SubscribeEvent
public static void registerPotion(RegistryEvent.Register<Potion> event){
event.getRegistry().register(injure.setRegistryName("mymod:injure"));
}
}
现在,我们可以用命令 /effect 玩家名 mymod:injure 120 0
来给自己加上Ⅰ级,持续时间120s的 injured 效果了,不知道 harbinger 的教程里是不是把命令打错了。。
药水类型
前面说过,状态效果和药水是两回事,当创建了药水类型后,创造模式药水栏里将会自动添加该药水类型的普通型/喷溅型/滞留型的药水瓶武器栏里会自动添加对应效果的弓箭。喝下一种药水可以获得多种状态效果,因此药水类型可以接收多个状态效果参数:
在PotionLoader里添加事件:
@SubscribeEvent
public static void registerPotionType(RegistryEvent.Register<PotionType> event){
event.getRegistry().register(new PotionType(new PotionEffect(injure)).setRegistryName("mymod:injuring"));
}
其中药水类型的构造器,乱七八糟的变量名大概是MCP项目没有翻译出来?
public PotionType(@Nullable String p_i46740_1_, PotionEffect... p_i46740_2_)
public PotionType(PotionEffect... p_i46739_1_)
- String 类型的参数可以省略,相当于非本地化名称,如果省略或者填 null,自动用注册名作为非本地化名称。
- PotionEffect 类型的参数是一个可变长参数,代表药水触发的一个或多个状态效果。
由于有普通型/喷溅型/滞留型三种药水瓶以及药水效果的弓箭,非本地化键也相应的有 potion.effect./splash_potion.effect./ingering_potion.effect./tipped_arrow.effect. 四个前缀,也就是说创建一个药水类型,在.lang语言文件里要写四条翻译文本。
添加状态效果的实际作用
和附魔不太一样的地方,状态效果并不全都需要在需要的事件监听里独立写逻辑。总结一下,状态效果有三大类:
-
修改状态属性类,比如迟缓/失明/挖掘疲劳/急迫等等,这些是一种对生物自身属性的更改,在构造器里使用
this.registerPotionAttributeModifier()
public Potion registerPotionAttributeModifier(IAttribute attribute, String uniqueId, double ammount, int operation)
- attribute 修改的生物自身属性,可使用 SharedMonsterAttributes 类中的字段
- uniqueId UUID,暂不清楚,参考原版
net/minecraft/potion/Potion.java (432行)
中写的的参数。 - ammount 调整数量,比如-1.0D
- operation 暂不清楚,参考原版 Potion 类中写的的参数。
-
周期性效果类,比如中毒/凋零,这样的状态效果通过重写
performEffect()
和isReady()
实现:@Override public void performEffect(EntityLivingBase entityLivingBaseIn, int amplifier) { entityLivingBaseIn.attackEntityFrom(DamageSource.MAGIC, 6.0f); } @Override public boolean isReady(int duration, int amplifier) { int j = 25 >> amplifier; if (j > 0) { return duration % j == 0;} else { return true;} }
- 在
performEffect()
中写你想周期性触发的任何事情。这里写的意思是生物受到6点魔法(药水)伤害。除了上面写的掉血,你还可以触发爆炸来实现人肉轰炸等等。 - amplifier 指的是药水等级,0为Ⅰ级
- 在
isReady()
中控制触发周期,比如上面就是原版的中毒状态的代码
- 在
其他效果类,比如 ustc_zzzz 教程中的摔落保护效果,属于事件触发,需要监听事件,这里就不展开了,之后再说。
药水合成表
使用 BrewingRecipeRegistry.addRecipe()
创建,同样可以把这个写在上一篇的 Recipes 类构造器里。
public static boolean addRecipe(ItemStack input, ItemStack ingredient, ItemStack output)
- input 药水瓶的位置
- ingredient 地狱疣/火药等配方的位置
- output 产物