Обновление игровых файлов

Рейтинг: 0Ответов: 2Опубликовано: 15.03.2023

Я разрабатываю игру на C++ с использованием DirectX 9. Это 3D шутер от первого лица (так планируется). В корневой папке с проектом есть ресурсы игры, такие как: configs, models, sounds и locations. К этим файлам очень легко получить доступ. Любой пользователь может заменить модели, звуки или вообще украсть их... Я разработал контейнер, где я упаковываю игровые ресурсы в архив, типа: configs.pck, models.pck и т.д. Игра работает через лаунчер, где этот инструмент проверяет HASH суммы файлов. Данные он берет с сервера. И тут я встретил проблему, которую я не как не могу решить. Как-то эти все файлы нужно обновлять!

Я написал совершенно другую программу, где в корневых файлах ищет версии всех клиентов игры. И создает их патчи. То есть ищет один файл в старой сборке и в новой. Через бинарный анализ ищет байты, которые не хватает в старой сборке или тех, которых воообще нет. Честно? Анализатор вышел очень плохой. Патчи были размером больше, чем оригинал файла. Так как сохранялось и стартовая позиция offset байта и длина и сами данные. Учитывались флаги состояния буфера. Или заменить, или удалить и т.д. Следовательно из-за корявого анализатора не получилось и грамотно сделать и патчинг этих самых файлов. Игровой движок вылетал с ошибкой, что файлы были повреждены. А лаунчер бесконечно старается решить проблему с HASH суммами файлов. Так как после патчинга они всегда разные.

В анализаторе нужно учитывать не просто замена байтов. Эта замена может быть не просто с 3 байтами 0x1, 0x2, 0x3 на 0x15, 0x2, 0x1. А в оригинале может быть и больше байтов, чем в старом блоке. Нужно учитывать множество факторов, чтобы анализатор понял, что с этим куском данных делать.

Небольшая дополнительная информация о этапах загрузки
При парсинге карты и ее сборки, в ней же лежат ссылки на long offsets блоках данных. Эти блоки нужны для того, чтобы как бы вытягивать модели из контейнера. Я ставлю нужный offset из карты в поток чтения models.pck и начинаю читать первые 4 байта - это длина одной модели. Как только данные считались, идет расшифровка простым XOR с ключем (Который загружается с сервера).

Подскажите куда мне копать? Где посмотреть формулы? Есть может у кого готовое решение?

Ответы

▲ -1Принят

Нашел на просторах гита вот такое решение: https://github.com/google/diff-match-patch/blob/master/cpp/diff_match_patch.cpp
Полностью решил свои все проблемы, спасибо всем кто пытался помочь.

▲ 0

Предположения и допущения (прошу уточнить в комментариях, верно ли я полагаю):

  • вопрос по сути о том, как организовать апдейтер для ресурсов игры.
  • упакованные ресурсы зашифрованы (либо шифром, либо архивированием, иначе толку от простой упаковки в вашем сценарии почти ноль).
  • в идеальном случае, зашифрованные и/или упакованные данные - это белый шум (а иначе, дешифровка и распаковка нехитрое дело). Разница между двумя "шумами" равна шуму.

Таким образом, построение дифференциальной разницы ПОСЛЕ создания упаковок - нецелесообразно. Надо её делать на шаге ДО упаковки.

  1. Берете, например, корпус ресурсов версии 1.0 и сравниваете его с корпусом 1.1. Для простоты - можно просто по-файлово. Получаете дифф.разницу (уж тут должно быть тривиально, какие файлы добавились, какие удалились, какие заменились).
  2. Пакуете и шифруете разницу, называете например patch1.pck.
  3. Теперь игре надо уметь, при загрузке составить карту ресурсов на текущую версию. Т.е. определить, что будет взято из оригинального models.pck, а что из patch1.pck (а что из patch2.pck, а что более недоступно, т.к. удалено).
  4. Играете.

Разумеется, тут возможны дальнейшие оптимизации типа:

  • делать дифф не по файлам, а по содержимому с использованием более хитрых алгоритмов (например Венгерского) для минимизации размера диффа (см. комментарии про rsync).
  • при апдейте перепаковывать ресурсы, внедряя патч в ресурсы.
  • делать кросс-патчи для разных версий
  • итп итд

P.S. Важно понимать, что от воровства ресурсов 100% защиты нет. Подменная DLL-ка с потрохами выдаст все модели, текстуры и шейдеры. Так что шифровка - это защиты от дурака, не более. Соответственно не тратьте на нее слишком много сил и времени.