diff --git a/gui/wolf_workflow_tab.py b/gui/wolf_workflow_tab.py index 2be7abd..9b8d369 100644 --- a/gui/wolf_workflow_tab.py +++ b/gui/wolf_workflow_tab.py @@ -4397,8 +4397,6 @@ class WolfWorkflowTab(QWidget): f" Added {result.files_added} file(s), omitted " f"{result.excluded_entries} tool/private item(s)." ) - if result.sanitized_plugin_lists: - log(" Removed playtest plugins from the archived plugins.js.") return True, ( f"Created {result.output_path.name} ({size_mb:.1f} MB) at " f"{result.output_path}." diff --git a/gui/workflow_tab.py b/gui/workflow_tab.py index f2b4ea7..ed6d042 100644 --- a/gui/workflow_tab.py +++ b/gui/workflow_tab.py @@ -526,7 +526,7 @@ _STEP_HELP: dict[int, str] = { "• Export ALL - everything under translated/

" "Create Public Release ZIP packages the complete game beside its folder while " "omitting translator workspaces, VCS metadata, documentation, backups, saves, and " - "playtest plugins. GameUpdate files are kept." + "other tool artifacts. GameUpdate files and all installed plugins are kept." ), 6: ( "Step 6 - Images (MV/MZ)

" @@ -2228,7 +2228,7 @@ class WorkflowTab(QWidget): self._release_zip_btn = _make_btn("📦 Create Public Release ZIP", "#007acc") self._release_zip_btn.setToolTip( "Archive the detected game folder for players. Excludes DazedTL workspaces, " - "version-control files, documentation, backups, saves, and playtest plugins; " + "version-control files, documentation, backups, and saves; " "keeps GameUpdate files. The source game folder is not changed." ) self._release_zip_btn.clicked.connect(self._create_public_release) @@ -4211,8 +4211,6 @@ class WorkflowTab(QWidget): f"{result.files_added} file(s); omitted {result.excluded_entries} " "tool/private item(s)." ) - if result.sanitized_plugin_lists: - message += " Removed playtest plugins from the archived plugins.js." self._log(f"✅ {message}") QMessageBox.information( self, diff --git a/tests/test_release_package.py b/tests/test_release_package.py index b76ce11..f0dace3 100644 --- a/tests/test_release_package.py +++ b/tests/test_release_package.py @@ -79,7 +79,8 @@ class ReleasePackageTests(unittest.TestCase): prefix = "Translated Game/" with zipfile.ZipFile(output) as archive: names = set(archive.namelist()) - archived_plugins = archive.read(prefix + "js/plugins.js").decode("utf-8") + archived_plugin_bytes = archive.read(prefix + "js/plugins.js") + archived_plugins = archived_plugin_bytes.decode("utf-8") for relative in ( "Game.exe", @@ -92,6 +93,8 @@ class ReleasePackageTests(unittest.TestCase): "gameupdate/patch.ps1", "gameupdate/patch-config.txt", "js/plugins/CorePlugin.js", + "js/plugins/TLInspector.js", + "js/plugins/Forge_MZ.js", ): self.assertIn(prefix + relative, names) @@ -111,17 +114,15 @@ class ReleasePackageTests(unittest.TestCase): ".gitignore", ".env", "gameupdate/previous_patch_sha.txt", - "js/plugins/TLInspector.js", - "js/plugins/Forge_MZ.js", ): self.assertNotIn(prefix + relative, names) self.assertIn('"name":"CorePlugin"', archived_plugins) - self.assertNotIn("TLInspector", archived_plugins) - self.assertNotIn("Forge_MZ", archived_plugins) + self.assertIn("TLInspector", archived_plugins) + self.assertIn("Forge_MZ", archived_plugins) + self.assertEqual(archived_plugin_bytes, plugins_js) self.assertEqual(source_plugins.read_bytes(), plugins_js) self.assertEqual(result.output_path, output.resolve()) - self.assertEqual(result.sanitized_plugin_lists, 1) self.assertEqual(progress[-1][:2], (result.files_added, result.files_added)) def test_release_path_must_be_outside_game_folder(self): diff --git a/util/release_package.py b/util/release_package.py index 3c2af03..8701b16 100644 --- a/util/release_package.py +++ b/util/release_package.py @@ -2,9 +2,7 @@ from __future__ import annotations -import codecs import os -import re import tempfile import zipfile from dataclasses import dataclass @@ -25,7 +23,6 @@ class ReleasePackageResult: files_added: int bytes_added: int excluded_entries: int - sanitized_plugin_lists: int # These are never game payloads and should be ignored wherever they occur. @@ -91,16 +88,10 @@ _EXCLUDED_FILE_NAMES = frozenset( ".gitattributes", ".gitignore", "desktop.ini", - "forge_mv.bat", - "forge_mv.js", - "forge_mz.bat", - "forge_mz.js", "patch2.ps1", "patch2.sh", "previous_patch_sha.txt", "thumbs.db", - "tlinspector.bat", - "tlinspector.js", } ) @@ -115,8 +106,6 @@ _UPDATER_ROOT_FILE_NAMES = frozenset( _ROOT_DOCUMENT_SUFFIXES = frozenset({".doc", ".docx", ".markdown", ".md", ".pdf", ".rst"}) _BACKUP_SUFFIXES = (".bak", ".backup", ".orig", ".tmp") -_PLUGIN_LIST_PATHS = frozenset({"js/plugins.js", "www/js/plugins.js"}) -_PLAYTEST_PLUGIN_NAMES = ("TLInspector", "Forge_MV", "Forge_MZ") def default_release_zip_path(game_root: str | Path) -> Path: @@ -205,67 +194,6 @@ def _iter_release_files(root: Path) -> tuple[list[tuple[Path, Path]], int]: return files, excluded -def _remove_plugin_object(content: str, plugin_name: str) -> str: - """Remove one object from RPG Maker's JavaScript plugin-array syntax.""" - marker = re.search(rf'"name"\s*:\s*"{re.escape(plugin_name)}"', content) - while marker: - start = content.rfind("{", 0, marker.start()) - if start < 0: - raise ReleasePackageError(f"Could not remove {plugin_name} from plugins.js") - depth = 0 - end = None - in_string = False - escaped = False - for index in range(start, len(content)): - char = content[index] - if in_string: - if escaped: - escaped = False - elif char == "\\": - escaped = True - elif char == '"': - in_string = False - continue - if char == '"': - in_string = True - elif char == "{": - depth += 1 - elif char == "}": - depth -= 1 - if depth == 0: - end = index + 1 - break - if end is None: - raise ReleasePackageError(f"Could not parse {plugin_name} in plugins.js") - - before = content[:start].rstrip() - after = content[end:].lstrip() - if after.startswith(","): - after = after[1:].lstrip() - elif before.endswith(","): - before = before[:-1].rstrip() - separator = "\n" if before and after and not before.endswith("\n") else "" - content = before + separator + after - marker = re.search(rf'"name"\s*:\s*"{re.escape(plugin_name)}"', content) - return re.sub(r",(\s*)\];", r"\1];", content) - - -def sanitize_plugins_js(raw: bytes) -> tuple[bytes, bool]: - """Remove DazedTL playtest entries while preserving the source file's BOM.""" - had_bom = raw.startswith(codecs.BOM_UTF8) - try: - content = raw.decode("utf-8-sig") - except UnicodeDecodeError as exc: - raise ReleasePackageError(f"plugins.js is not valid UTF-8: {exc}") from exc - original = content - for plugin_name in _PLAYTEST_PLUGIN_NAMES: - content = _remove_plugin_object(content, plugin_name) - if content == original: - return raw, False - encoded = content.encode("utf-8") - return (codecs.BOM_UTF8 + encoded if had_bom else encoded), True - - def _archive_name(root: Path, relative: Path) -> str: return (Path(root.name or "game") / relative).as_posix() @@ -306,7 +234,6 @@ def create_release_zip( temporary = Path(temporary_name) files_added = 0 bytes_added = 0 - sanitized = 0 try: with zipfile.ZipFile( temporary, @@ -319,16 +246,8 @@ def create_release_zip( if progress: progress(index, total, relative.as_posix()) arcname = _archive_name(root, relative) - if relative.as_posix().casefold() in _PLUGIN_LIST_PATHS: - raw = source.read_bytes() - payload, changed = sanitize_plugins_js(raw) - info = zipfile.ZipInfo.from_file(source, arcname=arcname) - archive.writestr(info, payload, compress_type=zipfile.ZIP_DEFLATED) - sanitized += int(changed) - bytes_added += len(payload) - else: - archive.write(source, arcname=arcname) - bytes_added += source.stat().st_size + archive.write(source, arcname=arcname) + bytes_added += source.stat().st_size files_added += 1 os.replace(temporary, output) except Exception: @@ -340,5 +259,4 @@ def create_release_zip( files_added=files_added, bytes_added=bytes_added, excluded_entries=excluded, - sanitized_plugin_lists=sanitized, )