mod byte_angle; pub mod codec; pub mod packets; mod var_int; mod var_long; use std::io::{Read, Write}; use std::mem; use anyhow::{anyhow, ensure, Context}; use arrayvec::ArrayVec; use bitvec::prelude::*; pub use byte_angle::ByteAngle; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use serde::de::DeserializeOwned; use serde::Serialize; use uuid::Uuid; pub use var_int::VarInt; pub use var_long::VarLong; use vek::{Vec2, Vec3, Vec4}; use crate::EntityId; /// Trait for types that can be written to the Minecraft protocol. pub trait Encode { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()>; } /// Trait for types that can be read from the Minecraft protocol. pub trait Decode: Sized { fn decode(r: &mut impl Read) -> anyhow::Result; } /// The maximum number of bytes in a single packet. pub const MAX_PACKET_SIZE: i32 = 2097151; impl Encode for () { fn encode(&self, _w: &mut impl Write) -> anyhow::Result<()> { Ok(()) } } impl Decode for () { fn decode(_r: &mut impl Read) -> anyhow::Result { Ok(()) } } impl Encode for (T, U) { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { self.0.encode(w)?; self.1.encode(w) } } impl Decode for (T, U) { fn decode(r: &mut impl Read) -> anyhow::Result { Ok((T::decode(r)?, U::decode(r)?)) } } impl Encode for &T { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { (*self).encode(w) } } impl Encode for bool { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_u8(*self as u8)?; Ok(()) } } impl Decode for bool { fn decode(r: &mut impl Read) -> anyhow::Result { let n = r.read_u8()?; ensure!(n < 2, "boolean is not 0 or 1"); Ok(n == 1) } } impl Encode for u8 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_u8(*self)?; Ok(()) } } impl Decode for u8 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_u8()?) } } impl Encode for i8 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_i8(*self)?; Ok(()) } } impl Decode for i8 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_i8()?) } } impl Encode for u16 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_u16::(*self)?; Ok(()) } } impl Decode for u16 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_u16::()?) } } impl Encode for i16 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_i16::(*self)?; Ok(()) } } impl Decode for i16 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_i16::()?) } } impl Encode for u32 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_u32::(*self)?; Ok(()) } } impl Decode for u32 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_u32::()?) } } impl Encode for i32 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_i32::(*self)?; Ok(()) } } impl Decode for i32 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_i32::()?) } } impl Encode for u64 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_u64::(*self)?; Ok(()) } } impl Decode for u64 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_u64::()?) } } impl Encode for i64 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_i64::(*self)?; Ok(()) } } impl Decode for i64 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(r.read_i64::()?) } } impl Encode for f32 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { ensure!( self.is_finite(), "attempt to encode non-finite f32 ({})", self ); w.write_f32::(*self)?; Ok(()) } } impl Decode for f32 { fn decode(r: &mut impl Read) -> anyhow::Result { let f = r.read_f32::()?; ensure!(f.is_finite(), "attempt to decode non-finite f32 ({f})"); Ok(f) } } impl Encode for f64 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { ensure!( self.is_finite(), "attempt to encode non-finite f64 ({})", self ); w.write_f64::(*self)?; Ok(()) } } impl Decode for f64 { fn decode(r: &mut impl Read) -> anyhow::Result { let f = r.read_f64::()?; ensure!(f.is_finite(), "attempt to decode non-finite f64 ({f})"); Ok(f) } } impl Encode for Option { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { match self { Some(t) => { true.encode(w)?; t.encode(w) } None => false.encode(w), } } } impl Decode for Option { fn decode(r: &mut impl Read) -> anyhow::Result { if bool::decode(r)? { Ok(Some(T::decode(r)?)) } else { Ok(None) } } } impl Encode for Box { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { self.as_ref().encode(w) } } impl Decode for Box { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(Box::new(T::decode(r)?)) } } impl Encode for Box { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_string_bounded(self, 0, 32767, w) } } impl Decode for Box { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(String::decode(r)?.into_boxed_str()) } } #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct BoundedInt(pub T); impl BoundedInt { pub const fn min_bound(&self) -> i64 { MIN } pub const fn max_bound(&self) -> i64 { MAX } } impl From for BoundedInt { fn from(t: T) -> Self { Self(t) } } impl Encode for BoundedInt where T: Encode + Copy + Into, { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { let val = self.0.into(); ensure!( (MIN..=MAX).contains(&val), "Integer is not in bounds while encoding (got {val}, expected {MIN}..={MAX})" ); self.0.encode(w) } } impl Decode for BoundedInt where T: Decode + Copy + Into, { fn decode(r: &mut impl Read) -> anyhow::Result { let res = T::decode(r)?; let val = res.into(); ensure!( (MIN..=MAX).contains(&val), "Integer is not in bounds while decoding (got {val}, expected {MIN}..={MAX})" ); Ok(Self(res)) } } // TODO: bounded float? impl Encode for String { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_string_bounded(self, 0, 32767, w) } } impl Decode for String { fn decode(r: &mut impl Read) -> anyhow::Result { decode_string_bounded(0, 32767, r) } } /// A string with a minimum and maximum character length known at compile time. /// If the string is not in bounds, an error is generated while /// encoding/decoding. /// /// Note that the length is a count of the characters in the string, not bytes. /// /// When encoded and decoded, the string is VarInt prefixed. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)] pub struct BoundedString(pub String); impl BoundedString { pub const fn min_bound(&self) -> usize { MIN } pub const fn max_bound(&self) -> usize { MAX } } impl Encode for BoundedString { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_string_bounded(&self.0, MIN, MAX, w) } } impl Decode for BoundedString { fn decode(r: &mut impl Read) -> anyhow::Result { decode_string_bounded(MIN, MAX, r).map(Self) } } impl From for BoundedString { fn from(s: String) -> Self { Self(s) } } impl Encode for Vec { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_array_bounded(self, 0, usize::MAX, w) } } impl Decode for Vec { fn decode(r: &mut impl Read) -> anyhow::Result { decode_array_bounded(0, usize::MAX, r) } } impl Encode for Box<[T]> { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_array_bounded(self, 0, usize::MAX, w) } } impl Decode for Box<[T]> { fn decode(r: &mut impl Read) -> anyhow::Result { decode_array_bounded(0, usize::MAX, r).map(|v| v.into_boxed_slice()) } } impl Encode for [T; N] { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_array_bounded(self, N, N, w) } } impl Decode for [T; N] { fn decode(r: &mut impl Read) -> anyhow::Result { let mut elems = ArrayVec::new(); for _ in 0..N { elems.push(T::decode(r)?); } elems .into_inner() .map_err(|_| unreachable!("mismatched array size")) } } impl Encode for Vec2 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { self.x.encode(w)?; self.y.encode(w) } } impl Encode for Vec3 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { self.x.encode(w)?; self.y.encode(w)?; self.z.encode(w) } } impl Encode for Vec4 { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { self.x.encode(w)?; self.y.encode(w)?; self.z.encode(w)?; self.w.encode(w) } } impl Decode for Vec2 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(Vec2::new(T::decode(r)?, T::decode(r)?)) } } impl Decode for Vec3 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(Vec3::new(T::decode(r)?, T::decode(r)?, T::decode(r)?)) } } impl Decode for Vec4 { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(Vec4::new( T::decode(r)?, T::decode(r)?, T::decode(r)?, T::decode(r)?, )) } } /// An array with a minimum and maximum character length known at compile time. /// If the array is not in bounds, an error is generated while /// encoding/decoding. /// /// When encoding/decoding, the array is VarInt prefixed. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)] pub struct BoundedArray(pub Vec); impl Encode for BoundedArray { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_array_bounded(&self.0, MIN, MAX, w) } } impl Decode for BoundedArray { fn decode(r: &mut impl Read) -> anyhow::Result { decode_array_bounded(MIN, MAX, r).map(Self) } } impl From> for BoundedArray { fn from(v: Vec) -> Self { Self(v) } } impl Encode for Uuid { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_u128::(self.as_u128())?; Ok(()) } } impl Decode for Uuid { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(Uuid::from_u128(r.read_u128::()?)) } } impl Encode for nbt::Blob { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { Ok(nbt::to_writer(w, self, None)?) } } impl Decode for nbt::Blob { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(nbt::from_reader(r)?) } } /// Wrapper type acting as a bridge between Serde and [Encode]/[Decode] through /// the NBT format. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)] pub struct Nbt(pub T); impl Encode for Nbt { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { Ok(nbt::to_writer(w, &self.0, None)?) } } impl Decode for Nbt { fn decode(r: &mut impl Read) -> anyhow::Result { Ok(Self(nbt::from_reader(r)?)) } } impl Encode for BitVec { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_array_bounded(self.as_raw_slice(), 0, usize::MAX, w) } } impl Decode for BitVec { fn decode(r: &mut impl Read) -> anyhow::Result { BitVec::try_from_vec(Vec::decode(r)?) .map_err(|_| anyhow!("Array is too long for bit vector")) } } impl Encode for BitBox { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { encode_array_bounded(self.as_raw_slice(), 0, usize::MAX, w) } } impl Decode for BitBox { fn decode(r: &mut impl Read) -> anyhow::Result { BitVec::decode(r).map(|v| v.into_boxed_bitslice()) } } /// When decoding, reads the rest of the data in a packet and stuffs it into a /// `Vec`. When encoding, the data is inserted into the packet with no /// length prefix. #[derive(Clone, Debug)] pub struct RawBytes(pub Vec); impl Decode for RawBytes { fn decode(r: &mut impl Read) -> anyhow::Result { let mut buf = Vec::new(); r.read_to_end(&mut buf)?; Ok(RawBytes(buf)) } } impl Encode for RawBytes { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { w.write_all(&self.0).map_err(|e| e.into()) } } impl Encode for Option { fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> { match self { Some(id) => VarInt( id.to_network_id() .checked_add(1) .context("i32::MAX is unrepresentable as an optional VarInt")?, ), None => VarInt(0), } .encode(w) } } fn encode_array_bounded( s: &[T], min: usize, max: usize, w: &mut impl Write, ) -> anyhow::Result<()> { assert!(min <= max); let len = s.len(); ensure!( (min..=max).contains(&len), "Length of array is out of bounds while encoding (got {len}, expected {min}..={max})" ); ensure!( len <= i32::MAX as usize, "Length of array ({len}) exceeds i32::MAX" ); VarInt(len as i32).encode(w)?; for t in s { t.encode(w)?; } Ok(()) } pub(crate) fn encode_string_bounded( s: &str, min: usize, max: usize, w: &mut impl Write, ) -> anyhow::Result<()> { assert!(min <= max, "Bad min and max"); let char_count = s.chars().count(); ensure!( (min..=max).contains(&char_count), "Char count of string is out of bounds while encoding (got {char_count}, expected \ {min}..={max})" ); encode_array_bounded(s.as_bytes(), 0, usize::MAX, w) } pub(crate) fn decode_string_bounded( min: usize, max: usize, r: &mut impl Read, ) -> anyhow::Result { assert!(min <= max); let bytes = decode_array_bounded(min, max.saturating_mul(4), r)?; let string = String::from_utf8(bytes)?; let char_count = string.chars().count(); ensure!( (min..=max).contains(&char_count), "Char count of string is out of bounds while decoding (got {char_count}, expected \ {min}..={max}" ); Ok(string) } pub(crate) fn decode_array_bounded( min: usize, max: usize, r: &mut impl Read, ) -> anyhow::Result> { assert!(min <= max); let len = VarInt::decode(r)?.0; ensure!( len >= 0 && (min..=max).contains(&(len as usize)), "Length of array is out of bounds while decoding (got {len}, needed {min}..={max})", ); // Don't allocate more than what would roughly fit in a single packet in case we // get a malicious array length. let cap = (MAX_PACKET_SIZE as usize / mem::size_of::().max(1)).min(len as usize); let mut res = Vec::with_capacity(cap); for _ in 0..len { res.push(T::decode(r)?); } Ok(res) }