DR -> DR SDK #16

Merged
shenjackyuanjie merged 41 commits from feature/dr-sdk into main 2023-05-03 00:40:53 +08:00
12 changed files with 191 additions and 59 deletions
Showing only changes of commit ca9b928658 - Show all commits

View File

@ -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

View File

@ -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):
""" 服务器启动时调用 """

View File

@ -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))

View File

@ -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}"

View File

@ -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

View File

@ -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 左下右上 """

View File

@ -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",

View File

@ -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<bool> {
@ -39,6 +39,7 @@ fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<render::camera::CameraRs>()?;
m.add_class::<render::camera::CenterCameraRs>()?;
m.add_class::<render::screen::PartFrame>()?;
m.add_class::<python::data::PySR1Ship>()?;
m.add_class::<python::data::PySR1PartList>()?;
m.add_class::<python::data::PySR1PartType>()?;
Ok(())

View File

@ -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 }
}
}

View File

@ -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<SR1PartType>,
pub cache: Option<HashMap<String, SR1PartType>>,
pub cache: HashMap<String, SR1PartType>,
pub name: String,
}
impl SR1PartList {
#[inline]
pub fn new(name: String, types: Vec<SR1PartType>) -> 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<SR1PartList> {
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<String, SR1PartType> {
if let Some(map) = &self.cache {
return map.clone();
pub fn get_part_type(self, type_name: String) -> Option<SR1PartType> {
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());
None
}
self.cache = Some(map.clone());
map
pub fn part_types_new(part_types: Vec<SR1PartType>, name: Option<String>) -> 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<SR1PartType>) -> Self { SR1PartList { name, cache: None, types } }
pub fn part_types_new(part_types: Vec<SR1PartType>, name: Option<String>) -> 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<String>) -> 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<Vec<(Vec<SR1PartData>, Option<Vec<Connection>>)>>,
}
impl SR1Ship {
pub fn from_file(file_name: String, ship_name: Option<String>) -> Option<Self> {
// 首先验证文件是否存在 不存在则返回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<String>) -> SR1Ship {
@ -582,6 +629,14 @@ pub mod sr1 {
}
}
}
pub fn get_max_box(parts: &Vec<SR1PartData>, 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<f64>) -> Self {
pub fn new_width_height(width: f64, height: f64, radius: Option<f64>) -> Self {
let d_width = width / 2.0;
let d_height = height / 2.0;
let mut edges: Vec<Edge> = 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<f64>, y: Option<f64>) {
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 {

View File

@ -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

View File

@ -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: