就,天天重构,淦!
This commit is contained in:
parent
226fcbfce8
commit
996fb72b54
@ -4,6 +4,10 @@
|
|||||||
# All rights reserved
|
# All rights reserved
|
||||||
# -------------------------------
|
# -------------------------------
|
||||||
|
|
||||||
|
import time
|
||||||
|
import logging.config
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from Difficult_Rocket.api.types import Options, Version
|
from Difficult_Rocket.api.types import Options, Version
|
||||||
|
|
||||||
game_version = Version("0.8.3.0") # 游戏版本
|
game_version = Version("0.8.3.0") # 游戏版本
|
||||||
@ -70,6 +74,22 @@ class _DR_status(Options):
|
|||||||
|
|
||||||
DR_status = _DR_status()
|
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:
|
if DR_status.playing:
|
||||||
from Difficult_Rocket.utils.thread import new_thread
|
from Difficult_Rocket.utils.thread import new_thread
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ class ClientWindow(Window):
|
|||||||
self.set_icon(pyglet.image.load('./textures/icon.png'))
|
self.set_icon(pyglet.image.load('./textures/icon.png'))
|
||||||
self.load_fonts()
|
self.load_fonts()
|
||||||
self.screen_list['DR_debug'] = DRDEBUGScreen(self)
|
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:
|
def load_fonts(self) -> None:
|
||||||
fonts_folder_path = self.main_config['runtime']['fonts_folder']
|
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.logger.info(tr().language_available().format(os.listdir('./configs/lang')))
|
||||||
self.save_info()
|
self.save_info()
|
||||||
elif command.find('mods'):
|
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}")
|
self.logger.info(f"mod: {mod.name} id: {mod.mod_id} version: {mod.version}")
|
||||||
|
|
||||||
@_call_screen_after
|
@_call_screen_after
|
||||||
@ -483,7 +483,7 @@ class ClientWindow(Window):
|
|||||||
|
|
||||||
@_call_screen_before
|
@_call_screen_before
|
||||||
def on_close(self, source: str = 'window') -> None:
|
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_get().format(tr().game[source]()))
|
||||||
self.logger.info(tr().window.game.stop())
|
self.logger.info(tr().window.game.stop())
|
||||||
# self.fps_log.check_list = False
|
# self.fps_log.check_list = False
|
||||||
|
@ -11,27 +11,21 @@ github: @shenjackyuanjie
|
|||||||
gitee: @shenjackyuanjie
|
gitee: @shenjackyuanjie
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
import importlib
|
|
||||||
import importlib.util
|
|
||||||
import logging.config
|
import logging.config
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from pathlib import Path
|
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.utils import tools
|
||||||
from Difficult_Rocket.api.types import Options
|
from Difficult_Rocket.api.types import Options
|
||||||
from Difficult_Rocket.utils.translate import tr
|
from Difficult_Rocket.utils.translate import tr
|
||||||
from Difficult_Rocket.runtime import DR_runtime
|
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.utils.thread import new_thread
|
||||||
from Difficult_Rocket.crash import write_info_to_cache
|
from Difficult_Rocket.crash import write_info_to_cache
|
||||||
from Difficult_Rocket import client, server, DR_status
|
from Difficult_Rocket import client, server, DR_status
|
||||||
@ -78,75 +72,21 @@ class Game(Options):
|
|||||||
console_class: Console = Console
|
console_class: Console = Console
|
||||||
|
|
||||||
main_config: Dict
|
main_config: Dict
|
||||||
logging_config: Dict
|
|
||||||
logger: logging.Logger
|
logger: logging.Logger
|
||||||
|
|
||||||
mod_module: List["ModInfo"] = []
|
mod_manager: ModManager
|
||||||
|
|
||||||
def init_logger(self) -> None:
|
def dispatch_mod_event(self, event_name: str, *args, **kwargs) -> None:
|
||||||
log_path = self.logging_config['handlers']['file']['filename']
|
self.mod_manager.dispatch_event(event_name, *args, **kwargs)
|
||||||
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 init_mods(self) -> None:
|
def init_mods(self) -> None:
|
||||||
"""验证/加载 mod"""
|
"""验证/加载 mod"""
|
||||||
self.mod_module = []
|
from Difficult_Rocket.mod import loader as mod_loader
|
||||||
mods = []
|
mod_loader.logger = logging.getLogger('mod_manager')
|
||||||
mod_path = Path(DR_runtime.mod_path)
|
self.mod_manager = ModManager()
|
||||||
if not mod_path.exists():
|
mod_class = self.mod_manager.load_mods()
|
||||||
self.logger.info(tr().main.mod.find.faild.no_mod_folder())
|
self.mod_manager.init_mods(mod_class)
|
||||||
return
|
self.dispatch_mod_event('on_load', game=self)
|
||||||
# 寻找有效 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
|
|
||||||
|
|
||||||
def init_console(self) -> None:
|
def init_console(self) -> None:
|
||||||
self.console = self.console_class()
|
self.console = self.console_class()
|
||||||
@ -166,32 +106,15 @@ class Game(Options):
|
|||||||
else:
|
else:
|
||||||
self.client.start()
|
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:
|
def log_env(self) -> None:
|
||||||
cache_steam = StringIO()
|
self.logger.info(f'\n{self.as_markdown()}')
|
||||||
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
|
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
self.client = client.Client(game=self, net_mode='local')
|
self.client = client.Client(game=self, net_mode='local')
|
||||||
self.server = server.Server(net_mode='local')
|
self.server = server.Server(net_mode='local')
|
||||||
|
|
||||||
def init(self, **kwargs) -> bool:
|
def init(self, **kwargs) -> bool:
|
||||||
|
self.logger = logging.getLogger('main')
|
||||||
self.load_file()
|
self.load_file()
|
||||||
self.setup()
|
self.setup()
|
||||||
self.log_env()
|
self.log_env()
|
||||||
@ -199,9 +122,6 @@ class Game(Options):
|
|||||||
|
|
||||||
def load_file(self) -> bool:
|
def load_file(self) -> bool:
|
||||||
"""加载文件"""
|
"""加载文件"""
|
||||||
self.logging_config = tools.load_file('configs/logger.toml')
|
|
||||||
self.init_logger()
|
|
||||||
self.init_mods()
|
self.init_mods()
|
||||||
self.init_console()
|
self.init_console()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -4,14 +4,21 @@
|
|||||||
# All rights reserved
|
# All rights reserved
|
||||||
# -------------------------------
|
# -------------------------------
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
import traceback
|
||||||
|
import importlib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Dict, Optional
|
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.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):
|
class ModManager(Options):
|
||||||
@ -20,21 +27,68 @@ class ModManager(Options):
|
|||||||
mods_path: List[Path] = [Path('./mods')]
|
mods_path: List[Path] = [Path('./mods')]
|
||||||
loaded_mod_modules: Dict[str, ModInfo] = {}
|
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:
|
: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 = []
|
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():
|
if not path.exists():
|
||||||
path.mkdir(parents=True)
|
path.mkdir(parents=True)
|
||||||
continue
|
continue
|
||||||
for mod in path.iterdir():
|
for mod in path.iterdir():
|
||||||
...
|
try:
|
||||||
|
if mod.name == '__pycache__':
|
||||||
def init(self) -> None:
|
# 忽略 __pycache__ 文件夹 (Python 编译文件)
|
||||||
self.logger = logging.getLogger('client')
|
continue
|
||||||
self.logger.name = 'mod_manager'
|
logger.info(tr().mod.load.loading().format(mod))
|
||||||
self.logger.info('Mod Manager init')
|
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):
|
def __str__(self):
|
||||||
if not any(not x[0] for x in self._get_list):
|
if not any(not x[0] for x in self._get_list):
|
||||||
return self._value
|
return str(self._value)
|
||||||
if self._config.crack_normal:
|
if self._config.crack_normal:
|
||||||
return f'{".".join(f"{gets[1]}({gets[0]})" for gets in self._get_list)}'
|
return f'{".".join(f"{gets[1]}({gets[0]})" for gets in self._get_list)}'
|
||||||
elif self._config.insert_crack:
|
elif self._config.insert_crack:
|
||||||
return f'{self._value}.{".".join(gets[1] for gets in self._get_list if not gets[0])}'
|
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:
|
class Tr:
|
||||||
|
@ -20,16 +20,18 @@ logger.logfile_level = "日志文件记录级别:"
|
|||||||
logger.logfile_fmt = "日志文件记录格式:"
|
logger.logfile_fmt = "日志文件记录格式:"
|
||||||
logger.logfile_datefmt = "日志文件日期格式:"
|
logger.logfile_datefmt = "日志文件日期格式:"
|
||||||
game_start.at = "游戏主线程开始于:"
|
game_start.at = "游戏主线程开始于:"
|
||||||
mod.find.start = "正在校验 Mod: {}"
|
|
||||||
mod.find.faild.no_spec = "importlib 无法找到 spec"
|
[mod]
|
||||||
mod.find.faild.no_mod_folder = "没有找到 Mod 文件夹"
|
load.start = "开始加载路径 {} 下的 Mod"
|
||||||
mod.find.done = "所有 Mod 校验完成"
|
load.use_time = "Mod 加载消耗时间: {} 秒"
|
||||||
mod.load.start = "正在加载 Mod: {}"
|
load.done = "所有 Mod 加载完成"
|
||||||
mod.load.info = "mod id: {} 版本号: {}"
|
load.loading = "正在加载 Mod: {}"
|
||||||
mod.load.faild.info = "Mod 加载失败: {} 错误信息: {}"
|
load.faild.error = "Mod 加载失败: {} 错误信息: {}"
|
||||||
mod.load.faild.no_mod_class = "没有找到 Mod 类"
|
load.faild.no_mod_class = "Mod 加载失败: {} 没有找到 Mod 类"
|
||||||
mod.load.done = "所有 Mod 加载完成"
|
init.success = "mod id: {} 版本号: {}"
|
||||||
mod.event.error = "Mod 事件 {} 发生错误 {} Mod: {}"
|
init.faild = "Mod 初始化失败: {} 错误信息: {}\n堆栈信息: {}"
|
||||||
|
init.use_time = "Mod 初始化消耗时间: {} 秒"
|
||||||
|
event.error = "Mod 事件 {} 发生错误 {} Mod: {}\n堆栈信息: {}"
|
||||||
|
|
||||||
[client]
|
[client]
|
||||||
setup.start = "客户端加载开始"
|
setup.start = "客户端加载开始"
|
||||||
|
@ -22,7 +22,7 @@ datefmt = "%Y-%m-%d %H:%M:%S"
|
|||||||
[handlers.console]
|
[handlers.console]
|
||||||
class = "logging.StreamHandler"
|
class = "logging.StreamHandler"
|
||||||
formatter = "file"
|
formatter = "file"
|
||||||
level = "DEBUG"
|
level = "INFO"
|
||||||
|
|
||||||
[handlers.file]
|
[handlers.file]
|
||||||
class = "logging.FileHandler"
|
class = "logging.FileHandler"
|
||||||
|
Loading…
Reference in New Issue
Block a user