# PGames — локальная библиотека игр в браузере Домашний сервер для коллекции игр, которые играются прямо в браузере: визуальные новеллы, игры-«песочницы» с открытым миром, текстовые квесты и другие. Вы загружаете архив или папку с игрой, сервер распознаёт движок, переводит сценарии и ассеты в собственный формат **PGVN** (JSON-скрипты, WebP, Opus, WebM) и удаляет исходники; играть можно во встроенном плеере, без установки. У каждой игры может быть несколько версий (форков) от разных пользователей; версии делят общие ассеты, поэтому форк почти не занимает места. Есть редактор модов и переводов, ревизии и слияние. Каждый движок и каждая особенная игра подключаются профилем (см. [docs/GAME_PROFILES.md](docs/GAME_PROFILES.md)): | Движок | Состояние | | --- | --- | | Ren'Py | основной: сценарии, Python-песочница, ATL, экраны | | Unity + Naninovel (в том числе Tomie) | импорт скомпилированных сценариев | | GameMaker (песочницы вроде FF692) | планируется: загрузчик `data.win` и виртуальная машина GML | | QSP (Quest Soft Player) | планируется: текстовые квесты `.qsp` | | Unity (без Naninovel), Godot, RPG Maker | пока отклоняются при загрузке | Игры других движков отклоняются на входе: неподдерживаемое никогда не «импортируется наполовину». Подробности устройства — в [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). Пакетный импорт коллекции, строгая проверка совместимости и текущие ограничения Naninovel описаны в [docs/IMPORT.md](docs/IMPORT.md). Профили игр (отдельный конвейер для игр с особенностями) — в [docs/GAME_PROFILES.md](docs/GAME_PROFILES.md). Редактор модов, слияние, перенос на новую версию, ревизии и сборщик мусора — в [docs/MODDING.md](docs/MODDING.md). Машинный перевод нейросетью, которая работает на компьютере переводчика (без участия сервера), — страница `/translator` и раздел «Машинный перевод через локальный переводчик» в [docs/LOCALIZATION.md](docs/LOCALIZATION.md). ## Установка на VM ```bash git clone pgames && cd pgames cp .env.example .env # обязательно поменяйте SECRET_KEY (openssl rand -hex 32) и пароли docker compose up -d --build ``` Приложение слушает `http://:8080` (порт — `HTTP_PORT` в `.env`). Caddy на хосте Proxmox: ``` games.example.lan { reverse_proxy 192.168.1.50:8080 } ``` Если в браузере сайт открывается по HTTPS через Caddy, оставьте `COOKIE_SECURE=true`; при доступе напрямую по HTTP поставьте `false`, иначе браузер не сохранит сессию. ## Первый вход Логин `admin` / пароль из `ADMIN_PASSWORD` (по умолчанию `admin`). Сразу после входа нужно задать свой логин и пароль. Регистрации нет: пользователей создаёт админ в разделе «Пользователи». Сервер генерирует пароль и показывает его один раз — передайте его человеку, при первом входе он задаст свой. Права настраиваются через роли («Роли»): `admin`, `moderator`, `player` плюс свои. ## Импорт уже распакованных игр Если игры уже лежат на VM распакованными, архивировать их не нужно. Подключите папку к контейнеру (только чтение) и запустите импорт: ```bash docker compose run --rm -v /srv/games:/games:ro backend \ python -m app.import_dir "/games/Some-Game" --title "Some Game" ``` Папка не изменяется, сконвертированная копия попадает в библиотеку как обычная загрузка. Проверить, насколько хорошо конвертер понимает игру, не трогая медиа (минуты вместо часов), можно сухим прогоном: ```bash docker compose run --rm -v /srv/games:/games:ro backend \ python -W ignore -m app.converter.analyze "/games/Some-Game" ``` ## Данные и бэкап * `./data/blobs` — сконвертированные игры (неизменяемые файлы по sha256); * том `db` — PostgreSQL (пользователи, игры, версии, сохранения). Для бэкапа достаточно `pg_dump` и копии `data/blobs`. ## Разработка На Windows тестовый стенд поднимается одной командой: `start-test.bat`. Он запускает отдельный compose-проект `pgames-test` на http://localhost:8090 (свой `.env.test`, данные в `data-test\`), генерирует тестовую игру `data-test\sample.zip` и открывает браузер. `start-test.bat stop` — остановить, `reset` — удалить стенд вместе с данными, `logs` — логи бэкенда и воркера. ```bash cd backend && pip install -r requirements-dev.txt ruff && ruff check . && python -m pytest cd frontend && npm install && npm run dev # проксирует /api на :8000 cd frontend && npm run typecheck && npm test python -m tests.make_sample sample.zip # тестовая игра (из backend/) ``` Тесты конвертера требуют `ffmpeg` в `PATH`. Те же проверки (ruff, pytest, `tsc`, тесты и сборка фронтенда) выполняет GitHub Actions (`.github/workflows/ci.yml`); `mypy` запускается там как справочная проверка. Каталоги `data/` и `data-test/` содержат библиотеку и тестовый стенд (гигабайты), они в `.gitignore` — не добавляйте их в коммиты и в образы Docker. Вход ограничен по числу неудачных попыток: 8 ошибок за 15 минут по IP или по логину блокируют вход на оставшееся время (ответ 429 с `Retry-After`). Счётчик хранится в памяти процесса и сбрасывается при перезапуске backend. ## Что поддерживает конвертер Ren'Py `label`, реплики (в т.ч. атрибуты, `extend`, `centered`, NVL), `scene/show/hide` с `at`/`as`/`behind`/`zorder`/`with`, переходы (`dissolve`, `fade`, `Fade(...)`, `vpunch`, wipe/slide…), `menu` с условиями и `set`, `if/elif/else`, `while`, `jump/call/return` (включая `expression`), `$`/`python:`/`init python:` (подмножество Python: переменные, выражения, списки/словари, циклы), `define/default`, `Character(...)`, `image` (файлы, цвета, `Transform`, `im.*`, `Composite`, `ConditionSwitch`, `Movie`, покадровые ATL-анимации с `pause`/`repeat`), `layeredimage` (always/attribute/group/if), `transform` со статическими свойствами, `Shake`, `camera`, вложенные метки и именованные `menu`, `call label(args)` и метки с параметрами, `play/queue/stop/voice` и свои каналы (`register_channel`), `pause`, `.rpa`, `.rpyc` (через unrpyc), автоопределение картинок из `images/`, GUI-текстбокс и шрифты игры. Для Naninovel/Tomie см. [docs/IMPORT.md](docs/IMPORT.md). Python игры выполняется в песочнице плеера: свои `def` и `class` (наследование, `super()`, свойства, замыкания, `lambda`, `*args`/`**kwargs`), `try`/`except`/ `finally`, `raise`, `assert`, `match`, `for`/`while … else`, comprehension, модули `re`, `copy`, `time`, `datetime`, `collections.defaultdict`, `functools.partial`. Код, который ждёт игрока (`renpy.input`, `narrator()`, реплики персонажей, `renpy.pause`, `renpy.display_menu`, `renpy.call_screen`), работает внутри циклов и функций. `eval` и `exec` строк разбираются своим парсером выражений и простых операторов. ATL: движение (`linear`/`ease`/`easein`/`easeout`), `pause`, `repeat`, `parallel`, `choice`, `block`, `on show`/`on hide`/`on hover`, `contains`, `time`, `function`, смена картинок с `with dissolve`, параметры и вызов других transform, `matrixcolor`, `blur`. Просмотр сцен из галереи (`Replay`/`EndReplay`). Экраны игры (`screen`, `call screen`, `show screen`) и их действия — см. [docs/SCREENS.md](docs/SCREENS.md). Пока **не** поддерживается: в экранах — `imagemap`, `mousearea`, `drag`, `side`; шейдеры (выбрасываются как чисто графические); `AlphaMask` и transform, в теле которого картинка; в Python — специальные методы кроме `__init__`/`__str__`/`__repr__`, генераторы, `with`, системные модули (`os`, `socket`, …), а также собственные операторы и внутренности движка (`renpy.register_statement`, `renpy.Render`). Такие места перечислены в отчёте конвертации у версии и останавливают импорт.