`init -490 screen`, `import x as y` and `from m import A as B`, classes with @renpy.pure, pickle hooks
on classes, `*` items in tuples and lists, generator functions (yield statements; the player runs them
to the end), multi-line expressions that need brackets, Null() and Animation() images, images given as
expressions (`"path/{}.png".format(x)`, f-strings), window statements in init, `offset` in ATL, input
widgets with their values and the focus/confirm actions, `continue` and `break` in screens, `drag`
and DiamondBox-style `fixed` with cell_size, `getattr(...)()` calls, transforms called with arguments,
and the whitelist for the new runtime. JSON files of a game are shipped as data files. Also fixes
blocking_names failing on a call of a call during full conversion.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
PGames — локальная библиотека игр в браузере
Домашний сервер для коллекции игр, которые играются прямо в браузере: визуальные новеллы, игры-«песочницы» с открытым миром, текстовые квесты и другие. Вы загружаете архив или папку с игрой, сервер распознаёт движок, переводит сценарии и ассеты в собственный формат PGVN (JSON-скрипты, WebP, Opus, WebM) и удаляет исходники; играть можно во встроенном плеере, без установки. У каждой игры может быть несколько версий (форков) от разных пользователей; версии делят общие ассеты, поэтому форк почти не занимает места. Есть редактор модов и переводов, ревизии и слияние.
Каждый движок и каждая особенная игра подключаются профилем (см. 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.
Пакетный импорт коллекции, строгая проверка совместимости и текущие ограничения Naninovel описаны в docs/IMPORT.md.
Профили игр (отдельный конвейер для игр с особенностями) — в docs/GAME_PROFILES.md.
Редактор модов, слияние, перенос на новую версию, ревизии и сборщик мусора — в docs/MODDING.md.
Машинный перевод нейросетью, которая работает на компьютере переводчика (без
участия сервера), — страница /translator и раздел «Машинный перевод через
локальный переводчик» в docs/LOCALIZATION.md.
Локальное улучшение графики — страница /imager: SwarmUI, ComfyUI или A1111,
кэш в браузере для плеера и пакетная замена картинок в модах с предпросмотром и откатом.
Настройка и ограничения — в docs/IMAGE_ENHANCE.md.
Импорт обложек из F95zone и настройка авторизованной сессии — в docs/F95.md.
Установка на VM
git clone <repo> pgames && cd pgames
cp .env.example .env
# обязательно поменяйте SECRET_KEY (openssl rand -hex 32) и пароли
docker compose up -d --build
Приложение слушает http://<IP VM>: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 распакованными, архивировать их не нужно. Подключите папку к контейнеру (только чтение) и запустите импорт:
docker compose run --rm -v /srv/games:/games:ro backend \
python -m app.import_dir "/games/Some-Game" --title "Some Game"
Папка не изменяется, сконвертированная копия попадает в библиотеку как обычная загрузка. Проверить, насколько хорошо конвертер понимает игру, не трогая медиа (минуты вместо часов), можно сухим прогоном:
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 — логи бэкенда и воркера.
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.
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.
Пока не поддерживается: в экранах — imagemap, mousearea, drag, side; шейдеры
(выбрасываются как чисто графические); AlphaMask и transform, в теле которого картинка;
в Python — специальные методы кроме __init__/__str__/__repr__, генераторы, with,
системные модули (os, socket, …), а также собственные операторы и внутренности движка
(renpy.register_statement, renpy.Render). Такие места перечислены в отчёте конвертации
у версии и останавливают импорт.