就,天天重构,淦!

This commit is contained in:
shenjack 2023-06-22 13:34:14 +08:00
parent 226fcbfce8
commit 996fb72b54
7 changed files with 118 additions and 122 deletions

View File

@ -4,6 +4,10 @@
# All rights reserved
# -------------------------------
import time
import logging.config
from pathlib import Path
from Difficult_Rocket.api.types import Options, Version
game_version = Version("0.8.3.0") # 游戏版本
@ -70,6 +74,22 @@ class _DR_status(Options):
DR_status = _DR_status()
def load_logging():
with open('./configs/logger.toml') as f:
import rtoml
logger_config = rtoml.load(f)
log_path = logger_config['handlers']['file']['filename']
log_path = f"logs/{log_path.format(time.strftime('%Y-%m-%d %H-%M-%S', time.gmtime(time.time_ns() / 1000_000_000)))}"
if not Path('logs/').is_dir():
Path('logs/').mkdir()
logger_config['handlers']['file']['filename'] = log_path
logging.config.dictConfig(logger_config)
load_logging()
if DR_status.playing:
from Difficult_Rocket.utils.thread import new_thread

View File

@ -256,7 +256,7 @@ class ClientWindow(Window):
self.set_icon(pyglet.image.load('./textures/icon.png'))
self.load_fonts()
self.screen_list['DR_debug'] = DRDEBUGScreen(self)
self.game.dispatch_event('on_client_start', game=self.game, client=self)
self.game.dispatch_mod_event('on_client_start', game=self.game, client=self)
def load_fonts(self) -> None:
fonts_folder_path = self.main_config['runtime']['fonts_folder']
@ -383,7 +383,7 @@ class ClientWindow(Window):
self.logger.info(tr().language_available().format(os.listdir('./configs/lang')))
self.save_info()
elif command.find('mods'):
for mod in self.game.mod_module:
for mod in self.game.mod_manager.loaded_mod_modules.values():
self.logger.info(f"mod: {mod.name} id: {mod.mod_id} version: {mod.version}")
@_call_screen_after
@ -483,7 +483,7 @@ class ClientWindow(Window):
@_call_screen_before
def on_close(self, source: str = 'window') -> None:
self.game.dispatch_event('on_close', game=self.game, client=self, source=source)
self.game.dispatch_mod_event('on_close', game=self.game, client=self, source=source)
self.logger.info(tr().window.game.stop_get().format(tr().game[source]()))
self.logger.info(tr().window.game.stop())
# self.fps_log.check_list = False

View File

