美味的曲奇
参考 https://www.spigotmc.org/threads ... 42387/#post-4036567 此实现
我做出了这个类
[ItemSerializer]https://pastebin.com/k1AiTVqu
[Reflex]https://pastebin.com/e3324Te1
测试环境 1.18.1 paper
他在序列化的时候工作的很好,但是在反序列化解析NBT时时不断的有各种问题
包括不限于找不到方法,返回值不返回 NBTTagCompound 而返回 String(?)
有什么办法能够高效简单的完美序列化物品,完整保留所有NBT数据
* 能不用NMS更好

Neige
本帖最后由 Neige 于 2022-5-13 09:54 编辑

bukkit保存把物品保存进yaml的时候就是无损保存
以及,你发的链接里的那个方法我试了一下,好像没问题()

美味的曲奇
Neige 发表于 2022-5-13 09:45
bukkit保存把物品保存进yaml的时候就是无损保存
以及,你发的链接里的那个方法我试了一下,好像没问题() ...

我记得保存到yaml会丢失未知NBT,而且我想把它序列化成json
你测试的是我剪贴板里的那个吗,好像1.16.5+NMS变了些东西...导致不能用了

Neige
本帖最后由 Neige 于 2022-5-13 10:30 编辑
美味的曲奇 发表于 2022-5-13 10:07
我记得保存到yaml会丢失未知NBT,而且我想把它序列化成json
你测试的是我剪贴板里的那个吗,好像1.16.5+N ...

不会丢失。。。我一直无法理解为什么有人说这个方法无法保存未知NBT。
所有未知NBT都被一层gzip加密一层base64加密以后变成了一段String,存入了ItemMeta中的internal字段。
试一试就知道了,这样序列化反序列化确实是无损的。

我是在1.16.5试的()如果1.16.5+有问题的话那可能真的有问题()

你说的“想序列化成json”说的是想序列化成那种完全可读的json吗?所有未知nbt都能看出来的那种

美味的曲奇
Neige 发表于 2022-5-13 10:28
不会丢失。。。我一直无法理解为什么有人说这个方法无法保存未知NBT。
所有未知NBT都被一层gzip加密一层ba ...

我希望完全序列化为一个json对象 就是现在这个实现所序列化出来的效果
因为这样可读性最高,可以镶套在JSON中可以以独立为*.json,而且理论兼容模组物品

_zZ白熊Zz_
美味的曲奇 发表于 2022-5-13 11:59
我希望完全序列化为一个json对象 就是现在这个实现所序列化出来的效果
因为这样可读性最高,可以镶套在JS ...

要"兼容"的话,那你大概得自己做一个。

此外我推荐 ProtocolLib 的 StreamSerializer

美味的曲奇
_zZ白熊Zz_ 发表于 2022-5-13 12:04
要"兼容"的话,那你大概得自己做一个。

此外我推荐 ProtocolLib 的 StreamSerializer ...

我知道有很多外部库,但是不想挂太多依赖
如果这个继续裂开的话我大概真得去自己实现

_zZ白熊Zz_
美味的曲奇 发表于 2022-5-13 12:18
我知道有很多外部库,但是不想挂太多依赖
如果这个继续裂开的话我大概真得去自己实现 ...

