DR -> DR SDK #16
@ -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
|
||||
|
@ -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):
|
||||
""" 服务器启动时调用 """
|
||||
|
@ -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))
|
||||
|
@ -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}"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 左下右上 """
|
||||
|
@ -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",
|
||||
|
@ -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(())
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
self.cache = Some(map.clone());
|
||||
map
|
||||
None
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user