本帖最后由 602723113 于 2020-4-15 12:04 编辑
2020/4/15 更新对1.13.2以上BukkitAPI对Attribute的相关操作
目录:
- 导读
- NBT是啥子(如果已经知道了的可以直接跳到下一章)
- 代码实例
- Attribute
|
|
|
本教程使用的是 Spigot1.10.2-R0.1-SNAPSHOT 核心
和 Spigot1.15.2 的核心
在阅读之前请确保你具有NMS与Java基础知识
首在教程开始之前我们需要知道其实BukkitAPI提供了几个可以“设置”NBT的方法,当然其实就只有DisplayName和Lore
- //实例化一个物品
- ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
- ItemMeta im = item.getItemMeta();
- im.setDisplayName("§6[ §e§l钻石剑 §6]");
- im.setLore(Arrays.asList("展示剑..", "第二行Lore"));
- item.setItemMeta(im);
复制代码 输出其NBT:

那么既然BukkitAPI没有给我们包装NBT相关的方法那么我们就只能去NMS底层操作啦=w= |
|
|
NBT (Named Binary Tag) 是一种基于标签的二进制格式设计,携带大量与少量的附加数据的二进制数据。格式被设计成将数据存储在由各种标记组成的树结构中。
在Minecraft所有的物品中每一项都有一个NBTCompound它包含了[lore(描述), name(展示名), damage value(伤害值), attack_speed(攻击速度), 应该放在哪个物品栏当中(如头盔只能放头部), amount(数量)] |
|
|
那么既然我们要给一个物品增加NBT数据那么我们首先需要一个item
- ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
复制代码 之后呢我们需要获取这个物品的nms对象
- net.minecraft.server.v1_10_R1.ItemStack nmsItem
- = CraftItemStack.asNMSCopy(item);
复制代码 之后我们需要获取该物品的NBT对象,下面我使用了三元运算符
- NBTTagCompound compound = (nmsItem.hasTag()) ? nmsItem.getTag()
- : new NBTTagCompound();
复制代码 那么我们获取到了物品的NBT对象,我们就可以对其进行set数据了
- //下面这个是set的一个使用方法
- //我们需要填入一个String和一个NBTBase的实例
- compound.set(String dataName, NBTBase data);
- //我们可以使用NBT来做一个类似绑定的效果
- compound.set("绑定", new NBTTagString("May_Speed"));
- //NBTTagString是什么?我给你指条路吧=w=
- //拿着反编译工具去nms包下查询NBTTagString这个类所继承了的类
- //(好吧其实就是NBTBase)
复制代码 那么我们set好之后只是在一个NBT上set了数据,我们还要把这个NBT给set进物品
- nmsItem.setTag(compound);
- //之后将nmsItem转换为BukkitAPI中的ItemStack
- ItemStack hasNBTItem = CraftItemStack.asBukkitCopy(nmsItem);
复制代码 输出其NBT数据: (图小的可以点开来看)

完整代码:
- ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
- net.minecraft.server.v1_10_R1.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
- compound.set("绑定", new NBTTagString("May_Speed"));
- nmsItem.setTag(compound);
- ItemStack hasNBTItem = CraftItemStack.asBukkitCopy(nmsItem);
复制代码 |
|
|
|
在一些RPG地图中我们有时会看到这样的武器
这个就是一把利用Attribute与NBTTag制造的一把武器=w=
那么我们要怎么利用代码做出这样的效果呢?
这里我要补充的是,在1.13.2版本的时候,BukkitAPI更新了对物品的Attribute的相关操作,相关的commit请点这个链接:点我
此外,如果你事先是不清楚BukkitAPI下 org.bukkit.attribute 的使用方法,我建议你可以看看这个教程
或者看我下面的一些操作,看你能不能看懂吧哈哈哈哈哈哈啊哈哈哈
1.13.2以下的版本 - //和往常一样我们实例化一个物品
- ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
- ItemMeta im = item.getItemMeta();
- im.setDisplayName("§6[ §e§l战火 §6]");
- item.setItemMeta(im);
复制代码 之后获取这个物品的NBT
- NBTTagCompound compound =
- (nmsItem.hasTag()) ? nmsItem.getTag() : new NBTTagCompound();
复制代码 那么之后我们需要新建一个NBT集合
- NBTTagList modifiers = new NBTTagList();
复制代码 之后我们再实例化一个NBT数据出来
- NBTTagCompound damage = new NBTTagCompound();
复制代码 之后往里面写入一些数据
- //AttributeName指该修改的位置也就是 属性名 (17-8-18修订 嘻嘻嘻)
- //Name指该Attribute的名字 可以通过NBTCompound.get(String name)得到
- //Amount指该Attribute的属性所修改的的值
- //Operation值该Attribute的值是百分比还是数值来算
- // 数值为0 百分比为1(7-2号修订=w=)
- //UUID是用于区分这些Attribute的建议可以设置大一些
- //Slot值该Attribute在玩家的哪个 部位 才会生效,不填写则所有部位都会生效
- damage.set("AttributeName", new NBTTagString("generic.attackDamage"));
- damage.set("Name", new NBTTagString("Damage"));
- damage.set("Amount", new NBTTagInt(20));
- damage.set("Operation", new NBTTagInt(0));
- damage.set("UUIDLeast", new NBTTagInt(20000));
- damage.set("UUIDMost", new NBTTagInt(1000));
- damage.set("Slot", new NBTTagString("mainhand"));
复制代码 将刚刚写入好数据的damageNBT给放入NBT集合当中
之后将此NBT集合数据放入总NBT数据中
- compound.set("AttributeModifiers", modifiers);
复制代码 之后和上面的一样进行NBT保存
- nmsItem.setTag(compound);
复制代码 看不懂我在说啥?来看图吧=w=

