# Профили игр Общий конвейер (загрузка, очередь, хранилище блобов, моды, оболочка плеера) не знает подробностей конкретных игр. Всё, что относится к движку или к одной сборке игры, живёт в профиле — модуле в `backend/app/games/`. ## Что такое профиль Класс `GameProfile` (`app/games/base.py`): | Член | Назначение | | --- | --- | | `id` | Стабильный идентификатор в отчётах, например `tomie/expansion-1.3801` | | `engine` | Семейство движка из `compatibility.detect` (`renpy`, `naninovel`, …) | | `specific` | `True` для профиля, привязанного к одной сборке: он выбирается раньше общего профиля движка | | `runtime` | Значение `game.runtime`, если игре нужен отдельный плеер | | `claims(root)` | Дешёвая проверка, что профиль подходит (например, SHA-256 сборки) | | `inspect(root, work)` | Проверка совместимости без записи блобов; при отказе — `CompatibilityError` | | `convert(root, work, progress)` | Полный импорт в PGVN | | `validate_mod(game, scripts, manifest)` | Дополнительные проверки изменённого мода | | `unity_hooks()` | Расширение общего читателя Unity/Naninovel (`app/games/hooks.py`) | `app/games/registry.py` выбирает профиль: `select(engine, root)` — сначала `specific`-профили, затем общий профиль движка; `for_runtime(runtime)` — для валидации модов. Остальной код обращается только к реестру: `pipeline`, `preflight`, `compatibility.detect`, `mods`. ## Как добавить игру со своим конвейером 1. Создайте `backend/app/games/<имя>/` с классом профиля. Задайте `engine`, `specific = True`, `claims()` (хэш сборки, а не имя папки) и `inspect`/`convert`. 2. Особенности чтения Unity-данных вынесите в наследника `ReaderHooks` (`begin`, `accept_duplicate_script`, `scan_object`) и передайте его в `read_package(..., hooks=...)`. 3. Зарегистрируйте профиль в `app/games/__init__.py`. 4. Если игре нужен свой плеер, добавьте `runtime` и запись в `frontend/src/player/runtimes.ts` (загрузчик подгружается лениво). 5. Проверки: профиль закрывается по принципу «закрыто по умолчанию» — неизвестное отклоняется. Добавьте тесты по образцу `tests/test_tomie_*.py` и `tests/test_game_profiles.py`. ## Профили сейчас * `renpy` — `app/games/renpy.py`; конвертация остаётся в `converter/pipeline.py`, потому что объединяет распаковку архива, RPA и медиа. * `naninovel` — общий импорт Naninovel (`converter/naninovel.py`). * `tomie/expansion-1.3801` — `app/games/tomie/`: хэш сборки (`profile.py`), формат и нативный интерпретатор команд (`format.py`, `validation.py`), медиа (`assets.py`), хуки читателя (`reader.py`), известные дефекты оригинала (`defects.py`), проверка модов (`mod.py`), импорт (`convert.py`). ## Известные дефекты оригинала Профиль может перечислить ошибки самой игры (переход на несуществующую метку, ветка без `EndIf`), которые оригинал тоже не обрабатывает. Они не блокируют импорт, а попадают в отчёт как предупреждения; плеер на таком месте останавливается с явной ошибкой. Список точный: ключ — (код, сообщение, сценарий), значение — максимальное число. Новые или лишние случаи, в том числе в моде, по-прежнему отклоняются. Добавлять записи ради прохождения импорта нельзя.