@ -11,27 +11,21 @@ github: @shenjackyuanjie
gitee: @shenjackyuanjie
"""
import sys
import time
import logging
import traceback
import importlib
import importlib.util
import logging.config
import multiprocessing
from io import StringIO
from pathlib import Path
from typing import TYPE_CHECKING, List, Optional, Dict, TypeVar
from typing import List, Optional, Dict
if TYPE_CHECKING:
from Difficult_Rocket.api.mod import ModInfo
else:
ModInfo = TypeVar('ModInfo')
from Difficult_Rocket.utils import tools
from Difficult_Rocket.api.types import Options
from Difficult_Rocket.utils.translate import tr
from Difficult_Rocket.runtime import DR_runtime
from Difficult_Rocket.mod.loader import ModManager
from Difficult_Rocket.utils.thread import new_thread
from Difficult_Rocket.crash import write_info_to_cache
from Difficult_Rocket import client, server, DR_status
@ -78,75 +72,21 @@ class Game(Options):
console_class: Console = Console
main_config: Dict
logging_config: Dict
logger: logging.Logger
mod_module: List["ModInfo"] = []
mod_manager: ModManager
def init_logger(self) -> None:
log_path = self.logging_config['handlers']['file']['filename']
log_path = f"logs/{log_path.format(time.strftime('%Y-%m-%d %H-%M-%S' , time.gmtime(DR_runtime.start_time_ns / 1000_000_000)))}"
mkdir = False
if not Path('logs/').is_dir():
Path('logs/').mkdir()
mkdir = True
self.logging_config['handlers']['file']['filename'] = log_path
logging.config.dictConfig(self.logging_config)
self.logger = logging.getLogger('main')
if mkdir:
self.logger.info(tr().main.logger.mkdir())
def dispatch_mod_event(self, event_name: str, *args, **kwargs) -> None:
self.mod_manager.dispatch_event(event_name, *args, **kwargs)
def init_mods(self) -> None:
"""验证/加载 mod"""
self.mod_module = []
mods = []
mod_path = Path(DR_runtime.mod_path)
if not mod_path.exists():
self.logger.info(tr().main.mod.find.faild.no_mod_folder())
return
# 寻找有效 mod
paths = mod_path.iterdir()
sys.path.append(DR_runtime.mod_path)
for mod_path in paths:
try:
if mod_path.name == '__pycache__':
continue
self.logger.info(tr().main.mod.find.start().format(mod_path))
if mod_path.is_dir():
if importlib.util.find_spec(mod_path.name) is not None:
mods.append(mod_path.name)
else:
self.logger.warning(tr().main.mod.load.faild.info().format(mod_path.name, tr().main.mod.find.faild.no_spec()))
elif mod_path.suffix in ('.pyz', '.zip', '.pyd', '.py'):
if importlib.util.find_spec(mod_path.name) is not None:
mods.append(mod_path.name)
except ImportError as e:
self.logger.warning(tr().main.mod.find.faild().format(mod_path, e))
self.logger.info(tr().main.mod.find.done())
# 加载有效 mod
module = []
for mod in mods:
try:
self.logger.info(tr().main.mod.load.start().format(mod))
mod_module = importlib.import_module(mod)
if not hasattr(mod_module, "mod_class"):
self.logger.warning(tr().main.mod.load.faild.info().format(mod, tr().main.mod.load.faild.no_mod_class()))
del mod_module # 释放内存
continue
mod_class: type(ModInfo) = mod_module.mod_class
mod_class = mod_class()
module.append(mod_class)
self.logger.info(tr().main.mod.load.info().format(mod_class.mod_id, mod_class.version))
except ImportError as e:
self.logger.warning(tr().main.mod.load.faild.info().format(mod, e))
self.logger.info(tr().main.mod.load.done())
self.mod_module = module
mod_list = []
for mod in module:
mod_list.append((mod.mod_id, mod.version))
# 调用 on_load
self.dispatch_event('on_load', game=self)
DR_runtime.DR_Mod_List = mod_list
from Difficult_Rocket.mod import loader as mod_loader
mod_loader.logger = logging.getLogger('mod_manager')
self.mod_manager = ModManager()
mod_class = self.mod_manager.load_mods()
self.mod_manager.init_mods(mod_class)
self.dispatch_mod_event('on_load', game=self)
def init_console(self) -> None:
self.console = self.console_class()
@ -166,32 +106,15 @@ class Game(Options):
else:
self.client.start()
def dispatch_event(self, event_name: str, *args, **kwargs) -> None:
"""向 mod 分发事件"""
for mod in self.mod_module:
if hasattr(mod, event_name):
try:
getattr(mod, event_name)(*args, **kwargs)
except Exception:
error = traceback.format_exc()
self.logger.error(tr().main.mod.event.error().format(event_name, error, mod.mod_id))
def log_env(self) -> None:
cache_steam = StringIO()
write_info_to_cache(cache_steam)
text = cache_steam.getvalue()
self.logger.info(text)
self.flush_option()
config_cache = self.logging_config.copy()
self.logging_config = {"logging_config": "too long to show"}
self.logger.info(f"\n{self.as_markdown()}")
self.logging_config = config_cache
self.logger.info(f'\n{self.as_markdown()}')
def setup(self) -> None:
self.client = client.Client(game=self, net_mode='local')
self.server = server.Server(net_mode='local')
def init(self, **kwargs) -> bool:
self.logger = logging.getLogger('main')
self.load_file()
self.setup()
self.log_env()
@ -199,9 +122,6 @@ class Game(Options):
def load_file(self) -> bool:
"""加载文件"""
self.logging_config = tools.load_file('configs/logger.toml')
self.init_logger()
self.init_mods()
self.init_console()
return True

View File

@ -4,14 +4,21 @@
# All rights reserved
# -------------------------------
import sys
import time
import logging
import traceback
import importlib
from pathlib import Path
from typing import List, Dict, Optional
from Difficult_Rocket.api.screen import BaseScreen
from Difficult_Rocket.api.types import Options, Version
from Difficult_Rocket.mod.api import ModInfo
# from Difficult_Rocket import DR_status, DR_runtime
from Difficult_Rocket.utils.translate import tr
from Difficult_Rocket.api.types import Options, Version
logger = logging.getLogger('mod_manager')
ONE_FILE_SUFFIX = ('.py', '.pyc', '.pyd')
PACKAGE_SUFFIX = ('.pyz', '.zip', '.dr_mod')
class ModManager(Options):
@ -20,21 +27,68 @@ class ModManager(Options):
mods_path: List[Path] = [Path('./mods')]
loaded_mod_modules: Dict[str, ModInfo] = {}
def find_mods(self) -> List[Path]:
def dispatch_event(self, event_name: str, *args, **kwargs):
"""
查找mods文件夹下的所有mod
分发事件
:param event_name:
:param args:
:param kwargs:
:return:
"""
for mod in self.loaded_mod_modules.values():
if hasattr(mod, event_name):
try:
getattr(mod, event_name)(*args, **kwargs)
except Exception as e:
logger.error(tr().mod.event.error().format(mod, event_name, e, traceback.format_exc()))
def load_mods(self, extra_path: Optional[List[Path]] = None) -> List[type(ModInfo)]:
"""
加载所有 mod (可提供额外的 mod 路径)
:param extra_path: 额外的 mod 路径
:return:
"""
find_path = self.mods_path + (extra_path if extra_path is not None else [])
sys.path += [str(path_) for path_ in find_path]
mods = []
for path in self.mods_path:
start_time = time.time()
logger.info(tr().mod.load.start().format(find_path))
for path in find_path:
if not path.exists():
path.mkdir(parents=True)
continue
for mod in path.iterdir():
...
def init(self) -> None:
self.logger = logging.getLogger('client')
self.logger.name = 'mod_manager'
self.logger.info('Mod Manager init')
try:
if mod.name == '__pycache__':
# 忽略 __pycache__ 文件夹 (Python 编译文件)
continue
logger.info(tr().mod.load.loading().format(mod))
if mod.is_dir() or mod.suffix in PACKAGE_SUFFIX or mod.suffix in ONE_FILE_SUFFIX:
# 文件夹 mod
loading_mod = importlib.import_module(mod.name)
if not hasattr(loading_mod, 'mod_class'):
logger.warning(tr().mod.load.faild.no_mod_class().format(mod))
continue
mod_class: type(ModInfo) = loading_mod.mod_class # 获取 mod 类
mods.append(mod_class)
except ImportError:
logger.warning(tr().mod.load.faild.error().format(mod))
logger.info(tr().mod.load.use_time().format(time.time() - start_time))
return mods
def init_mods(self, mods: List[type(ModInfo)]):
"""
加载 mod
:param mods:
:return:
"""
start_time = time.time()
for mod_class in mods:
try:
init_mod = mod_class()
self.loaded_mod_modules[init_mod.name] = init_mod
logger.info(tr().mod.init.success().format(init_mod, init_mod.version))
except Exception as e:
logger.error(tr().mod.init.faild().format(mod_class, e, traceback.format_exc()))
continue
logger.info(tr().mod.init.use_time().format(time.time() - start_time))

View File

@ -140,12 +140,12 @@ class Translates:
def __str__(self):
if not any(not x[0] for x in self._get_list):
return self._value
return str(self._value)
if self._config.crack_normal:
return f'{".".join(f"{gets[1]}({gets[0]})" for gets in self._get_list)}'
elif self._config.insert_crack:
return f'{self._value}.{".".join(gets[1] for gets in self._get_list if not gets[0])}'
return self._value
return str(self._value)
class Tr:

View File

@ -20,16 +20,18 @@ logger.logfile_level = "日志文件记录级别:"
logger.logfile_fmt = "日志文件记录格式:"
logger.logfile_datefmt = "日志文件日期格式:"
game_start.at = "游戏主线程开始于:"
mod.find.start = "正在校验 Mod: {}"
mod.find.faild.no_spec = "importlib 无法找到 spec"
mod.find.faild.no_mod_folder = "没有找到 Mod 文件夹"
mod.find.done = "所有 Mod 校验完成"
mod.load.start = "正在加载 Mod: {}"
mod.load.info = "mod id: {} 版本号: {}"
mod.load.faild.info = "Mod 加载失败: {} 错误信息: {}"
mod.load.faild.no_mod_class = "没有找到 Mod 类"
mod.load.done = "所有 Mod 加载完成"
mod.event.error = "Mod 事件 {} 发生错误 {} Mod: {}"
[mod]
load.start = "开始加载路径 {} 下的 Mod"
load.use_time = "Mod 加载消耗时间: {} 秒"
load.done = "所有 Mod 加载完成"
load.loading = "正在加载 Mod: {}"
load.faild.error = "Mod 加载失败: {} 错误信息: {}"
load.faild.no_mod_class = "Mod 加载失败: {} 没有找到 Mod 类"
init.success = "mod id: {} 版本号: {}"
init.faild = "Mod 初始化失败: {} 错误信息: {}\n堆栈信息: {}"
init.use_time = "Mod 初始化消耗时间: {} 秒"
event.error = "Mod 事件 {} 发生错误 {} Mod: {}\n堆栈信息: {}"
[client]
setup.start = "客户端加载开始"

View File

@ -22,7 +22,7 @@ datefmt = "%Y-%m-%d %H:%M:%S"
[handlers.console]
class = "logging.StreamHandler"
formatter = "file"
level = "DEBUG"
level = "INFO"
[handlers.file]
class = "logging.FileHandler"