Rewrite packet

This commit is contained in:
Garen Tyler 2022-04-16 13:18:49 -06:00
parent 6bd701b41a
commit 56b645df18
No known key found for this signature in database
GPG Key ID: E3BF83D66394FD92
18 changed files with 372 additions and 2928 deletions

26
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -1 +0,0 @@
pub mod player;

View File

@ -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<String>),
}
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<String> {
&mut self.names.1
}
}
impl Default for Player {
fn default() -> Self {
Player::new()
}
}

View File

@ -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<Config> {
use std::{fs::File, io::prelude::*};
let mut data = String::new();
@ -50,7 +44,7 @@ lazy_static! {
}
}
};
static ref FAVICON: std::io::Result<Vec<u8>> = {
pub static ref FAVICON: std::io::Result<Vec<u8>> = {
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<T> = Result<(T, usize), ParseError>;
}

View File

@ -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<u8> {
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<Vec<u8>> {
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<u8>`.
pub fn get_bytes(v: Vec<u8>, 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)
}

View File

@ -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<u8>`.
// pub trait MCType: Into<Vec<u8>> + TryFrom<Vec<u8>> + Display {
// pub async fn read(_stream: &mut TcpStream) -> tokio::io::Result<Self>;
// }
pub enum MCTypeError {
NetworkError(tokio::io::Error),
NotEnoughData,
ParseError,
}
#[async_trait::async_trait]
pub trait MCType: Into<Vec<u8>> + TryFrom<Vec<u8>> + Clone + Debug + Display {
fn to_bytes(&self) -> Vec<u8>;
fn from_bytes(bytes: Vec<u8>) -> Result<Self, MCTypeError>;
async fn read(t: &mut TcpStream) -> Result<Self, MCTypeError>;
async fn write(t: &mut TcpStream) -> tokio::io::Result<()>;
}

View File

@ -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<MCByte> {
Ok(MCByte::from_bytes(vec![read_byte(t).await?]))
pub fn parse_byte(data: &[u8]) -> ParseResult<i8> {
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<u8>) -> 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<i16> {
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<i32> {
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<i64> {
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<i32> {
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<u8> {
self.value.to_be_bytes().to_vec()
}
Ok((output, bytes_read as usize))
}
impl From<i8> for MCByte {
fn from(v: i8) -> MCByte {
MCByte { value: v }
}
}
impl Into<i8> for MCByte {
fn into(self) -> i8 {
self.value
}
}
impl PartialEq<i8> 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<Vec<u8>> for MCByte {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
if bytes.is_empty() {
Err("Not enough bytes")
pub fn serialize_varint(value: i32) -> Vec<u8> {
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<Vec<u8>> for MCByte {
fn into(self) -> Vec<u8> {
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<MCUnsignedByte> {
Ok(MCUnsignedByte::from_bytes(vec![read_byte(t).await?]))
}
pub fn from_bytes(v: Vec<u8>) -> MCUnsignedByte {
MCUnsignedByte {
value: get_bytes(v, 1)[0],
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.value.to_be_bytes().to_vec()
pub fn parse_unsigned_byte(data: &[u8]) -> ParseResult<u8> {
if data.is_empty() {
Err(ParseError::NotEnoughData)
} else {
let value = u8::from_be_bytes([data[0]]);
Ok((value, 1))
}
}
impl From<u8> for MCUnsignedByte {
fn from(v: u8) -> MCUnsignedByte {
MCUnsignedByte { value: v }
}
}
impl Into<u8> for MCUnsignedByte {
fn into(self) -> u8 {
self.value
}
}
impl PartialEq<u8> 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<Vec<u8>> for MCUnsignedByte {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCUnsignedByte {
fn into(self) -> Vec<u8> {
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<MCShort> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
pub fn parse_unsigned_short(data: &[u8]) -> ParseResult<u16> {
if data.len() < 2 {
Err(ParseError::NotEnoughData)
} else {
let value = u16::from_be_bytes([data[0], data[1]]);
Ok((value, 2))
}
}
impl From<i16> for MCShort {
fn from(v: i16) -> MCShort {
MCShort { value: v }
}
}
impl Into<i16> for MCShort {
fn into(self) -> i16 {
self.value
}
}
impl PartialEq<i16> 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<Vec<u8>> for MCShort {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCShort {
fn into(self) -> Vec<u8> {
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<MCUnsignedShort> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
pub fn parse_unsigned_int(data: &[u8]) -> ParseResult<u32> {
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<u16> for MCUnsignedShort {
fn from(v: u16) -> MCUnsignedShort {
MCUnsignedShort { value: v }
}
}
impl Into<u16> for MCUnsignedShort {
fn into(self) -> u16 {
self.value
}
}
impl PartialEq<u16> 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<Vec<u8>> for MCUnsignedShort {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCUnsignedShort {
fn into(self) -> Vec<u8> {
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<MCInt> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
pub fn parse_unsigned_long(data: &[u8]) -> ParseResult<u64> {
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<i32> for MCInt {
fn from(v: i32) -> MCInt {
MCInt { value: v }
}
}
impl Into<i32> for MCInt {
fn into(self) -> i32 {
self.value
}
}
impl PartialEq<i32> 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<Vec<u8>> for MCInt {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCInt {
fn into(self) -> Vec<u8> {
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<MCUnsignedInt> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
}
}
impl From<u32> for MCUnsignedInt {
fn from(v: u32) -> MCUnsignedInt {
MCUnsignedInt { value: v }
}
}
impl Into<u32> for MCUnsignedInt {
fn into(self) -> u32 {
self.value
}
}
impl PartialEq<u32> 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<Vec<u8>> for MCUnsignedInt {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCUnsignedInt {
fn into(self) -> Vec<u8> {
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<MCLong> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
}
}
impl From<i64> for MCLong {
fn from(v: i64) -> MCLong {
MCLong { value: v }
}
}
impl Into<i64> for MCLong {
fn into(self) -> i64 {
self.value
}
}
impl PartialEq<i64> 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<Vec<u8>> for MCLong {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCLong {
fn into(self) -> Vec<u8> {
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<MCUnsignedLong> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
}
}
impl From<u64> for MCUnsignedLong {
fn from(v: u64) -> MCUnsignedLong {
MCUnsignedLong { value: v }
}
}
impl Into<u64> for MCUnsignedLong {
fn into(self) -> u64 {
self.value
}
}
impl PartialEq<u64> 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<Vec<u8>> for MCUnsignedLong {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCUnsignedLong {
fn into(self) -> Vec<u8> {
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<MCFloat> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
}
}
impl From<f32> for MCFloat {
fn from(v: f32) -> MCFloat {
MCFloat { value: v }
}
}
impl Into<f32> for MCFloat {
fn into(self) -> f32 {
self.value
}
}
impl PartialEq<f32> 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<Vec<u8>> for MCFloat {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCFloat {
fn into(self) -> Vec<u8> {
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<MCDouble> {
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<u8>) -> 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<u8> {
self.value.to_be_bytes().to_vec()
}
}
impl From<f64> for MCDouble {
fn from(v: f64) -> MCDouble {
MCDouble { value: v }
}
}
impl Into<f64> for MCDouble {
fn into(self) -> f64 {
self.value
}
}
impl PartialEq<f64> 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<Vec<u8>> for MCDouble {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCDouble {
fn into(self) -> Vec<u8> {
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<MCVarInt> {
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<u8>) -> MCVarInt {
unimplemented!()
}
pub fn to_bytes(&self) -> Vec<u8> {
Into::<Vec<u8>>::into(*self)
}
}
impl From<u8> for MCVarInt {
fn from(v: u8) -> MCVarInt {
MCVarInt { value: v as i32 }
}
}
impl Into<u8> for MCVarInt {
fn into(self) -> u8 {
self.value as u8
}
}
impl PartialEq<u8> for MCVarInt {
fn eq(&self, other: &u8) -> bool {
self.value == *other as i32
}
}
impl From<i32> for MCVarInt {
fn from(v: i32) -> MCVarInt {
MCVarInt { value: v }
}
}
impl Into<i32> for MCVarInt {
fn into(self) -> i32 {
self.value
}
}
impl PartialEq<i32> 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<Vec<u8>> for MCVarInt {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Vec<u8>> for MCVarInt {
fn into(self) -> Vec<u8> {
let mut value = self.value;
let mut run_once = false;
let mut out: Vec<u8> = 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
}
}

View File

@ -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<bool> for MCBoolean {
fn from(v: bool) -> MCBoolean {
if v {
MCBoolean::True
} else {
MCBoolean::False
}
pub fn parse_bool(data: &[u8]) -> ParseResult<bool> {
if data.is_empty() {
Err(ParseError::NotEnoughData)
} else {
Ok((data[0] == 1, 1))
}
}
impl Into<bool> 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<Vec<u8>> for MCBoolean {
type Error = &'static str;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
if bytes.is_empty() {
Err("Not enough bytes")
} else if bytes[0] == 1u8 {
Ok(MCBoolean::True)
} else {
Ok(MCBoolean::False)
}
}
}
impl Into<Vec<u8>> for MCBoolean {
fn into(self) -> Vec<u8> {
match self {
MCBoolean::True => vec![0x01],
MCBoolean::False => vec![0x00],
}
}
}
impl MCBoolean {
pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCBoolean> {
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<String> {
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<String> for MCString {
fn from(s: String) -> MCString {
MCString { value: s }
}
}
impl Into<String> for MCString {
fn into(self) -> String {
self.value
}
}
impl PartialEq<&str> for MCString {
fn eq(&self, other: &&str) -> bool {
self.value == **other
}
}
impl PartialEq<String> 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<Vec<u8>> for MCString {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
Err("Cannot read MCString from bytes")
}
}
impl Into<Vec<u8>> for MCString {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let str_len: Vec<u8> = 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<Self> {
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<u8> {
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<JSON> {
unimplemented!()
}
impl From<&str> for MCChat {
fn from(s: &str) -> MCChat {
MCChat { text: s.into() }
}
}
impl From<String> for MCChat {
fn from(s: String) -> MCChat {
MCChat { text: s.into() }
}
}
impl Into<String> 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<String> 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<Vec<u8>> for MCChat {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
Err("Cannot read MCChat from bytes")
}
}
impl Into<Vec<u8>> for MCChat {
fn into(self) -> Vec<u8> {
// Just output
// {"text": "<data>"}
Into::<MCString>::into(
json!({
"text": self.text.value
})
.to_string(),
)
.into()
}
}
impl MCChat {
pub async fn read(_t: &mut TcpStream) -> tokio::io::Result<Self> {
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<Vec<u8>> for MCPosition {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
Err("Cannot read MCPosition from bytes")
}
}
impl Into<Vec<u8>> for MCPosition {
fn into(self) -> Vec<u8> {
// Just output
// {"text": "<data>"}
let mut out = vec![];
let mut temp = vec![];
temp.extend_from_slice(
&((((Into::<i64>::into(self.x) & 0x3FFFFFF) << 38)
| ((Into::<i64>::into(self.y) & 0xFFF) << 26)
| (Into::<i64>::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::<Vec<u8>>::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<Self> {
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<u8> {
unimplemented!()
}

24
src/net/mod.rs Normal file
View File

@ -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<u8>,
}
impl NetworkClient {
pub async fn read_bytes(&mut self) -> Result<(), ()> {
unimplemented!()
}
}

104
src/net/packets.rs Normal file
View File

@ -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<Packet> {
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<u8> {
use Packet::*;
let (id, mut body): (usize, Vec<u8>) = 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
}
}

View File

@ -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<NetworkClient>,
network_receiver: Receiver<NetworkClient>,
pub players: Vec<Player>,
}
pub struct Server {}
impl Server {
pub fn new<A: 'static + ToSocketAddrs + Send>(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<A: ToSocketAddrs>(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<P: PacketCommon>(
&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!()
}
}

View File

@ -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<ServerboundMessage>,
packets: VecDeque<Packet>,
pub player: Option<crate::entity::player::Player>,
}
impl NetworkClient {
/// Create a new `NetworkClient`
pub fn new(
stream: TcpStream,
id: u128,
message_sender: Sender<ServerboundMessage>,
) -> 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::<Handshake>().await)
}
NetworkClientState::Status => {
Some(self.get_wrapped_packet::<StatusRequest>().await)
}
NetworkClientState::Login => {
Some(self.get_wrapped_packet::<LoginStart>().await)
}
NetworkClientState::Play => {
Some(self.get_wrapped_packet::<KeepAlivePong>().await)
}
_ => None,
},
0x01 => {
match self.state {
NetworkClientState::Status => {
Some(self.get_wrapped_packet::<StatusPing>().await)
}
NetworkClientState::Login => None, // TODO: 0x01 Encryption Response
NetworkClientState::Play => {
Some(self.get_wrapped_packet::<ServerboundChatMessage>().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::<Player>().await),
0x04 => Some(self.get_wrapped_packet::<PlayerPosition>().await),
0x05 => Some(self.get_wrapped_packet::<PlayerLook>().await),
0x06 => Some(
self.get_wrapped_packet::<ServerboundPlayerPositionAndLook>()
.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::<ClientSettings>().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<Packet> {
self.packets.pop_front()
}
/// Send a generic packet to the client.
pub async fn send_packet<P: PacketCommon>(&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<T: PacketCommon>(&mut self) -> tokio::io::Result<T> {
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<T: PacketCommon>(&mut self) -> tokio::io::Result<Packet> {
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<C: Into<MCChat>>(
&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<S: Into<MCString>>(&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::<KeepAlivePong>().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(())
}
}

View File

@ -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<Vec<u8>> for StatusResponse {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x00 Status Response.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.json_response));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for StatusResponse {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct StatusPong {
pub payload: MCLong,
}
impl Into<Vec<u8>> for StatusPong {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x01 Status Pong.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.payload));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for StatusPong {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct LoginSuccess {
pub uuid: MCString,
pub username: MCString,
}
impl Into<Vec<u8>> for LoginSuccess {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x02 Login Success.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.uuid));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.username));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for LoginSuccess {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct LoginDisconnect {
pub reason: MCChat,
}
impl Into<Vec<u8>> for LoginDisconnect {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x00 Login Disconnect.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.reason));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for LoginDisconnect {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for JoinGame {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x01 Join Game.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.entity_id));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.gamemode));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.dimension));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.difficulty));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.max_players));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.level_type));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.reduced_debug_info));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for JoinGame {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct HeldItemChange {
pub selected_slot: MCByte,
}
impl Into<Vec<u8>> for HeldItemChange {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x09 Held Item Change.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.selected_slot));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for HeldItemChange {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for EntityStatus {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x1a Entity Status.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.entity_id));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.entity_status));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for EntityStatus {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for ClientboundPlayerPositionAndLook {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x08 Player Position and Look.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.x));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.y));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.z));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.yaw));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.pitch));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.flags));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for ClientboundPlayerPositionAndLook {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for SpawnPosition {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x05 Spawn Position.
// temp.extend_from_slice(&Into::<Vec<u8>>::into(self.position));
temp.extend_from_slice(&0u64.to_be_bytes());
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for SpawnPosition {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct KeepAlivePing {
pub payload: MCVarInt,
}
impl Into<Vec<u8>> for KeepAlivePing {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x00 Keep Alive.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.payload));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for KeepAlivePing {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct Disconnect {
pub reason: MCChat,
}
impl Into<Vec<u8>> for Disconnect {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x40 Disconnect.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.reason));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for Disconnect {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for ClientboundChatMessage {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x02 Clientbound Chat Message.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.text));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.position));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for ClientboundChatMessage {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}

View File

@ -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<Packet> for $name {
fn into(self) -> Packet {
Packet::$name(self.clone())
}
}
impl TryFrom<Packet> for $name {
type Error = &'static str;
fn try_from(p: Packet) -> Result<Self, Self::Error> {
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<Packet> + 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<Self>;
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<Self> {
panic!("cannot PacketCommon::read a generic Packet")
}
async fn write(&self, _t: &mut TcpStream) -> tokio::io::Result<()> {
panic!("cannot PacketCommon::write a generic Packet")
}
}

View File

@ -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<Vec<u8>> for Handshake {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x00 Handshake.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.protocol_version));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.server_address));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.server_port));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.next_state));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for Handshake {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct StatusRequest {}
impl Into<Vec<u8>> for StatusRequest {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x00 Status Request.
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for StatusRequest {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
let statusrequest = StatusRequest::new();
Ok(statusrequest)
}
async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct StatusPing {
pub payload: MCLong,
}
impl Into<Vec<u8>> for StatusPing {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x01 Status Pong.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.payload));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for StatusPing {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct LoginStart {
pub player_name: MCString,
}
impl Into<Vec<u8>> for LoginStart {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x00 Login Start.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.player_name));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for LoginStart {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for ClientSettings {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x15 Client Settings.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.locale));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.view_distance));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.chat_mode));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.chat_colors));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.displayed_skin_parts));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for ClientSettings {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct KeepAlivePong {
pub payload: MCVarInt,
}
impl Into<Vec<u8>> for KeepAlivePong {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x00 Keep Alive.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.payload));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for KeepAlivePong {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct ServerboundChatMessage {
pub text: MCString,
}
impl Into<Vec<u8>> for ServerboundChatMessage {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x01 Serverbound Chat Message.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.text));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for ServerboundChatMessage {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct Player {
pub on_ground: MCBoolean,
}
impl Into<Vec<u8>> for Player {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x03 Player.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.on_ground));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for Player {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for PlayerPosition {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x04 Player Position.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.x));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.y));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.z));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.on_ground));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for PlayerPosition {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for PlayerLook {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x05 Player Look.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.yaw));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.pitch));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.on_ground));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for PlayerLook {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::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<Vec<u8>> for ServerboundPlayerPositionAndLook {
fn into(self) -> Vec<u8> {
let mut out = vec![];
let mut temp: Vec<u8> = MCVarInt::from(Self::id()).into(); // 0x06 Serverbound Player Position And Look.
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.x));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.y));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.z));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.yaw));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.pitch));
temp.extend_from_slice(&Into::<Vec<u8>>::into(self.on_ground));
out.extend_from_slice(&Into::<Vec<u8>>::into(MCVarInt::from(temp.len() as i32)));
out.extend_from_slice(&temp);
out
}
}
impl TryFrom<Vec<u8>> for ServerboundPlayerPositionAndLook {
type Error = &'static str;
fn try_from(_bytes: Vec<u8>) -> Result<Self, Self::Error> {
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<Self> {
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::<Vec<u8>>::into(self.clone()) {
write_byte(t, b).await?;
}
Ok(())
}
}

View File

@ -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,
}
}
}

View File

@ -1 +0,0 @@
pub mod location;