use anyhow::{Result, bail}; use glam::Vec3; use std::io::{Read, Write}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Resource(pub u128); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Object(pub u128); #[derive(Debug, Clone)] pub enum Packet { RequestResource(Resource), RespondResource(Resource, Vec), Add(Object, Resource), Remove(Object), Position(Object, Vec3, Vec3), Pose(Object, Vec), Parent(Object, Object), Sound(Object, Vec), } impl Packet { pub fn serialize(&self, w: &mut impl Write) -> Result<()> { match self { Packet::RequestResource(resource) => { w.write_all(&[0x01])?; w.write_all(&resource.0.to_be_bytes())?; } Packet::RespondResource(resource, vec) => { w.write_all(&[0x02])?; w.write_all(&resource.0.to_be_bytes())?; w.write_all(&(vec.len() as u16).to_be_bytes())?; w.write_all(&vec)?; } Packet::Add(object, resource) => { w.write_all(&[0x03])?; w.write_all(&object.0.to_be_bytes())?; w.write_all(&resource.0.to_be_bytes())?; } 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 tag = [0u8; 1]; r.read_exact(&mut tag)?; Ok(match tag[0] { 0x01 => Packet::RequestResource(Resource(read_u128(r)?)), 0x02 => Packet::RespondResource(Resource(read_u128(r)?), read_data(r)?), 0x03 => Packet::Add(Object(read_u128(r)?), Resource(read_u128(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)?), _ => 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_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) }