Перейти к содержимому

Разбор SNBT в своем проекте

WIP: пока не реализовано или реализовано частично. Следите: #321

В этом туториале вы подключите один крейт mcrs к своему Rust-проекту, прочитаете им строку SNBT, посмотрите на теги и запишете их обратно. SNBT - текстовая форма NBT, та самая, которую набирают в командах, например {Health:20.0f}. Программа занимает около пятнадцати строк, и меньшего примера работы с крейтом mcrs снаружи репозитория нет.

Добавьте в Cargo.toml оба крейта как git-зависимости с одним и тем же rev:

[dependencies]
mcrs_minecraft_snbt = { git = "https://github.com/andreypfau/mcrs", rev = "51d45c26ae772bd71fb1e02caae8cab2e5ad4495" }
mcrs_minecraft_nbt = { git = "https://github.com/andreypfau/mcrs", rev = "51d45c26ae772bd71fb1e02caae8cab2e5ad4495" }

Всегда указывайте rev, потому что релизов на crates.io нет, а main двигается с каждым снапшотом игры. Одинаковый rev у двух крейтов нужен потому, что типы тегов, которые возвращает mcrs_minecraft_snbt, приходят из mcrs_minecraft_nbt.

Еще понадобится nightly-компилятор. Репозиторий закрепляет nightly-2026-09-02 в rust-toolchain.toml, но этот файл действует только внутри чекаута mcrs, так что nightly для своего проекта вы выбираете сами. Собирается ли mcrs_minecraft_snbt еще и на stable, никто не проверял. Сборка на stable входит в работу, после которой крейты можно будет публиковать.1

Оба крейта входят в список тех, что CI собирает без Bevy, поэтому Bevy эта зависимость не подтянет. Убедиться в этом можно командой cargo tree со страницы Использование крейтов в своем проекте.

Положите этот код в src/main.rs:

use mcrs_minecraft_nbt::tag::NbtTag;
use mcrs_minecraft_snbt::{parse_compound, write};
fn main() {
let compound = parse_compound("{Health:20.0f, Name:\"Alex\", Pos:[1.5d, 64.0d, -3.0d]}")
.expect("valid SNBT");
println!("{:?}", compound.get_string("Name")); // Some("Alex")
println!("{:?}", compound.get("Health")); // Some(Float(20.0))
// Bad input gives an error with a key and a position, not a panic.
let error = parse_compound("{Health:}").unwrap_err();
println!("{error}");
// Writing gives the text the game would write.
println!("{}", write(&NbtTag::Compound(compound)));
}

Программа разбирает compound, то есть тег NBT, который хранит именованные теги в фигурных скобках. Потом она читает два значения по имени, показывает ошибку на сломанном вводе и печатает compound обратно в виде текста. В таблице собрано то, чем она пользуется, и соседние точки входа двух крейтов.

Имя Что делает
parse_compound Читает текст, в котором один compound и больше ничего
parse_tag Читает текст, в котором один любой тег и больше ничего
read_tag, read_compound Начинают с позиции в более длинном тексте и сообщают, где остановились. Это нужно парсеру команд
NbtCompound Дает методы get_* и put_* для каждого типа, например get_string, get_int и get_compound
SnbtError Содержит kind и байтовую position
write Печатает тег так же, как игра, поэтому 1. превращается в 1.0d, а список печатается в компактной форме

Числа и строки крейт разбирает по правилам игры. Сюда входят суффиксы типов, литералы 0x и 0b, разделители _ и экранирование. Тестовый файл крейта сверяет эти правила с записанными фикстурами игры.

SNBT - только текстовая сторона. Бинарное чтение и запись, сжатие и поддержка serde находятся в mcrs_minecraft_nbt, том самом крейте, от которого вы уже зависите ради типов тегов.

У бинарного кодека три кодировки.2 BigEndian нужна для Java Edition, LittleEndian - для хранения мира Bedrock, NetworkLittleEndian - для пакетов Bedrock. У каждой точки входа вроде from_bytes есть форма _with::<E>, которая принимает кодировку, а функции без этого суффикса работают с BigEndian.

Дальше: Использование крейтов в своем проекте, там описаны ограничения пути через git. Другие крейты ищите в карте крейтов.

  1. Решения нет#321 Отслеживает работу, после которой крейты протокола, сети и игровых данных можно публиковать. ↩ ↩2

  2. Работает#661 NBT с little-endian и сетевыми varint в mcrs_minecraft_nbt. ↩

Источники и проверка

Проверено: 26.4-snapshot-7, 3540f457b, 2026-11-10

Переведено с версии 3540f457b

Следить: #321