Minecraft(我的世界)中文论坛

 找回密码
 注册(register)
查看: 5566|回复: 16

[插件开发教程] [Tutorial][Bukkit][UD]如何给物品增加NBT数据

[复制链接]
发表于 2017-6-11 08:40:19 | 显示全部楼层 |阅读模式

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x
本帖最后由 602723113 于 2017-8-18 11:01 编辑

NBT

目录:
  • 导读
  • NBT是啥子(如果已经知道了的可以直接跳到下一章)
  • 代码实例
  • Attribute

导读

本教程使用的是 Spigot1.10.2-R0.1-SNAPSHOT 核心
在阅读之前请确保你具有NMSJava基础知识

首在教程开始之前我们需要知道其实BukkitAPI提供了几个可以“设置”NBT的方法,当然其实就只有DisplayName和Lore
  1. //实例化一个物品
  2. ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
  3. ItemMeta im = item.getItemMeta();
  4. im.setDisplayName("§6[ §e§l钻石剑 §6]");
  5. im.setLore(Arrays.asList("展示剑..", "第二行Lore"));
  6. item.setItemMeta(im);
复制代码
输出其NBT:

                               
登录/注册后可看大图

那么既然BukkitAPI没有给我们包装NBT相关的方法那么我们就只能去NMS底层操作啦=w=


什么是NBT

NBT (Named Binary Tag) 是一种基于标签的二进制格式设计,携带大量与少量的附加数据的二进制数据。格式被设计成将数据存储在由各种标记组成的树结构中。
在Minecraft所有的物品中每一项都有一个NBTCompound它包含了[lore(描述), name(展示名), damage value(伤害值), attack_speed(攻击速度), 应该放在哪个物品栏当中(如头盔只能放头部), amount(数量)]

代码实例

那么既然我们要给一个物品增加NBT数据那么我们首先需要一个item
  1. ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
复制代码
之后呢我们需要获取这个物品的nms对象
  1. net.minecraft.server.v1_10_R1.ItemStack nmsItem
  2. = CraftItemStack.asNMSCopy(item);
复制代码
之后我们需要获取该物品的NBT对象,下面我使用了三元运算符
  1. NBTTagCompound compound = (nmsItem.hasTag()) ? nmsItem.getTag()
  2. : new NBTTagCompound();
复制代码
那么我们获取到了物品的NBT对象,我们就可以对其进行set数据了
  1. //下面这个是set的一个使用方法
  2. //我们需要填入一个String和一个NBTBase的实例
  3. compound.set(String dataName, NBTBase data);

  4. //我们可以使用NBT来做一个类似绑定的效果
  5. compound.set("绑定", new NBTTagString("May_Speed"));
  6. //NBTTagString是什么?我给你指条路吧=w=
  7. //拿着反编译工具去nms包下查询NBTTagString这个类所继承了的类
  8. //(好吧其实就是NBTBase)
复制代码
那么我们set好之后只是在一个NBT上set了数据,我们还要把这个NBT给set进物品
  1. nmsItem.setTag(compound);
  2. //之后将nmsItem转换为BukkitAPI中的ItemStack
  3. ItemStack hasNBTItem = CraftItemStack.asBukkitCopy(nmsItem);
复制代码
输出其NBT数据: (图小的可以点开来看)

                               
登录/注册后可看大图

完整代码:


AttributeNBTTag

在一些RPG地图中我们有时会看到这样的武器

                               
登录/注册后可看大图


这个就是一把利用Attribute与NBTTag制造的一把武器=w=
那么我们要怎么利用代码做出这样的效果呢?
  1. //和往常一样我们实例化一个物品
  2. ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
  3. ItemMeta im = item.getItemMeta();
  4. im.setDisplayName("§6[ §e§l战火 §6]");
  5. item.setItemMeta(im);
复制代码
之后获取这个物品的NBT
  1. NBTTagCompound compound =
  2. (nmsItem.hasTag()) ? nmsItem.getTag() : new NBTTagCompound();
复制代码
那么之后我们需要新建一个NBT集合
  1. NBTTagList modifiers = new NBTTagList();
复制代码
之后我们再实例化一个NBT数据出来
  1. NBTTagCompound damage = new NBTTagCompound();
复制代码
之后往里面写入一些数据

  1. //AttributeName指该修改的位置也就是 属性名 (17-8-18修订 嘻嘻嘻)
  2. //Name指该Attribute的名字 可以通过NBTCompound.get(String name)得到
  3. //Amount指该Attribute的属性所修改的的值
  4. //Operation值该Attribute的值是百分比还是数值来算
  5. //  数值为0 百分比为1(7-2号修订=w=)
  6. //UUID是用于区分这些Attribute的建议可以设置大一些
  7. //Slot值该Attribute在玩家的哪个 部位 才会生效,不填写则所有部位都会生效
  8. damage.set("AttributeName", new NBTTagString("generic.attackDamage"));
  9. damage.set("Name", new NBTTagString("Damage"));
  10. damage.set("Amount", new NBTTagInt(20));
  11. damage.set("Operation", new NBTTagInt(0));
  12. damage.set("UUIDLeast", new NBTTagInt(20000));
  13. damage.set("UUIDMost", new NBTTagInt(1000));
  14. damage.set("Slot", new NBTTagString("mainhand"));
复制代码
将刚刚写入好数据的damageNBT给放入NBT集合当中
  1. modifiers.add(damage);
