diff --git a/Cargo.lock b/Cargo.lock index 8430ddd1..0c25e106 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,6 +303,7 @@ name = "minecraft-protocol" version = "0.1.0" dependencies = [ "async-recursion", + "async-trait", "byteorder", "bytes", "thiserror", diff --git a/minecraft-protocol/Cargo.toml b/minecraft-protocol/Cargo.toml index 1716b826..80e2b625 100644 --- a/minecraft-protocol/Cargo.toml +++ b/minecraft-protocol/Cargo.toml @@ -13,3 +13,4 @@ thiserror = "^1.0.30" tokio = {version = "^1.14.0", features = ["io-util", "net", "macros"]} tokio-util = "^0.6.9" trust-dns-resolver = "^0.20.3" +async-trait = "0.1.51" diff --git a/minecraft-protocol/src/connection.rs b/minecraft-protocol/src/connection.rs index e0d781c8..e5784eb6 100644 --- a/minecraft-protocol/src/connection.rs +++ b/minecraft-protocol/src/connection.rs @@ -72,7 +72,7 @@ impl Connection { } /// Write a packet to the server - pub async fn send_packet(&mut self, packet: &impl Packet) { + pub async fn send_packet(&mut self, packet: Packet<'_>) { // TODO: implement compression // packet structure: diff --git a/minecraft-protocol/src/mc_buf.rs b/minecraft-protocol/src/mc_buf.rs index a58905b7..087e66a1 100644 --- a/minecraft-protocol/src/mc_buf.rs +++ b/minecraft-protocol/src/mc_buf.rs @@ -96,19 +96,7 @@ mod tests { } } -pub fn write_utf_with_len(buf: &mut Vec, string: &String, len: usize) { - if string.len() > len { - panic!( - "String too big (was {} bytes encoded, max {})", - string.len(), - len - ); - } - write_varint(buf, string.len() as i32); - write_bytes(buf, string.as_bytes()); -} - -pub async fn read_utf( +pub async fn read_utf_with_len( buf: &mut BufReader, max_length: u32, ) -> Result { @@ -146,8 +134,24 @@ pub async fn read_utf( Ok(string) } +pub fn write_utf_with_len(buf: &mut Vec, string: &String, len: usize) { + if string.len() > len { + panic!( + "String too big (was {} bytes encoded, max {})", + string.len(), + len + ); + } + write_varint(buf, string.len() as i32); + write_bytes(buf, string.as_bytes()); +} + +pub async fn read_utf(buf: &mut T) -> Result { + read_utf_with_len(buf, MAX_STRING_LENGTH.into()).await +} + pub fn write_utf(buf: &mut Vec, string: &String) { - write_utf_with_len(buf, string, MAX_STRING_LENGTH as usize); + write_utf_with_len(buf, string, MAX_STRING_LENGTH.into()); } pub fn write_short(buf: &mut Vec, n: u16) { diff --git a/minecraft-protocol/src/packets/client_intention_packet.rs b/minecraft-protocol/src/packets/client_intention_packet.rs deleted file mode 100644 index 424c645f..00000000 --- a/minecraft-protocol/src/packets/client_intention_packet.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::hash::Hash; - -use crate::mc_buf; - -use super::{ConnectionProtocol, Packet}; - -#[derive(Hash)] -pub struct ClientIntentionPacket<'a> { - pub protocol_version: u32, - pub hostname: &'a String, - pub port: u16, - /// 1 for status, 2 for login - pub intention: ConnectionProtocol, -} - -// implement "Packet" for "ClientIntentionPacket" -impl<'a> Packet for ClientIntentionPacket<'a> { - fn get_id(&self) -> u32 { - 0x00 - } - - // implement "from_reader" for "ClientIntentionPacket" - fn write(&self, buf: &mut Vec) { - mc_buf::write_varint(buf, self.protocol_version as i32); - mc_buf::write_utf(buf, &self.hostname); - mc_buf::write_short(buf, self.port); - mc_buf::write_varint(buf, self.intention.clone() as i32); - } - - fn parse(&self, buf: T) -> () {} -} diff --git a/minecraft-protocol/src/packets/clientbound_status_response_packet.rs b/minecraft-protocol/src/packets/clientbound_status_response_packet.rs deleted file mode 100644 index ddca9b1f..00000000 --- a/minecraft-protocol/src/packets/clientbound_status_response_packet.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::hash::Hash; - -use super::Packet; - -#[derive(Hash)] -pub struct ServerboundStatusRequestPacket { - // status: ServerStatus, - status: String, -} - -// implement "Packet" for "ClientIntentionPacket" -impl Packet for ServerboundStatusRequestPacket { - fn get_id(&self) -> u32 { - 0x00 - } - - // implement "from_reader" for "ClientIntentionPacket" - fn write(&self, _buf: &mut Vec) {} - fn parse(&self, buf: T) -> () { - mc_buf::read_utf; - // this.status = GsonHelper.fromJson(GSON, friendlyByteBuf.readUtf(32767), ServerStatus.class); - } -} diff --git a/minecraft-protocol/src/packets/mod.rs b/minecraft-protocol/src/packets/mod.rs index 8d943be0..5fb34743 100644 --- a/minecraft-protocol/src/packets/mod.rs +++ b/minecraft-protocol/src/packets/mod.rs @@ -1,21 +1,39 @@ -mod client_intention_packet; -pub use client_intention_packet::ClientIntentionPacket; -mod serverbound_status_request_packet; -pub use serverbound_status_request_packet::ServerboundStatusRequestPacket; +mod game; +mod handshake; +mod login; +mod status; + +use async_trait::async_trait; use tokio::io::AsyncRead; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ConnectionProtocol { - Handshaking = -1, - Play = 0, + Handshake = -1, + Game = 0, Status = 1, Login = 2, } -pub trait Packet { - /// Get the id of the packet, this is always a byte. - fn get_id(&self) -> u32; - - fn write(&self, buf: &mut Vec) -> (); - fn parse(&self, buf: T) -> (); +pub enum Packet<'a> { + // game + // handshake + ClientIntentionPacket(&'a handshake::client_intention_packet::ClientIntentionPacket<'a>), + // login + // status + ServerboundStatusRequestPacket( + &'a status::serverbound_status_request_packet::ServerboundStatusRequestPacket, + ), + ClientboundStatusRequestPacket( + &'a status::clientbound_status_response_packet::ClientboundStatusRequestPacket, + ), +} + +pub trait PacketTrait { + /// Return a version of the packet that you can actually use for stuff + fn get(&self) -> Packet; + fn write(&self, buf: &mut Vec) -> (); + fn parse( + buf: &mut T, + // is using a static lifetime here a good idea? idk + ) -> Result, String>; } diff --git a/minecraft-protocol/src/packets/serverbound_status_request_packet.rs b/minecraft-protocol/src/packets/serverbound_status_request_packet.rs deleted file mode 100644 index ab9001f4..00000000 --- a/minecraft-protocol/src/packets/serverbound_status_request_packet.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::hash::Hash; - -use super::Packet; - -#[derive(Hash)] -pub struct ServerboundStatusRequestPacket {} - -// implement "Packet" for "ClientIntentionPacket" -impl Packet for ServerboundStatusRequestPacket { - fn get_id(&self) -> u32 { - 0x00 - } - - // implement "from_reader" for "ClientIntentionPacket" - fn write(&self, _buf: &mut Vec) {} - fn parse(&self, buf: T) -> () {} -}