Save some progress towards derive macro

This commit is contained in:
vagola 2020-01-02 04:52:46 +03:00
parent d384ed2814
commit f43592c01f
6 changed files with 327 additions and 407 deletions

View File

@ -10,5 +10,7 @@ publish = false
proc-macro = true proc-macro = true
[dependencies] [dependencies]
syn = "1.0" # Versions match serde crate to reduce compile time.
quote = "1.0" proc-macro2 = "0.4.30"
syn = "0.15.44"
quote = "0.6.13"

View File

@ -1,27 +1,80 @@
extern crate proc_macro; extern crate proc_macro;
use proc_macro::TokenStream; use proc_macro::TokenStream as TokenStream1;
use quote::quote; use proc_macro2::Ident;
use syn::{parse_macro_input, DeriveInput}; use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, TokenStreamExt};
use syn::{parse_macro_input, Data, DeriveInput, Field, Fields};
#[proc_macro_derive(Packet)] #[proc_macro_derive(Packet)]
pub fn derive_packet(input: TokenStream) -> TokenStream { pub fn derive_packet(input: proc_macro::TokenStream) -> TokenStream1 {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
let name = input.ident; let name = &input.ident;
let output = quote! { match input.data {
impl crate::PacketParser for #name { Data::Struct(data) => {
let fields = &data.fields;
let encoder = impl_encoder_trait(name, fields);
let decoder = impl_decoder_trait(name, fields);
TokenStream1::from(quote! {
#encoder
#decoder
})
}
_ => panic!("Packet derive are available only for structures"),
}
}
fn impl_encoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
let encode = quote_field(fields, |field| {
let name = &field.ident;
quote! {
Encoder::encode(&self.#name, writer);
}
});
quote! {
impl crate::Encoder for #name {
fn encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), crate::EncodeError> {
#encode
Ok(())
}
}
}
}
fn impl_decoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
let decode = quote_field(fields, |field| {
quote! {
todo!();
}
});
quote! {
impl crate::Decoder for #name {
type Output = Self; type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> { fn decode<R: std::io::Read>(reader: &mut R) -> Result<Self::Output, crate::DecodeError> {
todo!(); #decode
}
}
}
} }
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> { fn quote_field<F: Fn(&Field) -> TokenStream2>(fields: &Fields, func: F) -> TokenStream2 {
todo!(); let mut output = quote!();
}
}
};
TokenStream::from(output) match fields {
Fields::Named(named_fields) => {
output.append_all(named_fields.named.iter().map(|f| func(f)))
}
_ => panic!("Packet derive are available only for named fields"),
}
output
} }

View File

@ -1,12 +1,12 @@
use std::io::{Read, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use crate::chat::Message; use crate::chat::Message;
use crate::{DecodeError, EncodeError, PacketParser, PacketRead, PacketWrite}; use crate::DecodeError;
use mc_varint::{VarIntRead, VarIntWrite}; use crate::Decoder;
use crate::Encoder;
use minecraft_protocol_derive::Packet;
use nbt::CompoundTag; use nbt::CompoundTag;
use std::io::Read;
const SERVER_BOUND_CHAT_MESSAGE_MAX_LENGTH: u32 = 256; const SERVER_BOUND_CHAT_MESSAGE_MAX_LENGTH: u32 = 256;
const LEVEL_TYPE_MAX_LENGTH: u32 = 16; const LEVEL_TYPE_MAX_LENGTH: u32 = 16;
@ -85,6 +85,7 @@ impl GameClientBoundPacket {
} }
} }
#[derive(Packet, Debug)]
pub struct ServerBoundChatMessage { pub struct ServerBoundChatMessage {
pub message: String, pub message: String,
} }
@ -97,20 +98,7 @@ impl ServerBoundChatMessage {
} }
} }
impl PacketParser for ServerBoundChatMessage { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_string(&self.message, SERVER_BOUND_CHAT_MESSAGE_MAX_LENGTH)
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let message = reader.read_string(SERVER_BOUND_CHAT_MESSAGE_MAX_LENGTH)?;
Ok(ServerBoundChatMessage { message })
}
}
pub struct ClientBoundChatMessage { pub struct ClientBoundChatMessage {
pub message: Message, pub message: Message,
pub position: MessagePosition, pub position: MessagePosition,
@ -131,27 +119,7 @@ impl ClientBoundChatMessage {
} }
} }
impl PacketParser for ClientBoundChatMessage { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_chat_message(&self.message)?;
writer.write_enum(&self.position)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let message = reader.read_chat_message()?;
let position = reader.read_enum()?;
let chat_message = ClientBoundChatMessage { message, position };
Ok(chat_message)
}
}
#[derive(Debug)]
pub struct JoinGame { pub struct JoinGame {
pub entity_id: u32, pub entity_id: u32,
pub game_mode: GameMode, pub game_mode: GameMode,
@ -195,42 +163,7 @@ impl JoinGame {
} }
} }
impl PacketParser for JoinGame { #[derive(Packet)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_u32::<BigEndian>(self.entity_id)?;
writer.write_enum(&self.game_mode)?;
writer.write_i32::<BigEndian>(self.dimension)?;
writer.write_u8(self.max_players)?;
writer.write_string(&self.level_type, LEVEL_TYPE_MAX_LENGTH)?;
writer.write_var_i32(self.view_distance as i32)?;
writer.write_bool(self.reduced_debug_info)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let entity_id = reader.read_u32::<BigEndian>()?;
let game_mode = reader.read_enum()?;
let dimension = reader.read_i32::<BigEndian>()?;
let max_players = reader.read_u8()?;
let level_type = reader.read_string(LEVEL_TYPE_MAX_LENGTH)?;
let view_distance = reader.read_var_i32()? as u8;
let reduced_debug_info = reader.read_bool()?;
Ok(JoinGame {
entity_id,
game_mode,
dimension,
max_players,
level_type,
view_distance,
reduced_debug_info,
})
}
}
pub struct ServerBoundKeepAlive { pub struct ServerBoundKeepAlive {
pub id: u64, pub id: u64,
} }
@ -243,22 +176,7 @@ impl ServerBoundKeepAlive {
} }
} }
impl PacketParser for ServerBoundKeepAlive { #[derive(Packet)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_u64::<BigEndian>(self.id)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let id = reader.read_u64::<BigEndian>()?;
Ok(ServerBoundKeepAlive { id })
}
}
pub struct ClientBoundKeepAlive { pub struct ClientBoundKeepAlive {
pub id: u64, pub id: u64,
} }
@ -271,22 +189,7 @@ impl ClientBoundKeepAlive {
} }
} }
impl PacketParser for ClientBoundKeepAlive { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_u64::<BigEndian>(self.id)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let id = reader.read_u64::<BigEndian>()?;
Ok(ClientBoundKeepAlive { id })
}
}
pub struct ChunkData { pub struct ChunkData {
pub x: i32, pub x: i32,
pub z: i32, pub z: i32,
@ -321,53 +224,6 @@ impl ChunkData {
} }
} }
impl PacketParser for ChunkData {
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_i32::<BigEndian>(self.x)?;
writer.write_i32::<BigEndian>(self.z)?;
writer.write_bool(self.full)?;
writer.write_var_i32(self.primary_mask)?;
writer.write_compound_tag(&self.heights)?;
writer.write_byte_array(&self.data)?;
writer.write_var_i32(self.tiles.len() as i32)?;
for tile_compound_tag in self.tiles.iter() {
writer.write_compound_tag(&tile_compound_tag)?;
}
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let x = reader.read_i32::<BigEndian>()?;
let z = reader.read_i32::<BigEndian>()?;
let full = reader.read_bool()?;
let primary_mask = reader.read_var_i32()?;
let heights = reader.read_compound_tag()?;
let data = reader.read_byte_array()?;
let tiles_length = reader.read_var_i32()?;
let mut tiles = Vec::new();
for _ in 0..tiles_length {
let tile_compound_tag = reader.read_compound_tag()?;
tiles.push(tile_compound_tag);
}
Ok(ChunkData {
x,
z,
full,
primary_mask,
heights,
data,
tiles,
})
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::chat::{Message, Payload}; use crate::chat::{Message, Payload};
@ -375,7 +231,8 @@ mod tests {
ChunkData, ClientBoundChatMessage, ClientBoundKeepAlive, GameMode, JoinGame, ChunkData, ClientBoundChatMessage, ClientBoundKeepAlive, GameMode, JoinGame,
MessagePosition, ServerBoundChatMessage, ServerBoundKeepAlive, MessagePosition, ServerBoundChatMessage, ServerBoundKeepAlive,
}; };
use crate::PacketParser; use crate::Decoder;
use crate::Encoder;
use nbt::CompoundTag; use nbt::CompoundTag;
use std::io::Cursor; use std::io::Cursor;

View File

