Перейти к содержанию

Почему это не «скачать и заменить»

Самый частый вопрос — «зачем такая сложная программа, ведь моды это просто файлы?». Объясню на примере, что произойдёт если делать наивно.

Наивный план

Скачать dlc.rpf от мода, положить в <GTA>\update\update.rpf, перезаписать. Готово. Так делает половина инструкций «как поставить мод» на ютубе.

Это работает. Один раз. Для одного мода. На конкретной версии GTA. Без второго мода поверх. Без отката. И без возможности нормально удалить.

Что ломается дальше — почти всё.

Что внутри update.rpf

update.rpf это не один файл с DLC. Это архивный том в формате RPF8 размером ~2 ГБ, внутри которого иерархия каталогов и десятки тысяч ресурсов: текстуры (.ytd), модели (.ydr/.ydd/.yft), партиклы (.ypt), скрипты-конфиги (.meta/.ymf/.ymt), флэш-вектора для интерфейса (.gfx), звук (.awc), и вложенные .rpf внутри .rpf (например x64/dlcpacks/mpchristmas/dlc.rpf).

Каждый файл внутри RPF имеет:

  • свой Encryption flag (зашифрован AES-CTR с одним из 101 NG-ключа, либо без шифрования);
  • свой Compression flag (DEFLATE или сырой);
  • запись в TOC шапки архива с offset, size, checksum;
  • если это ресурс (.ydr/.ydd/.yft/.ytd/.ypt) — внутри второй слой: RSC7 header с pageMap, embedded SHA, version, virtual/physical page tables.

Если хоть один из этих параметров отъехал — игра выкинет файл целиком, и поведёт себя по-разному:

  • битая текстура → отсутствующая моделька на карте, синий gizmo вместо ассета;
  • битая модель → краш в момент загрузки уровня;
  • битый core.ypt (партиклы / трейсера) → краш в стрельбе или вообще на загрузке катсцены;
  • битый manifest.ymf → DLC не подгружается, мод не виден вообще;
  • битый header архива → игра пишет An exception occurred while loading game files. Files may be corrupted. и не запускается.

Что произойдёт с наивной заменой

Сценарий 1: первый мод поверх чистой GTA

Юзер качает redux_v1.rpf, переписывает свой update.rpf. Работает. Игра грузится с новой графикой.

Но если эта redux_v1.rpf упакована не идеально (а так и есть — её делал автор мода в CodeWalker, который нормализует имена файлов в lowercase и не пересчитывает некоторые внутренние checksum'ы) — рандомные крэши при загрузке катсцены. Юзер думает «у меня плохой комп» и сидит без мода.

Сценарий 2: второй мод поверх первого

Юзер хочет добавить кастомную минимапу к уже установленному redux'у. Качает второй .rpf, переписывает. Минимап работает. Redux пропал. Потому что новый файл — это другой update.rpf целиком, который вообще не знает что юзер хотел сохранить redux.

Сценарий 3: откат

Юзер захотел вернуться к ванилле, либо переустановить мод. Где взять оригинальный update.rpf? Rockstar Launcher его не восстанавливает — он проверяет только наличие файла, не содержимое. Нужно reinstall'ить всю GTA (~100 ГБ).

Сценарий 4: апдейт GTA

Через месяц Rockstar выпустил патч игры. Их updater скачивает delta-патч для update.rpf. Но у юзера там мод. Updater либо отказывается применять patch (хеш не сошёлся), либо его применяет и портит файл, либо просто скачивает новый update.rpf целиком — и мод исчезает.

Сценарий 5: античит на RP-сервере

Сервер при коннекте проверяет хеш файлов из update.rpf против своей белой таблицы. Файл подменён — кик. Если автор мода менял что-то лишнее (не нужное для визуала) — игрок кикается за то что хотел просто чуть красивее картинку.

Что делаем мы

Не подменяем файл целиком. Парсим оригинальный .rpf от мода, выделяем только те внутренние файлы что реально менялись против чистой версии, упаковываем их в наш собственный формат (patch.zip + manifest.json), считаем SHA-256 каждой части. Эта пара лежит на R2.

При установке юзеру:

  1. Считаем SHA его текущего update.rpf. Сравниваем с reference SHA для его версии игры (таблица gta_versions в Supabase) и с SHA после последней нашей установки (install_state.json).
  2. Если SHA не совпадает ни с чем — значит юзер модифицировал файл руками или другим лаунчером. Спрашиваем подтверждение, потом восстанавливаем чистую версию из локального кеша.
  3. Открываем чистый update.rpf через RageLib, проходим по дереву рекурсивно, копируем нетронутые файлы, заменяем модифицированные на наши из patch.zip, обрабатываем вложенные .rpf (например x64/dlcpacks/mpchristmas/dlc.rpf — там тоже могут быть правки).
  4. Атомарно (через временный файл + rename) пишем результат.
  5. Запускаем ArchiveFix.exe — внешний нативный инструмент, который пересчитывает все хеши TOC шапки. Без него GTA отбросит файл даже с валидным содержимым.
  6. Если процесс был убит между шагами 3 и 5 — на следующем запуске лаунчера OrphanBackupRecovery находит висячий .bak и откатывает.
  7. Записываем новый SHA в install_state.json. Следующая установка увидит «LAST = X» и поймёт что юзер не трогал файл руками.

В результате юзер может поставить redux, поверх него минимапу, поверх неё свой crosshair, потом откатить crosshair, потом снести вообще всё — и каждый раз получит рабочую GTA. И это не повредит оригинальный архив игры, потому что мы храним чистую копию отдельно.

Цена этого

  • Парсер мода (адмиn заливает новый redux). Сейчас 8–20 секунд на 1.5 ГБ архив.
  • Инжект на стороне юзера. 6 секунд на пересборку 2 ГБ архива на NVMe. Было 4 минуты в первой версии — как мы это вытянули.
  • Размер patch.zip. Типичный redux — 100–300 МБ против 2 ГБ полного .rpf. Юзер экономит в десятки раз на трафике против скачивания мода целиком.
  • ~3 000 строк C# в Core. Реальной формат-логики там немного, основное — корнер-кейсы.

Чего мы не делаем

  • Не патчим .exe GTA. У нас нет инжекта в процесс игры, нет хука Direct3D, нет шейдер-мода. Только файлы на диске. Игра запускается обычным образом через Rockstar Launcher.
  • Не пишем в Documents\Rockstar Games\GTA V\ (это пользовательские настройки, рабочая папка игры). Только в <GTA install>\update\update.rpf и в наш собственный %LocalAppData%\MiamiGraphics\.
  • Не патчим античит. RP-сервера сами решают что разрешено — мы стараемся менять только те файлы что они и так разрешают (визуальные). Trust on use.

Дальше: формат RPF8 →