复制代码
之后将此NBT集合数据放入总NBT数据中
  1. compound.set("AttributeModifiers", modifiers);
复制代码
之后和上面的一样进行NBT保存
  1. nmsItem.setTag(compound);
复制代码
看不懂我在说啥?来看图吧=w=

                               
登录/注册后可看大图




一些资源

可以用于ItemStack的 属性名


所有部位的Slot名


想要设置无法破坏?只需要在主NBTTagCompound里面写上



  1. compound.set("Unbreakable", new NBTTagByte((byte) 1));
  2. //1就是开启无法破坏 0就是关闭
复制代码

本教程完工于
2017/6/11 11:30

如需转载请站内PM我
来自群组: Unknown Domain

评分

参与人数 15人气 +22 金粒 +111 收起 理由
936796603 + 2 + 30 神乎其技,不服不行!
hahahahah + 2 很好的资料
ddyy163 + 1 + 15 写的很详细,感谢
V乐乐 + 1 + 15 太细了,赞
dust_of_heart + 2 非常有用,十分感谢
2048028141 + 1 MCBBS有你更精彩~
zhanshi123 + 2 dalao受教了
byxiaobai + 1 MCBBS有你更精彩~
kqn3 + 1 + 5 很棒的作品!
frea + 1 + 15 MCBBS有你更精彩~
1582952890 + 2 MCBBS有你更精彩~
ustc_zzzz + 3 + 25 很棒的作品!
w_cn + 1 + 5 很棒的作品!
1421312987 + 2 很棒的作品!
hurui + 1 厉害了我的哥

查看全部评分

发表于 2018-5-12 14:17:52 | 显示全部楼层
好难。头晕眼花
回复

使用道具 举报

发表于 2018-5-11 19:30:40 | 显示全部楼层
有一个问题,可以回答吗?
这个显示
+ 100伤害(新增)
而不是 100伤害(固定,非新增)
我想实现 固定默认的属性,而不是 +
回复

使用道具 举报

发表于 2018-3-22 19:45:02 | 显示全部楼层
generic.attackDamage    伤害
generic.attackSpeed      攻击速度
generic.maxHealth        生命值上线
generic.movementSpeed   移动速度
generic.armor  护甲
generic.luck  新云

装备的韧性的那个属性是那个
回复

使用道具 举报

发表于 2017-9-16 14:37:08 | 显示全部楼层
版主大大莫老,求该java文件。
回复

使用道具 举报

发表于 2017-9-14 11:18:12 | 显示全部楼层
支持版主 期待更新 萌新一脸萌萌~
回复

使用道具 举报

发表于 2017-9-11 00:29:01 | 显示全部楼层
请问有没有正版版本加入nbt标签的教程

评分

参与人数 1金粒 +1 收起 理由
602723113 + 1 如果是官服的话建议用命令方块,站内也有教.

查看全部评分

回复

使用道具 举报

发表于 2017-9-8 19:46:49 | 显示全部楼层
属性有更简单的添加方法QWQ
回复

使用道具 举报

发表于 2017-8-16 20:38:01 | 显示全部楼层
感谢楼主,非常有用,但是有个小地方似乎写错了把
  1. //AttributeName指该Attribute的名字,可以随意填写
复制代码
这一段里面的
damage.set("AttributeName", new NBTTagString("Damage"));
damage.set("Name", new NBTTagString("generic.attackDamage"));
这两个似乎写反了把#(滑稽)
难道是防伸手党#(坏笑)

评分

参与人数 1人气 +3 金粒 +20 收起 理由
602723113 + 3 + 20 MCBBS有你更精彩~

查看全部评分

回复

使用道具 举报

发表于 2017-8-7 16:11:55 | 显示全部楼层
反馈:
1.9版本以下 AttributeName 的名字必须填写为类型名,不然会无效!
回复

使用道具 举报

发表于 2017-6-27 08:08:35 | 显示全部楼层
好帖,写强化去了~
回复

使用道具 举报

发表于 2017-6-16 20:05:53 | 显示全部楼层
ItemStack可以存储NBT么?
1.7.2R的包
回复

使用道具 举报

发表于 2017-6-11 21:54:02 | 显示全部楼层
本来之前不会用插件的NBT 看完帖子才会
但是这样写必须对应版本
所以我自己改成了用反射执行方法的泛用工具包
回复

使用道具 举报

发表于 2017-6-11 11:58:39 | 显示全部楼层
本帖最后由 SmallFatCYW 于 2017-6-11 12:05 编辑

请教一下,"NMS"是?谢谢
好吧。。。刚刚找到了老外的解释帖子。原来是net.minecraft.server这个包啊
回复

使用道具 举报

发表于 2017-6-11 09:31:23 | 显示全部楼层
萌新一脸懵逼
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册(register)

本版积分规则

Archiver|小黑屋|Mcbbs.net ( 京ICP备15023768号-1 ) | 手机版本

GMT+8, 2018-12-16 19:09 , Processed in 1.040048 second(s), 23 queries , Memcache On.

"Minecraft"以及"我的世界"为Mojang Synergies AB的商标。本站与Mojang以及微软公司没有从属关系。

© 2010-2019 我的世界中文论坛 版权所有。本站原创图文内容版权属于原创作者,未经许可不得转载。

快速回复 返回顶部 返回列表