diff --git a/Cargo.lock b/Cargo.lock index a1e4c39..dccb4f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "arrayref" version = "0.3.6" @@ -40,6 +42,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "bytes" version = "1.0.1" @@ -52,6 +60,12 @@ version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "0.1.10" @@ -95,6 +109,7 @@ dependencies = [ "async-trait", "chrono", "ctrlc", + "fastnbt", "fern", "futures", "lazy_static", @@ -117,6 +132,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "fastnbt" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a5f728dc3e8c3154312f657d6cc9afd081b8c1becddc62ed67448e0a19adfd" +dependencies = [ + "byteorder", + "cesu8", + "serde", +] + [[package]] name = "fern" version = "0.6.0" diff --git a/Cargo.toml b/Cargo.toml index 5baa10f..e1fa9a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,8 @@ lazy_static = "1.4.0" ctrlc = "3.1.8" futures = "0.3.13" uuid = "0.8.2" +fastnbt = "*" + # colorful = "0.2.1" # ozelot = "0.9.0" # Ozelot 0.9.0 supports protocol version 578 (1.15.2) # toml = "0.5.6" diff --git a/src/entity/mod.rs b/src/entity/mod.rs deleted file mode 100644 index f28d7c2..0000000 --- a/src/entity/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod player; diff --git a/src/entity/player.rs b/src/entity/player.rs deleted file mode 100644 index 4bdd975..0000000 --- a/src/entity/player.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::world::location::Location; -use uuid::Uuid; - -#[derive(Debug, Clone, PartialEq)] -pub struct Player { - pub position: Location, - pub uuid: Uuid, - names: (String, Option), -} -impl Player { - pub fn new() -> Player { - Player { - position: Location::zero(), - uuid: Uuid::nil(), - names: ("Player".into(), None), - } - } - pub fn username(&self) -> &String { - &self.names.0 - } - pub fn username_mut(&mut self) -> &mut String { - &mut self.names.0 - } - pub fn display_name(&self) -> &String { - match &self.names.1 { - Some(name) => name, - None => &self.names.0, - } - } - pub fn display_name_mut(&mut self) -> &mut Option { - &mut self.names.1 - } -} -impl Default for Player { - fn default() -> Self { - Player::new() - } -} diff --git a/src/lib.rs b/src/lib.rs index c367efe..0be38f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,11 @@ #[macro_use] extern crate lazy_static; -/// Data types for every entity in the game. -pub mod entity; -/// Data types needed for the Minecraft protocol. pub mod mctypes; -/// The logic for the server. +pub mod net; pub mod server; -/// Data types for blocks, chunks, dimensions, and world files. -pub mod world; -use log::*; -use serde::{Deserialize, Serialize}; +use crate::prelude::*; use std::sync::mpsc::{self, Receiver}; #[derive(Serialize, Deserialize)] @@ -23,7 +17,7 @@ pub struct Config { } lazy_static! { - static ref CONFIG: Config = { + pub static ref CONFIG: Config = { let config_from_file = || -> std::io::Result { use std::{fs::File, io::prelude::*}; let mut data = String::new(); @@ -50,7 +44,7 @@ lazy_static! { } } }; - static ref FAVICON: std::io::Result> = { + pub static ref FAVICON: std::io::Result> = { use std::{fs::File, io::prelude::*}; let mut data = vec![]; let mut file = File::open(CONFIG.favicon.clone())?; @@ -97,3 +91,19 @@ pub fn init() -> Receiver<()> { pub async fn start_server() -> server::Server { server::Server::new(format!("0.0.0.0:{}", CONFIG.port)) } + +pub mod prelude { + pub use crate::{mctypes::*, CONFIG, FAVICON}; + pub use log::*; + pub use serde::{Deserialize, Serialize}; + pub type JSON = serde_json::Value; + pub type NBT = fastnbt::Value; + pub use std::collections::VecDeque; + #[derive(Clone, Debug, PartialEq)] + pub enum ParseError { + NotEnoughData, + InvalidData, + VarIntTooBig, + } + pub type ParseResult = Result<(T, usize), ParseError>; +} diff --git a/src/mctypes/functions.rs b/src/mctypes/functions.rs deleted file mode 100644 index 7e17ae5..0000000 --- a/src/mctypes/functions.rs +++ /dev/null @@ -1,49 +0,0 @@ -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 index 7c5a8bf..7abb13b 100644 --- a/src/mctypes/mod.rs +++ b/src/mctypes/mod.rs @@ -1,41 +1,5 @@ -#![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 index 89160a7..38624c7 100644 --- a/src/mctypes/numbers.rs +++ b/src/mctypes/numbers.rs @@ -1,736 +1,187 @@ -use super::*; -use std::convert::{From, Into, TryFrom}; -use std::fmt::Display; +use crate::prelude::*; -/// 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 parse_byte(data: &[u8]) -> ParseResult { + if data.is_empty() { + Err(ParseError::NotEnoughData) + } else { + let value = i8::from_be_bytes([data[0]]); + Ok((value, 1)) } - pub fn from_bytes(v: Vec) -> MCByte { - MCByte { - value: get_bytes(v, 1)[0] as i8, +} +pub fn serialize_byte(num: i8) -> [u8; 1] { + num.to_be_bytes() +} + +pub fn parse_short(data: &[u8]) -> ParseResult { + if data.len() < 2 { + Err(ParseError::NotEnoughData) + } else { + let value = i16::from_be_bytes([data[0], data[1]]); + Ok((value, 2)) + } +} +pub fn serialize_short(num: i16) -> [u8; 2] { + num.to_be_bytes() +} + +pub fn parse_int(data: &[u8]) -> ParseResult { + if data.len() < 4 { + Err(ParseError::NotEnoughData) + } else { + let value = i32::from_be_bytes([data[0], data[1], data[2], data[3]]); + Ok((value, 4)) + } +} +pub fn serialize_int(num: i32) -> [u8; 4] { + num.to_be_bytes() +} + +pub fn parse_long(data: &[u8]) -> ParseResult { + if data.len() < 8 { + Err(ParseError::NotEnoughData) + } else { + let value = i64::from_be_bytes([ + data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], + ]); + Ok((value, 8)) + } +} +pub fn serialize_long(num: i64) -> [u8; 8] { + num.to_be_bytes() +} + +pub fn parse_varint(data: &[u8]) -> ParseResult { + let mut offset = 0; + let mut output = 0i32; + let mut bytes_read = 0i32; + + loop { + if data.len() <= offset { + return Err(ParseError::NotEnoughData); + } + + output |= (((data[offset] & 0x7f) as i32) << bytes_read * 7) as i32; + bytes_read += 1; + if data[offset] & 0x80 != 0x80 { + break; + } + offset += 1; + if bytes_read >= 5 { + return Err(ParseError::VarIntTooBig); } } - pub fn to_bytes(&self) -> Vec { - self.value.to_be_bytes().to_vec() - } + + Ok((output, bytes_read as usize)) } -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") +pub fn serialize_varint(value: i32) -> Vec { + println!("serializing {}", value); + let mut value = value as u32; + let mut output = vec![]; + loop { + let data = (value & 0x7f) as u8; + value >>= 7; + println!("\tvalue: {}", value); + + if value == 0 { + output.push(data); + break; } else { - let mut a = [0u8; 1]; - a.copy_from_slice(&get_bytes(bytes, 1)); - Ok(MCByte { - value: i8::from_be_bytes(a), - }) + output.push(data | 0x80); } } -} -impl Into> for MCByte { - fn into(self) -> Vec { - self.value.to_be_bytes().to_vec() - } + output } -/// 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() +pub fn parse_unsigned_byte(data: &[u8]) -> ParseResult { + if data.is_empty() { + Err(ParseError::NotEnoughData) + } else { + let value = u8::from_be_bytes([data[0]]); + Ok((value, 1)) } } -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() - } +pub fn serialize_unsigned_byte(num: u8) -> [u8; 1] { + num.to_be_bytes() } -/// 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() +pub fn parse_unsigned_short(data: &[u8]) -> ParseResult { + if data.len() < 2 { + Err(ParseError::NotEnoughData) + } else { + let value = u16::from_be_bytes([data[0], data[1]]); + Ok((value, 2)) } } -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() - } +pub fn serialize_unsigned_short(num: u16) -> [u8; 2] { + num.to_be_bytes() } -/// 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() +pub fn parse_unsigned_int(data: &[u8]) -> ParseResult { + if data.len() < 4 { + Err(ParseError::NotEnoughData) + } else { + let value = u32::from_be_bytes([data[0], data[1], data[2], data[3]]); + Ok((value, 4)) } } -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() - } +pub fn serialize_unsigned_int(num: u32) -> [u8; 4] { + num.to_be_bytes() } -/// 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() +pub fn parse_unsigned_long(data: &[u8]) -> ParseResult { + if data.len() < 8 { + Err(ParseError::NotEnoughData) + } else { + let value = u64::from_be_bytes([ + data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], + ]); + Ok((value, 8)) } } -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() - } +pub fn serialize_unsigned_long(num: u64) -> [u8; 8] { + num.to_be_bytes() } -/// 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() - } -} +#[cfg(test)] +mod tests { + use super::*; -/// 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), + #[test] + fn parse_varint_works() { + let tests = vec![ + (Ok((0, 1)), vec![0x00]), + (Ok((1, 1)), vec![0x01]), + (Ok((2, 1)), vec![0x02]), + (Ok((127, 1)), vec![0x7f]), + (Ok((128, 2)), vec![0x80, 0x01]), + (Ok((255, 2)), vec![0xff, 0x01]), + (Ok((25565, 3)), vec![0xdd, 0xc7, 0x01]), + (Ok((2097151, 3)), vec![0xff, 0xff, 0x7f]), + (Ok((2147483647, 5)), vec![0xff, 0xff, 0xff, 0xff, 0x07]), + (Ok((-1, 5)), vec![0xff, 0xff, 0xff, 0xff, 0x0f]), + (Ok((-2147483648, 5)), vec![0x80, 0x80, 0x80, 0x80, 0x08]), + ]; + for test in &tests { + assert_eq!(test.0, parse_varint(&test.1)); } } - 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), - }) + #[test] + fn serialize_varint_works() { + let tests = vec![ + (0, vec![0x00]), + (1, vec![0x01]), + (2, vec![0x02]), + (127, vec![0x7f]), + (128, vec![0x80, 0x01]), + (255, vec![0xff, 0x01]), + (25565, vec![0xdd, 0xc7, 0x01]), + (2097151, vec![0xff, 0xff, 0x7f]), + (2147483647, vec![0xff, 0xff, 0xff, 0xff, 0x07]), + (-1, vec![0xff, 0xff, 0xff, 0xff, 0x0f]), + (-2147483648, vec![0x80, 0x80, 0x80, 0x80, 0x08]), + ]; + for test in &tests { + assert_eq!(serialize_varint(test.0), test.1); } } } -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 = 0i128; - 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 i128; - result |= value << (7 * num_read); - num_read += 1; - if num_read > 5 { - return Err(io_error("MCVarInt is too big")); - } - } - Ok(MCVarInt { - value: result as i32, - }) - } - pub fn from_bytes(_v: Vec) -> MCVarInt { - unimplemented!() - } - pub fn to_bytes(&self) -> Vec { - Into::>::into(*self) - } -} -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 index 2da991f..0952e0b 100644 --- a/src/mctypes/other.rs +++ b/src/mctypes/other.rs @@ -1,293 +1,43 @@ use super::*; -use std::convert::{From, Into, TryFrom}; -use std::fmt::{Debug, Display}; +use crate::prelude::*; -/// 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 - } +pub fn parse_bool(data: &[u8]) -> ParseResult { + if data.is_empty() { + Err(ParseError::NotEnoughData) + } else { + Ok((data[0] == 1, 1)) } } -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()) +pub fn serialize_bool(value: bool) -> [u8; 1] { + if value { + [0x01] + } else { + [0x00] } } -/// 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(), - } +pub fn parse_string(data: &[u8]) -> ParseResult { + let mut offset = 0; + let (length, offset_delta) = parse_varint(&data[offset..])?; + offset += offset_delta; + let length = length as usize; + if data.len() < offset + length { + return Err(ParseError::NotEnoughData); } + let output = String::from_utf8_lossy(&data[offset..offset + length]).to_string(); + offset += length; + Ok((output, offset)) } -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(), - }) - } +pub fn serialize_string(value: &str) -> Vec { + let mut output = vec![]; + output.extend_from_slice(&serialize_varint(value.len() as i32)); + output.extend_from_slice(value.as_bytes()); + output } -/// A normal `MCString`, but with extra embedded formatting data. -#[derive(Debug, PartialEq)] -pub struct MCChat { - pub text: MCString, +pub fn parse_json(data: &[u8]) -> ParseResult { + unimplemented!() } -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(), - } - } +pub fn serialize_json(value: JSON) -> Vec { + unimplemented!() } diff --git a/src/net/mod.rs b/src/net/mod.rs new file mode 100644 index 0000000..6b73a97 --- /dev/null +++ b/src/net/mod.rs @@ -0,0 +1,24 @@ +pub mod packets; + +use crate::prelude::*; +use tokio::net::TcpStream; + +#[derive(PartialEq, Copy, Clone, Debug)] +pub enum NetworkClientState { + Disconnected, + Handshake, + Status, + Login, + Play, +} + +pub struct NetworkClient { + pub status: NetworkClientState, + pub stream: TcpStream, + pub buffer: VecDeque, +} +impl NetworkClient { + pub async fn read_bytes(&mut self) -> Result<(), ()> { + unimplemented!() + } +} diff --git a/src/net/packets.rs b/src/net/packets.rs new file mode 100644 index 0000000..90b3577 --- /dev/null +++ b/src/net/packets.rs @@ -0,0 +1,104 @@ +use super::NetworkClientState; +use crate::prelude::*; + +#[derive(Clone, PartialEq, Debug)] +pub enum Packet { + // Handshake + SH00Handshake { + protocol_version: i32, + server_address: String, + server_port: u16, + next_state: NetworkClientState, + }, + + // Status + CS00Response { + json_response: JSON, + }, + CS01Pong { + payload: i64, + }, + SS00Request, + SS01Ping { + payload: i64, + }, + // Login + // Play +} +impl Packet { + pub fn parse_body( + data: &[u8], + length: usize, + id: usize, + state: NetworkClientState, + serverbound: bool, + ) -> ParseResult { + use NetworkClientState::*; + use Packet::*; + + let mut offset = 0; + match state { + Disconnected => Err(ParseError::InvalidData), + Handshake => { + if id == 0x00 && serverbound { + let (protocol_version, offset_delta) = parse_varint(&data[offset..])?; + offset += offset_delta; + let (server_address, offset_delta) = parse_string(&data[offset..])?; + offset += offset_delta; + let (server_port, offset_delta) = parse_unsigned_short(&data[offset..])?; + offset += offset_delta; + let (next_state, offset_delta) = parse_varint(&data[offset..])?; + offset += offset_delta; + let next_state = match next_state { + 0 => NetworkClientState::Status, + 1 => NetworkClientState::Login, + _ => return Err(ParseError::InvalidData), + }; + Ok(( + Packet::SH00Handshake { + protocol_version, + server_address, + server_port, + next_state, + }, + offset, + )) + } else { + Err(ParseError::InvalidData) + } + } + Status => match id { + 0x00 => { + if serverbound { + unimplemented!("Parse SS00Request") + } else { + unimplemented!("Parse CS00Response") + } + } + 0x01 => { + if serverbound { + unimplemented!("Parse SS01Ping") + } else { + unimplemented!("Parse CS01Pong") + } + } + _ => Err(ParseError::InvalidData), + }, + Login => unimplemented!("Parse Login packet"), + Play => unimplemented!("Parse Play packet"), + } + } + pub fn serialize(&self) -> Vec { + use Packet::*; + let (id, mut body): (usize, Vec) = match self { + CS00Response { json_response } => (0x00, serialize_json(json_response.clone())), + CS01Pong { payload } => (0x01, serialize_long(payload.clone()).to_vec()), + _ => unimplemented!(), + }; + let mut id_and_body = serialize_varint(id as i32); + id_and_body.append(&mut body); + let mut output = serialize_varint(id_and_body.len() as i32); + output.append(&mut id_and_body); + output + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs index 9153225..17648c5 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,272 +1,18 @@ -/// Internal messaging for the server. -pub mod messages; -/// Put the network client struct in its own file. -pub mod net; +use crate::prelude::*; +use tokio::net::ToSocketAddrs; -use crate::entity::player::Player; -use crate::{mctypes::*, CONFIG, FAVICON}; -use log::*; -use messages::*; -use net::{ - packets::{self, Packet, PacketCommon}, - *, -}; -use serde_json::json; -use std::sync::mpsc::{self, Receiver, TryRecvError}; -use std::time::Duration; -use tokio::net::{TcpListener, ToSocketAddrs}; +#[derive(Clone, Debug, PartialEq)] +pub enum ServerError {} -/// The struct containing all the data and running all the updates. -pub struct Server { - network_clients: Vec, - network_receiver: Receiver, - pub players: Vec, -} +pub struct Server {} impl Server { - pub fn new(addr: A) -> Server { - let (network_client_tx, network_client_rx) = mpsc::channel(); - let (serverbound_message_tx, _serverbound_message_rx) = mpsc::channel(); - tokio::task::spawn(async move { - let listener = TcpListener::bind(addr) - .await - .expect("Could not bind to TCP socket"); - let mut id = 0; - loop { - let (stream, _) = listener - .accept() - .await - .expect("Network receiver disconnected"); - network_client_tx - .send(NetworkClient::new( - stream, - id as u128, - serverbound_message_tx.clone(), - )) - .expect("Network receiver disconnected"); - id += 1; - } - }); - info!("Network server started!"); - Server { - network_receiver: network_client_rx, - network_clients: vec![], - // message_receiver: serverbound_message_rx, - players: vec![], - } + pub fn new(bind_address: A) -> Server { + unimplemented!() } - - /// Shut down the server. - /// - /// Disconnects all clients. - pub async fn shutdown(&mut self) { - info!( - "Server shutting down. Uptime: {:?}", - crate::START_TIME.elapsed() - ); - self.broadcast_message(ClientboundMessage::Disconnect( - "The server is shutting down".into(), - )) - .await; + pub async fn update(&mut self) -> Result<(), ServerError> { + unimplemented!() } - - pub fn num_players(&self) -> usize { - let mut num = 0; - for client in &self.network_clients { - if client.state == NetworkClientState::Play { - num += 1; - } - } - num - } - - /// Send a `ClientboundMessage` to all connected network clients. - pub async fn broadcast_message(&mut self, message: ClientboundMessage) { - let mut v = Vec::new(); - for client in self.network_clients.iter_mut() { - v.push(client.handle_message(message.clone())); - } - futures::future::join_all(v).await; - } - - /// Get a client from their id. - pub fn client_from_id(&mut self, client_id: u128) -> Option<&mut NetworkClient> { - // Find the client based on id. - let mut client_index = -1isize; - for (i, c) in self.network_clients.iter().enumerate() { - if c.id == client_id { - client_index = i as isize; - break; - } - } - if client_index == -1 { - return None; - } - Some(&mut self.network_clients[client_index as usize]) - } - - /// Update the game server. - pub async fn update(&mut self) -> tokio::io::Result<()> { - // Get new clients from the network listener thread. - loop { - match self.network_receiver.try_recv() { - Ok(client) => { - info!( - "Got client at {}", - client.stream.peer_addr().expect("could not get peer addr") - ); - self.network_clients.push(client) - } - Err(TryRecvError::Empty) => break, - Err(TryRecvError::Disconnected) => panic!("network sender disconnected"), - } - } - // Read new packets from each client. - for client in self.network_clients.iter_mut() { - // Update and ignore errors. - if client.update().await.is_err() { - client.force_disconnect(); - } - } - // Update the client and server according to each packet. - let mut packets = vec![]; - for client in self.network_clients.iter_mut() { - while let Some(packet) = client.read_packet() { - packets.push((client.id, packet)); - } - } - for (client_id, packet) in packets { - if self.handle_packet(client_id, packet).await.is_err() { - self.client_from_id(client_id).unwrap().force_disconnect(); - } - } - // Disconnect clients when necessary. - for client in self.network_clients.iter_mut() { - if client.state == NetworkClientState::Disconnected { - client.force_disconnect(); - } else if client.last_keep_alive.elapsed() > Duration::from_secs(20) { - debug!("Disconnecting client for timing out"); - client.state = NetworkClientState::Disconnected; - client.force_disconnect(); - } - } - // Remove disconnected clients. - self.network_clients - .retain(|nc| nc.state != NetworkClientState::Disconnected); - Ok(()) - } - - /// Handle a packet. - pub async fn handle_packet( - &mut self, - client_id: u128, - packet: P, - ) -> tokio::io::Result<()> { - let num_players = self.num_players(); - let mut client = self.client_from_id(client_id).unwrap(); - match packet.as_packet() { - // Handshaking. - Packet::Handshake(handshake) => { - if handshake.next_state == 1 { - client.state = NetworkClientState::Status; - } else if handshake.next_state == 2 { - client.state = NetworkClientState::Login; - } else { - client.state = NetworkClientState::Disconnected; - } - if handshake.protocol_version != 47 { - let mut logindisconnect = packets::LoginDisconnect::new(); - logindisconnect.reason = MCChat { - text: MCString::from("Incompatible client! Server is on 1.8.9"), - }; - client.send_packet(logindisconnect).await?; - client.state = NetworkClientState::Disconnected; - } - } - // Status. - Packet::StatusRequest(_statusrequest) => { - let mut statusresponse = packets::StatusResponse::new(); - statusresponse.json_response = json!({ - "version": { - "name": "1.8.9", - "protocol": 47, - }, - "players": { - "max": CONFIG.max_players, - "online": num_players, - "sample": [ - { - "name": "shvr", - "id": "e3f58380-60bb-4714-91f2-151d525e64aa" - } - ] - }, - "description": { - "text": CONFIG.motd - }, - "favicon": format!("data:image/png;base64,{}", if FAVICON.is_ok() { radix64::STD.encode(FAVICON.as_ref().unwrap().as_slice()) } else { "".to_owned() }) - }) - .to_string() - .into(); - client.send_packet(statusresponse).await?; - } - Packet::StatusPing(statusping) => { - let mut statuspong = packets::StatusPong::new(); - statuspong.payload = statusping.payload; - client.send_packet(statuspong).await?; - } - // Login. - Packet::LoginStart(loginstart) => { - client.player = Some(crate::entity::player::Player::new()); - let player = client.player.as_mut().unwrap(); - *player.username_mut() = loginstart.player_name.into(); - // Offline mode skips encryption and compression. - // TODO: Encryption and compression - let mut loginsuccess = packets::LoginSuccess::new(); - // We're in offline mode, so this is a temporary uuid. - // TODO: Get uuid and username from Mojang servers. - loginsuccess.uuid = player.uuid.clone().to_hyphenated().to_string().into(); - loginsuccess.username = player.username().clone().into(); - client.send_packet(loginsuccess).await?; - client.state = NetworkClientState::Play; - client.send_packet(packets::JoinGame::new()).await?; - } - Packet::ClientSettings(_clientsettings) => { - // TODO: Handle the packet. - client.send_packet(packets::HeldItemChange::new()).await?; - client - .send_packet(packets::ClientboundPlayerPositionAndLook::new()) - .await?; - client.send_packet(packets::SpawnPosition::new()).await?; - } - // Play. - Packet::KeepAlivePong(_keepalivepong) => { - // TODO: Handle the packet. - } - Packet::ServerboundChatMessage(chatmessage) => { - let player_name = client.player.as_ref().unwrap().username().clone(); - info!("<{}> {}", player_name, chatmessage.text); - self.broadcast_message(ClientboundMessage::Chat(format!( - "<{}> {}", - player_name, chatmessage.text - ))) - .await; - // TODO: Handle the packet. - } - Packet::Player(_player) => { - // TODO: Handle the packet. - } - Packet::PlayerPosition(_playerposition) => { - // TODO: Handle the packet. - } - Packet::PlayerLook(_playerlook) => { - // TODO: Handle the packet. - } - Packet::ServerboundPlayerPositionAndLook(_playerpositionandlook) => { - // TODO: Handle the packet. - } - // Other. - _ => error!("handling unknown packet type: {:?}", packet), - } - Ok(()) + pub async fn shutdown(&mut self) -> Result<(), ServerError> { + unimplemented!() } } diff --git a/src/server/net/mod.rs b/src/server/net/mod.rs deleted file mode 100644 index 398a730..0000000 --- a/src/server/net/mod.rs +++ /dev/null @@ -1,218 +0,0 @@ -/// Definitions for all the packets in the Minecraft protocol. -pub mod packets; - -use super::messages::*; -use crate::mctypes::*; -use log::*; -use packets::*; -// use serde_json::json; -use std::{ - collections::VecDeque, - sync::mpsc::Sender, - time::{Duration, Instant}, -}; -use tokio::net::TcpStream; - -/// The network client can only be in a few states, -/// this enum keeps track of that. -#[derive(PartialEq, Debug)] -pub enum NetworkClientState { - Handshake, - Status, - Login, - Play, - Disconnected, -} - -/// A wrapper to contain everything related -/// to networking for the client. -#[derive(Debug)] -pub struct NetworkClient { - pub id: u128, - pub connected: bool, - pub stream: TcpStream, - pub state: NetworkClientState, - pub last_keep_alive: Instant, - pub message_sender: Sender, - packets: VecDeque, - pub player: Option, -} -impl NetworkClient { - /// Create a new `NetworkClient` - pub fn new( - stream: TcpStream, - id: u128, - message_sender: Sender, - ) -> NetworkClient { - NetworkClient { - id, - connected: true, - stream, - state: NetworkClientState::Handshake, - last_keep_alive: Instant::now(), - message_sender, - packets: VecDeque::new(), - player: None, - } - } - - /// Try to read a new packet into the processing queue. - pub async fn update(&mut self) -> tokio::io::Result<()> { - // Don't try to read packets if disconnected. - if self.state == NetworkClientState::Disconnected { - return Ok(()); - } - if self.stream.peek(&mut [0u8; 4096]).await? > 0 { - // Read the packet header. - let (_packet_length, packet_id) = read_packet_header(&mut self.stream).await?; - // Get the packet based on packet_id. - let packet = match packet_id.value { - 0x00 => match self.state { - NetworkClientState::Handshake => { - Some(self.get_wrapped_packet::().await) - } - NetworkClientState::Status => { - Some(self.get_wrapped_packet::().await) - } - NetworkClientState::Login => { - Some(self.get_wrapped_packet::().await) - } - NetworkClientState::Play => { - Some(self.get_wrapped_packet::().await) - } - _ => None, - }, - 0x01 => { - match self.state { - NetworkClientState::Status => { - Some(self.get_wrapped_packet::().await) - } - NetworkClientState::Login => None, // TODO: 0x01 Encryption Response - NetworkClientState::Play => { - Some(self.get_wrapped_packet::().await) - } - _ => None, - } - } - // The rest of the packets are all always in the play state. - 0x02 => None, // TODO: 0x02 Use Entity - 0x03 => Some(self.get_wrapped_packet::().await), - 0x04 => Some(self.get_wrapped_packet::().await), - 0x05 => Some(self.get_wrapped_packet::().await), - 0x06 => Some( - self.get_wrapped_packet::() - .await, - ), - 0x07 => None, // TODO: 0x07 Player Digging - 0x08 => None, // TODO: 0x08 Player Block Placement - 0x09 => None, // TODO: 0x09 Held Item Change - 0x0a => None, // TODO: 0x0a Animation - 0x0b => None, // TODO: 0x0b Entity Action - 0x0c => None, // TODO: 0x0c Steer Vehicle - 0x0d => None, // TODO: 0x0d Close Window - 0x0e => None, // TODO: 0x0e Click Window - 0x0f => None, // TODO: 0x0f Confirm Transaction - 0x10 => None, // TODO: 0x10 Creative Inventory Action - 0x11 => None, // TODO: 0x11 Enchant Item - 0x12 => None, // TODO: 0x12 Update Sign - 0x13 => None, // TODO: 0x13 Player Abilities - 0x14 => None, // TODO: 0x14 Tab-Complete - 0x15 => Some(self.get_wrapped_packet::().await), - 0x16 => None, // TODO: 0x16 Client Status - 0x17 => None, // TODO: 0x17 Plugin Message - 0x18 => None, // TODO: 0x18 Spectate - 0x19 => None, // TODO: 0x19 Resource Pack Status - _ => None, - }; - if let Some(Ok(packet)) = packet { - // Add it to the internal queue to be processed. - self.packets.push_back(packet); - } - } - if self.last_keep_alive.elapsed() > Duration::from_millis(1000) { - debug!( - "Sending keep alive, last one was {:?} ago", - self.last_keep_alive.elapsed() - ); - self.keep_alive().await?; - } - Ok(()) - } - - /// Pop a packet from the queue. - pub fn read_packet(&mut self) -> Option { - self.packets.pop_front() - } - - /// Send a generic packet to the client. - pub async fn send_packet(&mut self, packet: P) -> tokio::io::Result<()> { - debug!("Sent {:?} {:#04X?} {:?}", self.state, P::id(), packet); - packet.write(&mut self.stream).await - } - - /// Read a generic packet from the network. - async fn get_packet(&mut self) -> tokio::io::Result { - let packet = T::read(&mut self.stream).await?; - debug!("Got {:?} {:#04X?} {:?}", self.state, T::id(), packet); - Ok(packet) - } - - /// Read a generic packet from the network and wrap it in `Packet`. - async fn get_wrapped_packet(&mut self) -> tokio::io::Result { - let packet = T::read(&mut self.stream).await?; - debug!("Got {:?} {:#04X?} {:?}", self.state, T::id(), packet); - Ok(packet.as_packet()) - } - - /// Send the client a message in chat. - pub async fn send_chat_message>( - &mut self, - message: C, - ) -> tokio::io::Result<()> { - let mut chatmessage = ClientboundChatMessage::new(); - chatmessage.text = message.into(); - self.send_packet(chatmessage).await?; - Ok(()) - } - - /// Disconnect the client. - /// - /// Sends `0x40 Disconnect` then waits 10 seconds before forcing the connection closed. - pub async fn disconnect>(&mut self, reason: S) -> tokio::io::Result<()> { - let mut disconnect = Disconnect::new(); - disconnect.reason.text = reason.into(); - self.send_packet(disconnect).await?; - self.force_disconnect(); - Ok(()) - } - - /// Force disconnect the client by marking it for cleanup as disconnected. - pub fn force_disconnect(&mut self) { - self.connected = false; - self.state = NetworkClientState::Disconnected; - } - - /// Send a keep alive packet to the client. - pub async fn keep_alive(&mut self) -> tokio::io::Result<()> { - if cfg!(debug_assertions) { - // self.send_chat_message("keep alive").await?; - } - // Keep alive ping to client. - self.send_packet(KeepAlivePing::new()).await?; - // Keep alive pong to server. - let (_packet_length, _packet_id) = read_packet_header(&mut self.stream).await?; - let _ = self.get_packet::().await?; - self.last_keep_alive = Instant::now(); - Ok(()) - } - - /// Receives messages from the server. - pub async fn handle_message(&mut self, message: ClientboundMessage) -> tokio::io::Result<()> { - use ClientboundMessage::*; - match message { - Chat(s) => self.send_chat_message(s).await?, - Disconnect(reason) => self.disconnect(reason).await?, - } - Ok(()) - } -} diff --git a/src/server/net/packets/clientbound.rs b/src/server/net/packets/clientbound.rs deleted file mode 100644 index 40864af..0000000 --- a/src/server/net/packets/clientbound.rs +++ /dev/null @@ -1,604 +0,0 @@ -use super::PacketCommon; -use crate::mctypes::*; -use crate::CONFIG; -use std::convert::{Into, TryFrom}; -use tokio::net::TcpStream; - -#[derive(Debug, Clone)] -pub struct StatusResponse { - pub json_response: MCString, -} -impl Into> for StatusResponse { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x00 Status Response. - temp.extend_from_slice(&Into::>::into(self.json_response)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for StatusResponse { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for StatusResponse { - fn new() -> Self { - StatusResponse { - json_response: MCString::from(""), - } - } - fn id() -> u8 { - 0x00 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut statusresponse = StatusResponse::new(); - statusresponse.json_response = MCString::read(t).await?; - Ok(statusresponse) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct StatusPong { - pub payload: MCLong, -} -impl Into> for StatusPong { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x01 Status Pong. - temp.extend_from_slice(&Into::>::into(self.payload)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for StatusPong { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for StatusPong { - fn new() -> Self { - StatusPong { payload: 0.into() } - } - fn id() -> u8 { - 0x01 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut statuspong = StatusPong::new(); - statuspong.payload = MCLong::read(t).await?; - Ok(statuspong) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct LoginSuccess { - pub uuid: MCString, - pub username: MCString, -} -impl Into> for LoginSuccess { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x02 Login Success. - temp.extend_from_slice(&Into::>::into(self.uuid)); - temp.extend_from_slice(&Into::>::into(self.username)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for LoginSuccess { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for LoginSuccess { - fn new() -> Self { - LoginSuccess { - uuid: MCString::from(""), - username: MCString::from(""), - } - } - fn id() -> u8 { - 0x02 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut loginsuccess = LoginSuccess::new(); - loginsuccess.uuid = MCString::read(t).await?; - loginsuccess.username = MCString::read(t).await?; - Ok(loginsuccess) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct LoginDisconnect { - pub reason: MCChat, -} -impl Into> for LoginDisconnect { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x00 Login Disconnect. - temp.extend_from_slice(&Into::>::into(self.reason)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for LoginDisconnect { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for LoginDisconnect { - fn new() -> Self { - LoginDisconnect { - reason: MCChat { - text: MCString::from(""), - }, - } - } - fn id() -> u8 { - 0x00 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut logindisconnect = LoginDisconnect::new(); - logindisconnect.reason = MCChat { - text: MCString::read(t).await?, - }; - Ok(logindisconnect) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct JoinGame { - pub entity_id: MCInt, // The player's Entity ID (EID) - pub gamemode: MCUnsignedByte, // 0: Survival, 1: Creative, 2: Adventure, 3: Spectator. Bit 3 (0x8) is the hardcore flag. - pub dimension: MCByte, // -1: Nether, 0: Overworld, 1: End - pub difficulty: MCUnsignedByte, // 0: Peaceful, 1: Easy, 2: Normal, 3: Hard - pub max_players: MCUnsignedByte, // Used by the client to draw the player list - pub level_type: MCString, // default, flat, largeBiomes, amplified, default_1_1 - pub reduced_debug_info: MCBoolean, // If true, a Notchian client shows reduced information on the debug screen. -} -impl Into> for JoinGame { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x01 Join Game. - temp.extend_from_slice(&Into::>::into(self.entity_id)); - temp.extend_from_slice(&Into::>::into(self.gamemode)); - temp.extend_from_slice(&Into::>::into(self.dimension)); - temp.extend_from_slice(&Into::>::into(self.difficulty)); - temp.extend_from_slice(&Into::>::into(self.max_players)); - temp.extend_from_slice(&Into::>::into(self.level_type)); - temp.extend_from_slice(&Into::>::into(self.reduced_debug_info)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for JoinGame { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for JoinGame { - fn new() -> Self { - JoinGame { - entity_id: 0.into(), - gamemode: 1.into(), // Default to creative mode. - dimension: 0.into(), // Default to overworld. - difficulty: 2.into(), - max_players: (CONFIG.max_players as u8).into(), - level_type: "default".into(), // Use the default world type. - reduced_debug_info: false.into(), // The debug info should be useful. - } - } - fn id() -> u8 { - 0x01 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut joingame = JoinGame::new(); - joingame.entity_id = MCInt::read(t).await?; - joingame.gamemode = MCUnsignedByte::read(t).await?; - joingame.dimension = MCByte::read(t).await?; - joingame.difficulty = MCUnsignedByte::read(t).await?; - joingame.max_players = MCUnsignedByte::read(t).await?; - joingame.level_type = MCString::read(t).await?; - joingame.reduced_debug_info = MCBoolean::read(t).await?; - Ok(joingame) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct HeldItemChange { - pub selected_slot: MCByte, -} -impl Into> for HeldItemChange { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x09 Held Item Change. - temp.extend_from_slice(&Into::>::into(self.selected_slot)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for HeldItemChange { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for HeldItemChange { - fn new() -> Self { - HeldItemChange { - selected_slot: 0.into(), - } - } - fn id() -> u8 { - 0x09 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut helditemchange = HeldItemChange::new(); - helditemchange.selected_slot = MCByte::read(t).await?; - Ok(helditemchange) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct EntityStatus { - pub entity_id: MCInt, - pub entity_status: MCByte, // See table below. - // 1: Sent when resetting a mob spawn minecart's timer / Rabbit jump animation - // 2: Living Entity hurt - // 3: Living Entity dead - // 4: Iron Golem throwing up arms - // 6: Wolf/Ocelot/Horse taming — Spawn “heart” particles - // 7: Wolf/Ocelot/Horse tamed — Spawn “smoke” particles - // 8: Wolf shaking water — Trigger the shaking animation - // 9: (of self) Eating accepted by server - // 10: Sheep eating grass - // 10: Play TNT ignite sound - // 11: Iron Golem handing over a rose - // 12: Villager mating — Spawn “heart” particles - // 13: Spawn particles indicating that a villager is angry and seeking revenge - // 14: Spawn happy particles near a villager - // 15: Witch animation — Spawn “magic” particles - // 16: Play zombie converting into a villager sound - // 17: Firework exploding - // 18: Animal in love (ready to mate) — Spawn “heart” particles - // 19: Reset squid rotation - // 20: Spawn explosion particle — works for some living entities - // 21: Play guardian sound — works for only for guardians - // 22: Enables reduced debug for players - // 23: Disables reduced debug for players -} -impl Into> for EntityStatus { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x1a Entity Status. - temp.extend_from_slice(&Into::>::into(self.entity_id)); - temp.extend_from_slice(&Into::>::into(self.entity_status)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for EntityStatus { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for EntityStatus { - fn new() -> Self { - EntityStatus { - entity_id: 0.into(), - entity_status: 0.into(), - } - } - fn id() -> u8 { - 0x1a - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut entitystatus = EntityStatus::new(); - entitystatus.entity_id = MCInt::read(t).await?; - entitystatus.entity_status = MCByte::read(t).await?; - Ok(entitystatus) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct ClientboundPlayerPositionAndLook { - pub x: MCDouble, - pub y: MCDouble, - pub z: MCDouble, - pub yaw: MCFloat, - pub pitch: MCFloat, - pub flags: MCByte, -} -impl Into> for ClientboundPlayerPositionAndLook { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x08 Player Position and Look. - temp.extend_from_slice(&Into::>::into(self.x)); - temp.extend_from_slice(&Into::>::into(self.y)); - temp.extend_from_slice(&Into::>::into(self.z)); - temp.extend_from_slice(&Into::>::into(self.yaw)); - temp.extend_from_slice(&Into::>::into(self.pitch)); - temp.extend_from_slice(&Into::>::into(self.flags)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for ClientboundPlayerPositionAndLook { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for ClientboundPlayerPositionAndLook { - fn new() -> Self { - ClientboundPlayerPositionAndLook { - x: 0.0.into(), - y: 0.0.into(), - z: 0.0.into(), - yaw: 0.0.into(), - pitch: 0.0.into(), - flags: 0x00.into(), - } - } - fn id() -> u8 { - 0x08 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut playerpositionandlook = ClientboundPlayerPositionAndLook::new(); - playerpositionandlook.x = MCDouble::read(t).await?; - playerpositionandlook.y = MCDouble::read(t).await?; - playerpositionandlook.z = MCDouble::read(t).await?; - playerpositionandlook.yaw = MCFloat::read(t).await?; - playerpositionandlook.pitch = MCFloat::read(t).await?; - playerpositionandlook.flags = MCByte::read(t).await?; - Ok(playerpositionandlook) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -// TODO: Actually send the position. -#[derive(Debug, Clone)] -pub struct SpawnPosition { - pub position: MCPosition, -} -impl Into> for SpawnPosition { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x05 Spawn Position. - // temp.extend_from_slice(&Into::>::into(self.position)); - temp.extend_from_slice(&0u64.to_be_bytes()); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for SpawnPosition { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for SpawnPosition { - fn new() -> Self { - SpawnPosition { - position: MCPosition::new(), - } - } - fn id() -> u8 { - 0x05 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut spawnposition = SpawnPosition::new(); - spawnposition.position = MCPosition::read(t).await?; - Ok(spawnposition) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct KeepAlivePing { - pub payload: MCVarInt, -} -impl Into> for KeepAlivePing { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x00 Keep Alive. - temp.extend_from_slice(&Into::>::into(self.payload)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for KeepAlivePing { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for KeepAlivePing { - fn new() -> Self { - KeepAlivePing { payload: 0.into() } - } - fn id() -> u8 { - 0x00 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut keepalive = KeepAlivePing::new(); - keepalive.payload = MCVarInt::read(t).await?; - Ok(keepalive) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct Disconnect { - pub reason: MCChat, -} -impl Into> for Disconnect { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x40 Disconnect. - temp.extend_from_slice(&Into::>::into(self.reason)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for Disconnect { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for Disconnect { - fn new() -> Self { - Disconnect { - reason: MCChat { - text: "Disconnected".into(), - }, - } - } - fn id() -> u8 { - 0x40 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut keepalive = Disconnect::new(); - keepalive.reason = MCChat::read(t).await?; - Ok(keepalive) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct ClientboundChatMessage { - pub text: MCChat, - pub position: MCByte, // 0: chat (chat box), 1: system message (chat box), 2: above hotbar -} -impl Into> for ClientboundChatMessage { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x02 Clientbound Chat Message. - temp.extend_from_slice(&Into::>::into(self.text)); - temp.extend_from_slice(&Into::>::into(self.position)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for ClientboundChatMessage { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for ClientboundChatMessage { - fn new() -> Self { - ClientboundChatMessage { - text: MCChat { text: "".into() }, - position: 0.into(), - } - } - fn id() -> u8 { - 0x02 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut clientboundchatmessage = ClientboundChatMessage::new(); - clientboundchatmessage.text = MCChat::read(t).await?; - clientboundchatmessage.position = MCByte::read(t).await?; - Ok(clientboundchatmessage) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} diff --git a/src/server/net/packets/mod.rs b/src/server/net/packets/mod.rs deleted file mode 100644 index 9d158de..0000000 --- a/src/server/net/packets/mod.rs +++ /dev/null @@ -1,125 +0,0 @@ -/// The packets that get sent to the client by the server. -pub mod clientbound; -/// The packets that get sent to the server by the client. -pub mod serverbound; - -use crate::mctypes::MCVarInt; -pub use clientbound::*; -use core::convert::TryFrom; -pub use serverbound::*; -use tokio::net::TcpStream; - -/// A helper function to read the packet header. -pub async fn read_packet_header(t: &mut TcpStream) -> tokio::io::Result<(MCVarInt, MCVarInt)> { - let length = MCVarInt::read(t).await?; - let id = MCVarInt::read(t).await?; - Ok((length, id)) -} - -/// A way to generically encode a packet. -macro_rules! register_packets { - ($($name:ident),*) => { - #[derive(Debug, Clone)] - pub enum Packet { - $($name($name),)* - Null, - } - impl Packet { - pub fn new() -> Packet { - Packet::Null - } - pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - match self { - $( - Packet::$name(p) => p.write(t).await, - )* - Packet::Null => Ok(()) - } - } - } - impl Default for Packet { - fn default() -> Self { - Packet::Null - } - } - $( - impl $name { - pub fn as_packet(&self) -> Packet { - Packet::$name(self.clone()) - } - } - impl Into for $name { - fn into(self) -> Packet { - Packet::$name(self.clone()) - } - } - impl TryFrom for $name { - type Error = &'static str; - fn try_from(p: Packet) -> Result { - match p { - Packet::$name(i) => Ok(i), - _ => Err("wrong kind"), - } - } - } - )* - }; -} - -// Register all the packets. -register_packets!( - // Clientbound. - StatusResponse, - StatusPong, - LoginSuccess, - LoginDisconnect, - JoinGame, - HeldItemChange, - EntityStatus, - ClientboundPlayerPositionAndLook, - SpawnPosition, - KeepAlivePing, - Disconnect, - ClientboundChatMessage, - // Serverbound. - Handshake, - StatusRequest, - StatusPing, - LoginStart, - ClientSettings, - KeepAlivePong, - ServerboundChatMessage, - Player, - PlayerPosition, - PlayerLook, - ServerboundPlayerPositionAndLook -); - -#[async_trait::async_trait] -pub trait PacketCommon: Into + core::fmt::Debug + Clone -where - Self: Sized, -{ - fn new() -> Self; - fn id() -> u8; - fn as_packet(&self) -> Packet { - self.clone().into() - } - async fn read(t: &mut TcpStream) -> tokio::io::Result; - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()>; -} -#[async_trait::async_trait] -impl PacketCommon for Packet { - fn new() -> Self { - Packet::new() - } - fn id() -> u8 { - 255 // The generic `Packet` doesn't really have an id, but I can't leave it blank. - } - async fn read(_t: &mut TcpStream) -> tokio::io::Result { - panic!("cannot PacketCommon::read a generic Packet") - } - async fn write(&self, _t: &mut TcpStream) -> tokio::io::Result<()> { - panic!("cannot PacketCommon::write a generic Packet") - } -} diff --git a/src/server/net/packets/serverbound.rs b/src/server/net/packets/serverbound.rs deleted file mode 100644 index b07c916..0000000 --- a/src/server/net/packets/serverbound.rs +++ /dev/null @@ -1,542 +0,0 @@ -use super::PacketCommon; -use crate::mctypes::*; -use std::convert::{Into, TryFrom}; -use tokio::net::TcpStream; - -/// Needed for every interaction with the server. -#[derive(Debug, Clone)] -pub struct Handshake { - pub protocol_version: MCVarInt, - pub server_address: MCString, - pub server_port: MCUnsignedShort, - pub next_state: MCVarInt, -} -impl Into> for Handshake { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x00 Handshake. - temp.extend_from_slice(&Into::>::into(self.protocol_version)); - temp.extend_from_slice(&Into::>::into(self.server_address)); - temp.extend_from_slice(&Into::>::into(self.server_port)); - temp.extend_from_slice(&Into::>::into(self.next_state)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for Handshake { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for Handshake { - fn new() -> Self { - Handshake { - protocol_version: 0.into(), - server_address: "".into(), - server_port: 0.into(), - next_state: 0.into(), - } - } - fn id() -> u8 { - 0x00 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut handshake = Handshake::new(); - handshake.protocol_version = MCVarInt::read(t).await?; - handshake.server_address = MCString::read(t).await?; - handshake.server_port = MCUnsignedShort::read(t).await?; - handshake.next_state = MCVarInt::read(t).await?; - Ok(handshake) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct StatusRequest {} -impl Into> for StatusRequest { - fn into(self) -> Vec { - let mut out = vec![]; - let temp: Vec = MCVarInt::from(Self::id()).into(); // 0x00 Status Request. - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for StatusRequest { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for StatusRequest { - fn new() -> Self { - StatusRequest {} - } - fn id() -> u8 { - 0x00 - } - async fn read(_t: &mut TcpStream) -> tokio::io::Result { - let statusrequest = StatusRequest::new(); - Ok(statusrequest) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct StatusPing { - pub payload: MCLong, -} -impl Into> for StatusPing { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x01 Status Pong. - temp.extend_from_slice(&Into::>::into(self.payload)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for StatusPing { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for StatusPing { - fn new() -> Self { - StatusPing { payload: 0.into() } - } - fn id() -> u8 { - 0x01 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut statusping = StatusPing::new(); - statusping.payload = MCLong::read(t).await?; - Ok(statusping) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct LoginStart { - pub player_name: MCString, -} -impl Into> for LoginStart { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x00 Login Start. - temp.extend_from_slice(&Into::>::into(self.player_name)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for LoginStart { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for LoginStart { - fn new() -> Self { - LoginStart { - player_name: "".into(), - } - } - fn id() -> u8 { - 0x00 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut loginstart = LoginStart::new(); - loginstart.player_name = MCString::read(t).await?; - Ok(loginstart) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct ClientSettings { - pub locale: MCString, - pub view_distance: MCByte, - pub chat_mode: MCVarInt, // 0: enabled, 1: commands only, 2: hidden. - pub chat_colors: MCBoolean, - pub displayed_skin_parts: MCUnsignedByte, // Bit mask - // Displayed skin parts flags: - // Bit 0 (0x01): Cape enabled - // Bit 1 (0x02): Jacket enabled - // Bit 2 (0x04): Left Sleeve enabled - // Bit 3 (0x08): Right Sleeve enabled - // Bit 4 (0x10): Left Pants Leg enabled - // Bit 5 (0x20): Right Pants Leg enabled - // Bit 6 (0x40): Hat enabled -} -impl Into> for ClientSettings { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x15 Client Settings. - temp.extend_from_slice(&Into::>::into(self.locale)); - temp.extend_from_slice(&Into::>::into(self.view_distance)); - temp.extend_from_slice(&Into::>::into(self.chat_mode)); - temp.extend_from_slice(&Into::>::into(self.chat_colors)); - temp.extend_from_slice(&Into::>::into(self.displayed_skin_parts)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for ClientSettings { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for ClientSettings { - fn new() -> Self { - ClientSettings { - locale: "en_US".into(), - view_distance: 8.into(), // 8 chunks. - chat_mode: 0.into(), // All chat enabled. - chat_colors: true.into(), - displayed_skin_parts: 0xff.into(), // Enable all parts. - } - } - fn id() -> u8 { - 0x15 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut clientsettings = ClientSettings::new(); - clientsettings.locale = MCString::read(t).await?; - clientsettings.view_distance = MCByte::read(t).await?; - clientsettings.chat_mode = MCVarInt::read(t).await?; - clientsettings.chat_colors = MCBoolean::read(t).await?; - clientsettings.displayed_skin_parts = MCUnsignedByte::read(t).await?; - Ok(clientsettings) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct KeepAlivePong { - pub payload: MCVarInt, -} -impl Into> for KeepAlivePong { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x00 Keep Alive. - temp.extend_from_slice(&Into::>::into(self.payload)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for KeepAlivePong { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for KeepAlivePong { - fn new() -> Self { - KeepAlivePong { payload: 0.into() } - } - fn id() -> u8 { - 0x00 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut keepalive = KeepAlivePong::new(); - keepalive.payload = MCVarInt::read(t).await?; - Ok(keepalive) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct ServerboundChatMessage { - pub text: MCString, -} -impl Into> for ServerboundChatMessage { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x01 Serverbound Chat Message. - temp.extend_from_slice(&Into::>::into(self.text)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for ServerboundChatMessage { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for ServerboundChatMessage { - fn new() -> Self { - ServerboundChatMessage { text: "".into() } - } - fn id() -> u8 { - 0x01 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut serverboundchatmessage = ServerboundChatMessage::new(); - serverboundchatmessage.text = MCString::read(t).await?; - Ok(serverboundchatmessage) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct Player { - pub on_ground: MCBoolean, -} -impl Into> for Player { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x03 Player. - temp.extend_from_slice(&Into::>::into(self.on_ground)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for Player { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for Player { - fn new() -> Self { - Player { - on_ground: false.into(), - } - } - fn id() -> u8 { - 0x03 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut player = Player::new(); - player.on_ground = MCBoolean::read(t).await?; - Ok(player) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct PlayerPosition { - pub x: MCDouble, - pub y: MCDouble, - pub z: MCDouble, - pub on_ground: MCBoolean, -} -impl Into> for PlayerPosition { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x04 Player Position. - temp.extend_from_slice(&Into::>::into(self.x)); - temp.extend_from_slice(&Into::>::into(self.y)); - temp.extend_from_slice(&Into::>::into(self.z)); - temp.extend_from_slice(&Into::>::into(self.on_ground)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for PlayerPosition { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for PlayerPosition { - fn new() -> Self { - PlayerPosition { - x: 0.0.into(), - y: 0.0.into(), - z: 0.0.into(), - on_ground: false.into(), - } - } - fn id() -> u8 { - 0x04 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut playerposition = PlayerPosition::new(); - playerposition.x = MCDouble::read(t).await?; - playerposition.y = MCDouble::read(t).await?; - playerposition.z = MCDouble::read(t).await?; - playerposition.on_ground = MCBoolean::read(t).await?; - Ok(playerposition) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct PlayerLook { - pub yaw: MCFloat, - pub pitch: MCFloat, - pub on_ground: MCBoolean, -} -impl Into> for PlayerLook { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x05 Player Look. - temp.extend_from_slice(&Into::>::into(self.yaw)); - temp.extend_from_slice(&Into::>::into(self.pitch)); - temp.extend_from_slice(&Into::>::into(self.on_ground)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for PlayerLook { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for PlayerLook { - fn new() -> Self { - PlayerLook { - yaw: 0.0.into(), - pitch: 0.0.into(), - on_ground: false.into(), - } - } - fn id() -> u8 { - 0x05 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut playerlook = PlayerLook::new(); - playerlook.yaw = MCFloat::read(t).await?; - playerlook.pitch = MCFloat::read(t).await?; - playerlook.on_ground = MCBoolean::read(t).await?; - Ok(playerlook) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} - -#[derive(Debug, Clone)] -pub struct ServerboundPlayerPositionAndLook { - pub x: MCDouble, - pub y: MCDouble, - pub z: MCDouble, - pub yaw: MCFloat, - pub pitch: MCFloat, - pub on_ground: MCBoolean, -} -impl Into> for ServerboundPlayerPositionAndLook { - fn into(self) -> Vec { - let mut out = vec![]; - let mut temp: Vec = MCVarInt::from(Self::id()).into(); // 0x06 Serverbound Player Position And Look. - temp.extend_from_slice(&Into::>::into(self.x)); - temp.extend_from_slice(&Into::>::into(self.y)); - temp.extend_from_slice(&Into::>::into(self.z)); - temp.extend_from_slice(&Into::>::into(self.yaw)); - temp.extend_from_slice(&Into::>::into(self.pitch)); - temp.extend_from_slice(&Into::>::into(self.on_ground)); - out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); - out.extend_from_slice(&temp); - out - } -} -impl TryFrom> for ServerboundPlayerPositionAndLook { - type Error = &'static str; - fn try_from(_bytes: Vec) -> Result { - Err("unimplemented") - } -} -#[async_trait::async_trait] -impl PacketCommon for ServerboundPlayerPositionAndLook { - fn new() -> Self { - ServerboundPlayerPositionAndLook { - x: 0.0.into(), - y: 0.0.into(), - z: 0.0.into(), - yaw: 0.0.into(), - pitch: 0.0.into(), - on_ground: false.into(), - } - } - fn id() -> u8 { - 0x06 - } - async fn read(t: &mut TcpStream) -> tokio::io::Result { - let mut playerpositionandlook = ServerboundPlayerPositionAndLook::new(); - playerpositionandlook.x = MCDouble::read(t).await?; - playerpositionandlook.y = MCDouble::read(t).await?; - playerpositionandlook.z = MCDouble::read(t).await?; - playerpositionandlook.yaw = MCFloat::read(t).await?; - playerpositionandlook.pitch = MCFloat::read(t).await?; - playerpositionandlook.on_ground = MCBoolean::read(t).await?; - Ok(playerpositionandlook) - } - async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { - for b in Into::>::into(self.clone()) { - write_byte(t, b).await?; - } - Ok(()) - } -} diff --git a/src/world/location.rs b/src/world/location.rs deleted file mode 100644 index 8a9fb24..0000000 --- a/src/world/location.rs +++ /dev/null @@ -1,55 +0,0 @@ -/// Used to store a point in a world. -#[derive(Debug, Clone, PartialEq)] -pub struct Location { - pub x: f64, - pub y: f64, - pub z: f64, - pub pitch: f32, - pub yaw: f32, - // TODO: Store a reference to the world this location is in. -} -impl Location { - /// Create a new `Location`. - pub fn new(x: f64, y: f64, z: f64, pitch: f32, yaw: f32) -> Location { - Location { - x, - y, - z, - pitch, - yaw, - } - } - - /// Create a new `Location` with no rotation. - pub fn position(x: f64, y: f64, z: f64) -> Location { - Location { - x, - y, - z, - pitch: 0.0, - yaw: 0.0, - } - } - - /// Create a new `Location` with no position. - pub fn rotation(pitch: f32, yaw: f32) -> Location { - Location { - x: 0.0, - y: 0.0, - z: 0.0, - pitch, - yaw, - } - } - - /// Create a new `Location` with no rotation or position. - pub fn zero() -> Location { - Location { - x: 0.0, - y: 0.0, - z: 0.0, - pitch: 0.0, - yaw: 0.0, - } - } -} diff --git a/src/world/mod.rs b/src/world/mod.rs deleted file mode 100644 index b6c6145..0000000 --- a/src/world/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod location;