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 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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
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 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(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user