mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
start adding packet macros
This commit is contained in:
parent
e81b85dd5b
commit
a1afbb6031
20 changed files with 285 additions and 88 deletions
26
Cargo.lock
generated
26
Cargo.lock
generated
|
@ -118,6 +118,9 @@ dependencies = [
|
|||
"azalea-nbt",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"packet-macros",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
|
@ -172,6 +175,15 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
|
||||
[[package]]
|
||||
name = "casey"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabe85130dda9cf267715582ce6cf1ab581c8dfe3cb33f7065fee0f14e3fea14"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.2.7"
|
||||
|
@ -676,6 +688,16 @@ version = "11.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "packet-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"casey",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.2"
|
||||
|
@ -755,9 +777,9 @@ checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.32"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
|
|
@ -15,6 +15,9 @@ azalea-core = {path = "../azalea-core"}
|
|||
azalea-nbt = {path = "../azalea-nbt"}
|
||||
byteorder = "^1.4.3"
|
||||
bytes = "^1.1.0"
|
||||
num-derive = "^0.3.3"
|
||||
num-traits = "^0.2.14"
|
||||
packet-macros = {path = "./packet-macros"}
|
||||
serde = {version = "1.0.130", features = ["serde_derive"]}
|
||||
serde_json = "^1.0.72"
|
||||
thiserror = "^1.0.30"
|
||||
|
|
14
azalea-protocol/packet-macros/Cargo.toml
Normal file
14
azalea-protocol/packet-macros/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "packet-macros"
|
||||
version = "0.1.0"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
casey = "^0.3.3"
|
||||
proc-macro2 = "^1.0.36"
|
||||
quote = "^1.0.10"
|
||||
syn = "^1.0.82"
|
164
azalea-protocol/packet-macros/src/lib.rs
Normal file
164
azalea-protocol/packet-macros/src/lib.rs
Normal file
|
@ -0,0 +1,164 @@
|
|||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use syn::{self, parse_macro_input, spanned::Spanned, DeriveInput, FieldsNamed};
|
||||
|
||||
fn as_packet_derive(
|
||||
input: proc_macro::TokenStream,
|
||||
state: proc_macro2::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
let fields = match data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields,
|
||||
_ => panic!("#[derive(*Packet)] can only be used on structs"),
|
||||
};
|
||||
let FieldsNamed { named, .. } = match fields {
|
||||
syn::Fields::Named(f) => f,
|
||||
_ => panic!("#[derive(*Packet)] can only be used on structs with named fields"),
|
||||
};
|
||||
|
||||
let write_fields = named
|
||||
.iter()
|
||||
.map(|f| {
|
||||
let field_name = &f.ident;
|
||||
let field_type = &f.ty;
|
||||
// do a different buf.write_* for each field depending on the type
|
||||
// if it's a string, use buf.write_string
|
||||
match field_type {
|
||||
syn::Type::Path(syn::TypePath { path, .. }) => {
|
||||
if path.is_ident("String") {
|
||||
quote! { buf.write_utf(&self.#field_name)?; }
|
||||
} else if path.is_ident("ResourceLocation") {
|
||||
quote! { buf.write_resource_location(&self.#field_name)?; }
|
||||
// i don't know how to do this in a way that isn't terrible
|
||||
} else if path.to_token_stream().to_string() == "Vec < u8 >" {
|
||||
quote! { buf.write_bytes(&self.#field_name)?; }
|
||||
} else if path.is_ident("i32") {
|
||||
// only treat it as a varint if it has the varint attribute
|
||||
if f.attrs.iter().any(|attr| attr.path.is_ident("varint")) {
|
||||
quote! { buf.write_varint(self.#field_name)?; }
|
||||
} else {
|
||||
quote! { buf.write_i32(self.#field_name)?; }
|
||||
}
|
||||
} else if path.is_ident("u32") {
|
||||
if f.attrs.iter().any(|attr| attr.path.is_ident("varint")) {
|
||||
quote! { buf.write_varint(self.#field_name as i32)?; }
|
||||
} else {
|
||||
quote! { buf.write_u32(self.#field_name)?; }
|
||||
}
|
||||
} else if path.is_ident("u16") {
|
||||
quote! { buf.write_short(self.#field_name as i16)?; }
|
||||
} else if path.is_ident("ConnectionProtocol") {
|
||||
quote! { buf.write_varint(self.#field_name.clone() as i32)?; }
|
||||
} else {
|
||||
panic!(
|
||||
"#[derive(*Packet)] doesn't know how to write {}",
|
||||
path.to_token_stream()
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => panic!(
|
||||
"Error writing field {}: {}",
|
||||
field_name.clone().unwrap(),
|
||||
field_type.to_token_stream()
|
||||
),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let read_fields = named
|
||||
.iter()
|
||||
.map(|f| {
|
||||
let field_name = &f.ident;
|
||||
let field_type = &f.ty;
|
||||
// do a different buf.write_* for each field depending on the type
|
||||
// if it's a string, use buf.write_string
|
||||
match field_type {
|
||||
syn::Type::Path(syn::TypePath { path, .. }) => {
|
||||
if path.is_ident("String") {
|
||||
quote! { let #field_name = buf.read_utf().await?; }
|
||||
} else if path.is_ident("ResourceLocation") {
|
||||
quote! { let #field_name = buf.read_resource_location().await?; }
|
||||
// i don't know how to do this in a way that isn't terrible
|
||||
} else if path.to_token_stream().to_string() == "Vec < u8 >" {
|
||||
quote! { let #field_name = buf.read_bytes().await?; }
|
||||
} else if path.is_ident("i32") {
|
||||
// only treat it as a varint if it has the varint attribute
|
||||
if f.attrs.iter().any(|a| a.path.is_ident("varint")) {
|
||||
quote! { let #field_name = buf.read_varint().await?; }
|
||||
} else {
|
||||
quote! { let #field_name = buf.read_i32().await?; }
|
||||
}
|
||||
} else if path.is_ident("u32") {
|
||||
if f.attrs.iter().any(|a| a.path.is_ident("varint")) {
|
||||
quote! { let #field_name = buf.read_varint().await? as u32; }
|
||||
} else {
|
||||
quote! { let #field_name = buf.read_u32().await?; }
|
||||
}
|
||||
} else if path.is_ident("u16") {
|
||||
quote! { let #field_name = buf.read_short().await? as u16; }
|
||||
} else if path.is_ident("ConnectionProtocol") {
|
||||
quote! {
|
||||
let #field_name = ConnectionProtocol::from_i32(buf.read_varint().await?)
|
||||
.ok_or_else(|| "Invalid intention".to_string())?;
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"#[derive(*Packet)] doesn't know how to read {}",
|
||||
path.to_token_stream()
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => panic!(
|
||||
"Error reading field {}: {}",
|
||||
field_name.clone().unwrap(),
|
||||
field_type.to_token_stream()
|
||||
),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let read_field_names = named.iter().map(|f| &f.ident).collect::<Vec<_>>();
|
||||
|
||||
let gen = quote! {
|
||||
impl #ident {
|
||||
pub fn get(self) -> #state {
|
||||
#state::#ident(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
#(#write_fields)*
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
buf: &mut T,
|
||||
) -> Result<#state, String> {
|
||||
#(#read_fields)*
|
||||
Ok(#ident {
|
||||
#(#read_field_names: #read_field_names),*
|
||||
}.get())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
gen.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(GamePacket, attributes(varint))]
|
||||
pub fn derive_game_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
as_packet_derive(input, quote! {crate::packets::game::GamePacket})
|
||||
}
|
||||
|
||||
#[proc_macro_derive(HandshakePacket, attributes(varint))]
|
||||
pub fn derive_handshake_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
as_packet_derive(input, quote! {crate::packets::handshake::HandshakePacket})
|
||||
}
|
||||
|
||||
#[proc_macro_derive(LoginPacket, attributes(varint))]
|
||||
pub fn derive_login_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
as_packet_derive(input, quote! {crate::packets::login::LoginPacket})
|
||||
}
|
||||
|
||||
#[proc_macro_derive(StatusPacket, attributes(varint))]
|
||||
pub fn derive_status_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
as_packet_derive(input, quote! {crate::packets::status::StatusPacket})
|
||||
}
|
|
@ -35,7 +35,7 @@ pub trait Writable {
|
|||
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_short(&mut self, n: i16) -> Result<(), std::io::Error>;
|
||||
fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
|
||||
fn write_int(&mut self, n: i32) -> Result<(), std::io::Error>;
|
||||
fn write_boolean(&mut self, b: bool) -> Result<(), std::io::Error>;
|
||||
|
@ -125,8 +125,8 @@ impl Writable for Vec<u8> {
|
|||
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_short(&mut self, n: i16) -> Result<(), std::io::Error> {
|
||||
WriteBytesExt::write_i16::<BigEndian>(self, n)
|
||||
}
|
||||
|
||||
fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
|
||||
|
@ -176,6 +176,7 @@ pub trait Readable {
|
|||
async fn read_nbt(&mut self) -> Result<azalea_nbt::Tag, String>;
|
||||
async fn read_long(&mut self) -> Result<i64, String>;
|
||||
async fn read_resource_location(&mut self) -> Result<ResourceLocation, String>;
|
||||
async fn read_short(&mut self) -> Result<i16, String>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
@ -334,6 +335,13 @@ where
|
|||
let location = ResourceLocation::new(&location_string)?;
|
||||
Ok(location)
|
||||
}
|
||||
|
||||
async fn read_short(&mut self) -> Result<i16, String> {
|
||||
match AsyncReadExt::read_i16(self).await {
|
||||
Ok(r) => Ok(r),
|
||||
Err(_) => Err("Error reading short".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,30 +1,10 @@
|
|||
use super::GamePacket;
|
||||
use crate::mc_buf::{Readable, Writable};
|
||||
use azalea_core::{game_type::GameType, resource_location::ResourceLocation};
|
||||
use crate::packets::game::GamePacket;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use packet_macros::GamePacket;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, GamePacket)]
|
||||
pub struct ClientboundCustomPayloadPacket {
|
||||
pub identifier: ResourceLocation,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl ClientboundCustomPayloadPacket {
|
||||
pub fn get(self) -> GamePacket {
|
||||
GamePacket::ClientboundCustomPayloadPacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
buf.write_resource_location(&self.identifier)?;
|
||||
buf.write_bytes(&self.data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
buf: &mut T,
|
||||
) -> Result<GamePacket, String> {
|
||||
let identifier = buf.read_resource_location().await?;
|
||||
let data = buf.read_bytes().await?;
|
||||
|
||||
Ok(ClientboundCustomPayloadPacket { identifier, data }.get())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,10 @@
|
|||
|
||||
use super::GamePacket;
|
||||
use crate::mc_buf::{Readable, Writable};
|
||||
use packet_macros::GamePacket;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, GamePacket)]
|
||||
pub struct ClientboundUpdateViewDistancePacket {
|
||||
#[varint]
|
||||
pub view_distance: i32,
|
||||
}
|
||||
|
||||
impl ClientboundUpdateViewDistancePacket {
|
||||
pub fn get(self) -> GamePacket {
|
||||
GamePacket::ClientboundUpdateViewDistancePacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
buf.write_varint(self.view_distance)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
buf: &mut T,
|
||||
) -> Result<GamePacket, String> {
|
||||
let view_distance = buf.read_varint().await?;
|
||||
|
||||
Ok(ClientboundUpdateViewDistancePacket { view_distance }.get())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,9 @@ impl ProtocolPacket for GamePacket {
|
|||
}
|
||||
}
|
||||
|
||||
fn write(&self, _buf: &mut Vec<u8>) {}
|
||||
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read a packet by its id, ConnectionProtocol, and flow
|
||||
async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
|
@ -48,7 +50,8 @@ impl ProtocolPacket for GamePacket {
|
|||
0x4a => clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket
|
||||
::read(buf)
|
||||
.await?,
|
||||
_ => return Err(format!("Unknown ServerToClient game packet id: {}", id)),
|
||||
// _ => return Err(format!("Unknown ServerToClient game packet id: {}", id)),
|
||||
_ => panic!("Unknown ServerToClient game packet id: {}", id),
|
||||
},
|
||||
PacketFlow::ClientToServer => match id {
|
||||
// 0x00 => serverbound_hello_packet::ServerboundHelloPacket::read(buf).await?,
|
||||
|
|
|
@ -1,34 +1,48 @@
|
|||
use crate::{
|
||||
mc_buf::{Readable, Writable},
|
||||
packets::ConnectionProtocol,
|
||||
};
|
||||
use num_traits::FromPrimitive;
|
||||
use packet_macros::HandshakePacket;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::{mc_buf::Writable, packets::ConnectionProtocol};
|
||||
|
||||
use super::HandshakePacket;
|
||||
|
||||
#[derive(Hash, Clone, Debug)]
|
||||
#[derive(Hash, Clone, Debug, HandshakePacket)]
|
||||
pub struct ClientIntentionPacket {
|
||||
#[varint]
|
||||
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)
|
||||
}
|
||||
// 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 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 T,
|
||||
) -> Result<HandshakePacket, String> {
|
||||
Err("ClientIntentionPacket::parse not implemented".to_string())
|
||||
// Ok(ClientIntentionPacket {}.get())
|
||||
}
|
||||
}
|
||||
// pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
// buf: &mut T,
|
||||
// ) -> Result<HandshakePacket, String> {
|
||||
// let protocol_version = buf.read_varint().await? as u32;
|
||||
// let hostname = buf.read_utf().await?;
|
||||
// let port = buf.read_short().await? as u16;
|
||||
// let intention = buf.read_varint().await?;
|
||||
|
||||
// Ok(HandshakePacket::ClientIntentionPacket(
|
||||
// ClientIntentionPacket {
|
||||
// protocol_version,
|
||||
// hostname,
|
||||
// port,
|
||||
// intention: ConnectionProtocol::from_i32(intention)
|
||||
// .ok_or_else(|| "Invalid intention".to_string())?,
|
||||
// },
|
||||
// ))
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -22,7 +22,7 @@ impl ProtocolPacket for HandshakePacket {
|
|||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &mut Vec<u8>) {
|
||||
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
HandshakePacket::ClientIntentionPacket(packet) => packet.write(buf),
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@ impl ClientboundCustomQueryPacket {
|
|||
LoginPacket::ClientboundCustomQueryPacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) {
|
||||
pub fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
buf.write_varint(self.transaction_id as i32).unwrap();
|
||||
buf.write_utf(self.identifier.to_string().as_str()).unwrap();
|
||||
buf.write_bytes(&self.data).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
|
|
|
@ -14,11 +14,12 @@ impl ClientboundGameProfilePacket {
|
|||
LoginPacket::ClientboundGameProfilePacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) {
|
||||
pub fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
for n in self.game_profile.uuid.to_int_array() {
|
||||
buf.write_int(n as i32).unwrap();
|
||||
}
|
||||
buf.write_utf(self.game_profile.name.as_str()).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
|
|
|
@ -16,7 +16,7 @@ impl ClientboundHelloPacket {
|
|||
LoginPacket::ClientboundHelloPacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &mut Vec<u8>) {
|
||||
pub fn write(&self, _buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
panic!("ClientboundHelloPacket::write not implemented")
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,9 @@ impl ClientboundLoginCompressionPacket {
|
|||
LoginPacket::ClientboundLoginCompressionPacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) {
|
||||
pub fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
buf.write_varint(self.compression_threshold).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
|
|
|
@ -34,7 +34,7 @@ impl ProtocolPacket for LoginPacket {
|
|||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &mut Vec<u8>) {
|
||||
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
LoginPacket::ClientboundCustomQueryPacket(packet) => packet.write(buf),
|
||||
LoginPacket::ClientboundGameProfilePacket(packet) => packet.write(buf),
|
||||
|
|
|
@ -14,8 +14,9 @@ impl ServerboundHelloPacket {
|
|||
LoginPacket::ServerboundHelloPacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut Vec<u8>) {
|
||||
pub fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
buf.write_utf(&self.username).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
|
|
|
@ -3,13 +3,13 @@ pub mod handshake;
|
|||
pub mod login;
|
||||
pub mod status;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::connect::PacketFlow;
|
||||
use async_trait::async_trait;
|
||||
use num_derive::FromPrimitive;
|
||||
|
||||
pub const PROTOCOL_VERSION: u32 = 757;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, FromPrimitive)]
|
||||
pub enum ConnectionProtocol {
|
||||
Handshake = -1,
|
||||
Game = 0,
|
||||
|
@ -42,5 +42,5 @@ where
|
|||
where
|
||||
Self: Sized;
|
||||
|
||||
fn write(&self, buf: &mut Vec<u8>);
|
||||
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error>;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,9 @@ impl ClientboundStatusResponsePacket {
|
|||
StatusPacket::ClientboundStatusResponsePacket(Box::new(self))
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &mut Vec<u8>) {}
|
||||
pub fn write(&self, _buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||
buf: &mut T,
|
||||
|
|
|
@ -29,7 +29,7 @@ impl ProtocolPacket for StatusPacket {
|
|||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &mut Vec<u8>) {
|
||||
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
StatusPacket::ServerboundStatusRequestPacket(packet) => packet.write(buf),
|
||||
StatusPacket::ClientboundStatusResponsePacket(packet) => packet.write(buf),
|
||||
|
|
|
@ -10,7 +10,7 @@ impl ServerboundStatusRequestPacket {
|
|||
StatusPacket::ServerboundStatusRequestPacket(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &mut Vec<u8>) {
|
||||
pub fn write(&self, _buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
panic!("ServerboundStatusRequestPacket::write not implemented")
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue