diff --git a/Difficult_Rocket/__init__.py b/Difficult_Rocket/__init__.py index f76dfae..3082502 100644 --- a/Difficult_Rocket/__init__.py +++ b/Difficult_Rocket/__init__.py @@ -10,15 +10,20 @@ mail: 3695888@qq.com github: @shenjackyuanjie gitee: @shenjackyuanjie """ - +import ctypes from Difficult_Rocket.utils.typings import Options from libs.MCDR.version import Version -game_version = Version("0.6.3") +game_version = Version("0.6.4") __version__ = game_version +long_version: int = 1 +""" +long_version: 一个用于标记内部协议的整数 +1: 我可算想起来还有这回事了 v0.6.4 +""" class DR_option(Options): @@ -31,6 +36,7 @@ class DR_option(Options): record_threads: bool = True use_cProfile: bool = False use_local_logging: bool = False + report_translate_no_found: bool = True # tests playing: bool = False @@ -45,14 +51,16 @@ class _DR_runtime(Options): name = 'DR Runtime' # game statue DR_version: Version = game_version + DR_long_version: int = long_version # run status start_time_ns: int = None - client_setup_time_ns: int = None - server_setup_time_ns: int = None + client_setup_cause_ns: int = None + server_setup_cause_ns: int = None # game options _language = 'zh-CN' + default_language: str = 'zh-CN' def __init__(self, **kwargs): super().__init__(**kwargs) diff --git a/Difficult_Rocket/client/__init__.py b/Difficult_Rocket/client/__init__.py index 0c04e81..693ed61 100644 --- a/Difficult_Rocket/client/__init__.py +++ b/Difficult_Rocket/client/__init__.py @@ -24,7 +24,7 @@ from decimal import Decimal from Difficult_Rocket import Options, DR_runtime from Difficult_Rocket.command import line, tree from Difficult_Rocket.utils.translate import tr -# from Difficult_Rocket.client.screen import DRScreen +from Difficult_Rocket.client.screen import DRScreen # from Difficult_Rocket.client.screen import DRDEBUGScreen from Difficult_Rocket.utils import tools, translate from Difficult_Rocket.utils.new_thread import new_thread @@ -138,7 +138,7 @@ class ClientWindow(Window): self.logger.info(tr.lang('window', 'os.pid_is').format(os.getpid(), os.getppid())) end_time = time.time_ns() self.use_time = end_time - start_time - DR_runtime.client_setup_time_ns = self.use_time + DR_runtime.client_setup_cause_ns = self.use_time self.logger.info(tr.lang('window', 'setup.use_time').format(Decimal(self.use_time) / 1000000000)) self.logger.debug(tr.lang('window', 'setup.use_time_ns').format(self.use_time)) self.count = 0 diff --git a/Difficult_Rocket/client/guis/rua.lua b/Difficult_Rocket/client/guis/rua.lua deleted file mode 100644 index ea29fb0..0000000 --- a/Difficult_Rocket/client/guis/rua.lua +++ /dev/null @@ -1,5 +0,0 @@ ---- ---- Generated by EmmyLua(https://github.com/EmmyLua) ---- Created by shenjack. ---- DateTime: 2022/11/20 11:57 ---- \ No newline at end of file diff --git a/Difficult_Rocket/client/screen.py b/Difficult_Rocket/client/screen.py index c8e7754..adbab2f 100644 --- a/Difficult_Rocket/client/screen.py +++ b/Difficult_Rocket/client/screen.py @@ -4,14 +4,17 @@ # All rights reserved # ------------------------------- -# import ctypes +import typing -from Difficult_Rocket.client import ClientWindow from Difficult_Rocket.command.tree import CommandTree +if typing.TYPE_CHECKING: + from Difficult_Rocket.client import ClientWindow + + class BaseScreen: - def __init__(self, main_window: ClientWindow): + def __init__(self, main_window: "ClientWindow"): self.window_pointer = main_window self.command_tree = None self.create_command_tree() @@ -24,10 +27,10 @@ class BaseScreen: class DRScreen(BaseScreen): - def __init__(self, main_window: ClientWindow): + def __init__(self, main_window: "ClientWindow"): super().__init__(main_window) class DRDEBUGScreen(BaseScreen): - def __init__(self, main_window: ClientWindow): + def __init__(self, main_window: "ClientWindow"): super().__init__(main_window) diff --git a/Difficult_Rocket/crash/crash.py b/Difficult_Rocket/crash/crash.py index 1b90eb2..a144058 100644 --- a/Difficult_Rocket/crash/crash.py +++ b/Difficult_Rocket/crash/crash.py @@ -76,8 +76,11 @@ def write_markdown_tablet(crash_file: TextIO, tablet: list) -> None: a_len = max(tablet[1], 6) b_len = max(tablet[2], 5) c_len = max(tablet[3], 10) - crash_file.write(f'\n| Option{" " * (a_len - 4)}| Value{" " * (b_len[2] - 3)} | Value Type{" " * (c_len[3] - 8)} |\n') + crash_file.write(f'\n| Option{" " * (a_len - 4)} | Value{" " * (b_len - 3)} | Value Type{" " * (c_len - 8)} |\n') crash_file.write(f'|:{"-" * (a_len + 3)}|:{"-" * (b_len + 3)}|:{"-" * (c_len + 3)}|\n') + for a, b, c in tablet[0]: + b, c = str(b), str(c) + crash_file.write(f'| `{a}`{" " * (a_len - len(a))} | `{b}`{" " * (b_len - len(b))} | `{c}`{" " * (c_len - len(c))} |\n') def create_crash_report(info: str = None) -> None: @@ -95,31 +98,15 @@ def create_crash_report(info: str = None) -> None: # 运行状态信息 from Difficult_Rocket import DR_option, DR_runtime cache_stream.write(Run_message) - cache_stream.write(markdown_line_handler(f'DR Version: {Difficult_Rocket.game_version}', level=1)) cache_stream.write(markdown_line_handler(f'DR language: {DR_runtime.language}', level=1)) cache_stream.write(markdown_line_handler(f'Running Dir: {Path(os.curdir).resolve()}', level=1)) option_with_len = DR_runtime.option_with_len() - option_with_len[1] = max(option_with_len[1], 6) - option_with_len[2] = max(option_with_len[2], 5) - option_with_len[3] = max(option_with_len[3], 10) - cache_stream.write(f'\n| Option{" " * (option_with_len[1] - 4)} | Value{" " * (option_with_len[2] - 3)} | Value Type{" " * (option_with_len[3] - 8)} |\n') - cache_stream.write(f'|:{"-" * (option_with_len[1] + 3)}|:{"-" * (option_with_len[2] + 3)}|:{"-" * (option_with_len[3] + 3)}|\n') - for a, b, c in option_with_len[0]: - b, c = str(b), str(c) - cache_stream.write(f'| `{a}`{" " * (option_with_len[1] - len(a))} | `{b}`{" " * (option_with_len[2] - len(b))} | `{c}`{" " * (option_with_len[3] - len(c))} |\n') - + write_markdown_tablet(crash_file=cache_stream, tablet=option_with_len) # # DR 的游戏设置 cache_stream.write(DR_configs) option_with_len = DR_option.option_with_len() - option_with_len[1] = max(option_with_len[1], 6) - option_with_len[2] = max(option_with_len[2], 5) - option_with_len[3] = max(option_with_len[3], 10) - cache_stream.write(f'| Option{" " * (option_with_len[1] - 4)} | Value{" " * (option_with_len[2] - 3)} | Value Type{" " * (option_with_len[3] - 8)} |\n') - cache_stream.write(f'|:{"-" * (option_with_len[1] + 3)}|:{"-" * (option_with_len[2] + 3)}|:{"-" * (option_with_len[3] + 3)}|\n') - for a, b, c in option_with_len[0]: - b, c = str(b), str(c) - cache_stream.write(f'| `{a}`{" " * (option_with_len[1] - len(a))} | `{b}`{" " * (option_with_len[2] - len(b))} | `{c}`{" " * (option_with_len[3] - len(c))} |\n') + write_markdown_tablet(crash_file=cache_stream, tablet=option_with_len) # 多进程信息 cache_stream.write(Process_message) for process in all_process: @@ -150,10 +137,9 @@ def create_crash_report(info: str = None) -> None: cache_stream.write(markdown_line_handler(f'processor: {to_code(platform.processor())}', level=1)) cache_stream.write(markdown_line_handler(f'release: {to_code(platform.release())}', level=1)) cache_stream.write(markdown_line_handler(f'version: {to_code(platform.version())}', level=1)) - except io.BlockingIOError: - raise finally: get_cache = cache_stream.getvalue() + cache_stream.close() with open('./crash_report/{}'.format(filename), 'w+', encoding='utf-8') as crash_file: crash_file.write(get_cache) diff --git a/Difficult_Rocket/exception/language.py b/Difficult_Rocket/exception/language.py index ec0c083..8964f8f 100644 --- a/Difficult_Rocket/exception/language.py +++ b/Difficult_Rocket/exception/language.py @@ -22,7 +22,15 @@ class TranslateError(BaseError): class TranslateKeyNotFound(TranslateError): """语言文件某项缺失""" + def __init__(self, item_names: list): + self.item_names: list = item_names + + def __str__(self): + return f"{self.__class__.__name__}: Can't get item {'. '.join(self.item_names)}" class TranslateFileNotFound(TranslateError): """翻译文件缺失""" + + + diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index 2a41959..4da0294 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -59,7 +59,7 @@ class Game: self.server = server.Server(net_mode='local') def python_version_check(self) -> None: # best 3.8+ and write at 3.8.10 - self.logger.info('{} {} %(levelname)d'.format(tr['main']['version.now_on'], self.on_python_v)) + self.logger.info('{} {}'.format(tr['main']['version.now_on'], self.on_python_v)) if self.on_python_v_info[0] == 2: self.logger.critical('%s' % tr['main']['version.need3+']) raise SystemError('%s' % tr['main']['version.need3+']) diff --git a/Difficult_Rocket/server/__init__.py b/Difficult_Rocket/server/__init__.py index 5c2351b..ff3b3ed 100644 --- a/Difficult_Rocket/server/__init__.py +++ b/Difficult_Rocket/server/__init__.py @@ -12,33 +12,31 @@ gitee: @shenjackyuanjie """ import os -import sys +# import pymunk import logging - -if __name__ == '__main__': # been start will not run this - sys.path.append('/bin/libs') - sys.path.append('/bin') +# import multiprocessing from Difficult_Rocket.utils import tools from Difficult_Rocket.utils.translate import tr -from Difficult_Rocket.api.delivery import Delivery -from Difficult_Rocket.utils.new_thread import new_thread +# from Difficult_Rocket.api.delivery import Delivery +# from Difficult_Rocket.utils.new_thread import new_thread # TODO 改变服务端启动逻辑 0.6.0会写完的( class Server: - def __init__(self, net_mode='local', Dev: Delivery = Delivery): + def __init__(self, net_mode='local'): # logging self.logger = logging.getLogger('server') # value - self.process_id = 'Server' + self.process_id = os.getpid() + # os.set self.process_name = 'server process' # config self.config = tools.load_file('configs/main.config') - self.dev = Dev - self.net_mode = net_mode + # self.dev = Dev + # self.net_mode = net_mode self.logger.info(tr.lang('server', 'setup.done')) def run(self): diff --git a/Difficult_Rocket/utils/translate.py b/Difficult_Rocket/utils/translate.py index 3d629b7..8ab9ccc 100644 --- a/Difficult_Rocket/utils/translate.py +++ b/Difficult_Rocket/utils/translate.py @@ -5,15 +5,16 @@ # ------------------------------- """ -writen by shenjackyuanjie +writen by shenjackyuanjie <3695888@qq.com> mail: 3695888@qq.com github: @shenjackyuanjie gitee: @shenjackyuanjie """ import inspect +# import dataclasses -from typing import Union +from typing import Union, Tuple, Any, Type, List, Dict, Hashable from Difficult_Rocket import DR_runtime, DR_option from Difficult_Rocket.utils import tools @@ -24,6 +25,63 @@ from Difficult_Rocket.exception.language import * 你觉得呢? """ +class Translated: + def __init__(self, value: Union[list, tuple, dict, str], raise_error: bool = False): + self.value = value + self.raise_error = raise_error + self.item_names = [] + + def __getattr__(self, item): + if hasattr(object, item): + return getattr(object, item) + self.item_names.append(item) + return self + + def __getitem__(self, item): + self.item_names.append(item) + return self + + def __str__(self): + if not self.item_names: + return self.value + else: + return f'{self.value}.{".".join(self.item_names)}' + + +class Translating: + def __init__(self, value: Union[Dict[str, Any], list, tuple], raise_error: bool = False, get_list: list = None): + self.value: Union[Dict[str, Any], list, tuple] = value + self.raise_error = raise_error + self.get_list = get_list or [] + + def __getitem__(self, item: Union[str, Hashable]) -> Union["Translating", Translated]: + cache_get_list = self.get_list.copy() + cache_get_list.append(item) + try: + cache = self.value[item] + except (KeyError, TypeError): + if DEBUG_PRINT: + frame = inspect.currentframe() + last_frame = frame.f_back + if last_frame.f_code == self.__getattr__.__code__: + last_frame = last_frame.f_back + call_info = f'Translate Not Found at {last_frame.f_code.co_name} by {".".join(cache_get_list)} at:' \ + f'{last_frame.f_code.co_filename}:{last_frame.f_lineno}' + print(call_info) + if not self.raise_error: + return Translated('.'.join(cache_get_list), raise_error=False) + else: + raise GetItemError(item_names=cache_get_list) + return Translating(value=cache, raise_error=self.raise_error, get_list=cache_get_list) + + def __getattr__(self, item: Union[str, Hashable]) -> Union["Translating", Translated]: + if hasattr(object, item): + return getattr(object, item) + return self.__getitem__(item) + + def __str__(self): + return str(self.value) + class Tr: """ @@ -31,19 +89,14 @@ class Tr: GOOD """ - def __init__(self): - self.config_regs = {} + def __init__(self, language: str = DR_runtime.language): + self.language_name = language + self.translates: Dict = tools.load_file(f'configs/lang/{language}.toml') + self.default_translate: Dict = tools.load_file(f'configs/lang/{DR_runtime.default_language}.toml') + self.不抛出异常 = False - def add_config(self, configs: dict) -> None: - frame = inspect.currentframe() - self.config_regs[frame.f_back.f_code.co_filename] = configs - - def __call__(self, *args, **kwargs): - frame = inspect.currentframe() - if frame.f_back.f_code.co_filename in self.config_regs: - ... - else: - ... + def __call__(self): + ... class Lang: @@ -60,8 +113,8 @@ class Lang: """ def __init__(self) -> None: - self.翻译结果 = tools.load_file(f'configs/lang/{DR_runtime.language}.toml') - self.默认翻译 = tools.load_file('configs/lang/zh-CN.toml') + self.translates = tools.load_file(f'configs/lang/{DR_runtime.language}.toml') + self.default_translates = tools.load_file('configs/lang/zh-CN.toml') self.直接返回原始数据 = True def __str__(self) -> str: @@ -69,10 +122,10 @@ class Lang: def __getitem__(self, item) -> Union[int, str, list, dict]: try: - return self.翻译结果[item] + return self.translates[item] except KeyError: try: - return self.默认翻译[item] + return self.default_translates[item] except KeyError: raise TranslateKeyNotFound(f'there\'s no key {item} in both {DR_option.language} and zh-CN') @@ -83,20 +136,20 @@ class Lang: # honor_existing=False, # depth=2) try: - 结果 = self.翻译结果 - for 选项 in args: - 结果 = 结果[选项] - return 结果 + result = self.translates + for option in args: + result = result[option] + return result except KeyError: try: - 结果 = self.默认翻译 - for 选项 in args: - 结果 = 结果[选项] - return 结果 - except KeyError: + result = self.default_translates + for option in args: + result = result[option] + return result + except KeyError as e: if self.直接返回原始数据: return args - raise TranslateKeyNotFound(f'there\'s no key {args} in both {DR_option.language} and zh-CN') + raise TranslateKeyNotFound(f'there\'s no key {args} in both {DR_option.language} and zh-CN') from e def 翻译(self, *args) -> Union[int, str, list, dict]: return self.lang(args) @@ -104,9 +157,9 @@ class Lang: def _update_lang(self) -> str: """ 用于更新语言(内部调用) - @return: 设置完成后的语言 + :return: 设置完成后的语言 """ - self.翻译结果 = tools.load_file(f'configs/lang/{DR_option.language}.toml') + self.translates = tools.load_file(f'configs/lang/{DR_option.language}.toml') return DR_option.language @@ -134,3 +187,5 @@ CMPL = 'Cascadia Mono PL' 微软等宽无线 = CM 微软等宽带电线 = CCPL 微软等宽带电线无线 = CMPL + +得意黑 = '得意黑' diff --git a/README.md b/README.md index 7f33963..2ee5b80 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ ## 版本 [![Generic badge](https://img.shields.io/badge/Release-0.6.1-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases) -[![Generic badge](https://img.shields.io/badge/Pre_Release-0.6.1-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases) -[![Generic badge](https://img.shields.io/badge/Devloping-0.6.3-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases) +[![Generic badge](https://img.shields.io/badge/Pre_Release-0.6.4-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases) +[![Generic badge](https://img.shields.io/badge/Devloping-0.7.0-blue.svg)](https://github.com/shenjackyuanjie/Difficult-Rocket/releases) ## English README please look [here](../README.md) diff --git a/configs/lang/zh-CN.toml b/configs/lang/zh-CN.toml index 9a4fe5d..7a4b3ee 100644 --- a/configs/lang/zh-CN.toml +++ b/configs/lang/zh-CN.toml @@ -53,3 +53,6 @@ language = "简体中文" [server] "setup.done" = "服务端载入完成" "os.pid_is" = "服务端 PID: {} PPID: {}" + +[game] + diff --git a/docs/update_logs.md b/docs/update_logs.md index d920ff2..7f7ae5b 100644 --- a/docs/update_logs.md +++ b/docs/update_logs.md @@ -8,13 +8,24 @@ ## Readme First! ##### most badge can be clicked and jump [![Generic badge](https://img.shields.io/badge/SemVer-2.0.0-blue.svg)](https://Semver.org/) -![Generic badge](https://img.shields.io/badge/Version-0.6.1-yellow.svg) +![Generic badge](https://img.shields.io/badge/Version-0.6.4-yellow.svg) - [![Readme-github](https://img.shields.io/badge/Readme-Github-blue.svg?style=flat-square&logo=Github)](https://github.com/shenjackyuanjie/Difficult-Rocket) - [![Readme-gitee](https://img.shields.io/badge/Readme-Gitee-blue.svg?style=flat-square&logo=Gitee)](https://gitee.com/shenjackyuanjie/Difficult-Rocket) - [![Readme-gitee](https://img.shields.io/badge/Readme-中文(点我!)-blue.svg?style=flat-square)](README-cn.md) - Using [SemVer 2.0.0](https://semver.org/) to manage version +## 20221124 V 0.6.4 + +### 最后的 0.6 呢 + +### Add + +- `Logger!` +- nuitka 文档 +- 准备给我的 5600x 的散热器洗一洗( +- 一些 client + ## 20220627 ## 20220511 V 0.6.3 diff --git a/libs/utils/logger.py b/libs/utils/logger.py index d8652a0..4354b0e 100644 --- a/libs/utils/logger.py +++ b/libs/utils/logger.py @@ -7,6 +7,7 @@ # Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com # All rights reserved # ------------------------------- +import io import os import re import sys @@ -17,8 +18,6 @@ import threading import dataclasses from abc import ABC -from queue import Queue -from time import strftime from types import FrameType from logging import NOTSET, DEBUG from typing import NamedTuple, Optional, Type, Union, Dict, Iterable, Any, List @@ -434,6 +433,10 @@ class StdHandler(StreamHandlerTemplate): print('', end='', flush=True) return True + def __repr__(self): + return f'StdHandler(level={self.level}, formatter={self.formatter})' + + class CachedFileHandler(StreamHandlerTemplate): """ 缓存文件的处理器 """ @@ -454,15 +457,14 @@ class CachedFileHandler(StreamHandlerTemplate): else: self.file_conf = LogFileConf() # 缓存 - self.string_queue = Queue(maxsize=self.file_conf.file_cache_len) + self.len = 0 + self.cache_stream = io.StringIO() # 状态 self.started = True self.thread_started = False - self.running = False + self.flushing = False # 同步锁 - self.cache_lock = threading.Lock() # 主锁 - self.time_limit_lock = ThreadLock(self.cache_lock, time_out=1 / 60) # 直接用于 with 的主锁 - self.threaded_write = threading.Timer(1, self._thread_write, kwargs={'by_thread': True}) # 基于 timer 的多线程 + self.threaded_write = threading.Timer(1, self.flush, kwargs={'by_thread': True}) # 基于 timer 的多线程 def _start_thread(self) -> bool: """ @@ -472,7 +474,7 @@ class CachedFileHandler(StreamHandlerTemplate): """ if self.thread_started: return False - self.threaded_write = threading.Timer(1, self._thread_write, kwargs={'by_thread': True}) + self.threaded_write = threading.Timer(1, self.flush, kwargs={'by_thread': True}) self.threaded_write.start() self.thread_started = True return True @@ -488,29 +490,38 @@ class CachedFileHandler(StreamHandlerTemplate): return False self.threaded_write.cancel() - def _thread_write(self, by_thread: bool) -> None: - if not self.string_queue.empty(): # 队列非空 - with self.time_limit_lock and open(file=self.file_conf.file_name, mode=self.file_conf.file_mode, - encoding=self.file_conf.file_encoding) as log_file: - while not self.string_queue.empty(): - log_file.write(self.string_queue.get()) - def write(self, message: Message_content) -> bool: - if not message.flush: - if self.string_queue.qsize() + 1 <= self.file_conf.file_cache_len: - self.string_queue.put_nowait(message) - else: - if not self.thread_started: - self.threaded_write.start() - else: - ... + self.len += 1 + self.cache_stream.write(message.text) + if message.flush or self.len >= self.file_conf.file_cache_len: + if not self.flush(): + self.flush() + elif not self.thread_started: + self._start_thread() return True def close(self) -> bool: - ... + self.cache_stream.close() + return True + + def flush(self, by_thread: Optional[bool] = False) -> bool: + if by_thread: + self.threaded_write = threading.Timer(1, self.flush, kwargs={'by_thread': True}) + self.threaded_write.start() + if self.flushing: + return False + self.flushing = True + if cache := self.cache_stream.getvalue(): + self.flushing = True + self.cache_stream.close() + self.cache_stream = io.StringIO() + self.len = 0 + with open(file=self.file_conf.file_name, mode=self.file_conf.file_mode, + encoding=self.file_conf.file_encoding) as log_file: + log_file.write(cache) + self.flushing = False + return True - def flush(self) -> bool: - ... class LogFileCache: @@ -707,7 +718,7 @@ class Logger: if isinstance(value, dict): if 'strftime' in value: value['strftime']: str - formats[key] = f"{get_key_from_dict(self.colors[get_name_by_level(level)], key, self.colors[key])}{strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 5]))}{color_reset_suffix}" + formats[key] = f"{get_key_from_dict(self.colors[get_name_by_level(level)], key, self.colors[key])}{time.strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 5]))}{color_reset_suffix}" print_text = self.formats['MESSAGE']['format'].format(level_with_color=level_with_color, level=level_with_color, message=text, **formats) @@ -866,7 +877,7 @@ def format_str(text: str) -> str: if isinstance(value, dict): if 'strftime' in value: value['strftime']: str - formats[key] = strftime(value['strftime'].replace( + formats[key] = time.strftime(value['strftime'].replace( '%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 5])) return text.format(**formats) diff --git a/requirement.txt b/requirement.txt index 8376c0c..78a5747 100644 --- a/requirement.txt +++ b/requirement.txt @@ -4,6 +4,7 @@ objprint # selenium tomlkit +pymunk rtoml setuptools Cython