[package]
-name = "mt_data"
+name = "mt_ser"
version = "0.1.0"
edition = "2021"
-[features]
-all = ["client", "server", "random", "serde"]
-client = []
-random = ["dep:generate-random", "dep:rand"]
-serde = ["dep:serde", "dep:serde_arrays", "enumset/serde"]
-server = []
-
[dependencies]
byteorder = "1.4.3"
enumset = { git = "https://github.com/Lymia/enumset" }
flate2 = { version = "1.0.25", features = ["zlib"], default-features = false }
-generate-random = { git = "https://github.com/minetest-rust/generate-random", features = ["enumset"], optional = true }
-mt_data_derive = { path = "derive" }
+mt_ser_derive = { path = "derive" }
paste = "1.0.11"
-rand = { version = "0.8.5", optional = true }
-serde = { version = "1.0.152", features = ["derive"], optional = true }
-serde_arrays = { version = "0.1.0", optional = true }
thiserror = "1.0.38"
[package]
-name = "mt_data_derive"
+name = "mt_ser_derive"
version = "0.1.0"
edition = "2021"
}
fn wrap_attr(attr: &mut syn::Attribute) {
+ let path = attr.path.clone();
+ let tokens = attr.tokens.clone();
+
match attr.path.get_ident().map(|i| i.to_string()).as_deref() {
Some("mt") => {
- let path = attr.path.clone();
- let tokens = attr.tokens.clone();
-
*attr = parse_quote! {
#[cfg_attr(any(feature = "client", feature = "server"), #path #tokens)]
};
}
Some("serde") => {
- let path = attr.path.clone();
- let tokens = attr.tokens.clone();
-
*attr = parse_quote! {
#[cfg_attr(feature = "serde", #path #tokens)]
};
len64: bool,
utf16: bool,
zlib: bool,
- zstd: bool,
+ zstd: bool, // TODO
default: bool,
}
fn get_cfg(args: &MtArgs) -> syn::Type {
- let mut ty: syn::Type = parse_quote! { mt_data::DefCfg };
+ let mut ty: syn::Type = parse_quote! { mt_ser::DefCfg };
if args.len0 {
- ty = parse_quote! { mt_data::NoLen };
+ ty = parse_quote! { () };
}
macro_rules! impl_len {
impl_len!(len64, u64);
if args.utf16 {
- ty = parse_quote! { mt_data::Utf16<#ty> };
+ ty = parse_quote! { mt_ser::Utf16<#ty> };
}
ty
}
-/*
-fn is_ident(path: &syn::Path, ident: &str) -> bool {
- matches!(path.segments.first().map(|p| &p.ident), Some(idt) if idt == ident)
-}
-
-fn get_type_generics<const N: usize>(path: &syn::Path) -> Option<[&syn::Type; N]> {
- use syn::{AngleBracketedGenericArguments as Args, PathArguments::AngleBracketed};
-
- path.segments
- .first()
- .map(|seg| match &seg.arguments {
- AngleBracketed(Args { args, .. }) => args
- .iter()
- .flat_map(|arg| match arg {
- syn::GenericArgument::Type(t) => Some(t),
- _ => None,
- })
- .collect::<Vec<_>>()
- .try_into()
- .ok(),
- _ => None,
- })
- .flatten()
-}
-*/
-
type Fields<'a> = Vec<(TokStr, &'a syn::Field)>;
fn get_fields(fields: &syn::Fields, ident: impl Fn(TokStr) -> TokStr) -> Fields {
($name:ident) => {
if let Some(x) = args.$name {
code.extend(quote! {
- #x.mt_serialize::<mt_data::DefCfg>(__writer)?;
+ #x.mt_serialize::<mt_ser::DefCfg>(__writer)?;
});
}
};
if args.zlib {
code = quote! {
let mut __writer = {
- let mut __stream = mt_data::flate2::write::ZlibEncoder::new(__writer, flate2::Compression::default());
+ let mut __stream = mt_ser::flate2::write::ZlibEncoder::new(
+ __writer,
+ mt_ser::flate2::Compression::default(),
+ );
let __writer = &mut __stream;
#code
__stream.finish()?
($name:ident, $T:ty) => {
if args.$name {
code = quote! {
- mt_data::MtSerialize::mt_serialize::<$T>(&{
+ mt_ser::MtSerialize::mt_serialize::<$T>(&{
let mut __buf = Vec::new();
let __writer = &mut __buf;
#code
.map(|(ident, field)| {
serialize_args(MtArgs::from_field(field), |args| {
let cfg = get_cfg(args);
- quote! { mt_data::MtSerialize::mt_serialize::<#cfg>(#ident, __writer)?; }
+ quote! { mt_ser::MtSerialize::mt_serialize::<#cfg>(#ident, __writer)?; }
})
})
.collect()
let ident_fn = match &v.fields {
syn::Fields::Unnamed(_) => |f| quote! {
- mt_data::paste::paste! { [<field_ #f>] }
+ mt_ser::paste::paste! { [<field_ #f>] }
},
_ => |f| quote! { #f },
};
quote! {
#before
#typename::#variant #destruct => {
- mt_data::MtSerialize::mt_serialize::<mt_data::DefCfg>(&((#discr) as #repr), __writer)?;
+ mt_ser::MtSerialize::mt_serialize::<mt_ser::DefCfg>(&((#discr) as #repr), __writer)?;
#code
}
}
quote! {
#[automatically_derived]
- impl mt_data::MtSerialize for #typename {
- fn mt_serialize<C: MtCfg>(&self, __writer: &mut impl std::io::Write) -> Result<(), mt_data::SerializeError> {
+ impl mt_ser::MtSerialize for #typename {
+ fn mt_serialize<C: mt_ser::MtCfg>(&self, __writer: &mut impl std::io::Write) -> Result<(), mt_ser::SerializeError> {
#code
Ok(())
} = parse_macro_input!(input);
quote! {
#[automatically_derived]
- impl mt_data::MtDeserialize for #typename {
- fn mt_deserialize<C: MtCfg>(__reader: &mut impl std::io::Read) -> Result<Self, mt_data::DeserializeError> {
- Err(mt_data::DeserializeError::Unimplemented)
+ impl mt_ser::MtDeserialize for #typename {
+ fn mt_deserialize<C: mt_ser::MtCfg>(__reader: &mut impl std::io::Read) -> Result<Self, mt_ser::DeserializeError> {
+ Err(mt_ser::DeserializeError::Unimplemented)
}
}
}.into()
#![feature(associated_type_bounds)]
#![feature(iterator_try_collect)]
-pub use enumset;
pub use flate2;
+pub use mt_ser_derive::{mt_derive, MtDeserialize, MtSerialize};
pub use paste;
-#[cfg(feature = "random")]
-pub use generate_random;
-
-#[cfg(feature = "random")]
-pub use rand;
-
-#[cfg(feature = "serde")]
-pub use serde;
-
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
-use enumset::{EnumSet, EnumSetType, EnumSetTypeWithRepr};
-use mt_data_derive::mt_derive;
-pub use mt_data_derive::{MtDeserialize, MtSerialize};
+use enumset::{EnumSet, EnumSetTypeWithRepr};
use paste::paste as paste_macro;
use std::{
collections::{HashMap, HashSet},
convert::Infallible,
- fmt,
io::{self, Read, Write},
num::TryFromIntError,
ops::Deref,
};
use thiserror::Error;
-#[cfg(feature = "serde")]
-use serde::{Deserialize, Serialize};
-
-#[cfg(feature = "random")]
-use generate_random::GenerateRandom;
-
-#[cfg(any(feature = "client", feature = "server"))]
-use crate as mt_data;
+#[cfg(test)]
+mod tests;
#[derive(Error, Debug)]
pub enum SerializeError {
fn or_default(self) -> Self;
}
+pub struct WrapRead<'a, R: Read>(pub &'a mut R);
+impl<'a, R: Read> Read for WrapRead<'a, R> {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ self.0.read(buf)
+ }
+
+ fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
+ self.0.read_vectored(bufs)
+ }
+
+ /*
+
+ fn is_read_vectored(&self) -> bool {
+ self.0.is_read_vectored()
+ }
+
+ */
+
+ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+ self.0.read_to_end(buf)
+ }
+
+ fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
+ self.0.read_to_string(buf)
+ }
+
+ fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+ self.0.read_exact(buf)
+ }
+
+ /*
+
+ fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+ self.0.read_buf(buf)
+ }
+
+ fn read_buf_exact(&mut self, cursor: io::BorrowedCursor<'_>) -> io::Result<()> {
+ self.0.read_buf_exact(cursor)
+ }
+
+ */
+}
+
impl<T: MtDeserialize + Default> OrDefault<T> for Result<T, DeserializeError> {
fn or_default(self) -> Self {
match self {
}
}
-pub trait MtCfg:
- Sized + MtSerialize + MtDeserialize + TryFrom<usize, Error: Into<SerializeError>>
-{
+pub trait MtLen {
+ fn option(&self) -> Option<usize>;
+
type Range: Iterator<Item = usize> + 'static;
+ fn range(&self) -> Self::Range;
+
+ type Take<R: Read>: Read;
+ fn take<R: Read>(&self, reader: R) -> Self::Take<R>;
+}
+
+pub trait MtCfg {
+ type Len: MtLen;
fn utf16() -> bool {
false
}
- fn var_len() -> bool;
+ fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError>;
+ fn read_len(reader: &mut impl Read) -> Result<Self::Len, DeserializeError>;
+}
- fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> {
- Self::try_from(len)
- .map_err(Into::into)?
- .mt_serialize::<DefCfg>(writer)
+pub trait MtSerialize {
+ fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError>;
+}
+
+pub trait MtDeserialize: Sized {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError>;
+}
+
+impl MtLen for usize {
+ fn option(&self) -> Option<usize> {
+ Some(*self)
}
- fn read_len(reader: &mut impl Read) -> Result<Self::Range, DeserializeError>;
+ type Range = std::ops::Range<usize>;
+ fn range(&self) -> Self::Range {
+ 0..*self
+ }
+
+ type Take<R: Read> = io::Take<R>;
+ fn take<R: Read>(&self, reader: R) -> Self::Take<R> {
+ reader.take(*self as u64)
+ }
}
trait MtCfgLen:
}
impl<T: MtCfgLen> MtCfg for T {
- type Range = std::ops::Range<usize>;
+ type Len = usize;
- fn var_len() -> bool {
- false
+ fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> {
+ Self::try_from(len)
+ .map_err(Into::into)?
+ .mt_serialize::<DefCfg>(writer)
}
- fn read_len(reader: &mut impl Read) -> Result<Self::Range, DeserializeError> {
- let len = Self::mt_deserialize::<DefCfg>(reader)?
+ fn read_len(reader: &mut impl Read) -> Result<Self::Len, DeserializeError> {
+ Ok(Self::mt_deserialize::<DefCfg>(reader)?
.try_into()
- .map_err(Into::into)?;
-
- Ok(0..len)
+ .map_err(Into::into)?)
}
}
-pub type DefCfg = u16;
-
-pub trait MtSerialize: Sized {
- fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError>;
-}
-
-pub trait MtDeserialize: Sized {
- fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError>;
-}
-
impl MtCfgLen for u8 {}
impl MtCfgLen for u16 {}
impl MtCfgLen for u32 {}
impl MtCfgLen for u64 {}
-#[derive(Debug)]
-pub struct NoLen;
+pub type DefCfg = u16;
-impl MtSerialize for NoLen {
- fn mt_serialize<C: MtCfg>(&self, _writer: &mut impl Write) -> Result<(), SerializeError> {
- Ok(())
- }
-}
+impl MtCfg for () {
+ type Len = ();
-impl MtDeserialize for NoLen {
- fn mt_deserialize<C: MtCfg>(_reader: &mut impl Read) -> Result<Self, DeserializeError> {
- Ok(Self)
+ fn write_len(_len: usize, _writer: &mut impl Write) -> Result<(), SerializeError> {
+ Ok(())
}
-}
-impl TryFrom<usize> for NoLen {
- type Error = Infallible;
-
- fn try_from(_x: usize) -> Result<Self, Self::Error> {
- Ok(Self)
+ fn read_len(_writer: &mut impl Read) -> Result<Self::Len, DeserializeError> {
+ Ok(())
}
}
-impl MtCfg for NoLen {
- fn var_len() -> bool {
- true
+impl MtLen for () {
+ fn option(&self) -> Option<usize> {
+ None
}
type Range = std::ops::RangeFrom<usize>;
-
- fn read_len(_reader: &mut impl Read) -> Result<Self::Range, DeserializeError> {
- Ok(0..)
- }
-}
-
-pub struct Utf16<B: MtCfg>(pub B);
-
-impl<B: MtCfg> MtSerialize for Utf16<B> {
- fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- self.0.mt_serialize::<DefCfg>(writer)
+ fn range(&self) -> Self::Range {
+ 0..
}
-}
-impl<B: MtCfg> MtDeserialize for Utf16<B> {
- fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
- Ok(Self(B::mt_deserialize::<DefCfg>(reader)?))
+ type Take<R: Read> = R;
+ fn take<R: Read>(&self, reader: R) -> Self::Take<R> {
+ reader
}
}
-impl<B: MtCfg> TryFrom<usize> for Utf16<B> {
- type Error = <usize as TryInto<B>>::Error;
-
- fn try_from(x: usize) -> Result<Self, Self::Error> {
- Ok(Self(x.try_into()?))
- }
-}
+pub struct Utf16<B: MtCfg>(pub B);
impl<B: MtCfg> MtCfg for Utf16<B> {
- type Range = B::Range;
+ type Len = B::Len;
fn utf16() -> bool {
true
}
- fn var_len() -> bool {
- B::var_len()
+ fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> {
+ B::write_len(len, writer)
}
- fn read_len(reader: &mut impl Read) -> Result<Self::Range, DeserializeError> {
+ fn read_len(reader: &mut impl Read) -> Result<Self::Len, DeserializeError> {
B::read_len(reader)
}
}
}
}
-fn mt_serialize_seq<C: MtCfg, T: MtSerialize>(
+pub fn mt_serialize_seq<C: MtCfg, T: MtSerialize>(
writer: &mut impl Write,
iter: impl ExactSizeIterator + IntoIterator<Item = T>,
) -> Result<(), SerializeError> {
.try_for_each(|item| item.mt_serialize::<DefCfg>(writer))
}
-fn mt_deserialize_seq<'a, C: MtCfg, T: MtDeserialize>(
+pub fn mt_deserialize_seq<'a, C: MtCfg, T: MtDeserialize>(
+ reader: &'a mut impl Read,
+) -> Result<impl Iterator<Item = Result<T, DeserializeError>> + 'a, DeserializeError> {
+ let len = C::read_len(reader)?;
+ mt_deserialize_sized_seq(&len, reader)
+}
+
+pub fn mt_deserialize_sized_seq<'a, L: MtLen, T: MtDeserialize>(
+ len: &L,
reader: &'a mut impl Read,
) -> Result<impl Iterator<Item = Result<T, DeserializeError>> + 'a, DeserializeError> {
- Ok(C::read_len(reader)?
- .into_iter()
- .map_while(|_| match T::mt_deserialize::<DefCfg>(reader) {
- Err(DeserializeError::UnexpectedEof) if C::var_len() => None,
+ let variable = len.option().is_none();
+
+ Ok(len
+ .range()
+ .map_while(move |_| match T::mt_deserialize::<DefCfg>(reader) {
+ Err(DeserializeError::UnexpectedEof) if variable => None,
x => Some(x),
}))
}
impl<T: MtSerialize, const N: usize> MtSerialize for [T; N] {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- mt_serialize_seq::<NoLen, _>(writer, self.iter())
+ mt_serialize_seq::<(), _>(writer, self.iter())
}
}
}
}
+// TODO: support more tuples
impl<A: MtSerialize, B: MtSerialize> MtSerialize for (A, B) {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
self.0.mt_serialize::<DefCfg>(writer)?;
Some(e) => Err(e),
}
} else {
- // TODO: UTF-8 decode
- Ok("".into())
+ let len = C::read_len(reader)?;
+
+ // use capacity if available
+ let mut st = match len.option() {
+ Some(x) => String::with_capacity(x),
+ None => String::new(),
+ };
+
+ len.take(WrapRead(reader)).read_to_string(&mut st)?;
+
+ Ok(st)
}
}
}
Ok(Self::new(T::mt_deserialize::<C>(reader)?))
}
}
-
-mod to_clt;
-mod to_srv;
-
-pub use to_clt::*;
-pub use to_srv::*;
--- /dev/null
+use super::*;
+
+fn reserialize<C: MtCfg, T: MtSerialize + MtDeserialize>(item: &T) -> T {
+ let mut writer = Vec::new();
+ item.mt_serialize::<C>(&mut writer).unwrap();
+
+ let mut reader = std::io::Cursor::new(writer);
+ T::mt_deserialize::<C>(&mut reader).unwrap()
+}
+
+#[test]
+fn test_reserialize() {
+ let vec = vec![1, 2, 3];
+ // encoded with 8-bit length
+ assert_eq!(vec, reserialize::<u8, _>(&vec));
+
+ let vec2 = vec![1, 2, 3];
+ // encoded without length - drains the Reader
+ assert_eq!(vec2, reserialize::<(), _>(&vec2));
+
+ let st: String = "µ ß 私 😀\n".into();
+ // encoded as UTF-16 with 32-bit length (also works with () or other types)
+ assert_eq!(st, reserialize::<Utf16<u32>, _>(&st));
+
+ let long: Vec<_> = (0..=256).collect();
+ assert!(matches!(
+ long.mt_serialize::<u8>(&mut Vec::new()),
+ Err(SerializeError::TooBig(_))
+ ));
+}
+++ /dev/null
-use crate::*;
-
-#[mt_derive(to = "clt")]
-pub struct ArgbColor {
- pub a: u8,
- pub r: u8,
- pub g: u8,
- pub b: u8,
-}
-
-#[mt_derive(to = "clt", repr = "u8")]
-pub enum ModChanSig {
- JoinOk = 0,
- JoinFail,
- LeaveOk,
- LeaveFail,
- NotRegistered,
- SetState,
-}
-
-mod chat;
-mod env;
-mod hud;
-mod media;
-mod status;
-
-pub use chat::*;
-pub use env::*;
-pub use hud::*;
-pub use media::*;
-pub use status::*;
-
-#[mt_derive(to = "clt", repr = "u8", tag = "type", content = "data")]
-pub enum ToCltPkt {
- Hello {
- serialize_version: u8,
- #[mt(const16 = 1)] // compression
- proto_version: u16,
- auth_methods: EnumSet<AuthMethod>,
- username: String,
- } = 2,
- AcceptAuth {
- player_pos: [f32; 3],
- map_seed: u64,
- send_interval: f32,
- sudo_auth_methods: EnumSet<AuthMethod>,
- } = 3,
- AcceptSudoMode {
- sudo_auth_methods: EnumSet<AuthMethod>,
- } = 4,
- DenySudoMode = 5,
- Kick(KickReason) = 10,
- BlockData {
- pos: [i16; 3],
- #[mt(zstd)]
- block: Box<MapBlock>,
- } = 32,
- AddNode {
- pos: [i16; 3],
- param0: u16,
- param1: u8,
- param2: u8,
- keep_meta: bool,
- } = 33,
- RemoveNode {
- pos: [i16; 3],
- } = 34,
- Inv {
- inv: String,
- } = 39,
- TimeOfDay {
- time: u16,
- speed: f32,
- } = 41,
- CsmRestrictionFlags {
- flags: EnumSet<CsmRestrictionFlag>,
- map_range: u32,
- } = 42,
- AddPlayerVelocity {
- vel: [f32; 3],
- } = 43,
- MediaPush {
- no_len_hash: String,
- filename: String,
- callback_token: u32,
- should_cache: bool,
- } = 44,
- ChatMsg {
- #[mt(const8 = 1)]
- msg_type: ChatMsgType,
- #[mt(utf16)]
- sender: String,
- #[mt(utf16)]
- text: String,
- timestamp: i64, // unix time
- } = 47,
- ObjRemoveAdd {
- remove: Vec<u16>,
- add: Vec<ObjAdd>,
- } = 49,
- ObjMsgs {
- msgs: Vec<ObjMsg>,
- } = 50,
- Hp {
- hp: u16,
- #[mt(default)]
- damage_effect: bool,
- } = 51,
- MovePlayer {
- pos: [f32; 3],
- pitch: f32,
- yaw: f32,
- } = 52,
- LegacyKick {
- #[mt(utf16)]
- reason: String,
- } = 53,
- Fov {
- fov: f32,
- multiplier: bool,
- transition_time: f32,
- } = 54,
- DeathScreen {
- point_cam: bool,
- point_at: [f32; 3],
- } = 55,
- Media {
- n: u16,
- i: u16,
- files: Vec<MediaPayload>, // FIXME: can we use a HashMap for this?
- } = 56,
- NodeDefs {
- defs: Vec<NodeDef>,
- } = 58,
- AnnounceMedia {
- files: Vec<MediaAnnounce>, // FIXME: can we use a HashMap for this?
- url: String,
- } = 60,
- #[mt(size32, zlib)]
- ItemDefs {
- #[mt(const8 = 0)] // version
- defs: Vec<ItemDef>,
- aliases: HashMap<String, String>,
- } = 61,
- PlaySound {
- id: u32,
- name: String,
- gain: f32,
- src_type: SoundSrcType,
- pos: [f32; 3],
- src_obj_id: u16,
- #[serde(rename = "loop")]
- sound_loop: bool,
- fade: f32,
- pitch: f32,
- ephermeral: bool,
- } = 63,
- StopSound {
- id: u32,
- } = 64,
- Privs {
- privs: HashSet<String>,
- } = 65,
- InvFormspec {
- #[mt(size32)]
- formspec: String,
- } = 66,
- DetachedInv {
- name: String,
- keep: bool,
- len: u16,
- #[mt(len0)]
- inv: String,
- } = 67,
- ShowFormspec {
- #[mt(len32)]
- formspec: String,
- formname: String,
- } = 68,
- Movement {
- default_accel: f32,
- air_accel: f32,
- fast_accel: f32,
- walk_speed: f32,
- crouch_speed: f32,
- fast_speed: f32,
- climb_speed: f32,
- jump_speed: f32,
- gravity: f32,
- } = 69,
- SpawnParticle {
- pos: [f32; 3],
- vel: [f32; 3],
- acc: [f32; 3],
- expiration_time: f32,
- size: f32,
- collide: bool,
- #[mt(len32)]
- texture: String,
- vertical: bool,
- collision_rm: bool,
- anim_params: TileAnim,
- glow: u8,
- obj_collision: bool,
- node_param0: u16,
- node_param2: u8,
- node_tile: u8,
- } = 70,
- AddParticleSpawner {
- amount: u16,
- duration: f32,
- pos: [[f32; 3]; 2],
- vel: [[f32; 3]; 2],
- acc: [[f32; 3]; 2],
- expiration_time: [f32; 2],
- size: [f32; 2],
- collide: bool,
- #[mt(len32)]
- texture: String,
- id: u32,
- vertical: bool,
- collision_rm: bool,
- attached_obj_id: u16,
- anim_params: TileAnim,
- glow: u8,
- obj_collision: bool,
- node_param0: u16,
- node_param2: u8,
- node_tile: u8,
- } = 71,
- AddHud {
- id: u32,
- hud: HudElement,
- } = 73,
- RemoveHud {
- id: u32,
- } = 74,
- ChangeHud {
- id: u32,
- change: HudChange,
- } = 75,
- HudFlags {
- flags: EnumSet<HudFlag>,
- mask: EnumSet<HudFlag>,
- } = 76,
- SetHotbarParam(HotbarParam) = 77,
- Breath {
- breath: u16,
- } = 78,
- // TODO
- SkyParams = 79,
- OverrideDayNightRatio {
- #[serde(rename = "override")]
- ratio_override: bool,
- ratio: u16,
- } = 80,
- LocalPlayerAnim {
- idle: [i32; 2],
- walk: [i32; 2],
- dig: [i32; 2],
- walk_dig: [i32; 2],
- speed: f32,
- } = 81,
- EyeOffset {
- first: [f32; 3],
- third: [f32; 3],
- } = 82,
- RemoveParticleSpawner {
- id: u32,
- } = 83,
- CloudParams {
- density: f32,
- diffuse_color: ArgbColor,
- ambient_color: ArgbColor,
- height: f32,
- thickness: f32,
- speed: [f32; 2],
- } = 84,
- FadeSound {
- id: u32,
- step: f32,
- gain: f32,
- } = 85,
- UpdatePlayerList {
- update_type: PlayerListUpdateType,
- players: HashSet<String>,
- } = 86,
- ModChanMsg {
- channel: String,
- sender: String,
- msg: String,
- } = 87,
- ModChanSig {
- signal: ModChanSig,
- channel: String,
- } = 88,
- NodeMetasChanged(#[mt(size32)] HashMap<[i16; 3], NodeMeta>) = 89,
- SunParams {
- visible: bool,
- texture: String,
- tone_map: String,
- rise: String,
- rising: bool,
- size: f32,
- } = 90,
- MoonParams {
- visible: bool,
- texture: String,
- tone_map: String,
- size: f32,
- } = 91,
- StarParams {
- visible: bool,
- texture: String,
- tone_map: String,
- size: f32,
- } = 92,
- SrpBytesSaltB {
- salt: Vec<u8>,
- b: Vec<u8>,
- } = 96,
- FormspecPrepend {
- prepend: String,
- } = 97,
- MinimapModes(MinimapModePkt) = 98,
-}
+++ /dev/null
-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,
-}
+++ /dev/null
-use super::*;
-
-#[mt_derive(to = "clt")]
-pub struct ObjAdd; // TODO
-
-#[mt_derive(to = "clt")]
-pub struct ObjMsg; // TODO
-
-#[mt_derive(to = "clt", repr = "u8", enumset)]
-pub enum MapBlockFlag {
- IsUnderground = 0,
- DayNightDiff,
- LightExpired,
- NotGenerated,
-}
-
-pub const ALWAYS_LIT_FROM: u16 = 0xf000;
-
-#[mt_derive(to = "clt")]
-pub struct MapBlock {
- pub flags: EnumSet<MapBlockFlag>,
- pub lit_from: u16,
-
- #[mt(const8 = 2)]
- #[serde(skip)]
- pub param0_size: (),
-
- #[mt(const8 = 2)]
- #[serde(skip)]
- pub param12_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],
-
- pub node_metas: HashMap<u16, NodeMeta>,
-
- #[mt(const8 = 2)]
- #[serde(skip)]
- pub version: (),
-}
+++ /dev/null
-use super::*;
-
-#[mt_derive(to = "clt", repr = "u32", enumset)]
-pub enum HudStyleFlag {
- Bold,
- Italic,
- Mono,
-}
-
-#[mt_derive(to = "clt", repr = "u8", tag = "attribute", content = "value")]
-pub enum HudChange {
- Pos([f32; 2]) = 0,
- Name(String),
- Scale([f32; 2]),
- Text(String),
- Number(u32),
- Item(u32),
- Dir(u32),
- Align([f32; 2]),
- Offset([f32; 2]),
- WorldPos([f32; 3]),
- ZIndex(i32),
- Text2(String),
- Style(EnumSet<HudStyleFlag>),
-}
-
-#[mt_derive(to = "clt", repr = "u8")]
-pub enum HudType {
- Image = 0,
- Text,
- Statbar,
- Inv,
- Waypoint,
- ImageWaypoint,
-}
-
-#[mt_derive(to = "clt")]
-pub struct HudElement {
- pub hud_type: HudType,
- pub pos: [f32; 2],
- pub name: String,
- pub scale: [f32; 2],
- pub text: String,
- pub number: u32,
- pub item: u32,
- pub dir: u32,
- pub align: [f32; 2],
- pub offset: [f32; 2],
- pub world_pos: [f32; 3],
- pub z_index: i32,
- pub text_2: String,
- pub style: EnumSet<HudStyleFlag>,
-}
-
-impl HudElement {
- pub fn apply_change(&mut self, change: HudChange) {
- use HudChange::*;
-
- match change {
- Pos(v) => self.pos = v,
- Name(v) => self.name = v,
- Scale(v) => self.scale = v,
- Text(v) => self.text = v,
- Number(v) => self.number = v,
- Item(v) => self.item = v,
- Dir(v) => self.dir = v,
- Align(v) => self.align = v,
- Offset(v) => self.offset = v,
- WorldPos(v) => self.world_pos = v,
- ZIndex(v) => self.z_index = v,
- Text2(v) => self.text_2 = v,
- Style(v) => self.style = v,
- }
- }
-}
-
-#[mt_derive(to = "clt", repr = "u32", enumset)]
-pub enum HudFlag {
- Hotbar,
- HealthBar,
- Crosshair,
- WieldedItem,
- BreathBar,
- Minimap,
- RadarMinimap,
-}
-
-#[mt_derive(to = "clt", repr = "u16", tag = "attribute", content = "value")]
-pub enum HotbarParam {
- Size(#[mt(const16 = 4)] u32) = 0,
- Image(String),
- SelectionImage(String),
-}
-
-#[mt_derive(to = "clt", repr = "u16")]
-pub enum MinimapType {
- None = 0,
- Surface,
- Radar,
- Texture,
-}
-
-#[mt_derive(to = "clt")]
-pub struct MinimapMode {
- pub minimap_type: MinimapType,
- pub label: String,
- pub size: u16,
- pub texture: String,
- pub scale: u16,
-}
-
-#[mt_derive(to = "clt", custom)]
-pub struct MinimapModePkt {
- current: u16,
- modes: Vec<MinimapMode>,
-}
-
-#[cfg(feature = "server")]
-impl MtSerialize for MinimapModePkt {
- fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- DefCfg::write_len(self.modes.len(), writer)?;
- self.current.mt_serialize::<DefCfg>(writer)?;
- self.modes.mt_serialize::<NoLen>(writer)?;
-
- Ok(())
- }
-}
-
-#[cfg(feature = "client")]
-impl MtDeserialize for MinimapModePkt {
- fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
- let range = DefCfg::read_len(reader)?;
- let current = MtDeserialize::mt_deserialize::<DefCfg>(reader)?;
- let modes = range
- .map(|_| MtDeserialize::mt_deserialize::<DefCfg>(reader))
- .try_collect()?;
-
- Ok(Self { current, modes })
- }
-}
-
-/*
-TODO: rustify this
-
-var DefaultMinimap = []MinimapMode{
- {Type: NoMinimap},
- {Type: SurfaceMinimap, Size: 256},
- {Type: SurfaceMinimap, Size: 128},
- {Type: SurfaceMinimap, Size: 64},
- {Type: RadarMinimap, Size: 512},
- {Type: RadarMinimap, Size: 256},
- {Type: RadarMinimap, Size: 128},
-}
-*/
+++ /dev/null
-use super::*;
-
-#[mt_derive(to = "clt")]
-pub struct MediaAnnounce {
- pub name: String,
- pub base64_sha1: String,
-}
-
-#[mt_derive(to = "clt")]
-pub struct MediaPayload {
- pub name: String,
- #[mt(len32)]
- pub data: Vec<u8>,
-}
-
-#[mt_derive(to = "clt")]
-pub struct TileAnim; // TODO
-
-#[mt_derive(to = "clt")]
-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 = "u16")]
-pub enum SoundSrcType {
- Nowhere = 0,
- Pos,
- Obj,
-}
+++ /dev/null
-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,
-}
+++ /dev/null
-use crate::*;
-
-#[mt_derive(to = "srv", repr = "u32", enumset)]
-pub enum Key {
- Forward,
- Backward,
- Left,
- Right,
- Jump,
- Special,
- Sneak,
- Dig,
- Place,
- Zoom,
-}
-
-#[mt_derive(to = "srv")]
-pub struct PlayerPos {
- pub pos_100: [i32; 3],
- pub vel_100: [i32; 3],
- pub pitch_100: i32,
- pub yaw_100: i32,
- pub keys: EnumSet<Key>,
- pub fov_80: u8,
- pub wanted_range: u8,
-}
-
-#[mt_derive(to = "srv", repr = "u8")]
-pub enum Interaction {
- Dig = 0,
- StopDigging,
- Dug,
- Place,
- Use,
- Activate,
-}
-
-#[mt_derive(to = "srv")]
-pub struct PointedThing; // TODO
-
-#[mt_derive(to = "srv", repr = "u16", tag = "type", content = "data")]
-pub enum ToSrvPkt {
- Nil = 0,
- Init {
- serialize_version: u8,
- #[mt(const16 = 1)] // supported compression
- min_proto_version: u16,
- max_proto_version: u16,
- player_name: String,
- #[mt(default)]
- send_full_item_meta: bool,
- } = 2,
- Init2 {
- lang: String,
- } = 17,
- JoinModChan {
- channel: String,
- } = 23,
- LeaveModChan {
- channel: String,
- } = 24,
- MsgModChan {
- channel: String,
- msg: String,
- } = 25,
- PlayerPos(PlayerPos) = 35,
- GotBlocks {
- #[mt(len8)]
- blocks: Vec<[i16; 3]>,
- } = 36,
- DeletedBlocks {
- #[mt(len8)]
- blocks: Vec<[i16; 3]>,
- } = 37,
- InvAction {
- #[mt(len0)]
- action: String,
- } = 49,
- ChatMsg {
- #[mt(utf16)]
- msg: String,
- } = 50,
- FallDmg {
- amount: u16,
- } = 53,
- SelectItem {
- select_item: u16,
- } = 55,
- Respawn = 56,
- Interact {
- action: Interaction,
- item_slot: u16,
- #[mt(size32)]
- pointed: PointedThing,
- pos: PlayerPos,
- } = 57,
- RemovedSounds {
- ids: Vec<i32>,
- } = 58,
- NodeMetaFields {
- pos: [i16; 3],
- formname: String,
- fields: HashMap<String, String>,
- } = 59,
- InvFields {
- formname: String,
- fields: HashMap<String, String>,
- } = 60,
- ReqMedia {
- filenames: Vec<String>,
- } = 64,
- CltReady {
- major: u8,
- minor: u8,
- patch: u8,
- reserved: u8,
- version: String,
- formspec: u16,
- } = 67,
- FirstSrp {
- salt: Vec<u8>,
- verifier: Vec<u8>,
- empty_passwd: bool,
- } = 80,
- SrpBytesA {
- a: Vec<u8>,
- no_sha1: bool,
- } = 81,
- SrpBytesM {
- m: Vec<u8>,
- } = 82,
- Disco = 0xffff,
-}