Расширение не определяет формат схемы — 31 из 33 файлов .schematic оказались чужими догадками
Пять форматов, четыре разных способа упаковки блоков, и .schematic используется двумя из них. Проверка корневого NBT-тега надёжнее, чем доверие имени файла, что подтверждено подсчётами.
В обращении находятся пять форматов схем, и имя файла является скорее подсказкой, чем фактом. Программа просмотра здесь определяет тип файла, заглядывая внутрь, и для этого есть веская причина.
Пять форматов, пять расширений
| расширение | формат |
|---|---|
.nbt | ванильная структура |
.schem | Губка |
.schematic | Губка — по умолчанию |
.litematic | Litematica |
.mcstructure | Бедрок |
Проблемная строка — .schematic. Это расширение используется как классическим форматом MCEdit, так и форматом Губки, и файлы переименовываются людьми, которые не знают или не заботятся об этом.
Подсчитано на реальном корпусе: из 33 файлов .schematic, 31 были MCEdit, один — ванильной структурой и один — Litematica. Таким образом, предположение по умолчанию, основанное на расширении, неверно почти для всех из них, а два файла вообще не были .schematic — просто неправильно названы.
Решение состоит в том, чтобы проверять корневой NBT-тег и позволять тому, чем файл является, преобладать над тем, как он называется:
- ключ
Regions→ Litematica paletteиblocks→ ванильная структура- в противном случае проверка формы MCEdit, затем возврат к расширению
Четыре способа упаковки одних и тех же блоков
Форматы не отличаются косметически. Каждый хранит данные блоков по-своему, и каждый выбор имеет свои последствия:
Ванильная .nbt — разреженный список. Одна запись на размещенный блок, каждая ссылается на индекс палитры. Воздух просто отсутствует, поэтому полая постройка обходится дешево.
Губка .schem — поток varint. Индексы палитры упакованы как переменные по длине целые числа: семь бит полезной нагрузки на байт, старший бит установлен для продолжения. Маленькие палитры стоят один байт на блок; палитра из более чем 127 записей начинает стоить два байта для высоких индексов. Плотный, но самоописывающийся.
MCEdit .schematic — плоский байтовый массив. Один байт на блок, поэтому максимум 256 типов блоков — именно поэтому ему нужен дополнительный массив AddBlocks, упаковывающий девятый бит как ниббл на блок. Это устаревший формат с числовыми идентификаторами, существовавший до состояний блоков, и его идентификаторы разрешаются через составной тег SchematicaMapping, а не являются именами.
Litematica .litematic — битово-упакованные длинные целые числа (bit-packed longs). Индексы упакованы ровно по max(2, bits needed for the palette) бит каждый, младший бит первым, и запись может пересекать границу между двумя длинными целыми числами. Палитра из 5 записей использует 3 бита на блок; палитра из 300 записей использует 9.
Значение имеет нижний предел в 2 бита: даже палитра из двух блоков не сжимается ниже 2 бит на запись, поэтому монохромная постройка не так мала, как предполагает математика.
Бедрок использует прямой порядок байтов
.mcstructure — это исключение на более низком уровне: Бедрок записывает NBT в прямом порядке байтов (little-endian NBT), тогда как каждый формат Java записывает в обратном порядке (big-endian). Это решается до начала любого анализа формата — если прочитать байты с неправильным порядком, вы получите не неправильную структуру, а мусор, который вообще не сможет быть разобран.
Что это означает на практике
Если схема где-то не открывается, первый вопрос не "файл поврежден", а "этот файл соответствует своему названию". .schematic со страницы загрузки гораздо чаще оказывается MCEdit, чем Губкой, и инструмент, который доверяет расширению, отклонит совершенно хороший файл.
А при сравнении двух экспортов одной и той же постройки, различия в размере в основном связаны с кодированием, а не с содержимым — разреженная ванильная .nbt полой постройки и битово-упакованная .litematic того же самого решают разные проблемы.