Last active
March 26, 2024 01:11
-
-
Save Frixuu/c2d0896356437d493842c3e2e6f4cf20 to your computer and use it in GitHub Desktop.
How to make Ren'Py 8 load raw Python files from .rpa archives
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import renpy.loader | |
from importlib.machinery import ModuleSpec | |
from types import ModuleType | |
from typing import Any, List, Optional, Union | |
class DummyLoader: | |
def __init__(self) -> None: | |
pass | |
def create_module(self, spec: ModuleSpec) -> None: | |
return None | |
def exec_module(self, module: ModuleType) -> None: | |
pass | |
class PythonFromRpaLoader: | |
archive_path: str | |
inner_path: str | |
def __init__(self, archive_path: str, inner_path: str) -> None: | |
self.archive_path = archive_path | |
self.inner_path = inner_path | |
def create_module(self, spec: ModuleSpec) -> None: | |
return None | |
def exec_module(self, module: ModuleType) -> None: | |
reader = renpy.loader.load_from_archive(self.inner_path) # type: ignore | |
if reader is None: | |
raise ModuleNotFoundError(path=self.archive_path) | |
module.__file__ = self.archive_path | |
with reader: | |
exec(reader.read(), module.__dict__) | |
class PythonFromRpaFinder: | |
@classmethod | |
def find_spec( | |
cls, | |
fullname: str, | |
path: Union[List[str], Any, None], | |
target: Optional[Any] = None, | |
) -> Optional[ModuleSpec]: | |
archives: list[tuple[str, Any]] = renpy.loader.archives # type: ignore | |
inner_path_base = fullname.removeprefix("game.").replace(".", "/") | |
candidate = inner_path_base + "/__init__.py" | |
for archive_path, index in archives: | |
if candidate in index: | |
return ModuleSpec( | |
fullname, | |
PythonFromRpaLoader(archive_path, candidate), # type: ignore | |
is_package=True, | |
) | |
candidate = inner_path_base + ".py" | |
for archive_path, index in archives: | |
if candidate in index: | |
return ModuleSpec( | |
fullname, | |
PythonFromRpaLoader(archive_path, candidate), # type: ignore | |
is_package=False, | |
) | |
candidate = inner_path_base + "/" | |
for _, index in archives: | |
files_in_archive = list(index.keys()) | |
if any(file_path.startswith(candidate) for file_path in files_in_archive): | |
return ModuleSpec( | |
fullname, | |
DummyLoader(), # type: ignore | |
is_package=True, | |
) | |
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
python early: | |
import sys | |
from game.load_python import PythonFromRpaFinder | |
sys.meta_path.append(PythonFromRpaFinder) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment