202 lines
18 KiB
Markdown
202 lines
18 KiB
Markdown
# Автоматический импорт и проверка совместимости
|
||
|
||
PGames исполняет восстановленные сценарии в браузере. Наличие ресурсов игры
|
||
или распознанного движка само по себе не означает, что игра совместима.
|
||
|
||
## Порядок обработки
|
||
|
||
После получения архива API читает список файлов. Неизвестный движок,
|
||
неподдерживаемые Unity, Godot, GameMaker и RPG Maker отклоняются до очереди
|
||
конвертации. EXE-файлы не запускаются и не принимаются вместо архива игры.
|
||
|
||
Воркер проверяет сценарии перед конвертацией медиа. Для архивов Ren'Py сначала
|
||
извлекаются только сценарии и RPA; отдельно лежащие изображения, аудио и видео
|
||
на этом этапе не распаковываются. RPA со сценариями необходимо прочитать из
|
||
внешнего архива, но из самого RPA для проверки извлекаются только скрипты.
|
||
Для уже распакованных игр проверка выполняется до копирования медиа.
|
||
|
||
Определения неподдерживаемых функций и классов, вызовы отсутствующих функций,
|
||
переходы к отсутствующим меткам, выполняемые screen-команды, динамические ATL
|
||
и ошибки декомпиляции останавливают импорт. Объявление неиспользуемого screen
|
||
само по себе не является выполнением экрана. Кодировки сценариев читаются по
|
||
объявлению `coding:` либо как UTF-8; повреждённые символы не заменяются молча.
|
||
|
||
Ошибка имеет `engine`, `compatible: false` и список `issues` с кодом, причиной,
|
||
местом и количеством обнаруженных случаев. В интерфейсе версии доступны все
|
||
причины остановки. Неподдерживаемая игра не получает статус `ready`.
|
||
|
||
Проверка сценариев не является доказательством прохождения всех веток игры.
|
||
Она обнаруживает известные неподдерживаемые конструкции и явные ошибки.
|
||
Ошибка обработки медиа также останавливает конвертацию. Промежуточные блобы
|
||
не опубликованы в манифесте; их впоследствии удаляет сборщик мусора.
|
||
|
||
## Коллекция на диске
|
||
|
||
Команды выполняются из каталога `backend` в окружении с зависимостями проекта,
|
||
FFmpeg, 7-Zip и настроенным `UNRPYC_PATH`.
|
||
|
||
```powershell
|
||
python -m app.import_library "D:\Torrents\Pgames" --check --output report.json
|
||
python -m app.import_library "D:\Torrents\Pgames" --import --owner admin --output report.json
|
||
```
|
||
|
||
Для одной игры укажите `--single`: путь должен вести к её папке или архиву.
|
||
Проверяются сценарии и совместимость тем же способом, что при импорте:
|
||
|
||
```powershell
|
||
python -m app.import_library "D:\Torrents\Pgames\Renpy\DesertStalker-0.21.4-pc" --single --check --output desert-stalker.json
|
||
python -m app.import_library "D:\Games\SomeGame.zip" --single --check --output game.json
|
||
```
|
||
|
||
Для подробного разбора Ren'Py и сохранения извлечённых/декомпилированных
|
||
сценариев доступна диагностическая команда (без конвертации медиа):
|
||
|
||
```powershell
|
||
python -m app.converter.analyze --dump ..\data-test\renpy-dump "D:\Torrents\Pgames\Renpy\DesertStalker-0.21.4-pc"
|
||
```
|
||
|
||
Приоритет — общая поддержка синтаксиса и поведения Ren'Py в конвертере и
|
||
плеере. Патчи отдельных сборок находятся в `app/games/renpy_builds.py`;
|
||
замены блоков дополнительно проверяют SHA-256 исходного текста. Неизвестные
|
||
изменения проходят обычную строгую проверку. В DesertStalker 0.21.4 блок
|
||
восстановления нативных сохранений заменяется вызовом загрузчика PGames;
|
||
сохранения Ren'Py в формате pickle не переносятся.
|
||
|
||
Начальный код оригинальной игры можно дополнительно проверить в браузерном
|
||
интерпретаторе без конвертации медиа. После создания дампа выполните из `backend`:
|
||
|
||
```powershell
|
||
python -m tests.export_renpy_runtime "D:\Torrents\Pgames\Renpy\DesertStalker-0.21.4-pc" "..\data-test\renpy-dump\DesertStalker-0.21.4-pc" "..\data-test\desert-runtime.json"
|
||
```
|
||
|
||
Затем из `frontend`:
|
||
|
||
```powershell
|
||
$env:PGAMES_RENPY_RUNTIME = "D:\Github\pgames-manager\data-test\desert-runtime.json"
|
||
node --test tests/renpy-original.test.mjs
|
||
```
|
||
|
||
Это проверка `init`/`default` и сохранности загрузчика PGames; прохождение
|
||
сюжета, визуальные эффекты и все ветки она не подтверждает. Оригинальные
|
||
сценарии и дампы не включаются в репозиторий.
|
||
|
||
`--check` не создаёт карточек или версий и не изменяет исходные игры.
|
||
`--import` создаёт версии только для прошедших проверку игр. Обработка
|
||
коллекции продолжается после отказа отдельной игры. При наличии хотя бы одного
|
||
отказа команда завершается с кодом 2. Полный JSON-отчёт обновляется после каждой
|
||
игры. Для одноимённых папки и архива проверяется распакованная папка.
|
||
Повторный запуск `--import` создаёт новые карточки: это не синхронизатор каталога.
|
||
|
||
Нужно подключить каталог коллекции к контейнеру для использования команды
|
||
на сервере. Путь клиента Windows автоматически не становится доступен серверу.
|
||
Входные каталоги используются только для чтения; временная распаковка и
|
||
декомпиляция происходят отдельно.
|
||
|
||
## MIST 1.0.3 и общая поддержка Ren'Py
|
||
|
||
Оригинальная сборка MIST 1.0.3 проходит проверку сценариев и полную конвертацию:
|
||
3527 изображений, 355 аудиофайлов, 778 видео и 5 шрифтов. Общий плеер поддерживает
|
||
циклы `ui.interact()` с результатами `Return` от уже показанных экранов,
|
||
`renpy.movie_cutscene` с ожиданием/пропуском, регистрацию изображений через
|
||
`renpy.image`/`ImageReference`, пользовательские микшеры и базовую `Gallery`.
|
||
У видео `Movie` сохраняются маски прозрачности и режим повтора; красный канал
|
||
маски задаёт прозрачность кадра. Эти возможности применяются ко всем играм.
|
||
|
||
На исходных сценариях MIST проверены начальный код, победа/поражение QTE,
|
||
мини-игра поднятия руки и продолжение её цикла после загрузки сохранения.
|
||
Тесты `frontend/tests/mist-runtime.test.mjs` включаются переменной
|
||
`PGAMES_MIST_RUNTIME`, указывающей на JSON из `tests.export_renpy_runtime`.
|
||
`PGAMES_MIST_ORIGINAL` включает backend-проверку оригинального дистрибутива.
|
||
Полное прохождение сюжета и визуальная проверка каждой сцены не подтверждены.
|
||
|
||
В оригинальном `scripts.rpa` есть четыре перехода на отсутствующие метки
|
||
(`robinspent`, `breakfastdialog`, `firstdungeontalk`, `afterrscene09`) и показ
|
||
отсутствующего `newbuildingcontrolscreen`. Профиль `renpy/mist-1.0.3` распознаёт
|
||
сборку дополнительно по SHA-256 сценарного архива и допускает только эти пять
|
||
дефектов с исходным количеством вхождений. Они остаются предупреждениями;
|
||
при достижении такого места плеер останавливается с явной ошибкой. Замены
|
||
сюжетных переходов не подставляются. Изменённые сценарии проверяются заново.
|
||
|
||
В отчёте также перечислены 22 ссылки на отсутствующие медиа оригинала,
|
||
включая старые объявления анимаций, иконку `Roastedfish_Kachel.png` и два
|
||
side-изображения. Они не подменяются другими картинками; это ограничение
|
||
самого дистрибутива, которое нужно учитывать при проверке конкретных веток.
|
||
|
||
## Текущая поддержка Naninovel
|
||
|
||
Добавлен импорт скомпилированных сценариев из Unity-ресурсов Mono-сборок
|
||
Naninovel. Код игры не запускается. Для поддерживаемого старого формата
|
||
managed references схемы берутся из сохранённых метаданных или DLL игры,
|
||
результат чтения проверяется побайтным циклом записи. Неизвестная схема или
|
||
различающиеся копии сценария приводят к отказу.
|
||
|
||
Поддерживается ограниченное подмножество: реплики и продолжения реплик,
|
||
переменные, безопасно разобранные выражения, if/else, статические переходы
|
||
и подпрограммы, выборы с `GotoPath`, паузы, показ и скрытие текста,
|
||
статические изображения/персонажи, базовые аудиокоманды и выход в меню.
|
||
Все параметры команды проверяются; неизвестные параметры также вызывают отказ.
|
||
Изображения и аудио разрешаются по однозначному имени ресурса. Для иных схем
|
||
ресурсов, внешних интерфейсов и игровых расширений нужен дополнительный адаптер.
|
||
|
||
Служебные выражения не исполняются как Python или JavaScript: сервер разбирает
|
||
их в AST, а браузер вычисляет разрешённые операции. Текст переводится до
|
||
подстановки переменных. Переменные и накопленные варианты выбора входят в
|
||
состояние сохранения общего плеера.
|
||
|
||
Извлекаются адресуемые текстовые записи из `DefaultUI`, `Tips`, `CharacterNames`,
|
||
`Inventory`, файлов `StreamingAssets/text` и соответствующих встроенных TextAsset.
|
||
Части подсказок и синонимы имеют отдельные записи. Ключи и разделители остаются
|
||
в метаданных. Редактор переводов использует устойчивые ID записей; изменение
|
||
выражений, тегов и служебных разделителей отклоняется при сохранении перевода.
|
||
Имена персонажей используют словарь `CharacterNames` при его наличии.
|
||
|
||
### Tomie
|
||
|
||
Добавлен отдельный адаптер `tomie/1` для Expansion 1.3801. Он выбирается по
|
||
SHA-256 оригинальной `Assembly-CSharp.dll`; переименованная или новая сборка
|
||
не получает этот профиль автоматически. Таблицы имён, комментариев и видео
|
||
читаются из констант IL без запуска DLL. Исходные переменные восстанавливаются
|
||
из `CustomVariablesConfiguration`, образы — по ключам Unity ResourceManager.
|
||
Дубли Texture2D/Sprite под одним ключом разрешаются в пользу полной текстуры.
|
||
|
||
Плеер использует исходный список команд Naninovel. Проверены создание персонажа
|
||
до поля на извлечённых Unity-сценариях и цепочки дня/ночи на данных Godot-порта.
|
||
Перенесены игровые функции, динамические обработчики выбора, поле и кубики,
|
||
инвентарь, сообщения, сцена, видео, эффекты и мини-игра. Сохранение включает стек
|
||
подпрограмм, очередь команд, варианты выбора, инвентарь, генератор случайных
|
||
чисел, состояние сцены и мини-игры. Ветвления соответствуют реализации в DLL:
|
||
`BeginIf`/`Else` ищут следующую ветку в списке команд, `EndIf` — пустая команда.
|
||
|
||
Исходные команды хранятся в редактируемых модулях PGVN; видимый текст индексируется
|
||
общим редактором переводов. При запуске VM собирается заново из модулей, поэтому
|
||
редактирование текста мода не оставляет устаревшую копию сценария в плеере.
|
||
Адреса меток привязаны к ID команд: вставка команд не смещает переходы;
|
||
удаление команды, на которую указывает метка, требует исправления адреса.
|
||
Неизвестные команды, параметры, эффекты и интерфейсы останавливают импорт.
|
||
Предпросмотр Tomie с отдельной строки пока явно отклоняется; запуск с начала
|
||
поддерживается.
|
||
|
||
Оригинальная папка Tomie проходит строгую проверку. В скриптах остаются 31 дефект
|
||
самой игры: 22 перехода на отсутствующие метки (например, `B_Rest.Start` и
|
||
`AB_Studio.SkillUp`), 6 условных блоков без `EndIf` и 3 некорректных присваивания
|
||
в вариантах выбора. Они перечислены в `app/games/tomie/defects.py`, показываются
|
||
в отчёте версии как предупреждения, а плеер останавливается с явной ошибкой, если
|
||
игра доходит до такого места. Любой новый дефект по-прежнему останавливает импорт.
|
||
Автоматическая подмена сюжета не выполняется. Полное прохождение игры и экспорт
|
||
всего медиакаталога через конвертер ещё не подтверждены.
|
||
|
||
Устройство профилей и добавление новых игр описаны в [GAME_PROFILES.md](GAME_PROFILES.md).
|
||
|
||
Проверка браузерного интерфейса находится в `frontend/tests/tomie-browser.test.mjs`.
|
||
Она использует уже установленный Playwright через `PGAMES_PLAYWRIGHT_PATH`;
|
||
при необходимости путь к Chromium задаётся `PGAMES_CHROMIUM_EXECUTABLE`.
|
||
Тесты оригинальных данных включаются переменными `PGAMES_TOMIE_ORIGINAL`
|
||
(папка дистрибутива), `PGAMES_TOMIE_PORT` (папка Godot-порта),
|
||
`PGAMES_TOMIE_FIXTURE` (его `story/opening.json`) и `PGAMES_TOMIE_RUNTIME`
|
||
(восстановленный `runtime_data` в JSON). Эти файлы не включаются в репозиторий.
|
||
|
||
Каталоги `.local-translator`, `migration-staging` и `migration-tools` не
|
||
считаются отдельными играми. Импорт читает текущие ресурсы дистрибутива:
|
||
установленный переводческий патч автоматически не откатывается, резервные
|
||
копии не подставляются вместо исходников без отдельной обработки профиля.
|