状态效果与药水
状态效果有时也称药水效果,在代码中称为 MobEffect,会逐刻影响实体。本篇介绍其用法、效果与药水的区别,以及如何添加自己的效果和药水。
术语
MobEffect逐刻影响实体。与方块或物品一样,它是注册表对象,必须注册,且为单例。- 瞬时效果是一种只施加一刻的特殊状态效果。原版有瞬间治疗和瞬间伤害两种。
MobEffectInstance是设置了持续时间、等级及其他属性的效果实例。它与MobEffect的关系,类似ItemStack与Item。Potion是一组MobEffectInstance。原版主要将其用于下文的四种药水物品,但也可按需设置在任何物品上。物品如何使用其上设置的药水,由物品自身决定。- 药水物品是用于承载药水的物品。这是非正式术语,与原版
PotionItem类无关(该类只表示普通药水物品)。Minecraft 当前有药水、喷溅药水、滞留药水和药箭四种;Mod 可以增加更多。
MobEffect
继承 MobEffect 类即可创建自己的效果:
public class MyMobEffect extends MobEffect {
public MyMobEffect(MobEffectCategory category, int color) {
super(category, color);
}
@Override
public boolean applyEffectTick(LivingEntity entity, int amplifier) {
// Apply your effect logic here.
// If this returns false when shouldApplyEffectTickThisTick returns true, the effect will immediately be removed
return true;
}
// Whether the effect should apply this tick. Used e.g. by the Regeneration effect that only applies
// once every x ticks, depending on the tick count and amplifier.
@Override
public boolean shouldApplyEffectTickThisTick(int tickCount, int amplifier) {
return tickCount % 2 == 0; // replace this with whatever check you want
}
// Utility method that is called when the effect is first added to the entity.
// This does not get called again until all instances of this effect have been removed from the entity.
@Override
public void onEffectAdded(LivingEntity entity, int amplifier) {
super.onEffectAdded(entity, amplifier);
}
// Utility method that is called when the effect is added to the entity.
// This gets called every time this effect is added to the entity.
@Override
public void onEffectStarted(LivingEntity entity, int amplifier) {
}
}
与所有注册表对象一样,效果必须注册:
//MOB_EFFECTS is a DeferredRegister<MobEffect>
public static final Holder<MyMobEffect> MY_MOB_EFFECT = MOB_EFFECTS.register("my_mob_effect", () -> new MyMobEffect(
//Can be either BENEFICIAL, NEUTRAL or HARMFUL. Used to determine the potion tooltip color of this effect.
MobEffectCategory.BENEFICIAL,
//The color of the effect particles.
0xffffff
));
MobEffect 也提供为受影响实体添加属性修饰符的默认功能。例如,迅捷效果会为移动速度添加属性修饰符。添加方式如下:
public static final Holder<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) {
// Apply your effect logic here.
}
}
然后照常注册效果。
事件
许多效果在其他位置应用逻辑。例如,漂浮效果在活体实体的移动处理器中实现。Mod 效果通常适合放在事件处理器中应用。NeoForge 也提供了一些相关事件:
MobEffectEvent.Applicable:游戏检查能否向实体应用效果实例时触发,可拒绝或强制向目标添加效果。MobEffectEvent.Added:效果实例加入目标时触发,包含目标先前可能已有的效果实例信息。MobEffectEvent.Expired:效果实例过期,即计时器归零时触发。MobEffectEvent.Remove:效果因过期以外的原因移除时触发,例如喝牛奶或使用命令。
MobEffectInstance
简单来说,MobEffectInstance 就是应用于实体上的效果。调用构造函数创建:
MobEffectInstance instance = new MobEffectInstance(
// The mob effect to use.
MobEffects.REGENERATION,
// The duration to use, in ticks. Defaults to 0 if not specified.
500,
// The amplifier to use. This is the "strength" of the effect, i.e. Strength I, Strength II, etc;
// starting at 0. Defaults to 0 if not specified.
0,
// Whether the effect is an "ambient" effect, meaning it is being applied by an ambient source,
// of which Minecraft currently has the beacon and the conduit. Defaults to false if not specified.
false,
// Whether the effect is visible in the inventory. Defaults to true if not specified.
true,
// Whether an effect icon is visible in the top right corner. Defaults to true if not specified.
true
);
另有多个构造函数重载,分别省略最后 1 至 5 个参数。
说明
MobEffectInstance是可变对象。若需要副本,请调用new MobEffectInstance(oldInstance)。
使用 MobEffectInstance
向实体添加效果实例:
MobEffectInstance instance = new MobEffectInstance(...);
entity.addEffect(instance);
也可以从实体移除效果实例。新实例会覆盖实体上已有的同种 MobEffect 实例,因此一个实体上的每种效果最多只有一个实例。移除时只需指定 MobEffect:
entity.removeEffect(MobEffects.REGENERATION);
说明 效果只能应用于
LivingEntity及其子类,即玩家和生物。物品或投出的雪球等对象无法受其影响。
Potion
调用 Potion 构造函数,传入希望包含的 MobEffectInstance 即可创建药水。例如:
//POTIONS is a DeferredRegister<Potion>
public static final Supplier<Potion> MY_POTION = POTIONS.register("my_potion", () -> new Potion(new MobEffectInstance(MY_MOB_EFFECT, 3600)));
new Potion 接收可变参数,因此可添加任意数量的效果,也可以通过 new Potion() 创建没有任何效果的空药水。原版的粗制药水(awkward)就是这样添加的。
第一个构造参数可以传入药水名称,用于翻译。原版延长版和加强版药水用它保持与基础版相同的名称。该名称不是必填项,省略时会从注册表查询。
PotionContents 提供药水物品的各种辅助方法。药水物品通过 DataComponent#POTION_CONTENTS 存储其 PotionContents。
酿造
添加药水后,相应药水物品就已存在,但生存模式还没有获取途径,下面为其添加酿造配方。
药水通常在酿造台制作。Mojang 尚未为酿造配方提供数据包支持,因此必须通过代码,在 RegisterBrewingRecipesEvent 事件中添加配方:
@SubscribeEvent // on the game event bus
public static void registerBrewingRecipes(RegisterBrewingRecipesEvent event) {
// Gets the builder to add recipes to
PotionBrewing.Builder builder = event.getBuilder();
// Will add brewing recipes for all container potions (e.g. potion, splash potion, lingering potion)
builder.addMix(
// The initial potion to apply to
Potions.AWKWARD,
// The brewing ingredient. This is the item at the top of the brewing stand.
Items.FEATHER,
// The resulting potion
MY_POTION
);
}
来源: NeoForged/Documentation(1.21.1)。中文翻译依据提交
4a680cdd4d15。