生物与药水
生物效果与药水(Mob Effects & Potions)
状态效果(Status Effects),有时被称为药水效果(Potion Effects),在代码中被称为MobEffect
,是每刻(tick)影响实体的效果。本文将解释如何使用它们,效果和药水之间的区别,以及如何添加你自己的MobEffect
。
术语
-
MobEffect
:每刻影响实体的效果。与方块或物品一样,MobEffect
是注册对象,意味着它们必须注册并且是单例。 - 瞬时生物效果(Instant Mob Effect) :一种特殊类型的生物效果,设计为仅应用一瞬。原版有两个瞬时效果:瞬间治疗(Instant Health)和瞬间伤害(Instant Harming)。
-
MobEffectInstance
:MobEffect
的实例,具有持续时间、放大倍数和其他属性(见下文)。MobEffectInstance
与MobEffect
的关系类似于ItemStack
与Item
的关系。 -
Potion
:一组MobEffectInstance
的集合。原版主要将药水用于四种药水物品(见下文),但它们可以随意应用于任何物品。物品是否以及如何使用药水取决于物品本身。 - 药水物品(Potion Item) :一种应该设置药水的物品。这是一个非正式术语,原版的
PotionItem
类与此无关(它指的是“普通”药水物品)。Minecraft 目前有四种药水物品:药水、喷溅药水、滞留药水和药箭;但模组可能会添加更多。
生物效果(MobEffects)
要创建你自己的MobEffect
,扩展MobEffect
类:
public class MyMobEffect extends MobEffect {
public MyMobEffect(MobEffectCategory category, int color) {
super(category, color);
}
@Override
public boolean applyEffectTick(LivingEntity entity, int amplifier) {
// 在这里应用你的效果逻辑。
// 如果此方法返回 false 且 shouldApplyEffectTickThisTick 返回 true,效果将立即被移除
return true;
}
// 效果是否应在当前刻应用。例如,再生效果每 x 刻应用一次,取决于刻计数和放大倍数。
@Override
public boolean shouldApplyEffectTickThisTick(int tickCount, int amplifier) {
return tickCount % 2 == 0; // 替换为你想要的检查
}
// 当效果首次添加到实体时调用的实用方法。
// 在从实体中移除所有此效果的实例之前,不会再次调用此方法。
@Override
public void onEffectAdded(LivingEntity entity, int amplifier) {
super.onEffectAdded(entity, amplifier);
}
// 当效果添加到实体时调用的实用方法。
// 每次将此效果添加到实体时都会调用此方法。
@Override
public void onEffectStarted(LivingEntity entity, int amplifier) {
}
}
与所有注册对象一样,MobEffect
必须注册,如下所示:
// MOB_EFFECTS 是 DeferredRegister<MobEffect>
public static final Supplier<MyMobEffect> MY_MOB_EFFECT = MOB_EFFECTS.register("my_mob_effect", () -> new MyMobEffect(
// 可以是 BENEFICIAL、NEUTRAL 或 HARMFUL。用于确定此效果的工具提示颜色。
MobEffectCategory.BENEFICIAL,
// 效果粒子的颜色。
0xffffff
));
MobEffect
类还提供了向受影响的实体添加属性修饰符的默认功能。例如,速度效果为移动速度添加了属性修饰符。效果属性修饰符的添加方式如下:
public static final Supplier<MyMobEffect> MY_MOB_EFFECT = MOB_EFFECTS.register("my_mob_effect", () -> new MyMobEffect(...)
.addAttributeModifier(Attributes.ATTACK_DAMAGE, ResourceLocation.fromNamespaceAndPath("examplemod", "effect.strength"), 2.0, AttributeModifier.Operation.ADD_VALUE)
);
瞬时生物效果(InstantenousMobEffect)
如果你想创建一个瞬时效果,可以使用辅助类InstantenousMobEffect
而不是常规的MobEffect
类,如下所示:
public class MyMobEffect extends InstantenousMobEffect {
public MyMobEffect(MobEffectCategory category, int color) {
super(category, color);
}
@Override
public void applyEffectTick(LivingEntity entity, int amplifier) {
// 在这里应用你的效果逻辑。
}
}
然后,像平常一样注册你的效果。
事件
许多效果的逻辑在其他地方应用。例如,漂浮效果在实体的移动处理程序中应用。对于模组的MobEffect
,通常有意义在事件处理程序中应用它们。NeoForge 还提供了一些与效果相关的事件:
-
MobEffectEvent.Applicable
:当游戏检查MobEffectInstance
是否可以应用于实体时触发。此事件可用于拒绝或强制将效果实例添加到目标。 -
MobEffectEvent.Added
:当MobEffectInstance
添加到目标时触发。此事件包含有关目标上可能存在的先前MobEffectInstance
的信息。 -
MobEffectEvent.Expired
:当MobEffectInstance
到期(即计时器归零)时触发。 -
MobEffectEvent.Remove
:当效果通过其他方式(例如喝牛奶或通过命令)从实体中移除时触发。
生物效果实例(MobEffectInstances)
MobEffectInstance
简单来说就是应用于实体的效果。创建MobEffectInstance
是通过调用构造函数完成的:
MobEffectInstance instance = new MobEffectInstance(
// 要使用的生物效果。
MobEffects.REGENERATION,
// 要使用的持续时间(以刻为单位)。如果未指定,默认为 0。
500,
// 要使用的放大倍数。这是效果的“强度”,例如力量 I、力量 II 等;从 0 开始。如果未指定,默认为 0。
0,
// 效果是否为“环境”效果,意味着它由环境源应用,Minecraft 目前有信标和潮涌核心。如果未指定,默认为 false。
false,
// 效果是否在物品栏中可见。如果未指定,默认为 true。
true,
// 效果图标是否在右上角可见。如果未指定,默认为 true。
true
);
提供了几个构造函数重载,分别省略最后 1-5 个参数。
注意:MobEffectInstance
是可变的。如果你需要副本,请调用new MobEffectInstance(oldInstance)
。
使用MobEffectInstance
可以将MobEffectInstance
添加到实体中,如下所示:
MobEffectInstance instance = new MobEffectInstance(...);
entity.addEffect(instance);
同样,MobEffectInstance
也可以从实体中移除。由于MobEffectInstance
会覆盖实体上相同MobEffect
的现有MobEffectInstance
,因此每个MobEffect
和实体只能有一个MobEffectInstance
。因此,在移除时指定MobEffect
就足够了:
entity.removeEffect(MobEffects.REGENERATION);
注意:MobEffect
只能应用于LivingEntity
或其子类,即玩家和生物。物品或投掷的雪球等不能被MobEffect
影响。
药水(Potions)
药水是通过调用Potion
的构造函数并传入你希望药水具有的MobEffectInstance
来创建的。例如:
// POTIONS 是 DeferredRegister<Potion>
public static final Supplier<Potion> MY_POTION = POTIONS.register("my_potion", () -> new Potion(new MobEffectInstance(MY_MOB_EFFECT, 3600)));
请注意,new Potion
的参数是一个可变参数(vararg)。这意味着你可以向药水中添加任意数量的效果。这也意味着可以创建空药水,即没有任何效果的药水。只需调用new Potion()
即可!(顺便说一下,原版就是这样添加“尴尬”药水的。)
药水的名称可以作为构造函数的第一个参数传递。它用于翻译;例如,原版中的长效和强效药水变体使用此功能来与它们的基础变体具有相同的名称。名称不是必需的;如果省略,将从注册表中查询名称。
Potion
类提供了与药水物品相关的各种辅助方法。药水物品通过PotionContents
存储其PotionContents
。
酿造(Brewing)
现在你的药水已经添加,药水物品可用于你的药水。然而,在生存模式下无法获得你的药水,所以让我们改变这一点!
药水传统上是在酿造台中制作的。不幸的是,Mojang 没有为酿造配方提供数据包支持,因此我们必须通过代码通过RegisterBrewingRecipesEvent
事件添加我们的配方。如下所示:
// 使用某种方法监听事件
@SubscribeEvent
public static void registerBrewingRecipes(RegisterBrewingRecipesEvent event) {
// 获取要添加配方的构建器
PotionBrewing.Builder builder = event.getBuilder();
// 将为所有容器药水(例如药水、喷溅药水、滞留药水)添加酿造配方
builder.addMix(
// 要应用的初始药水
Potions.AWKWARD,
// 酿造原料。这是酿造台顶部的物品。
Items.FEATHER,
// 结果药水
MY_POTION
);
}