Как я копался в сохраненке кубической песочницы.
Данный пост, возможно, будет интересен тем кто захочет сделать свою кубическую песочницу чтобы узнать о одной из возможных реализаций хранения данных.
В посте приведены данные годичной давности.
Год-два назад я увлекался игрой в такую кубическую песочницу как Starmade.
Игру пишут на Java (номер версии игры до сих пор не переступил цифру 1.0), графический движок LWJGL, и это можно было бы назвать клоном Minecraft (движок тот же и тот же "кубизм"), если бы это не было космической песочницей с свободой передвижения по всем трем осям.
Если в Майнкрафте некоторые маньяки фанаты строили огромные замки и прочие циклопические здания, то в Стармейде строят космические корабли не менее грандиозные - как авторские задумки так и реализации кораблей из разных SciFi вселенных, впрочем, те же замки тоже можно строить, только теперь они еще и летать смогут.
Рекомендую ознакомиться с официальными и неофициальными трейлерами от сообщества хотя бы ради общего интереса.
Случилось мне пересечься с группой таких строителей.
Говорят "Тыжпрограммист, выручай, у нас и так много времени уходит на постройку корпуса корабля, сделай ка программу чтобы обшивку полублоками сглаживала".
Ассортимент форм блоков используемых для решения данной задачи представлен на картинке.
Стоит также добавить, что блоки разных видов, включая различие в форме, цвете и материале в игре считаются совершенно разными и имеют разные ID, на уровне внутренней структуры группировки нет, хотя для удобства игроков в UI игры все же добавили такую группировку.
В сети, конечно, уже были разные наработки, но не знание языков и опыта вынудили создавать свой велосипед.
Перейдем к разбору.
В первую очередь для создания моей программы представляет интерес два файла, которые нам отправляет игровой сервер:
ServerName.properties - список с идентификаторами (именами) и номерами блоков
ServerName.xml - файл XML формата с описанием, наверное, всего что клиенту игры следует знать, сюда включается описания свойств каждого используемого типа блоков на сервере: иконка, текстура, масса, max HP, броня, геометрия, можно ли блок включить и большое число других малопонятных свойств. В этом файле блоки обозначаются по имени, а игра хранит блоки как цифры, поэтому предыдущий файл тоже важен.
На основе этих двух файлов я формирую массив информации о блоках который поможет правильно привести сырые данные по блокам в удобный для программы вид.
В игре отстроенный корабль можно сохранить в виде Blueprint-а, и потом его можно либо заспавнить админскими командами, либо "купить" за ресурсы или игровую валюту.
Основным моим объектом интереса и были блюпринты.
В понимании формата мне помогли добрые люди, разобравшие его и выложившие описание в открытый доступ. Конечно, я пытался и сам разобраться, но ковыряние в скомпиленных файлах Java не мой конек.
К тому же, мне все равно пришлось уточнять некоторые детали формата самому, где методом тыка, где перебором значений - игра застряла на стадии открытой беты и формат блюпринта немного меняется с новыми версиями, так что опубликованные описания формата немного отставали от реального положения дел.
Для моих целей были интересны header.smbph (файл статистики) и DATA (сами блоки). Кроме папки DATA также могут быть папки с "вложенными блюпринтами" - на корабле могли быть турели, которые по сути сами являются отдельными кораблями. По ТЗ такой случай не рассматривался.
header.smbph
Тип объекта - поддерживаются такие объекты как: планета, астероид, станция, корабль, магазин, "неизвестно".
Границы - координаты стен "коробки" в которую поместится корабль, центр корабля и коробки находится в блоке с координатами (0,0,0), это первый блок корабля при постройке и является его ядром.
Массив статистики, собственно, содержит информацию о типе и количестве блоков в корабле.
Данный файл используется для определения поместится ли корабль в точке спавна и сколько ресурсов требуется для его постройки без необходимости пересчитывать блоки блюпринта каждый раз.
logic.smbpl
В игре используются "блоки-контроллеры". Например, контроллер оружия знает какие пушки он включает, а одна пушка состоит из группы блоков, количество которых определяет мощность. Также есть блоки-модификаторы и блоки логики, которые также знают на какие дочерние блоки они воздействуют.
Все это хранится в данном файле, но поскольку мне его трогать было не нужно, разбор данного файла не производился.
meta.smbpm
Тут хранится информация о пристыкованных объектах (турели и доки).
Также, судя по описанию, тут еще много чего может храниться, вплоть до сериализованных объектов Java. Для меня тут черная магия.
Я не хочу копировать чужие таблицы по этим двум файлам, поскольку не имел опыта работы с ними и не знаком с ньюансами их формирования.
Cама большая работа была с папкой DATA
Тут хранятся файлы-чанки с информацией о блоках.
Файлы начинаются с имени блюпринта, далее через точку идет смещение данного чанка относительно центра, координаты соседних чанков отличаются на единицу, получается формат вида
имя.X.Y.Z.smd2
Индексы чанков - показывают чанк с каким номером должен быть в этом месте, -1 если пусто.
Timestamp - время последнего изменения.
Размер чанка и Размер сжатого чанка - чанк всегда имеет размер 5120 байт (для рассматриваемой версии игры), при этом "лишнее" место оставшееся после сжатия забивается нолями.
Данные с блоками - после распаковки дает массив размера 16^3 с элементами по 3 байта.
Лично меня структура файла немного смутила - на лицо дублирование значений да и вдруг сжатый чанк не уместится в отведенное место. Возможно это был компромиссный вариант на то время.
В зависимости от типа блока его кодирование немного отличается.
В первом 3 бита отвечают за направление "лица" блока.
Во втором и третьем два бита отвечают за поворот "лица" по часовой стрелке, остальные - за его направление.
В процессе решения задачи обнаружилось, что X и Z координаты в данных внутри файлов и в имени файлов имеют разный порядок. Возможно это как-то связано с обратным порядком записи байтов в сохраненных переменных.
Также некоторые проблемы были с приведением системы координат блюпринта (файл-чанк-блок) к единому знаменателю.
И еще о координатах - в Blueprint блок с координатами (0;0;0) находится в центре чанка.
На этом обзор формата хранения я заканчиваю.
Работа алгоритма разбивалась на два этапа - поиск мест для блоков с большим числом квадратных граней, затем для блоков с большим числом треугольных граней. И все это присолено выбором как повернуть блок чтобы он стал правильно.
Итог:
Когда я закончил "сглаживальщик",то я не встретил особого потока энтузиазма, отзывов и пожеланий у ребят которые его просили сделать.
Формат данных к тому моменту в очередной раз изменился, а разбираться в новом формате или дорабатывать имеющийся при отсутствии отдачи особого желания уже не было.
В сухом остатке - файл с константами и типами данных , и файл с функциями для вытаскивания и запихивания данных.
Если кому интересно, то можно вот тут посмотреть описание формата Blueprint данной игры на английском языке (часть информации могло устареть)
Поздравляю с реализацией Марширующих кубов! Каждый уважающий себя второкурсник должен сделать нечто подобное.
Порекомендовал бы писать моды для Space engineers, там внутриигровые скрипты на C# имеются, довольно востребованная штука.
Это о многом говорит про игру, если пользователям приходится подпирать костыли костылями для того, чтобы их творения выглядели лучше.
На самом деле не играл, но по таким играм знаком с предметом рассмотрения.
(Алсо, автор - молодец)
Непонятно, но круто =)