NBT形式リファレンス

Minecraft Bedrock EditionとJava Editionに対応し、一般的なものから小規模なものまで両方の全サーバーコアを扱えます: Vanilla、Paper、Spigot、Purpur、Folia、Fabric、Forge、NeoForge、Mohist、Sponge、Bedrock Dedicated Server、PocketMine-MP、Nukkit、PowerNukkitX、Cloudburst、Dragonfly、Endstone、LeviLaminaなど。全一覧。

NBT(Named Binary Tag)はMinecraftのバイナリツリー形式です。タグは1バイトの型、長さ付きの名前、ペイロードからなり、Compoundは TAG_End で閉じるまで入れ子になります。JavaとBedrockでは13種類のタグ型と5種類のエンコードが使われています。このページで各形式を説明し、上のエディターで実ファイルを確認できます。

13種類のタグ型ビッグエンディアンリトルエンディアンVarintgzipzlibSNBT

ここに確認するNBTファイルをドロップ

level.dat · .nbt · .mcstructure · .schem · .schematic · .dat · チャンクのダンプ

13種類のタグ型

IdタグペイロードSNBT
0TAG_Endなし — Compoundを閉じる—
1TAG_Byte1バイト、符号付き −128…1271b
2TAG_Short2バイト、符号付き1s
3TAG_Int4バイト、符号付き1
4TAG_Long8バイト、符号付き1L
5TAG_Float4バイト、IEEE 7541.0f
6TAG_Double8バイト、IEEE 7541.0d
7TAG_Byte_Arrayint長、その後に指定数のbyte[B;1b,2b]
8TAG_Stringunsigned short長、その後にUTF-8バイト列"text"
9TAG_List要素型byte、int長、その後に名前なしペイロード[1,2]
10TAG_CompoundTAG_End まで型 + 名前 + ペイロードを反復{a:1}
11TAG_Int_Arrayint長、その後に指定数の4バイトint[I;1,2]
12TAG_Long_Arrayint長、その後に指定数の8バイトlong[L;1L,2L]

1ファイルは単一のルート TAG_Compound です。型byte 0x0A、名前、Compound内容の順です。名前付きタグが現れるのはCompound内だけで、List要素はペイロードだけを持つため、List内の型はすべて同じです。

実際に使われる5種類のエンコード

エンコード整数文字列長ルート用途
Java(従来形式)固定長ビッグエンディアン2バイトビッグエンディアン名前付きJavaワールド、構造物、スキーマティック
Java ネットワーク (1.20.2+)固定長ビッグエンディアン2バイトビッグエンディアン名前なしJavaプロトコル
Bedrock固定長リトルエンディアン2バイトリトルエンディアン名前付きBedrockワールド、.mcstructure、LevelDB値
Bedrock level.dat固定長リトルエンディアン2バイトリトルエンディアン8バイトヘッダー後に名前付きBedrockワールドメタデータ
Bedrock ネットワークintとlongはZigzag varint符号なし可変長整数名前付きBedrockプロトコル

varint形式でも TAG_Short、TAG_Float、TAG_Double は固定長リトルエンディアンです。TAG_Int と TAG_Long だけがzigzag varintになり、配列とListの長さも TAG_Int と同じ方式です。文字列長はunsigned varintなので、固定長形式の65535バイト上限もありません。

文字列: 修正版UTF-8とUTF-8

Javaは DataOutputStream.writeUTF の修正版UTF-8を使います。NULは C0 80 として書かれ、通常の 00 は使いません。基本多言語面外の文字は1つの4バイト列ではなく2つの3バイトサロゲート(CESU-8)で書きます。Bedrockは標準UTF-8です。両方を同じエンコードとして扱うツールは、保存時に絵文字や一部のCJK文字を壊します。このエディターは形式ごとに正しくエンコードします。

圧縮

NBT自体は圧縮されず、コンテナーが圧縮方式を決めます。Javaファイルは通常gzip(マジック 1F 8B)、リージョン内のチャンクはzlib(78 01、78 9C、78 DA)、Bedrockの level.dat と構造物ファイルは非圧縮です。マジックバイトで判定するため同じパーサーで処理できます。誤った圧縮方式で保存すると、手動編集したワールドを読み込めない主な原因になります。

最小ファイルをバイト単位で確認

標準例 hello_world.nbt は、名前 hello world のルートCompoundに、文字列タグ name が1つあり、その値は Bananrama です。Javaのビッグエンディアン形式では次のとおりです。

0A                          TAG_Compound
00 0B 68 65 6C 6C 6F 20 77 6F 72 6C 64   name length 11, "hello world"
   08                       TAG_String
   00 04 6E 61 6D 65        name length 4, "name"
   00 09 42 61 6E 61 6E 72 61 6D 61      value length 9, "Bananrama"
00                          TAG_End

同じ文書のBedrockリトルエンディアン形式では、2つの長さフィールドのバイト順だけが異なり、0B 00 となり、Javaの 00 0B とは逆です。BedrockネットワークNBTでは長さが1バイトvarintの 0B と 04 になり、パディングはありません。3形式のいずれをドロップしても自動判定します。

SNBT

SNBTはNBTのテキスト表現で、コマンドが受け取る形式です: /data merge entity @s {Invulnerable:1b}。型を失わないよう、byteは b、shortは s、longは L、floatは f、doubleは d、intは接尾辞なしで表し、型付き配列は [B;…]、[I;…]、[L;…] と書きます。任意のファイルをSNBTへ出力すると、通常のテキストdiffでワールドの2バージョンを比較できます。

よくある質問

公式のNBT仕様はありますか?

Mojangによる正式仕様はありません。2010年にNotchが記録し、その後コミュニティが維持しています。このページのタグIDと配置は現在のゲームが読み書きする形式に対応します。

Bedrockがリトルエンディアンなのはなぜですか?

BedrockエンジンはC++でリトルエンディアンのハードウェアを対象とし、値をネイティブ順で保存します。JavaはDataOutputの仕様に従いビッグエンディアンです。

zigzag varintエンコードとは何ですか?

負数も短く保ちながら整数を少ないバイトで書く方式です。符号を最下位ビットへ折り込むため、−1は1、1は2としてエンコードされます。Bedrockプロトコルはintとlongに使います。

TAG_Listに複数の型を混在できますか?

できません。Listは1つの要素型を宣言し、すべての項目が一致する必要があります。混合データにはCompoundのListを使います。

文字列の最大長は?

固定長形式では長さフィールドがunsigned shortなので65535バイトです。varintネットワーク形式には実用上の制限がありません。

関連ツール