feat: skip a verified placeholder file in The Only Doe 0.05 instead of failing the media conversion

gui/journal_icon.png in that build is a text note ("PLACEHOLDER: Download a journal icon...") with an
.svg next to it, so Ren'Py cannot load it either. A build can now list placeholder files by path and
SHA-256; only an exact match is skipped and the report carries a non-blocking warning. The full
conversion of the game (2898 files, 2.77 GB) now finishes without failed media.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-26 04:02:22 +03:00
1 parent b3f435f416
commit 25bd39dd43
3 files changed
+32 -2

No files matched your search

+5 -2
View File
@@ -86,7 +86,7 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
return profile.convert(detection.root, work, progress)
game_dir = find_game_dir(src_root)
from app.games.renpy_builds import identify, prepare_source, skipped_files, waive_known
from app.games.renpy_builds import identify, placeholder_files, prepare_source, skipped_files, waive_known
build = identify(game_dir) # before the archives are unpacked and scripts decompiled
rpas = sorted(game_dir.rglob("*.rpa"))
for i, rpa in enumerate(rpas, 1):
@@ -125,8 +125,11 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
files: dict[str, dict[str, Any]] = {}
aliases: dict[str, str] = {}
placeholders = placeholder_files(build, game_dir)
for p in sorted(placeholders):
data.warn("Файл-заглушка оригинала не конвертируется", p.relative_to(game_dir).as_posix(), blocking=False)
media = [p for p in game_dir.rglob("*")
if p.is_file() and assets.kind_of(p) and not _is_engine_file(game_dir, p)]
if p.is_file() and assets.kind_of(p) and not _is_engine_file(game_dir, p) and p not in placeholders]
counts = {"image": 0, "audio": 0, "video": 0, "font": 0}
failed: list[str] = []
done = 0
+15
View File
@@ -92,6 +92,8 @@ BUILDS: dict[str, dict] = {
},
"bb19a33af00324fa027a629c052aee885e72f1b7bee7074403a5b9e20c69e2d8": {
"id": "renpy/the-only-doe-0.05",
# The author left a text note instead of a picture; Ren'Py cannot load it either (there is an .svg next to it)
"placeholders": {"gui/journal_icon.png": "4b45bd642d6e43c85dabb5e8b0df3e52e628cde7640519af1a64751750f6b711"},
# One menu branch tests `... before_sleeping=2` (assignment), which Ren'Py cannot compile either:
# sleep.rpyc holds the same text. The port corrects the operator; the digest pins the exact line.
"lines": {
@@ -134,6 +136,19 @@ def skipped_files(build_id: str | None) -> set[str]:
return {name.lower() for name in build.get("skip", ())} if build else set()
def placeholder_files(build_id: str | None, game_dir: Path) -> set[Path]:
"""Files of the build that carry text instead of media; only an exact SHA-256 match is skipped."""
build = next((b for b in BUILDS.values() if b["id"] == build_id), {})
found = set()
for relative, digest in build.get("placeholders", {}).items():
path = game_dir / relative
if path.is_file():
with path.open("rb") as stream:
if hashlib.file_digest(stream, "sha256").hexdigest() == digest:
found.add(path)
return found
def identify(game_dir: Path) -> str | None:
"""The id of a known build, or None."""
build = BUILDS.get(fingerprint(game_dir))
+12
View File
@@ -71,3 +71,15 @@ def test_known_build_line_patch_requires_the_exact_line():
assert renpy_builds.prepare_source("renpy/the-only-doe-0.05", "other.rpy", source) == source
edited = source.replace("spitroast", "other")
assert renpy_builds.prepare_source("renpy/the-only-doe-0.05", "sleep.rpy", edited) == edited
def test_placeholder_media_is_skipped_only_on_an_exact_match(tmp_path):
from app.games import renpy_builds
icon = tmp_path / "gui" / "journal_icon.png"
icon.parent.mkdir()
icon.write_text("PLACEHOLDER: Download a journal icon from a free resource and save as journal_icon.png in gui folder.")
assert renpy_builds.placeholder_files("renpy/the-only-doe-0.05", tmp_path) == {icon}
assert renpy_builds.placeholder_files(None, tmp_path) == set()
icon.write_text("a real file now")
assert renpy_builds.placeholder_files("renpy/the-only-doe-0.05", tmp_path) == set()