22 个重大版本发布

0.27.0 2023 年 4 月 6 日
0.25.0 2022 年 4 月 15 日
0.23.1 2021 年 12 月 29 日
0.21.0 2021 年 7 月 17 日
0.6.0 2020 年 7 月 15 日

#2144 in 编码

MIT/Apache

3.5MB
15K SLoC

fastnbt 项目

fastnbt-shield fastnbt-version-shield fastnbt-docs-shield build-status-shield

fastsnbt-shield fastsnbt-version-shield fastsnbt-docs-shield

fastanvil-shield fastanvil-version-shield fastanvil-docs-shield

FastNBT 是一个 serde 序列化和反序列化器,用于 Minecraft: Java Edition 的 NBT 格式,包括 Value 类型以及 nbt! 宏。有关字符串化 NBT(sNBT)信息,请参阅 FastSNBT。

FastAnvil 允许渲染世界地图,并提供用于使用区域文件格式的 Region 结构。支持从 1.20 到 1.13 的版本,对 1.12 的支持略有缺陷。

下面是一个使用浏览器中的 Rust-to-WASM 驱动的 Minecraft 地图渲染器演示。

演示

owengage.com/anvil 上可以看到 Hermitcraft 第 8 季和其他演示。

alt rendered map

来自 fastnbt-toolsanvil 二进制文件可以充分利用您的 CPU 渲染您的世界。

示例

可以在 fastnbt/examplesfastanvil/examplestools/src 中找到许多示例。以下是一些示例。

示例:编辑 level.dat

以下代码将世界出生点更改为 250, 200, 250(可能不是一个好主意!)。完整示例在 fastnbt/examples 目录中。

#[derive(Serialize, Deserialize)]
struct LevelDat {
    #[serde(rename = "Data")]
    data: Data,
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Data {
    spawn_x: i32,
    spawn_y: i32,
    spawn_z: i32,

    #[serde(flatten)]
    other: HashMap<String, Value>,
}

fn main() {
    let args: Vec<_> = std::env::args_os().collect();
    let file = std::fs::File::open(&args[1]).unwrap();
    let mut decoder = GzDecoder::new(file);
    let mut bytes = vec![];
    decoder.read_to_end(&mut bytes).unwrap();

    let mut leveldat: LevelDat = fastnbt::from_bytes(&bytes).unwrap();

    leveldat.data.spawn_x = 250;
    leveldat.data.spawn_y = 200;
    leveldat.data.spawn_z = 250;

    let new_bytes = fastnbt::to_bytes(&leveldat).unwrap();
    let outfile = std::fs::File::create("level.dat").unwrap();
    let mut encoder = GzEncoder::new(outfile, Compression::fast());
    encoder.write_all(&new_bytes).unwrap();
}

示例:打印玩家库存

此示例演示如何从世界中的 玩家数据文件 打印出玩家的库存和末影箱内容。我们

  • 使用 serde 的重命名属性来使 rustfmt 符合字段名称,
  • 使用生存期来节省字符串分配,并且
  • 使用 Value 类型来反序列化我们未指定确切结构的字段。
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct PlayerDat<'a> {
    data_version: i32,

    #[serde(borrow)]
    inventory: Vec<InventorySlot<'a>>,
    ender_items: Vec<InventorySlot<'a>>,
}

#[derive(Deserialize, Debug)]
struct InventorySlot<'a> {
    id: &'a str,        // We avoid allocating a string here.
    tag: Option<Value>, // Also get the less structured properties of the object.

    // We need to rename fields a lot.
    #[serde(rename = "Count")]
    count: i8,
}

fn main() {
    let args: Vec<_> = std::env::args().skip(1).collect();
    let file = std::fs::File::open(args[0].clone()).unwrap();

    // Player dat files are compressed with GZip.
    let mut decoder = GzDecoder::new(file);
    let mut data = vec![];
    decoder.read_to_end(&mut data).unwrap();

    let player: Result<PlayerDat> = from_bytes(data.as_slice());

    println!("{:#?}", player);
}

用法

对于库

[dependencies]
fastnbt = "2"
fastanvil = "0.31"

对于 anvil 可执行文件

cargo install fastnbt-tools

依赖项

~20–32MB
~311K SLoC