use anyhow::{Result, bail}; use glam::Vec3; use std::{ fmt::Display, io::{Read, Write}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Resource(pub [u8; 32]); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Object(pub u128); #[derive(Debug, Clone)] pub enum Packet { RequestResource(Resource), RespondResource(Vec), Add(Object, Resource), Remove(Object), Position(Object, Vec3, Vec3), Pose(Object, Vec), Parent(Object, Object), Sound(Object, Vec), } impl Object { pub fn new() -> Self { Self(rand::random()) } } impl Packet { pub fn serialize(&self, w: &mut impl Write) -> Result<()> { let mut buf = Vec::new(); self.serialize_inner(&mut buf)?; w.write_all(&(buf.len() as u16).to_be_bytes())?; w.write_all(&buf)?; Ok(()) } pub fn serialize_inner(&self, w: &mut impl Write) -> Result<()> { match self { Packet::RequestResource(resource) => { w.write_all(&[0x01])?; w.write_all(&resource.0)?; } Packet::RespondResource(data) => { w.write_all(&[0x02])?; w.write_all(&(data.len() as u16).to_be_bytes())?; w.write_all(&data)?; } Packet::Add(object, resource) => { w.write_all(&[0x03])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&resource.0)?; } Packet::Remove(object) => { w.write_all(&[0x04])?; w.write_all(&object.0.to_be_bytes())?; } Packet::Position(object, pos, rot) => { w.write_all(&[0x05])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&pos.x.to_be_bytes())?; w.write_all(&pos.y.to_be_bytes())?; w.write_all(&pos.z.to_be_bytes())?; w.write_all(&rot.x.to_be_bytes())?; w.write_all(&rot.y.to_be_bytes())?; w.write_all(&rot.z.to_be_bytes())?; } Packet::Pose(object, vec) => { w.write_all(&[0x06])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&(vec.len() as u16).to_be_bytes())?; } Packet::Parent(parent, child) => { w.write_all(&[0x07])?; w.write_all(&parent.0.to_be_bytes())?; w.write_all(&child.0.to_be_bytes())?; } Packet::Sound(object, vec) => { w.write_all(&[0x08])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&(vec.len() as u16).to_be_bytes())?; } } Ok(()) } pub fn deserialize(r: &mut impl Read) -> Result { let mut size_tag = [0u8; 3]; r.read_exact(&mut size_tag)?; Ok(match size_tag[2] { 0x01 => Packet::RequestResource(read_res(r)?), 0x02 => Packet::RespondResource(read_data(r)?), 0x03 => Packet::Add(Object(read_u128(r)?), read_res(r)?), 0x04 => Packet::Remove(Object(read_u128(r)?)), 0x05 => Packet::Position( Object(read_u128(r)?), Vec3::new(read_float(r)?, read_float(r)?, read_float(r)?), Vec3::new(read_float(r)?, read_float(r)?, read_float(r)?), ), 0x06 => Packet::Pose(Object(read_u128(r)?), read_params(r)?), 0x07 => Packet::Parent(Object(read_u128(r)?), Object(read_u128(r)?)), 0x08 => Packet::Sound(Object(read_u128(r)?), read_data(r)?), _ => { for _ in 0..u16::from_be_bytes([size_tag[0], size_tag[1]]) - 1 { r.read_exact(&mut [0])?; } bail!("unknown packet tag"); } }) } } fn read_u128(r: &mut impl Read) -> Result { let mut buf = [0; 16]; r.read_exact(&mut buf)?; Ok(u128::from_be_bytes(buf)) } fn read_res(r: &mut impl Read) -> Result { let mut buf = [0; 32]; r.read_exact(&mut buf)?; Ok(Resource(buf)) } fn read_data(r: &mut impl Read) -> Result> { let mut size = [0; 2]; r.read_exact(&mut size)?; let size = u16::from_be_bytes(size); let mut buf = vec![0; size as usize]; r.read_exact(&mut buf)?; Ok(buf) } fn read_float(r: &mut impl Read) -> Result { let mut buf = [0; 4]; r.read_exact(&mut buf)?; Ok(f32::from_be_bytes(buf)) } fn read_params(r: &mut impl Read) -> Result> { let mut size = [0; 2]; r.read_exact(&mut size)?; let size = u16::from_be_bytes(size); let mut v = Vec::with_capacity(size as usize); for _ in 0..size { v.push(read_float(r)?); } Ok(v) } impl Display for Resource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "Res{{{:08x}{:08x}{:08x}{:08x}}}", u64::from_be_bytes(self.0[0..8].try_into().unwrap()), u64::from_be_bytes(self.0[8..16].try_into().unwrap()), u64::from_be_bytes(self.0[16..24].try_into().unwrap()), u64::from_be_bytes(self.0[24..32].try_into().unwrap()), ) } }