NBT
Формат NBT (от англ. Named Binary Tag — «именованный двоичный тег») используется Minecraft в различных файлах для хранения данных. Формат описан Нотчем в очень краткой спецификации. Формат разработан для хранения данных в структуре-дереве, состоящей из различных тегов. У каждого тега есть идентификатор и название. Оригинальная известная версия NBT, 19132, была введена в Beta 1.3, и с тех пор была обновлена до 19133 вместе с Anvil; в этом обновлении был добавлен тег для массива целочисленных переменных. Формат NBT был ещё в Indev и использовал теги с 0 по 10.
Определение тега
Тег — отдельный элемент дерева данных. Первый байт в теге — это тип тега (также называемый идентификатором или ID), затем 2 байта хранят длину названия, затем название в виде строки в формате UTF-8 (следует отметить, что TAG_End не имеет названия и не включает дополнительные 2 байта; предполагается, что название пустое). Названия тегов могут содержать пробелы, хотя сам Minecraft не имеет таких тегов. Наконец, следующие байты — содержимое тега, зависящее от типа тега. Таблица ниже описывает 12 известных тегов в версии NBT 19133:
ID | Иконка | Тип тега | Содержимое | Описание | Ёмкость |
---|---|---|---|---|---|
0 | TAG_End | Нет. | Используется для обозначения конца составных тегов. У этого тега нет названия, поэтому он всегда представлен одним байтом, равным 0. Также этот тип используется в пустых тегах списков. | — | |
1 | TAG_Byte | 1 байт / 8 битов, со знаком | Целочисленный тип со знаком. Иногда используется для логических переменных. | Весь промежуток от -(27) до (27 - 1) (от -128 до 127) | |
2 | TAG_Short | 2 байта / 16 битов, со знаком, обратный порядок байтов | Целочисленный тип со знаком. | Весь промежуток от -(215) до (215 - 1) (от -32 768 до 32 767) | |
3 | TAG_Int | 4 байта / 32 бита, со знаком, обратный порядок байтов | Целочисленный тип со знаком. | Весь промежуток от -(231) до (231 - 1) (от -2 147 483 648 до 2 147 483 647) | |
4 | TAG_Long | 8 байт / 64 бита, со знаком, обратный порядок байтов. | Целочисленный тип со знаком. | Весь промежуток от -(263) до (263 - 1) (от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807) | |
5 | TAG_Float | 4 байта / 32 бита, со знаком, обратный порядок байтов, IEEE 754-2008, binary32 | Тип чисел с плавающей точкой со знаком. | Точность меняется на протяжении числовой прямой; см. [ruwiki:Число одинарной точности Число одинарной точности]. | |
6 | TAG_Double | 8 байт / 64 бита, со знаком, обратный порядок байтов, IEEE 754-2008, binary64 | Тип чисел с плавающей точкой со знаком. | Точность меняется на протяжении числовой прямой; см. [ruwiki:Число двойной точности Число двойной точности]. | |
7 | TAG_Byte_Array | Один TAG_Int, обозначающий размер, затем размер тегов TAG_Byte. | Массив байтовых переменных. | Максимальное число элементов изменяется от (231 - 9) до (231 - 1) (от 2 147 483 639 до 2 147 483 647) и зависит от текущей JVM. | |
8 | TAG_String | Один TAG_Short, обозначающий длину, затем строка в формате UTF-8 с размером длина. | Строка в формате UTF-8. Она имеет размер, а не завершается нулём. | 32 767 точек кода UTF-8 (см. [ruwiki:UTF-8 UTF-8]; наиболее распространённые символы состоят из одной точки кода. | |
9 | TAG_List | Один TAG_Byte, обозначающий тип, затем TAG_Int, обозначающий размер, затем размер тегов типа тип. | Последовательный список тегов без ID и без названий. | В связи с ограничениями JVM и реализацией ArrayList, максимальный размер списка — (231 - 9) или 2 147 483 639. Также следует отметить, что максимальная глубина размещения списков и составных тегов равна 512. | |
10 | TAG_Compound | Полные теги, затем один тег TAG_End. | Список полных тегов, включающий их типы, названия и содержимые. Все теги должны иметь различные имена. | В отличие от списков, ограничения на количество тегов в составном теге нет (хотя имеется неявное ограничение в виде размера виртуальной памяти). Также следует отметить, что максимальная глубина размещения списков и составных тегов равна 512. | |
11 | TAG_Int_Array | Один TAG_Int, обозначающий размер, затем размер тегов TAG_Int. | Массив тегов TAG_Int. | Максимальное число элементов изменяется от (231 - 9) до (231 - 1) (от 2 147 483 639 до 2 147 483 647) и зависит от текущей JVM. | |
12 | TAG_Long_Array | Одно значение TAG_Int (без заголовка), обозначающий размер, затем набор тегов TAG_Long. | Массив тегов TAG_Long. | Максимальное число элементов изменяется от (231 - 9) до (231 - 1) (от 2 147 483 639 до 2 147 483 647) и зависит от текущей JVM. |
Списки и составные теги могут быть вложены. Следует отметить, что в списке списков подсписки могут иметь разные типы элементов.
Формат файлов
Файл NBT — это сжатый GZip составной тег, включающий название и тип. Некоторые такие файлы, используемые Minecraft, не являются сжатыми GZip, хотя в большинстве случаев спецификация Нотча, предписывающая сжатие, соблюдается. В Xbox 360 издании чанки сжимаются XMemCompress, разновидностью алгоритма сжатия LZX. Заголовка, указывающего версию или какую-либо иную информацию, в файлах нет, версия указана только в файле level.dat.
Использование в Minecraft
Использование формата NBT в Minecraft местами является странным. В некоторых случаях пустые списки могут быть представлены списками байтов (или тегов End в более новых версиях Minecraft), а не списками правильного типа. К тому же, каждый корневой тег имеет пустое название и включает только один составной тег с самими данными и названием. Например:
- Корневой тег для большинства структур NBT в Minecraft.
- Название: Единственный тег, содержащийся в корневом теге. Он имеет название и содержит сами данные.
Ещё одна заметная странность — это то, что, хотя оригинальная спецификация Нотча допускает пробелы в названиях тегов и приведённый в ней пример использует это, в Minecraft нет файлов с пробелами в тегах. Также использование прописных букв в названиях тегов непостоянно: где-то с прописной буквы пишется каждое слово, где-то — каждое, кроме первого, а где-то используются только строчные буквы.
Область применения
- level.dat хранится в сжатом формате NBT.
- Файлы <player>.dat хранятся в сжатом формате NBT.
- idcounts.dat хранится в несжатом формате NBT.
- villages.dat хранится в сжатом формате NBT.
- Файлы map_<#>.dat хранятся в сжатом формате NBT.
- servers.dat, используется для хранения списка сохранённых серверов как несжатый формат NBT.
- Чанки хранятся в сжатом формате NBT в файлах областей.
- scoreboard.dat хранится в сжатом формате NBT.
- Натуральные структуры хранятся в сжатом формате NBT.
Программное обеспечение
Mojang предоставила экземпляры классов Java для работы с NBT, предназначенные для использования разработчиками, как часть исходного кода для преобразователя McRegion → Anvil. Помимо этого, сообщество разработало программы для просмотра и изменения сжатых и несжатых файлов NBT, например, NBTExplorer и NBT2YAML (все вышеприведённые программы поддерживают последние версии NBT).