mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
Simplify packet macro
Now every packet implements McBufWritable and McBufReadable and uses those so the code doesn't have to be duplicated.
This commit is contained in:
parent
0dc6decf7f
commit
8313952541
8 changed files with 68 additions and 85 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -75,7 +75,6 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||
name = "azalea-auth"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
|
@ -97,6 +96,7 @@ name = "azalea-client"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"azalea-auth",
|
||||
"azalea-core",
|
||||
"azalea-crypto",
|
||||
"azalea-protocol",
|
||||
"tokio",
|
||||
|
|
|
@ -6,5 +6,4 @@ version = "0.1.0"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
num-bigint = "^0.4.3"
|
||||
uuid = "^0.8.2"
|
||||
|
|
|
@ -7,6 +7,7 @@ version = "0.1.0"
|
|||
|
||||
[dependencies]
|
||||
azalea-auth = {path = "../azalea-auth"}
|
||||
azalea-core = {path = "../azalea-core"}
|
||||
azalea-crypto = {path = "../azalea-crypto"}
|
||||
azalea-protocol = {path = "../azalea-protocol"}
|
||||
tokio = {version = "1.18.0", features = ["sync"]}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use crate::Player;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use azalea_protocol::{
|
||||
connect::{GameConnection, HandshakeConnection},
|
||||
packets::{
|
||||
game::GamePacket,
|
||||
game::{serverbound_custom_payload_packet::ServerboundCustomPayloadPacket, GamePacket},
|
||||
handshake::client_intention_packet::ClientIntentionPacket,
|
||||
login::{
|
||||
serverbound_hello_packet::ServerboundHelloPacket,
|
||||
|
@ -15,8 +17,6 @@ use std::sync::Arc;
|
|||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::Player;
|
||||
|
||||
///! Connect to Minecraft servers.
|
||||
|
||||
/// Something that can join Minecraft servers.
|
||||
|
@ -148,7 +148,7 @@ impl Client {
|
|||
loop {
|
||||
let r = conn.lock().await.read().await;
|
||||
match r {
|
||||
Ok(packet) => Self::handle(&packet, &tx, &state).await,
|
||||
Ok(packet) => Self::handle(&packet, &tx, &state, &conn).await,
|
||||
Err(e) => {
|
||||
panic!("Error: {:?}", e);
|
||||
}
|
||||
|
@ -160,12 +160,21 @@ impl Client {
|
|||
packet: &GamePacket,
|
||||
tx: &UnboundedSender<Event>,
|
||||
state: &Arc<Mutex<ClientState>>,
|
||||
conn: &Arc<Mutex<GameConnection>>,
|
||||
) {
|
||||
match packet {
|
||||
GamePacket::ClientboundLoginPacket(p) => {
|
||||
println!("Got login packet {:?}", p);
|
||||
|
||||
state.lock().await.player.entity.id = p.player_id;
|
||||
conn.lock().await.write(
|
||||
ServerboundCustomPayloadPacket {
|
||||
identifier: ResourceLocation::new("brand").unwrap(),
|
||||
// they don't have to know :)
|
||||
data: "vanilla".into(),
|
||||
}
|
||||
.get(),
|
||||
);
|
||||
|
||||
tx.send(Event::Login).unwrap();
|
||||
}
|
||||
|
@ -221,6 +230,7 @@ impl Client {
|
|||
GamePacket::ClientboundAddMobPacket(p) => {
|
||||
println!("Got add mob packet {:?}", p);
|
||||
}
|
||||
GamePacket::ServerboundCustomPayloadPacket(_) => todo!(),
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
|
|
@ -3,13 +3,10 @@ use quote::{quote, ToTokens};
|
|||
use syn::{
|
||||
self, braced,
|
||||
parse::{Parse, ParseStream, Result},
|
||||
parse_macro_input, DeriveInput, FieldsNamed, Ident, LitInt, Token,
|
||||
parse_macro_input, Data, DeriveInput, FieldsNamed, Ident, LitInt, Token,
|
||||
};
|
||||
|
||||
#[proc_macro_derive(McBufReadable, attributes(varint))]
|
||||
pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||
let fields = match data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields,
|
||||
_ => panic!("#[derive(*Packet)] can only be used on structs"),
|
||||
|
@ -50,7 +47,6 @@ pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream {
|
|||
|
||||
quote! {
|
||||
#[async_trait::async_trait]
|
||||
|
||||
impl crate::mc_buf::McBufReadable for #ident {
|
||||
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
|
||||
where
|
||||
|
@ -63,13 +59,9 @@ pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(McBufWritable, attributes(varint))]
|
||||
pub fn derive_mcbufwritable(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||
let fields = match data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields,
|
||||
_ => panic!("#[derive(*Packet)] can only be used on structs"),
|
||||
|
@ -115,13 +107,26 @@ pub fn derive_mcbufwritable(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(McBufReadable, attributes(varint))]
|
||||
pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
create_impl_mcbufreadable(&ident, &data).into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(McBufWritable, attributes(varint))]
|
||||
pub fn derive_mcbufwritable(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
create_impl_mcbufwritable(&ident, &data).into()
|
||||
}
|
||||
|
||||
fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
let fields = match data {
|
||||
let fields = match &data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields,
|
||||
_ => panic!("#[derive(*Packet)] can only be used on structs"),
|
||||
};
|
||||
|
@ -130,85 +135,33 @@ fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> Toke
|
|||
_ => 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(_) => {
|
||||
if f.attrs.iter().any(|attr| attr.path.is_ident("varint")) {
|
||||
quote! {
|
||||
crate::mc_buf::McBufVarintWritable::varint_write_into(&self.#field_name, buf)?;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
crate::mc_buf::McBufWritable::write_into(&self.#field_name, buf)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!(
|
||||
"Error writing field {}: {}",
|
||||
field_name.clone().unwrap(),
|
||||
field_type.to_token_stream()
|
||||
),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mcbufreadable_impl = create_impl_mcbufreadable(&ident, &data);
|
||||
let mcbufwritable_impl = create_impl_mcbufwritable(&ident, &data);
|
||||
|
||||
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(_) => {
|
||||
if f.attrs.iter().any(|a| a.path.is_ident("varint")) {
|
||||
quote! {
|
||||
let #field_name = crate::mc_buf::McBufVarintReadable::varint_read_into(buf).await?;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
let #field_name = crate::mc_buf::McBufReadable::read_into(buf).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => 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<_>>();
|
||||
|
||||
quote! {
|
||||
let contents = 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(())
|
||||
crate::mc_buf::McBufWritable::write_into(self, buf)
|
||||
}
|
||||
|
||||
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())
|
||||
use crate::mc_buf::McBufReadable;
|
||||
Ok(Self::read_into(buf).await?.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
|
||||
#mcbufreadable_impl
|
||||
|
||||
#mcbufwritable_impl
|
||||
};
|
||||
|
||||
contents.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(GamePacket, attributes(varint))]
|
||||
|
|
|
@ -32,6 +32,12 @@ impl From<Vec<u8>> for UnsizedByteArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&str> for UnsizedByteArray {
|
||||
fn from(s: &str) -> Self {
|
||||
Self(s.as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents Java's BitSet, a list of bits.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, McBufReadable, McBufWritable)]
|
||||
pub struct BitSet {
|
||||
|
|
|
@ -16,12 +16,15 @@ pub mod clientbound_set_chunk_cache_center;
|
|||
pub mod clientbound_update_recipes_packet;
|
||||
pub mod clientbound_update_tags_packet;
|
||||
pub mod clientbound_update_view_distance_packet;
|
||||
pub mod serverbound_custom_payload_packet;
|
||||
|
||||
use packet_macros::declare_state_packets;
|
||||
|
||||
declare_state_packets!(
|
||||
GamePacket,
|
||||
Serverbound => {},
|
||||
Serverbound => {
|
||||
0x0a: serverbound_custom_payload_packet::ServerboundCustomPayloadPacket,
|
||||
},
|
||||
Clientbound => {
|
||||
0x02: clientbound_add_mob_packet::ClientboundAddMobPacket,
|
||||
0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// i don't know the actual name of this packet, i couldn't find it in the source code
|
||||
|
||||
use crate::mc_buf::UnsizedByteArray;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use packet_macros::GamePacket;
|
||||
|
||||
#[derive(Clone, Debug, GamePacket)]
|
||||
pub struct ServerboundCustomPayloadPacket {
|
||||
pub identifier: ResourceLocation,
|
||||
pub data: UnsizedByteArray,
|
||||
}
|
Loading…
Add table
Reference in a new issue