Refactor protocol derive module (#11)
This commit is contained in:
parent
f733fabedc
commit
70bfd01848
45
protocol-derive/src/error.rs
Normal file
45
protocol-derive/src/error.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use syn::Error as SynError;
|
||||||
|
|
||||||
|
/// Possible errors while deriving.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) enum DeriveInputParserError {
|
||||||
|
/// Derive attribute must be placed on a structure or enum.
|
||||||
|
UnsupportedData,
|
||||||
|
/// Data fields must be named.
|
||||||
|
UnnamedDataFields,
|
||||||
|
FieldError {
|
||||||
|
field_error: FieldError,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Possible errors while parsing field.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) enum FieldError {
|
||||||
|
/// Failed to parse field meta due incorrect syntax.
|
||||||
|
BadAttributeSyntax { syn_error: SynError },
|
||||||
|
/// Unsupported field attribute type.
|
||||||
|
UnsupportedAttribute,
|
||||||
|
/// Field meta has wrong value type.
|
||||||
|
/// For example an int was expected, but a string was supplied.
|
||||||
|
AttributeWrongValueType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FieldError> for DeriveInputParserError {
|
||||||
|
fn from(field_error: FieldError) -> Self {
|
||||||
|
DeriveInputParserError::FieldError { field_error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SynError> for DeriveInputParserError {
|
||||||
|
fn from(syn_error: SynError) -> Self {
|
||||||
|
DeriveInputParserError::FieldError {
|
||||||
|
field_error: FieldError::BadAttributeSyntax { syn_error },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SynError> for FieldError {
|
||||||
|
fn from(syn_error: SynError) -> Self {
|
||||||
|
FieldError::BadAttributeSyntax { syn_error }
|
||||||
|
}
|
||||||
|
}
|
@ -1,185 +1,28 @@
|
|||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro::TokenStream as TokenStream1;
|
use crate::parse::parse_derive_input;
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use crate::render::decoder::render_decoder;
|
||||||
use proc_macro2::{Ident, Span};
|
use crate::render::encoder::render_encoder;
|
||||||
use quote::{quote, TokenStreamExt};
|
use proc_macro::TokenStream;
|
||||||
use std::iter::FromIterator;
|
use syn::parse_macro_input;
|
||||||
use syn::{parse_macro_input, Data, DeriveInput, Field, Fields, Lit, Meta, NestedMeta};
|
use syn::DeriveInput;
|
||||||
|
|
||||||
#[proc_macro_derive(Packet, attributes(packet))]
|
mod error;
|
||||||
pub fn derive_packet(input: proc_macro::TokenStream) -> TokenStream1 {
|
mod parse;
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
mod render;
|
||||||
let name = &input.ident;
|
|
||||||
|
|
||||||
match input.data {
|
#[proc_macro_derive(Encoder, attributes(data_type))]
|
||||||
Data::Struct(data) => {
|
pub fn derive_encoder(tokens: TokenStream) -> TokenStream {
|
||||||
let fields = &data.fields;
|
let input = parse_macro_input!(tokens as DeriveInput);
|
||||||
|
let (name, fields) = parse_derive_input(&input).expect("Failed to parse derive input");
|
||||||
|
|
||||||
let encoder = impl_encoder_trait(name, fields);
|
TokenStream::from(render_encoder(name, &fields))
|
||||||
let decoder = impl_decoder_trait(name, fields);
|
|
||||||
|
|
||||||
TokenStream1::from(quote! {
|
|
||||||
#encoder
|
|
||||||
|
|
||||||
#decoder
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => panic!("Expected only structures"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impl_encoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
#[proc_macro_derive(Decoder, attributes(data_type))]
|
||||||
let encode = quote_field(fields, |field| {
|
pub fn derive_decoder(tokens: TokenStream) -> TokenStream {
|
||||||
let name = &field.ident;
|
let input = parse_macro_input!(tokens as DeriveInput);
|
||||||
|
let (name, fields) = parse_derive_input(&input).expect("Failed to parse derive input");
|
||||||
|
|
||||||
let unparsed_meta = get_packet_field_meta(field);
|
TokenStream::from(render_decoder(name, &fields))
|
||||||
let parsed_meta = parse_packet_field_meta(&unparsed_meta);
|
|
||||||
|
|
||||||
// This is special case because max length are used only for strings.
|
|
||||||
if let Some(max_length) = parsed_meta.max_length {
|
|
||||||
return quote! {
|
|
||||||
crate::encoder::EncoderWriteExt::write_string(writer, &self.#name, #max_length)?;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let module = parsed_meta.module.as_deref().unwrap_or("Encoder");
|
|
||||||
let module_ident = Ident::new(&module, Span::call_site());
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
crate::encoder::#module_ident::encode(&self.#name, writer)?;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#[automatically_derived]
|
|
||||||
impl crate::encoder::Encoder for #name {
|
|
||||||
fn encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), crate::error::EncodeError> {
|
|
||||||
#encode
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn impl_decoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
|
||||||
let decode = quote_field(fields, |field| {
|
|
||||||
let name = &field.ident;
|
|
||||||
let ty = &field.ty;
|
|
||||||
|
|
||||||
let unparsed_meta = get_packet_field_meta(field);
|
|
||||||
let parsed_meta = parse_packet_field_meta(&unparsed_meta);
|
|
||||||
|
|
||||||
// This is special case because max length are used only for strings.
|
|
||||||
if let Some(max_length) = parsed_meta.max_length {
|
|
||||||
return quote! {
|
|
||||||
let #name = crate::decoder::DecoderReadExt::read_string(reader, #max_length)?;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
match parsed_meta.module {
|
|
||||||
Some(module) => {
|
|
||||||
let module_ident = Ident::new(&module, Span::call_site());
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
let #name = crate::decoder::#module_ident::decode(reader)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
quote! {
|
|
||||||
let #name = <#ty as crate::decoder::Decoder>::decode(reader)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let create = quote_field(fields, |field| {
|
|
||||||
let name = &field.ident;
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#name,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#[automatically_derived]
|
|
||||||
impl crate::decoder::Decoder for #name {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn decode<R: std::io::Read>(reader: &mut R) -> Result<Self::Output, crate::error::DecodeError> {
|
|
||||||
#decode
|
|
||||||
|
|
||||||
Ok(#name {
|
|
||||||
#create
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct PacketFieldMeta {
|
|
||||||
module: Option<String>,
|
|
||||||
max_length: Option<u16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_packet_field_meta(meta_list: &Vec<NestedMeta>) -> PacketFieldMeta {
|
|
||||||
let mut module = None;
|
|
||||||
let mut max_length = None;
|
|
||||||
|
|
||||||
for meta in meta_list {
|
|
||||||
match meta {
|
|
||||||
NestedMeta::Meta(Meta::NameValue(named_meta)) => match &named_meta.path {
|
|
||||||
path if path.is_ident("with") => match &named_meta.lit {
|
|
||||||
Lit::Str(lit_str) => module = Some(lit_str.value()),
|
|
||||||
_ => panic!("\"with\" attribute value must be string"),
|
|
||||||
},
|
|
||||||
path if path.is_ident("max_length") => match &named_meta.lit {
|
|
||||||
Lit::Int(lit_int) => {
|
|
||||||
max_length = Some(
|
|
||||||
lit_int
|
|
||||||
.base10_parse::<u16>()
|
|
||||||
.expect("Failed to parse max length attribute"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => panic!("\"max_length\" attribute value must be integer"),
|
|
||||||
},
|
|
||||||
path => panic!(
|
|
||||||
"Received unrecognized attribute : \"{}\"",
|
|
||||||
path.get_ident().unwrap()
|
|
||||||
),
|
|
||||||
},
|
|
||||||
_ => panic!("Expected only named meta values"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketFieldMeta { module, max_length }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_packet_field_meta(field: &Field) -> Vec<NestedMeta> {
|
|
||||||
field
|
|
||||||
.attrs
|
|
||||||
.iter()
|
|
||||||
.filter(|a| a.path.is_ident("packet"))
|
|
||||||
.map(|a| a.parse_meta().expect("Failed to parse field attribute"))
|
|
||||||
.map(|m| match m {
|
|
||||||
Meta::List(meta_list) => Vec::from_iter(meta_list.nested),
|
|
||||||
_ => panic!("Expected only list attributes"),
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn quote_field<F: Fn(&Field) -> TokenStream2>(fields: &Fields, func: F) -> TokenStream2 {
|
|
||||||
let mut output = quote!();
|
|
||||||
|
|
||||||
match fields {
|
|
||||||
Fields::Named(named_fields) => {
|
|
||||||
output.append_all(named_fields.named.iter().map(|f| func(f)))
|
|
||||||
}
|
|
||||||
_ => panic!("Expected only for named fields"),
|
|
||||||
}
|
|
||||||
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
|
118
protocol-derive/src/parse.rs
Normal file
118
protocol-derive/src/parse.rs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
use crate::error::{DeriveInputParserError, FieldError};
|
||||||
|
use proc_macro2::Ident;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
use syn::Error as SynError;
|
||||||
|
use syn::{Data, DeriveInput, Field, Fields, FieldsNamed, Lit, Meta, NestedMeta, Type};
|
||||||
|
|
||||||
|
pub(crate) struct FieldData<'a> {
|
||||||
|
pub(crate) name: &'a Ident,
|
||||||
|
pub(crate) ty: &'a Type,
|
||||||
|
pub(crate) attribute: Attribute,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
pub(crate) enum Attribute {
|
||||||
|
With { module: String },
|
||||||
|
MaxLength { length: usize },
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_derive_input(
|
||||||
|
input: &DeriveInput,
|
||||||
|
) -> Result<(&Ident, Vec<FieldData>), DeriveInputParserError> {
|
||||||
|
let name = &input.ident;
|
||||||
|
|
||||||
|
match &input.data {
|
||||||
|
Data::Struct(data) => match &data.fields {
|
||||||
|
Fields::Named(named_fields) => Ok((name, parse_fields(named_fields)?)),
|
||||||
|
_ => Err(DeriveInputParserError::UnnamedDataFields),
|
||||||
|
},
|
||||||
|
_ => Err(DeriveInputParserError::UnsupportedData),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_fields(named_fields: &FieldsNamed) -> Result<Vec<FieldData>, DeriveInputParserError> {
|
||||||
|
let mut fields_data = Vec::new();
|
||||||
|
|
||||||
|
for field in named_fields.named.iter() {
|
||||||
|
let name = field.ident.as_ref().unwrap();
|
||||||
|
let ty = &field.ty;
|
||||||
|
|
||||||
|
let nested_metas = parse_field_nested_metas(field)?;
|
||||||
|
let attribute = parse_attribute(nested_metas)?;
|
||||||
|
|
||||||
|
fields_data.push(FieldData {
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
attribute,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(fields_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_field_nested_metas(field: &Field) -> Result<Vec<NestedMeta>, DeriveInputParserError> {
|
||||||
|
let parsed_metas = field
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.filter(|a| a.path.is_ident("data_type"))
|
||||||
|
.map(|a| a.parse_meta())
|
||||||
|
.collect::<Result<Vec<Meta>, SynError>>()?;
|
||||||
|
|
||||||
|
let nested_metas = parsed_metas
|
||||||
|
.into_iter()
|
||||||
|
.map(|m| match m {
|
||||||
|
Meta::List(meta_list) => Ok(Vec::from_iter(meta_list.nested)),
|
||||||
|
_ => Err(FieldError::UnsupportedAttribute),
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<Vec<NestedMeta>>, FieldError>>()?;
|
||||||
|
|
||||||
|
Ok(nested_metas.into_iter().flatten().collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_attribute(nested_metas: Vec<NestedMeta>) -> Result<Attribute, DeriveInputParserError> {
|
||||||
|
let attribute_parsers: Vec<fn(&NestedMeta) -> Result<Attribute, FieldError>> =
|
||||||
|
vec![get_module_attribute, get_max_length_attribute];
|
||||||
|
|
||||||
|
for nested_meta in nested_metas.iter() {
|
||||||
|
for attribute_parser in attribute_parsers.iter() {
|
||||||
|
let attribute = attribute_parser(nested_meta)?;
|
||||||
|
|
||||||
|
if attribute != Attribute::Empty {
|
||||||
|
return Ok(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Attribute::Empty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_module_attribute(nested_meta: &NestedMeta) -> Result<Attribute, FieldError> {
|
||||||
|
if let NestedMeta::Meta(Meta::NameValue(named_meta)) = nested_meta {
|
||||||
|
if matches!(&named_meta.path, path if path.is_ident("with")) {
|
||||||
|
return match &named_meta.lit {
|
||||||
|
Lit::Str(lit_str) => Ok(Attribute::With {
|
||||||
|
module: lit_str.value(),
|
||||||
|
}),
|
||||||
|
_ => Err(FieldError::AttributeWrongValueType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Attribute::Empty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_max_length_attribute(nested_meta: &NestedMeta) -> Result<Attribute, FieldError> {
|
||||||
|
if let NestedMeta::Meta(Meta::NameValue(named_meta)) = nested_meta {
|
||||||
|
if matches!(&named_meta.path, path if path.is_ident("max_length")) {
|
||||||
|
return match &named_meta.lit {
|
||||||
|
Lit::Int(lit_int) => Ok(Attribute::MaxLength {
|
||||||
|
length: lit_int.base10_parse::<usize>()?,
|
||||||
|
}),
|
||||||
|
_ => Err(FieldError::AttributeWrongValueType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Attribute::Empty)
|
||||||
|
}
|
72
protocol-derive/src/render/decoder.rs
Normal file
72
protocol-derive/src/render/decoder.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
use crate::parse::{Attribute, FieldData};
|
||||||
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
|
use proc_macro2::{Ident, Span};
|
||||||
|
use quote::quote;
|
||||||
|
use syn::Type;
|
||||||
|
|
||||||
|
pub(crate) fn render_decoder(name: &Ident, fields: &Vec<FieldData>) -> TokenStream2 {
|
||||||
|
let struct_create = render_struct_create(name, fields);
|
||||||
|
let render_fields = render_fields(fields);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl crate::decoder::Decoder for #name {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn decode<R: std::io::Read>(reader: &mut R) -> Result<Self::Output, crate::error::DecodeError> {
|
||||||
|
#render_fields
|
||||||
|
|
||||||
|
Ok(#struct_create)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_struct_create(name: &Ident, fields: &Vec<FieldData>) -> TokenStream2 {
|
||||||
|
let struct_fields = fields
|
||||||
|
.iter()
|
||||||
|
.map(|f| f.name)
|
||||||
|
.map(|n| quote!(#n,))
|
||||||
|
.collect::<TokenStream2>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#name {
|
||||||
|
#struct_fields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_fields(fields: &Vec<FieldData>) -> TokenStream2 {
|
||||||
|
fields.iter().map(|f| render_field(f)).flatten().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_field(field: &FieldData) -> TokenStream2 {
|
||||||
|
let name = field.name;
|
||||||
|
let ty = field.ty;
|
||||||
|
|
||||||
|
match &field.attribute {
|
||||||
|
Attribute::With { module } => render_with_field(name, module),
|
||||||
|
Attribute::MaxLength { length } => render_max_length_field(name, *length as u16),
|
||||||
|
Attribute::Empty => render_simple_field(name, ty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_simple_field(name: &Ident, ty: &Type) -> TokenStream2 {
|
||||||
|
quote! {
|
||||||
|
let #name = <#ty as crate::decoder::Decoder>::decode(reader)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_field(name: &Ident, module: &str) -> TokenStream2 {
|
||||||
|
let module_ident = Ident::new(module, Span::call_site());
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
let #name = crate::decoder::#module_ident::decode(reader)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_max_length_field(name: &Ident, max_length: u16) -> TokenStream2 {
|
||||||
|
quote! {
|
||||||
|
let #name = crate::decoder::DecoderReadExt::read_string(reader, #max_length)?;
|
||||||
|
}
|
||||||
|
}
|
51
protocol-derive/src/render/encoder.rs
Normal file
51
protocol-derive/src/render/encoder.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use crate::parse::{Attribute, FieldData};
|
||||||
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
|
use proc_macro2::{Ident, Span};
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
pub(crate) fn render_encoder(name: &Ident, fields: &Vec<FieldData>) -> TokenStream2 {
|
||||||
|
let render_fields = render_fields(fields);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl crate::encoder::Encoder for #name {
|
||||||
|
fn encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), crate::error::EncodeError> {
|
||||||
|
#render_fields
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_fields(fields: &Vec<FieldData>) -> TokenStream2 {
|
||||||
|
fields.iter().map(|f| render_field(f)).flatten().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_field(field: &FieldData) -> TokenStream2 {
|
||||||
|
let name = field.name;
|
||||||
|
|
||||||
|
match &field.attribute {
|
||||||
|
Attribute::With { module } => render_with_field(name, module),
|
||||||
|
Attribute::MaxLength { length } => render_max_length_field(name, *length as u16),
|
||||||
|
Attribute::Empty => render_simple_field(name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_simple_field(name: &Ident) -> TokenStream2 {
|
||||||
|
render_with_field(name, "Encoder")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_field(name: &Ident, module: &str) -> TokenStream2 {
|
||||||
|
let module_ident = Ident::new(module, Span::call_site());
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
crate::encoder::#module_ident::encode(&self.#name, writer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_max_length_field(name: &Ident, max_length: u16) -> TokenStream2 {
|
||||||
|
quote! {
|
||||||
|
crate::encoder::EncoderWriteExt::write_string(writer, &self.#name, #max_length)?;
|
||||||
|
}
|
||||||
|
}
|
2
protocol-derive/src/render/mod.rs
Normal file
2
protocol-derive/src/render/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub(crate) mod decoder;
|
||||||
|
pub(crate) mod encoder;
|
@ -4,7 +4,7 @@ use crate::data::chat::Message;
|
|||||||
use crate::decoder::Decoder;
|
use crate::decoder::Decoder;
|
||||||
use crate::error::DecodeError;
|
use crate::error::DecodeError;
|
||||||
use crate::impl_enum_encoder_decoder;
|
use crate::impl_enum_encoder_decoder;
|
||||||
use minecraft_protocol_derive::Packet;
|
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||||
use nbt::CompoundTag;
|
use nbt::CompoundTag;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
@ -89,9 +89,9 @@ impl GameClientBoundPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct ServerBoundChatMessage {
|
pub struct ServerBoundChatMessage {
|
||||||
#[packet(max_length = 256)]
|
#[data_type(max_length = 256)]
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ impl ServerBoundChatMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct ClientBoundChatMessage {
|
pub struct ClientBoundChatMessage {
|
||||||
pub message: Message,
|
pub message: Message,
|
||||||
pub position: MessagePosition,
|
pub position: MessagePosition,
|
||||||
@ -126,15 +126,15 @@ impl ClientBoundChatMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct JoinGame {
|
pub struct JoinGame {
|
||||||
pub entity_id: u32,
|
pub entity_id: u32,
|
||||||
pub game_mode: GameMode,
|
pub game_mode: GameMode,
|
||||||
pub dimension: i32,
|
pub dimension: i32,
|
||||||
pub max_players: u8,
|
pub max_players: u8,
|
||||||
#[packet(max_length = 16)]
|
#[data_type(max_length = 16)]
|
||||||
pub level_type: String,
|
pub level_type: String,
|
||||||
#[packet(with = "var_int")]
|
#[data_type(with = "var_int")]
|
||||||
pub view_distance: i32,
|
pub view_distance: i32,
|
||||||
pub reduced_debug_info: bool,
|
pub reduced_debug_info: bool,
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ impl JoinGame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet)]
|
#[derive(Encoder, Decoder)]
|
||||||
pub struct ServerBoundKeepAlive {
|
pub struct ServerBoundKeepAlive {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ impl ServerBoundKeepAlive {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet)]
|
#[derive(Encoder, Decoder)]
|
||||||
pub struct ClientBoundKeepAlive {
|
pub struct ClientBoundKeepAlive {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
}
|
}
|
||||||
@ -200,12 +200,12 @@ impl ClientBoundKeepAlive {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct ChunkData {
|
pub struct ChunkData {
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub z: i32,
|
pub z: i32,
|
||||||
pub full: bool,
|
pub full: bool,
|
||||||
#[packet(with = "var_int")]
|
#[data_type(with = "var_int")]
|
||||||
pub primary_mask: i32,
|
pub primary_mask: i32,
|
||||||
pub heights: CompoundTag,
|
pub heights: CompoundTag,
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
@ -236,7 +236,7 @@ impl ChunkData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct GameDisconnect {
|
pub struct GameDisconnect {
|
||||||
pub reason: Message,
|
pub reason: Message,
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use uuid::Uuid;
|
|||||||
use crate::data::chat::Message;
|
use crate::data::chat::Message;
|
||||||
use crate::decoder::Decoder;
|
use crate::decoder::Decoder;
|
||||||
use crate::error::DecodeError;
|
use crate::error::DecodeError;
|
||||||
use minecraft_protocol_derive::Packet;
|
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||||
|
|
||||||
pub enum LoginServerBoundPacket {
|
pub enum LoginServerBoundPacket {
|
||||||
LoginStart(LoginStart),
|
LoginStart(LoginStart),
|
||||||
@ -102,7 +102,7 @@ impl LoginClientBoundPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct LoginStart {
|
pub struct LoginStart {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ impl LoginStart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct EncryptionResponse {
|
pub struct EncryptionResponse {
|
||||||
pub shared_secret: Vec<u8>,
|
pub shared_secret: Vec<u8>,
|
||||||
pub verify_token: Vec<u8>,
|
pub verify_token: Vec<u8>,
|
||||||
@ -132,12 +132,12 @@ impl EncryptionResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct LoginPluginResponse {
|
pub struct LoginPluginResponse {
|
||||||
#[packet(with = "var_int")]
|
#[data_type(with = "var_int")]
|
||||||
pub message_id: i32,
|
pub message_id: i32,
|
||||||
pub successful: bool,
|
pub successful: bool,
|
||||||
#[packet(with = "rest")]
|
#[data_type(with = "rest")]
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ impl LoginPluginResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct LoginDisconnect {
|
pub struct LoginDisconnect {
|
||||||
pub reason: Message,
|
pub reason: Message,
|
||||||
}
|
}
|
||||||
@ -166,9 +166,9 @@ impl LoginDisconnect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct EncryptionRequest {
|
pub struct EncryptionRequest {
|
||||||
#[packet(max_length = 20)]
|
#[data_type(max_length = 20)]
|
||||||
pub server_id: String,
|
pub server_id: String,
|
||||||
pub public_key: Vec<u8>,
|
pub public_key: Vec<u8>,
|
||||||
pub verify_token: Vec<u8>,
|
pub verify_token: Vec<u8>,
|
||||||
@ -190,11 +190,11 @@ impl EncryptionRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct LoginSuccess {
|
pub struct LoginSuccess {
|
||||||
#[packet(with = "uuid_hyp_str")]
|
#[data_type(with = "uuid_hyp_str")]
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
#[packet(max_length = 16)]
|
#[data_type(max_length = 16)]
|
||||||
pub username: String,
|
pub username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,9 +206,9 @@ impl LoginSuccess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct SetCompression {
|
pub struct SetCompression {
|
||||||
#[packet(with = "var_int")]
|
#[data_type(with = "var_int")]
|
||||||
pub threshold: i32,
|
pub threshold: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,12 +220,12 @@ impl SetCompression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct LoginPluginRequest {
|
pub struct LoginPluginRequest {
|
||||||
#[packet(with = "var_int")]
|
#[data_type(with = "var_int")]
|
||||||
pub message_id: i32,
|
pub message_id: i32,
|
||||||
pub channel: String,
|
pub channel: String,
|
||||||
#[packet(with = "rest")]
|
#[data_type(with = "rest")]
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::data::server_status::*;
|
use crate::data::server_status::*;
|
||||||
use crate::decoder::Decoder;
|
use crate::decoder::Decoder;
|
||||||
use crate::error::DecodeError;
|
use crate::error::DecodeError;
|
||||||
use minecraft_protocol_derive::Packet;
|
use minecraft_protocol_derive::{Decoder, Encoder};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
pub enum StatusServerBoundPacket {
|
pub enum StatusServerBoundPacket {
|
||||||
@ -44,7 +44,7 @@ impl StatusClientBoundPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct PingRequest {
|
pub struct PingRequest {
|
||||||
pub time: u64,
|
pub time: u64,
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ impl PingRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct PingResponse {
|
pub struct PingResponse {
|
||||||
pub time: u64,
|
pub time: u64,
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ impl PingResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Encoder, Decoder, Debug)]
|
||||||
pub struct StatusResponse {
|
pub struct StatusResponse {
|
||||||
pub server_status: ServerStatus,
|
pub server_status: ServerStatus,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user