@ -6,8 +6,8 @@ use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::string::FromUtf8Error; use std::string::FromUtf8Error;
use byteorder::ReadBytesExt;
use byteorder::WriteBytesExt; use byteorder::WriteBytesExt;
use byteorder::{BigEndian, ReadBytesExt};
use mc_varint::{VarIntRead, VarIntWrite}; use mc_varint::{VarIntRead, VarIntWrite};
use serde_json::error::Error as JsonError; use serde_json::error::Error as JsonError;
use uuid::parser::ParseError as UuidParseError; use uuid::parser::ParseError as UuidParseError;
@ -16,6 +16,8 @@ use crate::chat::Message;
use nbt::decode::TagDecodeError; use nbt::decode::TagDecodeError;
use nbt::CompoundTag; use nbt::CompoundTag;
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
pub mod chat; pub mod chat;
pub mod game; pub mod game;
@ -125,10 +127,12 @@ impl From<TagDecodeError> for DecodeError {
} }
} }
trait PacketParser { trait Encoder {
type Output;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError>; fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError>;
}
trait Decoder {
type Output;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError>; fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError>;
} }
@ -261,3 +265,208 @@ impl<W: Write> PacketWrite for W {
Ok(()) Ok(())
} }
} }
// TODO: Replace primitive impls with macros.
impl Encoder for u8 {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_u8(*self)?)
}
}
impl Decoder for u8 {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_u8()?)
}
}
impl Encoder for i32 {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_i32::<BigEndian>(*self)?)
}
}
impl Decoder for i32 {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_i32::<BigEndian>()?)
}
}
impl Encoder for u32 {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_u32::<BigEndian>(*self)?)
}
}
impl Decoder for u32 {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_u32::<BigEndian>()?)
}
}
impl Encoder for i64 {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_i64::<BigEndian>(*self)?)
}
}
impl Decoder for i64 {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_i64::<BigEndian>()?)
}
}
impl Encoder for u64 {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_u64::<BigEndian>(*self)?)
}
}
impl Decoder for u64 {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_u64::<BigEndian>()?)
}
}
impl Encoder for String {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_string(self, STRING_MAX_LENGTH)?)
}
}
impl Decoder for String {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_string(STRING_MAX_LENGTH)?)
}
}
impl Encoder for bool {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_bool(*self)?)
}
}
impl Decoder for bool {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_bool()?)
}
}
impl<T: ToPrimitive> Encoder for T {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_enum(self)?)
}
}
impl<T: ToPrimitive> Decoder for T {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_enum())
}
}
impl Encoder for Vec<u8> {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_byte_array(self)?)
}
}
impl Decoder for Vec<u8> {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_byte_array()?)
}
}
impl Encoder for Uuid {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_all(self.as_bytes())?)
}
}
impl Decoder for Uuid {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let buf = [0; 16];
reader.read_exact(&buf)?;
Ok(Uuid::from_bytes(buf))
}
}
impl Encoder for CompoundTag {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
Ok(writer.write_compound_tag(self)?)
}
}
impl Decoder for CompoundTag {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
Ok(reader.read_compound_tag()?)
}
}
impl Encoder for Vec<CompoundTag> {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_var_i32(self.len() as i32)?;
for compound_tag in self {
writer.write_compound_tag(&compound_tag)?;
}
Ok(())
}
}
impl Decoder for Vec<CompoundTag> {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let length = reader.read_var_i32()? as usize;
let mut vec = Vec::with_capacity(length);
for _ in 0..length {
let compound_tag = reader.read_compound_tag()?;
vec.push(compound_tag);
}
Ok(vec)
}
}
impl<T: Serialize> Encoder for T {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
let json = serde_json::to_string(self)?;
writer.write_string(&json, STRING_MAX_LENGTH)?;
Ok(())
}
}
impl<'de, T: Deserialize<'de>> Decoder for T {
type Output = Self;
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let json = reader.read_string(STRING_MAX_LENGTH)?;
serde_json::from_str(&json)?
}
}

View File

