feat: add mod editing, revision merges and secure game storage
Add immutable revisions, PGVN editor, asset replacement, merge and rebase workflows, authenticated media delivery and reachability GC. Harden the script interpreter, pin unrpyc and remove tracked build metadata. Include current compatibility checks, Naninovel import and regression tests.
This commit is contained in:
1 parent
06ff19ac4a
commit
c8d83b3fe7
65 files changed
+3825
-68
No files matched your search
@@ -19,6 +19,7 @@ from app.converter.rpa import RpaError, extract_rpa
|
||||
from app.converter.rpy_lexer import ParseError
|
||||
from app.converter.rpy_parser import RpyParser, ScriptData
|
||||
from app.converter.rpyc import decompile_missing
|
||||
from app.converter.compatibility import CompatibilityError, Issue, audit_ir, detect, require_supported_scripts
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
FORMAT = "pgvn/1"
|
||||
@@ -46,12 +47,26 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
|
||||
data = ScriptData()
|
||||
|
||||
if archive.is_dir():
|
||||
detection = detect(archive)
|
||||
if detection.engine == "naninovel":
|
||||
from app.converter.naninovel import convert_naninovel
|
||||
return convert_naninovel(detection.root, work, progress)
|
||||
# Inspect scripts before copying/converting multi-gigabyte media collections.
|
||||
from app.converter.preflight import inspect_directory
|
||||
inspect_directory(detection.root)
|
||||
progress("Копирование файлов игры")
|
||||
game_dir = src_root / "game"
|
||||
shutil.copytree(find_game_dir(archive), game_dir)
|
||||
else:
|
||||
from app.converter.preflight import inspect_archive
|
||||
progress("Проверка движка и сценариев до распаковки медиа")
|
||||
inspect_archive(archive, filename)
|
||||
progress("Распаковка архива")
|
||||
extract(archive, filename, src_root)
|
||||
detection = detect(src_root)
|
||||
if detection.engine == "naninovel":
|
||||
from app.converter.naninovel import convert_naninovel
|
||||
return convert_naninovel(detection.root, work, progress)
|
||||
game_dir = find_game_dir(src_root)
|
||||
|
||||
rpas = sorted(game_dir.rglob("*.rpa"))
|
||||
@@ -79,6 +94,8 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
|
||||
data.warn("Слишком глубокая вложенность", rel)
|
||||
if not any(lbl["name"] == "start" for labels in data.modules.values() for lbl in labels):
|
||||
raise RuntimeError("В скриптах не найдена метка start — нечего запускать")
|
||||
audit_ir(data)
|
||||
require_supported_scripts(data)
|
||||
|
||||
files: dict[str, dict[str, Any]] = {}
|
||||
aliases: dict[str, str] = {}
|
||||
@@ -112,6 +129,10 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
|
||||
aliases[rel.lower()] = logical
|
||||
counts[assets.kind_of(p)] += 1
|
||||
|
||||
if failed:
|
||||
raise CompatibilityError("renpy", [Issue("media_conversion", "Не удалось конвертировать обязательное медиа", name)
|
||||
for name in failed])
|
||||
|
||||
progress("Сборка формата PGVN")
|
||||
_auto_images(data, aliases)
|
||||
missing: set[str] = set()
|
||||
@@ -176,6 +197,11 @@ def convert_archive(archive: Path, filename: str, work: Path, progress: Progress
|
||||
|
||||
total = sum(f["size"] for f in files.values())
|
||||
report = {
|
||||
"engine": "renpy",
|
||||
"compatible": True,
|
||||
"converterVersion": "pgvn-tools/2",
|
||||
"unrpycRevision": (get_settings().unrpyc_path.parent / "REVISION").read_text().strip()
|
||||
if (get_settings().unrpyc_path.parent / "REVISION").is_file() else "unavailable",
|
||||
"format": FORMAT,
|
||||
"durationSec": round(time.monotonic() - started, 1),
|
||||
"scripts": len(rpy_files),
|
||||
|
||||
Reference in new issue
Block a user