Add join game packet

This commit is contained in:
vagola 2019-12-27 01:08:17 +03:00
parent 61d3c950b3
commit 0838c3688d
2 changed files with 111 additions and 10 deletions

View File

@ -1,13 +1,14 @@
use std::io::{Read, Write};
use byteorder::{ReadBytesExt, WriteBytesExt};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};
use crate::chat::Message;
use crate::{DecodeError, EncodeError, Packet, PacketRead, PacketWrite};
use mc_varint::{VarIntRead, VarIntWrite};
const SERVER_BOUND_CHAT_MESSAGE_MAX_LENGTH: u32 = 256;
const LEVEL_TYPE_MAX_LENGTH: u32 = 16;
pub enum GameServerBoundPacket {
ServerBoundChatMessage(ServerBoundChatMessage),
@ -15,6 +16,7 @@ pub enum GameServerBoundPacket {
pub enum GameClientBoundPacket {
ClientBoundChatMessage(ClientBoundChatMessage),
JoinGame(JoinGame),
}
impl GameServerBoundPacket {
@ -40,6 +42,7 @@ impl GameClientBoundPacket {
pub fn get_type_id(&self) -> u8 {
match self {
GameClientBoundPacket::ClientBoundChatMessage(_) => 0x0E,
GameClientBoundPacket::JoinGame(_) => 0x25,
}
}
@ -50,6 +53,11 @@ impl GameClientBoundPacket {
Ok(GameClientBoundPacket::ClientBoundChatMessage(chat_message))
}
0x25 => {
let join_game = JoinGame::decode(reader)?;
Ok(GameClientBoundPacket::JoinGame(join_game))
}
_ => Err(DecodeError::UnknownPacketType { type_id }),
}
}
@ -106,23 +114,97 @@ impl Packet for ClientBoundChatMessage {
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
writer.write_chat_message(&self.message)?;
writer.write_u8(ToPrimitive::to_u8(&self.position).unwrap())?;
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_type_id = reader.read_u8()?;
let position = FromPrimitive::from_u8(position_type_id).ok_or_else(|| {
DecodeError::UnknownEnumType {
type_id: position_type_id,
}
})?;
let position = reader.read_enum()?;
let chat_message = ClientBoundChatMessage { message, position };
Ok(chat_message)
}
}
#[derive(Debug)]
pub struct JoinGame {
pub entity_id: u32,
pub game_mode: GameMode,
pub dimension: i32,
pub max_players: u8,
pub level_type: String,
pub view_distance: u8,
pub reduced_debug_info: bool,
}
#[derive(Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
pub enum GameMode {
Survival = 0,
Creative = 1,
Adventure = 2,
Spectator = 3,
Hardcore = 8,
}
impl JoinGame {
pub fn new(
entity_id: u32,
game_mode: GameMode,
dimension: i32,
max_players: u8,
level_type: String,
view_distance: u8,
reduced_debug_info: bool,
) -> GameClientBoundPacket {
let join_game = JoinGame {
entity_id,
game_mode,
dimension,
max_players,
level_type,
view_distance,
reduced_debug_info,
};
GameClientBoundPacket::JoinGame(join_game)
}
}
impl Packet for JoinGame {
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_u32(self.view_distance as u32)?;
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_u32()? 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,
})
}
}

View File

@ -13,6 +13,7 @@ use serde_json::error::Error as JsonError;
use uuid::parser::ParseError as UuidParseError;
use crate::chat::Message;
use num_traits::{FromPrimitive, ToPrimitive};
pub mod chat;
pub mod game;
@ -128,6 +129,8 @@ trait PacketRead {
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError>;
fn read_chat_message(&mut self) -> Result<Message, DecodeError>;
fn read_enum<T: FromPrimitive>(&mut self) -> Result<T, DecodeError>;
}
/// Trait adds additional helper methods for `Write` to write protocol data.
@ -139,6 +142,8 @@ trait PacketWrite {
fn write_byte_array(&mut self, value: &[u8]) -> Result<(), EncodeError>;
fn write_chat_message(&mut self, value: &Message) -> Result<(), EncodeError>;
fn write_enum<T: ToPrimitive>(&mut self, value: &T) -> Result<(), EncodeError>;
}
impl<R: Read> PacketRead for R {
@ -178,6 +183,13 @@ impl<R: Read> PacketRead for R {
Ok(message)
}
fn read_enum<T: FromPrimitive>(&mut self) -> Result<T, DecodeError> {
let type_id = self.read_u8()?;
let result = FromPrimitive::from_u8(type_id);
result.ok_or_else(|| DecodeError::UnknownEnumType { type_id })
}
}
impl<W: Write> PacketWrite for W {
@ -214,4 +226,11 @@ impl<W: Write> PacketWrite for W {
fn write_chat_message(&mut self, value: &Message) -> Result<(), EncodeError> {
self.write_string(&value.to_json()?, STRING_MAX_LENGTH)
}
fn write_enum<T: ToPrimitive>(&mut self, value: &T) -> Result<(), EncodeError> {
let type_value = ToPrimitive::to_u8(value).unwrap();
self.write_u8(type_value)?;
Ok(())
}
}