diff --git a/protocol/src/decoder.rs b/protocol/src/decoder.rs index 0b4f102..fee6ddf 100644 --- a/protocol/src/decoder.rs +++ b/protocol/src/decoder.rs @@ -222,6 +222,22 @@ impl Decoder for Vec { } } +impl Decoder for Vec { + type Output = Self; + + fn decode(reader: &mut R) -> Result { + let length = reader.read_var_i32()? as usize; + let mut vec = Vec::with_capacity(length); + + for _ in 0..length { + let identifier = reader.read_string(32767)?; + vec.push(identifier); + } + + Ok(vec) + } +} + pub mod var_int { use crate::decoder::DecoderReadExt; use crate::error::DecodeError; @@ -261,8 +277,17 @@ pub mod uuid_hyp_str { use uuid::Uuid; pub fn decode(reader: &mut R) -> Result { - let uuid_hyphenated_string = reader.read_string(36)?; - let uuid = Uuid::parse_str(&uuid_hyphenated_string)?; + // TODO(timvisee): use custom encoder for this, rather than putting this in uuid_hyp_str + + let data = [reader.read_var_i64()?, reader.read_var_i64()?]; + + // TODO(timvisee): remove unsafe + let raw = unsafe { std::mem::transmute(data) }; + + let uuid = Uuid::from_bytes(raw); + + // let uuid_hyphenated_string = reader.read_string(36)?; + // let uuid = Uuid::parse_str(&uuid_hyphenated_string)?; Ok(uuid) } diff --git a/protocol/src/encoder.rs b/protocol/src/encoder.rs index 906f9c8..8c43c45 100644 --- a/protocol/src/encoder.rs +++ b/protocol/src/encoder.rs @@ -183,7 +183,7 @@ impl Encoder for Vec { } } -// TODO: identifier encoder, we might want a custom type +// TODO(timvisee): identifier encoder, we might want a custom type impl Encoder for Vec { fn encode(&self, writer: &mut W) -> Result<(), EncodeError> { writer.write_var_i32(self.len() as i32)?; @@ -196,19 +196,6 @@ impl Encoder for Vec { } } -// TODO: BitSet encoder, implement this -// TODO: impl Encoder for Vec { -// TODO: fn encode(&self, writer: &mut W) -> Result<(), EncodeError> { -// TODO: writer.write_var_i32(self.len() as i32)?; - -// TODO: for mask in self { -// TODO: writer.write_i64::(*mask)? -// TODO: } - -// TODO: Ok(()) -// TODO: } -// TODO: } - pub mod var_int { use crate::encoder::EncoderWriteExt; use crate::error::EncodeError; @@ -251,7 +238,7 @@ pub mod uuid_hyp_str { use uuid::{Uuid, Version}; pub fn encode(value: &Uuid, writer: &mut W) -> Result<(), EncodeError> { - // TODO: use custom encoder for this, rather than putting this in uuid_hyp_str + // TODO(timvisee): use custom encoder for this, rather than putting this in uuid_hyp_str match value.get_version() { Some(Version::Md5) => { writer.write_all(value.as_bytes())?; diff --git a/protocol/src/version/v1_17_1/game.rs b/protocol/src/version/v1_17_1/game.rs index b9b7b34..52caaaa 100644 --- a/protocol/src/version/v1_17_1/game.rs +++ b/protocol/src/version/v1_17_1/game.rs @@ -27,8 +27,13 @@ pub enum GameClientBoundPacket { BossBar(BossBar), EntityAction(EntityAction), + Respawn(Respawn), PlayerPositionAndLook(PlayerPositionAndLook), + SpawnPosition(SpawnPosition), + SetTitleSubtitle(SetTitleSubtitle), + SetTitleText(SetTitleText), TimeUpdate(TimeUpdate), + SetTitleTimes(SetTitleTimes), } impl GameServerBoundPacket { @@ -68,7 +73,12 @@ impl GameClientBoundPacket { GameClientBoundPacket::BossBar(_) => 0x0D, GameClientBoundPacket::EntityAction(_) => 0x1B, GameClientBoundPacket::PlayerPositionAndLook(_) => 0x38, + GameClientBoundPacket::Respawn(_) => 0x3D, + GameClientBoundPacket::SpawnPosition(_) => 0x4B, + GameClientBoundPacket::SetTitleSubtitle(_) => 0x57, GameClientBoundPacket::TimeUpdate(_) => 0x58, + GameClientBoundPacket::SetTitleText(_) => 0x59, + GameClientBoundPacket::SetTitleTimes(_) => 0x5A, } } @@ -94,31 +104,56 @@ impl GameClientBoundPacket { Ok(GameClientBoundPacket::ChunkData(chunk_data)) } - // TODO: 0x25 => { - // TODO: let join_game = JoinGame::decode(reader)?; + 0x25 => { + let join_game = JoinGame::decode(reader)?; - // TODO: Ok(GameClientBoundPacket::JoinGame(join_game)) - // TODO: } - // TODO: 0x38 => { - // TODO: let player_position = PlayerPositionAndLook::decode(reader)?; + Ok(GameClientBoundPacket::JoinGame(join_game)) + } + 0x3D => { + let respawn = Respawn::decode(reader)?; - // TODO: Ok(GameClientBoundPacket::PlayerPositionAndLook( - // TODO: player_position, - // TODO: )) - // TODO: } - // TODO: 0x58 => { - // TODO: let time_update = TimeUpdate::decode(reader)?; + Ok(GameClientBoundPacket::Respawn(respawn)) + } + 0x38 => { + let player_position = PlayerPositionAndLook::decode(reader)?; - // TODO: Ok(GameClientBoundPacket::TimeUpdate(time_update)) - // TODO: } + Ok(GameClientBoundPacket::PlayerPositionAndLook( + player_position, + )) + } + 0x4B => { + let spawn_position = SpawnPosition::decode(reader)?; + + Ok(GameClientBoundPacket::SpawnPosition(spawn_position)) + } + 0x57 => { + let title_subtitle = SetTitleSubtitle::decode(reader)?; + + Ok(GameClientBoundPacket::SetTitleSubtitle(title_subtitle)) + } + 0x58 => { + let time_update = TimeUpdate::decode(reader)?; + + Ok(GameClientBoundPacket::TimeUpdate(time_update)) + } + 0x59 => { + let title_text = SetTitleText::decode(reader)?; + + Ok(GameClientBoundPacket::SetTitleText(title_text)) + } + 0x5A => { + let title_times = SetTitleTimes::decode(reader)?; + + Ok(GameClientBoundPacket::SetTitleTimes(title_times)) + } _ => Err(DecodeError::UnknownPacketType { type_id }), } } } -// TODO: implement decoder -// TODO: implement new() -#[derive(Encoder, Debug)] +// TODO(timvisee): implement new() +// TODO(timvisee): remove clone? +#[derive(Clone, Encoder, Decoder, Debug)] pub struct JoinGame { pub entity_id: u32, pub hardcore: bool, @@ -139,9 +174,21 @@ pub struct JoinGame { pub is_flat: bool, } -// TODO: implement decoder -// TODO: implement new() -#[derive(Encoder, Debug)] +// TODO(timvisee): implement new() +#[derive(Encoder, Decoder, Debug)] +pub struct Respawn { + pub dimension: CompoundTag, + pub world_name: String, + pub hashed_seed: i64, + pub game_mode: u8, + pub previous_game_mode: u8, + pub is_debug: bool, + pub is_flat: bool, + pub copy_metadata: bool, +} + +// TODO(timvisee): implement new() +#[derive(Encoder, Decoder, Debug)] pub struct PlayerPositionAndLook { pub x: f64, pub y: f64, @@ -154,9 +201,8 @@ pub struct PlayerPositionAndLook { pub dismount_vehicle: bool, } -// TODO: implement decoder -// TODO: implement new() -#[derive(Encoder, Debug)] +// TODO(timvisee): implement new() +#[derive(Encoder, Decoder, Debug)] pub struct TimeUpdate { pub world_age: i64, pub time_of_day: i64, @@ -184,27 +230,3 @@ pub struct SpawnPosition { pub position: u64, pub angle: f32, } - -// TODO: implement decoder -// TODO: implement new() -// #[derive(Encoder, Debug)] -// pub struct ChunkData { -// pub x: i32, -// pub z: i32, -// // TODO: should be BitSet type! -// pub primary_mask: Vec, -// pub heightmaps: CompoundTag, - -// #[data_type(with = "var_int_array")] -// pub biomes: Vec, - -// // TODO: extract this from block_entities with sized datatype -// #[data_type(with = "var_int")] -// pub data_size: i32, -// pub data: Vec, - -// // TODO: extract this from block_entities with sized datatype -// #[data_type(with = "var_int")] -// pub block_entities_size: i32, -// pub block_entities: Vec, -// }