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. В нём хранятся глобальные параметры игрового мира, например время суток, здоровье игрока, наполнение инвентаря, скорость и позиция и т.д. Важнее то, что в нём хранится случайное зерно, которое используется генератором уровня при наполнения мира блоками.
Всё это также можно изменить, использовав программы, такие как: NBTExplorer.

Этот файл имеет следующую древовидную структуру:

- 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 тактов, 24 000 тактов в одних игровых сутках, что делает их длиной 20 реальных минут. 0 — это начало цикла день/ночь, 12 000 — начало захода солнца, 13 800 — начало ночного времени, 22 200 — начало восхода солнца, 24 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 соответствует десяти сердцам (каждое очко здоровья — половина сердца). - 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_Byte(

- TAG_Compound(): Объект в ячейке инвентаря.

- TAG_Int(

- TAG_Long(

- TAG_Compound(

### Формат чанков

Формат файла чанка имеет такую же структуру, как и *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_Int(

- TAG_Compound(