mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +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_protocol::ServerAddress;
|
||||
use minecraft_client::{connect::join_server, ping::ping_server};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
async fn bot() {
|
||||
let address = ServerAddress::parse(&"mc.hypixel.net".to_string()).unwrap();
|
||||
let response = ping::ping_server(&address).await.unwrap();
|
||||
println!("{}", response.description.to_ansi(None));
|
||||
let address = "localhost:63425";
|
||||
let response = join_server(&address.try_into().unwrap()).await.unwrap();
|
||||
// println!("{}", response.description.to_ansi(None));
|
||||
println!("connected");
|
||||
}
|
||||
|
||||
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 {
|
||||
let formatting_code = legacy_color_code.chars().nth(i + 1).unwrap();
|
||||
if let Ok(formatter) = ChatFormatting::from_code(formatting_code) {
|
||||
if components.is_empty() {
|
||||
components.push(TextComponent::new("".to_string()));
|
||||
} else if !components.last().unwrap().text.is_empty() {
|
||||
if components.is_empty() || !components.last().unwrap().text.is_empty() {
|
||||
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;
|
||||
|
||||
#[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.
|
||||
|
||||
use minecraft_protocol::{
|
||||
connection::Connection,
|
||||
connect::Connection,
|
||||
packets::{
|
||||
handshake::client_intention_packet::ClientIntentionPacket,
|
||||
status::{
|
||||
clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
||||
serverbound_status_request_packet::ServerboundStatusRequestPacket,
|
||||
},
|
||||
ConnectionProtocol, Packet, PacketTrait,
|
||||
ConnectionProtocol, Packet, PacketTrait, PROTOCOL_VERSION,
|
||||
},
|
||||
resolver, ServerAddress,
|
||||
};
|
||||
|
@ -23,7 +22,7 @@ pub async fn ping_server(
|
|||
// send the client intention packet and switch to the status state
|
||||
conn.send_packet(
|
||||
ClientIntentionPacket {
|
||||
protocol_version: 757,
|
||||
protocol_version: PROTOCOL_VERSION,
|
||||
hostname: address.host.clone(),
|
||||
port: address.port,
|
||||
intention: ConnectionProtocol::Status,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub mod connection;
|
||||
pub mod connect;
|
||||
pub mod mc_buf;
|
||||
pub mod packets;
|
||||
pub mod resolver;
|
||||
|
@ -20,9 +20,12 @@ pub struct ServerIpAddress {
|
|||
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
|
||||
pub fn parse(string: &str) -> Result<ServerAddress, String> {
|
||||
fn try_from(string: &str) -> Result<Self, Self::Error> {
|
||||
if string.is_empty() {
|
||||
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();
|
||||
}
|
||||
|
||||
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]) {
|
||||
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) {
|
||||
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;
|
||||
|
||||
#[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 tokio::io::{AsyncRead, BufReader};
|
||||
|
||||
use crate::connection::PacketFlow;
|
||||
use crate::connect::PacketFlow;
|
||||
|
||||
pub const PROTOCOL_VERSION: u32 = 757;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ConnectionProtocol {
|
||||
|
@ -18,90 +20,123 @@ pub enum ConnectionProtocol {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Packet {
|
||||
// game
|
||||
|
||||
// handshake
|
||||
ClientIntentionPacket(handshake::client_intention_packet::ClientIntentionPacket),
|
||||
|
||||
// login
|
||||
|
||||
// status
|
||||
ServerboundStatusRequestPacket(
|
||||
status::serverbound_status_request_packet::ServerboundStatusRequestPacket,
|
||||
),
|
||||
ClientboundStatusResponsePacket(
|
||||
status::clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
||||
),
|
||||
Game(game::GamePacket),
|
||||
Handshake(handshake::HandshakePacket),
|
||||
Login(login::LoginPacket),
|
||||
Status(status::StatusPacket),
|
||||
}
|
||||
|
||||
// TODO: do all this with macros so it's less repetitive
|
||||
impl Packet {
|
||||
fn get_inner_packet(&self) -> &dyn PacketTrait {
|
||||
match self {
|
||||
Packet::ClientIntentionPacket(packet) => packet,
|
||||
Packet::ServerboundStatusRequestPacket(packet) => packet,
|
||||
Packet::ClientboundStatusResponsePacket(packet) => packet,
|
||||
}
|
||||
}
|
||||
#[async_trait]
|
||||
pub trait ProtocolPacket {
|
||||
fn get_inner<P: PacketTrait>(&self) -> &P;
|
||||
|
||||
pub fn id(&self) -> u32 {
|
||||
match self {
|
||||
Packet::ClientIntentionPacket(_packet) => 0x00,
|
||||
Packet::ServerboundStatusRequestPacket(_packet) => 0x00,
|
||||
Packet::ClientboundStatusResponsePacket(_packet) => 0x00,
|
||||
}
|
||||
}
|
||||
fn id(&self) -> u32;
|
||||
|
||||
/// 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,
|
||||
protocol: &ConnectionProtocol,
|
||||
flow: &PacketFlow,
|
||||
buf: &mut BufReader<T>,
|
||||
) -> Result<Packet, String> {
|
||||
match protocol {
|
||||
ConnectionProtocol::Handshake => match id {
|
||||
0x00 => Ok(
|
||||
handshake::client_intention_packet::ClientIntentionPacket::read(buf).await?,
|
||||
),
|
||||
_ => 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()),
|
||||
}
|
||||
}
|
||||
) -> Result<P, String>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) {
|
||||
self.get_inner_packet().write(buf);
|
||||
}
|
||||
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 {
|
||||
/// 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>);
|
||||
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>,
|
||||
) -> Result<Packet, String>
|
||||
) -> Result<P, String>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@ use crate::{
|
|||
packets::{Packet, PacketTrait},
|
||||
};
|
||||
|
||||
use super::StatusPacket;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct Version {
|
||||
pub name: String,
|
||||
pub name: Component,
|
||||
pub protocol: u32,
|
||||
}
|
||||
|
||||
|
@ -31,14 +33,16 @@ pub struct Players {
|
|||
// the entire packet is just json, which is why it has deserialize
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct ClientboundStatusResponsePacket {
|
||||
pub version: Version,
|
||||
pub description: Component,
|
||||
pub favicon: Option<String>,
|
||||
pub players: Players,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl PacketTrait for ClientboundStatusResponsePacket {
|
||||
fn get(self) -> Packet {
|
||||
Packet::ClientboundStatusResponsePacket(self)
|
||||
fn get(self) -> StatusPacket {
|
||||
StatusPacket::ClientboundStatusResponsePacket(self)
|
||||
}
|
||||
|
||||
fn write(&self, _buf: &mut Vec<u8>) {}
|
||||
|
|
|
@ -1,2 +1,80 @@
|
|||
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::{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 tokio::io::BufReader;
|
||||
|
||||
use crate::{
|
||||
packets::{Packet, PacketTrait},
|
||||
};
|
||||
use crate::packets::{Packet, PacketTrait, ProtocolPacket};
|
||||
|
||||
use super::StatusPacket;
|
||||
|
||||
#[derive(Hash, Clone, Debug)]
|
||||
pub struct ServerboundStatusRequestPacket {}
|
||||
|
||||
#[async_trait]
|
||||
impl PacketTrait for ServerboundStatusRequestPacket {
|
||||
fn get(self) -> Packet {
|
||||
Packet::ServerboundStatusRequestPacket(self)
|
||||
fn get(self) -> StatusPacket {
|
||||
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>(
|
||||
_buf: &mut BufReader<T>,
|
||||
|
|
Loading…
Add table
Reference in a new issue