1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 23:44:38 +00:00

start adding declare_state_packets

This commit is contained in:
mat 2022-04-19 00:48:13 -05:00
commit f60426cd5a
2 changed files with 201 additions and 73 deletions

View file

@ -1,10 +1,14 @@
use quote::{quote, ToTokens}; use std::collections::{BTreeMap, HashMap};
use syn::{self, parse_macro_input, DeriveInput, FieldsNamed};
fn as_packet_derive( use proc_macro::TokenStream;
input: proc_macro::TokenStream, use quote::{quote, ToTokens};
state: proc_macro2::TokenStream, use syn::{
) -> proc_macro::TokenStream { self, braced,
parse::{Parse, ParseStream, Result},
parse_macro_input, DeriveInput, Expr, FieldsNamed, Ident, LitInt, Token, Type, Visibility,
};
fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input); let DeriveInput { ident, data, .. } = parse_macro_input!(input);
let fields = match data { let fields = match data {
@ -99,21 +103,132 @@ fn as_packet_derive(
} }
#[proc_macro_derive(GamePacket, attributes(varint))] #[proc_macro_derive(GamePacket, attributes(varint))]
pub fn derive_game_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn derive_game_packet(input: TokenStream) -> TokenStream {
as_packet_derive(input, quote! {crate::packets::game::GamePacket}) as_packet_derive(input, quote! {crate::packets::game::GamePacket})
} }
#[proc_macro_derive(HandshakePacket, attributes(varint))] #[proc_macro_derive(HandshakePacket, attributes(varint))]
pub fn derive_handshake_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn derive_handshake_packet(input: TokenStream) -> TokenStream {
as_packet_derive(input, quote! {crate::packets::handshake::HandshakePacket}) as_packet_derive(input, quote! {crate::packets::handshake::HandshakePacket})
} }
#[proc_macro_derive(LoginPacket, attributes(varint))] #[proc_macro_derive(LoginPacket, attributes(varint))]
pub fn derive_login_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn derive_login_packet(input: TokenStream) -> TokenStream {
as_packet_derive(input, quote! {crate::packets::login::LoginPacket}) as_packet_derive(input, quote! {crate::packets::login::LoginPacket})
} }
#[proc_macro_derive(StatusPacket, attributes(varint))] #[proc_macro_derive(StatusPacket, attributes(varint))]
pub fn derive_status_packet(input: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn derive_status_packet(input: TokenStream) -> TokenStream {
as_packet_derive(input, quote! {crate::packets::status::StatusPacket}) as_packet_derive(input, quote! {crate::packets::status::StatusPacket})
} }
#[derive(Debug)]
struct PacketIdPair {
id: u32,
module: Ident,
name: Ident,
}
#[derive(Debug)]
struct PacketIdMap {
packets: Vec<PacketIdPair>,
}
impl Parse for PacketIdMap {
fn parse(input: ParseStream) -> Result<Self> {
let mut packets = vec![];
loop {
// 0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
// 0x0e
let packet_id: LitInt = match input.parse() {
Ok(i) => i,
Err(_) => break,
};
let packet_id = packet_id.base10_parse::<u32>()?;
// :
input.parse::<Token![:]>()?;
// clientbound_change_difficulty_packet
let module: Ident = input.parse()?;
// ::
input.parse::<Token![::]>()?;
// ClientboundChangeDifficultyPacket
let name: Ident = input.parse()?;
input.parse::<Token![,]>()?;
packets.push(PacketIdPair {
id: packet_id,
module,
name,
});
}
Ok(PacketIdMap { packets })
}
}
#[derive(Debug)]
struct DeclareStatePackets {
name: Ident,
serverbound: PacketIdMap,
clientbound: PacketIdMap,
}
impl Parse for DeclareStatePackets {
fn parse(input: ParseStream) -> Result<Self> {
let name = input.parse()?;
input.parse::<Token![,]>()?;
let serverbound_token: Ident = input.parse()?;
if serverbound_token != "Serverbound" {
return Err(syn::Error::new(
serverbound_token.span(),
"Expected `Serverbound`",
));
}
input.parse::<Token![=>]>()?;
let content;
braced!(content in input);
let serverbound = content.parse()?;
input.parse::<Token![,]>()?;
let clientbound_token: Ident = input.parse()?;
if clientbound_token != "Clientbound" {
return Err(syn::Error::new(
clientbound_token.span(),
"Expected `Clientbound`",
));
}
input.parse::<Token![=>]>()?;
let content;
braced!(content in input);
let clientbound = content.parse()?;
Ok(DeclareStatePackets {
name,
serverbound,
clientbound,
})
}
}
#[proc_macro]
pub fn declare_state_packets(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeclareStatePackets);
let name = input.name;
let mut enum_contents = quote!();
for PacketIdPair { id, module, name } in input.serverbound.packets {
enum_contents.extend(quote! {#name(#module::#name)});
}
quote! {
#[derive(Clone, Debug)]
pub enum #name
where
Self: Sized,
{
#enum_contents
}
}
.into()
}

View file

@ -6,70 +6,83 @@ pub mod clientbound_update_view_distance_packet;
use super::ProtocolPacket; use super::ProtocolPacket;
use crate::connect::PacketFlow; use crate::connect::PacketFlow;
use async_trait::async_trait; use async_trait::async_trait;
use packet_macros::declare_state_packets;
#[derive(Clone, Debug)] declare_state_packets!(
pub enum GamePacket GamePacket,
where // no serverbound packets implemented yet
Self: Sized, Serverbound => {},
{ Clientbound => {
ClientboundLoginPacket(clientbound_login_packet::ClientboundLoginPacket), 0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
ClientboundUpdateViewDistancePacket( 0x18: clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket, 0x26: clientbound_login_packet::ClientboundLoginPacket,
), 0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket,
ClientboundCustomPayloadPacket(
clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
),
ClientboundChangeDifficultyPacket(
clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
),
}
#[async_trait]
impl ProtocolPacket for GamePacket {
fn id(&self) -> u32 {
match self {
GamePacket::ClientboundChangeDifficultyPacket(_packet) => 0x0e,
GamePacket::ClientboundCustomPayloadPacket(_packet) => 0x18,
GamePacket::ClientboundLoginPacket(_packet) => 0x26,
GamePacket::ClientboundUpdateViewDistancePacket(_packet) => 0x4a,
}
} }
);
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> { // #[derive(Clone, Debug)]
match self { // pub enum GamePacket
GamePacket::ClientboundChangeDifficultyPacket(packet) => packet.write(buf), // where
GamePacket::ClientboundCustomPayloadPacket(packet) => packet.write(buf), // Self: Sized,
GamePacket::ClientboundLoginPacket(packet) => packet.write(buf), // {
GamePacket::ClientboundUpdateViewDistancePacket(packet) => packet.write(buf), // ClientboundLoginPacket(clientbound_login_packet::ClientboundLoginPacket),
} // ClientboundUpdateViewDistancePacket(
} // clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket,
// ),
// ClientboundCustomPayloadPacket(
// clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
// ),
// ClientboundChangeDifficultyPacket(
// clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
// ),
// }
/// Read a packet by its id, ConnectionProtocol, and flow // #[async_trait]
async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>( // impl ProtocolPacket for GamePacket {
id: u32, // fn id(&self) -> u32 {
flow: &PacketFlow, // match self {
buf: &mut T, // GamePacket::ClientboundChangeDifficultyPacket(_packet) => 0x0e,
) -> Result<GamePacket, String> // GamePacket::ClientboundCustomPayloadPacket(_packet) => 0x18,
where // GamePacket::ClientboundLoginPacket(_packet) => 0x26,
Self: Sized, // GamePacket::ClientboundUpdateViewDistancePacket(_packet) => 0x4a,
{ // }
Ok(match flow { // }
PacketFlow::ServerToClient => match id {
0x0e => clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket // fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
::read(buf) // match self {
.await?, // GamePacket::ClientboundChangeDifficultyPacket(packet) => packet.write(buf),
0x18 => clientbound_custom_payload_packet::ClientboundCustomPayloadPacket::read(buf).await?, // GamePacket::ClientboundCustomPayloadPacket(packet) => packet.write(buf),
0x26 => clientbound_login_packet::ClientboundLoginPacket::read(buf).await?, // GamePacket::ClientboundLoginPacket(packet) => packet.write(buf),
0x4a => clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket // GamePacket::ClientboundUpdateViewDistancePacket(packet) => packet.write(buf),
::read(buf) // }
.await?, // }
// _ => return Err(format!("Unknown ServerToClient game packet id: {}", id)),
_ => panic!("Unknown ServerToClient game packet id: {}", id), // /// Read a packet by its id, ConnectionProtocol, and flow
}, // async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
PacketFlow::ClientToServer => match id { // id: u32,
// 0x00 => serverbound_hello_packet::ServerboundHelloPacket::read(buf).await?, // flow: &PacketFlow,
_ => return Err(format!("Unknown ClientToServer game packet id: {}", id)), // buf: &mut T,
}, // ) -> Result<GamePacket, String>
}) // where
} // Self: Sized,
} // {
// Ok(match flow {
// PacketFlow::ServerToClient => match id {
// 0x0e => clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket
// ::read(buf)
// .await?,
// 0x18 => clientbound_custom_payload_packet::ClientboundCustomPayloadPacket::read(buf).await?,
// 0x26 => clientbound_login_packet::ClientboundLoginPacket::read(buf).await?,
// 0x4a => clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket
// ::read(buf)
// .await?,
// // _ => 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?,
// _ => return Err(format!("Unknown ClientToServer game packet id: {}", id)),
// },
// })
// }
// }