1.13.2以上的版本
怎么说呢,早在1.13.2版本的时候BukkitAPI就已经更新了,并且相较于上面的方式来说,这种方法更为快捷,方便,同时也不用反射
但是要注意的是,只能编辑Attribute,而不是NBT这一点是要注意的
引入案例:我们现在需要做一个物品,这个物品名字叫 加速火把 当玩家手持它的时候它可以给玩家加速!那么在以前的时候,我们都是 使用Lore或者DisplayName 监听器,然后设置玩家的移速
那么现在我们可以不用这样了!因为好用的API增加了!
首先我们实例化一个火把 - ItemStack torch = new ItemStack(Material.TORCH);
复制代码之后我们获取它的 ItemMeta - ItemMeta itemMeta = torch.getItemMeta();
复制代码为了让它更美观,这里增加一些修饰 - itemMeta.setDisplayName("§f§l[ §a§l加速火把 §f§l]");
- itemMeta.setLore(Lists.newArrayList("§fPY又痒了? 我来给你加加速!"));;
复制代码重点来了,啪啪啪 AttributeModifier modifier = new AttributeModifier(UUID.randomUUID(), "我是加速火把", 0.2D, Operation.ADD_NUMBER, EquipmentSlot.OFF_HAND);
itemMeta.addAttributeModifier(Attribute.GENERIC_MOVEMENT_SPEED, modifier); |
在上方的代码里,我们使用了ItemMeta下的方法 addAttributeModifier,它的参数是长这样的 addAttributeModifier(Attribute attribute, AttributeModifier modifier)
- 第一个参数 attribute,其实是一个枚举,你可以直接在IDE里 Attribute. 就可以看到所有可以操作的属性了
- 第二个参数 modifier,这个就是属性修改器,我们可以在这里设置
- 这个attribute的UUID(UUID.randomUUID())
- 这个attitude的名字("我是加速火把")
- 这个attribute所增加或减少的值(0.2D)
- 增加的方式(Operation)
- 限定物品指定的位置才能生效(EquipmentSlot)
那么在上面我写的是,当这个 加速火把是在 副手手持的时候,就增加 0.2 的速度
最后我们需要把itemMeta设置回物品
- torch.setItemMeta(itemMeta);
复制代码现在让我们来看看成品的效果!
完整代码: ItemStack torch = new ItemStack(Material.TORCH); ItemMeta itemMeta = torch.getItemMeta(); itemMeta.setDisplayName("§f§l[ §a§l加速火把 §f§l]"); itemMeta.setLore(Lists.newArrayList("§fPY又痒了? 我来给你加加速!"));
AttributeModifier modifier = new AttributeModifier(UUID.randomUUID(), "我是加速火把", 0.2D, Operation.ADD_NUMBER, EquipmentSlot.OFF_HAND); itemMeta.addAttributeModifier(Attribute.GENERIC_MOVEMENT_SPEED, modifier);
torch.setItemMeta(itemMeta); |
那么同样的我们也可以利用这种方式给其他的物品增加attribute
下面我写了一个测试代码,方便读者用以测试,代码你可以随意CV
具体使用方法: 为了方便起见,这只是一个测试代码,请使用者在玩家状态下使用这个指令,如果你的指令是其他名字可以自己改成别的,默认指令是test 使用方法: - /test 1 获得所有的物品
- /test 2 查询玩家身上所有的物品的attribute
使用效果:
|
|
|
可以用于ItemStack的 属性名
generic.attackDamage
generic.attackSpeed
generic.maxHealth
generic.movementSpeed
generic.armor
generic.luck
|
所有部位的Slot名
mainhand(主手)
offhand(副手)
feet(脚部)
legs(腿部)
chest(身体)
head(头部)
|
想要设置无法破坏?只需要在主NBTTagCompound里面写上
- compound.set("Unbreakable", new NBTTagByte((byte) 1));
- //1就是开启无法破坏 0就是关闭
复制代码
其实在1.11以上的版本,ItemMeta增加了 unbreakable 的api
你可以直接 ItemMeta.setUnbreakable(true) 来设置
|
|
|
本教程完工于
2017/6/11 11:30
在2020/4/15 更新!
如需转载请站内PM我
[groupid=1181]Unknown Domain[/groupid]