aboutsummaryrefslogtreecommitdiff
path: root/azalea-protocol
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-protocol')
-rw-r--r--azalea-protocol/packet-macros/src/lib.rs133
-rw-r--r--azalea-protocol/src/packets/game/mod.rs139
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)),
+// },
+// })
+// }
+// }