@ -1,10 +1,11 @@
use std::io::{Read, Write}; use crate::chat::Message;
use crate::DecodeError;
use mc_varint::{VarIntRead, VarIntWrite}; use crate::Decoder;
use crate::Encoder;
use std::io::Read;
use uuid::Uuid; use uuid::Uuid;
use crate::chat::Message; use minecraft_protocol_derive::Packet;
use crate::{DecodeError, EncodeError, PacketParser, PacketRead, PacketWrite, STRING_MAX_LENGTH};
const LOGIN_MAX_LENGTH: u32 = 16; const LOGIN_MAX_LENGTH: u32 = 16;
const SERVER_ID_MAX_LENGTH: u32 = 20; const SERVER_ID_MAX_LENGTH: u32 = 20;
@ -106,6 +107,7 @@ impl LoginClientBoundPacket {
} }
} }
#[derive(Packet, Debug)]
pub struct LoginStart { pub struct LoginStart {
pub name: String, pub name: String,
} }
@ -118,20 +120,7 @@ impl LoginStart {
} }
} }
impl PacketParser for LoginStart { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_string(&self.name, LOGIN_MAX_LENGTH)
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let name = reader.read_string(LOGIN_MAX_LENGTH)?;
Ok(LoginStart { name })
}
}
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>,
@ -148,27 +137,7 @@ impl EncryptionResponse {
} }
} }
impl PacketParser for EncryptionResponse { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_byte_array(&self.shared_secret)?;
writer.write_byte_array(&self.verify_token)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let shared_secret = reader.read_byte_array()?;
let verify_token = reader.read_byte_array()?;
Ok(EncryptionResponse {
shared_secret,
verify_token,
})
}
}
pub struct LoginPluginResponse { pub struct LoginPluginResponse {
pub message_id: i32, pub message_id: i32,
pub successful: bool, pub successful: bool,
@ -187,32 +156,7 @@ impl LoginPluginResponse {
} }
} }
impl PacketParser for LoginPluginResponse { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_var_i32(self.message_id)?;
writer.write_bool(self.successful)?;
writer.write_all(&self.data)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let message_id = reader.read_var_i32()?;
let successful = reader.read_bool()?;
let mut data = Vec::new();
reader.read_to_end(data.as_mut())?;
Ok(LoginPluginResponse {
message_id,
successful,
data,
})
}
}
pub struct LoginDisconnect { pub struct LoginDisconnect {
pub reason: Message, pub reason: Message,
} }
@ -225,22 +169,7 @@ impl LoginDisconnect {
} }
} }
impl PacketParser for LoginDisconnect { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_chat_message(&self.reason)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let reason = reader.read_chat_message()?;
Ok(LoginDisconnect { reason })
}
}
pub struct EncryptionRequest { pub struct EncryptionRequest {
pub server_id: String, pub server_id: String,
pub public_key: Vec<u8>, pub public_key: Vec<u8>,
@ -263,30 +192,7 @@ impl EncryptionRequest {
} }
} }
impl PacketParser for EncryptionRequest { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_string(&self.server_id, SERVER_ID_MAX_LENGTH)?;
writer.write_byte_array(&self.public_key)?;
writer.write_byte_array(&self.verify_token)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let server_id = reader.read_string(SERVER_ID_MAX_LENGTH)?;
let public_key = reader.read_byte_array()?;
let verify_token = reader.read_byte_array()?;
Ok(EncryptionRequest {
server_id,
public_key,
verify_token,
})
}
}
pub struct LoginSuccess { pub struct LoginSuccess {
pub uuid: Uuid, pub uuid: Uuid,
pub username: String, pub username: String,
@ -300,28 +206,7 @@ impl LoginSuccess {
} }
} }
impl PacketParser for LoginSuccess { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
let uuid_hyphenated_string = self.uuid.to_hyphenated().to_string();
writer.write_string(&uuid_hyphenated_string, HYPHENATED_UUID_LENGTH)?;
writer.write_string(&self.username, LOGIN_MAX_LENGTH)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let uuid_hyphenated_string = reader.read_string(HYPHENATED_UUID_LENGTH)?;
let uuid = Uuid::parse_str(&uuid_hyphenated_string)?;
let username = reader.read_string(LOGIN_MAX_LENGTH)?;
Ok(LoginSuccess { uuid, username })
}
}
pub struct SetCompression { pub struct SetCompression {
pub threshold: i32, pub threshold: i32,
} }
@ -334,22 +219,7 @@ impl SetCompression {
} }
} }
impl PacketParser for SetCompression { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_var_i32(self.threshold)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let threshold = reader.read_var_i32()?;
Ok(SetCompression { threshold })
}
}
pub struct LoginPluginRequest { pub struct LoginPluginRequest {
pub message_id: i32, pub message_id: i32,
pub channel: String, pub channel: String,
@ -368,38 +238,14 @@ impl LoginPluginRequest {
} }
} }
impl PacketParser for LoginPluginRequest {
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_var_i32(self.message_id)?;
writer.write_string(&self.channel, STRING_MAX_LENGTH)?;
writer.write_all(&self.data)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let message_id = reader.read_var_i32()?;
let channel = reader.read_string(STRING_MAX_LENGTH)?;
let mut data = Vec::new();
reader.read_to_end(data.as_mut())?;
Ok(LoginPluginRequest {
message_id,
channel,
data,
})
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::chat::{Message, Payload}; use crate::chat::{Message, Payload};
use crate::login::{EncryptionRequest, LoginDisconnect, LoginPluginRequest, SetCompression}; use crate::login::{EncryptionRequest, LoginDisconnect, LoginPluginRequest, SetCompression};
use crate::login::{EncryptionResponse, LoginPluginResponse}; use crate::login::{EncryptionResponse, LoginPluginResponse};
use crate::login::{LoginStart, LoginSuccess}; use crate::login::{LoginStart, LoginSuccess};
use crate::PacketParser; use crate::Decoder;
use crate::Encoder;
use std::io::Cursor; use std::io::Cursor;
use uuid::Uuid; use uuid::Uuid;

View File

@ -1,11 +1,11 @@
use std::io::{Read, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
use crate::chat::Message; use crate::chat::Message;
use crate::{DecodeError, EncodeError, PacketParser, PacketRead, PacketWrite, STRING_MAX_LENGTH}; use crate::DecodeError;
use crate::Decoder;
use minecraft_protocol_derive::Packet;
use std::io::Read;
pub enum StatusServerBoundPacket { pub enum StatusServerBoundPacket {
StatusRequest, StatusRequest,
@ -47,6 +47,7 @@ impl StatusClientBoundPacket {
} }
} }
#[derive(Packet, Debug)]
pub struct PingRequest { pub struct PingRequest {
pub time: u64, pub time: u64,
} }
@ -59,22 +60,7 @@ impl PingRequest {
} }
} }
impl PacketParser for PingRequest { #[derive(Packet, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_u64::<BigEndian>(self.time)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let time = reader.read_u64::<BigEndian>()?;
Ok(PingRequest { time })
}
}
pub struct PingResponse { pub struct PingResponse {
pub time: u64, pub time: u64,
} }
@ -87,36 +73,20 @@ impl PingResponse {
} }
} }
impl PacketParser for PingResponse { #[derive(Serialize, Deserialize, Debug)]
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_u64::<BigEndian>(self.time)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let time = reader.read_u64::<BigEndian>()?;
Ok(PingResponse { time })
}
}
#[derive(Serialize, Deserialize)]
pub struct ServerStatus { pub struct ServerStatus {
pub version: ServerVersion, pub version: ServerVersion,
pub players: OnlinePlayers, pub players: OnlinePlayers,
pub description: Message, pub description: Message,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct ServerVersion { pub struct ServerVersion {
pub name: String, pub name: String,
pub protocol: u32, pub protocol: u32,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct OnlinePlayers { pub struct OnlinePlayers {
pub max: u32, pub max: u32,
pub online: u32, pub online: u32,
@ -129,6 +99,7 @@ pub struct OnlinePlayer {
pub id: Uuid, pub id: Uuid,
} }
#[derive(Packet, Debug)]
pub struct StatusResponse { pub struct StatusResponse {
pub server_status: ServerStatus, pub server_status: ServerStatus,
} }
@ -141,25 +112,6 @@ impl StatusResponse {
} }
} }
impl PacketParser for StatusResponse {
type Output = Self;
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
let json = serde_json::to_string(&self.server_status)?;
writer.write_string(&json, STRING_MAX_LENGTH)?;
Ok(())
}
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
let json = reader.read_string(STRING_MAX_LENGTH)?;
let server_status = serde_json::from_str(&json)?;
let status_response = StatusResponse { server_status };
Ok(status_response)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::chat::{Message, Payload}; use crate::chat::{Message, Payload};
@ -167,7 +119,8 @@ mod tests {
OnlinePlayer, OnlinePlayers, PingRequest, PingResponse, ServerStatus, ServerVersion, OnlinePlayer, OnlinePlayers, PingRequest, PingResponse, ServerStatus, ServerVersion,
StatusResponse, StatusResponse,
}; };
use crate::PacketParser; use crate::Decoder;
use crate::Encoder;
use std::io::Cursor; use std::io::Cursor;
use uuid::Uuid; use uuid::Uuid;