diff --git a/Difficult_Rocket/__init__.py b/Difficult_Rocket/__init__.py index df1e4cd..5aadb0a 100644 --- a/Difficult_Rocket/__init__.py +++ b/Difficult_Rocket/__init__.py @@ -20,7 +20,7 @@ from libs.MCDR.version import Version game_version = Version("0.7.2.2") # 游戏版本 build_version = Version("1.2.1.0") # 编译文件版本(与游戏本体无关) -Api_version = Version("0.0.2.0") # API 版本 +Api_version = Version("0.1.0.0") # API 版本 __version__ = game_version long_version: int = 15 diff --git a/Difficult_Rocket/api/mod/__init__.py b/Difficult_Rocket/api/mod/__init__.py index 0b6d945..933fb66 100644 --- a/Difficult_Rocket/api/mod/__init__.py +++ b/Difficult_Rocket/api/mod/__init__.py @@ -17,15 +17,10 @@ if TYPE_CHECKING: else: Game = TypeVar("Game") ClientWindow = TypeVar("ClientWindow") + from Difficult_Rocket import DR_runtime from ..types import Options - -""" -加载mod时会更改的参数 -这里的只是范例,实际加载时会根据mod配置修改 -""" - RequireVersion = Tuple[Version, Version] # 第一个是最低兼容版本,第二个是最高兼容版本 # 例如: ("1.0.0", "1.1.0") 表示从1.0.0版本开始兼容,到1.1.0版本结束兼容 @@ -60,9 +55,10 @@ class ModInfo(Options): config: Options = Options() # mod 配置存储 old_mod: Optional["ModInfo"] = None # 旧的mod实例 - def on_load(self, game: Game, old_self: Optional["ModInfo"] = None): + def on_load(self, game: Game, old_self: Optional["ModInfo"] = None) -> bool: """ 加载时调用 """ print(f'Mod {self.mod_id} loaded') + return True def on_server_start(self, game: Game): """ 服务器启动时调用 """ diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index 9e1eb61..f9991a6 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -22,13 +22,15 @@ import multiprocessing from io import StringIO from pathlib import Path +from typing import TYPE_CHECKING 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 from Difficult_Rocket.crash import write_info_to_cache from Difficult_Rocket.utils import tools from Difficult_Rocket.utils.translate import tr @@ -105,7 +107,7 @@ class Game: 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 = mod_module.mod_class + 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)) diff --git a/configs/main.toml b/configs/main.toml index 94e6a4f..05599b8 100644 --- a/configs/main.toml +++ b/configs/main.toml @@ -7,8 +7,8 @@ fonts_folder = "libs/fonts" [window] style = "None" -width = 1191 -height = 886 +width = 2571 +height = 1510 visible = true gui_scale = 1 caption = "Difficult Rocket v{DR_version}|DR_rs v{DR_Rust_get_version}" diff --git a/docs/src/update_logs.md b/docs/src/update_logs.md index e16da34..9657bdd 100644 --- a/docs/src/update_logs.md +++ b/docs/src/update_logs.md @@ -22,13 +22,27 @@ - [![Readme-gitee](https://img.shields.io/badge/Readme-中文(点我!)-blue.svg?style=flat-square)](../../README.md) - Using [SemVer 2.0.0](https://semver.org/) to manage version -## 202305 DR `0.8.0.0` + DR_api `0.1.0.0` + 15 +## 202305 DR `0.8.0.0` + DR_api `0.1.0.0` + DR_rs `0.2.7.0` + 15 > 啊哈! mod 加载来啦! > 啊啊啊啊啊 大重构 api +### DR_rs `0.2.7.0` +- `__init__.py` + - 添加了 `SR1Ship_rs` 的 typing + - `name` + - `description` + - `lift_off` + - `touch_ground` + - `img_pos() -> Tuple[int, int, int, int]` +- 导出了 `SR1Ship_rs` + - Exported `SR1Ship_rs` +- `types::SR1PartData` + - `get_box(&self, part_type: &SR1PartType) -> (f64, f64, f64, f64)` +- `types::SR1Ship` + - `from_file` ### Remove @@ -82,6 +96,13 @@ ### Mod Loader - `ModInfo` + - `on_load(game: Game, old_self: Optional[ModInfo]) -> bool` + - `game`: Game 对象 用于存储 DR SDK 的信息 + - `old_self`: 旧的 ModInfo 对象, 可以用于从上次加载中恢复信息 + - 返回值: 是否加载成功 + - `game`: Game object used to store information about the DR SDK + - `old_self`: Old ModInfo object, can be used to restore information from the last load + - Return value: Whether the load is successful ## 20230422 DR `0.7.2.2` + DR_rs `0.2.6.1` + DR_api `0.0.2.0` + 14 diff --git a/mods/dr_game/Difficult_Rocket_rs/__init__.py b/mods/dr_game/Difficult_Rocket_rs/__init__.py index 03c57ef..8b601e1 100644 --- a/mods/dr_game/Difficult_Rocket_rs/__init__.py +++ b/mods/dr_game/Difficult_Rocket_rs/__init__.py @@ -40,22 +40,16 @@ if TYPE_CHECKING: @property def dx(self) -> float: ... - @property def dy(self) -> float: ... - @property def zoom(self) -> float: ... - @property def position(self) -> Tuple[float, float]: ... - @dx.setter def dx(self, value: float) -> None: ... - @dy.setter def dy(self, value: float) -> None: ... - @zoom.setter def zoom(self, value: float) -> None: ... @@ -93,3 +87,17 @@ if TYPE_CHECKING: def as_dict(self) -> Dict[str, SR1PartType_rs]: ... def get_part_type(self, name: str) -> SR1PartType_rs: ... + + class SR1Ship_rs: + """ 用于高效且省内存的读取 SR1Ship """ + @property + def name(self) -> str: ... + @property + def description(self) -> str: ... + @property + def lift_off(self) -> bool: ... + @property + def touch_ground(self) -> bool: ... + @property + def img_pos(self) -> Tuple[int, int, int, int]: ... + """ -x -y +x +y 左下右上 """ diff --git a/mods/dr_game/Difficult_Rocket_rs/src/setup.py b/mods/dr_game/Difficult_Rocket_rs/src/setup.py index bd0fa18..ff43eda 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/setup.py +++ b/mods/dr_game/Difficult_Rocket_rs/src/setup.py @@ -12,7 +12,7 @@ package_path = 'Difficult_Rocket_rs' setup( name='Difficult_Rocket_rs', - version="0.2.6.2", + version="0.2.7.0", author='shenjackyuanjie', author_email='3695888@qq.com', rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs", 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 6f51ded..cb41705 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/lib.rs @@ -17,7 +17,7 @@ mod types; use pyo3::prelude::*; #[pyfunction] -fn get_version_str() -> String { "0.2.6.2".to_string() } +fn get_version_str() -> String { "0.2.7.0".to_string() } #[pyfunction] fn test_call(py_obj: &PyAny) -> PyResult { @@ -39,6 +39,7 @@ fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; 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 e934e56..329320a 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/python.rs @@ -13,8 +13,8 @@ pub mod data { use crate::sr1_data::part_list::RawPartList; use crate::sr1_data::ship::RawShip; + use crate::types::sr1::{SR1PartData, SR1PartListTrait}; use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship}; - use crate::types::sr1::{SR1PartListTrait, SR1ShipTrait}; #[pyclass] #[pyo3(name = "SR1PartType_rs")] @@ -70,6 +70,12 @@ pub mod data { } } + #[pyclass] + #[pyo3(name = "SR1PartData_rs")] + pub struct PySR1PartData { + pub data: SR1PartData, + } + #[pyclass] #[pyo3(name = "SR1Ship_rs")] #[pyo3(text_signature = "(file_path = './configs/dock1.xml', part_list = './configs/PartList.xml', ship_name = 'NewShip')")] @@ -82,11 +88,29 @@ pub mod data { impl PySR1Ship { #[new] fn new(file_path: String, part_list: String, ship_name: String) -> Self { - let raw_ship: RawShip = RawShip::from_file(file_path).unwrap(); - let ship = raw_ship.to_sr_ship(Some(ship_name)); + let ship = SR1Ship::from_file(file_path, Some(ship_name)).unwrap(); let part_list = SR1PartList::from_file(part_list).unwrap(); Self { ship, part_list } } + + fn get_img_pos(&self) -> (i64, i64, i64, i64) { + let mut img_pos = (0, 0, 0, 0); + // -x, -y, +x, +y + // 左下角,右上角 + for part in self.ship.types.iter() { + // let part_box = part + todo!("get_img_pos") + } + img_pos + } + + fn get_name(&self) -> String { self.ship.name.clone() } + + fn get_description(&self) -> String { self.ship.description.clone() } + + fn get_lift_off(&self) -> bool { self.ship.lift_off } + + fn get_touch_ground(&self) -> bool { self.ship.touch_ground } } } 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 df6c174..e5d7369 100644 --- a/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs +++ b/mods/dr_game/Difficult_Rocket_rs/src/src/types.rs @@ -8,7 +8,9 @@ pub mod sr1 { use std::collections::HashMap; + use std::fs; + use super::math::{Edge, Shape}; use crate::sr1_data::part_list::Damage as RawDamage; use crate::sr1_data::part_list::{AttachPoint, AttachPoints, Engine, Lander, Rcs, Shape as RawShape, Solar, Tank}; use crate::sr1_data::part_list::{RawPartList, RawPartType, SR1PartTypeEnum}; @@ -179,31 +181,49 @@ pub mod sr1 { #[derive(Debug, Clone)] pub struct SR1PartList { pub types: Vec, - pub cache: Option>, + pub cache: HashMap, pub name: String, } impl SR1PartList { + #[inline] + pub fn new(name: String, types: Vec) -> SR1PartList { + let mut map = HashMap::new(); + for part in types.iter() { + map.insert(part.id.clone(), part.clone()); + } + SR1PartList { + types, + cache: map, + name, + } + } + #[inline] pub fn from_file(file_name: String) -> Option { if let Some(raw_list) = RawPartList::from_file(file_name) { - return Some(raw_list.to_sr_part_list(None)); + let sr_list = raw_list.to_sr_part_list(None); + let mut map = HashMap::new(); + for part in sr_list.types.iter() { + map.insert(part.id.clone(), part.clone()); + } } None } #[inline] - pub fn get_hash_map(&mut self) -> HashMap { - if let Some(map) = &self.cache { - return map.clone(); + pub fn get_part_type(self, type_name: String) -> Option { + if let Some(part) = self.cache.get(&type_name) { + return Some(part.clone()); } - let mut map = HashMap::new(); - for part in self.types.iter() { - map.insert(part.id.clone(), part.clone()); - } - self.cache = Some(map.clone()); - map + None } + + pub fn part_types_new(part_types: Vec, name: Option) -> Self { + SR1PartList::new(name.unwrap_or("NewPartList".to_string()), part_types) + } + + pub fn insert_part(&mut self, part: SR1PartType) -> () { self.types.insert(0, part); } } pub trait SR1PartTypeData { @@ -226,17 +246,6 @@ pub mod sr1 { fn to_raw_ship(&self) -> RawShip; } - impl SR1PartList { - #[inline] - pub fn new(name: String, types: Vec) -> Self { SR1PartList { name, cache: None, types } } - - pub fn part_types_new(part_types: Vec, name: Option) -> Self { - SR1PartList::new(name.unwrap_or("NewPartList".to_string()), part_types) - } - - pub fn insert_part(&mut self, part: SR1PartType) -> () { self.types.insert(0, part); } - } - impl SR1PartListTrait for SR1PartList { fn to_sr_part_list(&self, name: Option) -> SR1PartList { return if let Some(name) = name { @@ -491,6 +500,32 @@ pub mod sr1 { pub explode: bool, } + impl SR1PartData { + pub fn get_box(&self, part_type: &SR1PartType) -> (f64, f64, f64, f64) { + 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), Some(self.y)); + let mut pos_box = (0_f64, 0_f64, 0_f64, 0_f64); + match shape.bounds[0] { + Edge::OneTimeLine(line) => { + pos_box.0 = line.start.x; + pos_box.1 = line.start.y; + } + _ => {} + } + match shape.bounds[2] { + Edge::OneTimeLine(line) => { + pos_box.2 = line.start.x; + pos_box.3 = line.start.y; + } + _ => {} + } + pos_box + } + } + #[derive(Debug, Clone)] pub enum SR1PartDataAttr { Tank { @@ -532,6 +567,18 @@ pub mod sr1 { pub disconnected: Option, Option>)>>, } + impl SR1Ship { + pub fn from_file(file_name: String, ship_name: Option) -> Option { + // 首先验证文件是否存在 不存在则返回None + if !std::path::Path::new(&file_name).exists() { + return None; + } + // 解析为 RawShip + let ship: RawShip = RawShip::from_file(file_name).unwrap(); + Some(ship.to_sr_ship(ship_name)) + } + } + impl SR1ShipTrait for SR1Ship { #[inline] fn to_sr_ship(&self, name: Option) -> SR1Ship { @@ -582,6 +629,14 @@ pub mod sr1 { } } } + + pub fn get_max_box(parts: &Vec, part_list: &SR1PartList) -> (f64, f64, f64, f64) { + let mut max_box = (0_f64, 0_f64, 0_f64, 0_f64); + for part in parts.iter() { + let part_type = part_list.get_part_type(part.part_type); + } + todo!("get_max_box") + } } #[allow(unused)] @@ -686,7 +741,7 @@ pub mod math { } } - pub fn new_width_height(width: f64, height: f64, angle: Option) -> Self { + pub fn new_width_height(width: f64, height: f64, radius: Option) -> Self { let d_width = width / 2.0; let d_height = height / 2.0; let mut edges: Vec = vec![ @@ -695,17 +750,17 @@ pub mod math { Edge::OneTimeLine(OneTimeLine::pos_new(d_width, d_height, -d_width, d_height)), Edge::OneTimeLine(OneTimeLine::pos_new(-d_width, d_height, -d_width, -d_height)), ]; - if let Some(angle) = angle { + if let Some(radius) = radius { edges = edges .iter() .map(|edge| match edge { Edge::OneTimeLine(line) => { - let start = line.start.rotate(angle); - let end = line.end.rotate(angle); + let start = line.start.rotate_radius(radius); + let end = line.end.rotate_radius(radius); Edge::OneTimeLine(OneTimeLine::point_new(&start, &end)) } Edge::CircularArc(arc) => { - let pos = arc.pos.rotate(angle); + let pos = arc.pos.rotate_radius(radius); Edge::CircularArc(CircularArc { r: arc.r, pos, @@ -722,6 +777,25 @@ pub mod math { bounds: edges, } } + + pub fn move_xy(&mut self, x: Option, y: Option) { + let x = x.unwrap_or(0.0); + let y = y.unwrap_or(0.0); + for edge in self.bounds.iter() { + match edge { + Edge::OneTimeLine(mut line) => { + line.start.x += x; + line.start.y += y; + line.end.x += x; + line.end.y += y; + } + Edge::CircularArc(mut arc) => { + arc.pos.x += x; + arc.pos.y += y; + } + } + } + } } impl OneTimeLine { diff --git a/mods/dr_game/__init__.py b/mods/dr_game/__init__.py index 09beac7..112642c 100644 --- a/mods/dr_game/__init__.py +++ b/mods/dr_game/__init__.py @@ -26,7 +26,7 @@ class _DR_mod_runtime(Options): DR_rust_version: Version = DR_rust_version DR_rust_get_version: Optional[Version] = None - def init(self, **kwargs) -> None: + def init(self) -> None: try: from .Difficult_Rocket_rs import get_version_str self.DR_rust_get_version = Version(get_version_str()) @@ -36,12 +36,7 @@ class _DR_mod_runtime(Options): warnings.warn(f'DR_rust builtin version is {self.DR_rust_version} but true version is {get_version_str()}.\n' f'Builtin version {relationship} than true version') self.use_DR_rust = self.use_DR_rust and self.DR_rust_available - except Exception as e: - try: - from .Difficult_Rocket_rs import get_version_str - print(type(get_version_str)) - except: - ... + except Exception: traceback.print_exc() self.DR_rust_available = False self.use_DR_rust = False @@ -69,11 +64,15 @@ class DR_mod(ModInfo): # DR_Api_version = # DR Api版本 # 同理 不管 API 版本 这东西要是不兼容了才是大问题 - def on_load(self, game: Game, old_self: Optional["DR_mod"] = None): + def on_load(self, game: Game, old_self: Optional["DR_mod"] = None) -> bool: + if not DR_mod_runtime.DR_rust_available: + return False if old_self: game.client.window.add_sub_screen("SR1_ship", old_self.screen) else: self.config.flush_option() + print("DR_mod: on_load") + return True def on_client_start(self, game: Game, client: ClientWindow): from .sr1_ship import SR1ShipRender diff --git a/mods/dr_game/sr1_ship.py b/mods/dr_game/sr1_ship.py index ae53a58..6a46b49 100644 --- a/mods/dr_game/sr1_ship.py +++ b/mods/dr_game/sr1_ship.py @@ -19,6 +19,7 @@ from pyglet.math import Vec4 from pyglet.text import Label from pyglet.shapes import Line from pyglet.sprite import Sprite +from pyglet.image import Texture from pyglet.graphics import Batch, Group from . import DR_mod_runtime @@ -360,6 +361,12 @@ class SR1ShipRender(BaseScreen): image_data = screenshot(self.window_pointer) image_data.save('test.png') + elif command.re_match('gen_img'): + if not self.rendered: + return + # ship_size = self.ship.size + base_textures = Texture.create(100, 100) + ... def on_mouse_drag(self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int, window: "ClientWindow"): if not self.focus: