Add join game packet
This commit is contained in:
parent
61d3c950b3
commit
0838c3688d
102
src/game.rs
102
src/game.rs
@ -1,13 +1,14 @@
|
|||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
|
||||||
|
|
||||||
use crate::chat::Message;
|
use crate::chat::Message;
|
||||||
use crate::{DecodeError, EncodeError, Packet, PacketRead, PacketWrite};
|
use crate::{DecodeError, EncodeError, Packet, PacketRead, PacketWrite};
|
||||||
|
use mc_varint::{VarIntRead, VarIntWrite};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
pub enum GameServerBoundPacket {
|
pub enum GameServerBoundPacket {
|
||||||
ServerBoundChatMessage(ServerBoundChatMessage),
|
ServerBoundChatMessage(ServerBoundChatMessage),
|
||||||
@ -15,6 +16,7 @@ pub enum GameServerBoundPacket {
|
|||||||
|
|
||||||
pub enum GameClientBoundPacket {
|
pub enum GameClientBoundPacket {
|
||||||
ClientBoundChatMessage(ClientBoundChatMessage),
|
ClientBoundChatMessage(ClientBoundChatMessage),
|
||||||
|
JoinGame(JoinGame),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameServerBoundPacket {
|
impl GameServerBoundPacket {
|
||||||
@ -40,6 +42,7 @@ impl GameClientBoundPacket {
|
|||||||
pub fn get_type_id(&self) -> u8 {
|
pub fn get_type_id(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
GameClientBoundPacket::ClientBoundChatMessage(_) => 0x0E,
|
GameClientBoundPacket::ClientBoundChatMessage(_) => 0x0E,
|
||||||
|
GameClientBoundPacket::JoinGame(_) => 0x25,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +53,11 @@ impl GameClientBoundPacket {
|
|||||||
|
|
||||||
Ok(GameClientBoundPacket::ClientBoundChatMessage(chat_message))
|
Ok(GameClientBoundPacket::ClientBoundChatMessage(chat_message))
|
||||||
}
|
}
|
||||||
|
0x25 => {
|
||||||
|
let join_game = JoinGame::decode(reader)?;
|
||||||
|
|
||||||
|
Ok(GameClientBoundPacket::JoinGame(join_game))
|
||||||
|
}
|
||||||
_ => Err(DecodeError::UnknownPacketType { type_id }),
|
_ => Err(DecodeError::UnknownPacketType { type_id }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,23 +114,97 @@ impl Packet for ClientBoundChatMessage {
|
|||||||
|
|
||||||
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
||||||
writer.write_chat_message(&self.message)?;
|
writer.write_chat_message(&self.message)?;
|
||||||
writer.write_u8(ToPrimitive::to_u8(&self.position).unwrap())?;
|
writer.write_enum(&self.position)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
|
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
|
||||||
let message = reader.read_chat_message()?;
|
let message = reader.read_chat_message()?;
|
||||||
let position_type_id = reader.read_u8()?;
|
let position = reader.read_enum()?;
|
||||||
|
|
||||||
let position = FromPrimitive::from_u8(position_type_id).ok_or_else(|| {
|
|
||||||
DecodeError::UnknownEnumType {
|
|
||||||
type_id: position_type_id,
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let chat_message = ClientBoundChatMessage { message, position };
|
let chat_message = ClientBoundChatMessage { message, position };
|
||||||
|
|
||||||
Ok(chat_message)
|
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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
19
src/lib.rs
19
src/lib.rs
@ -13,6 +13,7 @@ use serde_json::error::Error as JsonError;
|
|||||||
use uuid::parser::ParseError as UuidParseError;
|
use uuid::parser::ParseError as UuidParseError;
|
||||||
|
|
||||||
use crate::chat::Message;
|
use crate::chat::Message;
|
||||||
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
|
|
||||||
pub mod chat;
|
pub mod chat;
|
||||||
pub mod game;
|
pub mod game;
|
||||||
@ -128,6 +129,8 @@ trait PacketRead {
|
|||||||
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError>;
|
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError>;
|
||||||
|
|
||||||
fn read_chat_message(&mut self) -> Result<Message, 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.
|
/// 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_byte_array(&mut self, value: &[u8]) -> Result<(), EncodeError>;
|
||||||
|
|
||||||
fn write_chat_message(&mut self, value: &Message) -> 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 {
|
impl<R: Read> PacketRead for R {
|
||||||
@ -178,6 +183,13 @@ impl<R: Read> PacketRead for R {
|
|||||||
|
|
||||||
Ok(message)
|
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 {
|
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> {
|
fn write_chat_message(&mut self, value: &Message) -> Result<(), EncodeError> {
|
||||||
self.write_string(&value.to_json()?, STRING_MAX_LENGTH)
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user