Started Macros

This commit is contained in:
Kyler 2023-12-24 19:45:54 -07:00
parent 600de7f025
commit f3f5de64ac
8 changed files with 263 additions and 95 deletions

26
Cargo.lock generated
View File

@ -25,7 +25,7 @@ checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.42",
]
[[package]]
@ -198,11 +198,20 @@ name = "purple_cello_mc_protocol"
version = "0.1.0"
dependencies = [
"async-trait",
"purple_cello_mc_protocol_derive",
"serde",
"serde_json",
"tokio",
]
[[package]]
name = "purple_cello_mc_protocol_derive"
version = "0.1.0"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "quote"
version = "1.0.33"
@ -256,7 +265,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.42",
]
[[package]]
@ -295,6 +304,17 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.42"
@ -333,7 +353,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.42",
]
[[package]]

View File

@ -10,3 +10,4 @@ tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
async-trait = "0.1.75"
purple_cello_mc_protocol_derive = { path = "./purple_cello_mc_protocol_derive" }

View File

@ -0,0 +1,157 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DataStruct, DeriveInput};
#[proc_macro_derive(Packet)]
pub fn packet_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let struct_name = &input.ident;
if let Data::Struct(DataStruct { fields, .. }) = &input.data {
let field_names: Vec<_> = fields
.iter()
.map(|field| field.ident.as_ref().unwrap())
.collect();
let field_types: Vec<_> = fields
.iter()
.map(|field| &field.ty)
.collect();
// let get_code = quote! {
// Ok(Self {
// #( #field_names: #{
// let data_fn = #{
// let field_ty_str = stringify!(#field_types).replace(" ", "");
// TYPE_FUNCTION_GET_MAPPING
// .iter()
// .find(|(ty, _)| field_ty_str.contains(*ty))
// .map(|(_, fn_name)| fn_name)
// .unwrap_or_else(|| panic!("Unknown type: {}", field_ty_str))
// };
// let fn_ident = syn::Ident::new(data_fn, proc_macro2::Span::call_site());
// quote! { #fn_ident(data)? }
// }, )*
// })
// };
// let convert_code = quote! {
// let mut data: Vec<u8> = vec![];
// data.append(&mut mc_types::convert_var_int(Self::packet_id()));
// #( data.append(&mut #{
// let data_fn = #{
// let field_ty_str = stringify!(#field_types).replace(" ", "");
// TYPE_FUNCTION_CONVERT_MAPPING
// .iter()
// .find(|(ty, _)| field_ty_str.contains(*ty))
// .map(|(_, fn_name)| fn_name)
// .unwrap_or_else(|| panic!("Unknown type: {}", field_ty_str))
// };
// let fn_ident = syn::Ident::new(data_fn, proc_macro2::Span::call_site());
// quote! { #fn_ident(self.#field_names) }
// }); )*
// };
let type_function_get_mapping: Vec<(&str, &str)> = vec![
("Boolean", "mc_types::get_boolean"),
("Byte", "mc_types::get_byte"),
("UnsignedByte", "mc_types::get_unsigned_byte"),
("Short", "mc_types::get_short"),
("UnsignedShort", "mc_types::get_unsigned_short"),
("Int", "mc_types::get_int"),
("Long", "mc_types::get_long"),
("Float", "mc_types::get_float"),
("Double", "mc_types::get_double"),
("String", "mc_types::get_string"),
("Json", "mc_types::get_string"),
("Identifier", "mc_types::get_string"),
("VarInt", "mc_types::get_var_int"),
("VarLong", "mc_types::get_var_long"),
("Position", "mc_types::get_position"),
("Angle", "mc_types::get_unsigned_short"),
("Uuid", "mc_types::get_uuid"),
("ByteArray", "mc_types::get_byte_array"),
];
let type_function_convert_mapping: Vec<(&str, &str)> = vec![
("Boolean", "mc_types::convert_boolean"),
("Byte", "mc_types::convert_byte"),
("UnsignedByte", "mc_types::convert_unsigned_byte"),
("Short", "mc_types::convert_short"),
("UnsignedShort", "mc_types::convert_unsigned_short"),
("Int", "mc_types::convert_int"),
("Long", "mc_types::convert_long"),
("Float", "mc_types::convert_float"),
("Double", "mc_types::convert_double"),
("String", "mc_types::convert_string"),
("Json", "mc_types::convert_string"),
("Identifier", "mc_types::convert_string"),
("VarInt", "mc_types::convert_var_int"),
("VarLong", "mc_types::convert_var_long"),
("Position", "mc_types::convert_position"),
("Angle", "mc_types::convert_unsigned_short"),
("Uuid", "mc_types::convert_uuid"),
("ByteArray", "mc_types::convert_byte_array"),
];
let get_code = {
let field_code: Vec<_> = field_names.iter().zip(field_types.iter()).map(|(name, ty)| {
let data_fn = {
let field_ty_str = stringify!(#ty).replace(" ", "");
type_function_get_mapping
.iter()
.find(|(ty, _)| field_ty_str.contains(*ty))
.map(|(_, fn_name)| fn_name)
.unwrap_or_else(|| panic!("Unknown type: {}", field_ty_str))
};
quote! { #name: #data_fn(data)?, }
}).collect::<Vec<_>>();
quote! {
Ok(Self {
#( #field_code )*
})
}
};
let convert_code = {
let field_code: Vec<_> = field_names.iter().zip(field_types.iter()).map(|(name, ty)| {
let data_fn = {
let field_ty_str = stringify!(#ty).replace(" ", "");
type_function_convert_mapping
.iter()
.find(|(ty, _)| field_ty_str.contains(*ty))
.map(|(_, fn_name)| fn_name)
.unwrap_or_else(|| panic!("Unknown type: {}", field_ty_str))
};
quote! { mc_types::#data_fn(self.#name), }
}).collect::<Vec<_>>();
quote! {
let mut data: Vec<u8> = vec![];
data.append(&mut mc_types::convert_var_int(Self::packet_id()));
#( data.append(&mut #field_code );)*
data
}
};
let gen = quote! {
impl Packet for #struct_name {
fn packet_id() -> i32 { 0 }
fn get(data: &mut Vec<u8>) -> Result<Self> {
#get_code
}
fn convert(&self) -> Vec<u8> {
#convert_code
}
}
};
return gen.into();
}
TokenStream::from(quote! {
compile_error!("Packet derive macro only supports named structs");
})
}

View File

@ -4,7 +4,8 @@ pub mod serverbound {
use tokio::net::tcp::OwnedReadHalf;
use crate::mc_types::{self, Result, Packet, PacketError};
use crate::mc_types::{self, Result, Packet, PacketError, MCTypes};
use purple_cello_mc_protocol_derive::packet_derive;
pub enum HandshakeEnum {
Handshake(Handshake),
@ -22,36 +23,38 @@ pub mod serverbound {
}
}
#[derive(packet_derive)]
pub struct Handshake {
pub protocol_version: i32,
pub server_address: String,
pub server_port: u16,
pub next_state: i32,
pub protocol_version: MCTypes::VarInt,
pub server_address: MCTypes::String,
pub server_port: MCTypes::UnsignedShort,
pub next_state: MCTypes::VarInt,
}
impl Packet for Handshake {
// impl Packet for Handshake {
fn packet_id() -> i32 {0}
// fn packet_id() -> i32 {0}
fn get(data: &mut Vec<u8>) -> Result<Self> {
Ok(Self {
protocol_version: mc_types::get_var_int(data)?,
server_address: mc_types::get_string(data)?,
server_port: mc_types::get_u16(data),
next_state: mc_types::get_var_int(data)?,
})
}
// fn get(data: &mut Vec<u8>) -> Result<Self> {
// Ok(Self {
// protocol_version: mc_types::get_var_int(data)?,
// server_address: mc_types::get_string(data)?,
// server_port: mc_types::get_unsigned_short(data)?,
// next_state: mc_types::get_var_int(data)?,
// })
// }
fn convert(&self) -> Vec<u8> {
let mut data: Vec<u8> = vec![];
data.append(&mut mc_types::convert_var_int(Self::packet_id()));
data.append(&mut mc_types::convert_var_int(self.protocol_version));
data.append(&mut mc_types::convert_string(&self.server_address));
data.append(&mut mc_types::convert_u16(self.server_port));
data.append(&mut mc_types::convert_var_int(self.next_state));
// fn convert(&self) -> Vec<u8> {
// let mut data: Vec<u8> = vec![];
// data.append(&mut mc_types::convert_var_int(Self::packet_id()));
// data.append(&mut mc_types::convert_var_int(self.protocol_version));
// data.append(&mut mc_types::convert_string(&self.server_address));
// data.append(
// &mut mc_types::convert_unsigned_short(self.server_port));
// data.append(&mut mc_types::convert_var_int(self.next_state));
data
}
// data
// }
}
// }
}

View File

@ -1,6 +1,6 @@
// Yeahbut December 2023
pub mod mc_types;
// pub mod handshake;
// pub mod status;
// pub mod login;
pub mod handshake;
pub mod status;
pub mod login;

View File

@ -4,7 +4,7 @@ pub mod clientbound {
use tokio::net::tcp::OwnedReadHalf;
use crate::mc_types::{self, Result, Packet, PacketArray, PacketError};
use crate::mc_types::{self, Result, Packet, MCTypeArray, PacketError};
pub enum Login {
Disconnect(Disconnect),
@ -97,7 +97,7 @@ pub mod clientbound {
fn get(mut data: &mut Vec<u8>) -> Result<Self> {
Ok(Self {
uuid: mc_types::get_uuid(&mut data),
uuid: mc_types::get_uuid(&mut data)?,
username: mc_types::get_string(&mut data)?,
properties: LoginSuccessProperty::get_array(&mut data)?,
})
@ -132,12 +132,12 @@ pub mod clientbound {
}
}
impl PacketArray for LoginSuccessProperty {
impl MCTypeArray for LoginSuccessProperty {
fn get(mut data: &mut Vec<u8>) -> Result<Self> {
let name = mc_types::get_string(&mut data)?;
let value = mc_types::get_string(&mut data)?;
let is_signed = mc_types::get_bool(&mut data);
let is_signed = mc_types::get_boolean(&mut data)?;
let mut signature: Option<String> = None;
if is_signed {
signature = Some(mc_types::get_string(&mut data)?);
@ -155,10 +155,10 @@ pub mod clientbound {
data.append(&mut mc_types::convert_string(&self.value));
match &self.signature {
Some(value) => {
data.append(&mut &mut mc_types::convert_bool(true));
data.append(&mut &mut mc_types::convert_boolean(true));
data.append(&mut mc_types::convert_string(&value));
},
None => data.append(&mut &mut mc_types::convert_bool(false))
None => data.append(&mut &mut mc_types::convert_boolean(false))
}
data

View File

@ -109,6 +109,25 @@ async fn read_var_int_stream(stream: &mut OwnedReadHalf) -> Result<i32> {
// enum MCTypes
// pub enum MCTypes {
// Boolean,
// Byte,
// UnsignedByte,
// Short,
// UnsignedShort,
// Int,
// Long,
// Float,
// Double,
// String,
// VarInt,
// VarLong,
// Uuid,
// Optional,
// Array,
// ByteArray,
// }
pub enum MCTypes {
Boolean,
Byte,
@ -131,8 +150,8 @@ pub enum MCTypes {
Position,
Angle,
Uuid,
Optional,
Array,
// Optional,
// Array,
// Enum,
ByteArray,
}
@ -278,24 +297,6 @@ pub fn convert_string(s: &str) -> Vec<u8> {
// convert_nbt_tag(value)
// }
// fn get_json_chat <- string
pub fn get_json_chat(data: &mut Vec<u8>) -> Result<String> {
get_string(data)
}
// fn convert_json_chat <- string
pub fn convert_json_chat(value: String) -> Vec<u8> {
convert_string(value)
}
// fn get_identifier <- string
pub fn get_identifier(data: &mut Vec<u8>) -> Result<String> {
get_string(data)
}
// fn convert_identifier <- string
pub fn convert_identifier(value: String) -> Vec<u8> {
convert_string(value)
}
// fn get_var_int
pub fn get_var_int(data: &mut Vec<u8>) -> Result<i32> {
Ok(get_var(data, 32)? as i32)
@ -374,48 +375,34 @@ pub struct MCPosition {
z: i32,
y: i16,
}
impl MCPosition {
// fn get_position
pub fn get(data: &mut Vec<u8>) -> Result<Self> {
let pos = get_long(data)?;
Ok(MCPosition {
x: (pos >> 38) as i32,
z: (pos << 26 >> 38) as i32,
y: (pos << 52 >> 52) as i16,
})
}
// fn convert_position
pub fn convert(&self) -> Vec<u8> {
let pos: u64 =
((self.x as u64 & 0x3FFFFFF) << 38) |
((self.z as u64 & 0x3FFFFFF) << 12) |
(self.y as u64 & 0xFFF);
convert_long(pos as i64)
}
// fn get_position
pub fn get_position(data: &mut Vec<u8>) -> Result<MCPosition> {
let pos = get_long(data)?;
Ok(MCPosition {
x: (pos >> 38) as i32,
z: (pos << 26 >> 38) as i32,
y: (pos << 52 >> 52) as i16,
})
}
// fn get_angle <- u8
pub fn get_angle(data: &mut Vec<u8>) -> Result<u8> {
get_unsigned_byte(data)
}
// fn convert_angle <- u8
pub fn convert_angle(value: u8) -> Vec<u8> {
convert_unsigned_byte(value)
// fn convert_position
pub fn convert_position(value: MCPosition) -> Vec<u8> {
let pos: u64 =
((value.x as u64 & 0x3FFFFFF) << 38) |
((value.z as u64 & 0x3FFFFFF) << 12) |
(value.y as u64 & 0xFFF);
convert_long(pos as i64)
}
// fn get_uuid
pub fn get_uuid(data: &mut Vec<u8>) -> Result<i128> {
if data.len() < std::mem::size_of::<i128>() {
pub fn get_uuid(data: &mut Vec<u8>) -> Result<u128> {
if data.len() < std::mem::size_of::<u128>() {
return Err(Box::new(PacketError::RanOutOfBytes))
}
Ok(i128::from_be_bytes(
data.drain(0..std::mem::size_of::<i128>()).as_slice().try_into()?))
Ok(u128::from_be_bytes(
data.drain(0..std::mem::size_of::<u128>()).as_slice().try_into()?))
}
// fn convert_uuid
pub fn convert_uuid(value: i128) -> Vec<u8> {
pub fn convert_uuid(value: u128) -> Vec<u8> {
value.to_be_bytes().to_vec()
}

View File

@ -107,14 +107,14 @@ pub mod clientbound {
fn get(mut data: &mut Vec<u8>) -> Result<Self> {
Ok(Self {
payload: mc_types::get_i64(&mut data)
payload: mc_types::get_long(&mut data)?
})
}
fn convert(&self) -> Vec<u8> {
let mut data: Vec<u8> = vec![];
data.append(&mut mc_types::convert_var_int(Self::packet_id()));
data.append(&mut mc_types::convert_i64(self.payload));
data.append(&mut mc_types::convert_long(self.payload));
data
}
@ -177,14 +177,14 @@ pub mod serverbound {
fn get(mut data: &mut Vec<u8>) -> Result<Self> {
Ok(Self {
payload: mc_types::get_i64(&mut data)
payload: mc_types::get_long(&mut data)?
})
}
fn convert(&self) -> Vec<u8> {
let mut data: Vec<u8> = vec![];
data.append(&mut mc_types::convert_var_int(Self::packet_id()));
data.append(&mut mc_types::convert_i64(self.payload));
data.append(&mut mc_types::convert_long(self.payload));
data
}