理论部分的最后一章里,我们来讲一些关于物品之前没讲完的内容。
首先,让我们从一个 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」,如果不设置 ignoreLimit
为 true
,就会被限制到「耐久 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);
}
!> 当心同名!
这里的 Damageable
是 org.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」一样,看图:
这里实际上就有两个 AttributeModifier
,一个修改攻击速度,一个修改攻击伤害,并且只有在主手(EquipmentSlot.HAND
)才有效。
虽然上面我创建了三个 AtttributeModifier
,但实际上你也可以只用一个,只是我习惯分别设置。
最后别忘了返还!
item.setItemMeta(im);
这样我们就做好了一个拿在副手就可以加速的钻石剑。
笔者认为,到目前为止,你已经具备了开发一个插件需要的全部基础知识,接下来只需要合理利用它们,就可以做出好的插件来了。当然,你还需要学习其它的一些插件,诸如权限系统之类的,但由于这些插件不是 Bukkit 提供的,本教程无法涵盖,还请见谅。你可以查阅它们各自的文档来获取更多信息。