Skip to content

Latest commit

 

History

History
159 lines (106 loc) · 6.51 KB

7-5.md

File metadata and controls

159 lines (106 loc) · 6.51 KB

7-5 附魔、耐久与属性修改

理论部分的最后一章里,我们来讲一些关于物品之前没讲完的内容。

首先,让我们从一个 ItemStack 开始。

ItemStack item = new ItemStack(Material.DIAMOND_AXE);

附魔

要为物品添加附魔相当简单,只看代码你应该也看得懂。

ItemMeta im = item.getItemMeta();
im.addEnchant(Enchantment.DURABILITY, 300, true);
// 耐久 300

addEnchant 方法这样工作:

boolean addEnchant(Enchantment ench, int level, boolean ignoreLimit)

ench 只能取 Enchantment 类中的值,其中包括了所有的原版附魔。

level 是附魔的等级。

ignoreLimit 表示是否突破附魔等级上限,比如上面我们设置的是「耐久 300」,如果不设置 ignoreLimittrue,就会被限制到「耐久 III」。

最后记得返还:

item.setItemMeta(im);

耐久

这里的耐久不是上面的耐久,这里的耐久指的是物品的耐久度,例如钻石镐的耐久度是 1561,即可以挖掘 1561 个方块。

在 Bukkit 中,我们的思路得换过来。Bukkit 不是记录「物品还有多少耐久度」,而是记录「已经损失了多少耐久度」。

要修改耐久度,我们可以这么做:

ItemMeta im = item.getItemMeta();
if (im instanceof Damageable) {
    Damageable dmg = (Damageable) im;
    dmg.setDamage(100);
    item.setItemMeta((ItemMeta) dmg);
}

!> 当心同名
这里的 Damageableorg.bukkit.inventory.meta.Damageable,不是 org.bukkit.entity.Damageable

首先我们判断获得的 ItemMeta 是不是 Damageable 的,如果不是,表明它没有耐久度(如火把)。

如果有,我们通过一次强制类型转换将其转换为 Damageable 对象。

setDamage 方法用于设置已经损失的耐久度,setDamage(100) 表示损失 100 耐久度,对于钻石镐而言,那就是「还可以挖掘 1561 - 100 = 1461」个方块,以此类推。如果设置超过 1561,物品即被损坏。

重复进行 setDamage 没有效果,因为它是「设置」,不是「累加」,如果要累加,需要使用:

dmg.setDamage(dmg.getDamage() + 100);

最后,我们进行一次强制类型转换,将设置耐久后的 ItemMeta 返还回去。

由于 Damageable 接口中并没有 setLore 这样的操作,因此不太好用,在设置耐久后应该重新转换为 ItemMeta 再进行后续处理。


如果要设置物品不可破坏,没必要监听事件并且取消或者恢复耐久,可以直接使用:

im.setUnbreakable(true);

就可以了。

属性修改

要修改诸如攻击速度,玩家移动速度时,可以避免使用 NBT 或者 setWalkSpeed 这样麻烦的方法,我们可以使用属性修改器AttributeModifier)。

一个 AttributeModifier 代表的是「一种算法」,包括了「何时生效」、「数量」、「计算类型」等等。

下面我们以玩家用副手持有我们的钻石剑时提升攻击速度、移动速度和伤害为例,演示 AttributeModifier 的使用方法:

ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
AttributeModifier am = new AttributeModifier(UUID.randomUUID(), "内部名字", 2.2, AttributeModifier.Operation.ADD_SCALAR, EquipmentSlot.OFF_HAND);
AttributeModifier am2 = new AttributeModifier(UUID.randomUUID(), "提升移动速度", 0.2, AttributeModifier.Operation.MULTIPLY_SCALAR_1, EquipmentSlot.OFF_HAND);
AttributeModifier am3 = new AttributeModifier(UUID.randomUUID(), "提升攻击速度", 1.2, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.OFF_HAND);


ItemMeta im = item.getItemMeta();
im.addAttributeModifier(Attribute.GENERIC_ATTACK_DAMAGE, am);
im.addAttributeModifier(Attribute.GENERIC_MOVEMENT_SPEED, am2);
im.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEED, am3);

AttributeModifier 的构造方法如下:

AttributeModifier(
    UUID id,
    String name,
    double amound, 
    AttributeModifier.Operation operation,
    @Nullable
    EquipmentSlot slot
)

五个参数,最后一个可省略,它们分别是:

  • 这个修改器的 ID,通常使用 UUID.randomUUID 随机生成一个
  • 这个修改器的名字,和记分板一样,只是内部名字,不会给玩家显示
  • 数量,这个数值的效果取决于下面的操作
  • 操作,必须取 AttributeModifier.Operation 中的值,可能的取值有三种:
    • ADD_NUMBER 最终加算,直接将指定属性添加指定的值
    • MULTIPLY_SCALAR_1 将指定的数值加上 1 后最终乘算,0.2 相当于 + 20%(1.2 倍),1.2 则相当于 + 120%(2.2 倍)
    • ADD_SCALAR 直接乘算指定的数值,0.4 相当于 - 60%,1.5 相当于 + 50%
  • 生效区域,可选,只能取 EquipmentSlot 中的值,包括:
    • HAND 主手
    • OFF_HAND 副手
    • FEET 脚上
    • LEGS 腿上
    • CHEST 身上
    • HEAD 头上

上面我虽然用了三种不同的算法,但并不是说对应的属性就只能用这种算法,乘算和加算的选取根据插件的设计来决定就好啦。

addAttributeModifier 将属性「应用」到物品上。

第二个参数就是刚刚创建的 AttributeModifier,第一个参数是要修改的属性,只能取 Attribute 中的值,可能的取值很多,这里就不一一列举了,如 GENERIC_MAX_HEALTH 更改最大生命值(「+ XXX 生命上限」),GENERIC_ARMOR 设置盔甲量(「+ XXX 盔甲」)等等,这里我们分别设置了攻击伤害,攻击速度和移动速度。

这里的 AttributeModifier 实际上就和游戏中的「在 XX 时:XXX」一样,看图:

AMF.png

这里实际上就有两个 AttributeModifier,一个修改攻击速度,一个修改攻击伤害,并且只有在主手(EquipmentSlot.HAND)才有效。

虽然上面我创建了三个 AtttributeModifier,但实际上你也可以只用一个,只是我习惯分别设置。

最后别忘了返还!

item.setItemMeta(im);

这样我们就做好了一个拿在副手就可以加速的钻石剑。


笔者认为,到目前为止,你已经具备了开发一个插件需要的全部基础知识,接下来只需要合理利用它们,就可以做出好的插件来了。当然,你还需要学习其它的一些插件,诸如权限系统之类的,但由于这些插件不是 Bukkit 提供的,本教程无法涵盖,还请见谅。你可以查阅它们各自的文档来获取更多信息。