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).