Compare commits
No commits in common. "ad83def45e737aac0053e007de8db51b719dac1c" and "3629bcf163af342f6718eb3e09b3999075231d96" have entirely different histories.
ad83def45e
...
3629bcf163
@ -1,5 +1,3 @@
|
|||||||
<div style="text-align: center;">
|
|
||||||
|
|
||||||
# Difficult Rocket
|
# Difficult Rocket
|
||||||
|
|
||||||
中文 | [English](./docs/README-en.md)
|
中文 | [English](./docs/README-en.md)
|
||||||
@ -121,8 +119,6 @@ setuptools-rust >= 1.6.0
|
|||||||
- [@Billchyi](https://github.com/Billchyi) : 文档矫正
|
- [@Billchyi](https://github.com/Billchyi) : 文档矫正
|
||||||
- [@MSDNicrosoft](https://github.com/MSDNicrosoft) : 优化代码
|
- [@MSDNicrosoft](https://github.com/MSDNicrosoft) : 优化代码
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 相关链接
|
## 相关链接
|
||||||
|
|
||||||
## 关于分享协议
|
## 关于分享协议
|
||||||
|
@ -7,8 +7,8 @@ fonts_folder = "assets/fonts"
|
|||||||
|
|
||||||
[window]
|
[window]
|
||||||
style = "None"
|
style = "None"
|
||||||
width = 1112
|
width = 1301
|
||||||
height = 793
|
height = 970
|
||||||
visible = true
|
visible = true
|
||||||
gui_scale = 1
|
gui_scale = 1
|
||||||
caption = "Difficult Rocket v{DR_version}"
|
caption = "Difficult Rocket v{DR_version}"
|
||||||
|
@ -2,31 +2,8 @@
|
|||||||
# DR game/DR rs 更新日志
|
# DR game/DR rs 更新日志
|
||||||
|
|
||||||
- 最新版本号
|
- 最新版本号
|
||||||
- DR game: 0.3.2.0
|
- DR game: 0.3.1.3
|
||||||
- DR rs: 0.2.19.0
|
- DR rs: 0.2.17.0
|
||||||
|
|
||||||
## 20230721 DR rs 0.2.19.0
|
|
||||||
|
|
||||||
### Add
|
|
||||||
|
|
||||||
- `PySR1Ship`
|
|
||||||
- `as_list`
|
|
||||||
|
|
||||||
## 20230721 DR game 0.3.2.0
|
|
||||||
|
|
||||||
### BUG Fix
|
|
||||||
|
|
||||||
- [#46](https://github.com/shenjackyuanjie/Difficult-Rocket/issues/46)
|
|
||||||
- 渲染偏移 bug
|
|
||||||
|
|
||||||
## 20230721 DR rs 0.2.18.0
|
|
||||||
|
|
||||||
### Add
|
|
||||||
|
|
||||||
- 导出了 export
|
|
||||||
- `PySR1PartData`
|
|
||||||
- `PySaveStatus`
|
|
||||||
- `map_ptype_textures(part_type: str) -> str`
|
|
||||||
|
|
||||||
## 20230721 DR rs 0.2.17.0
|
## 20230721 DR rs 0.2.17.0
|
||||||
|
|
||||||
|
@ -9,81 +9,49 @@ from .lib import *
|
|||||||
from typing import TYPE_CHECKING, Dict, Tuple, Optional, List
|
from typing import TYPE_CHECKING, Dict, Tuple, Optional, List
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
def test_call(py_obj) -> bool:
|
def test_call(py_obj) -> bool:
|
||||||
""" 这里展示的代码实际上就是实际的等效实现 """
|
""" 这里展示的代码实际上就是实际的等效实现 """
|
||||||
py_obj.draw()
|
py_obj.draw()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_version_str() -> str: ...
|
||||||
|
|
||||||
def get_version_str() -> str:
|
def part_list_read_test(file_name: Optional[str] = "./assets/builtin/PartList.xml") -> None: ...
|
||||||
"""
|
|
||||||
获取版本号
|
def read_ship_test(path: Optional[str] = "./assets/builtin/dock1.xml") -> None: ...
|
||||||
:return: 版本号
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def part_list_read_test(file_name: Optional[str] = "./assets/builtin/PartList.xml") -> None:
|
class SR1PartType_rs:
|
||||||
"""
|
""" 用于从 rust 中读取 SR1PartType
|
||||||
PartList 读取测试
|
|
||||||
:param file_name:
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def read_ship_test(path: Optional[str] = "./assets/builtin/dock1.xml") -> None:
|
|
||||||
"""
|
|
||||||
飞船存档读取测试
|
|
||||||
:param path:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def map_ptype_textures(part_type: str) -> str:
|
|
||||||
"""
|
|
||||||
获取零件的贴图 (写死的)
|
|
||||||
:param part_type:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class SR1PartType_rs: # NOQA
|
|
||||||
"""
|
|
||||||
用于从 rust 中读取 SR1PartType
|
|
||||||
不能从 Python 端创建
|
不能从 Python 端创建
|
||||||
自带一些可从 Python 端读取的属性 (实际上就是一个接口)
|
自带一些可从 Python 端读取的属性 (实际上就是一个接口)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
""" 零件的名字 """
|
""" 零件的名字 """
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self) -> str:
|
def description(self) -> str:
|
||||||
""" 零件的描述 """
|
""" 零件的描述 """
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mass(self) -> float:
|
def mass(self) -> float:
|
||||||
""" 零件的质量 """
|
""" 零件的质量 """
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self) -> int:
|
def width(self) -> int:
|
||||||
""" 零件的宽度 """
|
""" 零件的宽度 """
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def height(self) -> int:
|
def height(self) -> int:
|
||||||
""" 零件的高度 """
|
""" 零件的高度 """
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def friction(self) -> float:
|
def friction(self) -> float:
|
||||||
""" 零件的摩擦系数 """
|
""" 零件的摩擦系数 """
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hidden(self) -> bool:
|
def hidden(self) -> bool:
|
||||||
""" 零件是否隐藏 """
|
""" 零件是否隐藏 """
|
||||||
|
|
||||||
|
|
||||||
class SR1PartList_rs: # NOQA
|
class SR1PartList_rs:
|
||||||
""" 用于从 rust 中读取 SR1PartList """
|
""" 用于从 rust 中读取 SR1PartList """
|
||||||
|
|
||||||
def __init__(self, file_name: Optional[str] = "./assets/builtin/PartList.xml",
|
def __init__(self, file_name: Optional[str] = "./assets/builtin/PartList.xml",
|
||||||
list_name: Optional[str] = 'NewPartList'): ...
|
list_name: Optional[str] = 'NewPartList'): ...
|
||||||
|
|
||||||
@ -91,104 +59,63 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
def get_part_type(self, name: str) -> SR1PartType_rs: ...
|
def get_part_type(self, name: str) -> SR1PartType_rs: ...
|
||||||
|
|
||||||
|
class SR1PartData_rs:
|
||||||
class SR1PartData_rs: # NOQA
|
""" 用于从 rust 中读取 SR1PartData (其实好像也没啥用哈)
|
||||||
"""
|
"""
|
||||||
用于从 rust 中读取 SR1PartData (其实好像也没啥用哈)
|
|
||||||
"""
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> int: ...
|
def id(self) -> int: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def part_type_id(self) -> str: ...
|
def part_type_id(self) -> str: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pos(self) -> Tuple[float, float]: ...
|
def pos(self) -> Tuple[float, float]: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def x(self) -> float: ...
|
def x(self) -> float: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def y(self) -> float: ...
|
def y(self) -> float: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def activate(self) -> bool: ...
|
def activate(self) -> bool: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def angle(self) -> float: ...
|
def angle(self) -> float: ...
|
||||||
|
|
||||||
@property
|
|
||||||
def angle_r(self) -> float: ...
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def angle_v(self) -> float: ...
|
def angle_v(self) -> float: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def explode(self) -> bool: ...
|
def explode(self) -> bool: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def flip_x(self) -> bool: ...
|
def flip_x(self) -> bool: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def flip_y(self) -> bool: ...
|
def flip_y(self) -> bool: ...
|
||||||
|
|
||||||
|
class SaveStatus_rs:
|
||||||
class SaveStatus_rs: # NOQA
|
|
||||||
def __init__(self, save_default: Optional[bool] = False) -> None: ...
|
def __init__(self, save_default: Optional[bool] = False) -> None: ...
|
||||||
|
|
||||||
|
class SR1Ship_rs:
|
||||||
class SR1Ship_rs: # NOQA
|
|
||||||
""" 用于高效且省内存的读取 SR1Ship """
|
""" 用于高效且省内存的读取 SR1Ship """
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
file_path: Optional[str] = './assets/builtin/dock1.xml',
|
file_path: Optional[str] = './assets/builtin/dock1.xml',
|
||||||
part_list: Optional[SR1PartList_rs] = None,
|
part_list: Optional[SR1PartList_rs] = None,
|
||||||
ship_name: Optional[str] = 'NewShip'): ...
|
ship_name: Optional[str] = 'NewShip'): ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str: ...
|
def name(self) -> str: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self) -> str: ...
|
def description(self) -> str: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lift_off(self) -> bool: ...
|
def lift_off(self) -> bool: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def touch_ground(self) -> bool: ...
|
def touch_ground(self) -> bool: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mass(self) -> float:
|
def img_pos(self) -> Tuple[int, int, int, int]: ...
|
||||||
""" 获取整搜船的质量 """
|
""" -x -y +x +y 左下右上 """
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def img_pos(self) -> Tuple[int, int, int, int]:
|
def connection(self) -> List[Tuple[int, int, int, int]]: ...
|
||||||
""" -x -y +x +y 左下右上 """
|
"""获取所有连接信息"""
|
||||||
|
def get_part_box(self, part_id: int) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]: ...
|
||||||
@property
|
|
||||||
def connection(self) -> List[Tuple[int, int, int, int]]:
|
|
||||||
"""获取所有连接信息"""
|
|
||||||
|
|
||||||
def get_part_box(self, part_id: int) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]:
|
|
||||||
"""获取所有零件的盒子"""
|
|
||||||
|
|
||||||
def as_list(self) -> List[Tuple[SR1PartType_rs, SR1PartData_rs]]:
|
|
||||||
"""用于返回一个包含所有已连接零件的列表"""
|
|
||||||
|
|
||||||
def as_dict(self) -> Dict[int, List[Tuple[SR1PartType_rs, SR1PartData_rs]]]:
|
def as_dict(self) -> Dict[int, List[Tuple[SR1PartType_rs, SR1PartData_rs]]]:
|
||||||
"""用于返回一个包含所有已连接零件的字典"""
|
"""用于返回一个包含所有已连接零件的字典"""
|
||||||
|
|
||||||
def save(self, file_path: str, save_status: Optional[SaveStatus_rs] = None) -> None: ...
|
def save(self, file_path: str, save_status: Optional[SaveStatus_rs] = None) -> None: ...
|
||||||
|
|
||||||
|
class Console_rs:
|
||||||
class Console_rs: # NOQA
|
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
|
|
||||||
def start(self) -> None: ...
|
def start(self) -> None: ...
|
||||||
|
|
||||||
def stop(self) -> bool: ...
|
def stop(self) -> bool: ...
|
||||||
|
|
||||||
def get_command(self) -> Optional[str]: ...
|
def get_command(self) -> Optional[str]: ...
|
||||||
|
|
||||||
def new_command(self) -> bool: ...
|
def new_command(self) -> bool: ...
|
||||||
|
2
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
2
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
@ -116,7 +116,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "difficult_rocket_rs"
|
name = "difficult_rocket_rs"
|
||||||
version = "0.2.19"
|
version = "0.2.17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pyo3",
|
"pyo3",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "difficult_rocket_rs"
|
name = "difficult_rocket_rs"
|
||||||
version = "0.2.19"
|
version = "0.2.17"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license-file = '../../LICENSE'
|
license-file = '../../LICENSE'
|
||||||
authors = [
|
|
||||||
"shenjackyuanjie <3695888@qq.com>"
|
|
||||||
]
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ package_path = 'Difficult_Rocket_rs'
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='Difficult_Rocket_rs',
|
name='Difficult_Rocket_rs',
|
||||||
version="0.2.18.0",
|
version="0.2.16.0",
|
||||||
author='shenjackyuanjie',
|
author='shenjackyuanjie',
|
||||||
author_email='3695888@qq.com',
|
author_email='3695888@qq.com',
|
||||||
rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs",
|
rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs",
|
||||||
|
@ -24,7 +24,7 @@ enum LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_version_str() -> String { "0.2.19.0".to_string() }
|
fn get_version_str() -> String { "0.2.17.0".to_string() }
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
||||||
@ -43,12 +43,9 @@ fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|||||||
m.add_function(wrap_pyfunction!(sr1_data::part_list::read_part_list_py, m)?)?;
|
m.add_function(wrap_pyfunction!(sr1_data::part_list::read_part_list_py, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(sr1_data::ship::py_raw_ship_from_file, m)?)?;
|
m.add_function(wrap_pyfunction!(sr1_data::ship::py_raw_ship_from_file, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(python::data::load_and_save_test, m)?)?;
|
m.add_function(wrap_pyfunction!(python::data::load_and_save_test, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(python::data::py_map_ptype_textures, m)?)?;
|
|
||||||
m.add_class::<python::data::PySR1Ship>()?;
|
m.add_class::<python::data::PySR1Ship>()?;
|
||||||
m.add_class::<python::data::PySR1PartList>()?;
|
m.add_class::<python::data::PySR1PartList>()?;
|
||||||
m.add_class::<python::data::PySR1PartType>()?;
|
m.add_class::<python::data::PySR1PartType>()?;
|
||||||
m.add_class::<python::data::PySR1PartData>()?;
|
|
||||||
m.add_class::<python::data::PySaveStatus>()?;
|
|
||||||
m.add_class::<python::console::PyConsole>()?;
|
m.add_class::<python::console::PyConsole>()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -13,15 +13,10 @@ pub mod data {
|
|||||||
|
|
||||||
use crate::sr1_data::part_list::RawPartList;
|
use crate::sr1_data::part_list::RawPartList;
|
||||||
use crate::types::math::{Point2D, Rotatable};
|
use crate::types::math::{Point2D, Rotatable};
|
||||||
use crate::types::sr1::{get_max_box, map_ptype_textures, SR1PartData, SR1PartListTrait};
|
use crate::types::sr1::{get_max_box, SR1PartData, SR1PartListTrait};
|
||||||
use crate::types::sr1::{IdType, SaveStatus};
|
use crate::types::sr1::{IdType, SaveStatus};
|
||||||
use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship};
|
use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship};
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
#[pyo3(signature = (part_type))]
|
|
||||||
#[pyo3(name = "map_ptype_textures")]
|
|
||||||
pub fn py_map_ptype_textures(part_type: String) -> String { map_ptype_textures(part_type) }
|
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[pyo3(name = "SaveStatus_rs")]
|
#[pyo3(name = "SaveStatus_rs")]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -142,9 +137,6 @@ pub mod data {
|
|||||||
#[getter]
|
#[getter]
|
||||||
fn get_angle(&self) -> f64 { self.data.angle }
|
fn get_angle(&self) -> f64 { self.data.angle }
|
||||||
|
|
||||||
#[getter]
|
|
||||||
fn get_angle_r(&self) -> f64 { self.data.angle_degrees() }
|
|
||||||
|
|
||||||
#[getter]
|
#[getter]
|
||||||
fn get_angle_v(&self) -> f64 { self.data.angle_v }
|
fn get_angle_v(&self) -> f64 { self.data.angle_v }
|
||||||
|
|
||||||
@ -229,20 +221,8 @@ pub mod data {
|
|||||||
connections
|
connections
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_list(&self) -> Vec<(PySR1PartType, PySR1PartData)> {
|
fn as_dict(&self) -> HashMap<i64, Vec<(PySR1PartType, PySR1PartData)>> {
|
||||||
let mut parts: Vec<(PySR1PartType, PySR1PartData)> = Vec::new();
|
let mut parts: HashMap<i64, Vec<(PySR1PartType, PySR1PartData)>> = HashMap::new();
|
||||||
for part_data in self.ship.parts.iter() {
|
|
||||||
if let Some(part_type) = self.part_list.get_part_type(&part_data.part_type_id) {
|
|
||||||
let part_type = PySR1PartType::new(part_type.clone());
|
|
||||||
let py_part_data = PySR1PartData::new(part_data.clone());
|
|
||||||
parts.push((part_type, py_part_data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parts
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_dict(&self) -> HashMap<IdType, Vec<(PySR1PartType, PySR1PartData)>> {
|
|
||||||
let mut parts: HashMap<IdType, Vec<(PySR1PartType, PySR1PartData)>> = HashMap::new();
|
|
||||||
for part_data in self.ship.parts.iter() {
|
for part_data in self.ship.parts.iter() {
|
||||||
if let Some(part_type) = self.part_list.get_part_type(&part_data.part_type_id) {
|
if let Some(part_type) = self.part_list.get_part_type(&part_data.part_type_id) {
|
||||||
let part_type = PySR1PartType::new(part_type.clone());
|
let part_type = PySR1PartType::new(part_type.clone());
|
||||||
|
@ -24,29 +24,6 @@ pub mod sr1 {
|
|||||||
pub type IdType = i64;
|
pub type IdType = i64;
|
||||||
pub type ConnectionsType = Vec<(Vec<SR1PartData>, Option<Vec<Connection>>)>;
|
pub type ConnectionsType = Vec<(Vec<SR1PartData>, Option<Vec<Connection>>)>;
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn radians_map_to_degrees(angle: f64) -> f64 {
|
|
||||||
// match angle {
|
|
||||||
// 0.0 => 0.,
|
|
||||||
// 1.570796 => 270.,
|
|
||||||
// 3.141593 => 180.,
|
|
||||||
// 4.712389 => 90.,
|
|
||||||
// _ => {
|
|
||||||
// angle.to_degrees()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
#[allow(clippy::approx_constant)]
|
|
||||||
if angle == 1.570796 {
|
|
||||||
270.
|
|
||||||
} else if angle == 3.141593 {
|
|
||||||
180.
|
|
||||||
} else if angle == 4.712389 {
|
|
||||||
90.
|
|
||||||
} else {
|
|
||||||
angle.to_degrees()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn map_ptype_textures(ptype: String) -> String {
|
pub fn map_ptype_textures(ptype: String) -> String {
|
||||||
@ -529,8 +506,6 @@ pub mod sr1 {
|
|||||||
}
|
}
|
||||||
pos_box
|
pos_box
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn angle_degrees(&self) -> f64 { radians_map_to_degrees(self.angle) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -16,7 +16,7 @@ from Difficult_Rocket.api.mod import ModInfo
|
|||||||
from Difficult_Rocket.client import ClientWindow
|
from Difficult_Rocket.client import ClientWindow
|
||||||
from Difficult_Rocket.api.types import Options, Version
|
from Difficult_Rocket.api.types import Options, Version
|
||||||
|
|
||||||
DR_rust_version = Version("0.2.19.0") # DR_mod 的 Rust 编写部分的兼容版本
|
DR_rust_version = Version("0.2.17.0") # DR_mod 的 Rust 编写部分的兼容版本
|
||||||
|
|
||||||
logger = logging.getLogger('client.dr_game')
|
logger = logging.getLogger('client.dr_game')
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ DR_mod_runtime = _DR_mod_runtime()
|
|||||||
class DR_mod(ModInfo): # NOQA
|
class DR_mod(ModInfo): # NOQA
|
||||||
mod_id = "difficult_rocket_mod"
|
mod_id = "difficult_rocket_mod"
|
||||||
name = "Difficult Rocket mod"
|
name = "Difficult Rocket mod"
|
||||||
version = Version("0.3.2.0")
|
version = Version("0.3.1.2")
|
||||||
|
|
||||||
writer = "shenjackyuanjie"
|
writer = "shenjackyuanjie"
|
||||||
link = "shenjack.top"
|
link = "shenjack.top"
|
||||||
@ -81,7 +81,7 @@ class DR_mod(ModInfo): # NOQA
|
|||||||
else:
|
else:
|
||||||
self.config.flush_option()
|
self.config.flush_option()
|
||||||
logger.info("on_load")
|
logger.info("on_load")
|
||||||
logger.info(f"\n{self.as_markdown()}")
|
logger.info(self.as_markdown())
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_client_start(self, game: Game, client: ClientWindow):
|
def on_client_start(self, game: Game, client: ClientWindow):
|
||||||
|
@ -40,16 +40,38 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
from .Difficult_Rocket_rs import (SR1PartList_rs,
|
from .Difficult_Rocket_rs import (SR1PartList_rs,
|
||||||
SR1Ship_rs,
|
SR1Ship_rs)
|
||||||
SR1PartData_rs,
|
|
||||||
SR1PartType_rs,
|
|
||||||
map_ptype_textures)
|
|
||||||
|
|
||||||
logger = logging.getLogger('client.dr_game_sr1_ship')
|
logger = logging.getLogger('client.dr_game_sr1_ship')
|
||||||
logger.level = logging.DEBUG
|
logger.level = logging.DEBUG
|
||||||
sr_tr = Tr(lang_path=Path(__file__).parent / 'lang')
|
sr_tr = Tr(lang_path=Path(__file__).parent / 'lang')
|
||||||
|
|
||||||
|
|
||||||
|
def get_sr1_part(part_xml: Element) -> Optional[SR1PartData]:
|
||||||
|
if part_xml.tag != 'Part':
|
||||||
|
return None
|
||||||
|
# print(f"tag: {part.tag} attrib: {part.attrib}")
|
||||||
|
part_id = int(part_xml.attrib.get('id'))
|
||||||
|
part_type = part_xml.attrib.get('partType')
|
||||||
|
part_x = float(part_xml.attrib.get('x'))
|
||||||
|
part_y = float(part_xml.attrib.get('y'))
|
||||||
|
part_activate = xml_bool(part_xml.attrib.get('activated'))
|
||||||
|
part_angle = float(part_xml.attrib.get('angle'))
|
||||||
|
part_angle_v = float(part_xml.attrib.get('angleV'))
|
||||||
|
part_editor_angle = int(part_xml.attrib.get('editorAngle'))
|
||||||
|
part_flip_x = xml_bool(part_xml.attrib.get('flippedX'))
|
||||||
|
part_flip_y = xml_bool(part_xml.attrib.get('flippedY'))
|
||||||
|
part_explode = xml_bool(part_xml.attrib.get('exploded'))
|
||||||
|
if part_type not in SR1PartTexture.part_type_sprite:
|
||||||
|
part_textures = None
|
||||||
|
else:
|
||||||
|
part_textures = SR1PartTexture.get_textures_from_type(part_type)
|
||||||
|
return SR1PartData(x=part_x, y=part_y, id=part_id, p_type=part_type,
|
||||||
|
active=part_activate, angle=part_angle, angle_v=part_angle_v,
|
||||||
|
editor_angle=part_editor_angle, flip_x=part_flip_x,
|
||||||
|
flip_y=part_flip_y, explode=part_explode, textures=part_textures)
|
||||||
|
|
||||||
|
|
||||||
class SR1ShipRender_Option(Options): # NOQA
|
class SR1ShipRender_Option(Options): # NOQA
|
||||||
# debug option
|
# debug option
|
||||||
debug_d_pos: bool = False
|
debug_d_pos: bool = False
|
||||||
@ -75,8 +97,6 @@ class SR1ShipRender(BaseScreen):
|
|||||||
self.render_option = SR1ShipRender_Option()
|
self.render_option = SR1ShipRender_Option()
|
||||||
self.dx = 0
|
self.dx = 0
|
||||||
self.dy = 0
|
self.dy = 0
|
||||||
self.width = main_window.width
|
|
||||||
self.height = main_window.height
|
|
||||||
|
|
||||||
self.main_batch = Batch()
|
self.main_batch = Batch()
|
||||||
self.part_group = Group(10, parent=main_window.main_group)
|
self.part_group = Group(10, parent=main_window.main_group)
|
||||||
@ -92,29 +112,32 @@ class SR1ShipRender(BaseScreen):
|
|||||||
self.render_d_label = Label('debug label NODATA', font_name=Fonts.微软等宽无线,
|
self.render_d_label = Label('debug label NODATA', font_name=Fonts.微软等宽无线,
|
||||||
x=main_window.width / 2, y=main_window.height / 2)
|
x=main_window.width / 2, y=main_window.height / 2)
|
||||||
self.render_d_label.visible = self.render_option.debug_d_pos
|
self.render_d_label.visible = self.render_option.debug_d_pos
|
||||||
self.camera = CenterCamera(main_window, min_zoom=(1 / 2) ** 10, max_zoom=10)
|
|
||||||
|
|
||||||
# Optional data
|
# Optional data
|
||||||
self.textures: SR1Textures = SR1Textures()
|
|
||||||
self.gen_draw: Optional[Generator] = None
|
self.gen_draw: Optional[Generator] = None
|
||||||
|
self.textures: Union[SR1Textures, None] = None
|
||||||
|
self.xml_name: Optional[str] = None # 准备移除, 更换为基于 rust 的 xml 解析
|
||||||
|
self.xml_doc: Optional[ElementTree] = None # 准备移除, 更换为基于 rust 的 xml 解析
|
||||||
|
self.xml_root: Optional[Element] = None # 准备移除, 更换为基于 rust 的 xml 解析
|
||||||
self.rust_ship: Optional[SR1Ship_rs] = None
|
self.rust_ship: Optional[SR1Ship_rs] = None
|
||||||
self.ship_name: Optional[str] = None
|
|
||||||
|
|
||||||
# List/Dict data
|
# List/Dict data
|
||||||
self.parts_sprite: Dict[int, List[Sprite]] = {}
|
self.part_data: Dict[int, SR1PartData] = {}
|
||||||
|
self.parts_sprite: Dict[int, Sprite] = {}
|
||||||
self.part_box_dict: Dict[int, Rectangle] = {}
|
self.part_box_dict: Dict[int, Rectangle] = {}
|
||||||
self.part_line_box: Dict[int, List[Line]] = {}
|
self.part_line_box: Dict[int, List[Line]] = {}
|
||||||
self.part_line_list: List[Line] = []
|
self.part_line_list: List[Line] = []
|
||||||
|
|
||||||
|
|
||||||
|
load_end_time = time.time_ns()
|
||||||
|
logger.info(sr_tr().mod.info.setup.use_time().format((load_end_time - load_start_time) / 1000000000))
|
||||||
|
self.camera = CenterCamera(main_window, min_zoom=(1 / 2) ** 10, max_zoom=10)
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
self.rust_parts = None
|
self.rust_parts = None
|
||||||
self.part_list_rs = SR1PartList_rs('assets/builtin/PartList.xml', 'builtin_part_list')
|
self.part_list_rs = SR1PartList_rs('assets/builtin/PartList.xml', 'builtin_part_list')
|
||||||
|
|
||||||
self.load_xml('assets/builtin/dock1.xml')
|
self.load_xml('assets/builtin/dock1.xml')
|
||||||
|
|
||||||
load_end_time = time.time_ns()
|
|
||||||
logger.info(sr_tr().mod.info.setup.use_time().format((load_end_time - load_start_time) / 1000000000))
|
|
||||||
|
|
||||||
def load_xml(self, file_path: str) -> bool:
|
def load_xml(self, file_path: str) -> bool:
|
||||||
"""
|
"""
|
||||||
加载 xml 文件
|
加载 xml 文件
|
||||||
@ -124,7 +147,10 @@ class SR1ShipRender(BaseScreen):
|
|||||||
try:
|
try:
|
||||||
start_time = time.time_ns()
|
start_time = time.time_ns()
|
||||||
logger.info(sr_tr().sr1.ship.xml.loading().format(file_path))
|
logger.info(sr_tr().sr1.ship.xml.loading().format(file_path))
|
||||||
self.ship_name = file_path.split('/')[-1].split('.')[0]
|
cache_doc = parse(file_path)
|
||||||
|
self.xml_doc = cache_doc
|
||||||
|
self.xml_root = self.xml_doc.getroot()
|
||||||
|
self.xml_name = file_path
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
self.rust_ship = SR1Ship_rs(file_path, self.part_list_rs, 'a_new_ship')
|
self.rust_ship = SR1Ship_rs(file_path, self.part_list_rs, 'a_new_ship')
|
||||||
logger.info(sr_tr().sr1.ship.xml.load_done())
|
logger.info(sr_tr().sr1.ship.xml.load_done())
|
||||||
@ -135,34 +161,44 @@ class SR1ShipRender(BaseScreen):
|
|||||||
print(e)
|
print(e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def gen_sprite(self, each_count: int = 100) -> Generator:
|
def load_textures(self):
|
||||||
|
"""
|
||||||
|
初始化纹理加载
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self.textures = SR1Textures()
|
||||||
|
|
||||||
|
def gen_sprite(self, part_datas: Dict[int, SR1PartData], each_count: int = 100) -> Generator:
|
||||||
"""
|
"""
|
||||||
生成 sprite
|
生成 sprite
|
||||||
通过生成器减少一次性渲染的压力
|
通过生成器减少一次性渲染的压力
|
||||||
|
:param part_datas: 所有的部件数据
|
||||||
:param each_count: 每次生成的数量 (默认 100) (过大会导致卡顿)
|
:param each_count: 每次生成的数量 (默认 100) (过大会导致卡顿)
|
||||||
:return: 生成器
|
:return: 生成器
|
||||||
"""
|
"""
|
||||||
count = 0
|
count = 0
|
||||||
self.drawing = True
|
self.drawing = True
|
||||||
# rust 渲染
|
for part_id, part in part_datas.items():
|
||||||
if DR_mod_runtime.use_DR_rust:
|
# 下面就是调用 pyglet 去渲染的部分
|
||||||
cache = self.rust_ship.as_dict()
|
# render_scale = DR_status.gui_scale # 这个是 DR 的缩放比例 可以调节的
|
||||||
for p_id, parts in cache.items():
|
# 在不缩放的情况下,XML的1个单位长度对应60个像素
|
||||||
p_id: int
|
render_x = part.x * 60
|
||||||
parts: List[Tuple[SR1PartType_rs, SR1PartData_rs]]
|
render_y = part.y * 60
|
||||||
part_group = Group(2, parent=self.part_group)
|
cache_sprite = Sprite(img=self.textures.get_texture(part.textures),
|
||||||
batch = []
|
x=render_x, y=render_y, z=random.random(),
|
||||||
for p_type, p_data in parts:
|
batch=self.main_batch, group=self.part_group)
|
||||||
part_sprite = Sprite(img=self.textures.get_texture(map_ptype_textures(p_data.part_type_id)),
|
# 你得帮我换算一下 XML 里的 x y 和这里的屏幕像素的关系(OK
|
||||||
x=p_data.x * 60, y=p_data.y * 60, z=random.random(),
|
# 旋转啥的不是大问题, 我找你要那个渲染代码就是要 x y 的换算逻辑
|
||||||
batch=self.main_batch, group=part_group)
|
cache_sprite.rotation = SR1Rotation.get_rotation(part.angle)
|
||||||
part_sprite.rotation = p_data.angle_r
|
if part.flip_x:
|
||||||
part_sprite.scale_x = -1 if p_data.flip_x else 1
|
cache_sprite.scale_x = -1
|
||||||
part_sprite.scale_y = -1 if p_data.flip_y else 1
|
if part.flip_y:
|
||||||
|
cache_sprite.scale_y = -1
|
||||||
|
self.parts_sprite[part.id] = cache_sprite
|
||||||
|
|
||||||
batch.append(part_sprite)
|
if DR_mod_runtime.use_DR_rust:
|
||||||
line_box_group = Group(6, parent=self.part_group)
|
line_box_group = Group(6, parent=self.part_group)
|
||||||
part_debug_box = self.rust_ship.get_part_box(p_id)
|
part_debug_box = self.rust_ship.get_part_box(part.id)
|
||||||
if part_debug_box:
|
if part_debug_box:
|
||||||
# 线框
|
# 线框
|
||||||
part_line_box = []
|
part_line_box = []
|
||||||
@ -181,17 +217,17 @@ class SR1ShipRender(BaseScreen):
|
|||||||
part_line_box.append(Line(x=part_debug_box[1][0] * 30, y=part_debug_box[0][1] * 30,
|
part_line_box.append(Line(x=part_debug_box[1][0] * 30, y=part_debug_box[0][1] * 30,
|
||||||
x2=part_debug_box[0][0] * 30, y2=part_debug_box[0][1] * 30,
|
x2=part_debug_box[0][0] * 30, y2=part_debug_box[0][1] * 30,
|
||||||
batch=self.main_batch, width=width, color=color, group=line_box_group))
|
batch=self.main_batch, width=width, color=color, group=line_box_group))
|
||||||
self.part_line_box[p_id] = part_line_box
|
self.part_line_box[part.id] = part_line_box
|
||||||
self.parts_sprite[p_id] = batch
|
count += 1
|
||||||
count += 1
|
if count >= each_count:
|
||||||
if count >= each_count:
|
count = 0
|
||||||
count = 0
|
yield count
|
||||||
yield
|
if DR_mod_runtime.use_DR_rust:
|
||||||
connect_line_group = Group(7, parent=self.part_group)
|
connect_line_group = Group(7, parent=self.part_group)
|
||||||
for connect in self.rust_ship.connection:
|
for connect in self.rust_ship.connection:
|
||||||
# 连接线
|
# 连接线
|
||||||
parent_part_data = cache[connect[2]][0][1]
|
parent_part_data = self.part_data[connect[2]]
|
||||||
child_part_data = cache[connect[3]][0][1]
|
child_part_data = self.part_data[connect[3]]
|
||||||
color = (random.randrange(100, 255), random.randrange(0, 255), random.randrange(0, 255), 255)
|
color = (random.randrange(100, 255), random.randrange(0, 255), random.randrange(0, 255), 255)
|
||||||
self.part_line_list.append(Line(x=parent_part_data.x * 60, y=parent_part_data.y * 60,
|
self.part_line_list.append(Line(x=parent_part_data.x * 60, y=parent_part_data.y * 60,
|
||||||
x2=child_part_data.x * 60, y2=child_part_data.y * 60,
|
x2=child_part_data.x * 60, y2=child_part_data.y * 60,
|
||||||
@ -201,31 +237,6 @@ class SR1ShipRender(BaseScreen):
|
|||||||
if count >= each_count * 3:
|
if count >= each_count * 3:
|
||||||
count = 0
|
count = 0
|
||||||
yield count
|
yield count
|
||||||
|
|
||||||
# python 渲染
|
|
||||||
# for part_id, part in part_datas.items():
|
|
||||||
# # 下面就是调用 pyglet 去渲染的部分
|
|
||||||
# # render_scale = DR_status.gui_scale # 这个是 DR 的缩放比例 可以调节的
|
|
||||||
# # 在不缩放的情况下,XML的1个单位长度对应60个像素
|
|
||||||
# # render_x = part.x * 60
|
|
||||||
# # render_y = part.y * 60
|
|
||||||
# # cache_sprite = Sprite(img=self.textures.get_texture(part.textures),
|
|
||||||
# # x=render_x, y=render_y, z=random.random(),
|
|
||||||
# # batch=self.main_batch, group=self.part_group)
|
|
||||||
# # # 你得帮我换算一下 XML 里的 x y 和这里的屏幕像素的关系
|
|
||||||
# # # 旋转啥的不是大问题, 我找你要那个渲染代码就是要 x y 的换算逻辑
|
|
||||||
# # cache_sprite.rotation = SR1Rotation.get_rotation(part.angle)
|
|
||||||
# # if part.flip_x:
|
|
||||||
# # cache_sprite.scale_x = -1
|
|
||||||
# # if part.flip_y:
|
|
||||||
# # cache_sprite.scale_y = -1
|
|
||||||
# # self.parts_sprite[part.id] = cache_sprite
|
|
||||||
#
|
|
||||||
# if DR_mod_runtime.use_DR_rust:
|
|
||||||
# count += 1
|
|
||||||
# if count >= each_count:
|
|
||||||
# count = 0
|
|
||||||
# yield count
|
|
||||||
self.drawing = False
|
self.drawing = False
|
||||||
raise GeneratorExit
|
raise GeneratorExit
|
||||||
|
|
||||||
@ -233,28 +244,40 @@ class SR1ShipRender(BaseScreen):
|
|||||||
"""
|
"""
|
||||||
渲染船
|
渲染船
|
||||||
"""
|
"""
|
||||||
logger.info(sr_tr().sr1.ship.ship.load().format(self.ship_name))
|
if self.textures is None:
|
||||||
|
self.load_textures()
|
||||||
|
logger.info(sr_tr().sr1.ship.ship.load().format(self.xml_name))
|
||||||
start_time = time.perf_counter_ns()
|
start_time = time.perf_counter_ns()
|
||||||
|
self.part_data: Dict[int, SR1PartData] = {}
|
||||||
self.parts_sprite: Dict[int, Sprite] = {}
|
self.parts_sprite: Dict[int, Sprite] = {}
|
||||||
self.part_line_box = {}
|
self.part_line_box = {}
|
||||||
self.part_line_list = []
|
self.part_line_list = []
|
||||||
# self.camera.zoom = 1.0
|
self.camera.zoom = 1.0
|
||||||
# self.camera.dx = 0
|
self.camera.dx = 0
|
||||||
# self.camera.dy = 0
|
self.camera.dy = 0
|
||||||
|
parts = self.xml_root.find('Parts')
|
||||||
|
for part_xml in parts:
|
||||||
|
if part_xml.tag != 'Part':
|
||||||
|
continue # 如果不是部件,则跳过
|
||||||
|
part = get_sr1_part(part_xml)
|
||||||
|
if part.id in self.part_data:
|
||||||
|
print(f'hey! warning! id{part.id}')
|
||||||
|
self.part_data[part.id] = part
|
||||||
# 调用生成器 减少卡顿
|
# 调用生成器 减少卡顿
|
||||||
try:
|
try:
|
||||||
self.gen_draw = self.gen_sprite()
|
self.gen_draw = self.gen_sprite(self.part_data)
|
||||||
next(self.gen_draw)
|
next(self.gen_draw)
|
||||||
except (GeneratorExit, StopIteration):
|
except GeneratorExit:
|
||||||
self.drawing = False
|
self.drawing = False
|
||||||
self.need_draw = False
|
self.need_draw = False
|
||||||
full_mass = 0
|
full_mass = 0
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
full_mass = self.rust_ship.mass
|
for part in self.part_data:
|
||||||
|
full_mass += self.part_list_rs.get_part_type(self.part_data[part].p_type).mass * 500
|
||||||
logger.info(sr_tr().sr1.ship.ship.load_time().format(
|
logger.info(sr_tr().sr1.ship.ship.load_time().format(
|
||||||
(time.perf_counter_ns() - start_time) / 1000000000))
|
(time.perf_counter_ns() - start_time) / 1000000000))
|
||||||
logger.info(sr_tr().sr1.ship.ship.info().format(
|
logger.info(sr_tr().sr1.ship.ship.info().format(
|
||||||
len(self.rust_ship.as_list()), f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else sr_tr().game.require_DR_rs()))
|
len(self.part_data), f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else sr_tr().game.require_DR_rs()))
|
||||||
self.rendered = True
|
self.rendered = True
|
||||||
|
|
||||||
def draw_batch(self, window: "ClientWindow"):
|
def draw_batch(self, window: "ClientWindow"):
|
||||||
@ -276,7 +299,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
if self.drawing:
|
if self.drawing:
|
||||||
try:
|
try:
|
||||||
next(self.gen_draw)
|
next(self.gen_draw)
|
||||||
except (GeneratorExit, StopIteration):
|
except GeneratorExit:
|
||||||
self.drawing = False
|
self.drawing = False
|
||||||
self.logger.info(sr_tr().sr1.ship.ship.render.done())
|
self.logger.info(sr_tr().sr1.ship.ship.render.done())
|
||||||
|
|
||||||
|
@ -33,8 +33,10 @@ class SR1PartData:
|
|||||||
|
|
||||||
class SR1Textures(Options):
|
class SR1Textures(Options):
|
||||||
""" 存储 sr1 的材质 img """
|
""" 存储 sr1 的材质 img """
|
||||||
def load_file(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
for image_name in self.flush_option():
|
super().__init__(**kwargs)
|
||||||
|
self.flush_option()
|
||||||
|
for image_name in self.cached_options:
|
||||||
img = load(f'assets/textures/parts/{image_name}.png')
|
img = load(f'assets/textures/parts/{image_name}.png')
|
||||||
img.anchor_x = img.width // 2
|
img.anchor_x = img.width // 2
|
||||||
img.anchor_y = img.height // 2
|
img.anchor_y = img.height // 2
|
||||||
@ -47,14 +49,8 @@ class SR1Textures(Options):
|
|||||||
:param name:
|
:param name:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if name in self.cached_options:
|
assert name in self.cached_options
|
||||||
return self.cached_options.get(name)
|
return self.cached_options.get(name)
|
||||||
else:
|
|
||||||
img = load(f'assets/textures/parts/{name}.png')
|
|
||||||
img.anchor_x = img.width // 2
|
|
||||||
img.anchor_y = img.height // 2
|
|
||||||
setattr(self, name, img)
|
|
||||||
return img
|
|
||||||
|
|
||||||
Battery: AbstractImage = None
|
Battery: AbstractImage = None
|
||||||
Beam: AbstractImage = None
|
Beam: AbstractImage = None
|
||||||
@ -138,11 +134,6 @@ class SR1Rotation(Options):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_rotation(cls, radian: float) -> float:
|
def get_rotation(cls, radian: float) -> float:
|
||||||
"""
|
|
||||||
实际上就是将弧度转换为角度 (同时自带一个映射表)
|
|
||||||
:param radian:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if radian in cls.radian_angle_map:
|
if radian in cls.radian_angle_map:
|
||||||
return cls.radian_angle_map[radian]
|
return cls.radian_angle_map[radian]
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user