From 957b03be3137453b01210b38692c466eebf9d55e Mon Sep 17 00:00:00 2001 From: shenjack-mac <3695888@qq.com> Date: Sun, 14 May 2023 15:48:10 +0800 Subject: [PATCH 1/7] add Console_rs --- mods/dr_game/Difficult_Rocket_rs/__init__.py | 5 + .../Difficult_Rocket_rs/src/src/lib.rs | 1 + .../Difficult_Rocket_rs/src/src/python.rs | 55 ++++- .../Difficult_Rocket_rs/src/src/types.rs | 224 +++++++++--------- 4 files changed, 166 insertions(+), 119 deletions(-) diff --git a/mods/dr_game/Difficult_Rocket_rs/__init__.py b/mods/dr_game/Difficult_Rocket_rs/__init__.py index 8b601e1..f1d1832 100644 --- a/mods/dr_game/Difficult_Rocket_rs/__init__.py +++ b/mods/dr_game/Difficult_Rocket_rs/__init__.py @@ -101,3 +101,8 @@ if TYPE_CHECKING: @property def img_pos(self) -> Tuple[int, int, int, int]: ... """ -x -y +x +y 左下右上 """ + + class Console_rs: + def __init__(self) -> None: ... + def stop_console(self) -> None: ... + def get_command(self) -> Optional[str]: ... diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs index 4eef625..861fd2e 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs @@ -52,6 +52,7 @@ fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs index a543772..4564c46 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs @@ -12,7 +12,6 @@ pub mod data { use pyo3::prelude::*; use crate::sr1_data::part_list::RawPartList; - use crate::sr1_data::ship::RawShip; use crate::types::sr1::{get_max_box, SR1PartData, SR1PartListTrait}; use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship}; @@ -167,3 +166,57 @@ pub mod translate { } } } + +pub mod console { + use std::println; + + use pyo3::prelude::*; + + #[pyclass] + #[pyo3(name = "Console_rs")] + pub struct PyConsole { + /// 向子线程发送结束信号 + pub stop_sender: std::sync::mpsc::Sender<()>, + /// + pub keyboard_input_receiver: std::sync::mpsc::Receiver, + } + + #[pymethods] + impl PyConsole { + #[new] + fn new() -> Self { + let (stop_sender, stop_receiver) = std::sync::mpsc::channel(); + let (keyboard_input_sender, keyboard_input_receiver) = std::sync::mpsc::channel(); + std::thread::spawn(move || { + let std_in = std::io::stdin(); + loop { + if let Ok(()) = stop_receiver.try_recv() { + break; + } + let mut input = String::new(); + print!(">>"); + let _ = std_in.read_line(&mut input); + if !input.is_empty() { + keyboard_input_sender.send(input).unwrap(); + } + } + }); + + Self { + stop_sender, + keyboard_input_receiver, + } + } + + fn stop_console(&self) { self.stop_sender.send(()).unwrap(); } + + fn get_command(&self) -> Option { + // 获取输入 + if let Ok(string) = self.keyboard_input_receiver.try_recv() { + println!("rust recv input: {}", string); + return Some(string); + } + None + } + } +} diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs index 6bfe573..6348930 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs @@ -138,10 +138,10 @@ pub mod sr1 { impl Damage { pub fn to_raw_damage(&self) -> RawDamage { RawDamage { - disconnect: self.disconnect.to_owned(), - explode: self.explode.to_owned(), - explosion_power: Some(self.explosion_power.to_owned()), - explosion_size: Some(self.explosion_size.to_owned()), + disconnect: self.disconnect, + explode: self.explode, + explosion_power: Some(self.explosion_power), + explosion_size: Some(self.explosion_size), } } } @@ -225,10 +225,10 @@ pub mod sr1 { if cache.is_none() { let mut map = HashMap::new(); for part in self.types.iter() { - map.insert(part.id.to_owned(), part.to_owned()); + map.insert(part.id.clone(), part.clone()); } - *cache = Some(map); - self.cache.replace(cache.to_owned()); + *cache = Some(map.clone()); + self.cache.replace(cache.clone()); } cache.to_owned().unwrap() } @@ -237,7 +237,7 @@ pub mod sr1 { pub fn get_part_type(&self, type_name: String) -> Option { let cache = self.get_cache(); match cache.get(&type_name) { - Some(part) => Some(part.to_owned()), + Some(part) => Some(part.clone()), None => None, } } @@ -294,18 +294,18 @@ pub mod sr1 { fn to_raw_part_type(&self) -> RawPartType { let tank: Option = match &self.attr { - Some(attr) => match attr { + Some(attr) => match attr.to_owned() { SR1PartTypeAttr::Tank { fuel, dry_mass, fuel_type } => Some(Tank { - fuel: fuel.to_owned(), - dry_mass: dry_mass.to_owned(), - fuel_type: Some(fuel_type.to_owned()), + fuel, + dry_mass, + fuel_type: Some(fuel_type), }), _ => None, }, _ => None, }; let engine: Option = match &self.attr { - Some(attr) => match attr { + Some(attr) => match attr.to_owned() { SR1PartTypeAttr::Engine { power, consumption, @@ -314,39 +314,33 @@ pub mod sr1 { fuel_type, throttle_exponential, } => Some(Engine { - power: power.to_owned(), - consumption: consumption.to_owned(), - throttle_exponential: Some(throttle_exponential.to_owned()), - size: size.to_owned(), - turn: turn.to_owned(), - fuel_type: Some(fuel_type.to_owned()), + power, + consumption, + throttle_exponential: Some(throttle_exponential), + size, + turn, + fuel_type: Some(fuel_type), }), _ => None, }, _ => None, }; let rcs: Option = match &self.attr { - Some(attr) => match attr { - SR1PartTypeAttr::Rcs { power, consumption, size } => Some(Rcs { - power: power.to_owned(), - consumption: consumption.to_owned(), - size: size.to_owned(), - }), + Some(attr) => match attr.to_owned() { + SR1PartTypeAttr::Rcs { power, consumption, size } => Some(Rcs { power, consumption, size }), _ => None, }, _ => None, }; let solar: Option = match &self.attr { - Some(attr) => match attr { - SR1PartTypeAttr::Solar { charge_rate } => Some(Solar { - charge_rate: charge_rate.to_owned(), - }), + Some(attr) => match attr.to_owned() { + SR1PartTypeAttr::Solar { charge_rate } => Some(Solar { charge_rate }), _ => None, }, _ => None, }; let lander: Option = match &self.attr { - Some(attr) => match attr { + Some(attr) => match attr.to_owned() { SR1PartTypeAttr::Lander { max_angle, min_length, @@ -355,12 +349,12 @@ pub mod sr1 { length_speed, width, } => Some(Lander { - max_angle: max_angle.to_owned(), - min_length: min_length.to_owned(), - max_length: max_length.to_owned(), - angle_speed: Some(angle_speed.to_owned()), - length_speed: Some(length_speed.to_owned()), - width: width.to_owned(), + max_angle, + min_length, + max_length, + angle_speed: Some(angle_speed), + length_speed: Some(length_speed), + width, }), _ => None, }, @@ -382,19 +376,19 @@ pub mod sr1 { description: self.description.clone(), sprite: self.sprite.clone(), r#type: self.p_type.clone(), - mass: self.mass.to_owned(), - width: self.width.to_owned(), - height: self.height.to_owned(), - friction: Some(self.friction.to_owned()), + mass: self.mass, + width: self.width, + height: self.height, + friction: Some(self.friction), category: Some(self.category.clone()), - ignore_editor_intersections: Some(self.ignore_editor_intersections.to_owned()), - disable_editor_rotation: Some(self.disable_editor_rotation.to_owned()), - can_explode: Some(self.can_explode.to_owned()), - cover_height: Some(self.cover_height.to_owned()), - sandbox_only: Some(self.sandbox_only.to_owned()), - drag: Some(self.drag.to_owned()), - hidden: Some(self.hidden.to_owned()), - buoyancy: Some(self.buoyancy.to_owned()), + ignore_editor_intersections: Some(self.ignore_editor_intersections), + disable_editor_rotation: Some(self.disable_editor_rotation), + can_explode: Some(self.can_explode), + cover_height: Some(self.cover_height), + sandbox_only: Some(self.sandbox_only), + drag: Some(self.drag), + hidden: Some(self.hidden), + buoyancy: Some(self.buoyancy), damage: Some(self.damage.to_raw_damage()), tank, engine, @@ -422,36 +416,6 @@ pub mod sr1 { } else { (None, None) }; - // let pod = match &self.attr { - // SR1PartDataAttr::Pod { - // name, - // throttle, - // current_stage, - // steps, - // } => Some({ - // let mut actives = Vec::new(); - // for step in steps { - // let mut steps_ = Vec::new(); - // for active in step { - // steps_.push(RawActivate { - // id: active.0, - // moved: bool_to_i8(active.1), - // }); - // } - // actives.push(RawStep { activates: steps_ }); - // } - // let stages = RawStaging { - // current_stage: *current_stage, - // steps: actives, - // }; - // RawPod { - // name: name.clone(), - // throttle: *throttle, - // stages, - // } - // }), - // _ => None, - // }; let pod = match (&self.attr.name, &self.attr.throttle, &self.attr.current_stage, &self.attr.steps) { (Some(name), Some(throttle), Some(current_stage), Some(steps)) => Some({ let mut actives = Vec::new(); @@ -482,25 +446,25 @@ pub mod sr1 { engine, pod, part_type_id: self.part_type_id.clone(), - id: self.id.to_owned(), - x: self.x.to_owned(), - y: self.y.to_owned(), - editor_angle: self.editor_angle.to_owned(), - angle: self.angle.to_owned(), - angle_v: self.angle_v.to_owned(), - flip_x: Some(bool_to_i8(self.flip_x.to_owned())), - flip_y: Some(bool_to_i8(self.flip_y.to_owned())), - chute_x: self.attr.chute_x.to_owned(), - chute_y: self.attr.chute_y.to_owned(), - chute_height: self.attr.chute_height.to_owned(), - extension: self.attr.extension.to_owned(), - inflate: option_bool_to_option_i8(self.attr.inflate.to_owned()), - inflation: option_bool_to_option_i8(self.attr.inflation.to_owned()), - exploded: Some(bool_to_i8(self.explode.to_owned())), - rope: option_bool_to_option_i8(self.attr.rope.to_owned()), - chute_angle: self.attr.chute_angle.to_owned(), - activated: Some(bool_to_i8(self.active.to_owned())), - deployed: option_bool_to_option_i8(self.attr.deployed.to_owned()), + id: self.id, + x: self.x, + y: self.y, + editor_angle: self.editor_angle, + angle: self.angle, + angle_v: self.angle_v, + flip_x: Some(bool_to_i8(self.flip_x)), + flip_y: Some(bool_to_i8(self.flip_y)), + chute_x: self.attr.chute_x, + chute_y: self.attr.chute_y, + chute_height: self.attr.chute_height, + extension: self.attr.extension, + inflate: option_bool_to_option_i8(self.attr.inflate), + inflation: option_bool_to_option_i8(self.attr.inflation), + exploded: Some(bool_to_i8(self.explode)), + rope: option_bool_to_option_i8(self.attr.rope), + chute_angle: self.attr.chute_angle, + activated: Some(bool_to_i8(self.active)), + deployed: option_bool_to_option_i8(self.attr.deployed), } } } @@ -528,11 +492,11 @@ pub mod sr1 { impl SR1PartData { pub fn get_box(&self, part_type: &SR1PartType) -> (f64, f64, f64, f64) { - let width = part_type.width.to_owned(); - let height = part_type.height.to_owned(); - let radius = self.angle.to_owned(); + let width = part_type.width; + let height = part_type.height; + let radius = self.angle; let mut shape = Shape::new_width_height(width as f64, height as f64, Some(radius)); - shape.move_xy(Some(self.x.to_owned()), Some(self.y.to_owned())); + shape.move_xy(Some(self.x), Some(self.y)); let mut pos_box = (0_f64, 0_f64, 0_f64, 0_f64); match shape.bounds[0] { Edge::OneTimeLine(line) => { @@ -652,15 +616,15 @@ pub mod sr1 { }; let (name, throttle, current_stage, steps) = if let Some(pod) = &raw_data.pod { ( - Some(pod.name.to_owned()), - Some(pod.throttle.to_owned()), - Some(pod.stages.current_stage.to_owned()), + Some(pod.name.clone()), + Some(pod.throttle), + Some(pod.stages.current_stage), Some({ let mut steps = Vec::new(); for step in &pod.stages.steps { let mut step_vec = Vec::new(); for act in &step.activates { - step_vec.push((act.id.to_owned(), i8_to_bool(act.moved.to_owned()))); + step_vec.push((act.id, i8_to_bool(act.moved))); } steps.push(step_vec); } @@ -676,15 +640,15 @@ pub mod sr1 { throttle, current_stage, steps, - extension: raw_data.extension.to_owned(), - chute_x: raw_data.chute_x.to_owned(), - chute_y: raw_data.chute_y.to_owned(), - chute_height: raw_data.chute_height.to_owned(), - chute_angle: raw_data.chute_angle.to_owned(), - inflate: option_i8_to_option_bool(raw_data.inflate.to_owned()), - inflation: option_i8_to_option_bool(raw_data.inflation.to_owned()), - deployed: option_i8_to_option_bool(raw_data.deployed.to_owned()), - rope: option_i8_to_option_bool(raw_data.rope.to_owned()), + extension: raw_data.extension, + chute_x: raw_data.chute_x, + chute_y: raw_data.chute_y, + chute_height: raw_data.chute_height, + chute_angle: raw_data.chute_angle, + inflate: option_i8_to_option_bool(raw_data.inflate), + inflation: option_i8_to_option_bool(raw_data.inflation), + deployed: option_i8_to_option_bool(raw_data.deployed), + rope: option_i8_to_option_bool(raw_data.rope), part_type: Cell::new(part_type), }; if guess & results.part_type.get().is_none() { @@ -715,6 +679,30 @@ pub mod sr1 { let ship: RawShip = RawShip::from_file(file_name).unwrap(); Some(ship.to_sr_ship(ship_name)) } + + pub fn parse_part_list_to_part(&mut self, part_list: SR1PartList) { + // parse parts + for part in self.parts.iter_mut() { + let part_type_id = part.part_type_id.clone(); + if let Some(part_type) = part_list.get_part_type(part_type_id) { + part.part_type = part_type.p_type; + } else { + part.part_type = SR1PartTypeEnum::strut; + } + } + for disconnects in self.disconnected.iter_mut() { + for (parts, _) in disconnects.iter_mut() { + for part in parts.iter_mut() { + let part_type_id = part.part_type_id.clone(); + if let Some(part_type) = part_list.get_part_type(part_type_id) { + part.part_type = part_type.p_type; + } else { + part.part_type = SR1PartTypeEnum::strut; + } + } + } + } + } } impl SR1ShipTrait for SR1Ship { @@ -761,8 +749,8 @@ pub mod sr1 { parts: RawParts { parts }, connects: connections, version: 1, - lift_off: bool_to_i8(self.lift_off.to_owned()), - touch_ground: bool_to_i8(self.touch_ground.to_owned()), + lift_off: bool_to_i8(self.lift_off), + touch_ground: bool_to_i8(self.touch_ground), disconnected, } } @@ -800,8 +788,8 @@ pub mod math { #[inline] pub fn distance(&self, other: &Point2D) -> f64 { - let dx = (other.x.to_owned() - self.x.to_owned()).powf(2.0); - let dy = (other.y.to_owned() - self.y.to_owned()).powf(2.0); + let dx = (other.x - self.x).powf(2.0); + let dy = (other.y - self.y).powf(2.0); (dx + dy).powf(0.5) } From 6ee9d6293750e27ebf68d28a64e5caf9726427a6 Mon Sep 17 00:00:00 2001 From: shenjack-mac <3695888@qq.com> Date: Sun, 14 May 2023 15:49:27 +0800 Subject: [PATCH 2/7] use mod console --- Difficult_Rocket/client/__init__.py | 8 ++++++-- mods/dr_game/sr1_ship.py | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Difficult_Rocket/client/__init__.py b/Difficult_Rocket/client/__init__.py index 14568ae..259438b 100644 --- a/Difficult_Rocket/client/__init__.py +++ b/Difficult_Rocket/client/__init__.py @@ -211,7 +211,7 @@ class ClientWindow(Window): def start_game(self) -> None: self.set_icon(pyglet.image.load('./textures/icon.png')) self.run_input = True - self.read_input() + # self.read_input() try: pyglet.app.event_loop.run(1 / self.main_config['runtime']['fps']) except KeyboardInterrupt: @@ -314,6 +314,7 @@ class ClientWindow(Window): self.logger.info(tr().window.command.text().format(command)) if command.re_match('stop'): # self.dispatch_event('on_exit') + print("command stop!") pyglet.app.platform_event_loop.stop() self.dispatch_event('on_close', 'command') # source = command elif command.re_match('fps'): @@ -439,10 +440,13 @@ class ClientWindow(Window): self.game.dispatch_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 + # self.fps_log.check_list = False DR_runtime.running = False if self.run_input: self.run_input = False self.save_info() super().on_close() self.logger.info(tr().window.game.end()) + + +ClientWindow.register_event_type("on_command") diff --git a/mods/dr_game/sr1_ship.py b/mods/dr_game/sr1_ship.py index 6a46b49..454d2bf 100644 --- a/mods/dr_game/sr1_ship.py +++ b/mods/dr_game/sr1_ship.py @@ -36,7 +36,7 @@ if TYPE_CHECKING: from Difficult_Rocket.client import ClientWindow if DR_mod_runtime.use_DR_rust: - from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs + from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs, Console_rs logger = logging.getLogger('client') @@ -135,6 +135,7 @@ class SR1ShipRender(BaseScreen): min_zoom=(1 / 2) ** 10, max_zoom=10) self.rust_parts = None self.part_list_rs = SR1PartList_rs('configs/PartList.xml', 'default_part_list') + self.console = Console_rs() def load_xml(self, file_path: str) -> bool: try: @@ -270,6 +271,11 @@ class SR1ShipRender(BaseScreen): self.debug_mouse_label.draw() if SR1ShipRender_Option.debug_mouse_d_pos: self.debug_mouse_delta_line.draw() + if DR_mod_runtime.use_DR_rust: + read_input = self.console.get_command() + if read_input: + print(f"Rust console: |{read_input}|") + window.dispatch_event("on_command", CommandText(read_input)) def on_resize(self, width: int, height: int, window: "ClientWindow"): if not self.rendered: @@ -381,6 +387,9 @@ class SR1ShipRender(BaseScreen): if self.load_xml(path): # 加载成功一个就停下 break self.render_ship() + + def on_close(self, window: "ClientWindow"): + self.console.stop_console() if __name__ == '__main__': From c9e109fdb540c69f7b493ec34415b425e0db3ea9 Mon Sep 17 00:00:00 2001 From: shenjack-mac <3695888@qq.com> Date: Sun, 14 May 2023 18:44:25 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=88=91=E4=B9=9F=E4=B8=8D=E6=B8=85?= =?UTF-8?q?=E6=A5=9A=E6=94=B9=E4=BA=86=E5=95=A5=EF=BC=8C=E4=BD=86=E6=98=AF?= =?UTF-8?q?=E5=8F=8D=E6=AD=A3=E6=88=91=E4=B8=8D=E7=AE=A1=EF=BC=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Difficult_Rocket/main.py | 128 +++++++++++++++++- mods/dr_game/Difficult_Rocket_rs/__init__.py | 3 +- .../Difficult_Rocket_rs/src/src/python.rs | 36 +++-- mods/dr_game/__init__.py | 11 +- mods/dr_game/console.py | 24 ++++ 5 files changed, 183 insertions(+), 19 deletions(-) create mode 100644 mods/dr_game/console.py diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index 1318e7b..50ca58d 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -22,7 +22,7 @@ import multiprocessing from io import StringIO from pathlib import Path -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, List, Optional, Dict, TypeVar if __name__ == '__main__': # been start will not run this sys.path.append('/bin/libs') @@ -31,9 +31,13 @@ if __name__ == '__main__': # been start will not run this from Difficult_Rocket import client, server, DR_option, DR_runtime if TYPE_CHECKING: from Difficult_Rocket.api.mod import ModInfo -from Difficult_Rocket.crash import write_info_to_cache +else: + ModInfo = TypeVar('ModInfo') from Difficult_Rocket.utils import tools from Difficult_Rocket.utils.translate import tr +from Difficult_Rocket.crash import write_info_to_cache +from Difficult_Rocket.api.types import Options +from Difficult_Rocket.utils.thread import new_thread class Game: @@ -114,7 +118,7 @@ class Game: 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().format(mod, e)) + self.logger.warning(tr().main.mod.load.faild.info().format(mod, e)) self.logger.info(tr().main.mod.load.done()) self.loaded_mods = module mod_list = [] @@ -163,3 +167,121 @@ class Game: def start(self) -> None: self._start() + + +class Console(Options): + name = 'python stdin console' + + running: bool = False + + @new_thread('python console', daemon=True, log_thread=True) + def main(self): + while self.running: + try: + get_str = input('>>>') + except (EOFError, KeyboardInterrupt): + get_str = 'stop' + self.caches.append(get_str) + if get_str == 'stop': + self.running = False + break + + def start(self): + self.running = True + self.caches: List[str] = [] + self.main() + + def stop(self): + self.running = False + + def get_command(self) -> str: + return self.caches.pop(0) + + +class MainGame(Options): + name = 'MainGame' + + client: client.Client + server: server.Server + console: Console + + main_config: Dict + logger: logging.Logger + + mod_module: List["ModInfo"] + + def init_logger(self) -> None: + ... + + def init_console(self) -> None: + self.console = Console() + self.console.start() + + def init_mods(self) -> None: + """验证/加载 mod""" + 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 + + 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 as e: + self.logger.error(tr().main.mod.event.error().format(event_name, e, mod.mod_id)) + + def init(self, **kwargs) -> None: + ... + + def load_file(self) -> bool: + """加载文件""" + self.init_logger() + self.init_mods() + return True diff --git a/mods/dr_game/Difficult_Rocket_rs/__init__.py b/mods/dr_game/Difficult_Rocket_rs/__init__.py index f1d1832..94c6dd5 100644 --- a/mods/dr_game/Difficult_Rocket_rs/__init__.py +++ b/mods/dr_game/Difficult_Rocket_rs/__init__.py @@ -104,5 +104,6 @@ if TYPE_CHECKING: class Console_rs: def __init__(self) -> None: ... - def stop_console(self) -> None: ... + def start(self) -> None: ... + def stop(self) -> bool: ... def get_command(self) -> Optional[str]: ... diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs index 4564c46..56494b8 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs @@ -176,15 +176,21 @@ pub mod console { #[pyo3(name = "Console_rs")] pub struct PyConsole { /// 向子线程发送结束信号 - pub stop_sender: std::sync::mpsc::Sender<()>, - /// - pub keyboard_input_receiver: std::sync::mpsc::Receiver, + pub stop_sender: Option>, + pub keyboard_input_receiver: Option>, } #[pymethods] impl PyConsole { #[new] fn new() -> Self { + Self { + stop_sender: None, + keyboard_input_receiver: None, + } + } + + fn start(&mut self) { let (stop_sender, stop_receiver) = std::sync::mpsc::channel(); let (keyboard_input_sender, keyboard_input_receiver) = std::sync::mpsc::channel(); std::thread::spawn(move || { @@ -194,27 +200,31 @@ pub mod console { break; } let mut input = String::new(); - print!(">>"); let _ = std_in.read_line(&mut input); if !input.is_empty() { keyboard_input_sender.send(input).unwrap(); } + print!(">>"); } }); - - Self { - stop_sender, - keyboard_input_receiver, - } + self.stop_sender = Some(stop_sender); + self.keyboard_input_receiver = Some(keyboard_input_receiver); } - fn stop_console(&self) { self.stop_sender.send(()).unwrap(); } + fn stop(&self) -> bool { + if let (Some(sender)) = &self.stop_sender { + sender.send(()).unwrap(); + return true; + } + false + } fn get_command(&self) -> Option { // 获取输入 - if let Ok(string) = self.keyboard_input_receiver.try_recv() { - println!("rust recv input: {}", string); - return Some(string); + if let (Some(receiver)) = &self.keyboard_input_receiver { + if let Ok(string) = receiver.try_recv() { + return Some(string); + } } None } diff --git a/mods/dr_game/__init__.py b/mods/dr_game/__init__.py index 79ab6f6..19ad067 100644 --- a/mods/dr_game/__init__.py +++ b/mods/dr_game/__init__.py @@ -9,9 +9,8 @@ import traceback from typing import Optional - from libs.MCDR.version import Version -from Difficult_Rocket.main import Game +from Difficult_Rocket.main import Game, Console from Difficult_Rocket.api.mod import ModInfo from Difficult_Rocket.api.types import Options from Difficult_Rocket.client import ClientWindow @@ -68,6 +67,14 @@ class DR_mod(ModInfo): def on_load(self, game: Game, old_self: Optional["DR_mod"] = None) -> bool: if not DR_mod_runtime.DR_rust_available: return False + from .console import RustConsole + + def init_console(self) -> None: + self.console = RustConsole() + self.console.start() + + game.init_console = init_console # 替换掉原来的 init_console 函数 + if old_self: game.client.window.add_sub_screen("SR1_ship", old_self.screen) else: diff --git a/mods/dr_game/console.py b/mods/dr_game/console.py new file mode 100644 index 0000000..62f88f8 --- /dev/null +++ b/mods/dr_game/console.py @@ -0,0 +1,24 @@ +from . import DR_mod_runtime +from Difficult_Rocket.main import Console + +if DR_mod_runtime.use_DR_rust: + from .Difficult_Rocket_rs import Console_rs + + +class RustConsole(Console): + name = 'Rust stdin Console' + + running: bool = False + console: Console_rs + + def start(self): + self.console.start() + + def stop(self): + return self.console.stop() + + def init(self, **kwargs) -> None: + self.console = Console_rs() + + def get_command(self) -> str: + return self.console.get_command() From 4f0ec98879633d61cb9bae68966596668c8c2c62 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sun, 14 May 2023 20:23:20 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E5=AE=8C=E5=96=84=20MainGame?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Difficult_Rocket/__init__.py | 1 + Difficult_Rocket/main.py | 47 +++++++++++++++---- Difficult_Rocket/utils/options.py | 11 +++-- configs/logger.toml | 1 - .../Difficult_Rocket_rs/src/src/lib.rs | 12 ++--- .../Difficult_Rocket_rs/src/src/python.rs | 4 +- mods/dr_game/__init__.py | 2 +- 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/Difficult_Rocket/__init__.py b/Difficult_Rocket/__init__.py index f654bda..fefefe9 100644 --- a/Difficult_Rocket/__init__.py +++ b/Difficult_Rocket/__init__.py @@ -5,6 +5,7 @@ # ------------------------------- import sys +import time import importlib import traceback import contextlib diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index 50ca58d..77081c0 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -15,6 +15,7 @@ import os import sys import time import logging +import traceback import importlib import importlib.util import logging.config @@ -28,16 +29,16 @@ if __name__ == '__main__': # been start will not run this sys.path.append('/bin/libs') sys.path.append('/bin') -from Difficult_Rocket import client, server, DR_option, DR_runtime if TYPE_CHECKING: from Difficult_Rocket.api.mod import ModInfo else: ModInfo = TypeVar('ModInfo') from Difficult_Rocket.utils import tools -from Difficult_Rocket.utils.translate import tr -from Difficult_Rocket.crash import write_info_to_cache from Difficult_Rocket.api.types import Options +from Difficult_Rocket.utils.translate import tr from Difficult_Rocket.utils.thread import new_thread +from Difficult_Rocket.crash import write_info_to_cache +from Difficult_Rocket import client, server, DR_option, DR_runtime class Game: @@ -206,12 +207,23 @@ class MainGame(Options): console: Console main_config: Dict + logging_config: Dict logger: logging.Logger mod_module: List["ModInfo"] def init_logger(self) -> None: - ... + log_path = self.logging_config['handlers']['file']['filename'] + log_path = Path(f"logs/{log_path.format(time.strftime('%Y-%m-%d %H-%M-%S' , time.gmtime(DR_runtime.start_time_ns)))}") + mkdir = False + if not log_path.exists(): + log_path.mkdir(parents=True) + mkdir = True + self.logging_config['handlers']['file']['filename'] = log_path.name + logging.config.dictConfig(self.logging_config) + self.logger = logging.getLogger('main') + if mkdir: + self.logger.info(tr().main.logger.mkdir()) def init_console(self) -> None: self.console = Console() @@ -274,14 +286,33 @@ class MainGame(Options): if hasattr(mod, event_name): try: getattr(mod, event_name)(*args, **kwargs) - except Exception as e: - self.logger.error(tr().main.mod.event.error().format(event_name, e, mod.mod_id)) + except Exception: + error = traceback.format_exc() + self.logger.error(tr().main.mod.event.error().format(event_name, error, mod.mod_id)) - def init(self, **kwargs) -> None: - ... + 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() + self.logger.info(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.load_file() + self.setup() + self.log_env() + return True 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 + diff --git a/Difficult_Rocket/utils/options.py b/Difficult_Rocket/utils/options.py index b8586e9..8ec927b 100644 --- a/Difficult_Rocket/utils/options.py +++ b/Difficult_Rocket/utils/options.py @@ -66,9 +66,10 @@ class Options: if option not in self.cached_options: raise OptionNameNotDefined(f"option: {option} with value: {value} is not defined") setattr(self, option, value) + run_load_file = True if hasattr(self, 'init'): - self.init(**kwargs) - if hasattr(self, 'load_file'): + run_load_file = not self.init(**kwargs) # 默认 False/None + if hasattr(self, 'load_file') and run_load_file: try: self.load_file() except Exception: @@ -78,8 +79,10 @@ class Options: if TYPE_CHECKING: _options: Dict[str, Union[Callable, object]] = {} - def init(self, **kwargs) -> None: - """ 如果子类定义了这个函数,则会在 __init__ 之后调用这个函数 """ + def init(self, **kwargs) -> bool: + """ 如果子类定义了这个函数,则会在 __init__ 之后调用这个函数 + 返回值为 True 则不会调用 load_file 函数 + """ def load_file(self) -> bool: """如果子类定义了这个函数,则会在 __init__ 和 init 之后再调用这个函数 diff --git a/configs/logger.toml b/configs/logger.toml index 927a7cd..5a65de0 100644 --- a/configs/logger.toml +++ b/configs/logger.toml @@ -27,7 +27,6 @@ level = "DEBUG" [handlers.file] class = "logging.FileHandler" filename = "{} DR.log" -datefmt = "%Y-%m-%d %H:%M:%S" encoding = "utf-8" formatter = "file" level = "DEBUG" diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs index 861fd2e..c40b0b5 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs @@ -19,15 +19,15 @@ use pyo3::prelude::*; // const MOD_PATH: String = String::from("mods"); enum LoadState { - init, - wait_start, - pre_start, - running, - clean, + Init, + WaitStart, + PreStart, + Running, + Clean, } #[pyfunction] -fn get_version_str() -> String { "0.2.7.0".to_string() } +fn get_version_str() -> String { "0.2.8.0".to_string() } #[pyfunction] fn test_call(py_obj: &PyAny) -> PyResult { diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs index 56494b8..32cccc2 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs @@ -212,7 +212,7 @@ pub mod console { } fn stop(&self) -> bool { - if let (Some(sender)) = &self.stop_sender { + if let Some(sender) = &self.stop_sender { sender.send(()).unwrap(); return true; } @@ -221,7 +221,7 @@ pub mod console { fn get_command(&self) -> Option { // 获取输入 - if let (Some(receiver)) = &self.keyboard_input_receiver { + if let Some(receiver) = &self.keyboard_input_receiver { if let Ok(string) = receiver.try_recv() { return Some(string); } diff --git a/mods/dr_game/__init__.py b/mods/dr_game/__init__.py index 19ad067..48fee02 100644 --- a/mods/dr_game/__init__.py +++ b/mods/dr_game/__init__.py @@ -15,7 +15,7 @@ from Difficult_Rocket.api.mod import ModInfo from Difficult_Rocket.api.types import Options from Difficult_Rocket.client import ClientWindow -DR_rust_version = Version("0.2.7.0") # DR_mod 的 Rust 编写部分的兼容版本 +DR_rust_version = Version("0.2.8.0") # DR_mod 的 Rust 编写部分的兼容版本 class _DR_mod_runtime(Options): From ad19ef1e28199bbc2a1c89b70104dd303ea44cf5 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sun, 14 May 2023 20:42:18 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E9=87=8D=E6=9E=84=20Game=20obj?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Difficult_Rocket/main.py | 167 +++--------------- Difficult_Rocket/utils/options.py | 3 +- .../Difficult_Rocket_rs/src/src/lib.rs | 1 + mods/dr_game/__init__.py | 6 +- mods/dr_game/sr1_ship.py | 11 +- 5 files changed, 33 insertions(+), 155 deletions(-) diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index 77081c0..7f86288 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -11,7 +11,6 @@ github: @shenjackyuanjie gitee: @shenjackyuanjie """ -import os import sys import time import logging @@ -41,135 +40,6 @@ from Difficult_Rocket.crash import write_info_to_cache from Difficult_Rocket import client, server, DR_option, DR_runtime -class Game: - def __init__(self): - # basic config - self.on_python_v_info = sys.version_info - self.on_python_v = sys.version.split(' ')[0] - self.start_time = time.strftime('%Y-%m-%d %H-%M-%S', time.gmtime(time.time())) - # lang_config - self.language = tools.load_file('configs/main.toml', 'runtime')['language'] - DR_option.language = self.language - # logging config - log_config = tools.load_file('configs/logger.toml') - file_name = log_config['handlers']['file']['filename'] - del log_config['handlers']['file']['datefmt'] - log_config['handlers']['file']['filename'] = f'logs/{file_name.format(self.start_time)}' - try: - logging.config.dictConfig(log_config) - self.logger = logging.getLogger('main') - except ValueError: # it should be no 'logs/' folder - os.mkdir('logs') - logging.config.dictConfig(log_config) - self.logger = logging.getLogger('main') - self.logger.info(tr().main.logger.mkdir()) - self.logger.info(tr().language_set_to()) - self.logger.info(tr().main.logger.created()) - # version check - self.log_env() - self.python_version_check() - self.loaded_mods = [] - # self.client = client.Client - # self.server = server.Server - self.setup() - - def log_env(self) -> None: - cache_steam = StringIO() - write_info_to_cache(cache_steam) - text = cache_steam.getvalue() - self.logger.info(text) - - def load_mods(self) -> None: - 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.loaded_mods = 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 dispatch_event(self, event_name: str, *args, **kwargs) -> None: - for mod in self.loaded_mods: - if hasattr(mod, event_name): - try: - getattr(mod, event_name)(*args, **kwargs) - except Exception as e: - self.logger.error(tr().main.mod.event.error().format(event_name, e, mod.mod_id)) - - def setup(self) -> None: - self.load_mods() - self.client = client.Client(game=self, net_mode='local') - 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(f"{tr().main.version.now_on()} {self.on_python_v}") - if self.on_python_v_info[0] == 2: - self.logger.critical(tr().main.version.need3p()) - raise SystemError(tr().main.version.need3p()) - elif self.on_python_v_info[1] < 8: - warning = tools.name_handler(tr.main.version.best38p()) - self.logger.warning(warning) - - # @new_thread('main') - def _start(self): - self.server.run() - if DR_option.use_multiprocess: - try: - game_process = multiprocessing.Process(target=self.client.start, name='pyglet app') - game_process.start() - game_process.join() - except Exception: - return -1 - else: - return 1 - else: - self.client.start() - - def start(self) -> None: - self._start() - - class Console(Options): name = 'python stdin console' @@ -199,12 +69,13 @@ class Console(Options): return self.caches.pop(0) -class MainGame(Options): +class Game(Options): name = 'MainGame' client: client.Client server: server.Server console: Console + console_class: Console = Console main_config: Dict logging_config: Dict @@ -214,23 +85,20 @@ class MainGame(Options): def init_logger(self) -> None: log_path = self.logging_config['handlers']['file']['filename'] - log_path = Path(f"logs/{log_path.format(time.strftime('%Y-%m-%d %H-%M-%S' , time.gmtime(DR_runtime.start_time_ns)))}") + log_path = 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 log_path.exists(): + if not Path("logs/").exists(): log_path.mkdir(parents=True) mkdir = True - self.logging_config['handlers']['file']['filename'] = log_path.name + self.logging_config['handlers']['file']['filename'] = str(log_path.absolute()) logging.config.dictConfig(self.logging_config) self.logger = logging.getLogger('main') if mkdir: self.logger.info(tr().main.logger.mkdir()) - def init_console(self) -> None: - self.console = Console() - self.console.start() - def init_mods(self) -> None: """验证/加载 mod""" + print(self) mods = [] mod_path = Path(DR_runtime.mod_path) if not mod_path.exists(): @@ -280,6 +148,24 @@ class MainGame(Options): self.dispatch_event('on_load', game=self) DR_runtime.DR_Mod_List = mod_list + def init_console(self) -> None: + self.console = Console() + self.console.start() + + def start(self): + self.server.run() + if DR_option.use_multiprocess: + try: + game_process = multiprocessing.Process(target=self.client.start, name='pyglet app') + game_process.start() + game_process.join() + except Exception: + return -1 + else: + return 1 + else: + self.client.start() + def dispatch_event(self, event_name: str, *args, **kwargs) -> None: """向 mod 分发事件""" for mod in self.mod_module: @@ -296,7 +182,10 @@ class MainGame(Options): text = cache_steam.getvalue() self.logger.info(text) self.flush_option() - self.logger.info(self.as_markdown()) + 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: self.client = client.Client(game=self, net_mode='local') diff --git a/Difficult_Rocket/utils/options.py b/Difficult_Rocket/utils/options.py index 8ec927b..1be17c2 100644 --- a/Difficult_Rocket/utils/options.py +++ b/Difficult_Rocket/utils/options.py @@ -68,7 +68,8 @@ class Options: setattr(self, option, value) run_load_file = True if hasattr(self, 'init'): - run_load_file = not self.init(**kwargs) # 默认 False/None + run_load_file = self.init(**kwargs) # 默认 False/None + run_load_file = not run_load_file if hasattr(self, 'load_file') and run_load_file: try: self.load_file() diff --git a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs index c40b0b5..97c570f 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs @@ -18,6 +18,7 @@ use pyo3::prelude::*; // const MOD_PATH: String = String::from("mods"); +#[allow(unused)] enum LoadState { Init, WaitStart, diff --git a/mods/dr_game/__init__.py b/mods/dr_game/__init__.py index 48fee02..712c039 100644 --- a/mods/dr_game/__init__.py +++ b/mods/dr_game/__init__.py @@ -69,11 +69,7 @@ class DR_mod(ModInfo): return False from .console import RustConsole - def init_console(self) -> None: - self.console = RustConsole() - self.console.start() - - game.init_console = init_console # 替换掉原来的 init_console 函数 + game.console_class = RustConsole # 替换掉原来的 console 类 if old_self: game.client.window.add_sub_screen("SR1_ship", old_self.screen) diff --git a/mods/dr_game/sr1_ship.py b/mods/dr_game/sr1_ship.py index 454d2bf..6a46b49 100644 --- a/mods/dr_game/sr1_ship.py +++ b/mods/dr_game/sr1_ship.py @@ -36,7 +36,7 @@ if TYPE_CHECKING: from Difficult_Rocket.client import ClientWindow if DR_mod_runtime.use_DR_rust: - from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs, Console_rs + from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs logger = logging.getLogger('client') @@ -135,7 +135,6 @@ class SR1ShipRender(BaseScreen): min_zoom=(1 / 2) ** 10, max_zoom=10) self.rust_parts = None self.part_list_rs = SR1PartList_rs('configs/PartList.xml', 'default_part_list') - self.console = Console_rs() def load_xml(self, file_path: str) -> bool: try: @@ -271,11 +270,6 @@ class SR1ShipRender(BaseScreen): self.debug_mouse_label.draw() if SR1ShipRender_Option.debug_mouse_d_pos: self.debug_mouse_delta_line.draw() - if DR_mod_runtime.use_DR_rust: - read_input = self.console.get_command() - if read_input: - print(f"Rust console: |{read_input}|") - window.dispatch_event("on_command", CommandText(read_input)) def on_resize(self, width: int, height: int, window: "ClientWindow"): if not self.rendered: @@ -387,9 +381,6 @@ class SR1ShipRender(BaseScreen): if self.load_xml(path): # 加载成功一个就停下 break self.render_ship() - - def on_close(self, window: "ClientWindow"): - self.console.stop_console() if __name__ == '__main__': From 6f5b87a2ce5fe73d1486ebc485a98d5f330a60f5 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sun, 14 May 2023 20:56:19 +0800 Subject: [PATCH 6/7] Add CommandText.find --- Difficult_Rocket/client/__init__.py | 40 ++++++++--------------------- Difficult_Rocket/command/api.py | 9 ++++++- Difficult_Rocket/main.py | 2 +- docs/src/update_logs.md | 11 ++++++++ 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/Difficult_Rocket/client/__init__.py b/Difficult_Rocket/client/__init__.py index 259438b..16a28d2 100644 --- a/Difficult_Rocket/client/__init__.py +++ b/Difficult_Rocket/client/__init__.py @@ -210,8 +210,6 @@ class ClientWindow(Window): def start_game(self) -> None: self.set_icon(pyglet.image.load('./textures/icon.png')) - self.run_input = True - # self.read_input() try: pyglet.app.event_loop.run(1 / self.main_config['runtime']['fps']) except KeyboardInterrupt: @@ -221,22 +219,6 @@ class ClientWindow(Window): self.dispatch_event("on_close") sys.exit(0) - @new_thread('window read_input', daemon=True) - def read_input(self): - self.logger.debug('read_input start') - while self.run_input: - try: - get = input(">") - except (EOFError, KeyboardInterrupt): - self.run_input = False - break - if get in ('', ' ', '\n', '\r'): - continue - if get == 'stop': - self.run_input = False - self.command_list.append(get) - self.logger.debug('read_input end') - @new_thread('window save_info') def save_info(self): self.logger.info(tr().client.config.save.start()) @@ -266,10 +248,8 @@ class ClientWindow(Window): @_call_screen_after def on_draw(self, *dt): - if self.command_list: - for command in self.command_list: - self.on_command(line.CommandText(command)) - self.command_list.pop(0) + while command := self.game.console.get_command(): + self.on_command(line.CommandText(command)) pyglet.gl.glClearColor(0.1, 0, 0, 0.0) self.clear() self.draw_update(float(self.SPF)) @@ -310,26 +290,26 @@ class ClientWindow(Window): @_call_screen_after def on_command(self, command: line.CommandText): - print(command.re_match('/')) + print(command.find('/')) self.logger.info(tr().window.command.text().format(command)) - if command.re_match('stop'): + if command.find('stop'): # self.dispatch_event('on_exit') print("command stop!") pyglet.app.platform_event_loop.stop() self.dispatch_event('on_close', 'command') # source = command - elif command.re_match('fps'): - if command.re_match('log'): + elif command.find('fps'): + if command.find('log'): self.logger.debug(self.fps_log.fps_list) - elif command.re_match('max'): + elif command.find('max'): self.logger.info(self.fps_log.max_fps) self.command.push_line(self.fps_log.max_fps, block_line=True) - elif command.re_match('min'): + elif command.find('min'): self.logger.info(self.fps_log.min_fps) self.command.push_line(self.fps_log.min_fps, block_line=True) - elif command.re_match('default'): + elif command.find('default'): self.set_size(int(self.main_config['window_default']['width']), int(self.main_config['window_default']['height'])) - elif command.re_match('lang'): + elif command.find('lang'): try: lang = command.text[5:] tr._language = lang diff --git a/Difficult_Rocket/command/api.py b/Difficult_Rocket/command/api.py index 0ddbf27..b9b770a 100644 --- a/Difficult_Rocket/command/api.py +++ b/Difficult_Rocket/command/api.py @@ -43,7 +43,14 @@ class CommandText: break i += 1 - def find(self, text: str) -> Union[str, bool]: + def find(self, text: str) -> bool: + find = self.text.find(text) + if find != -1: + self.text = self.text[find + len(text):] + return True + return False + + def re_find(self, text: str) -> Union[str, bool]: return finding.group() if (finding := re.match(text, self.text)) else False def re_match(self, text: str) -> bool: diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index 7f86288..383117c 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -149,7 +149,7 @@ class Game(Options): DR_runtime.DR_Mod_List = mod_list def init_console(self) -> None: - self.console = Console() + self.console = self.console_class() self.console.start() def start(self): diff --git a/docs/src/update_logs.md b/docs/src/update_logs.md index f299b20..c41eab8 100644 --- a/docs/src/update_logs.md +++ b/docs/src/update_logs.md @@ -114,6 +114,13 @@ - 修改 返回值 类型+类型注释 - Modify the return value type + type annotation - `List[Union[List[Tuple[str, Any, Any]], int, Any]]:` -> `Tuple[List[Tuple[str, Union[Any, Type], Type]], int, int, int]` +- `Difficult_Roocket.main.Game` + - 使用 `Options` 完全重构 + - 分离 `init mods` `init console` `init logger` `load_file` + - Completely refactored using `Options` + - Separate `init mods` `init console` `init logger` `load_file` +- `Difficult_Rocket.command.api.CommandText` + - `find` -> `re_find` ### Add @@ -122,6 +129,10 @@ - 用于方便的用人类可读的 Markdown 格式 直接输出一个已经实例化的 `Options` 类的所有字段 - Add `as_markdown` method - Used to easily output all fields of an instantiated `Options` class in a human-readable Markdown format +- `Difficult_Rocket.command.api.CommandText` + - 添加基于 `str.find` 的 `find(text: str) -> bool` 方法 + - Add method `find(text: str)` based on `str.find` + ### Docs From 5ed49ef45b0d76938f33aa77ff16ee2bf6ff0b88 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sun, 14 May 2023 20:59:04 +0800 Subject: [PATCH 7/7] docs update [build skip] [build rs skip] --- docs/src/update_logs.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/src/update_logs.md b/docs/src/update_logs.md index c41eab8..3725763 100644 --- a/docs/src/update_logs.md +++ b/docs/src/update_logs.md @@ -59,6 +59,9 @@ - `get_box(&self, part_type: &SR1PartType) -> (f64, f64, f64, f64)` - `types::SR1Ship` - `from_file` +- 添加了 `Console_rs` + - 用于使用 Rust 多线程读取 stdin + - Use Rust mutithread to read stdin ### Remove