mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 23:44:38 +00:00
start implementing joining servers
This commit is contained in:
parent
2c3bf3b79e
commit
c96ae8fce4
19 changed files with 374 additions and 95 deletions
|
@ -1,11 +1,11 @@
|
||||||
use minecraft_client::ping;
|
use minecraft_client::{connect::join_server, ping::ping_server};
|
||||||
use minecraft_protocol::ServerAddress;
|
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
async fn bot() {
|
async fn bot() {
|
||||||
let address = ServerAddress::parse(&"mc.hypixel.net".to_string()).unwrap();
|
let address = "localhost:63425";
|
||||||
let response = ping::ping_server(&address).await.unwrap();
|
let response = join_server(&address.try_into().unwrap()).await.unwrap();
|
||||||
println!("{}", response.description.to_ansi(None));
|
// println!("{}", response.description.to_ansi(None));
|
||||||
|
println!("connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -27,9 +27,7 @@ pub fn legacy_color_code_to_text_component(legacy_color_code: &str) -> TextCompo
|
||||||
if legacy_color_code.chars().nth(i).unwrap() == LEGACY_FORMATTING_CODE_SYMBOL {
|
if legacy_color_code.chars().nth(i).unwrap() == LEGACY_FORMATTING_CODE_SYMBOL {
|
||||||
let formatting_code = legacy_color_code.chars().nth(i + 1).unwrap();
|
let formatting_code = legacy_color_code.chars().nth(i + 1).unwrap();
|
||||||
if let Ok(formatter) = ChatFormatting::from_code(formatting_code) {
|
if let Ok(formatter) = ChatFormatting::from_code(formatting_code) {
|
||||||
if components.is_empty() {
|
if components.is_empty() || !components.last().unwrap().text.is_empty() {
|
||||||
components.push(TextComponent::new("".to_string()));
|
|
||||||
} else if !components.last().unwrap().text.is_empty() {
|
|
||||||
components.push(TextComponent::new("".to_string()));
|
components.push(TextComponent::new("".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
49
minecraft-client/src/connect.rs
Normal file
49
minecraft-client/src/connect.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
///! Connect to Minecraft servers.
|
||||||
|
use minecraft_protocol::{
|
||||||
|
connect::Connection,
|
||||||
|
packets::{
|
||||||
|
handshake::client_intention_packet::ClientIntentionPacket,
|
||||||
|
login::serverbound_hello_packet::ServerboundHelloPacket,
|
||||||
|
status::clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
||||||
|
ConnectionProtocol, Packet, PacketTrait, PROTOCOL_VERSION,
|
||||||
|
},
|
||||||
|
resolver, ServerAddress,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn join_server(address: &ServerAddress) -> Result<(), String> {
|
||||||
|
let username = "bot".to_string();
|
||||||
|
|
||||||
|
let resolved_address = resolver::resolve_address(address).await?;
|
||||||
|
|
||||||
|
let mut conn = Connection::new(&resolved_address).await?;
|
||||||
|
|
||||||
|
// handshake
|
||||||
|
conn.send_packet(
|
||||||
|
ClientIntentionPacket {
|
||||||
|
protocol_version: PROTOCOL_VERSION,
|
||||||
|
hostname: address.host.clone(),
|
||||||
|
port: address.port,
|
||||||
|
intention: ConnectionProtocol::Login,
|
||||||
|
}
|
||||||
|
.get(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
conn.switch_state(ConnectionProtocol::Login);
|
||||||
|
|
||||||
|
// login start
|
||||||
|
conn.send_packet(ServerboundHelloPacket { username }.get())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// encryption request
|
||||||
|
let packet = conn.read_packet().await.unwrap();
|
||||||
|
let encryption_request_packet = match packet {
|
||||||
|
Packet::ClientboundHelloPacket(p) => p,
|
||||||
|
_ => Err(format!("Invalid packet type: {:?}", packet))?,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: client auth
|
||||||
|
|
||||||
|
// TODO: encryption response
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
//! Significantly abstract minecraft-protocol so it's actually useable for bots.
|
||||||
|
|
||||||
|
pub mod connect;
|
||||||
pub mod ping;
|
pub mod ping;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
0
minecraft-client/src/listeners/handshake.rs
Normal file
0
minecraft-client/src/listeners/handshake.rs
Normal file
3
minecraft-client/src/listeners/mod.rs
Normal file
3
minecraft-client/src/listeners/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
trait PacketListener {
|
||||||
|
handle(Packet)
|
||||||
|
}
|
|
@ -1,14 +1,13 @@
|
||||||
///! Ping Minecraft servers.
|
///! Ping Minecraft servers.
|
||||||
|
|
||||||
use minecraft_protocol::{
|
use minecraft_protocol::{
|
||||||
connection::Connection,
|
connect::Connection,
|
||||||
packets::{
|
packets::{
|
||||||
handshake::client_intention_packet::ClientIntentionPacket,
|
handshake::client_intention_packet::ClientIntentionPacket,
|
||||||
status::{
|
status::{
|
||||||
clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
||||||
serverbound_status_request_packet::ServerboundStatusRequestPacket,
|
serverbound_status_request_packet::ServerboundStatusRequestPacket,
|
||||||
},
|
},
|
||||||
ConnectionProtocol, Packet, PacketTrait,
|
ConnectionProtocol, Packet, PacketTrait, PROTOCOL_VERSION,
|
||||||
},
|
},
|
||||||
resolver, ServerAddress,
|
resolver, ServerAddress,
|
||||||
};
|
};
|
||||||
|
@ -23,7 +22,7 @@ pub async fn ping_server(
|
||||||
// send the client intention packet and switch to the status state
|
// send the client intention packet and switch to the status state
|
||||||
conn.send_packet(
|
conn.send_packet(
|
||||||
ClientIntentionPacket {
|
ClientIntentionPacket {
|
||||||
protocol_version: 757,
|
protocol_version: PROTOCOL_VERSION,
|
||||||
hostname: address.host.clone(),
|
hostname: address.host.clone(),
|
||||||
port: address.port,
|
port: address.port,
|
||||||
intention: ConnectionProtocol::Status,
|
intention: ConnectionProtocol::Status,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub mod connection;
|
pub mod connect;
|
||||||
pub mod mc_buf;
|
pub mod mc_buf;
|
||||||
pub mod packets;
|
pub mod packets;
|
||||||
pub mod resolver;
|
pub mod resolver;
|
||||||
|
@ -20,9 +20,12 @@ pub struct ServerIpAddress {
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerAddress {
|
// 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
|
/// Convert a Minecraft server address (host:port, the port is optional) to a ServerAddress
|
||||||
pub fn parse(string: &str) -> Result<ServerAddress, String> {
|
fn try_from(string: &str) -> Result<Self, Self::Error> {
|
||||||
if string.is_empty() {
|
if string.is_empty() {
|
||||||
return Err("Empty string".to_string());
|
return Err("Empty string".to_string());
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,17 @@ pub fn write_byte(buf: &mut Vec<u8>, n: u8) {
|
||||||
WriteBytesExt::write_u8(buf, n).unwrap();
|
WriteBytesExt::write_u8(buf, n).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_bytes<T: AsyncRead + std::marker::Unpin>(
|
||||||
|
buf: &mut BufReader<T>,
|
||||||
|
n: usize,
|
||||||
|
) -> Result<Vec<u8>, String> {
|
||||||
|
let mut bytes = vec![0; n];
|
||||||
|
match AsyncReadExt::read_exact(buf, &mut bytes).await {
|
||||||
|
Ok(_) => Ok(bytes),
|
||||||
|
Err(_) => Err("Error reading bytes".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) {
|
pub fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) {
|
||||||
buf.extend_from_slice(bytes);
|
buf.extend_from_slice(bytes);
|
||||||
}
|
}
|
||||||
|
@ -159,3 +170,15 @@ pub fn write_utf(buf: &mut Vec<u8>, string: &str) {
|
||||||
pub fn write_short(buf: &mut Vec<u8>, n: u16) {
|
pub fn write_short(buf: &mut Vec<u8>, n: u16) {
|
||||||
WriteBytesExt::write_u16::<BigEndian>(buf, n).unwrap();
|
WriteBytesExt::write_u16::<BigEndian>(buf, n).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_byte_array<T: AsyncRead + std::marker::Unpin>(
|
||||||
|
buf: &mut BufReader<T>,
|
||||||
|
) -> Result<Vec<u8>, String> {
|
||||||
|
let length = read_varint(buf).await?.0 as usize;
|
||||||
|
Ok(read_bytes(buf, length).await?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_byte_array(buf: &mut Vec<u8>, bytes: &[u8]) {
|
||||||
|
write_varint(buf, bytes.len() as i32);
|
||||||
|
write_bytes(buf, bytes);
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum GamePacket {}
|
||||||
|
|
|
@ -1 +1,6 @@
|
||||||
pub mod client_intention_packet;
|
pub mod client_intention_packet;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum HandshakePacket {
|
||||||
|
ClientIntentionPacket(client_intention_packet::ClientIntentionPacket),
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use tokio::io::BufReader;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
mc_buf,
|
||||||
|
packets::{Packet, PacketTrait},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Hash, Clone, Debug)]
|
||||||
|
pub struct ClientboundHelloPacket {
|
||||||
|
pub server_id: String,
|
||||||
|
pub public_key: Vec<u8>,
|
||||||
|
pub nonce: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl PacketTrait for ClientboundHelloPacket {
|
||||||
|
fn get(self) -> Packet {
|
||||||
|
Packet::ClientboundHelloPacket(self)
|
||||||
|
}
|
||||||
|
fn write(&self, _buf: &mut Vec<u8>) {
|
||||||
|
panic!("ClientboundHelloPacket::write not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||||
|
buf: &mut BufReader<T>,
|
||||||
|
) -> Result<Packet, String> {
|
||||||
|
let server_id = mc_buf::read_utf_with_len(buf, 20).await?;
|
||||||
|
let public_key = mc_buf::read_byte_array(buf).await?;
|
||||||
|
let nonce = mc_buf::read_byte_array(buf).await?;
|
||||||
|
|
||||||
|
Ok(ClientboundHelloPacket {
|
||||||
|
server_id,
|
||||||
|
public_key,
|
||||||
|
nonce,
|
||||||
|
}
|
||||||
|
.get())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,8 @@
|
||||||
|
pub mod clientbound_hello_packet;
|
||||||
|
pub mod serverbound_hello_packet;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum LoginPacket {
|
||||||
|
ServerboundHelloPacket(serverbound_hello_packet::ServerboundHelloPacket),
|
||||||
|
ClientboundHelloPacket(clientbound_hello_packet::ClientboundHelloPacket),
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use tokio::io::BufReader;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
mc_buf,
|
||||||
|
packets::{Packet, PacketTrait},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Hash, Clone, Debug)]
|
||||||
|
pub struct ServerboundHelloPacket {
|
||||||
|
pub username: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl PacketTrait for ServerboundHelloPacket {
|
||||||
|
fn get(self) -> Packet {
|
||||||
|
Packet::ServerboundHelloPacket(self)
|
||||||
|
}
|
||||||
|
fn write(&self, buf: &mut Vec<u8>) {
|
||||||
|
mc_buf::write_utf(buf, &self.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||||
|
_buf: &mut BufReader<T>,
|
||||||
|
) -> Result<Packet, String> {
|
||||||
|
Err("ServerboundHelloPacket::read not implemented".to_string())
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,9 @@ pub mod status;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use tokio::io::{AsyncRead, BufReader};
|
use tokio::io::{AsyncRead, BufReader};
|
||||||
|
|
||||||
use crate::connection::PacketFlow;
|
use crate::connect::PacketFlow;
|
||||||
|
|
||||||
|
pub const PROTOCOL_VERSION: u32 = 757;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum ConnectionProtocol {
|
pub enum ConnectionProtocol {
|
||||||
|
@ -18,90 +20,123 @@ pub enum ConnectionProtocol {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Packet {
|
pub enum Packet {
|
||||||
// game
|
Game(game::GamePacket),
|
||||||
|
Handshake(handshake::HandshakePacket),
|
||||||
// handshake
|
Login(login::LoginPacket),
|
||||||
ClientIntentionPacket(handshake::client_intention_packet::ClientIntentionPacket),
|
Status(status::StatusPacket),
|
||||||
|
|
||||||
// login
|
|
||||||
|
|
||||||
// status
|
|
||||||
ServerboundStatusRequestPacket(
|
|
||||||
status::serverbound_status_request_packet::ServerboundStatusRequestPacket,
|
|
||||||
),
|
|
||||||
ClientboundStatusResponsePacket(
|
|
||||||
status::clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: do all this with macros so it's less repetitive
|
#[async_trait]
|
||||||
impl Packet {
|
pub trait ProtocolPacket {
|
||||||
fn get_inner_packet(&self) -> &dyn PacketTrait {
|
fn get_inner<P: PacketTrait>(&self) -> &P;
|
||||||
match self {
|
|
||||||
Packet::ClientIntentionPacket(packet) => packet,
|
|
||||||
Packet::ServerboundStatusRequestPacket(packet) => packet,
|
|
||||||
Packet::ClientboundStatusResponsePacket(packet) => packet,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> u32 {
|
fn id(&self) -> u32;
|
||||||
match self {
|
|
||||||
Packet::ClientIntentionPacket(_packet) => 0x00,
|
|
||||||
Packet::ServerboundStatusRequestPacket(_packet) => 0x00,
|
|
||||||
Packet::ClientboundStatusResponsePacket(_packet) => 0x00,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read a packet by its id, ConnectionProtocol, and flow
|
/// Read a packet by its id, ConnectionProtocol, and flow
|
||||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
async fn read<
|
||||||
|
T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send,
|
||||||
|
P: ProtocolPacket,
|
||||||
|
>(
|
||||||
id: u32,
|
id: u32,
|
||||||
protocol: &ConnectionProtocol,
|
|
||||||
flow: &PacketFlow,
|
flow: &PacketFlow,
|
||||||
buf: &mut BufReader<T>,
|
buf: &mut BufReader<T>,
|
||||||
) -> Result<Packet, String> {
|
) -> Result<P, String>
|
||||||
match protocol {
|
where
|
||||||
ConnectionProtocol::Handshake => match id {
|
Self: Sized;
|
||||||
0x00 => Ok(
|
|
||||||
handshake::client_intention_packet::ClientIntentionPacket::read(buf).await?,
|
fn write(&self, buf: &mut Vec<u8>);
|
||||||
),
|
|
||||||
_ => Err(format!("Unknown packet id: {}", id)),
|
|
||||||
},
|
|
||||||
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 packet id: {}", id)),
|
|
||||||
},
|
|
||||||
PacketFlow::ClientToServer => match id {
|
|
||||||
0x00 => Ok(
|
|
||||||
status::serverbound_status_request_packet::ServerboundStatusRequestPacket
|
|
||||||
::read(buf)
|
|
||||||
.await?,
|
|
||||||
),
|
|
||||||
_ => Err(format!("Unknown packet id: {}", id)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ConnectionProtocol::Login => Err("Login protocol not implemented yet".to_string()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, buf: &mut Vec<u8>) {
|
// impl Packet {
|
||||||
self.get_inner_packet().write(buf);
|
// 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]
|
#[async_trait]
|
||||||
pub trait PacketTrait {
|
pub trait PacketTrait {
|
||||||
/// Return a version of the packet that you can actually use for stuff
|
/// Return a version of the packet that you can actually use for stuff
|
||||||
fn get(self) -> Packet;
|
fn get<P: ProtocolPacket>(self) -> P;
|
||||||
fn write(&self, buf: &mut Vec<u8>);
|
fn write(&self, buf: &mut Vec<u8>);
|
||||||
async fn read<T: AsyncRead + std::marker::Unpin + std::marker::Send>(
|
async fn read<T: AsyncRead + std::marker::Unpin + std::marker::Send, P: ProtocolPacket>(
|
||||||
buf: &mut BufReader<T>,
|
buf: &mut BufReader<T>,
|
||||||
) -> Result<Packet, String>
|
) -> Result<P, String>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,11 @@ use crate::{
|
||||||
packets::{Packet, PacketTrait},
|
packets::{Packet, PacketTrait},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::StatusPacket;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct Version {
|
pub struct Version {
|
||||||
pub name: String,
|
pub name: Component,
|
||||||
pub protocol: u32,
|
pub protocol: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,14 +33,16 @@ pub struct Players {
|
||||||
// the entire packet is just json, which is why it has deserialize
|
// the entire packet is just json, which is why it has deserialize
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct ClientboundStatusResponsePacket {
|
pub struct ClientboundStatusResponsePacket {
|
||||||
pub version: Version,
|
|
||||||
pub description: Component,
|
pub description: Component,
|
||||||
|
pub favicon: Option<String>,
|
||||||
|
pub players: Players,
|
||||||
|
pub version: Version,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl PacketTrait for ClientboundStatusResponsePacket {
|
impl PacketTrait for ClientboundStatusResponsePacket {
|
||||||
fn get(self) -> Packet {
|
fn get(self) -> StatusPacket {
|
||||||
Packet::ClientboundStatusResponsePacket(self)
|
StatusPacket::ClientboundStatusResponsePacket(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, _buf: &mut Vec<u8>) {}
|
fn write(&self, _buf: &mut Vec<u8>) {}
|
||||||
|
|
|
@ -1,2 +1,80 @@
|
||||||
pub mod clientbound_status_response_packet;
|
pub mod clientbound_status_response_packet;
|
||||||
pub mod serverbound_status_request_packet;
|
pub mod serverbound_status_request_packet;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use tokio::io::BufReader;
|
||||||
|
|
||||||
|
use crate::connect::PacketFlow;
|
||||||
|
|
||||||
|
use super::{ConnectionProtocol, PacketTrait, ProtocolPacket};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum StatusPacket {
|
||||||
|
ServerboundStatusRequestPacket(
|
||||||
|
serverbound_status_request_packet::ServerboundStatusRequestPacket,
|
||||||
|
),
|
||||||
|
ClientboundStatusResponsePacket(
|
||||||
|
clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[async_trait]
|
||||||
|
// impl ProtocolPacket for StatusPacket {
|
||||||
|
impl StatusPacket {
|
||||||
|
fn get_inner(self) -> impl PacketTrait {
|
||||||
|
match self {
|
||||||
|
StatusPacket::ServerboundStatusRequestPacket(packet) => packet,
|
||||||
|
StatusPacket::ClientboundStatusResponsePacket(packet) => packet,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fn get_inner(&self) -> StatusPacket {
|
||||||
|
// match self {
|
||||||
|
// StatusPacket::ServerboundStatusRequestPacket(packet) => packet,
|
||||||
|
// StatusPacket::ClientboundStatusResponsePacket(packet) => packet,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
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,
|
||||||
|
P: ProtocolPacket,
|
||||||
|
>(
|
||||||
|
id: u32,
|
||||||
|
flow: &PacketFlow,
|
||||||
|
buf: &mut BufReader<T>,
|
||||||
|
) -> Result<P, 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)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,19 +2,21 @@ use async_trait::async_trait;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use tokio::io::BufReader;
|
use tokio::io::BufReader;
|
||||||
|
|
||||||
use crate::{
|
use crate::packets::{Packet, PacketTrait, ProtocolPacket};
|
||||||
packets::{Packet, PacketTrait},
|
|
||||||
};
|
use super::StatusPacket;
|
||||||
|
|
||||||
#[derive(Hash, Clone, Debug)]
|
#[derive(Hash, Clone, Debug)]
|
||||||
pub struct ServerboundStatusRequestPacket {}
|
pub struct ServerboundStatusRequestPacket {}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl PacketTrait for ServerboundStatusRequestPacket {
|
impl PacketTrait for ServerboundStatusRequestPacket {
|
||||||
fn get(self) -> Packet {
|
fn get(self) -> StatusPacket {
|
||||||
Packet::ServerboundStatusRequestPacket(self)
|
StatusPacket::ServerboundStatusRequestPacket(self)
|
||||||
|
}
|
||||||
|
fn write(&self, _buf: &mut Vec<u8>) {
|
||||||
|
panic!("ServerboundStatusRequestPacket::write not implemented")
|
||||||
}
|
}
|
||||||
fn write(&self, _buf: &mut Vec<u8>) {}
|
|
||||||
|
|
||||||
async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||||
_buf: &mut BufReader<T>,
|
_buf: &mut BufReader<T>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue