aboutsummaryrefslogtreecommitdiff
path: root/minecraft-protocol
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2021-12-15 23:10:55 -0600
committermat <github@matdoes.dev>2021-12-15 23:10:55 -0600
commit9642558f8f8d983a7087f15d68be8cf07a85f0c2 (patch)
tree5f0a967f005cd5db510a13ab290c8ad6669b25aa /minecraft-protocol
parent72aefe871ca4983431b1a0b707b472e73ffea836 (diff)
downloadazalea-drasl-9642558f8f8d983a7087f15d68be8cf07a85f0c2.tar.xz
azalea
Diffstat (limited to 'minecraft-protocol')
-rw-r--r--minecraft-protocol/Cargo.toml19
-rw-r--r--minecraft-protocol/src/connect.rs116
-rw-r--r--minecraft-protocol/src/lib.rs56
-rw-r--r--minecraft-protocol/src/mc_buf.rs203
-rw-r--r--minecraft-protocol/src/packets/game/mod.rs35
-rw-r--r--minecraft-protocol/src/packets/handshake/client_intention_packet.rs36
-rw-r--r--minecraft-protocol/src/packets/handshake/mod.rs49
-rw-r--r--minecraft-protocol/src/packets/login/clientbound_custom_query_packet.rs41
-rw-r--r--minecraft-protocol/src/packets/login/clientbound_hello_packet.rs38
-rw-r--r--minecraft-protocol/src/packets/login/mod.rs63
-rw-r--r--minecraft-protocol/src/packets/login/serverbound_hello_packet.rs27
-rw-r--r--minecraft-protocol/src/packets/mod.rs146
-rw-r--r--minecraft-protocol/src/packets/status/clientbound_status_response_packet.rs58
-rw-r--r--minecraft-protocol/src/packets/status/mod.rs66
-rw-r--r--minecraft-protocol/src/packets/status/serverbound_status_request_packet.rs23
-rw-r--r--minecraft-protocol/src/read.rs28
-rw-r--r--minecraft-protocol/src/resolver.rs55
-rw-r--r--minecraft-protocol/src/write.rs27
18 files changed, 0 insertions, 1086 deletions
diff --git a/minecraft-protocol/Cargo.toml b/minecraft-protocol/Cargo.toml
deleted file mode 100644
index 3cbf663b..00000000
--- a/minecraft-protocol/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-edition = "2021"
-name = "minecraft-protocol"
-version = "0.1.0"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-async-recursion = "^0.3.2"
-async-trait = "0.1.51"
-byteorder = "^1.4.3"
-bytes = "^1.1.0"
-minecraft-chat = {path = "../minecraft-chat"}
-serde = {version = "1.0.130", features = ["serde_derive"]}
-serde_json = "^1.0.72"
-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"
diff --git a/minecraft-protocol/src/connect.rs b/minecraft-protocol/src/connect.rs
deleted file mode 100644
index f6dd9fe7..00000000
--- a/minecraft-protocol/src/connect.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-//! parse sending and receiving packets with a server.
-
-use crate::packets::game::GamePacket;
-use crate::packets::handshake::HandshakePacket;
-use crate::packets::login::LoginPacket;
-use crate::packets::status::StatusPacket;
-use crate::read::read_packet;
-use crate::write::write_packet;
-use crate::ServerIpAddress;
-use tokio::net::TcpStream;
-
-pub enum PacketFlow {
- ClientToServer,
- ServerToClient,
-}
-
-pub struct HandshakeConnection {
- pub flow: PacketFlow,
- /// The buffered writer
- pub stream: TcpStream,
-}
-
-pub struct GameConnection {
- pub flow: PacketFlow,
- /// The buffered writer
- pub stream: TcpStream,
-}
-
-pub struct StatusConnection {
- pub flow: PacketFlow,
- /// The buffered writer
- pub stream: TcpStream,
-}
-
-pub struct LoginConnection {
- pub flow: PacketFlow,
- /// The buffered writer
- pub stream: TcpStream,
-}
-
-impl HandshakeConnection {
- pub async fn new(address: &ServerIpAddress) -> Result<HandshakeConnection, String> {
- let ip = address.ip;
- let port = address.port;
-
- let stream = TcpStream::connect(format!("{}:{}", ip, port))
- .await
- .map_err(|_| "Failed to connect to server")?;
-
- // enable tcp_nodelay
- stream
- .set_nodelay(true)
- .expect("Error enabling tcp_nodelay");
-
- Ok(HandshakeConnection {
- flow: PacketFlow::ServerToClient,
- stream,
- })
- }
-
- pub fn login(self) -> LoginConnection {
- LoginConnection {
- flow: self.flow,
- stream: self.stream,
- }
- }
-
- pub fn status(self) -> StatusConnection {
- StatusConnection {
- flow: self.flow,
- stream: self.stream,
- }
- }
-
- pub async fn read(&mut self) -> Result<HandshakePacket, String> {
- read_packet::<HandshakePacket>(&self.flow, &mut self.stream).await
- }
-
- /// Write a packet to the server
- pub async fn write(&mut self, packet: HandshakePacket) {
- write_packet(packet, &mut self.stream).await;
- }
-}
-
-impl GameConnection {
- pub async fn read(&mut self) -> Result<GamePacket, String> {
- read_packet::<GamePacket>(&self.flow, &mut self.stream).await
- }
-
- /// Write a packet to the server
- pub async fn write(&mut self, packet: GamePacket) {
- write_packet(packet, &mut self.stream).await;
- }
-}
-
-impl StatusConnection {
- pub async fn read(&mut self) -> Result<StatusPacket, String> {
- read_packet::<StatusPacket>(&self.flow, &mut self.stream).await
- }
-
- /// Write a packet to the server
- pub async fn write(&mut self, packet: StatusPacket) {
- write_packet(packet, &mut self.stream).await;
- }
-}
-
-impl LoginConnection {
- pub async fn read(&mut self) -> Result<LoginPacket, String> {
- read_packet::<LoginPacket>(&self.flow, &mut self.stream).await
- }
-
- /// Write a packet to the server
- pub async fn write(&mut self, packet: LoginPacket) {
- write_packet(packet, &mut self.stream).await;
- }
-}
diff --git a/minecraft-protocol/src/lib.rs b/minecraft-protocol/src/lib.rs
deleted file mode 100644
index 684add45..00000000
--- a/minecraft-protocol/src/lib.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-//! This lib is responsible for parsing Minecraft packets.
-
-use std::net::IpAddr;
-use std::str::FromStr;
-
-pub mod connect;
-pub mod mc_buf;
-pub mod packets;
-pub mod read;
-pub mod resolver;
-pub mod write;
-
-#[derive(Debug)]
-pub struct ServerAddress {
- pub host: String,
- pub port: u16,
-}
-
-#[derive(Debug)]
-pub struct ServerIpAddress {
- pub ip: IpAddr,
- pub port: u16,
-}
-
-// impl try_from for ServerAddress
-impl<'a> TryFrom<&'a str> for ServerAddress {
- type Error = String;
-
- /// Convert a Minecraft server address (host:port, the port is optional) to a ServerAddress
- fn try_from(string: &str) -> Result<Self, Self::Error> {
- if string.is_empty() {
- return Err("Empty string".to_string());
- }
- let mut parts = string.split(':');
- let host = parts.next().ok_or("No host specified")?.to_string();
- // default the port to 25565
- let port = parts.next().unwrap_or("25565");
- let port = u16::from_str(port).map_err(|_| "Invalid port specified")?;
- Ok(ServerAddress { host, port })
- }
-}
-
-pub async fn connect(address: ServerAddress) -> Result<(), Box<dyn std::error::Error>> {
- let resolved_address = resolver::resolve_address(&address).await;
- println!("Resolved address: {:?}", resolved_address);
- Ok(())
-}
-
-#[cfg(test)]
-mod tests {
- #[test]
- fn it_works() {
- let result = 2 + 2;
- assert_eq!(result, 4);
- }
-}
diff --git a/minecraft-protocol/src/mc_buf.rs b/minecraft-protocol/src/mc_buf.rs
deleted file mode 100644
index 54ba1f7d..00000000
--- a/minecraft-protocol/src/mc_buf.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-//! Utilities for reading and writing for the Minecraft protocol
-
-use std::io::Write;
-
-use async_trait::async_trait;
-use byteorder::{BigEndian, WriteBytesExt};
-use tokio::io::{AsyncRead, AsyncReadExt};
-
-// const DEFAULT_NBT_QUOTA: u32 = 2097152;
-const MAX_STRING_LENGTH: u16 = 32767;
-// const MAX_COMPONENT_STRING_LENGTH: u32 = 262144;
-
-#[async_trait]
-pub trait Writable {
- fn write_byte(&mut self, n: u8) -> Result<(), std::io::Error>;
- fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
- fn write_varint(&mut self, value: i32) -> Result<(), std::io::Error>;
- fn write_utf_with_len(&mut self, string: &str, len: usize) -> Result<(), std::io::Error>;
- fn write_utf(&mut self, string: &str) -> Result<(), std::io::Error>;
- fn write_short(&mut self, n: u16) -> Result<(), std::io::Error>;
- fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
-}
-
-#[async_trait]
-impl Writable for Vec<u8> {
- fn write_byte(&mut self, n: u8) -> Result<(), std::io::Error> {
- WriteBytesExt::write_u8(self, n)
- }
-
- fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
- Ok(self.extend_from_slice(bytes))
- }
-
- fn write_varint(&mut self, mut value: i32) -> Result<(), std::io::Error> {
- let mut buffer = [0];
- if value == 0 {
- self.write_all(&buffer).unwrap();
- }
- while value != 0 {
- buffer[0] = (value & 0b0111_1111) as u8;
- value = (value >> 7) & (i32::max_value() >> 6);
- if value != 0 {
- buffer[0] |= 0b1000_0000;
- }
- self.write_all(&buffer)?;
- }
- Ok(())
- }
-
- fn write_utf_with_len(&mut self, string: &str, len: usize) -> Result<(), std::io::Error> {
- if string.len() > len {
- panic!(
- "String too big (was {} bytes encoded, max {})",
- string.len(),
- len
- );
- }
- self.write_varint(string.len() as i32);
- self.write_bytes(string.as_bytes())
- }
-
- fn write_utf(&mut self, string: &str) -> Result<(), std::io::Error> {
- self.write_utf_with_len(string, MAX_STRING_LENGTH.into())
- }
-
- fn write_short(&mut self, n: u16) -> Result<(), std::io::Error> {
- WriteBytesExt::write_u16::<BigEndian>(self, n)
- }
-
- fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
- self.write_varint(bytes.len() as i32);
- self.write_bytes(bytes)
- }
-}
-
-#[async_trait]
-pub trait Readable {
- async fn read_varint(&mut self) -> Result<(i32, u8), String>;
- async fn read_byte_array(&mut self) -> Result<Vec<u8>, String>;
- async fn read_bytes(&mut self, n: usize) -> Result<Vec<u8>, String>;
- async fn read_utf(&mut self) -> Result<String, String>;
- async fn read_utf_with_len(&mut self, max_length: u32) -> Result<String, String>;
- async fn read_byte(&mut self) -> Result<u8, String>;
-}
-
-#[async_trait]
-impl<R> Readable for R
-where
- R: AsyncRead + std::marker::Unpin + std::marker::Send,
-{
- // fast varints stolen from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67
- /// Read a single varint from the reader and return the value, along with the number of bytes read
- async fn read_varint(&mut self) -> Result<(i32, u8), String> {
- let mut buffer = [0];
- let mut ans = 0;
- for i in 0..4 {
- self.read_exact(&mut buffer)
- .await
- .map_err(|_| "Invalid VarInt".to_string())?;
- ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i);
- if buffer[0] & 0b1000_0000 == 0 {
- return Ok((ans, i + 1));
- }
- }
- Ok((ans, 5))
- }
-
- async fn read_byte_array(&mut self) -> Result<Vec<u8>, String> {
- let length = self.read_varint().await?.0 as usize;
- Ok(self.read_bytes(length).await?)
- }
-
- async fn read_bytes(&mut self, n: usize) -> Result<Vec<u8>, String> {
- let mut bytes = vec![0; n];
- match AsyncReadExt::read_exact(self, &mut bytes).await {
- Ok(_) => Ok(bytes),
- Err(_) => Err("Error reading bytes".to_string()),
- }
- }
-
- async fn read_utf(&mut self) -> Result<String, String> {
- self.read_utf_with_len(MAX_STRING_LENGTH.into()).await
- }
-
- async fn read_utf_with_len(&mut self, max_length: u32) -> Result<String, String> {
- let (length, _length_varint_length) = self.read_varint().await?;
- // i don't know why it's multiplied by 4 but it's like that in mojang's code so
- if length < 0 {
- return Err(
- "The received encoded string buffer length is less than zero! Weird string!"
- .to_string(),
- );
- }
- if length as u32 > max_length * 4 {
- return Err(format!(
- "The received encoded string buffer length is longer than maximum allowed ({} > {})",
- length,
- max_length * 4
- ));
- }
-
- // this is probably quite inefficient, idk how to do it better
- let mut string = String::new();
- let mut buffer = vec![0; length as usize];
- self.read_exact(&mut buffer)
- .await
- .map_err(|_| "Invalid UTF-8".to_string())?;
-
- string.push_str(std::str::from_utf8(&buffer).unwrap());
- if string.len() > length as usize {
- return Err(format!(
- "The received string length is longer than maximum allowed ({} > {})",
- length, max_length
- ));
- }
-
- Ok(string)
- }
-
- /// Read a single byte from the reader
- async fn read_byte(&mut self) -> Result<u8, String> {
- match AsyncReadExt::read_u8(self).await {
- Ok(r) => Ok(r),
- Err(_) => Err("Error reading byte".to_string()),
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::io::Cursor;
- use tokio::io::BufReader;
-
- #[test]
- fn test_write_varint() {
- let mut buf = Vec::new();
- buf.write_varint(123456);
- assert_eq!(buf, vec![192, 196, 7]);
-
- let mut buf = Vec::new();
- buf.write_varint(0);
- assert_eq!(buf, vec![0]);
- }
-
- #[tokio::test]
- async fn test_read_varint() {
- let mut buf = BufReader::new(Cursor::new(vec![192, 196, 7]));
- assert_eq!(buf.read_varint().await.unwrap(), (123456, 3));
-
- let mut buf = BufReader::new(Cursor::new(vec![0]));
- assert_eq!(buf.read_varint().await.unwrap(), (0, 1));
-
- let mut buf = BufReader::new(Cursor::new(vec![1]));
- assert_eq!(buf.read_varint().await.unwrap(), (1, 1));
- }
-
- #[tokio::test]
- async fn test_read_varint_longer() {
- let mut buf = BufReader::new(Cursor::new(vec![138, 56, 0, 135, 56, 123]));
- assert_eq!(buf.read_varint().await.unwrap(), (7178, 2));
- }
-}
diff --git a/minecraft-protocol/src/packets/game/mod.rs b/minecraft-protocol/src/packets/game/mod.rs
deleted file mode 100644
index a3ef2541..00000000
--- a/minecraft-protocol/src/packets/game/mod.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use async_trait::async_trait;
-use tokio::io::BufReader;
-
-use crate::connect::PacketFlow;
-
-use super::ProtocolPacket;
-
-#[derive(Clone, Debug)]
-pub enum GamePacket
-where
- Self: Sized, {}
-
-#[async_trait]
-impl ProtocolPacket for GamePacket {
- fn id(&self) -> u32 {
- 0x00
- }
-
- fn write(&self, _buf: &mut Vec<u8>) {}
-
- /// Read a packet by its id, ConnectionProtocol, and flow
- async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- _id: u32,
- flow: &PacketFlow,
- _buf: &mut BufReader<T>,
- ) -> Result<GamePacket, String>
- where
- Self: Sized,
- {
- match flow {
- PacketFlow::ServerToClient => Err("HandshakePacket::read not implemented".to_string()),
- PacketFlow::ClientToServer => Err("HandshakePacket::read not implemented".to_string()),
- }
- }
-}
diff --git a/minecraft-protocol/src/packets/handshake/client_intention_packet.rs b/minecraft-protocol/src/packets/handshake/client_intention_packet.rs
deleted file mode 100644
index 868626b3..00000000
--- a/minecraft-protocol/src/packets/handshake/client_intention_packet.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use std::hash::Hash;
-
-use tokio::io::BufReader;
-
-use crate::{mc_buf::Writable, packets::ConnectionProtocol};
-
-use super::HandshakePacket;
-
-#[derive(Hash, Clone, Debug)]
-pub struct ClientIntentionPacket {
- pub protocol_version: u32,
- pub hostname: String,
- pub port: u16,
- /// 1 for status, 2 for login
- pub intention: ConnectionProtocol,
-}
-
-impl ClientIntentionPacket {
- pub fn get(self) -> HandshakePacket {
- HandshakePacket::ClientIntentionPacket(self)
- }
-
- pub fn write(&self, buf: &mut Vec<u8>) {
- buf.write_varint(self.protocol_version as i32).unwrap();
- buf.write_utf(&self.hostname).unwrap();
- buf.write_short(self.port).unwrap();
- buf.write_varint(self.intention.clone() as i32).unwrap();
- }
-
- pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- _buf: &mut BufReader<T>,
- ) -> Result<HandshakePacket, String> {
- Err("ClientIntentionPacket::parse not implemented".to_string())
- // Ok(ClientIntentionPacket {}.get())
- }
-}
diff --git a/minecraft-protocol/src/packets/handshake/mod.rs b/minecraft-protocol/src/packets/handshake/mod.rs
deleted file mode 100644
index 01010e1e..00000000
--- a/minecraft-protocol/src/packets/handshake/mod.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-pub mod client_intention_packet;
-
-use async_trait::async_trait;
-use tokio::io::BufReader;
-
-use crate::connect::PacketFlow;
-
-use super::ProtocolPacket;
-
-#[derive(Clone, Debug)]
-pub enum HandshakePacket
-where
- Self: Sized,
-{
- ClientIntentionPacket(client_intention_packet::ClientIntentionPacket),
-}
-
-#[async_trait]
-impl ProtocolPacket for HandshakePacket {
- fn id(&self) -> u32 {
- match self {
- HandshakePacket::ClientIntentionPacket(_packet) => 0x00,
- }
- }
-
- fn write(&self, buf: &mut Vec<u8>) {
- match self {
- HandshakePacket::ClientIntentionPacket(packet) => packet.write(buf),
- }
- }
-
- /// Read a packet by its id, ConnectionProtocol, and flow
- async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- id: u32,
- flow: &PacketFlow,
- buf: &mut BufReader<T>,
- ) -> Result<HandshakePacket, String>
- where
- Self: Sized,
- {
- match flow {
- PacketFlow::ServerToClient => Err("HandshakePacket::read not implemented".to_string()),
- PacketFlow::ClientToServer => match id {
- 0x00 => Ok(client_intention_packet::ClientIntentionPacket::read(buf).await?),
- _ => Err(format!("Unknown ClientToServer status packet id: {}", id)),
- },
- }
- }
-}
diff --git a/minecraft-protocol/src/packets/login/clientbound_custom_query_packet.rs b/minecraft-protocol/src/packets/login/clientbound_custom_query_packet.rs
deleted file mode 100644
index 093176eb..00000000
--- a/minecraft-protocol/src/packets/login/clientbound_custom_query_packet.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-use std::hash::Hash;
-use tokio::io::BufReader;
-
-use crate::mc_buf::{self, Readable, Writable};
-
-use super::LoginPacket;
-
-#[derive(Hash, Clone, Debug)]
-pub struct ClientboundCustomQueryPacket {
- pub transaction_id: u32,
- // TODO: this should be a resource location
- pub identifier: String,
- pub data: Vec<u8>,
-}
-
-impl ClientboundCustomQueryPacket {
- pub fn get(self) -> LoginPacket {
- LoginPacket::ClientboundCustomQueryPacket(self)
- }
-
- pub fn write(&self, buf: &mut Vec<u8>) {
- buf.write_varint(self.transaction_id as i32).unwrap();
- buf.write_utf(&self.identifier).unwrap();
- buf.write_bytes(&self.data).unwrap();
- }
-
- pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- buf: &mut BufReader<T>,
- ) -> Result<LoginPacket, String> {
- let transaction_id = buf.read_varint().await?.0 as u32;
- // TODO: this should be a resource location
- let identifier = buf.read_utf().await?;
- let data = buf.read_bytes(1048576).await?;
- Ok(ClientboundCustomQueryPacket {
- transaction_id,
- identifier,
- data,
- }
- .get())
- }
-}
diff --git a/minecraft-protocol/src/packets/login/clientbound_hello_packet.rs b/minecraft-protocol/src/packets/login/clientbound_hello_packet.rs
deleted file mode 100644
index 36a48706..00000000
--- a/minecraft-protocol/src/packets/login/clientbound_hello_packet.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use std::hash::Hash;
-use tokio::io::BufReader;
-
-use crate::mc_buf::Readable;
-
-use super::LoginPacket;
-
-#[derive(Hash, Clone, Debug)]
-pub struct ClientboundHelloPacket {
- pub server_id: String,
- pub public_key: Vec<u8>,
- pub nonce: Vec<u8>,
-}
-
-impl ClientboundHelloPacket {
- pub fn get(self) -> LoginPacket {
- LoginPacket::ClientboundHelloPacket(self)
- }
-
- pub fn write(&self, _buf: &mut Vec<u8>) {
- panic!("ClientboundHelloPacket::write not implemented")
- }
-
- pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- buf: &mut BufReader<T>,
- ) -> Result<LoginPacket, String> {
- let server_id = buf.read_utf_with_len(20).await?;
- let public_key = buf.read_byte_array().await?;
- let nonce = buf.read_byte_array().await?;
-
- Ok(ClientboundHelloPacket {
- server_id,
- public_key,
- nonce,
- }
- .get())
- }
-}
diff --git a/minecraft-protocol/src/packets/login/mod.rs b/minecraft-protocol/src/packets/login/mod.rs
deleted file mode 100644
index f0ed6717..00000000
--- a/minecraft-protocol/src/packets/login/mod.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-pub mod clientbound_custom_query_packet;
-pub mod clientbound_hello_packet;
-pub mod serverbound_hello_packet;
-
-use async_trait::async_trait;
-use tokio::io::BufReader;
-
-use crate::connect::PacketFlow;
-
-use super::ProtocolPacket;
-
-#[derive(Clone, Debug)]
-pub enum LoginPacket
-where
- Self: Sized,
-{
- ClientboundCustomQueryPacket(clientbound_custom_query_packet::ClientboundCustomQueryPacket),
- ServerboundHelloPacket(serverbound_hello_packet::ServerboundHelloPacket),
- ClientboundHelloPacket(clientbound_hello_packet::ClientboundHelloPacket),
-}
-
-#[async_trait]
-impl ProtocolPacket for LoginPacket {
- fn id(&self) -> u32 {
- match self {
- LoginPacket::ClientboundCustomQueryPacket(_packet) => 0x04,
- LoginPacket::ServerboundHelloPacket(_packet) => 0x00,
- LoginPacket::ClientboundHelloPacket(_packet) => 0x01,
- }
- }
-
- fn write(&self, buf: &mut Vec<u8>) {
- match self {
- LoginPacket::ClientboundCustomQueryPacket(packet) => packet.write(buf),
- LoginPacket::ServerboundHelloPacket(packet) => packet.write(buf),
- LoginPacket::ClientboundHelloPacket(packet) => packet.write(buf),
- }
- }
-
- /// Read a packet by its id, ConnectionProtocol, and flow
- async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- id: u32,
- flow: &PacketFlow,
- buf: &mut BufReader<T>,
- ) -> Result<LoginPacket, String>
- where
- Self: Sized,
- {
- Ok(match flow {
- PacketFlow::ServerToClient => match id {
- 0x01 => clientbound_hello_packet::ClientboundHelloPacket::read(buf).await?,
- 0x04 => {
- clientbound_custom_query_packet::ClientboundCustomQueryPacket::read(buf).await?
- }
- _ => return Err(format!("Unknown ServerToClient status packet id: {}", id)),
- },
- PacketFlow::ClientToServer => match id {
- 0x00 => serverbound_hello_packet::ServerboundHelloPacket::read(buf).await?,
- _ => return Err(format!("Unknown ClientToServer status packet id: {}", id)),
- },
- })
- }
-}
diff --git a/minecraft-protocol/src/packets/login/serverbound_hello_packet.rs b/minecraft-protocol/src/packets/login/serverbound_hello_packet.rs
deleted file mode 100644
index 32a6dadc..00000000
--- a/minecraft-protocol/src/packets/login/serverbound_hello_packet.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use std::hash::Hash;
-use tokio::io::BufReader;
-
-use crate::mc_buf::Writable;
-
-use super::LoginPacket;
-
-#[derive(Hash, Clone, Debug)]
-pub struct ServerboundHelloPacket {
- pub username: String,
-}
-
-impl ServerboundHelloPacket {
- pub fn get(self) -> LoginPacket {
- LoginPacket::ServerboundHelloPacket(self)
- }
-
- pub fn write(&self, buf: &mut Vec<u8>) {
- buf.write_utf(&self.username).unwrap();
- }
-
- pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- _buf: &mut BufReader<T>,
- ) -> Result<LoginPacket, String> {
- Err("ServerboundHelloPacket::read not implemented".to_string())
- }
-}
diff --git a/minecraft-protocol/src/packets/mod.rs b/minecraft-protocol/src/packets/mod.rs
deleted file mode 100644
index a074b570..00000000
--- a/minecraft-protocol/src/packets/mod.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-pub mod game;
-pub mod handshake;
-pub mod login;
-pub mod status;
-
-use async_trait::async_trait;
-use tokio::io::BufReader;
-
-use crate::connect::PacketFlow;
-
-pub const PROTOCOL_VERSION: u32 = 757;
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum ConnectionProtocol {
- Handshake = -1,
- Game = 0,
- Status = 1,
- Login = 2,
-}
-
-#[derive(Clone, Debug)]
-pub enum Packet {
- Game(game::GamePacket),
- Handshake(handshake::HandshakePacket),
- Login(login::LoginPacket),
- Status(Box<status::StatusPacket>),
-}
-
-/// An enum of packets for a certain protocol
-#[async_trait]
-pub trait ProtocolPacket
-where
- Self: Sized,
-{
- fn id(&self) -> u32;
-
- /// Read a packet by its id, ConnectionProtocol, and flow
- async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- id: u32,
- flow: &PacketFlow,
- buf: &mut BufReader<T>,
- ) -> Result<Self, String>
- where
- Self: Sized;
-
- fn write(&self, buf: &mut Vec<u8>);
-}
-
-// impl Packet {
-// fn get_inner_packet(&self) -> &dyn PacketTrait {
-// match self {
-// Packet::ClientIntentionPacket(packet) => packet,
-// Packet::ServerboundStatusRequestPacket(packet) => packet,
-// Packet::ClientboundStatusResponsePacket(packet) => packet,
-// Packet::ServerboundHelloPacket(packet) => packet,
-// Packet::ClientboundHelloPacket(packet) => packet,
-// }
-// }
-
-// pub fn id(&self) -> u32 {
-// match self {
-// Packet::ClientIntentionPacket(_packet) => 0x00,
-// Packet::ServerboundStatusRequestPacket(_packet) => 0x00,
-// Packet::ClientboundStatusResponsePacket(_packet) => 0x00,
-// Packet::ServerboundHelloPacket(_packet) => 0x00,
-// Packet::ClientboundHelloPacket(_packet) => 0x01,
-// }
-// }
-
-// /// Read a packet by its id, ConnectionProtocol, and flow
-// pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
-// id: u32,
-// protocol: &ConnectionProtocol,
-// flow: &PacketFlow,
-// buf: &mut BufReader<T>,
-// ) -> Result<Packet, String> {
-// match protocol {
-// ConnectionProtocol::Handshake => match flow {
-// PacketFlow::ClientToServer => match id {
-// 0x00 => Ok(
-// handshake::client_intention_packet::ClientIntentionPacket::read(buf).await?,
-// ),
-// _ => Err(format!("Unknown ClientToServer handshake packet id: {}", id)),
-// }
-// PacketFlow::ServerToClient => Err("ServerToClient handshake packets not implemented".to_string()),
-// },
-
-// ConnectionProtocol::Game => Err("Game protocol not implemented yet".to_string()),
-
-// ConnectionProtocol::Status => match flow {
-// PacketFlow::ServerToClient => match id {
-// 0x00 => Ok(
-// status::clientbound_status_response_packet::ClientboundStatusResponsePacket
-// ::read(buf)
-// .await?,
-// ),
-// _ => Err(format!("Unknown ServerToClient status packet id: {}", id)),
-// },
-// PacketFlow::ClientToServer => match id {
-// 0x00 => Ok(
-// status::serverbound_status_request_packet::ServerboundStatusRequestPacket
-// ::read(buf)
-// .await?,
-// ),
-// _ => Err(format!("Unknown ClientToServer status packet id: {}", id)),
-// },
-// },
-
-// ConnectionProtocol::Login => match flow {
-// PacketFlow::ServerToClient => match id {
-// 0x01 => Ok(
-// login::clientbound_hello_packet::ClientboundHelloPacket::read(buf).await?,
-// ),
-// _ => Err(format!("Unknown ServerToClient login packet id: {}", id)),
-// },
-// PacketFlow::ClientToServer => match id {
-// 0x00 => Ok(
-// login::serverbound_hello_packet::ServerboundHelloPacket::read(buf).await?,
-// ),
-// _ => Err(format!("Unknown ClientToServer login packet id: {}", id)),
-// },
-// },
-// }
-// }
-
-// pub fn write(&self, buf: &mut Vec<u8>) {
-// self.get_inner_packet().write(buf);
-// }
-// }
-
-// #[async_trait]
-// pub trait PacketTrait
-// where
-// Self: Sized,
-// {
-// /// Return a version of the packet that you can actually use for stuff
-// fn get(self) -> dyn ProtocolPacket;
-
-// fn write(&self, buf: &mut Vec<u8>);
-
-// async fn read<T: AsyncRead + std::marker::Unpin + std::marker::Send, P: ProtocolPacket>(
-// buf: &mut BufReader<T>,
-// ) -> Result<P, String>
-// where
-// Self: Sized;
-// }
diff --git a/minecraft-protocol/src/packets/status/clientbound_status_response_packet.rs b/minecraft-protocol/src/packets/status/clientbound_status_response_packet.rs
deleted file mode 100644
index 920e3484..00000000
--- a/minecraft-protocol/src/packets/status/clientbound_status_response_packet.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use minecraft_chat::component::Component;
-use serde::Deserialize;
-use serde_json::Value;
-use tokio::io::BufReader;
-
-use crate::mc_buf::Readable;
-
-use super::StatusPacket;
-
-#[derive(Clone, Debug, Deserialize)]
-pub struct Version {
- pub name: Component,
- pub protocol: u32,
-}
-
-#[derive(Clone, Debug, Deserialize)]
-pub struct SamplePlayer {
- pub id: String,
- pub name: String,
-}
-
-#[derive(Clone, Debug, Deserialize)]
-pub struct Players {
- pub max: u32,
- pub online: u32,
- pub sample: Vec<SamplePlayer>,
-}
-
-// the entire packet is just json, which is why it has deserialize
-#[derive(Clone, Debug, Deserialize)]
-pub struct ClientboundStatusResponsePacket {
- pub description: Component,
- pub favicon: Option<String>,
- pub players: Players,
- pub version: Version,
-}
-
-impl ClientboundStatusResponsePacket {
- pub fn get(self) -> StatusPacket {
- StatusPacket::ClientboundStatusResponsePacket(Box::new(self))
- }
-
- pub fn write(&self, _buf: &mut Vec<u8>) {}
-
- pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- buf: &mut BufReader<T>,
- ) -> Result<StatusPacket, String> {
- let status_string = buf.read_utf().await?;
- let status_json: Value =
- serde_json::from_str(status_string.as_str()).expect("Server status isn't valid JSON");
-
- let packet = ClientboundStatusResponsePacket::deserialize(status_json)
- .map_err(|e| e.to_string())?
- .get();
-
- Ok(packet)
- }
-}
diff --git a/minecraft-protocol/src/packets/status/mod.rs b/minecraft-protocol/src/packets/status/mod.rs
deleted file mode 100644
index ac6a34e1..00000000
--- a/minecraft-protocol/src/packets/status/mod.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-pub mod clientbound_status_response_packet;
-pub mod serverbound_status_request_packet;
-
-use async_trait::async_trait;
-use tokio::io::BufReader;
-
-use crate::connect::PacketFlow;
-
-use super::ProtocolPacket;
-
-#[derive(Clone, Debug)]
-pub enum StatusPacket
-where
- Self: Sized,
-{
- ServerboundStatusRequestPacket(
- serverbound_status_request_packet::ServerboundStatusRequestPacket,
- ),
- ClientboundStatusResponsePacket(
- Box<clientbound_status_response_packet::ClientboundStatusResponsePacket>,
- ),
-}
-
-#[async_trait]
-impl ProtocolPacket for StatusPacket {
- fn id(&self) -> u32 {
- match self {
- StatusPacket::ServerboundStatusRequestPacket(_packet) => 0x00,
- StatusPacket::ClientboundStatusResponsePacket(_packet) => 0x00,
- }
- }
-
- fn write(&self, buf: &mut Vec<u8>) {
- match self {
- StatusPacket::ServerboundStatusRequestPacket(packet) => packet.write(buf),
- StatusPacket::ClientboundStatusResponsePacket(packet) => packet.write(buf),
- }
- }
-
- /// Read a packet by its id, ConnectionProtocol, and flow
- async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- id: u32,
- flow: &PacketFlow,
- buf: &mut BufReader<T>,
- ) -> Result<StatusPacket, String>
- where
- Self: Sized,
- {
- match flow {
- PacketFlow::ServerToClient => match id {
- 0x00 => Ok(
- clientbound_status_response_packet::ClientboundStatusResponsePacket::read(buf)
- .await?,
- ),
- _ => Err(format!("Unknown ServerToClient status packet id: {}", id)),
- },
- PacketFlow::ClientToServer => match id {
- 0x00 => Ok(
- serverbound_status_request_packet::ServerboundStatusRequestPacket::read(buf)
- .await?,
- ),
- _ => Err(format!("Unknown ClientToServer status packet id: {}", id)),
- },
- }
- }
-}
diff --git a/minecraft-protocol/src/packets/status/serverbound_status_request_packet.rs b/minecraft-protocol/src/packets/status/serverbound_status_request_packet.rs
deleted file mode 100644
index 6a58da1f..00000000
--- a/minecraft-protocol/src/packets/status/serverbound_status_request_packet.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use std::hash::Hash;
-use tokio::io::BufReader;
-
-use super::StatusPacket;
-
-#[derive(Hash, Clone, Debug)]
-pub struct ServerboundStatusRequestPacket {}
-
-impl ServerboundStatusRequestPacket {
- pub fn get(self) -> StatusPacket {
- StatusPacket::ServerboundStatusRequestPacket(self)
- }
-
- pub fn write(&self, _buf: &mut Vec<u8>) {
- panic!("ServerboundStatusRequestPacket::write not implemented")
- }
-
- pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
- _buf: &mut BufReader<T>,
- ) -> Result<StatusPacket, String> {
- Err("ServerboundStatusRequestPacket::read not implemented".to_string())
- }
-}
diff --git a/minecraft-protocol/src/read.rs b/minecraft-protocol/src/read.rs
deleted file mode 100644
index 6f242e8b..00000000
--- a/minecraft-protocol/src/read.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use tokio::{io::BufReader, net::TcpStream};
-
-use crate::{connect::PacketFlow, mc_buf::Readable, packets::ProtocolPacket};
-
-pub async fn read_packet<P: ProtocolPacket>(
- flow: &PacketFlow,
- stream: &mut TcpStream,
-) -> Result<P, String> {
- // what this does:
- // 1. reads the first 5 bytes, probably only some of this will be used to get the packet length
- // 2. how much we should read = packet length - 5
- // 3. read the rest of the packet and add it to the cursor
- // 4. figure out what packet this is and parse it
-
- // the first thing minecraft sends us is the length as a varint, which can be up to 5 bytes long
- let mut buf = BufReader::with_capacity(4 * 1024 * 1024, stream);
-
- let (_packet_size, _packet_size_varint_size) = buf.read_varint().await?;
-
- // then, minecraft tells us the packet id as a varint
- let (packet_id, _packet_id_size) = buf.read_varint().await?;
-
- // if we recognize the packet id, parse it
-
- let packet = P::read(packet_id.try_into().unwrap(), flow, &mut buf).await?;
-
- Ok(packet)
-}
diff --git a/minecraft-protocol/src/resolver.rs b/minecraft-protocol/src/resolver.rs
deleted file mode 100644
index 24687a6e..00000000
--- a/minecraft-protocol/src/resolver.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-use std::net::IpAddr;
-
-use crate::{ServerAddress, ServerIpAddress};
-use async_recursion::async_recursion;
-use trust_dns_resolver::{
- config::{ResolverConfig, ResolverOpts},
- TokioAsyncResolver,
-};
-
-/// Resolve a Minecraft server address into an IP address and port.
-/// If it's already an IP address, it's returned as-is.
-#[async_recursion]
-pub async fn resolve_address(address: &ServerAddress) -> Result<ServerIpAddress, String> {
- // If the address.host is already in the format of an ip address, return it.
- if let Ok(ip) = address.host.parse::<IpAddr>() {
- return Ok(ServerIpAddress {
- ip,
- port: address.port,
- });
- }
-
- // we specify Cloudflare instead of the default resolver because trust_dns_resolver has an issue on Windows where it's really slow using the default resolver
- let resolver =
- TokioAsyncResolver::tokio(ResolverConfig::cloudflare(), ResolverOpts::default()).unwrap();
-
- // first, we do a srv lookup for _minecraft._tcp.<host>
- let srv_redirect_result = resolver
- .srv_lookup(format!("_minecraft._tcp.{}", address.host).as_str())
- .await;
-
- // if it resolves that means it's a redirect so we call resolve_address again with the new host
- if let Ok(redirect_result) = srv_redirect_result {
- let redirect_srv = redirect_result
- .iter()
- .next()
- .ok_or_else(|| "No SRV record found".to_string())?;
- let redirect_address = ServerAddress {
- host: redirect_srv.target().to_utf8(),
- port: redirect_srv.port(),
- };
-
- println!("redirecting to {:?}", redirect_address);
-
- return resolve_address(&redirect_address).await;
- }
-
- // there's no redirect, try to resolve this as an ip address
- let lookup_ip_result = resolver.lookup_ip(address.host.clone()).await;
- let lookup_ip = lookup_ip_result.map_err(|_| "No IP found".to_string())?;
-
- Ok(ServerIpAddress {
- ip: lookup_ip.iter().next().unwrap(),
- port: address.port,
- })
-}
diff --git a/minecraft-protocol/src/write.rs b/minecraft-protocol/src/write.rs
deleted file mode 100644
index 3d8540eb..00000000
--- a/minecraft-protocol/src/write.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use tokio::{io::AsyncWriteExt, net::TcpStream};
-
-use crate::{mc_buf::Writable, packets::ProtocolPacket};
-
-pub async fn write_packet(packet: impl ProtocolPacket, stream: &mut TcpStream) {
- // TODO: implement compression
-
- // packet structure:
- // length (varint) + id (varint) + data
-
- // write the packet id
- let mut id_and_data_buf = vec![];
- id_and_data_buf.write_varint(packet.id() as i32);
- packet.write(&mut id_and_data_buf);
-
- // write the packet data
-
- // make a new buffer that has the length at the beginning
- // and id+data at the end
- let mut complete_buf: Vec<u8> = Vec::new();
- complete_buf.write_varint(id_and_data_buf.len() as i32);
- complete_buf.append(&mut id_and_data_buf);
-
- // finally, write and flush to the stream
- stream.write_all(&complete_buf).await.unwrap();
- stream.flush().await.unwrap();
-}