Структура .nbt хранит индексы палитры, а не названия блоков — вот почему она такая маленькая
Три ключа содержат всю постройку: размер, палитра и блоки. Каждый блок — это целое число, указывающее на палитру, поэтому объем камня 32³ стоит одну строку и 32 768 чисел.
Файл структуры .nbt — то, что сохраняет Блок-конструктор и что поставляется в датапаке — имеет гораздо более простой формат, чем кажется со стороны. Все, что нужно для постройки, находится в нескольких ключах верхнего уровня, и одно проектное решение объясняет, почему эти файлы такие маленькие.
Три ключа, которые несут постройку
size [x, y, z] — a list of exactly three integers
palette [ { Name, Properties } … ] — every DISTINCT block state, once
blocks [ { pos, state, nbt } … ] — one entry per placed block
palette содержит каждое уникальное состояние блока ровно один раз. Запись представляет собой Name — идентификатор блока, например minecraft:oak_stairs — плюс необязательное составное поле Properties, содержащее его состояние блока, такое как facing: north и half: bottom.
blocks никогда не повторяет имя. Каждая запись содержит pos из трех целых чисел и state, а state — это индекс в палитре, а не идентификатор блока. Дубовые ступеньки, смотрящие на север, являются строковыми данными один раз, и каждая последующая такая ступенька — это небольшое целое число.
В этом весь секрет. Объем обычного Камня 32 × 32 × 32 — это одна запись палитры и 32 768 индексных номеров, а не 32 768 копий слова minecraft:stone. Палитра растет в зависимости от того, сколько разных вещей вы использовали при постройке, а список блоков растет в зависимости от того, насколько большой вы построили. Это очень разные числа, и только одно из них обычно велико.
Два важных последствия, которые стоит учитывать при проектировании
Состояния блоков умножают вашу палитру, а не список блоков. Дубовые ступеньки — это не одна запись палитры, а одна на каждую фактически использованную ориентацию. Четыре направления, верхняя и нижняя половина, прямые и оба внутренних и внешних угла: один и тот же блок может занимать дюжину слотов палитры. Таким образом, детализированная постройка имеет большую палитру, а простая — нет, независимо от размера.
Только размещенные блоки получают запись. Список блоков — это список, а не плотный 3D-массив, и запись, которой нет, просто отсутствует — просмотрщик на этой странице заполняет свою сетку -1 и рассматривает отсутствующую координату как неразмещенную. Полая постройка действительно дешевле в хранении, чем сплошная того же размера.
nbt является поблочным и необязательным
Каждая запись в blocks может содержать свое собственное составное поле nbt, и большинство из них этого не делают. Здесь хранятся содержимое Сундука, текст таблички, моб спаунера и узоры баннера — прикрепленные к отдельному блоку, а не к палитре.
Различие имеет значение: данные палитры являются общими, а данные блока — нет. Два Сундука — это одна запись палитры, потому что они имеют одинаковое состояние блока, но каждый хранит свой собственный инвентарь в своем собственном nbt. Измените состояние блока, и вы затронете палитру; измените то, что внутри него, и вы затронете одну запись в списке блоков.
Чтение по слоям
Просмотрщик здесь намеренно 2D. Чтобы нарисовать слой y, он просматривает список блоков, сохраняет записи, у которых pos[1] равно y, и ищет state каждой из них в палитре. Это весь алгоритм, и его стоит знать, потому что именно так вы бы сами проверяли один из этих файлов: нет пространственного индекса для построения и нет декомпрессии, кроме оболочки gzip. Формат представляет собой плоский список, который вы фильтруете.
Что также означает, что файл структуры ничего не говорит вам о том, где он находится в мире. size — это ограничивающая рамка, а значения pos относятся к ее углу. Размещение — это дело Блока-конструктора, а не файла.