#minecraft #nbt #minecraft-server #codec #encode #data #compression

quartz_nbt

提供支持将 Minecraft NBT 数据序列化和反序列化为二进制和字符串形式

10 个版本

0.2.9 2024 年 3 月 19 日
0.2.8 2023 年 6 月 2 日
0.2.7 2023 年 4 月 26 日
0.2.6 2022 年 2 月 27 日
0.1.0 2020 年 12 月 20 日

#387编码

Download history 28/week @ 2024-04-22 16/week @ 2024-04-29 17/week @ 2024-05-06 18/week @ 2024-05-13 38/week @ 2024-05-20 47/week @ 2024-05-27 27/week @ 2024-06-03 27/week @ 2024-06-10 14/week @ 2024-06-17 45/week @ 2024-06-24 21/week @ 2024-07-01 12/week @ 2024-07-08 18/week @ 2024-07-15 47/week @ 2024-07-22 200/week @ 2024-07-29 36/week @ 2024-08-05

303 每月下载量
用于 3 crates

MIT 许可证

230KB
5.5K SLoC

quartz_nbt

Documentation Crates.io

支持对 Minecraft 的 NBT 格式进行编码和解码。该软件包支持 zlib 和 gz 压缩,并提供将 NBT 数据转换为字符串化 NBT (SNBT) 及反之的工具。

这是 Quartz 的独立 NBT 软件包,Quartz 是一个 Rust 实现的 Minecraft 服务器。

用法

查看这里的文档以获取示例。


lib.rs:

支持对 Minecraft 的 NBT 格式进行编码和解码。该软件包支持 zlib 和 gz 压缩,并提供将 NBT 数据转换为字符串化 NBT (SNBT) 及反之的工具。

基本用法

NBT 数据的基本单位是 NbtTag。较大的数据结构通过 NBT 标签的树状复合(哈希映射)和列表(向量)表示。

创建 NBT 数据

let mut compound = NbtCompound::new();
compound.insert("foo", 123);
compound.insert("bar", -3.6f32);

let mut list = NbtList::with_capacity(3);
(1i64..=3).for_each(|x| list.push(x));
compound.insert("list", list);

*compound.get_mut::<_, &mut i32>("foo").unwrap() += 1;

assert!(matches!(compound.get::<_, i32>("foo"), Ok(124)));
assert!(compound.get::<_, f64>("bar").is_err());
assert!(compound.get::<_, &NbtTag>("list").is_ok());

读取和写入 NBT

use quartz_nbt::io::{self, Flavor};
use std::io::Cursor;

let mut compound = NbtCompound::new();
compound.insert("foo", 123);
compound.insert("bar", -3.6f32);

let mut binary: Vec<u8> = Vec::new();
io::write_nbt(&mut binary, Some("root-tag"), &compound, Flavor::Uncompressed);

let read_compound = io::read_nbt(&mut Cursor::new(binary), Flavor::Uncompressed).unwrap();
assert_eq!(read_compound.1, "root-tag"); // The root tag's name is generally unused
assert_eq!(read_compound.0, compound);

查询标签

使用泛型使标签查询过程尽可能无缝,但这也允许发生两种类型的错误:缺少标签(无效键或索引)和标签类型不匹配。因此,在 std 集合等效中通常返回 Option 的方法在此软件包中返回 Result

直接将NBT标签转换为未包装值的错误通过TryFromTryInto表示,由NbtStructureError表示。查询NbtCompoundNbtList的错误由NbtReprError表示,其缩写为“NBT表示错误”。有关详细信息,请参阅错误的文档。

use std::convert::TryFrom;

let tag1: NbtTag = vec![1i8, 2, 3].into();
let tag2: NbtTag = "abcde".into();

assert_eq!(Vec::<i8>::try_from(tag1).unwrap(), vec![1i8, 2, 3]);
assert!(i16::try_from(tag2).is_err()); // Type mismatch
let mut compound = NbtCompound::new();
compound.insert("foo", 123);
compound.insert("bar", -3.6f32);

assert!(compound.get::<_, i32>("fooz").is_err()); // Missing tag
assert!(compound.get::<_, i32>("bar").is_err()); // Type mismatch

集合类型和迭代

NbtCompoundNbtList类型分别围绕MapVec进行包装。由于NbtTag隐藏了实际存储的数据类型,这些包装器提供了将标签解包到具体类型的实用工具。如果需要更多功能,则可以通过调用innerinner_mut和/或into_inner来访问这些包装器管理的内部集合。

列表

Minecraft的NBT规范目前对数组(或Rust中的Vec)有特殊的标签,用于存储i8i32i64。因此,这些类型的vec可以直接转换为NbtTag。所有其他NBT兼容类型必须存储在NbtList中。

可以通过常规查询获取上述特殊列表类型。

let mut compound = NbtCompound::new();
compound.insert("list", vec![10i32, 20, 30]);

compound.get_mut::<_, &mut [i32]>("list")
.unwrap()
.iter_mut()
.for_each(|x| *x /= 10);

let list = compound.get::<_, &[i32]>("list");
assert!(list.is_ok());
assert_eq!(list.unwrap(), [1i32, 2, 3].as_ref());

为NBT列表提供了迭代解包值的实用方法。请参阅iter_mapiter_mut_map

let mut list = NbtList::new();
list.push("abc");
list.push("ijk");
list.push("xyz");

list.iter_mut_map::<&mut String>()
.for_each(|s| s.unwrap().push('!'));

let mut iter = list.iter_map::<&str>();
assert!(matches!(iter.next(), Some(Ok("abc!"))));
assert!(matches!(iter.next(), Some(Ok("ijk!"))));
assert!(matches!(iter.next(), Some(Ok("xyz!"))));
assert!(matches!(iter.next(), None));

可以通过clone_from从迭代器(或将转换为迭代器的任何内容)中克隆数据来创建NBT列表。

let mut list1 = NbtList::new();
list1.push("abc");
list1.push("ijk");
list1.push("xyz");

let list2 = NbtList::clone_from(&["abc", "ijk", "xyz"]);

assert_eq!(list1, list2);

化合物

NbtCompound具有与NbtList相同的实用函数集,除了使用字符串键而不是索引之外。与列表类似,化合物具有iter_mapiter_mut_map实用函数,以及clone_from构造函数。有关更多详细信息,请参阅文档。

字符串化NBT (SNBT)

Minecraft还包含一个名为SNBT的NBT数据字符串编码。此编码基本上是JSON的扩展,具有更严格的类型和更宽松的字符串引号规则。有关更多详细信息,请参阅snbt模块文档。

use quartz_nbt::snbt;

let tag: NbtTag = vec![10i8, 15, 20].into();
assert_eq!(tag.to_snbt(), "[B;10,15,20]");

let mut compound = NbtCompound::new();
compound.insert("short", -10i16);
compound.insert("string", "fizzbuzz");
compound.insert("array", vec![1i64, 1, 2, 3, 5]);

const SNBT: &str = "{short: -10s, string: fizzbuzz, array: [L; 1, 1, 2, 3, 5]}";

assert_eq!(compound, snbt::parse(SNBT).unwrap());

依赖项

~1.7–2.3MB
~49K SLoC