Commit Graph
8 Commits
Author SHA1 Message Date
mrleo1nidandClaude Sonnet 5.5 e66160cffa feat: converter accepts the constructs of goodluke and SaintlyCorruption
`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>
2026-10-26 17:28:13 +03:00
mrleo1nid f9eb5c1212 feat: improve RenPy conversion and support MIST runtime
CI / frontend (push) Failing after 15s
CI / backend (push) Failing after 37s
2026-10-25 23:16:33 +03:00
mrleo1nidandClaude Sonnet 5.5 3923ee72fb feat: generator interpreter for Python that waits for the player (Ren'Py)
Python containing renpy.input, narrator("..."), character calls, renpy.say,
renpy.pause, renpy.display_menu, renpy.with_statement or renpy.call_screen now
runs through loops, try, functions, methods and expressions.

Player
- python.ts: execG/evalG/callG run only the code that may wait (mayBlock);
  everything else stays on the synchronous fast path. A waiting call returns a
  BlockingCall; outside the generator interpreter it is an explicit error. The
  interpreter scope is set aside while the player decides
- engine: drives the generator and answers requests (dialogue, text input with
  length/allow/exclude, pause, choice menu, transition, call screen)
- renpy.show/hide/scene, transitions and transforms as Python values,
  Character(...) objects, Borders, set_tag_attributes

Converter
- blocking_names() lists game functions that may wait, transitively, and ships
  them as game.json "blocking"; character calls are allowed
- hide screen of an unknown screen is harmless; images defined by a parenthesised
  expression are supported

Hooked now passes the strict compatibility check (with Tomie and Twisted-Thoughts).
Tests: waiting.py fixture run through the generator interpreter; blocking-name analysis.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 14:22:38 +03:00
mrleo1nidandClaude Sonnet 5.5 4418da47eb feat: report ATL problems only for used transforms; animate moving images
CI / frontend (push) Successful in 23s
CI / backend (push) Successful in 1m55s
- Unsupported ATL constructs in a transform now block the import only when the
  transform is used (at clause, another transform, even before its definition).
  Stock screens.rpy transforms for unused screens no longer fail games
- image blocks with one picture plus linear/ease/parallel/repeat keep their
  animation (image-level ATL); the renderer also starts it
- Python: skip @gui.variant/@renpy.variant functions (inactive variants), treat
  @renpy.pure as transparent, read renpy.store.x as x
- Accept renpy.transition, end_replay, block_rollback and music set_pause/set_pan
  as presentation-only no-ops, and implement them in the player (set_pause and
  set_pan were allowed by the converter but missing at runtime)
- Skip the 0x52-URM add-on directory (in-game console / save editor) when
  parsing scripts and media
- Tests for lazy ATL warnings, moving images and variants

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:20:39 +03:00
mrleo1nidandClaude Sonnet 5.5 962595c925 feat: support user-defined functions and classes in Ren'Py python
- Converter: def/return/global/nonlocal, class (inheritance, property,
  staticmethod, classmethod), lambda, *args/**kwargs and call-site unpacking.
  Unsupported dunder methods, generators and unknown decorators are still refused
- Player: closures, super(), instances that survive save/load, isinstance,
  hasattr/getattr/setattr, map/filter/sorted(key=), recursion limit
- audit_ir accepts calls to names, classes and methods the game defines itself;
  unknown renpy.* calls still block the import. Volume/pan/pause/replay calls
  are accepted as presentation-only no-ops; build.* settings are skipped
- Tests: IR fixture compiled from tests/fixtures/classes.py (tests/make_ir.py)
  and run in the interpreter; converter tests updated

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:01:09 +03:00
mrleo1nidandClaude Opus 5.5 e1d7b29f77 Localization stage 1: stable IDs, import of tl/ translations, language picker
- every script node gets a permanent id, say nodes a Ren'Py-style tid
- all languages from the game's tl/ are imported at conversion: dialogue blocks
  matched by their source-location comment or by label + original text,
  `translate strings` become a per-language strings table
- source language from config.language or detected from the dialogue
- manifest stores locales/<lang>/<module>.json and strings.json; game.json
  lists sourceLang and available locales with progress
- player: language picker in main menu and settings, fallback to source,
  __(), [var!t] and _preferences.language
- parser: `default` with init priority, and one bad statement no longer drops
  the whole file
- docs/LOCALIZATION.md: design for translations, publishing and mods

Line endings of several converter/player files go back to LF: an earlier
commit accidentally stored them as CRLF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 03:39:40 +03:00
mrleo1nidandClaude Opus 5.5 a97b46079e Converter: cover real Ren'Py games better, add folder import and dry run
Checked against six real games (Ren'Py 7.5 and 8.x):
- nested labels and named menus become jump anchors inside label bodies
- call with arguments and labels with parameters (dynamically scoped)
- frame-by-frame ATL images, Movie frames, layeredimage, camera, Shake,
  custom audio channels via register_channel, show text with expressions
- generator expressions in Python, no SyntaxWarning noise from decompiled code

Also:
- app.import_dir converts an unpacked game folder without changing it
- app.converter.analyze dry-runs the script part of the converter
- imports use their own "importing" status so a worker restart can't hijack them

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 03:23:20 +03:00
mrleo1nidandClaude Opus 5.5 364b312064 Initial MVP: local visual novel library with Ren'Py → PGVN converter
- FastAPI backend: admin bootstrap with forced credential change, admin-created
  users with one-time generated passwords, roles as permission sets
- Games and versions with content-addressed blob storage; forks copy only the
  manifest, so mods share assets with the original
- Worker: archive/RPA extraction, unrpyc for .rpyc, own .rpy parser, Python
  subset translated via ast, media converted to WebP/Opus/WebM
- React panel (library search, game page, upload, users, roles) and a
  framework-free web player with saves, history, skip/auto, transitions
- docker compose: postgres, backend, worker, nginx on a single HTTP port

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 02:41:32 +03:00