其实 ProtocolLib 已经普及到可以当作和 Bukkit 共生的程度了(

美味的曲奇
_zZ白熊Zz_ 发表于 2022-5-13 12:51
其实 ProtocolLib 已经普及到可以当作和 Bukkit 共生的程度了(

但ProtocolLib 是GPL协议的,有些时候会不太方便

_zZ白熊Zz_
美味的曲奇 发表于 2022-5-13 16:15
但ProtocolLib 是GPL协议的,有些时候会不太方便

这倒是。刚刚注意到是 GPL 2

不过只要把源代码公开(即使不是 GPL 2)就好,自己用的话甚至不需要公开(

Neige
美味的曲奇 发表于 2022-5-13 16:15
但ProtocolLib 是GPL协议的,有些时候会不太方便

Protocollib那个序列化是不可读的()

美味的曲奇
_zZ白熊Zz_ 发表于 2022-5-13 16:29
这倒是。刚刚注意到是 GPL 2

不过只要把源代码公开(即使不是 GPL 2)就好,自己用的话甚至不需要公开( ...

你没注意过GPL协议吗 “ Same license”
也就是基于我插件的其他插件也要开源,怕其他人开发附属的时候顾忌这点

Neige
美味的曲奇 发表于 2022-5-13 16:48
你没注意过GPL协议吗  “ Same license”
也就是基于我插件的其他插件也要开源,怕其他人开发附 ...

其实如果你不介意的话,用taboolib会方便很多。

美味的曲奇
Neige 发表于 2022-5-13 16:59
其实如果你不介意的话,用taboolib会方便很多。

正在用taboolib,但我没发现能直接序列化反序列化NBT的工具

Neige
美味的曲奇 发表于 2022-5-13 17:59
正在用taboolib,但我没发现能直接序列化反序列化NBT的工具

taboolib.module.nms.getItemTag

美味的曲奇
Neige 发表于 2022-5-13 18:07
taboolib.module.nms.getItemTag

我知道能获取物品的标签,也能设置,但是没法直接序列化
怕 ItemStack(xxxxxx).setItemTag 会无法完全覆盖

Neige
美味的曲奇 发表于 2022-5-13 19:02
我知道能获取物品的标签,也能设置,但是没法直接序列化
怕 ItemStack(xxxxxx).setItemTag 会无法完全覆 ...

物品应该就是由id,count和tag组成的吧。你记录一下tag,然后记录一下id和count。
你把tag用toJson转成json,然后你再弄一个差不多类似于
  1. {
  2. id: itemStack.getType(),
  3. count: itemStack.getAmount(),
  4. tag: itemStack.getItemTag().toJson()
  5. }
复制代码

这样的,就差不多了。不行你就toJson以后再解析一下给他转成json对象就完事儿了,存进文件里应该长得很正常

无敌三脚猫
美味的曲奇 发表于 2022-5-13 11:59
我希望完全序列化为一个json对象 就是现在这个实现所序列化出来的效果
因为这样可读性最高,可以镶套在JS ...

(纯外行路过)
插件里用到的nms物品,其实就是原版物品对吧?(或者说,原版有的方法,nms全都有对吧?)
那可以获取物品的nbt,转成string,这就是序列化了,把string转回nbt再转回物品,就是反序列化了(没错吧?)
在1.18来说的话就是,首先你要获取一个net.minecraft.world.item.ItemStack
调用m_41739_,获取nbt,再调用toString,就成了下面这种样子
虽然你不想用nms,但这种形式的可读性真的非常高啊有三四层楼那么高啊
  1. //一个物品
  2. {id:"minecraft:firework_rocket",Count:57b,tag:{Fireworks:{Flight:1b,Explosions:[{Type:4b,Trail:1b,Colors:[I;11743532],FadeColors:[I;14602026]}]}}}
  3. //另一个物品
  4. {id:"minecraft:bow",Count:1b,tag:{RepairCost:1,Damage:0,Enchantments:[{lvl:1s,id:"minecraft:infinity"}]}}
复制代码

把这个string放进net.minecraft.nbt.TagParser的m_129359_方法里重新变回nbt,再把这个nbt放进ItemStack的m_41712_方法里,好,这个字符串就成功的变回物品了

_zZ白熊Zz_
无敌三脚猫 发表于 2022-5-13 19:55
(纯外行路过)
插件里用到的nms物品,其实就是原版物品对吧?(或者说,原版有的方法,nms全都有对吧? ...

这个 m_41739_ 真的不是 fabric 的 yarn 一类的东西吗。。

无敌三脚猫
_zZ白熊Zz_ 发表于 2022-5-13 20:45
这个 m_41739_ 真的不是 fabric 的 yarn 一类的东西吗。。

不是,yarn里的方法都是method_7948这种格式
我听说高版本的nms用的就是官方映射表,所以我才写m_41739_ 这种名字
William_Shi 发表于 2022-4-30 18:40
1.17 开始就没有 NMS 了,因为反混淆表从原先的 BuildData 改成了官方发布的 Mapping
不过好像还是有办法用旧版nms的名字,那就不一样了

William_Shi
无敌三脚猫 发表于 2022-5-13 21:01
不是,yarn里的方法都是method_7948这种格式
我听说高版本的nms用的就是官方映射表,所以我才写m_41739_  ...

高版本插件的工具链不太一样,Special Source 出了一个 Maven 插件,以至于写 Bukkit 插件也可以在开发时使用官方 Mapping ,但是需要重混淆回一个 Spigot 自己的 Mapping。这个中间表不是 NMS。

a760243820
1111111111111

美味的曲奇
无敌三脚猫 发表于 2022-5-13 19:55
(纯外行路过)
插件里用到的nms物品,其实就是原版物品对吧?(或者说,原版有的方法,nms全都有对吧? ...

我正在尝试的就是这个方法,但是为了更好的兼容多版本我使用反射调用NMS,然后....
bug满天飞

结冰的离季
本帖最后由 结冰的离季 于 2022-5-14 13:23 编辑
美味的曲奇 发表于 2022-5-14 07:19
我正在尝试的就是这个方法,但是为了更好的兼容多版本我使用反射调用NMS,然后....
bug满天飞 ...

你都用nms 还用反射了为何不直接使用现成的库
https://github.com/BananaPuncher714/NBTEditor
这个挺轻量的,教程:https://www.spigotmc.org/threads ... le-entities.269621/
  1. //序列化
  2. String json = NBTEditor.getNBTCompound(new ItemStack(Material.ANDESITE)).toString();
  3. //反序列化
  4. ItemStack item = NBTEditor.getItemFromTag(NBTEditor.getNBTCompound(json));
复制代码



美味的曲奇
结冰的离季 发表于 2022-5-14 13:04
你都用nms 还用反射了为何不直接使用现成的库
https://github.com/BananaPuncher714/NBTEditor
这个挺轻量 ...

这个好唉,比我那大面积的try catch强太多了