Имя | Тип | Длина | Описание |
---|---|---|---|
⬤ Версия файла | int16
|
2 байта | Номер версии файла сохранения. |
⬤ Смещение Двоичных Данных | int32
|
4 байта | Это смещение файла, с которого начинаются встроенные двоичные данные. |
⬤ Неизвестно | int32
|
4 байта | Кажется, это неиспользуемые данные (все тесты считываются 0) |
⬤ Смещение Таблицы Имен | int32
|
4 байта | Это смещение, с которого начинается таблица имен. |
⬤ Смещение сегмента данных объекта | int32
|
4 байта | Это смещение, с которого начинаются сериализованные данные объекта (свойства). |
⬤ Время игры | float
|
4 байта | В этом разделе хранится внутриигровое время. |
⬤ Счетчик сохранений | int32
|
4 байта | В этом разделе хранится количество сохранений файла. |
Формат Соранения Файла (ASE)
На этой странице описан пользовательский формат файла сохранения, используемый ARK: Survival Evolved в файлах .ark
, и она предназначена для всех, кто хочет изучить или прочитать файлы сохранения напрямую. Файлы .ark
содержат текущее состояние мира, включая существ, инвентарь, предметы, построенные конструкции и состояние листвы. Это двоичный файл с несколькими сегментами, и в настоящее время существует одиннадцать версий формата с номерами от 1 до 11. На этой странице основное внимание уделяется версии 9.
Чтобы понять все это, вам нужны базовые знания о Двоичных файлах и базовое понимание представления чисел в памяти (числа с плавающей запятой, целые числа, и т.д.).
Основной процесс чтения данных файла сохранения Ark выглядит следующим образом:
- Чтение Объекта заголовка файла Ark
- Чтение Объекта имен двоичных данных
- Чтение Объекта таблицы имен
- Чтение Встроенного объекта двоичных данных
- Чтение Неизвестного объекта данных
- Чтение Массива игровых объектов
- Для каждого из игрового объекта прочтите Свойства объекта
Сегменты
Заголовок Файла
Заголовок расположен в самом начале файла и содержит такую информацию, как адреса сегментов, количество сохранений и общее время воспроизведения.
Объект Имен Двоичных Данных
Чтобы прочитать эту таблицу, вам нужно прочитать данные Строк в объект столько раз, сколько было указано в длине массива.
Имя | Тип | Длина | Описание |
---|---|---|---|
Длина массива | Int32 | 2 байта | Это говорит нам, сколько Строк содержится в этом массиве. |
Строковые данные | Строка | Неизвестные байты | Размер этих объектов неизвестен, поскольку данные считываются на лету. |
Таблица Имен
Концепция
"Имена" - это концепция Unreal Engine, которая (в рамках движка) позволяет эффективно сравнивать строки (нужно сравнивать только индексы или хэши (вычисляемые внутри), а не всю строку целиком) и сокращать использование памяти для часто повторяющегося текста. Имена состоят из двух частей:
- Центральная строковая таблица (которой является этот сегмент), которая в двоичном файле специфична для файла и объединена в глобальную, общую для всех объектов в движке во время выполнения;
- И ссылки на эту таблицу, состоящие из индекса таблицы
int32
и номера экземпляраint32
.
Ненулевой номер экземпляра добавляется (уменьшается на единицу) к строке, которой предшествует одиночное подчеркивание.
Распространенным "вариантом использования" имен являются имена объектов и активов, пути, имена и типы свойств и другие строки, которые могут часто появляться.
Сериализованный формат
Этот сегмент начинается со смещения, найденного в заголовке.
Имя | Тип | Длина | Описание |
---|---|---|---|
Длина массива | int32
|
4 байта | Это говорит нам, сколько строк содержится в таблице. |
Записи | string[]
|
Последовательность строк, завершающаяся нулем, количество которых определяется вышеупомянутым полем длины массива. |
Встроенный Объект Двоичных Данных
Использование этих данных неизвестно, мы будем читать массив массивов, содержащих числа Int32. Сначала мы прочитаем длину массива и выполним цикл столько раз, в каждом из этих циклов мы будем:
Считайте следующие 4 байта как Int32 и выполните цикл много раз, считывая каждый раз другое значение Int32 в SubArray.
Имя | Тип | Длина | Описание |
---|---|---|---|
Длина массива | Int32 | 4 байта | Это говорит нам о том, сколько массивов содержится в этом массиве |
SubArray Length | Int32 | 4 байта | Это говорит нам, сколько Строк содержится в этом массиве. |
Данные Int32 | Int32 | Длина подмассива * 4 байта | Числа Int32 в массиве |
Неизвестный Объект Данных
Это какой-то неизвестный объект данных, нам нужно правильно его прочитать на случай, если Ark в какой-то момент его использует.
Имя | Тип | Длина | Описание |
---|---|---|---|
Длина массива | Int32 | 4 байта | Это говорит нам, сколько массивов содержится в этом массиве. |
Неизвестный номер | Int32 | 4 байта | Это неизвестный номер, который выглядит как какой-то флаг. |
Неизвестное количество объектов | Int32 | 4 байта | Это неизвестное число, которое, похоже, сообщает нам количество объектов. |
Строковые данные | String | Неизвестные байты | Некоторые неизвестные строковые данные |
Таблица Метаданных Объекта
Это основной сегмент, который действует как индекс всех объектов игрового мира, содержащихся в файле.
Имя | Тип | Длина | Описание | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Длина массива | Int32 | 4 байта | Это говорит нам, сколько записей находится в этой таблице. | ||||||||||||||||||||||||||||||||||||||||||||||||
Записи |
|
Свойства Объекта
Это одна из самых "забавных" частей для чтения данных. Чтобы создать этот объект, мы заполним его массивом объектов, которые мы прочитали из файла. Сначала нам нужно просуммировать смещение блока свойств объекта заголовка файла Ark со смещением свойств игрового объекта и начнем чтение оттуда, пока не достигнем имени класса с именем "None"
Имя | Тип | Длина | Описание |
---|---|---|---|
Имя класса | Объект класса Ark | 8 байт | Имя класса свойства, если результат равен "None", нам нужно прекратить чтение в конце этого свойства. |
Свойства Содержание | Свойства Объекта | Неизвестные байты | Если предыдущее имя класса не было "None", то мы начинаем считывать содержимое свойства соответствующим образом |
Неизвестное целое число | Int32 | 4 байта | Неизвестное целое число, которое всегда равно 0 (это может быть просто NUL длиной 4 байта) |
Дополнительные данные | Дополнительный объект данных | Неизвестные байты | Иногда в конце свойств содержатся дополнительные данные. Вам следует сохранить эти данные, поскольку они могут содержать важную информацию. |
Свойства Объекта
После прочтения имени класса свойства вам необходимо прочитать данные в соответствии с его классификацией:
Объект BoolProperty
Имя | Тип | Длина | Описание |
---|---|---|---|
Длина | Int32 | 4 байта | Длина в байтах данных для чтения |
Индекс | Int32 | 4 байта | Индекс прочитанных данных (используется для некоторых свойств, которые повторяются несколько раз) |
Ценность | PropertyBoolean | 1 Bytes | Логическое значение |
ByteProperty Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read, Funny enough this sometimes does not tell us the exact size of bytes to read. |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | UInt8 Or Ark Class Object Or Raw Bytes | 1, 8 or Unknown Bytes | If Length is 1 read as UInt8, If Length is 8 then Read as a Ark Class Object followed with a value of another Ark Class Object, If the Length is different read as Raw Bytes. |
FloatProperty Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | Float | 4 байта | The Float Value |
DoubleProperty Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | Double | 8 байт | The Double Value |
IntProperty Object
This is read the same as Int32Property Object
Int8Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | Int8 | 1 Byte | The Signed Int8 Value |
UInt8Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | UInt8 | 1 Byte | The Unsigned UInt8 Value |
Int16Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | Int16 | 2 Bytes | The Signed Int16 Value |
UInt16Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | UInt16 | 2 Bytes | The Unsigned UInt16 Value |
Int32Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | Int32 | 4 байта | The Signed Int32 Value |
UInt32Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | UInt32 | 4 байта | The Unsigned UInt32 Value |
Int64Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | Int64 | 8 байт | The Signed Int64 Value |
UInt64Property Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | UInt64 | 8 байт | The Unsigned UInt64 Value |
NameProperty Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
Value | Объект класса Ark | 8 байт | The Ark Class Name Object |
ObjectProperty Object
Имя | Тип | Длина | Описание |
---|---|---|---|
Length | Int32 | 4 байта | Length in bytes of the data to read |
Index | Int32 | 4 байта | Index of the data read (Used on some properties that repeat themselves multiple times) |
ID | Int32 | 4 байта | This is an ID of some sort (Unknown use) |
Value | Int32 Or Ark Class Object | 4 or 8 Bytes | If the Length is 8 then Read the Int32 value, if it's 12 read the Ark Class Object as Value |
StructProperty Object
ArrayProperty Object
PropertyText Object
StrProperty Object
Ark Class Object
When reading an Ark Class Object you need to read always 8 bytes, and when an index is defined (more than 0) you need to append that index at the name of the class, so if you have your Name Table Object and in position #72 you have PrimalItem_WeaponEmptyCryopod_C (Note: There's no position 0 on the Name Table Object) it means that if your index = 1 you need to append _0 at the end making it PrimalItem_WeaponEmptyCryopod_C_0 and if your index=135 then you need to append _134.
Имя | Тип | Длина | Описание |
---|---|---|---|
ID | Int32 | 4 байта | The corresponding ID on Name Table Object |
Index | Int32 | 4 байта | The index of this Name, the game takes the Names and represents them with a _INDEX at the end, if this number is 0 we do not append a _0 to the name, we leave the original name as is, if we find a 1 or more in this value we need to start counting from 0, which means that Index=1 is Append=_0 |
Data Types
Below are the data types and how to read them accordingly.
String
Имя | Тип | Длина | Описание |
---|---|---|---|
String Length | Int32 | 4 байта | This tells us how many bytes to read |
String Data | String | String Length bytes | Read this data as a string, keep in mind the last character will be a 0x00 NUL character. |
Bool
Read 32Bit (4 Byte) In which the least significant bit indicates true
Double
Read 64Bit (8 Byte) Double Number
Float
Read 32Bit (4 Byte) Float Number
Int8
Read 8Bit (1 Byte) Signed Integer
UInt8
Read 8Bit (1 Byte) Unsigned Integer
Int16
Read 16Bit (2 Byte) Signed Integer
UInt16
Read 16Bit (2 Byte) Unsigned Integer
Int32
Read 32Bit (4 Byte) Signed Integer
UInt32
Read 32Bit (4 Byte) Unsigned Integer
Int64
Read 64Bit (8 Byte) Signed Integer
UInt64
Read 64Bit (8 Byte) Unsigned Integer
PropertyBoolean
Read 8Bit (1 Byte) In which the least significant bit indicates true.