diff --git a/src/lib.rs b/src/lib.rs index 69a3860..c367efe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,15 +3,14 @@ extern crate lazy_static; /// Data types for every entity in the game. pub mod entity; -/// Implementations of the data types needed for the Minecraft protocol. +/// Data types needed for the Minecraft protocol. pub mod mctypes; /// The logic for the server. pub mod server; -/// The data types for blocks, chunks, dimensions, and world files. +/// Data types for blocks, chunks, dimensions, and world files. pub mod world; use log::*; -pub use mctypes::*; use serde::{Deserialize, Serialize}; use std::sync::mpsc::{self, Receiver}; diff --git a/src/mctypes.rs b/src/mctypes.rs deleted file mode 100644 index 633b5f0..0000000 --- a/src/mctypes.rs +++ /dev/null @@ -1,1106 +0,0 @@ -#![allow(dead_code)] - -pub use functions::*; -pub use numbers::*; -pub use other::*; -use serde_json::json; -use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; - -// /// Make sure all types can serialize and deserialize to/from `Vec`. -// pub trait MCType: Into> + TryFrom> + Display { -// pub async fn read(_stream: &mut TcpStream) -> tokio::io::Result; -// } - -/// Helper functions. -pub mod functions { - use super::*; - - /// Read a single byte from the given `TcpStream`. - pub async fn read_byte(t: &mut T) -> tokio::io::Result { - let mut buffer = [0u8; 1]; - t.read_exact(&mut buffer).await?; - Ok(buffer[0]) - } - /// Read `l` bytes from the given `TcpStream`. - pub async fn read_bytes( - t: &mut T, - l: usize, - ) -> tokio::io::Result> { - let mut buffer = vec![]; - for _ in 0..l { - buffer.push(read_byte(t).await?); - } - Ok(buffer) - } - /// Write a single byte to the given `TcpStream`. - pub async fn write_byte(t: &mut T, value: u8) -> tokio::io::Result<()> { - t.write(&[value]).await?; - Ok(()) - } - /// Write multiple bytes to the given `TcpStream`. - pub async fn write_bytes( - t: &mut T, - bytes: &[u8], - ) -> tokio::io::Result<()> { - for b in bytes { - write_byte(t, *b).await?; - } - Ok(()) - } - /// Take `l` bytes from the given `Vec`. - pub fn get_bytes(v: Vec, l: usize) -> Box<[u8]> { - use std::collections::VecDeque; - let mut v = VecDeque::from(v); - while v.len() > l { - v.pop_front(); - } - while v.len() < l { - v.push_front(0u8); - } - let mut a = Vec::new(); - for b in v { - a.push(b); - } - a.into_boxed_slice() - } - /// Makes returning errors shorter. - pub fn io_error(s: &str) -> tokio::io::Error { - use tokio::io::{Error, ErrorKind}; - Error::new(ErrorKind::Other, s) - } -} - -/// The other types, (booleans and strings). -pub mod other { - use super::*; - use std::convert::{From, Into, TryFrom}; - use std::fmt::{Debug, Display}; - - /// The equivalent of a `bool`. - #[derive(Debug, Copy, Clone, PartialEq)] - pub enum MCBoolean { - True, - False, - } - impl From for MCBoolean { - fn from(v: bool) -> MCBoolean { - if v { - MCBoolean::True - } else { - MCBoolean::False - } - } - } - impl Into for MCBoolean { - fn into(self) -> bool { - match self { - MCBoolean::True => true, - MCBoolean::False => false, - } - } - } - impl Display for MCBoolean { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - MCBoolean::True => "true", - MCBoolean::False => "false", - } - ) - } - } - impl TryFrom> for MCBoolean { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.is_empty() { - Err("Not enough bytes") - } else if bytes[0] == 1u8 { - Ok(MCBoolean::True) - } else { - Ok(MCBoolean::False) - } - } - } - impl Into> for MCBoolean { - fn into(self) -> Vec { - match self { - MCBoolean::True => vec![0x01], - MCBoolean::False => vec![0x00], - } - } - } - impl MCBoolean { - pub async fn read(t: &mut T) -> tokio::io::Result { - let b = read_byte(t).await?; - Ok(MCBoolean::try_from(vec![b]).unwrap()) - } - } - - /// The equivalent of a `String`. - #[derive(PartialEq)] - pub struct MCString { - pub value: String, - } - impl From<&str> for MCString { - fn from(s: &str) -> MCString { - MCString { - value: s.to_owned(), - } - } - } - impl From for MCString { - fn from(s: String) -> MCString { - MCString { value: s } - } - } - impl Into for MCString { - fn into(self) -> String { - self.value - } - } - impl PartialEq<&str> for MCString { - fn eq(&self, other: &&str) -> bool { - self.value == **other - } - } - impl PartialEq for MCString { - fn eq(&self, other: &String) -> bool { - self.value == *other - } - } - impl PartialEq<&String> for MCString { - fn eq(&self, other: &&String) -> bool { - self.value == **other - } - } - impl Clone for MCString { - fn clone(&self) -> Self { - MCString { - value: self.value.clone(), - } - } - } - impl Debug for MCString { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "MCString {{ \"{}\" ({} chars) }}", - self.value, - self.value.len() - ) - } - } - impl Display for MCString { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCString { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("Cannot read MCString from bytes") - } - } - impl Into> for MCString { - fn into(self) -> Vec { - let mut out = vec![]; - let str_len: Vec = MCVarInt::from(self.value.len() as i32).into(); - for b in str_len { - out.push(b); - } - for b in self.value.into_bytes() { - out.push(b); - } - out - } - } - impl MCString { - pub async fn read(t: &mut T) -> tokio::io::Result { - let str_len = MCVarInt::read(t).await?; - let mut str_bytes = vec![]; - for _ in 0i32..str_len.into() { - str_bytes.push(read_byte(t).await?); - } - Ok(MCString { - value: String::from_utf8_lossy(&str_bytes).to_string(), - }) - } - } - - /// A normal `MCString`, but with extra embedded formatting data. - #[derive(Debug, PartialEq)] - pub struct MCChat { - pub text: MCString, - } - impl From<&str> for MCChat { - fn from(s: &str) -> MCChat { - MCChat { text: s.into() } - } - } - impl From for MCChat { - fn from(s: String) -> MCChat { - MCChat { text: s.into() } - } - } - impl Into for MCChat { - fn into(self) -> String { - self.text.value - } - } - impl PartialEq<&str> for MCChat { - fn eq(&self, other: &&str) -> bool { - self.text.value == **other - } - } - impl PartialEq for MCChat { - fn eq(&self, other: &String) -> bool { - self.text.value == *other - } - } - impl PartialEq<&String> for MCChat { - fn eq(&self, other: &&String) -> bool { - self.text.value == **other - } - } - impl Clone for MCChat { - fn clone(&self) -> Self { - MCChat { - text: self.text.clone(), - } - } - } - impl Display for MCChat { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "\"{}\" ({} chars)", - self.text.value, - self.text.value.len() - ) - } - } - impl TryFrom> for MCChat { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("Cannot read MCChat from bytes") - } - } - impl Into> for MCChat { - fn into(self) -> Vec { - // Just output - // {"text": ""} - Into::::into( - json!({ - "text": self.text.value - }) - .to_string(), - ) - .into() - } - } - impl MCChat { - pub async fn read(_t: &mut T) -> tokio::io::Result { - Err(io_error("Cannot read MCChat from stream")) - } - } - - // TODO: Actually make the MCPosition work. - #[derive(Debug, PartialEq, Clone)] - pub struct MCPosition { - x: MCLong, - y: MCLong, - z: MCLong, - } - impl Display for MCPosition { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "({}, {}, {})", self.x, self.y, self.z,) - } - } - impl TryFrom> for MCPosition { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("Cannot read MCPosition from bytes") - } - } - impl Into> for MCPosition { - fn into(self) -> Vec { - // Just output - // {"text": ""} - let mut out = vec![]; - let mut temp = vec![]; - temp.extend_from_slice( - &((((Into::::into(self.x) & 0x3FFFFFF) << 38) - | ((Into::::into(self.y) & 0xFFF) << 26) - | (Into::::into(self.z) & 0x3FFFFFF)) as u64) - .to_be_bytes(), - ); - // temp.extend_from_slice(&"{\"text\": \"".to_owned().into_bytes()); - // temp.extend_from_slice(&self.text.value.into_bytes()); - // temp.extend_from_slice(&"\"}".to_owned().into_bytes()); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } - } - impl MCPosition { - pub fn new() -> MCPosition { - MCPosition { - x: 0.into(), - y: 0.into(), - z: 0.into(), - } - } - pub async fn read(_t: &mut T) -> tokio::io::Result { - Err(io_error("Cannot read MCPosition from stream")) - } - } - impl Default for MCPosition { - fn default() -> Self { - MCPosition { - x: 0.into(), - y: 0.into(), - z: 0.into(), - } - } - } -} - -/// All the numbers, from `i8` and `u8` to `i64` and `u64`, plus `VarInt`s. -pub mod numbers { - use super::*; - use std::convert::{From, Into, TryFrom}; - use std::fmt::Display; - - /// The equivalent of an `i8` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCByte { - pub value: i8, // -128 to 127 - } - impl MCByte { - pub async fn read(t: &mut T) -> tokio::io::Result { - Ok(MCByte::from_bytes(vec![read_byte(t).await?])) - } - pub fn from_bytes(v: Vec) -> MCByte { - MCByte { - value: get_bytes(v, 1)[0] as i8, - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCByte { - fn from(v: i8) -> MCByte { - MCByte { value: v } - } - } - impl Into for MCByte { - fn into(self) -> i8 { - self.value - } - } - impl PartialEq for MCByte { - fn eq(&self, other: &i8) -> bool { - self.value == *other - } - } - impl Display for MCByte { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCByte { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.is_empty() { - Err("Not enough bytes") - } else { - let mut a = [0u8; 1]; - a.copy_from_slice(&get_bytes(bytes, 1)); - Ok(MCByte { - value: i8::from_be_bytes(a), - }) - } - } - } - impl Into> for MCByte { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of a `u8` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCUnsignedByte { - pub value: u8, // 0 to 255 - } - impl MCUnsignedByte { - pub async fn read(t: &mut T) -> tokio::io::Result { - Ok(MCUnsignedByte::from_bytes(vec![read_byte(t).await?])) - } - pub fn from_bytes(v: Vec) -> MCUnsignedByte { - MCUnsignedByte { - value: get_bytes(v, 1)[0], - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCUnsignedByte { - fn from(v: u8) -> MCUnsignedByte { - MCUnsignedByte { value: v } - } - } - impl Into for MCUnsignedByte { - fn into(self) -> u8 { - self.value - } - } - impl PartialEq for MCUnsignedByte { - fn eq(&self, other: &u8) -> bool { - self.value == *other - } - } - impl Display for MCUnsignedByte { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCUnsignedByte { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.is_empty() { - Err("Not enough bytes") - } else { - let mut a = [0u8; 1]; - a.copy_from_slice(&get_bytes(bytes, 1)); - Ok(MCUnsignedByte { - value: u8::from_be_bytes(a), - }) - } - } - } - impl Into> for MCUnsignedByte { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of an `i16` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCShort { - pub value: i16, // -32768 to 32767 - } - impl MCShort { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - bytes.push(read_byte(t).await?); // MSD - bytes.push(read_byte(t).await?); // LSD - Ok(MCShort::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCShort { - let mut a = [0u8; 2]; - a.copy_from_slice(&get_bytes(v, 2)); - MCShort { - value: i16::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCShort { - fn from(v: i16) -> MCShort { - MCShort { value: v } - } - } - impl Into for MCShort { - fn into(self) -> i16 { - self.value - } - } - impl PartialEq for MCShort { - fn eq(&self, other: &i16) -> bool { - self.value == *other - } - } - impl Display for MCShort { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCShort { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 2 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 2]; - a.copy_from_slice(&get_bytes(bytes, 2)); - Ok(MCShort { - value: i16::from_be_bytes(a), - }) - } - } - } - impl Into> for MCShort { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of a `u16` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCUnsignedShort { - pub value: u16, // 0 to 65535 - } - impl MCUnsignedShort { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - bytes.push(read_byte(t).await?); // MSD - bytes.push(read_byte(t).await?); // LSD - Ok(MCUnsignedShort::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCUnsignedShort { - let mut a = [0u8; 2]; - a.copy_from_slice(&get_bytes(v, 2)); - MCUnsignedShort { - value: u16::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCUnsignedShort { - fn from(v: u16) -> MCUnsignedShort { - MCUnsignedShort { value: v } - } - } - impl Into for MCUnsignedShort { - fn into(self) -> u16 { - self.value - } - } - impl PartialEq for MCUnsignedShort { - fn eq(&self, other: &u16) -> bool { - self.value == *other - } - } - impl Display for MCUnsignedShort { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCUnsignedShort { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 2 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 2]; - a.copy_from_slice(&get_bytes(bytes, 2)); - Ok(MCUnsignedShort { - value: u16::from_be_bytes(a), - }) - } - } - } - impl Into> for MCUnsignedShort { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of an `i32` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCInt { - pub value: i32, // -2147483648 to 2147483647 - } - impl MCInt { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - for _ in 0..4 { - bytes.push(read_byte(t).await?); - } - Ok(MCInt::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCInt { - let mut a = [0u8; 4]; - a.copy_from_slice(&get_bytes(v, 4)); - MCInt { - value: i32::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCInt { - fn from(v: i32) -> MCInt { - MCInt { value: v } - } - } - impl Into for MCInt { - fn into(self) -> i32 { - self.value - } - } - impl PartialEq for MCInt { - fn eq(&self, other: &i32) -> bool { - self.value == *other - } - } - impl Display for MCInt { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCInt { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 4 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 4]; - a.copy_from_slice(&get_bytes(bytes, 4)); - Ok(MCInt { - value: i32::from_be_bytes(a), - }) - } - } - } - impl Into> for MCInt { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of a `u32` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCUnsignedInt { - pub value: u32, // 0 to 4294967295 - } - impl MCUnsignedInt { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - for _ in 0..4 { - bytes.push(read_byte(t).await?); - } - Ok(MCUnsignedInt::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCUnsignedInt { - let mut a = [0u8; 4]; - a.copy_from_slice(&get_bytes(v, 4)); - MCUnsignedInt { - value: u32::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCUnsignedInt { - fn from(v: u32) -> MCUnsignedInt { - MCUnsignedInt { value: v } - } - } - impl Into for MCUnsignedInt { - fn into(self) -> u32 { - self.value - } - } - impl PartialEq for MCUnsignedInt { - fn eq(&self, other: &u32) -> bool { - self.value == *other - } - } - impl Display for MCUnsignedInt { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCUnsignedInt { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 4 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 4]; - a.copy_from_slice(&get_bytes(bytes, 4)); - Ok(MCUnsignedInt { - value: u32::from_be_bytes(a), - }) - } - } - } - impl Into> for MCUnsignedInt { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of an `864` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCLong { - pub value: i64, // -9223372036854775808 to 9223372036854775807 - } - impl MCLong { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - for _ in 0..8 { - bytes.push(read_byte(t).await?); - } - Ok(MCLong::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCLong { - let mut a = [0u8; 8]; - a.copy_from_slice(&get_bytes(v, 8)); - MCLong { - value: i64::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCLong { - fn from(v: i64) -> MCLong { - MCLong { value: v } - } - } - impl Into for MCLong { - fn into(self) -> i64 { - self.value - } - } - impl PartialEq for MCLong { - fn eq(&self, other: &i64) -> bool { - self.value == *other - } - } - impl Display for MCLong { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCLong { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 8 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 8]; - a.copy_from_slice(&get_bytes(bytes, 8)); - Ok(MCLong { - value: i64::from_be_bytes(a), - }) - } - } - } - impl Into> for MCLong { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of a `u64` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCUnsignedLong { - pub value: u64, // 0 to 18446744073709551615 - } - impl MCUnsignedLong { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - for _ in 0..8 { - bytes.push(read_byte(t).await?); - } - Ok(MCUnsignedLong::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCUnsignedLong { - let mut a = [0u8; 8]; - a.copy_from_slice(&get_bytes(v, 8)); - MCUnsignedLong { - value: u64::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCUnsignedLong { - fn from(v: u64) -> MCUnsignedLong { - MCUnsignedLong { value: v } - } - } - impl Into for MCUnsignedLong { - fn into(self) -> u64 { - self.value - } - } - impl PartialEq for MCUnsignedLong { - fn eq(&self, other: &u64) -> bool { - self.value == *other - } - } - impl Display for MCUnsignedLong { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCUnsignedLong { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 8 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 8]; - a.copy_from_slice(&get_bytes(bytes, 8)); - Ok(MCUnsignedLong { - value: u64::from_be_bytes(a), - }) - } - } - } - impl Into> for MCUnsignedLong { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of a `f32` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCFloat { - pub value: f32, // 32-bit floating point number - } - impl MCFloat { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - for _ in 0..4 { - bytes.push(read_byte(t).await?); - } - Ok(MCFloat::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCFloat { - let mut a = [0u8; 4]; - a.copy_from_slice(&get_bytes(v, 4)); - MCFloat { - value: f32::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCFloat { - fn from(v: f32) -> MCFloat { - MCFloat { value: v } - } - } - impl Into for MCFloat { - fn into(self) -> f32 { - self.value - } - } - impl PartialEq for MCFloat { - fn eq(&self, other: &f32) -> bool { - self.value == *other - } - } - impl Display for MCFloat { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCFloat { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 4 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 4]; - a.copy_from_slice(&get_bytes(bytes, 4)); - Ok(MCFloat { - value: f32::from_be_bytes(a), - }) - } - } - } - impl Into> for MCFloat { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// The equivalent of a `f64` - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCDouble { - pub value: f64, // 64-bit floating point number - } - impl MCDouble { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut bytes = Vec::new(); - for _ in 0..8 { - bytes.push(read_byte(t).await?); - } - Ok(MCDouble::from_bytes(bytes)) - } - pub fn from_bytes(v: Vec) -> MCDouble { - let mut a = [0u8; 8]; - a.copy_from_slice(&get_bytes(v, 8)); - MCDouble { - value: f64::from_be_bytes(a), - } - } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - impl From for MCDouble { - fn from(v: f64) -> MCDouble { - MCDouble { value: v } - } - } - impl Into for MCDouble { - fn into(self) -> f64 { - self.value - } - } - impl PartialEq for MCDouble { - fn eq(&self, other: &f64) -> bool { - self.value == *other - } - } - impl Display for MCDouble { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCDouble { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - if bytes.len() < 8 { - Err("Not enough bytes") - } else { - let mut a = [0u8; 8]; - a.copy_from_slice(&get_bytes(bytes, 8)); - Ok(MCDouble { - value: f64::from_be_bytes(a), - }) - } - } - } - impl Into> for MCDouble { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } - } - - /// A variable-length integer. - #[derive(Debug, Copy, Clone, PartialEq)] - pub struct MCVarInt { - pub value: i32, // Variable length 32-bit integer - } - impl MCVarInt { - pub async fn read(t: &mut T) -> tokio::io::Result { - let mut num_read = 0; - let mut result = 0i32; - let mut read = 0u8; - let mut run_once = false; - while (read & 0b10000000) != 0 || !run_once { - run_once = true; - read = read_byte(t).await?; - let value = (read & 0b01111111) as i32; - result |= value << (7 * num_read); - num_read += 1; - if num_read > 5 { - return Err(io_error("MCVarInt is too big")); - } - } - Ok(MCVarInt { value: result }) - } - pub fn from_bytes(_v: Vec) -> MCVarInt { - unimplemented!() - } - pub fn to_bytes(&self) -> Vec { - unimplemented!() - } - } - impl From for MCVarInt { - fn from(v: u8) -> MCVarInt { - MCVarInt { value: v as i32 } - } - } - impl Into for MCVarInt { - fn into(self) -> u8 { - self.value as u8 - } - } - impl PartialEq for MCVarInt { - fn eq(&self, other: &u8) -> bool { - self.value == *other as i32 - } - } - impl From for MCVarInt { - fn from(v: i32) -> MCVarInt { - MCVarInt { value: v } - } - } - impl Into for MCVarInt { - fn into(self) -> i32 { - self.value - } - } - impl PartialEq for MCVarInt { - fn eq(&self, other: &i32) -> bool { - self.value == *other - } - } - impl Display for MCVarInt { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) - } - } - impl TryFrom> for MCVarInt { - type Error = &'static str; - fn try_from(bytes: Vec) -> Result { - let mut num_read = 0; - let mut result: i32 = 0; - loop { - let value = bytes[num_read] & 0b01111111; - result |= (value << (7 * num_read)) as i32; - if bytes[num_read] & 0b10000000 == 0x00 { - break; - } - num_read += 1; - if num_read == bytes.len() { - return Err("Not enough bytes"); - } - if num_read > 5 { - return Err("VarInt is too big"); - } - } - Ok(MCVarInt { value: result }) - } - } - impl Into> for MCVarInt { - fn into(self) -> Vec { - let mut value = self.value; - let mut run_once = false; - let mut out: Vec = Vec::new(); - while value != 0 || !run_once { - run_once = true; - let mut temp: u8 = (value & 0b01111111) as u8; - value >>= 7; - if value != 0 { - temp |= 0b10000000; - } - out.push(temp); - } - out - } - } -} diff --git a/src/mctypes/functions.rs b/src/mctypes/functions.rs new file mode 100644 index 0000000..7e17ae5 --- /dev/null +++ b/src/mctypes/functions.rs @@ -0,0 +1,49 @@ +use super::*; + +/// Read a single byte from the given `TcpStream`. +pub async fn read_byte(t: &mut TcpStream) -> tokio::io::Result { + let mut buffer = [0u8; 1]; + t.read_exact(&mut buffer).await?; + Ok(buffer[0]) +} +/// Read `l` bytes from the given `TcpStream`. +pub async fn read_bytes(t: &mut TcpStream, l: usize) -> tokio::io::Result> { + let mut buffer = vec![]; + for _ in 0..l { + buffer.push(read_byte(t).await?); + } + Ok(buffer) +} +/// Write a single byte to the given `TcpStream`. +pub async fn write_byte(t: &mut TcpStream, value: u8) -> tokio::io::Result<()> { + t.write(&[value]).await?; + Ok(()) +} +/// Write multiple bytes to the given `TcpStream`. +pub async fn write_bytes(t: &mut TcpStream, bytes: &[u8]) -> tokio::io::Result<()> { + for b in bytes { + write_byte(t, *b).await?; + } + Ok(()) +} +/// Take `l` bytes from the given `Vec`. +pub fn get_bytes(v: Vec, l: usize) -> Box<[u8]> { + use std::collections::VecDeque; + let mut v = VecDeque::from(v); + while v.len() > l { + v.pop_front(); + } + while v.len() < l { + v.push_front(0u8); + } + let mut a = Vec::new(); + for b in v { + a.push(b); + } + a.into_boxed_slice() +} +/// Makes returning errors shorter. +pub fn io_error(s: &str) -> tokio::io::Error { + use tokio::io::{Error, ErrorKind}; + Error::new(ErrorKind::Other, s) +} diff --git a/src/mctypes/mod.rs b/src/mctypes/mod.rs new file mode 100644 index 0000000..7c5a8bf --- /dev/null +++ b/src/mctypes/mod.rs @@ -0,0 +1,41 @@ +#![allow(dead_code)] + +/// Helper functions. +pub mod functions; +/// All the numbers, from `i8` and `u8` to `i64` and `u64`, plus `VarInt`s. +pub mod numbers; +/// The other types, (booleans and strings). +pub mod other; + +pub use functions::*; +pub use numbers::*; +pub use other::*; +use serde_json::json; +use std::{ + clone::Clone, + convert::{Into, TryFrom}, + fmt::{Debug, Display}, +}; +use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::TcpStream, +}; + +// /// Make sure all types can serialize and deserialize to/from `Vec`. +// pub trait MCType: Into> + TryFrom> + Display { +// pub async fn read(_stream: &mut TcpStream) -> tokio::io::Result; +// } + +pub enum MCTypeError { + NetworkError(tokio::io::Error), + NotEnoughData, + ParseError, +} + +#[async_trait::async_trait] +pub trait MCType: Into> + TryFrom> + Clone + Debug + Display { + fn to_bytes(&self) -> Vec; + fn from_bytes(bytes: Vec) -> Result; + async fn read(t: &mut TcpStream) -> Result; + async fn write(t: &mut TcpStream) -> tokio::io::Result<()>; +} diff --git a/src/mctypes/numbers.rs b/src/mctypes/numbers.rs new file mode 100644 index 0000000..d4d6ca1 --- /dev/null +++ b/src/mctypes/numbers.rs @@ -0,0 +1,734 @@ +use super::*; +use std::convert::{From, Into, TryFrom}; +use std::fmt::Display; + +/// The equivalent of an `i8` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCByte { + pub value: i8, // -128 to 127 +} +impl MCByte { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + Ok(MCByte::from_bytes(vec![read_byte(t).await?])) + } + pub fn from_bytes(v: Vec) -> MCByte { + MCByte { + value: get_bytes(v, 1)[0] as i8, + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCByte { + fn from(v: i8) -> MCByte { + MCByte { value: v } + } +} +impl Into for MCByte { + fn into(self) -> i8 { + self.value + } +} +impl PartialEq for MCByte { + fn eq(&self, other: &i8) -> bool { + self.value == *other + } +} +impl Display for MCByte { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCByte { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.is_empty() { + Err("Not enough bytes") + } else { + let mut a = [0u8; 1]; + a.copy_from_slice(&get_bytes(bytes, 1)); + Ok(MCByte { + value: i8::from_be_bytes(a), + }) + } + } +} +impl Into> for MCByte { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of a `u8` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCUnsignedByte { + pub value: u8, // 0 to 255 +} +impl MCUnsignedByte { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + Ok(MCUnsignedByte::from_bytes(vec![read_byte(t).await?])) + } + pub fn from_bytes(v: Vec) -> MCUnsignedByte { + MCUnsignedByte { + value: get_bytes(v, 1)[0], + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCUnsignedByte { + fn from(v: u8) -> MCUnsignedByte { + MCUnsignedByte { value: v } + } +} +impl Into for MCUnsignedByte { + fn into(self) -> u8 { + self.value + } +} +impl PartialEq for MCUnsignedByte { + fn eq(&self, other: &u8) -> bool { + self.value == *other + } +} +impl Display for MCUnsignedByte { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCUnsignedByte { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.is_empty() { + Err("Not enough bytes") + } else { + let mut a = [0u8; 1]; + a.copy_from_slice(&get_bytes(bytes, 1)); + Ok(MCUnsignedByte { + value: u8::from_be_bytes(a), + }) + } + } +} +impl Into> for MCUnsignedByte { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of an `i16` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCShort { + pub value: i16, // -32768 to 32767 +} +impl MCShort { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + bytes.push(read_byte(t).await?); // MSD + bytes.push(read_byte(t).await?); // LSD + Ok(MCShort::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCShort { + let mut a = [0u8; 2]; + a.copy_from_slice(&get_bytes(v, 2)); + MCShort { + value: i16::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCShort { + fn from(v: i16) -> MCShort { + MCShort { value: v } + } +} +impl Into for MCShort { + fn into(self) -> i16 { + self.value + } +} +impl PartialEq for MCShort { + fn eq(&self, other: &i16) -> bool { + self.value == *other + } +} +impl Display for MCShort { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCShort { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 2 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 2]; + a.copy_from_slice(&get_bytes(bytes, 2)); + Ok(MCShort { + value: i16::from_be_bytes(a), + }) + } + } +} +impl Into> for MCShort { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of a `u16` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCUnsignedShort { + pub value: u16, // 0 to 65535 +} +impl MCUnsignedShort { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + bytes.push(read_byte(t).await?); // MSD + bytes.push(read_byte(t).await?); // LSD + Ok(MCUnsignedShort::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCUnsignedShort { + let mut a = [0u8; 2]; + a.copy_from_slice(&get_bytes(v, 2)); + MCUnsignedShort { + value: u16::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCUnsignedShort { + fn from(v: u16) -> MCUnsignedShort { + MCUnsignedShort { value: v } + } +} +impl Into for MCUnsignedShort { + fn into(self) -> u16 { + self.value + } +} +impl PartialEq for MCUnsignedShort { + fn eq(&self, other: &u16) -> bool { + self.value == *other + } +} +impl Display for MCUnsignedShort { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCUnsignedShort { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 2 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 2]; + a.copy_from_slice(&get_bytes(bytes, 2)); + Ok(MCUnsignedShort { + value: u16::from_be_bytes(a), + }) + } + } +} +impl Into> for MCUnsignedShort { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of an `i32` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCInt { + pub value: i32, // -2147483648 to 2147483647 +} +impl MCInt { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + for _ in 0..4 { + bytes.push(read_byte(t).await?); + } + Ok(MCInt::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCInt { + let mut a = [0u8; 4]; + a.copy_from_slice(&get_bytes(v, 4)); + MCInt { + value: i32::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCInt { + fn from(v: i32) -> MCInt { + MCInt { value: v } + } +} +impl Into for MCInt { + fn into(self) -> i32 { + self.value + } +} +impl PartialEq for MCInt { + fn eq(&self, other: &i32) -> bool { + self.value == *other + } +} +impl Display for MCInt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCInt { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 4 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 4]; + a.copy_from_slice(&get_bytes(bytes, 4)); + Ok(MCInt { + value: i32::from_be_bytes(a), + }) + } + } +} +impl Into> for MCInt { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of a `u32` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCUnsignedInt { + pub value: u32, // 0 to 4294967295 +} +impl MCUnsignedInt { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + for _ in 0..4 { + bytes.push(read_byte(t).await?); + } + Ok(MCUnsignedInt::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCUnsignedInt { + let mut a = [0u8; 4]; + a.copy_from_slice(&get_bytes(v, 4)); + MCUnsignedInt { + value: u32::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCUnsignedInt { + fn from(v: u32) -> MCUnsignedInt { + MCUnsignedInt { value: v } + } +} +impl Into for MCUnsignedInt { + fn into(self) -> u32 { + self.value + } +} +impl PartialEq for MCUnsignedInt { + fn eq(&self, other: &u32) -> bool { + self.value == *other + } +} +impl Display for MCUnsignedInt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCUnsignedInt { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 4 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 4]; + a.copy_from_slice(&get_bytes(bytes, 4)); + Ok(MCUnsignedInt { + value: u32::from_be_bytes(a), + }) + } + } +} +impl Into> for MCUnsignedInt { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of an `864` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCLong { + pub value: i64, // -9223372036854775808 to 9223372036854775807 +} +impl MCLong { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + for _ in 0..8 { + bytes.push(read_byte(t).await?); + } + Ok(MCLong::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCLong { + let mut a = [0u8; 8]; + a.copy_from_slice(&get_bytes(v, 8)); + MCLong { + value: i64::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCLong { + fn from(v: i64) -> MCLong { + MCLong { value: v } + } +} +impl Into for MCLong { + fn into(self) -> i64 { + self.value + } +} +impl PartialEq for MCLong { + fn eq(&self, other: &i64) -> bool { + self.value == *other + } +} +impl Display for MCLong { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCLong { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 8 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 8]; + a.copy_from_slice(&get_bytes(bytes, 8)); + Ok(MCLong { + value: i64::from_be_bytes(a), + }) + } + } +} +impl Into> for MCLong { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of a `u64` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCUnsignedLong { + pub value: u64, // 0 to 18446744073709551615 +} +impl MCUnsignedLong { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + for _ in 0..8 { + bytes.push(read_byte(t).await?); + } + Ok(MCUnsignedLong::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCUnsignedLong { + let mut a = [0u8; 8]; + a.copy_from_slice(&get_bytes(v, 8)); + MCUnsignedLong { + value: u64::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCUnsignedLong { + fn from(v: u64) -> MCUnsignedLong { + MCUnsignedLong { value: v } + } +} +impl Into for MCUnsignedLong { + fn into(self) -> u64 { + self.value + } +} +impl PartialEq for MCUnsignedLong { + fn eq(&self, other: &u64) -> bool { + self.value == *other + } +} +impl Display for MCUnsignedLong { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCUnsignedLong { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 8 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 8]; + a.copy_from_slice(&get_bytes(bytes, 8)); + Ok(MCUnsignedLong { + value: u64::from_be_bytes(a), + }) + } + } +} +impl Into> for MCUnsignedLong { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of a `f32` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCFloat { + pub value: f32, // 32-bit floating point number +} +impl MCFloat { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + for _ in 0..4 { + bytes.push(read_byte(t).await?); + } + Ok(MCFloat::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCFloat { + let mut a = [0u8; 4]; + a.copy_from_slice(&get_bytes(v, 4)); + MCFloat { + value: f32::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCFloat { + fn from(v: f32) -> MCFloat { + MCFloat { value: v } + } +} +impl Into for MCFloat { + fn into(self) -> f32 { + self.value + } +} +impl PartialEq for MCFloat { + fn eq(&self, other: &f32) -> bool { + self.value == *other + } +} +impl Display for MCFloat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCFloat { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 4 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 4]; + a.copy_from_slice(&get_bytes(bytes, 4)); + Ok(MCFloat { + value: f32::from_be_bytes(a), + }) + } + } +} +impl Into> for MCFloat { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// The equivalent of a `f64` +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCDouble { + pub value: f64, // 64-bit floating point number +} +impl MCDouble { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut bytes = Vec::new(); + for _ in 0..8 { + bytes.push(read_byte(t).await?); + } + Ok(MCDouble::from_bytes(bytes)) + } + pub fn from_bytes(v: Vec) -> MCDouble { + let mut a = [0u8; 8]; + a.copy_from_slice(&get_bytes(v, 8)); + MCDouble { + value: f64::from_be_bytes(a), + } + } + pub fn to_bytes(&self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} +impl From for MCDouble { + fn from(v: f64) -> MCDouble { + MCDouble { value: v } + } +} +impl Into for MCDouble { + fn into(self) -> f64 { + self.value + } +} +impl PartialEq for MCDouble { + fn eq(&self, other: &f64) -> bool { + self.value == *other + } +} +impl Display for MCDouble { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCDouble { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.len() < 8 { + Err("Not enough bytes") + } else { + let mut a = [0u8; 8]; + a.copy_from_slice(&get_bytes(bytes, 8)); + Ok(MCDouble { + value: f64::from_be_bytes(a), + }) + } + } +} +impl Into> for MCDouble { + fn into(self) -> Vec { + self.value.to_be_bytes().to_vec() + } +} + +/// A variable-length integer. +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct MCVarInt { + pub value: i32, // Variable length 32-bit integer +} +impl MCVarInt { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut num_read = 0; + let mut result = 0i32; + let mut read = 0u8; + let mut run_once = false; + while (read & 0b10000000) != 0 || !run_once { + run_once = true; + read = read_byte(t).await?; + let value = (read & 0b01111111) as i32; + result |= value << (7 * num_read); + num_read += 1; + if num_read > 5 { + return Err(io_error("MCVarInt is too big")); + } + } + Ok(MCVarInt { value: result }) + } + pub fn from_bytes(_v: Vec) -> MCVarInt { + unimplemented!() + } + pub fn to_bytes(&self) -> Vec { + unimplemented!() + } +} +impl From for MCVarInt { + fn from(v: u8) -> MCVarInt { + MCVarInt { value: v as i32 } + } +} +impl Into for MCVarInt { + fn into(self) -> u8 { + self.value as u8 + } +} +impl PartialEq for MCVarInt { + fn eq(&self, other: &u8) -> bool { + self.value == *other as i32 + } +} +impl From for MCVarInt { + fn from(v: i32) -> MCVarInt { + MCVarInt { value: v } + } +} +impl Into for MCVarInt { + fn into(self) -> i32 { + self.value + } +} +impl PartialEq for MCVarInt { + fn eq(&self, other: &i32) -> bool { + self.value == *other + } +} +impl Display for MCVarInt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCVarInt { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + let mut num_read = 0; + let mut result: i32 = 0; + loop { + let value = bytes[num_read] & 0b01111111; + result |= (value << (7 * num_read)) as i32; + if bytes[num_read] & 0b10000000 == 0x00 { + break; + } + num_read += 1; + if num_read == bytes.len() { + return Err("Not enough bytes"); + } + if num_read > 5 { + return Err("VarInt is too big"); + } + } + Ok(MCVarInt { value: result }) + } +} +impl Into> for MCVarInt { + fn into(self) -> Vec { + let mut value = self.value; + let mut run_once = false; + let mut out: Vec = Vec::new(); + while value != 0 || !run_once { + run_once = true; + let mut temp: u8 = (value & 0b01111111) as u8; + value >>= 7; + if value != 0 { + temp |= 0b10000000; + } + out.push(temp); + } + out + } +} diff --git a/src/mctypes/other.rs b/src/mctypes/other.rs new file mode 100644 index 0000000..2da991f --- /dev/null +++ b/src/mctypes/other.rs @@ -0,0 +1,293 @@ +use super::*; +use std::convert::{From, Into, TryFrom}; +use std::fmt::{Debug, Display}; + +/// The equivalent of a `bool`. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum MCBoolean { + True, + False, +} +impl From for MCBoolean { + fn from(v: bool) -> MCBoolean { + if v { + MCBoolean::True + } else { + MCBoolean::False + } + } +} +impl Into for MCBoolean { + fn into(self) -> bool { + match self { + MCBoolean::True => true, + MCBoolean::False => false, + } + } +} +impl Display for MCBoolean { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + MCBoolean::True => "true", + MCBoolean::False => "false", + } + ) + } +} +impl TryFrom> for MCBoolean { + type Error = &'static str; + fn try_from(bytes: Vec) -> Result { + if bytes.is_empty() { + Err("Not enough bytes") + } else if bytes[0] == 1u8 { + Ok(MCBoolean::True) + } else { + Ok(MCBoolean::False) + } + } +} +impl Into> for MCBoolean { + fn into(self) -> Vec { + match self { + MCBoolean::True => vec![0x01], + MCBoolean::False => vec![0x00], + } + } +} +impl MCBoolean { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let b = read_byte(t).await?; + Ok(MCBoolean::try_from(vec![b]).unwrap()) + } +} + +/// The equivalent of a `String`. +#[derive(PartialEq)] +pub struct MCString { + pub value: String, +} +impl From<&str> for MCString { + fn from(s: &str) -> MCString { + MCString { + value: s.to_owned(), + } + } +} +impl From for MCString { + fn from(s: String) -> MCString { + MCString { value: s } + } +} +impl Into for MCString { + fn into(self) -> String { + self.value + } +} +impl PartialEq<&str> for MCString { + fn eq(&self, other: &&str) -> bool { + self.value == **other + } +} +impl PartialEq for MCString { + fn eq(&self, other: &String) -> bool { + self.value == *other + } +} +impl PartialEq<&String> for MCString { + fn eq(&self, other: &&String) -> bool { + self.value == **other + } +} +impl Clone for MCString { + fn clone(&self) -> Self { + MCString { + value: self.value.clone(), + } + } +} +impl Debug for MCString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "MCString {{ \"{}\" ({} chars) }}", + self.value, + self.value.len() + ) + } +} +impl Display for MCString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.value) + } +} +impl TryFrom> for MCString { + type Error = &'static str; + fn try_from(_bytes: Vec) -> Result { + Err("Cannot read MCString from bytes") + } +} +impl Into> for MCString { + fn into(self) -> Vec { + let mut out = vec![]; + let str_len: Vec = MCVarInt::from(self.value.len() as i32).into(); + for b in str_len { + out.push(b); + } + for b in self.value.into_bytes() { + out.push(b); + } + out + } +} +impl MCString { + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let str_len = MCVarInt::read(t).await?; + let mut str_bytes = vec![]; + for _ in 0i32..str_len.into() { + str_bytes.push(read_byte(t).await?); + } + Ok(MCString { + value: String::from_utf8_lossy(&str_bytes).to_string(), + }) + } +} + +/// A normal `MCString`, but with extra embedded formatting data. +#[derive(Debug, PartialEq)] +pub struct MCChat { + pub text: MCString, +} +impl From<&str> for MCChat { + fn from(s: &str) -> MCChat { + MCChat { text: s.into() } + } +} +impl From for MCChat { + fn from(s: String) -> MCChat { + MCChat { text: s.into() } + } +} +impl Into for MCChat { + fn into(self) -> String { + self.text.value + } +} +impl PartialEq<&str> for MCChat { + fn eq(&self, other: &&str) -> bool { + self.text.value == **other + } +} +impl PartialEq for MCChat { + fn eq(&self, other: &String) -> bool { + self.text.value == *other + } +} +impl PartialEq<&String> for MCChat { + fn eq(&self, other: &&String) -> bool { + self.text.value == **other + } +} +impl Clone for MCChat { + fn clone(&self) -> Self { + MCChat { + text: self.text.clone(), + } + } +} +impl Display for MCChat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "\"{}\" ({} chars)", + self.text.value, + self.text.value.len() + ) + } +} +impl TryFrom> for MCChat { + type Error = &'static str; + fn try_from(_bytes: Vec) -> Result { + Err("Cannot read MCChat from bytes") + } +} +impl Into> for MCChat { + fn into(self) -> Vec { + // Just output + // {"text": ""} + Into::::into( + json!({ + "text": self.text.value + }) + .to_string(), + ) + .into() + } +} +impl MCChat { + pub async fn read(_t: &mut TcpStream) -> tokio::io::Result { + Err(io_error("Cannot read MCChat from stream")) + } +} + +// TODO: Actually make the MCPosition work. +#[derive(Debug, PartialEq, Clone)] +pub struct MCPosition { + x: MCLong, + y: MCLong, + z: MCLong, +} +impl Display for MCPosition { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "({}, {}, {})", self.x, self.y, self.z,) + } +} +impl TryFrom> for MCPosition { + type Error = &'static str; + fn try_from(_bytes: Vec) -> Result { + Err("Cannot read MCPosition from bytes") + } +} +impl Into> for MCPosition { + fn into(self) -> Vec { + // Just output + // {"text": ""} + let mut out = vec![]; + let mut temp = vec![]; + temp.extend_from_slice( + &((((Into::::into(self.x) & 0x3FFFFFF) << 38) + | ((Into::::into(self.y) & 0xFFF) << 26) + | (Into::::into(self.z) & 0x3FFFFFF)) as u64) + .to_be_bytes(), + ); + // temp.extend_from_slice(&"{\"text\": \"".to_owned().into_bytes()); + // temp.extend_from_slice(&self.text.value.into_bytes()); + // temp.extend_from_slice(&"\"}".to_owned().into_bytes()); + out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); + out.extend_from_slice(&temp); + out + } +} +impl MCPosition { + pub fn new() -> MCPosition { + MCPosition { + x: 0.into(), + y: 0.into(), + z: 0.into(), + } + } + pub async fn read(_t: &mut TcpStream) -> tokio::io::Result { + Err(io_error("Cannot read MCPosition from stream")) + } +} +impl Default for MCPosition { + fn default() -> Self { + MCPosition { + x: 0.into(), + y: 0.into(), + z: 0.into(), + } + } +}