aboutsummaryrefslogtreecommitdiff
path: root/azalea-protocol/azalea-protocol-macros/src
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2024-11-27 19:31:40 -0600
committerGitHub <noreply@github.com>2024-11-27 19:31:40 -0600
commit08958c2278b15ebeac8a964f392ebb792e479b61 (patch)
tree4ae3664cea38d7fd1a8f1e95ed06fac04ffe519e /azalea-protocol/azalea-protocol-macros/src
parent139d77d3c2b0922fba5e9d4fa2bd9819d78bd773 (diff)
downloadazalea-drasl-08958c2278b15ebeac8a964f392ebb792e479b61.tar.xz
Refactor azalea-protocol (#190)
* start updating to 1.21.4 * fix block codegen and stop using block data from burger * rename packet related modules and structs to be simpler * ItemSlot -> ItemStack for more consistency with mojmap * .get() -> .into_packet() * simplify declare_state_packets by removing packet ids * rename read_from and write_into to azalea_read and azalea_write * rename McBufReadable and McBufWritable to AzaleaRead and AzaleaWrite * McBuf -> AzBuf * remove most uses of into_variant * update codegen and use resourcelocation names for packets * implement #[limit(i)] attribute for AzBuf derive macro * fixes for 1.21.4 * fix examples * update some physics code and fix ChatType * remove unused imports in codegen * re-add some things to migrate.py and update +mc version numbers automatically * downgrade to 1.21.3 lol
Diffstat (limited to 'azalea-protocol/azalea-protocol-macros/src')
-rwxr-xr-xazalea-protocol/azalea-protocol-macros/src/lib.rs287
1 files changed, 169 insertions, 118 deletions
diff --git a/azalea-protocol/azalea-protocol-macros/src/lib.rs b/azalea-protocol/azalea-protocol-macros/src/lib.rs
index 756d0d82..393f8de9 100755
--- a/azalea-protocol/azalea-protocol-macros/src/lib.rs
+++ b/azalea-protocol/azalea-protocol-macros/src/lib.rs
@@ -1,9 +1,9 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{
- braced,
+ bracketed,
parse::{Parse, ParseStream, Result},
- parse_macro_input, DeriveInput, Ident, LitInt, Token,
+ parse_macro_input, DeriveInput, Ident, Token,
};
fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> TokenStream {
@@ -20,19 +20,22 @@ fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> Toke
let contents = quote! {
impl #ident {
- pub fn get(self) -> #state {
- #state::#variant_name(self)
- }
-
pub fn write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
- azalea_buf::McBufWritable::write_into(self, buf)
+ azalea_buf::AzaleaWrite::azalea_write(self, buf)
}
pub fn read(
buf: &mut std::io::Cursor<&[u8]>,
) -> Result<#state, azalea_buf::BufReadError> {
- use azalea_buf::McBufReadable;
- Ok(Self::read_from(buf)?.get())
+ use azalea_buf::AzaleaRead;
+ Ok(crate::packets::Packet::into_variant(Self::azalea_read(buf)?))
+ }
+
+ }
+
+ impl crate::packets::Packet<#state> for #ident {
+ fn into_variant(self) -> #state {
+ #state::#variant_name(self)
}
}
};
@@ -41,121 +44,99 @@ fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> Toke
}
#[proc_macro_derive(ServerboundGamePacket, attributes(var))]
-pub fn derive_serverbound_game_packet(input: TokenStream) -> TokenStream {
+pub fn derive_s_game_packet(input: TokenStream) -> TokenStream {
as_packet_derive(input, quote! {crate::packets::game::ServerboundGamePacket})
}
#[proc_macro_derive(ServerboundHandshakePacket, attributes(var))]
-pub fn derive_serverbound_handshake_packet(input: TokenStream) -> TokenStream {
+pub fn derive_s_handshake_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
- quote! {crate::packets::handshaking::ServerboundHandshakePacket},
+ quote! {crate::packets::handshake::ServerboundHandshakePacket},
)
}
#[proc_macro_derive(ServerboundLoginPacket, attributes(var))]
-pub fn derive_serverbound_login_packet(input: TokenStream) -> TokenStream {
+pub fn derive_s_login_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
quote! {crate::packets::login::ServerboundLoginPacket},
)
}
#[proc_macro_derive(ServerboundStatusPacket, attributes(var))]
-pub fn derive_serverbound_status_packet(input: TokenStream) -> TokenStream {
+pub fn derive_s_status_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
quote! {crate::packets::status::ServerboundStatusPacket},
)
}
-#[proc_macro_derive(ServerboundConfigurationPacket, attributes(var))]
-pub fn derive_serverbound_configuration_packet(input: TokenStream) -> TokenStream {
+#[proc_macro_derive(ServerboundConfigPacket, attributes(var))]
+pub fn derive_s_config_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
- quote! {crate::packets::configuration::ServerboundConfigurationPacket},
+ quote! {crate::packets::config::ServerboundConfigPacket},
)
}
#[proc_macro_derive(ClientboundGamePacket, attributes(var))]
-pub fn derive_clientbound_game_packet(input: TokenStream) -> TokenStream {
+pub fn derive_c_game_packet(input: TokenStream) -> TokenStream {
as_packet_derive(input, quote! {crate::packets::game::ClientboundGamePacket})
}
#[proc_macro_derive(ClientboundHandshakePacket, attributes(var))]
-pub fn derive_clientbound_handshake_packet(input: TokenStream) -> TokenStream {
+pub fn derive_c_handshake_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
- quote! {crate::packets::handshaking::ClientboundHandshakePacket},
+ quote! {crate::packets::handshake::ClientboundHandshakePacket},
)
}
#[proc_macro_derive(ClientboundLoginPacket, attributes(var))]
-pub fn derive_clientbound_login_packet(input: TokenStream) -> TokenStream {
+pub fn derive_c_login_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
quote! {crate::packets::login::ClientboundLoginPacket},
)
}
#[proc_macro_derive(ClientboundStatusPacket, attributes(var))]
-pub fn derive_clientbound_status_packet(input: TokenStream) -> TokenStream {
+pub fn derive_c_status_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
quote! {crate::packets::status::ClientboundStatusPacket},
)
}
-#[proc_macro_derive(ClientboundConfigurationPacket, attributes(var))]
-pub fn derive_clientbound_configuration_packet(input: TokenStream) -> TokenStream {
+#[proc_macro_derive(ClientboundConfigPacket, attributes(var))]
+pub fn derive_c_config_packet(input: TokenStream) -> TokenStream {
as_packet_derive(
input,
- quote! {crate::packets::configuration::ClientboundConfigurationPacket},
+ quote! {crate::packets::config::ClientboundConfigPacket},
)
}
#[derive(Debug)]
-struct PacketIdPair {
- id: u32,
- module: Ident,
- name: Ident,
-}
-#[derive(Debug)]
-struct PacketIdMap {
- packets: Vec<PacketIdPair>,
+struct PacketList {
+ packets: Vec<Ident>,
}
-impl Parse for PacketIdMap {
+impl Parse for PacketList {
fn parse(input: ParseStream) -> Result<Self> {
let mut packets = vec![];
// example:
- // 0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
-
- // 0x0e
- while let Ok(packet_id) = input.parse::<LitInt>() {
- 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()?;
-
- packets.push(PacketIdPair {
- id: packet_id,
- module,
- name,
- });
-
+ // change_difficulty,
+ // keep_alive,
+ while let Ok(packet_name) = input.parse::<Ident>() {
+ packets.push(packet_name);
if input.parse::<Token![,]>().is_err() {
break;
}
}
- Ok(PacketIdMap { packets })
+ Ok(PacketList { packets })
}
}
#[derive(Debug)]
struct DeclareStatePackets {
name: Ident,
- serverbound: PacketIdMap,
- clientbound: PacketIdMap,
+ clientbound: PacketList,
+ serverbound: PacketList,
}
impl Parse for DeclareStatePackets {
@@ -163,31 +144,31 @@ impl Parse for DeclareStatePackets {
let name = input.parse()?;
input.parse::<Token![,]>()?;
- let serverbound_token: Ident = input.parse()?;
- if serverbound_token != "Serverbound" {
+ let clientbound_token: Ident = input.parse()?;
+ if clientbound_token != "Clientbound" {
return Err(syn::Error::new(
- serverbound_token.span(),
- "Expected `Serverbound`",
+ clientbound_token.span(),
+ "Expected `Clientbound`",
));
}
input.parse::<Token![=>]>()?;
let content;
- braced!(content in input);
- let serverbound = content.parse()?;
+ bracketed!(content in input);
+ let clientbound = content.parse()?;
input.parse::<Token![,]>()?;
- let clientbound_token: Ident = input.parse()?;
- if clientbound_token != "Clientbound" {
+ let serverbound_token: Ident = input.parse()?;
+ if serverbound_token != "Serverbound" {
return Err(syn::Error::new(
- clientbound_token.span(),
- "Expected `Clientbound`",
+ serverbound_token.span(),
+ "Expected `Serverbound`",
));
}
input.parse::<Token![=>]>()?;
let content;
- braced!(content in input);
- let clientbound = content.parse()?;
+ bracketed!(content in input);
+ let serverbound = content.parse()?;
Ok(DeclareStatePackets {
name,
@@ -200,92 +181,111 @@ impl Parse for DeclareStatePackets {
pub fn declare_state_packets(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeclareStatePackets);
- let serverbound_state_name =
- Ident::new(&format!("Serverbound{}", input.name), input.name.span());
let clientbound_state_name =
Ident::new(&format!("Clientbound{}", input.name), input.name.span());
+ let serverbound_state_name =
+ Ident::new(&format!("Serverbound{}", input.name), input.name.span());
let state_name_litstr = syn::LitStr::new(&input.name.to_string(), input.name.span());
- let has_serverbound_packets = !input.serverbound.packets.is_empty();
let has_clientbound_packets = !input.clientbound.packets.is_empty();
+ let has_serverbound_packets = !input.serverbound.packets.is_empty();
- let mut serverbound_enum_contents = quote!();
+ let mut mod_and_use_statements_contents = quote!();
let mut clientbound_enum_contents = quote!();
- let mut serverbound_id_match_contents = quote!();
+ let mut serverbound_enum_contents = quote!();
let mut clientbound_id_match_contents = quote!();
- let mut serverbound_write_match_contents = quote!();
+ let mut serverbound_id_match_contents = quote!();
let mut clientbound_write_match_contents = quote!();
- let mut serverbound_read_match_contents = quote!();
+ let mut serverbound_write_match_contents = quote!();
let mut clientbound_read_match_contents = quote!();
+ let mut serverbound_read_match_contents = quote!();
- for PacketIdPair { id, module, name } in input.serverbound.packets {
- let variant_name = variant_name_from(&name);
+ for (id, packet_name) in input.clientbound.packets.iter().enumerate() {
+ let id = id as u32;
- let name_litstr = syn::LitStr::new(&name.to_string(), name.span());
- serverbound_enum_contents.extend(quote! {
- #variant_name(#module::#name),
+ let struct_name = packet_name_to_struct_name(packet_name, "clientbound");
+ let module_name = packet_name_to_module_name(packet_name, "clientbound");
+ let variant_name = packet_name_to_variant_name(packet_name);
+ let packet_name_litstr = syn::LitStr::new(&packet_name.to_string(), packet_name.span());
+
+ mod_and_use_statements_contents.extend(quote! {
+ pub mod #module_name;
+ pub use #module_name::#struct_name;
});
- serverbound_id_match_contents.extend(quote! {
- #serverbound_state_name::#variant_name(_packet) => #id,
+
+ clientbound_enum_contents.extend(quote! {
+ #variant_name(#module_name::#struct_name),
});
- serverbound_write_match_contents.extend(quote! {
- #serverbound_state_name::#variant_name(packet) => packet.write(buf),
+ clientbound_id_match_contents.extend(quote! {
+ #clientbound_state_name::#variant_name(_packet) => #id,
});
- serverbound_read_match_contents.extend(quote! {
+ clientbound_write_match_contents.extend(quote! {
+ #clientbound_state_name::#variant_name(packet) => packet.write(buf),
+ });
+ clientbound_read_match_contents.extend(quote! {
#id => {
- let data = #module::#name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
+ let data = #module_name::#struct_name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
source: e,
packet_id: #id,
backtrace: Box::new(std::backtrace::Backtrace::capture()),
- packet_name: #name_litstr.to_string(),
+ packet_name: #packet_name_litstr.to_string(),
})?;
#[cfg(debug_assertions)]
{
let mut leftover = Vec::new();
let _ = std::io::Read::read_to_end(buf, &mut leftover);
if !leftover.is_empty() {
- return Err(Box::new(crate::read::ReadPacketError::LeftoverData { packet_name: #name_litstr.to_string(), data: leftover }));
+ return Err(
+ Box::new(
+ crate::read::ReadPacketError::LeftoverData {
+ packet_name: #packet_name_litstr.to_string(),
+ data: leftover
+ }
+ )
+ );
}
}
data
},
});
}
- for PacketIdPair { id, module, name } in input.clientbound.packets {
- let name_litstr = syn::LitStr::new(&name.to_string(), name.span());
- let variant_name = variant_name_from(&name);
+ for (id, packet_name) in input.serverbound.packets.iter().enumerate() {
+ let id = id as u32;
- clientbound_enum_contents.extend(quote! {
- #variant_name(#module::#name),
+ let struct_name = packet_name_to_struct_name(packet_name, "serverbound");
+ let module_name = packet_name_to_module_name(packet_name, "serverbound");
+ let variant_name = packet_name_to_variant_name(packet_name);
+ let packet_name_litstr = syn::LitStr::new(&packet_name.to_string(), packet_name.span());
+
+ mod_and_use_statements_contents.extend(quote! {
+ pub mod #module_name;
+ pub use #module_name::#struct_name;
});
- clientbound_id_match_contents.extend(quote! {
- #clientbound_state_name::#variant_name(_packet) => #id,
+
+ serverbound_enum_contents.extend(quote! {
+ #variant_name(#module_name::#struct_name),
});
- clientbound_write_match_contents.extend(quote! {
- #clientbound_state_name::#variant_name(packet) => packet.write(buf),
+ serverbound_id_match_contents.extend(quote! {
+ #serverbound_state_name::#variant_name(_packet) => #id,
});
- clientbound_read_match_contents.extend(quote! {
+ serverbound_write_match_contents.extend(quote! {
+ #serverbound_state_name::#variant_name(packet) => packet.write(buf),
+ });
+ serverbound_read_match_contents.extend(quote! {
#id => {
- let data = #module::#name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
+ let data = #module_name::#struct_name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
source: e,
packet_id: #id,
backtrace: Box::new(std::backtrace::Backtrace::capture()),
- packet_name: #name_litstr.to_string(),
+ packet_name: #packet_name_litstr.to_string(),
})?;
#[cfg(debug_assertions)]
{
let mut leftover = Vec::new();
let _ = std::io::Read::read_to_end(buf, &mut leftover);
if !leftover.is_empty() {
- return Err(
- Box::new(
- crate::read::ReadPacketError::LeftoverData {
- packet_name: #name_litstr.to_string(),
- data: leftover
- }
- )
- );
+ return Err(Box::new(crate::read::ReadPacketError::LeftoverData { packet_name: #packet_name_litstr.to_string(), data: leftover }));
}
}
data
@@ -311,19 +311,21 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
}
let mut contents = quote! {
+ #mod_and_use_statements_contents
+
#[derive(Clone, Debug)]
- pub enum #serverbound_state_name
+ pub enum #clientbound_state_name
where
- Self: Sized,
+ Self: Sized,
{
- #serverbound_enum_contents
+ #clientbound_enum_contents
}
#[derive(Clone, Debug)]
- pub enum #clientbound_state_name
+ pub enum #serverbound_state_name
where
- Self: Sized,
+ Self: Sized,
{
- #clientbound_enum_contents
+ #serverbound_enum_contents
}
};
@@ -356,6 +358,13 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
})
}
}
+
+ impl crate::packets::Packet<#serverbound_state_name> for #serverbound_state_name {
+ /// No-op, exists so you can pass a packet enum when a Packet<> is expected.
+ fn into_variant(self) -> #serverbound_state_name {
+ self
+ }
+ }
});
contents.extend(quote! {
@@ -400,8 +409,50 @@ fn variant_name_from(name: &syn::Ident) -> syn::Ident {
} else if variant_name.starts_with("Serverbound") {
variant_name = variant_name["Serverbound".len()..].to_string();
}
- if variant_name.ends_with("Packet") {
- variant_name = variant_name[..variant_name.len() - "Packet".len()].to_string();
- }
syn::Ident::new(&variant_name, name.span())
}
+
+fn packet_name_to_struct_name(name: &syn::Ident, direction: &str) -> syn::Ident {
+ let struct_name_snake = format!("{direction}_{name}");
+ let struct_name = to_camel_case(&struct_name_snake);
+ syn::Ident::new(&struct_name, name.span())
+}
+fn packet_name_to_module_name(name: &syn::Ident, direction: &str) -> syn::Ident {
+ let module_name_snake = format!("{}_{name}", direction.chars().next().unwrap());
+ let module_name = to_snake_case(&module_name_snake);
+ syn::Ident::new(&module_name, name.span())
+}
+fn packet_name_to_variant_name(name: &syn::Ident) -> syn::Ident {
+ let variant_name = to_camel_case(&name.to_string());
+ syn::Ident::new(&variant_name, name.span())
+}
+
+fn to_camel_case(snake_case: &str) -> String {
+ let mut camel_case = String::new();
+ let mut capitalize_next = true;
+ for c in snake_case.chars() {
+ if c == '_' {
+ capitalize_next = true;
+ } else {
+ if capitalize_next {
+ camel_case.push(c.to_ascii_uppercase());
+ } else {
+ camel_case.push(c);
+ }
+ capitalize_next = false;
+ }
+ }
+ camel_case
+}
+fn to_snake_case(camel_case: &str) -> String {
+ let mut snake_case = String::new();
+ for c in camel_case.chars() {
+ if c.is_ascii_uppercase() {
+ snake_case.push('_');
+ snake_case.push(c.to_ascii_lowercase());
+ } else {
+ snake_case.push(c);
+ }
+ }
+ snake_case
+}