From: Lizzy Fleckenstein Date: Tue, 14 Feb 2023 15:17:20 +0000 (+0100) Subject: Implement NodeMeta and add Inventory stub X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=6c1870c9405a80cb9f08e7fbb2db0b504522e1b2;hp=3cb97b94d3e3d83fbbbefde9c0a40cdd27ea5416;p=mt_net.git Implement NodeMeta and add Inventory stub --- diff --git a/Cargo.toml b/Cargo.toml index 10a512e..eb9d99c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,17 +5,17 @@ edition = "2021" [features] all = ["client", "server", "random", "serde"] -test = ["client", "server", "random"] client = [] random = ["dep:generate-random", "dep:rand"] serde = ["dep:serde", "dep:serde_arrays", "enumset/serde"] server = [] +test = ["client", "server", "random"] [dependencies] -mt_ser = { git = "https://github.com/minetest-rust/mt_ser" } -#mt_ser = { path = "../mt_ser" } enumset = { git = "https://github.com/Lymia/enumset" } generate-random = { git = "https://github.com/minetest-rust/generate-random", features = ["enumset"], optional = true } +mt_ser = { git = "https://github.com/minetest-rust/mt_ser" } +#mt_ser = { path = "../mt_ser" } rand = { version = "0.8.5", optional = true } serde = { version = "1.0.152", features = ["derive"], optional = true } serde_arrays = { version = "0.1.0", optional = true } @@ -24,6 +24,6 @@ serde_arrays = { version = "0.1.0", optional = true } libtest-mimic = "0.6.0" [[test]] +harness = false name = "random" path = "tests/random.rs" -harness = false diff --git a/src/to_clt.rs b/src/to_clt.rs index 9aa9196..9848dae 100644 --- a/src/to_clt.rs +++ b/src/to_clt.rs @@ -18,19 +18,53 @@ pub enum ModChanSig { SetState, } -mod chat; -mod env; +#[mt_derive(to = "clt", repr = "u32", enumset)] +pub enum AuthMethod { + LegacyPasswd, + Srp, + FirstSrp, +} + +#[mt_derive(to = "clt", repr = "u64", enumset)] +pub enum CsmRestrictionFlag { + NoCsms, + NoChatMsgs, + NoItemDefs, + NoNodeDefs, + LimitMapRange, + NoPlayerList, +} + +#[mt_derive(to = "clt", repr = "u8")] +pub enum ChatMsgType { + Raw = 0, + Normal, + Announce, + System, +} + +#[mt_derive(to = "clt", repr = "u8")] +pub enum PlayerListUpdateType { + Init = 0, + Add, + Remove, +} + mod hud; +mod inv; +mod kick; +mod map; mod media; +mod obj; mod sky; -mod status; -pub use chat::*; -pub use env::*; pub use hud::*; +pub use inv::*; +pub use kick::*; +pub use map::*; pub use media::*; +pub use obj::*; pub use sky::*; -pub use status::*; #[mt_derive(to = "clt", repr = "u16", tag = "type", content = "data")] pub enum ToCltPkt { @@ -69,6 +103,7 @@ pub enum ToCltPkt { pos: [i16; 3], } = 34, Inv { + #[mt(len = "()")] inv: String, } = 39, TimeOfDay { @@ -297,7 +332,8 @@ pub enum ToCltPkt { channel: String, } = 88, NodeMetasChanged { - #[mt(size = "u32")] + #[mt(size = "u32", zlib)] + #[mt(len = "NodeMetasLen")] changed: HashMap<[i16; 3], NodeMeta>, } = 89, SunParams(SunParams) = 90, diff --git a/src/to_clt/chat.rs b/src/to_clt/chat.rs deleted file mode 100644 index 4d99853..0000000 --- a/src/to_clt/chat.rs +++ /dev/null @@ -1,16 +0,0 @@ -use super::*; - -#[mt_derive(to = "clt", repr = "u8")] -pub enum ChatMsgType { - Raw = 0, - Normal, - Announce, - System, -} - -#[mt_derive(to = "clt", repr = "u8")] -pub enum PlayerListUpdateType { - Init = 0, - Add, - Remove, -} diff --git a/src/to_clt/env.rs b/src/to_clt/env.rs deleted file mode 100644 index ecd3db3..0000000 --- a/src/to_clt/env.rs +++ /dev/null @@ -1,198 +0,0 @@ -use super::*; - -#[mt_derive(to = "clt", repr = "str")] -pub enum ObjVisual { - Cube, - Sprite, - UprightSprite, - Mesh, - Wielditem, - Item, -} - -#[mt_derive(to = "clt")] -pub struct ObjProps { - #[mt(const_before = "4u8")] // version - pub max_hp: u16, // player only - pub collide_with_nodes: bool, - pub weight: f32, // deprecated - pub collision_box: ([f32; 3], [f32; 3]), - pub selection_box: ([f32; 3], [f32; 3]), - pub pointable: bool, - pub visual: ObjVisual, - pub visual_size: [f32; 3], - pub textures: Vec, - pub sprite_sheet_size: [i16; 2], // in sprites - pub sprite_pos: [i16; 2], // in sprite sheet - pub visible: bool, - pub make_footstep_sounds: bool, - pub rotate_speed: f32, // in radians per second - pub mesh: String, - pub colors: Vec, - pub collide_with_objs: bool, - pub step_height: f32, - pub face_rotate_dir: bool, - pub face_rotate_dir_off: f32, // in degrees - pub backface_cull: bool, - pub nametag: String, - pub nametag_color: Color, - pub face_rotate_speed: f32, // in degrees per second - pub infotext: String, - pub itemstring: String, - pub glow: i8, - pub max_breath: u16, // player only - pub eye_height: f32, // player only - pub zoom_fov: f32, // in degrees. player only - pub use_texture_alpha: bool, - pub dmg_texture_mod: String, // suffix - pub shaded: bool, - pub show_on_minimap: bool, - pub nametag_bg: Color, -} - -#[mt_derive(to = "clt")] -pub struct ObjPos { - pub pos: [f32; 3], - pub vel: [f32; 3], - pub acc: [f32; 3], - pub rot: [f32; 3], - pub interpolate: bool, - pub end: bool, - pub update_interval: f32, -} - -#[mt_derive(to = "clt")] -pub struct ObjSprite { - pub frame0: [i16; 2], - pub frames: u16, - pub frame_duration: f32, - pub view_angle_frames: bool, -} - -#[mt_derive(to = "clt")] -pub struct ObjAnim { - pub frames: [i32; 2], - pub speed: f32, - pub blend: f32, - pub no_loop: bool, -} - -#[mt_derive(to = "clt")] -pub struct ObjBonePos { - pub pos: [f32; 3], - pub rot: [f32; 3], -} - -#[mt_derive(to = "clt")] -pub struct ObjAttach { - pub parent_id: u16, - pub bone: String, - pub pos: [f32; 3], - pub rot: [f32; 3], - pub force_visible: bool, -} - -#[mt_derive(to = "clt")] -pub struct ObjPhysicsOverride { - pub walk: f32, - pub jump: f32, - pub gravity: f32, - // the following are player only - pub no_sneak: bool, - pub no_sneak_glitch: bool, - pub old_sneak: bool, -} - -pub const GENERIC_CAO: u8 = 101; - -#[mt_derive(to = "clt", repr = "u8", tag = "type", content = "data")] -pub enum ObjMsg { - Props(ObjProps) = 0, - Pos(ObjPos), - TextureMod { - #[serde(rename = "mod")] - texture_mod: String, - }, - Sprite(ObjSprite), - Hp { - hp: u16, - }, - ArmorGroups { - armor: HashMap, - }, - Anim(ObjAnim), - BonePos { - bone: String, - pos: ObjBonePos, - }, - Attach(ObjAttach), - PhysicsOverride(ObjPhysicsOverride), - SpawnInfant { - #[mt(const_after = "GENERIC_CAO")] - id: u16, - } = 11, - AnimSpeed { - speed: f32, - }, -} - -#[mt_derive(to = "clt")] -pub struct ObjIdMsg { - pub id: u16, - #[mt(size = "u16")] - pub msg: ObjMsg, -} - -#[mt_derive(to = "clt")] -pub struct ObjInitMsg(#[mt(size = "u32")] pub ObjMsg); - -#[mt_derive(to = "clt")] -pub struct ObjInitData { - #[mt(const_before = "1u8")] // version - pub name: String, - pub is_player: bool, - pub id: u16, - pub pos: [f32; 3], - pub rot: [f32; 3], - pub hp: u16, - #[mt(len = "u8")] - pub msgs: Vec, -} - -#[mt_derive(to = "clt")] -pub struct ObjAdd { - pub id: u16, - #[mt(const_before = "GENERIC_CAO")] - #[mt(size = "u32")] - pub init_data: ObjInitData, -} - -#[mt_derive(to = "clt", repr = "u8", enumset)] -pub enum MapBlockFlag { - IsUnderground = 0, - DayNightDiff, - LightExpired, - NotGenerated, -} - -pub const ALWAYS_LIT_FROM: u16 = 0xf000; - -pub const CONTENT_UNKNOWN: u16 = 125; -pub const CONTENT_AIR: u16 = 126; -pub const CONTENT_IGNORE: u16 = 127; - -#[mt_derive(to = "clt")] -pub struct MapBlock { - pub flags: EnumSet, - pub lit_from: u16, - #[mt(const_before = "2u8")] // param0 size - #[mt(const_before = "2u8")] // param1 size + param2 size - #[serde(with = "serde_arrays")] - pub param_0: [u16; 4096], - #[serde(with = "serde_arrays")] - pub param_1: [u8; 4096], - #[serde(with = "serde_arrays")] - pub param_2: [u8; 4096], - #[mt(const_after = "2u8")] // version - pub node_metas: HashMap, -} diff --git a/src/to_clt/inv.rs b/src/to_clt/inv.rs new file mode 100644 index 0000000..2ada0a1 --- /dev/null +++ b/src/to_clt/inv.rs @@ -0,0 +1,37 @@ +use super::*; +use mt_ser::{DeserializeError, SerializeError}; +use std::io::{Read, Write}; + +#[mt_derive(to = "clt", custom)] +pub struct Inventory; // TODO + +#[cfg(feature = "server")] +impl MtSerialize for Inventory { + fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { + "EndInventory\n".mt_serialize::<()>(writer) + } +} + +fn read_line(reader: &mut impl Read) -> Result { + let utf8 = mt_ser::mt_deserialize_seq::<(), u8>(reader)? + .map_while(|x| match x { + Ok(0x0A) => None, + x => Some(x), + }) + .try_collect::>()?; + + String::from_utf8(utf8) + .map_err(|e| DeserializeError::Other(format!("Invalid UTF-8: {e}").into())) +} + +#[cfg(feature = "client")] +impl MtDeserialize for Inventory { + fn mt_deserialize(reader: &mut impl Read) -> Result { + loop { + match read_line(reader)?.as_str() { + "EndInventory" => return Ok(Self), + _ => {} + } + } + } +} diff --git a/src/to_clt/kick.rs b/src/to_clt/kick.rs new file mode 100644 index 0000000..6389df6 --- /dev/null +++ b/src/to_clt/kick.rs @@ -0,0 +1,63 @@ +use super::*; + +#[mt_derive(to = "clt", repr = "u8", tag = "reason")] +pub enum KickReason { + WrongPasswd, + UnexpectedData, + SrvIsSingleplayer, + UnsupportedVersion, + BadNameChars, + BadName, + TooManyClts, + EmptyPasswd, + AlreadyConnected, + SrvErr, + Custom { custom: String }, + Shutdown { custom: String, reconnect: bool }, + Crash { custom: String, reconnect: bool }, +} + +impl KickReason { + pub fn reconnect(&self) -> bool { + use KickReason::*; + + match self { + Shutdown { reconnect, .. } | Crash { reconnect, .. } => *reconnect, + _ => false, + } + } +} + +impl fmt::Display for KickReason { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use KickReason::*; + + match self { + WrongPasswd => write!(f, "wrong password"), + UnexpectedData => write!(f, "unexpected data"), + SrvIsSingleplayer => write!(f, "server is singleplayer"), + UnsupportedVersion => write!(f, "unsupported client version"), + BadNameChars => write!(f, "disallowed character(s) in player name"), + BadName => write!(f, "disallowed player name"), + TooManyClts => write!(f, "too many clients"), + EmptyPasswd => write!(f, "empty password"), + AlreadyConnected => write!(f, "another client is already connected with the same name"), + SrvErr => write!(f, "unsupported client version"), + Custom { custom } => write!(f, "{custom}"), + Shutdown { custom, .. } => { + if custom.is_empty() { + write!(f, "server shutdown") + } else { + write!(f, "server shutdown: {custom}") + } + } + Crash { custom, .. } => { + if custom.is_empty() { + write!(f, "server crash") + } else { + write!(f, "server crash: {custom}") + } + } + } + } +} diff --git a/src/to_clt/map.rs b/src/to_clt/map.rs new file mode 100644 index 0000000..296a23f --- /dev/null +++ b/src/to_clt/map.rs @@ -0,0 +1,71 @@ +use super::*; +use mt_ser::{DeserializeError, SerializeError}; + +#[mt_derive(to = "clt", repr = "u8", enumset)] +pub enum MapBlockFlag { + IsUnderground = 0, + DayNightDiff, + LightExpired, + NotGenerated, +} + +pub const ALWAYS_LIT_FROM: u16 = 0xf000; + +pub const CONTENT_UNKNOWN: u16 = 125; +pub const CONTENT_AIR: u16 = 126; +pub const CONTENT_IGNORE: u16 = 127; + +#[mt_derive(to = "clt")] +pub struct NodeMetaField { + #[mt(len = "u32")] + value: String, + private: bool, +} + +#[mt_derive(to = "clt")] +pub struct NodeMeta { + #[mt(len = "u32")] + fields: HashMap, + inv: Inventory, +} + +#[derive(Debug)] +pub struct NodeMetasLen; + +impl MtCfg for NodeMetasLen { + type Len = ::Len; + type Inner = ::Inner; + + fn write_len(len: usize, writer: &mut impl std::io::Write) -> Result<(), SerializeError> { + if len == 0 { + 0u8.mt_serialize::(writer) + } else { + 2u8.mt_serialize::(writer)?; + DefCfg::write_len(len, writer) + } + } + + fn read_len(reader: &mut impl std::io::Read) -> Result { + match u8::mt_deserialize::(reader)? { + 0 => Ok(0), + 2 => DefCfg::read_len(reader), + x => Err(DeserializeError::InvalidEnum("NodeMetasLen", Box::new(x))), + } + } +} + +#[mt_derive(to = "clt")] +pub struct MapBlock { + pub flags: EnumSet, + pub lit_from: u16, + #[mt(const_before = "2u8")] // param0 size + #[mt(const_before = "2u8")] // param1 size + param2 size + #[serde(with = "serde_arrays")] + pub param_0: [u16; 4096], + #[serde(with = "serde_arrays")] + pub param_1: [u8; 4096], + #[serde(with = "serde_arrays")] + pub param_2: [u8; 4096], + #[mt(len = "NodeMetasLen")] + pub metas: HashMap, +} diff --git a/src/to_clt/media.rs b/src/to_clt/media.rs index 50c709f..2cd516b 100644 --- a/src/to_clt/media.rs +++ b/src/to_clt/media.rs @@ -9,9 +9,6 @@ pub struct ItemDef; // TODO #[mt_derive(to = "clt")] pub struct NodeDef; // TODO -#[mt_derive(to = "clt")] -pub struct NodeMeta; // TODO - #[mt_derive(to = "clt", repr = "u8")] pub enum SoundSrcType { Nowhere = 0, diff --git a/src/to_clt/obj.rs b/src/to_clt/obj.rs new file mode 100644 index 0000000..9e88fff --- /dev/null +++ b/src/to_clt/obj.rs @@ -0,0 +1,168 @@ +use super::*; + +#[mt_derive(to = "clt", repr = "str")] +pub enum ObjVisual { + Cube, + Sprite, + UprightSprite, + Mesh, + Wielditem, + Item, +} + +#[mt_derive(to = "clt")] +pub struct ObjProps { + #[mt(const_before = "4u8")] // version + pub max_hp: u16, // player only + pub collide_with_nodes: bool, + pub weight: f32, // deprecated + pub collision_box: ([f32; 3], [f32; 3]), + pub selection_box: ([f32; 3], [f32; 3]), + pub pointable: bool, + pub visual: ObjVisual, + pub visual_size: [f32; 3], + pub textures: Vec, + pub sprite_sheet_size: [i16; 2], // in sprites + pub sprite_pos: [i16; 2], // in sprite sheet + pub visible: bool, + pub make_footstep_sounds: bool, + pub rotate_speed: f32, // in radians per second + pub mesh: String, + pub colors: Vec, + pub collide_with_objs: bool, + pub step_height: f32, + pub face_rotate_dir: bool, + pub face_rotate_dir_off: f32, // in degrees + pub backface_cull: bool, + pub nametag: String, + pub nametag_color: Color, + pub face_rotate_speed: f32, // in degrees per second + pub infotext: String, + pub itemstring: String, + pub glow: i8, + pub max_breath: u16, // player only + pub eye_height: f32, // player only + pub zoom_fov: f32, // in degrees. player only + pub use_texture_alpha: bool, + pub dmg_texture_mod: String, // suffix + pub shaded: bool, + pub show_on_minimap: bool, + pub nametag_bg: Color, +} + +#[mt_derive(to = "clt")] +pub struct ObjPos { + pub pos: [f32; 3], + pub vel: [f32; 3], + pub acc: [f32; 3], + pub rot: [f32; 3], + pub interpolate: bool, + pub end: bool, + pub update_interval: f32, +} + +#[mt_derive(to = "clt")] +pub struct ObjSprite { + pub frame0: [i16; 2], + pub frames: u16, + pub frame_duration: f32, + pub view_angle_frames: bool, +} + +#[mt_derive(to = "clt")] +pub struct ObjAnim { + pub frames: [i32; 2], + pub speed: f32, + pub blend: f32, + pub no_loop: bool, +} + +#[mt_derive(to = "clt")] +pub struct ObjBonePos { + pub pos: [f32; 3], + pub rot: [f32; 3], +} + +#[mt_derive(to = "clt")] +pub struct ObjAttach { + pub parent_id: u16, + pub bone: String, + pub pos: [f32; 3], + pub rot: [f32; 3], + pub force_visible: bool, +} + +#[mt_derive(to = "clt")] +pub struct ObjPhysicsOverride { + pub walk: f32, + pub jump: f32, + pub gravity: f32, + // the following are player only + pub no_sneak: bool, + pub no_sneak_glitch: bool, + pub old_sneak: bool, +} + +pub const GENERIC_CAO: u8 = 101; + +#[mt_derive(to = "clt", repr = "u8", tag = "type", content = "data")] +pub enum ObjMsg { + Props(Box) = 0, + Pos(ObjPos), + TextureMod { + #[serde(rename = "mod")] + texture_mod: String, + }, + Sprite(ObjSprite), + Hp { + hp: u16, + }, + ArmorGroups { + armor: HashMap, + }, + Anim(ObjAnim), + BonePos { + bone: String, + pos: ObjBonePos, + }, + Attach(ObjAttach), + PhysicsOverride(ObjPhysicsOverride), + SpawnInfant { + #[mt(const_after = "GENERIC_CAO")] + id: u16, + } = 11, + AnimSpeed { + speed: f32, + }, +} + +#[mt_derive(to = "clt")] +pub struct ObjIdMsg { + pub id: u16, + #[mt(size = "u16")] + pub msg: ObjMsg, +} + +#[mt_derive(to = "clt")] +pub struct ObjInitMsg(#[mt(size = "u32")] pub ObjMsg); + +#[mt_derive(to = "clt")] +pub struct ObjInitData { + #[mt(const_before = "1u8")] // version + pub name: String, + pub is_player: bool, + pub id: u16, + pub pos: [f32; 3], + pub rot: [f32; 3], + pub hp: u16, + #[mt(len = "u8")] + pub msgs: Vec, +} + +#[mt_derive(to = "clt")] +pub struct ObjAdd { + pub id: u16, + #[mt(const_before = "GENERIC_CAO")] + #[mt(size = "u32")] + pub init_data: ObjInitData, +} diff --git a/src/to_clt/status.rs b/src/to_clt/status.rs deleted file mode 100644 index 54adb45..0000000 --- a/src/to_clt/status.rs +++ /dev/null @@ -1,80 +0,0 @@ -use super::*; - -#[mt_derive(to = "clt", repr = "u8", tag = "reason")] -pub enum KickReason { - WrongPasswd, - UnexpectedData, - SrvIsSingleplayer, - UnsupportedVersion, - BadNameChars, - BadName, - TooManyClts, - EmptyPasswd, - AlreadyConnected, - SrvErr, - Custom { custom: String }, - Shutdown { custom: String, reconnect: bool }, - Crash { custom: String, reconnect: bool }, -} - -impl KickReason { - pub fn reconnect(&self) -> bool { - use KickReason::*; - - match self { - Shutdown { reconnect, .. } | Crash { reconnect, .. } => *reconnect, - _ => false, - } - } -} - -impl fmt::Display for KickReason { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use KickReason::*; - - match self { - WrongPasswd => write!(f, "wrong password"), - UnexpectedData => write!(f, "unexpected data"), - SrvIsSingleplayer => write!(f, "server is singleplayer"), - UnsupportedVersion => write!(f, "unsupported client version"), - BadNameChars => write!(f, "disallowed character(s) in player name"), - BadName => write!(f, "disallowed player name"), - TooManyClts => write!(f, "too many clients"), - EmptyPasswd => write!(f, "empty password"), - AlreadyConnected => write!(f, "another client is already connected with the same name"), - SrvErr => write!(f, "unsupported client version"), - Custom { custom } => write!(f, "{custom}"), - Shutdown { custom, .. } => { - if custom.is_empty() { - write!(f, "server shutdown") - } else { - write!(f, "server shutdown: {custom}") - } - } - Crash { custom, .. } => { - if custom.is_empty() { - write!(f, "server crash") - } else { - write!(f, "server crash: {custom}") - } - } - } - } -} - -#[mt_derive(to = "clt", repr = "u32", enumset)] -pub enum AuthMethod { - LegacyPasswd, - Srp, - FirstSrp, -} - -#[mt_derive(to = "clt", repr = "u64", enumset)] -pub enum CsmRestrictionFlag { - NoCsms, - NoChatMsgs, - NoItemDefs, - NoNodeDefs, - LimitMapRange, - NoPlayerList, -}