Довідка з формату 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: тег складається з однобайтового типу, імені з префіксом довжини та даних, а вкладені compound завершуються байтом TAG_End. У Java і Bedrock використовуються 13 типів тегів та п’ять кодувань. Нижче описано кожен варіант, а редактор вище дає змогу перевірити їх на реальному файлі.

13 типів тегівBig-endianLittle-endianVarintgzipzlibSNBT

Перетягніть будь-який файл 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_Arrayдовжина int, потім відповідна кількість байтів[B;1b,2b]
8TAG_Stringдовжина unsigned short, потім байти UTF-8"text"
9TAG_Listбайт типу елементів, довжина int, потім дані без імен[1,2]
10TAG_Compoundтип + ім’я + дані до TAG_End{a:1}
11TAG_Int_Arrayдовжина int, потім відповідна кількість 4-байтових int[I;1,2]
12TAG_Long_Arrayдовжина int, потім відповідна кількість 8-байтових long[L;1L,2L]

Файл містить один кореневий TAG_Compound: байт типу 0x0A, ім’я, а потім вміст compound. Іменовані теги трапляються лише всередині compound; елементи списку містять тільки дані, тому список є однорідним.

П’ять поширених кодувань

КодуванняЦілі числаДовжина рядкаКоріньВикористання
Java (класичне)Big-endian фіксованої ширини2-байтове big-endianІменованийСвіти Java, структури, схеми
Мережевий Java (1.20.2+)Big-endian фіксованої ширини2-байтове big-endianБезіменнийПротокол Java
BedrockLittle-endian фіксованої ширини2-байтове little-endianІменованийСвіти Bedrock, .mcstructure, значення LevelDB
Bedrock level.datLittle-endian фіксованої ширини2-байтове little-endianІменований, після 8-байтового заголовкаМетадані світу Bedrock
Мережевий BedrockZigzag varint для int і longБеззнаковий varintІменованийПротокол Bedrock

У кодуванні varint TAG_Short, TAG_Float і TAG_Double залишаються little-endian фіксованої ширини; лише TAG_Int та TAG_Long перетворюються на zigzag varint, а довжини масивів і списків кодуються так само, як TAG_Int. Довжини рядків є unsigned varint, тому обмеження у 65535 байтів, властиве фіксованим кодуванням, зникає.

Рядки: модифікований UTF-8 і UTF-8

Java серіалізує рядки через DataOutputStream.writeUTF, тобто використовує модифікований UTF-8: символ NUL записується як C0 80 замість 00, а символи поза Basic Multilingual Plane — як дві трибайтові сурогатні половини (CESU-8), а не одна чотирибайтова послідовність. Bedrock використовує стандартний UTF-8. Інструмент з одним кодуванням для обох форматів пошкоджує емодзі та деякий текст CJK під час збереження. Цей редактор кодує рядки відповідно до формату, тому назва світу з емодзі зберігається без змін.

Стиснення

Сам NBT не стиснений; спосіб визначає контейнер. Файли Java зазвичай використовують gzip (сигнатура 1F 8B), дані чанків усередині файлів регіонів — zlib (сигнатура 78 01, 78 9C або 78 DA), а Bedrock зберігає level.dat і файли структур без стиснення. Формат визначається за сигнатурою, тому один парсер обробляє всі три варіанти. Неправильне стиснення під час збереження — найпоширеніша причина, через яку відредагований вручну світ не завантажується.

Мінімальний файл побайтово

Канонічний hello_world.nbt: кореневий compound з іменем hello world, що містить один рядковий тег name зі значенням Bananrama. У кодуванні Java big-endian:

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 little-endian відрізняється лише порядком байтів у двох полях довжини: 0B 00 замість 00 0B. У Мережевий Bedrock NBT довжини стають однобайтовими varint 0B і 04 без заповнення. Перетягніть будь-який із трьох варіантів у редактор вище, і він визначить отриманий формат.

SNBT

SNBT — текстова форма NBT, яку приймають команди: /data merge entity @s {Invulnerable:1b}. Суфікси типів зберігають дані без втрат: b — byte, s — short, L — long, f — float, d — double, без суфікса — int; типізовані масиви записуються як [B;…], [I;…], [L;…]. Редактор експортує SNBT із будь-якого завантаженого файла, тому дві версії світу можна порівняти звичайним текстовим diff.

Часті запитання

Чи існує офіційна специфікація NBT?

Формальної специфікації від Mojang немає. Формат описав Notch у 2010 році, а відтоді документацію підтримує спільнота. Ідентифікатори тегів і структура на цій сторінці відповідають тому, що гра читає та записує зараз.

Чому Bedrock використовує little-endian?

Рушій Bedrock написаний на C++ і працює на обладнанні little-endian, тому зберігає значення у природному порядку. Серіалізація Java є big-endian відповідно до контракту Java DataOutput.

Що таке кодування zigzag varint?

Це спосіб записувати цілі числа мінімальною кількістю байтів, не збільшуючи від’ємні значення: знак переноситься в молодший біт, тому −1 кодується як 1, а 1 — як 2. Протокол Bedrock використовує його для ints і longs.

Чи може TAG_List містити різні типи?

Ні. Список оголошує один тип елементів, якому має відповідати кожен запис. Для різнорідних даних потрібен список compound.

Яка максимальна довжина рядка?

65535 байтів у фіксованих кодуваннях, оскільки поле довжини має тип unsigned short. Мережеве кодування varint практичного обмеження не має.

Пов’язані інструменти