Dokumentacja formatu NBT

Obsługuje Minecraft Bedrock Edition i Java Edition — a także każdy popularny i niszowy rdzeń serwera obu edycji: Vanilla, Paper, Spigot, Purpur, Folia, Fabric, Forge, NeoForge, Mohist, Sponge, Bedrock Dedicated Server, PocketMine-MP, Nukkit, PowerNukkitX, Cloudburst, Dragonfly, Endstone, LeviLamina i pozostałe. Pełna lista.

NBT (Named Binary Tag) to binarny format drzewa używany przez Minecraft: tag składa się z jednobajtowego typu, nazwy poprzedzonej długością i danych, a tagi złożone mogą się zagnieżdżać, dopóki nie zamknie ich bajt TAG_End. W Java i Bedrock występuje 13 typów tagów oraz pięć sposobów kodowania. Ta strona opisuje je wszystkie, a edytor powyżej pozwala sprawdzić informacje na prawdziwym pliku.

13 typów tagówWielkobajtoweMałobajtoweVarintgzipzlibSNBT

Upuść tutaj dowolny plik NBT do sprawdzenia

level.dat · .nbt · .mcstructure · .schem · .schematic · .dat · zrzuty chunków

13 typów tagów

IdTagDaneSNBT
0TAG_EndBrak — zamyka tag złożony—
1TAG_Byte1 bajt ze znakiem, od −128 do 1271b
2TAG_Short2 bajty ze znakiem1s
3TAG_Int4 bajty ze znakiem1
4TAG_Long8 bajtów ze znakiem1L
5TAG_Float4 bajty, IEEE 7541.0f
6TAG_Double8 bajtów, IEEE 7541.0d
7TAG_Byte_ArrayDługość typu int, a następnie odpowiednia liczba bajtów[B;1b,2b]
8TAG_StringDługość typu unsigned short, a następnie bajty UTF-8"text"
9TAG_ListBajt typu elementu, długość typu int, a następnie dane bez nazw[1,2]
10TAG_CompoundPowtarzane typ + nazwa + dane aż do TAG_End{a:1}
11TAG_Int_ArrayDługość typu int, a następnie odpowiednia liczba 4-bajtowych wartości int[I;1,2]
12TAG_Long_ArrayDługość typu int, a następnie odpowiednia liczba 8-bajtowych wartości long[L;1L,2L]

Plik zawiera jeden główny TAG_Compound: bajt typu 0x0A, nazwę, a następnie zawartość tagu złożonego. Nazwane tagi występują tylko wewnątrz tagów złożonych — elementy list zawierają wyłącznie dane, dlatego każda lista jest jednorodna.

Pięć używanych sposobów kodowania

KodowanieLiczby całkowiteDługość tekstuKorzeńZastosowanie
Java (klasyczne)Stała szerokość, kolejność wielkobajtowa2 bajty, kolejność wielkobajtowaNazwanyŚwiaty, struktury i schematy Java
Sieciowe Java (1.20.2+)Stała szerokość, kolejność wielkobajtowa2 bajty, kolejność wielkobajtowaBez nazwyProtokół Java
BedrockStała szerokość, kolejność małobajtowa2 bajty, kolejność małobajtowaNazwanyŚwiaty Bedrock, .mcstructure, wartości LevelDB
Bedrock level.datStała szerokość, kolejność małobajtowa2 bajty, kolejność małobajtowaNazwany, po 8-bajtowym nagłówkuMetadane świata Bedrock
Sieciowe BedrockVarint zigzag dla int i longVarint bez znakuNazwanyProtokół Bedrock

W kodowaniu varint tagi TAG_Short, TAG_Float i TAG_Double zachowują stałą szerokość i kolejność małobajtową. Tylko TAG_Int i TAG_Long stają się wartościami varint zigzag, a długości tablic i list są kodowane tak samo jak TAG_Int. Długości tekstu to wartości varint bez znaku, co dodatkowo znosi limit 65535 bajtów narzucany przez kodowania o stałej szerokości.

