Add field custom encoder decoder support
This commit is contained in:
parent
0a0500239b
commit
61fff6fcf7
@ -5,6 +5,7 @@ use proc_macro2::Ident;
|
|||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::{quote, TokenStreamExt};
|
use quote::{quote, TokenStreamExt};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
use syn::export::Span;
|
||||||
use syn::{parse_macro_input, Data, DeriveInput, Field, Fields, Lit, Meta, NestedMeta};
|
use syn::{parse_macro_input, Data, DeriveInput, Field, Fields, Lit, Meta, NestedMeta};
|
||||||
|
|
||||||
#[proc_macro_derive(Packet, attributes(packet))]
|
#[proc_macro_derive(Packet, attributes(packet))]
|
||||||
@ -34,11 +35,22 @@ fn impl_encoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
|||||||
let name = &field.ident;
|
let name = &field.ident;
|
||||||
|
|
||||||
let unparsed_meta = get_packet_field_meta(field);
|
let unparsed_meta = get_packet_field_meta(field);
|
||||||
let parsed_meta = parse_field_meta(&unparsed_meta);
|
let parsed_meta = parse_packet_field_meta(&unparsed_meta);
|
||||||
|
|
||||||
|
match parsed_meta.module {
|
||||||
|
Some(module) => {
|
||||||
|
let module_ident = Ident::new(&module, Span::call_site());
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
crate::#module_ident::encode(&self.#name, writer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
quote! {
|
quote! {
|
||||||
crate::Encoder::encode(&self.#name, writer)?;
|
crate::Encoder::encode(&self.#name, writer)?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@ -76,7 +88,7 @@ struct PacketFieldMeta {
|
|||||||
max_length: Option<u16>,
|
max_length: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_field_meta(meta_list: &Vec<NestedMeta>) -> PacketFieldMeta {
|
fn parse_packet_field_meta(meta_list: &Vec<NestedMeta>) -> PacketFieldMeta {
|
||||||
let mut module = None;
|
let mut module = None;
|
||||||
let mut max_length = None;
|
let mut max_length = None;
|
||||||
|
|
||||||
|
@ -8,9 +8,6 @@ use minecraft_protocol_derive::Packet;
|
|||||||
use nbt::CompoundTag;
|
use nbt::CompoundTag;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
const SERVER_BOUND_CHAT_MESSAGE_MAX_LENGTH: u32 = 256;
|
|
||||||
const LEVEL_TYPE_MAX_LENGTH: u32 = 16;
|
|
||||||
|
|
||||||
pub enum GameServerBoundPacket {
|
pub enum GameServerBoundPacket {
|
||||||
ServerBoundChatMessage(ServerBoundChatMessage),
|
ServerBoundChatMessage(ServerBoundChatMessage),
|
||||||
ServerBoundKeepAlive(ServerBoundKeepAlive),
|
ServerBoundKeepAlive(ServerBoundKeepAlive),
|
||||||
@ -87,6 +84,7 @@ impl GameClientBoundPacket {
|
|||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Packet, Debug)]
|
||||||
pub struct ServerBoundChatMessage {
|
pub struct ServerBoundChatMessage {
|
||||||
|
#[packet(max_length = 256)]
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +125,10 @@ pub struct JoinGame {
|
|||||||
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)]
|
||||||
pub level_type: String,
|
pub level_type: String,
|
||||||
pub view_distance: u8,
|
#[packet(with = "var_int")]
|
||||||
|
pub view_distance: i32,
|
||||||
pub reduced_debug_info: bool,
|
pub reduced_debug_info: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ impl JoinGame {
|
|||||||
dimension: i32,
|
dimension: i32,
|
||||||
max_players: u8,
|
max_players: u8,
|
||||||
level_type: String,
|
level_type: String,
|
||||||
view_distance: u8,
|
view_distance: i32,
|
||||||
reduced_debug_info: bool,
|
reduced_debug_info: bool,
|
||||||
) -> GameClientBoundPacket {
|
) -> GameClientBoundPacket {
|
||||||
let join_game = JoinGame {
|
let join_game = JoinGame {
|
||||||
@ -198,6 +198,7 @@ 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")]
|
||||||
pub primary_mask: i32,
|
pub primary_mask: i32,
|
||||||
pub heights: CompoundTag,
|
pub heights: CompoundTag,
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
|
@ -24,8 +24,9 @@ pub mod status;
|
|||||||
|
|
||||||
/// Current supported protocol version.
|
/// Current supported protocol version.
|
||||||
pub const PROTOCOL_VERSION: u32 = 498;
|
pub const PROTOCOL_VERSION: u32 = 498;
|
||||||
/// String maximum length.
|
/// Protocol limits maximum string length.
|
||||||
const STRING_MAX_LENGTH: u32 = 32_768;
|
const STRING_MAX_LENGTH: u32 = 32_768;
|
||||||
|
const HYPHENATED_UUID_LENGTH: u32 = 36;
|
||||||
|
|
||||||
/// Possible errors while encoding packet.
|
/// Possible errors while encoding packet.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -477,3 +478,76 @@ macro_rules! impl_json_encoder_decoder (
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
);
|
);
|
||||||
|
|
||||||
|
mod var_int {
|
||||||
|
use crate::{DecodeError, EncodeError, Encoder};
|
||||||
|
use mc_varint::{VarIntRead, VarIntWrite};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
pub fn encode<W: Write>(value: &i32, writer: &mut W) -> Result<(), EncodeError> {
|
||||||
|
writer.write_var_i32(*value)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode<R: Read>(reader: &mut R) -> Result<i32, DecodeError> {
|
||||||
|
Ok(reader.read_var_i32()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod var_long {
|
||||||
|
use crate::{DecodeError, EncodeError, Encoder};
|
||||||
|
use mc_varint::{VarIntRead, VarIntWrite};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
pub fn encode<W: Write>(value: &i64, writer: &mut W) -> Result<(), EncodeError> {
|
||||||
|
writer.write_var_i64(*value)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode<R: Read>(reader: &mut R) -> Result<i64, DecodeError> {
|
||||||
|
Ok(reader.read_var_i64()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod rest {
|
||||||
|
use crate::{DecodeError, Decoder, EncodeError, Encoder};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
pub fn encode<W: Write>(value: &[u8], writer: &mut W) -> Result<(), EncodeError> {
|
||||||
|
writer.write_all(value)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode<R: Read>(reader: &mut R) -> Result<Vec<u8>, DecodeError> {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
reader.read_to_end(data.as_mut())?;
|
||||||
|
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod uuid_hyp_str {
|
||||||
|
use crate::{
|
||||||
|
DecodeError, Decoder, DecoderReadExt, EncodeError, Encoder, EncoderWriteExt,
|
||||||
|
HYPHENATED_UUID_LENGTH,
|
||||||
|
};
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub fn encode<W: Write>(value: &Uuid, writer: &mut W) -> Result<(), EncodeError> {
|
||||||
|
let uuid_hyphenated_string = value.to_hyphenated().to_string();
|
||||||
|
writer.write_string(&uuid_hyphenated_string, HYPHENATED_UUID_LENGTH)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode<R: Read>(reader: &mut R) -> Result<Uuid, DecodeError> {
|
||||||
|
let uuid_hyphenated_string = reader.read_string(HYPHENATED_UUID_LENGTH)?;
|
||||||
|
let uuid = Uuid::parse_str(&uuid_hyphenated_string)?;
|
||||||
|
|
||||||
|
Ok(uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,10 +6,6 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use minecraft_protocol_derive::Packet;
|
use minecraft_protocol_derive::Packet;
|
||||||
|
|
||||||
const LOGIN_MAX_LENGTH: u32 = 16;
|
|
||||||
const SERVER_ID_MAX_LENGTH: u32 = 20;
|
|
||||||
const HYPHENATED_UUID_LENGTH: u32 = 36;
|
|
||||||
|
|
||||||
pub enum LoginServerBoundPacket {
|
pub enum LoginServerBoundPacket {
|
||||||
LoginStart(LoginStart),
|
LoginStart(LoginStart),
|
||||||
EncryptionResponse(EncryptionResponse),
|
EncryptionResponse(EncryptionResponse),
|
||||||
@ -138,8 +134,10 @@ impl EncryptionResponse {
|
|||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Packet, Debug)]
|
||||||
pub struct LoginPluginResponse {
|
pub struct LoginPluginResponse {
|
||||||
|
#[packet(with = "var_int")]
|
||||||
pub message_id: i32,
|
pub message_id: i32,
|
||||||
pub successful: bool,
|
pub successful: bool,
|
||||||
|
#[packet(with = "rest")]
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +192,9 @@ impl EncryptionRequest {
|
|||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Packet, Debug)]
|
||||||
pub struct LoginSuccess {
|
pub struct LoginSuccess {
|
||||||
|
#[packet(with = "uuid_hyp_str")]
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
|
#[packet(max_length = 16)]
|
||||||
pub username: String,
|
pub username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ impl LoginSuccess {
|
|||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Packet, Debug)]
|
||||||
pub struct SetCompression {
|
pub struct SetCompression {
|
||||||
#[packet(with = "varint")]
|
#[packet(with = "var_int")]
|
||||||
pub threshold: i32,
|
pub threshold: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,8 +222,10 @@ impl SetCompression {
|
|||||||
|
|
||||||
#[derive(Packet, Debug)]
|
#[derive(Packet, Debug)]
|
||||||
pub struct LoginPluginRequest {
|
pub struct LoginPluginRequest {
|
||||||
|
#[packet(with = "var_int")]
|
||||||
pub message_id: i32,
|
pub message_id: i32,
|
||||||
pub channel: String,
|
pub channel: String,
|
||||||
|
#[packet(with = "rest")]
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user