Skip to content

Latest commit

 

History

History
129 lines (91 loc) · 4.28 KB

File metadata and controls

129 lines (91 loc) · 4.28 KB

はじめに(Rust)

Rust 2021 edition、MSRV 1.75 です。

導入

Cargo.toml に git 参照を書きます。

[dependencies]
spring-nbt-library = { git = "https://github.com/ScriptArts/SpringNBTLibrary", tag = "v1.0.0" }

Cargo が自分で取得します。

ネットワークに繋がらない環境なら、Releasesspring-nbt-library-<版>.crate(拡張子が違うだけの tar.gz)を展開してパス参照します。

tar xzf spring-nbt-library-1.0.0.crate
[dependencies]
spring-nbt-library = { path = "spring-nbt-library-1.0.0" }

例外ではなく Result

Rust 版だけは例外ではなく Result<T, Error> を返します。 ErrorCode の集合は他言語と完全に一致します(adr/0005)。

use spring_nbt_library::error::{ErrorCode, Result};

NBT ファイルを読む

use spring_nbt_library::nbt::{read_file, NbtReadOptions};

// 圧縮方式(Gzip / Zlib / 無圧縮)は自動で判定される
let named = read_file("level.dat", &NbtReadOptions::default())?;
let data = named.tag.get_compound("Data")?;

println!("{}", data.get_string("LevelName")?);
println!("{}", data.get_int("DataVersion")?);

型が違えば ErrorCode::UnexpectedTagType が返ります。 キーが無いかもしれないときは opt_* を使います(無ければ Ok(None))。

書く

use spring_nbt_library::nbt::tag::{NbtCompound, NbtString, NbtTag};
use spring_nbt_library::nbt::{write_file, Compression, NamedTag, NbtWriteOptions};

let mut root = NbtCompound::new();
root.set("name", NbtTag::String(NbtString::new("SpringNBTLibrary")));
root.set("count", NbtTag::Int(42));

let options = NbtWriteOptions { compression: Compression::Gzip, ..Default::default() };
write_file("out.nbt", &NamedTag::new("", root), &options)?;

文字列は 2 形態

Rust の String は UTF-8 に限られるので、NBT に現れうる孤立サロゲートを保持できません。 そこで NbtString を列挙にしています(spec/10 2.3)。

pub enum NbtString {
    Text(String),          // 通常の文字列。実データはほぼすべてこちら
    Surrogates(Vec<u16>),  // UTF-8 に写せない UTF-16 コード単位の列
}

ワールドのブロックを読む

use spring_nbt_library::world::{MinecraftWorld, WorldOpenOptions};

let mut world = MinecraftWorld::open(world_path, WorldOpenOptions::default())?;

if let Some(overworld) = world.dimension("minecraft:overworld")? {
    // 絶対座標。リージョンとチャンクの解決は内部で行う
    if let Some(block) = overworld.get_block(100, 64, -200)? {
        println!("{block}");   // minecraft:grass_block[snowy=false]
    }
}

world.close()?;

ブロックを書き換える

let options = WorldOpenOptions { writable: true, ..Default::default() };
let mut world = MinecraftWorld::open(world_path, options)?;

if let Some(overworld) = world.dimension("minecraft:overworld")? {
    let stone = BlockState::parse("minecraft:stone")?;
    overworld.set_block(100, 64, -200, &stone)?;
    overworld.flush()?;   // ここで初めてディスクへ書かれる
}

world.close()?;

Minecraft を終了してから実行すること。 Rust 版は std にファイルロックが無いため session.lock は確認しません(adr/0008)。 起動していないことは呼び出し側で担保してください。

ブロックを置き換えても Heightmaps と光源は再計算されません(adr/0004)。

スタックの深さに注意

NBT のネストは既定で深さ 512 まで許します。 debug ビルドでは 1 段あたり約 8 KB 使うので、 深いデータを扱うなら大きめのスタックを持つスレッドで走らせてください (spec/00 5.1)。

次に読むもの