Ciągi znaków: zmodyfikowany UTF-8 a UTF-8

Java serializuje ciągi znaków za pomocą DataOutputStream.writeUTF, czyli zmodyfikowanego UTF-8: znak NUL jest zapisywany jako C0 80 zamiast 00, a znaki spoza podstawowej płaszczyzny wielojęzycznej jako dwie trzybajtowe połówki surogatowe (CESU-8), nie jedna sekwencja czterobajtowa. Bedrock używa standardowego UTF-8. Narzędzie zakładające to samo kodowanie w obu formatach uszkodzi podczas zapisu emoji i część tekstu CJK — ten edytor dobiera kodowanie do formatu, dlatego nazwa świata z emoji przechodzi przez edycję bez zmian.

Kompresja

Sam format NBT nie jest skompresowany; decyduje o tym kontener. Pliki Java zwykle używają gzip (sygnatura 1F 8B), dane chunków w plikach regionów — zlib (sygnatura 78 01, 78 9C lub 78 DA), natomiast Bedrock przechowuje level.dat i pliki struktur bez kompresji. Format jest wykrywany na podstawie bajtów sygnatury, więc jeden parser obsługuje wszystkie trzy warianty. Zapis z niewłaściwą kompresją jest najczęstszą przyczyną niewczytywania się ręcznie edytowanego świata.

Minimalny plik, bajt po bajcie

Klasyczny plik hello_world.nbt: główny tag złożony o nazwie hello world, zawierający jeden tag tekstowy name o wartości Bananrama. W wielkobajtowym kodowaniu 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

Ten sam dokument w małobajtowym kodowaniu Bedrock różni się jedynie kolejnością bajtów w dwóch polach długości: 0B 00 zamiast 00 0B. W sieciowym NBT Bedrock długości stają się pojedynczymi bajtami varint, 0B i 04, bez żadnego dopełnienia. Przeciągnij dowolny z trzech wariantów do edytora powyżej, a rozpozna on otrzymany format.

SNBT

SNBT to NBT zapisane jako tekst i właśnie tę postać przyjmują polecenia: /data merge entity @s {Invulnerable:1b}. Bezstratność zapewniają przyrostki typów — b oznacza Byte, s Short, L Long, f Float, d Double, a brak przyrostka Int — natomiast literały tablic typowanych zapisuje się jako [B;…], [I;…], [L;…]. Edytor eksportuje SNBT z dowolnego wczytanego pliku, dzięki czemu dwie wersje świata można porównać zwykłym narzędziem do tekstu.

Najczęściej zadawane pytania

Czy istnieje oficjalna specyfikacja NBT?

Mojang nie opublikował formalnej specyfikacji. Format został opisany przez Notch w 2010 roku i od tego czasu dokumentację utrzymuje społeczność; identyfikatory tagów i układ przedstawione na tej stronie odpowiadają danym odczytywanym i zapisywanym obecnie przez grę.

Dlaczego Bedrock używa kolejności małobajtowej?

Silnik Bedrock jest napisany w C++ i przeznaczony dla sprzętu małobajtowego, dlatego zapisuje wartości w kolejności natywnej. Serializacja Java jest wielkobajtowa, ponieważ tak określa ją kontrakt Java DataOutput.

Na czym polega kodowanie varint zigzag?

To sposób zapisywania liczb całkowitych przy użyciu jak najmniejszej liczby bajtów, który zachowuje krótki zapis liczb ujemnych: znak zostaje umieszczony w najmłodszym bicie, więc −1 koduje się jako 1, a 1 jako 2. Protokół Bedrock używa go dla wartości int i long.

Czy TAG_List może zawierać różne typy?

Nie. Lista deklaruje jeden typ elementów i każdy wpis musi być z nim zgodny. Dane różnych typów wymagają listy tagów złożonych.

Jaka jest maksymalna długość ciągu znaków?

W kodowaniach o stałej szerokości wynosi 65535 bajtów, ponieważ pole długości jest wartością unsigned short. Sieciowe kodowanie varint nie ma praktycznego limitu.

Powiązane narzędzia