diff --git a/protocol/src/protocol/mod.rs b/protocol/src/protocol/mod.rs index c247dba..3fcc23d 100644 --- a/protocol/src/protocol/mod.rs +++ b/protocol/src/protocol/mod.rs @@ -37,7 +37,7 @@ use flate2::Compression; use std::time::{Instant, Duration}; use crate::shared::Position; -pub const SUPPORTED_PROTOCOLS: [i32; 7] = [340, 316, 315, 210, 109, 107, 74]; +pub const SUPPORTED_PROTOCOLS: [i32; 8] = [340, 316, 315, 210, 109, 107, 74, 47]; /// Helper macro for defining packets diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index aea455f..bf87440 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -92,6 +92,13 @@ state_packets!( field displayed_skin_parts: u8 =, field main_hand: VarInt =, } + packet ClientSettings_u8_Handsfree { + field locale: String =, + field view_distance: u8 =, + field chat_mode: u8 =, + field chat_colors: bool =, + field displayed_skin_parts: u8 =, + } /// ConfirmTransactionServerbound is a reply to ConfirmTransaction. packet ConfirmTransactionServerbound { field id: u8 =, @@ -141,6 +148,13 @@ state_packets!( field target_z: f32 = when(|p: &UseEntity| p.ty.0 == 2), field hand: VarInt = when(|p: &UseEntity| p.ty.0 == 0 || p.ty.0 == 2), } + packet UseEntity_Handsfree { + field target_id: VarInt =, + field ty: VarInt =, + field target_x: f32 = when(|p: &UseEntity_Handsfree| p.ty.0 == 2), + field target_y: f32 = when(|p: &UseEntity_Handsfree| p.ty.0 == 2), + field target_z: f32 = when(|p: &UseEntity_Handsfree| p.ty.0 == 2), + } /// KeepAliveServerbound is sent by a client as a response to a /// KeepAliveClientbound. If the client doesn't reply the server /// may disconnect the client. @@ -273,6 +287,9 @@ state_packets!( packet ArmSwing { field hand: VarInt =, } + packet ArmSwing_Handsfree { + field empty: () =, + } /// SpectateTeleport is sent by clients in spectator mode to teleport to a player. packet SpectateTeleport { field target: UUID =, @@ -294,6 +311,15 @@ state_packets!( field cursor_y: u8 =, field cursor_z: u8 =, } + packet PlayerBlockPlacement_u8_Item { + field location: Position =, + field face: u8 =, + field hand: Option =, + field cursor_x: u8 =, + field cursor_y: u8 =, + field cursor_z: u8 =, + } + /// UseItem is sent when the client tries to use an item. packet UseItem { field hand: VarInt =, @@ -330,6 +356,19 @@ state_packets!( field velocity_y: i16 =, field velocity_z: i16 =, } + packet SpawnObject_i32_NoUUID { + field entity_id: VarInt =, + field ty: u8 =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field pitch: i8 =, + field yaw: i8 =, + field data: i32 =, + field velocity_x: i16 = when(|p: &SpawnObject_i32_NoUUID| p.data != 0), + field velocity_y: i16 = when(|p: &SpawnObject_i32_NoUUID| p.data != 0), + field velocity_z: i16 = when(|p: &SpawnObject_i32_NoUUID| p.data != 0), + } /// SpawnExperienceOrb spawns a single experience orb into the world when /// it is in range of the client. The count controls the amount of experience /// gained when collected. @@ -378,7 +417,7 @@ state_packets!( field velocity_x: i16 =, field velocity_y: i16 =, field velocity_z: i16 =, - field metadata: types::Metadata =, + field metadata: types::Metadata19 =, } packet SpawnMob_u8 { field entity_id: VarInt =, @@ -393,7 +432,7 @@ state_packets!( field velocity_x: i16 =, field velocity_y: i16 =, field velocity_z: i16 =, - field metadata: types::Metadata =, + field metadata: types::Metadata19 =, } packet SpawnMob_u8_i32 { field entity_id: VarInt =, @@ -408,7 +447,21 @@ state_packets!( field velocity_x: i16 =, field velocity_y: i16 =, field velocity_z: i16 =, - field metadata: types::Metadata =, + field metadata: types::Metadata19 =, + } + packet SpawnMob_u8_i32_NoUUID_18 { + field entity_id: VarInt =, + field ty: u8 =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field yaw: i8 =, + field pitch: i8 =, + field head_pitch: i8 =, + field velocity_x: i16 =, + field velocity_y: i16 =, + field velocity_z: i16 =, + field metadata: types::Metadata18 =, } /// SpawnPainting spawns a painting into the world when it is in range of /// the client. The title effects the size and the texture of the painting. @@ -436,7 +489,7 @@ state_packets!( field z: f64 =, field yaw: i8 =, field pitch: i8 =, - field metadata: types::Metadata =, + field metadata: types::Metadata19 =, } packet SpawnPlayer_i32 { field entity_id: VarInt =, @@ -446,7 +499,18 @@ state_packets!( field z: i32 =, field yaw: i8 =, field pitch: i8 =, - field metadata: types::Metadata =, + field metadata: types::Metadata19 =, + } + packet SpawnPlayer_i32_HeldItem_18 { + field entity_id: VarInt =, + field uuid: UUID =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field yaw: i8 =, + field pitch: i8 =, + field current_item: u16 =, + field metadata: types::Metadata18 =, } /// Animation is sent by the server to play an animation on a specific entity. packet Animation { @@ -664,6 +728,18 @@ state_packets!( field bitmask: VarInt =, field data: LenPrefixedBytes =, } + packet ChunkData_NoEntities_u16 { + field chunk_x: i32 =, + field chunk_z: i32 =, + field new: bool =, + field bitmask: u16 =, + field data: LenPrefixedBytes =, + } + packet ChunkDataBulk { + field skylight: bool =, + field chunk_meta: LenPrefixed =, + field chunk_data: Vec =, + } /// Effect plays a sound effect or particle at the target location with the /// volume (of sounds) being relative to the player's position unless /// DisableRelative is set to true. @@ -737,6 +813,16 @@ state_packets!( field z: Option = when(|p: &Maps| p.columns > 0), field data: Option> = when(|p: &Maps| p.columns > 0), } + packet Maps_NoTracking { + field item_damage: VarInt =, + field scale: i8 =, + field icons: LenPrefixed =, + field columns: u8 =, + field rows: Option = when(|p: &Maps_NoTracking| p.columns > 0), + field x: Option = when(|p: &Maps_NoTracking| p.columns > 0), + field z: Option = when(|p: &Maps_NoTracking| p.columns > 0), + field data: Option> = when(|p: &Maps_NoTracking| p.columns > 0), + } /// EntityMove moves the entity with the id by the offsets provided. packet EntityMove_i16 { field entity_id: VarInt =, @@ -782,6 +868,11 @@ state_packets!( packet Entity { field entity_id: VarInt =, } + /// EntityUpdateNBT updates the entity named binary tag. + packet EntityUpdateNBT { + field entity_id: VarInt =, + field nbt: Option =, + } /// Teleports the player's vehicle packet VehicleTeleport { field x: f64 =, @@ -881,6 +972,10 @@ state_packets!( field entity_id: VarInt =, field head_yaw: i8 =, } + packet EntityStatus { + field entity_id: i32 =, + field entity_status: i8 =, + } /// SelectAdvancementTab indicates the client should switch the advancement tab. packet SelectAdvancementTab { field has_id: bool =, @@ -915,7 +1010,11 @@ state_packets!( /// EntityMetadata updates the metadata for an entity. packet EntityMetadata { field entity_id: VarInt =, - field metadata: types::Metadata =, + field metadata: types::Metadata19 =, + } + packet EntityMetadata_18 { + field entity_id: VarInt =, + field metadata: types::Metadata18 =, } /// EntityAttach attaches to entities together, either by mounting or leashing. /// -1 can be used at the EntityID to deattach. @@ -944,6 +1043,11 @@ state_packets!( field slot: VarInt =, field item: Option =, } + packet EntityEquipment_u16 { + field entity_id: VarInt =, + field slot: u16 =, + field item: Option =, + } /// SetExperience updates the experience bar on the client. packet SetExperience { field experience_bar: f32 =, @@ -1266,6 +1370,29 @@ impl Serializable for BlockChangeRecord { } } +#[derive(Debug, Default)] +pub struct ChunkMeta { + pub x: i32, + pub z: i32, + pub bitmask: u16, +} + +impl Serializable for ChunkMeta { + fn read_from(buf: &mut R) -> Result { + Ok(ChunkMeta { + x: Serializable::read_from(buf)?, + z: Serializable::read_from(buf)?, + bitmask: Serializable::read_from(buf)?, + }) + } + + fn write_to(&self, buf: &mut W) -> Result<(), Error> { + self.x.write_to(buf)?; + self.z.write_to(buf)?; + self.bitmask.write_to(buf) + } +} + #[derive(Debug, Default)] pub struct ExplosionRecord { pub x: i8, diff --git a/protocol/src/protocol/versions.rs b/protocol/src/protocol/versions.rs index 259c5af..3e71b28 100644 --- a/protocol/src/protocol/versions.rs +++ b/protocol/src/protocol/versions.rs @@ -6,6 +6,7 @@ mod v1_10_2; mod v1_9_2; mod v1_9; mod v15w39c; +mod v1_8_9; pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 { match version { @@ -32,6 +33,9 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: // 15w39a/b/c 74 => v15w39c::translate_internal_packet_id(state, dir, id, to_internal), + // 1.8.9 - 1.8 + 47 => v1_8_9::translate_internal_packet_id(state, dir, id, to_internal), + _ => panic!("unsupported protocol version"), } } diff --git a/protocol/src/protocol/versions/v1_8_9.rs b/protocol/src/protocol/versions/v1_8_9.rs new file mode 100644 index 0000000..72d55ff --- /dev/null +++ b/protocol/src/protocol/versions/v1_8_9.rs @@ -0,0 +1,139 @@ +protocol_packet_ids!( + handshake Handshaking { + serverbound Serverbound { + 0x00 => Handshake + } + clientbound Clientbound { + } + } + play Play { + serverbound Serverbound { + 0x00 => KeepAliveServerbound_VarInt + 0x01 => ChatMessage + 0x02 => UseEntity_Handsfree + 0x03 => Player + 0x04 => PlayerPosition + 0x05 => PlayerLook + 0x06 => PlayerPositionLook + 0x07 => PlayerDigging_u8 + 0x08 => PlayerBlockPlacement_u8_Item + 0x09 => HeldItemChange + 0x0a => ArmSwing_Handsfree + 0x0b => PlayerAction + 0x0c => SteerVehicle + 0x0d => CloseWindow + 0x0e => ClickWindow_u8 + 0x0f => ConfirmTransactionServerbound + 0x10 => CreativeInventoryAction + 0x11 => EnchantItem + 0x12 => SetSign + 0x13 => ClientAbilities + 0x14 => TabComplete_NoAssume + 0x15 => ClientSettings_u8_Handsfree + 0x16 => ClientStatus + 0x17 => PluginMessageServerbound + 0x18 => SpectateTeleport + 0x19 => ResourcePackStatus + } + clientbound Clientbound { + 0x00 => KeepAliveClientbound_VarInt + 0x01 => JoinGame_i8 + 0x02 => ServerMessage + 0x03 => TimeUpdate + 0x04 => EntityEquipment_u16 + 0x05 => SpawnPosition + 0x06 => UpdateHealth + 0x07 => Respawn + 0x08 => TeleportPlayer_NoConfirm + 0x09 => SetCurrentHotbarSlot + 0x0a => EntityUsedBed + 0x0b => Animation + 0x0c => SpawnPlayer_i32_HeldItem_18 + 0x0d => CollectItem_nocount + 0x0e => SpawnObject_i32_NoUUID + 0x0f => SpawnMob_u8_i32_NoUUID_18 + 0x10 => SpawnPainting_NoUUID + 0x11 => SpawnExperienceOrb_i32 + 0x12 => EntityVelocity + 0x13 => EntityDestroy + 0x14 => Entity + 0x15 => EntityMove_i8 + 0x16 => EntityLook + 0x17 => EntityLookAndMove_i8 + 0x18 => EntityTeleport_i32 + 0x19 => EntityHeadLook + 0x1a => EntityStatus + 0x1b => EntityAttach_leashed + 0x1c => EntityMetadata_18 + 0x1d => EntityEffect + 0x1e => EntityRemoveEffect + 0x1f => SetExperience + 0x20 => EntityProperties + 0x21 => ChunkData_NoEntities_u16 + 0x22 => MultiBlockChange + 0x23 => BlockChange + 0x24 => BlockAction + 0x25 => BlockBreakAnimation + 0x26 => ChunkDataBulk + 0x27 => Explosion + 0x28 => Effect + 0x29 => NamedSoundEffect_u8_NoCategory + 0x2a => Particle + 0x2b => ChangeGameState + 0x2c => SpawnGlobalEntity_i32 + 0x2d => WindowOpen + 0x2e => WindowClose + 0x2f => WindowSetSlot + 0x30 => WindowItems + 0x31 => WindowProperty + 0x32 => ConfirmTransaction + 0x33 => UpdateSign + 0x34 => Maps_NoTracking + 0x35 => UpdateBlockEntity + 0x36 => SignEditorOpen + 0x37 => Statistics + 0x38 => PlayerInfo + 0x39 => PlayerAbilities + 0x3a => TabCompleteReply + 0x3b => ScoreboardObjective + 0x3c => UpdateScore + 0x3d => ScoreboardDisplay + 0x3e => Teams + 0x3f => PluginMessageClientbound + 0x40 => Disconnect + 0x41 => ServerDifficulty + 0x42 => CombatEvent + 0x43 => Camera + 0x44 => WorldBorder + 0x45 => Title_notext_component + 0x46 => SetCompression + 0x47 => PlayerListHeaderFooter + 0x48 => ResourcePackSend + 0x49 => EntityUpdateNBT + } + } + login Login { + serverbound Serverbound { + 0x00 => LoginStart + 0x01 => EncryptionResponse + } + clientbound Clientbound { + 0x00 => LoginDisconnect + 0x01 => EncryptionRequest + 0x02 => LoginSuccess + 0x03 => SetInitialCompression + } + } + status Status { + serverbound Serverbound { + 0x00 => StatusRequest + 0x01 => StatusPing + } + clientbound Clientbound { + 0x00 => StatusResponse + 0x01 => StatusPong + } + } +); + +