diff options
Diffstat (limited to 'azalea-protocol')
| -rw-r--r-- | azalea-protocol/packet-macros/src/lib.rs | 133 | ||||
| -rw-r--r-- | azalea-protocol/src/packets/game/mod.rs | 139 |
2 files changed, 200 insertions, 72 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() +} diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index 4efe72fb..cb07cf97 100644 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -6,70 +6,83 @@ pub mod clientbound_update_view_distance_packet; use super::ProtocolPacket; use crate::connect::PacketFlow; use async_trait::async_trait; +use packet_macros::declare_state_packets; -#[derive(Clone, Debug)] -pub enum GamePacket -where - Self: Sized, -{ - ClientboundLoginPacket(clientbound_login_packet::ClientboundLoginPacket), - ClientboundUpdateViewDistancePacket( - 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, - } +declare_state_packets!( + GamePacket, + // no serverbound packets implemented yet + Serverbound => {}, + Clientbound => { + 0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket, + 0x18: clientbound_custom_payload_packet::ClientboundCustomPayloadPacket, + 0x26: clientbound_login_packet::ClientboundLoginPacket, + 0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket, } +); - fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> { - match self { - GamePacket::ClientboundChangeDifficultyPacket(packet) => packet.write(buf), - GamePacket::ClientboundCustomPayloadPacket(packet) => packet.write(buf), - GamePacket::ClientboundLoginPacket(packet) => packet.write(buf), - GamePacket::ClientboundUpdateViewDistancePacket(packet) => packet.write(buf), - } - } +// #[derive(Clone, Debug)] +// pub enum GamePacket +// where +// Self: Sized, +// { +// 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 fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>( - id: u32, - flow: &PacketFlow, - 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)), - }, - }) - } -} +// #[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> { +// match self { +// GamePacket::ClientboundChangeDifficultyPacket(packet) => packet.write(buf), +// GamePacket::ClientboundCustomPayloadPacket(packet) => packet.write(buf), +// GamePacket::ClientboundLoginPacket(packet) => packet.write(buf), +// GamePacket::ClientboundUpdateViewDistancePacket(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>( +// id: u32, +// flow: &PacketFlow, +// 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)), +// }, +// }) +// } +// } |
