diff options
| author | mat <github@matdoes.dev> | 2022-04-19 00:48:13 -0500 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-04-19 00:48:13 -0500 |
| commit | f60426cd5a8a276adcb88988cef38d27f48de912 (patch) | |
| tree | a7bb1e5b55e8ebc458477d0df759f9b11b3deb75 /azalea-protocol/packet-macros/src | |
| parent | 747bfa568cb1da8afdeb29005bdd2836963ed613 (diff) | |
| download | azalea-drasl-f60426cd5a8a276adcb88988cef38d27f48de912.tar.xz | |
start adding declare_state_packets
Diffstat (limited to 'azalea-protocol/packet-macros/src')
| -rw-r--r-- | azalea-protocol/packet-macros/src/lib.rs | 133 |
1 files changed, 124 insertions, 9 deletions
diff --git a/azalea-protocol/packet-macros/src/lib.rs b/azalea-protocol/packet-macros/src/lib.rs index 957515c4..0e6ad0e1 100644 --- a/azalea-protocol/packet-macros/src/lib.rs +++ b/azalea-protocol/packet-macros/src/lib.rs @@ -1,10 +1,14 @@ +use std::collections::{BTreeMap, HashMap}; + +use proc_macro::TokenStream; use quote::{quote, ToTokens}; -use syn::{self, parse_macro_input, DeriveInput, FieldsNamed}; +use syn::{ + self, braced, + parse::{Parse, ParseStream, Result}, + parse_macro_input, DeriveInput, Expr, FieldsNamed, Ident, LitInt, Token, Type, Visibility, +}; -fn as_packet_derive( - input: proc_macro::TokenStream, - state: proc_macro2::TokenStream, -) -> proc_macro::TokenStream { +fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> TokenStream { let DeriveInput { ident, data, .. } = parse_macro_input!(input); let fields = match data { @@ -99,21 +103,132 @@ fn as_packet_derive( } #[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}) } #[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}) } #[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}) } #[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}) } + +#[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() +} |
