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>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-26 17:28:13 +03:00
1 parent f2fcd05467
commit e66160cffa
12 files changed
+176 -31

No files matched your search

+14
View File
@@ -162,6 +162,16 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
raise CompatibilityError("renpy", [Issue("media_conversion", "Не удалось конвертировать обязательное медиа", name)
for name in failed])
# JSON the game reads itself (`renpy.file("data/x.json").read()`): kept as it is, loaded before the game starts
data_files: list[str] = []
for p in sorted(game_dir.rglob("*.json")):
relative = p.relative_to(game_dir).as_posix()
if _is_engine_file(game_dir, p) or relative.lower().startswith(("cache/", "saves/")) or p.stat().st_size > DATA_FILE_LIMIT:
continue
blob_id, size = put_file(p, ".json")
files[f"data/{relative}"] = {"hash": blob_id, "size": size}
data_files.append(relative)
progress("Сборка формата PGVN")
_auto_images(data, aliases)
missing: set[str] = set()
@@ -212,6 +222,7 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
"channels": data.channels,
"build": data.build,
"files": aliases,
"dataFiles": data_files,
"defaults": data.defaults,
"init": data.init_code,
"ui": _ui(gui, aliases),
@@ -328,6 +339,9 @@ def _used_screens(data: ScriptData) -> set[str]:
return used
DATA_FILE_LIMIT = 4 * 1024 * 1024
def _is_engine_file(game_dir: Path, p: Path) -> bool:
parts = [x.lower() for x in p.relative_to(game_dir).parts]
return len(parts) > 1 and parts[0] in ENGINE_DIRS