diff --git a/DR.py b/DR.py index 4b255be..f1f1c9f 100644 --- a/DR.py +++ b/DR.py @@ -8,6 +8,8 @@ import time import cProfile import traceback +from io import StringIO + # TODO 默认位置配置文件 # TODO 可自定义工作路径 @@ -89,6 +91,10 @@ def main() -> None: print(error_format['error.unknown']) print(error) crash.create_crash_report(error) + cache_steam = StringIO() + crash.write_info_to_cache(cache_steam) + text = cache_steam.getvalue() + print(text) else: crash.record_thread = False print(crash.all_thread) diff --git a/Difficult_Rocket/__init__.py b/Difficult_Rocket/__init__.py index e04befb..0a51093 100644 --- a/Difficult_Rocket/__init__.py +++ b/Difficult_Rocket/__init__.py @@ -4,19 +4,15 @@ # All rights reserved # ------------------------------- -""" -writen by shenjackyuanjie -mail: 3695888@qq.com -github: @shenjackyuanjie -gitee: @shenjackyuanjie -""" - -# import ctypes +import os import sys import warnings +import importlib import traceback import contextlib -from typing import Optional +import importlib.util +from pathlib import Path +from typing import Optional, List, Tuple from Difficult_Rocket.api.types import Options @@ -24,10 +20,14 @@ from libs.MCDR.version import Version game_version = Version("0.7.2.2") # 游戏版本 build_version = Version("1.2.1.0") # 编译文件版本(与游戏本体无关) -DR_rust_version = Version("0.2.6.1") # DR 的 Rust 编写部分的版本 Api_version = Version("0.0.2.0") # API 版本 __version__ = game_version +# TODO 解耦 DR SDK 与 DR_mod 和 DR_rs +DR_rust_version = Version("0.2.6.1") # DR 的 Rust 编写部分的版本 +# 后面会移除的 DR_rs 相关信息 +# DR_rs和 DR_mod 的部分正在和 DR SDK 解耦 + long_version: int = 14 """ long_version: 一个用于标记内部协议的整数 @@ -64,22 +64,19 @@ class _DR_option(Options): report_translate_not_found: bool = True use_multiprocess: bool = False DR_rust_available: bool = False - use_DR_rust: bool = True use_cProfile: bool = False use_local_logging: bool = False - + use_DR_rust: bool = True + # tests playing: bool = False debugging: bool = False crash_report_test: bool = True - pyglet_macosx_dev_test: bool = True # window option gui_scale: float = 1.0 # default 1.0 2.0 -> 2x 3 -> 3x def init(self, **kwargs): - if sys.platform != 'darwin': # MacOS 的测试只能在 Macos 上跑 - self.pyglet_macosx_dev_test = False try: from libs.Difficult_Rocket_rs import test_call, get_version_str test_call(self) @@ -113,22 +110,25 @@ class _DR_runtime(Options): DR_version: Version = game_version # DR SDK 版本 Build_version: Version = build_version # DR 构建 版本 - DR_Rust_version: Version = DR_rust_version # 后面要去掉的 DR_rs 版本 - DR_Rust_get_version: Optional[Version] = None # 后面也要去掉的 DR_rs 版本 - API_version: Version = Api_version # DR SDK API 版本 DR_long_version: int = long_version # DR SDK 内部协议版本 (不要问我为什么不用 Version,我也在考虑) + DR_Mod_List: List[Tuple[str, Version]] = [] # DR Mod 列表 (name, version) + + DR_Rust_version: Version = DR_rust_version # 后面要去掉的 DR_rs 版本 + DR_Rust_get_version: Optional[Version] = None # 后面也要去掉的 DR_rs 版本 + # run status running: bool = False - start_time_ns: int = None - client_setup_cause_ns: int = None - server_setup_cause_ns: int = None + start_time_ns: Optional[int] = None + client_setup_cause_ns: Optional[int] = None + server_setup_cause_ns: Optional[int] = None # game runtimes # global_logger: logging.Logger # game options + mod_path: str = './mods' language: str = 'zh-CN' default_language: str = 'zh-CN' @@ -140,10 +140,45 @@ class _DR_runtime(Options): relationship = 'larger' if self.DR_Rust_version > self.DR_Rust_get_version else 'smaller' warnings.warn(f'DR_rust builtin version is {self.DR_Rust_version} but true version is {get_version_str()}.\n' f'Builtin version {relationship} than true version') + + def load_file(self) -> bool: with contextlib.suppress(FileNotFoundError): with open('./configs/main.toml', 'r', encoding='utf-8') as f: import rtoml - self.language = rtoml.load(f)['runtime']['language'] + config_file = rtoml.load(f) + self.language = config_file['runtime']['language'] + self.mod_path = config_file['game']['mods']['path'] + return True + return False + + def load_mods(self) -> None: + mod_list = self.find_mods() + + def find_mods(self) -> List[str]: + mods = [] + paths = Path(self.mod_path).iterdir() + sys.path.append(self.mod_path) + for mod_path in paths: + try: + if mod_path.is_dir() and mod_path.name != '__pycache__': # 处理文件夹 mod + if importlib.util.find_spec(mod_path.name) is not None: + module = importlib.import_module(mod_path.name) + mods.append(mod_path.name) + else: + print(f'can not import mod {mod_path} because importlib can not find spec') + elif mod_path.suffix in ('.pyz', '.zip'): # 处理压缩包 mod + if importlib.util.find_spec(mod_path.name) is not None: + module = importlib.import_module(mod_path.name) + mods.append(mod_path.name) + elif mod_path.suffix == '.py': # 处理单文件 mod + print(f'importing mod {mod_path=} {mod_path.stem}') + module = importlib.import_module(mod_path.stem) + mods.append(mod_path.stem) + except ImportError: + print(f'ImportError when loading mod {mod_path}') + traceback.print_exc() + self.DR_Mod_List = [(mod, Version('0.0.0-unknown')) for mod in mods] + return mods DR_option = _DR_option() diff --git a/Difficult_Rocket/utils/tools.py b/Difficult_Rocket/utils/tools.py index 7d2be64..5609e81 100644 --- a/Difficult_Rocket/utils/tools.py +++ b/Difficult_Rocket/utils/tools.py @@ -40,7 +40,7 @@ file_error = {FileNotFoundError: 'no {filetype} file was founded!:\n file name: def load_file(file_name: str, - stack: Union[str, list, dict] = None, + stack: Union[str, list, dict, None] = None, raise_error: bool = True, encoding: str = 'utf-8') -> Union[dict, ElementTree.ElementTree]: f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式) diff --git a/docs/src/update_logs.md b/docs/src/update_logs.md index 2a409dd..705fbe1 100644 --- a/docs/src/update_logs.md +++ b/docs/src/update_logs.md @@ -22,6 +22,42 @@ - [![Readme-gitee](https://img.shields.io/badge/Readme-中文(点我!)-blue.svg?style=flat-square)](../../README.md) - Using [SemVer 2.0.0](https://semver.org/) to manage version +## 202305 DR `0.8.0.0` + DR_api `0.1.0.0` + +> 啊哈! mod 加载来啦! + +### Remove + +- `game.config` + - 已删除 + - Removed + +### Changes + +- `main.toml` + - `game.mods.path` + - 存储 mod 的路径 + - Store the path of the mod +- `Difficult_Rocket.mod.MODInfo` -> `Difficult_Rocket.api.mod.ModInfo` + - 用于存储 mod 的信息 + - Used to store information about the mod +- `Difficult_Rocket.DR_runtime` + - 添加 `mod_path: str` 字段 + - 添加 `DR_Mod_List: List[Tuple[str, Version]]` 字段 + - 添加 `load_mods() -> None` 方法 + - 添加 `find_mods -> List[str]` 方法 + - Add `mod_path: str` field + - Add `DR_Mod_List: List[Tuple[str, Version]]` field + - Add `load_mods() -> None` method + - Add `find_mods -> List[str]` method +- 现在游戏崩溃时会自动在 stdio 中输出崩溃日志 内容跟 crash report 中的基本相同 + - Now when the game crashes, it will automatically output the crash log in stdio + - The content of the crash log is basically the same as the crash report + +### Mod Loader + +- `ModInfo` + ## 20230422 DR `0.7.2.2` + DR_rs `0.2.6.1` + DR_api `0.0.2.0` + 14 ### DR_rs V 0.2.6.1 @@ -556,8 +592,6 @@ long_version: 一个用于标记内部协议的整数 - 尝试加载 `icon` - 更新了主项目 -## 20220627 - ## 20220511 V 0.6.3 - 咕了好久的 update log 了 diff --git a/libs/MCDR/version.py b/libs/MCDR/version.py index 56e1cb9..fa29b02 100644 --- a/libs/MCDR/version.py +++ b/libs/MCDR/version.py @@ -102,6 +102,9 @@ class Version: version_str += '+' + str(self.build) return version_str + def __repr__(self): + return 'Version({})'.format(self.__str__()) + def __getitem__(self, index): if index < len(self.component): return self.component[index]