就,天天重构,淦!
This commit is contained in:
parent
226fcbfce8
commit
996fb72b54
@ -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
|
||||
|
||||
@ -80,4 +100,4 @@ if DR_status.playing:
|
||||
@new_thread('think')
|
||||
def think(some_thing_to_think):
|
||||
gotcha = think_it(some_thing_to_think)
|
||||
return gotcha
|
||||
return gotcha
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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:
|
||||
|
@ -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 = "客户端加载开始"
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user