Alpha формат карт
Alpha формат карт — формат хранения файлов игрового мира, который развил и усовершенствовал новую технологию, введённую во время работы над версией Infdev.
Во время разработки Minecraft Infdev был введён новый метод хранения данных: максимальный объём данных игрового мира составлял почти 235 петабайт (или 240 640 терабайт), что в несколько раз больше площади поверхности Земли. Поэтому чтобы уменьшить объём данных игрового мира и выделение оперативной памяти, Нотч разделил весь мира на т. н. чанки, размер которых составлял 16 x 128 x 16 блоков. Из них те, которые игрок не видит, хранятся на жестком диске, а не в оперативной памяти. В дополнение к этому, генерация игрового мира происходит только в определенном радиусе от игрока, что значительно уменьшает объём сохранений игры, поскольку игроки не могут быстро исследовать карту. Более поздние версии игры, такие как Alpha, Beta и Minecraft 1.0, до сих пор используют методику разбиения игрового мира на части из-за её эффективности.
Содержание
Структура папок игрового мира
Файлы игрового мира в версии Alpha хранятся в одной директории, которая содержит по крайней мере один файл под названием level.dat. Там также хранится файл формата session.lock, который контролирует, чтобы только одно приложение Minecraft использовало данный игровой мир.
Директория игрового мира может вмещать до 64 поддиректорий, в каждой из которых может быть ещё 64 папки. Эти папки идентифицируются координатами расположения (по осям X и Z) хранящегося в них чанка. Внутри папки хранится файл, определяющий структуру чанка и его наполнение сущностями. Каждый файл чанка также идентифицируется его координатами. Различие частей имени файла чанка получается представлением координат X и Z чанка в системе Base 36. Имена папок, в которых хранится файл чанка, создаются путём получения остатка от деления координат X и Z на 64 (или операцией побитового логического умножения с 63), а затем число переводится в base36. Отрицательные координаты должны быть инвертированы в положительные числа следующим путём: отрицательное число с помощью дополнительного кода конвертируется в двоичное, а затем опять в десятичное. Например, -13 переходит в 243 (если его размер типа byte).
К примеру, чтобы найти чанк с координатами (-13, 44):
- Название первой папки в base36(-13 % 64). Это base36(243 % 64 = 51) что представляется как "1f".
- Название второй вложенной папки — base36(44 % 64). Это base36(44) что представляется как "18".
- Название файла чанка "c." + base36(-13) + "." + base36(44) + ".dat". Результат: "c.-d.18.dat"
- Таким образом, чанк (-13, 44) хранится в "1f/18/c.-d.18.dat"
Каждый чанк хранит собственную позицию вне зависимости от названия папки или его файла.
Заметка: для упрощения можно использовать конвертер из base10 в base36: Base-10 to Base-36 Conversion Calculator. Для конвертации десятичных чисел в дополнительные можно использовать 2's Complement of Binary Number Calculator. Для конвертации двоичного числа в десятичное будет полезен Decimal/Binary Conversion Tool.
В версии Beta 1.3 введён формат MCRegion, где чанки хранятся группами по 32x32 в region-файле.
Измерения
Файлы измерений хранятся так же, как и обычный мир, однако вместо их скопления внутри папки мира, они выносятся в дополнительную подпапку со своими собственными данными о чанках и регионах. Их название начинается DIM
, а заканчивается идентификационным номером измерения.
Такие идентификационные номера измерений использовались в Alpha:
ID | Папка | Измерение |
---|---|---|
0 | saves/[Мир]/ |
Обычный мир всегда хранился в общей папке без приставки DIM
|
-1 | saves/[Мир]/DIM-1/ |
Нижний мир, добавленный в Halloween Update |
Формат session.lock
Файл session.lock содержит метку последнего использования файлов игрового мира. Объём файла составляет 8 байтов и содержит одно 64-битное целое число со знаком (signed integer) в порядке байтов big-endian. Значение этого числа — временная метка, которая являет собой количество миллисекунд, прошедших с 1 января 1970 года, 00:00:00 UTC.
В отличие от стандартных lock-файлов, session.lock гарантирует то, что последняя программа, использовавшая игровой мир, есть та, которой он принадлежит. Весь процесс выглядит примерно так:
- Программа обращается к session.lock
- Программа записывает временную метку в session.lock
- Программа отслеживает изменения session.lock
- Если содержание файла session.lock меняется, программа делает возврат к последней точке сохранения и блокирует файлы игрового мира.
Формат level.dat
Файл level.dat представляет собой NBT-структуру, помещенную в архив GZip. В нём хранятся глобальные параметры игрового мира, например время суток, здоровье игрока, наполнение инвентаря, скорость и позиция и т.д. Важнее то, что в нём хранится случайное зерно, которое используется генератором уровня при наполнения мира блоками.
Этот файл имеет следующую древовидную структуру:
- TAG_Compound(""): корневой тег.
- TAG_Compound("Data"): глобальные данные уровня.
- TAG_Long("LastPlayed"): хранит дату и время последнего сохранения мира в формате времени UNIX.
- TAG_Long("SizeOnDisk"): расчетный объем всего игрового мира в байтах.
- TAG_Long("RandomSeed"): случайное число, выступающее в качестве зерна для механизма генерации мира.
- TAG_Int("SpawnX"): координата точки спауна по оси X.
- TAG_Int("SpawnY"): координата точки спауна по оси Y.
- TAG_Int("SpawnZ"): координата точки спауна по оси Z.
- TAG_Long("Time"): хранит текущее время игровых суток в тактах. В одной реальной секунде 20 тактов, и 240 00 тактов в одной игровых сутках, что делает её длиной 20 реальных минут. 0 — это начало цикла день/ночь, 12 000 — начало захода солнца, 138 00 — начало ночного времени, 22 200 — начало восхода солнца, 240 000 — начало дневного времени (конец цикла). Значение, которое хранится в level.dat, всегда только увеличивается и может быть большим чем 24 000, но "время суток" в поле "Time" всегда в пределе 24 000.
- TAG_Compound("Player"): игрок в однопользовательской игре.
- TAG_Int("Dimension"): измерение, в котором находится игрок. 0 — обычный мир, а -1 соответствует Нижнему миру.
- TAG_List("Pos"): список 3-х TAG_Doubles для осей X, Y, и Z для определения положения игрока в пространстве.
- TAG_List("Rotation"): список 2-х TAG_Floats для осей наклона и рыскания — определение места, в которое смотрит игрок, то есть расположения головы.
- TAG_List("Motion"): список 3-х TAG_Doubles для осей X, Y, и Z. Значения определяют скорость движения игрока по осям (блоков за такт).
- TAG_Byte("OnGround"): 1 или 0 (true/false) - true если игрок на поверхности.
- TAG_Float("FallDistance"): количество блоков, которые игрок пролетел.
- TAG_Short("Health"): количество очков здоровья. 20 это 10 сердец.
- TAG_Short("AttackTime"): количество тактов, когда игрок невосприимчив до повреждений.
- TAG_Short("HurtTime"): количество тактов, когда игрок красный после получения урона.
- TAG_Short("DeathTime"): количество тактов, которые игрок был мертв - используется для контроля анимации смерти.
- TAG_Short("Air"): количество тактов до того, как игрок начал тонуть. Начинается с 300.
- TAG_Short("Fire"): когда значение отрицательное, количество тактов с момента возгорания игрока. Если число положительное - количество тактов до тушения игрока.
- TAG_Int("Score"): счет игрока. Счет так и не был реализован технически, ни в Alpha, ни в Beta, поэтому это значение нерелевантное.
- TAG_List("Inventory"): список TAG_Compounds, которые определяют наполнения инвентаря игрока.
- TAG_Compound(): Объект в ячейке инвентаря.
- TAG_Byte("Slot"): конкретный слот в инвентаре.
- TAG_Short("id"): идентификационный номер объекта.
- TAG_Short("Damage"): данные про объект или значение повреждения для инструментов.
- TAG_Short("Count"): количество этих объектов в одной ячейке (слоте), то есть размер стопки (стака). Значение в границах от -128 до 127. Значения, меньшие 2, не отображаются в игре.
- TAG_Compound(): Объект в ячейке инвентаря.
- TAG_Compound("Data"): глобальные данные уровня.
Формат чанков
Формат файла чанка имеет такую же структуру, как и level.dat (архивированные файлы NBT). Структура:
- TAG_Compound(""): корневой тег.
- TAG_Compound("Level"): глобальные данные для этого чанка.
- TAG_Int("xPos"): координата чанка по оси X.
- TAG_Int("zPos"): координата чанка по оси Z.
- TAG_Byte("TerrainPopulated"): 1 или 0 (true/false) - true, если генератор Minecraft Alpha сгенерировал специальные натуральные структуры, такие как сокровищница или пещера.
- TAG_Long("LastUpdate"): количество тактов с последнего обновления этого чанка.
- TAG_Byte_Array("Blocks"): 32768 байты номеров блоков — 8 бит на один блок.
- TAG_Byte_Array("Data"): 16384 байты данных про блоки — 4 бита на один блок.
- TAG_Byte_Array("BlockLight"): 16384 байты на освещение блоков — 4 бита на блок.
- TAG_Byte_Array("SkyLight"): 16384 байты на солнечный свет — 4 бита на блок.
- TAG_Byte_Array("HeightMap"): 256 байты про карту высот, 8 битов на колону XZ. Используется для расчёта распространения дневного/ночного света.
- TAG_List("Entities"): список TAG_Compounds для описания сущностей на чанке.
- TAG_Compound(): Сущность.
- TAG_List("TileEntities"): список TAG_Compounds для описания дополнительной информации про сущность (tile entity) в чанке.
- TAG_Compound(): дополнительная информация о сущности.
- TAG_Compound("Level"): глобальные данные для этого чанка.