diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 4a31c74..8103dec 100644 --- a/src/protocol/mod.rs +++ b/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; 3] = [340, 316, 315]; +pub const SUPPORTED_PROTOCOLS: [i32; 4] = [340, 316, 315, 210]; /// Helper macro for defining packets diff --git a/src/protocol/packet.rs b/src/protocol/packet.rs index 94a60e2..42ea33d 100644 --- a/src/protocol/packet.rs +++ b/src/protocol/packet.rs @@ -248,7 +248,7 @@ state_packets!( field target: UUID =, } /// PlayerBlockPlacement is sent when the client tries to place a block. - packet PlayerBlockPlacement { + packet PlayerBlockPlacement_f32 { field location: Position =, field face: VarInt =, field hand: VarInt =, @@ -256,6 +256,14 @@ state_packets!( field cursor_y: f32 =, field cursor_z: f32 =, } + packet PlayerBlockPlacement_u8 { + field location: Position =, + field face: VarInt =, + field hand: VarInt =, + 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 =, @@ -314,6 +322,21 @@ state_packets!( field velocity_z: i16 =, field metadata: types::Metadata =, } + packet SpawnMob_u8 { + field entity_id: VarInt =, + field uuid: UUID =, + field ty: u8 =, + field x: f64 =, + field y: f64 =, + field z: f64 =, + 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::Metadata =, + } /// 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. packet SpawnPainting { @@ -826,6 +849,14 @@ state_packets!( field fade_stay: Option = when(|p: &Title| p.action.0 == 3), field fade_out: Option = when(|p: &Title| p.action.0 == 3), } + packet Title_notext { + field action: VarInt =, + field title: Option = when(|p: &Title_notext| p.action.0 == 0), + field sub_title: Option = when(|p: &Title_notext| p.action.0 == 1), + field fade_in: Option = when(|p: &Title_notext| p.action.0 == 2), + field fade_stay: Option = when(|p: &Title_notext| p.action.0 == 2), + field fade_out: Option = when(|p: &Title_notext| p.action.0 == 2), + } /// SoundEffect plays the named sound at the target location. packet SoundEffect { field name: VarInt =, @@ -848,6 +879,10 @@ state_packets!( field collector_entity_id: VarInt =, field number_of_items: VarInt =, } + packet CollectItem_nocount { + field collected_entity_id: VarInt =, + field collector_entity_id: VarInt =, + } /// EntityTeleport teleports the entity to the target location. This is /// sent if the entity moves further than EntityMove allows. packet EntityTeleport { diff --git a/src/protocol/versions.rs b/src/protocol/versions.rs index ce355d6..63bb6c1 100644 --- a/src/protocol/versions.rs +++ b/src/protocol/versions.rs @@ -2,6 +2,7 @@ use crate::protocol::*; mod v1_12_2; mod v1_11_2; +mod v1_10_2; pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 { match version { @@ -16,6 +17,9 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: // 1.11 315 => v1_11_2::translate_internal_packet_id(state, dir, id, to_internal), + // 1.10.2 + 210 => v1_10_2::translate_internal_packet_id(state, dir, id, to_internal), + _ => panic!("unsupported protocol version"), } } diff --git a/src/protocol/versions/v1_10_2.rs b/src/protocol/versions/v1_10_2.rs new file mode 100644 index 0000000..add7478 --- /dev/null +++ b/src/protocol/versions/v1_10_2.rs @@ -0,0 +1,145 @@ +protocol_packet_ids!( + handshake Handshaking { + serverbound Serverbound { + 0x00 => Handshake + } + clientbound Clientbound { + } + } + play Play { + serverbound Serverbound { + 0x00 => TeleportConfirm + 0x01 => TabComplete + 0x02 => ChatMessage + 0x03 => ClientStatus + 0x04 => ClientSettings + 0x05 => ConfirmTransactionServerbound + 0x06 => EnchantItem + 0x07 => ClickWindow + 0x08 => CloseWindow + 0x09 => PluginMessageServerbound + 0x0a => UseEntity + 0x0b => KeepAliveServerbound_VarInt + 0x0c => PlayerPosition + 0x0d => PlayerPositionLook + 0x0e => PlayerLook + 0x0f => Player + 0x10 => VehicleMove + 0x11 => SteerBoat + 0x12 => ClientAbilities + 0x13 => PlayerDigging + 0x14 => PlayerAction + 0x15 => SteerVehicle + 0x16 => ResourcePackStatus + 0x17 => HeldItemChange + 0x18 => CreativeInventoryAction + 0x19 => SetSign + 0x1a => ArmSwing + 0x1b => SpectateTeleport + 0x1c => PlayerBlockPlacement_u8 + 0x1d => UseItem + } + clientbound Clientbound { + 0x00 => SpawnObject + 0x01 => SpawnExperienceOrb + 0x02 => SpawnGlobalEntity + 0x03 => SpawnMob_u8 + 0x04 => SpawnPainting + 0x05 => SpawnPlayer + 0x06 => Animation + 0x07 => Statistics + 0x08 => BlockBreakAnimation + 0x09 => UpdateBlockEntity + 0x0a => BlockAction + 0x0b => BlockChange + 0x0c => BossBar + 0x0d => ServerDifficulty + 0x0e => TabCompleteReply + 0x0f => ServerMessage + 0x10 => MultiBlockChange + 0x11 => ConfirmTransaction + 0x12 => WindowClose + 0x13 => WindowOpen + 0x14 => WindowItems + 0x15 => WindowProperty + 0x16 => WindowSetSlot + 0x17 => SetCooldown + 0x18 => PluginMessageClientbound + 0x19 => NamedSoundEffect + 0x1a => Disconnect + 0x1b => EntityAction + 0x1c => Explosion + 0x1d => ChunkUnload + 0x1e => ChangeGameState + 0x1f => KeepAliveClientbound_VarInt + 0x20 => ChunkData + 0x21 => Effect + 0x22 => Particle + 0x23 => JoinGame + 0x24 => Maps + 0x25 => EntityMove + 0x26 => EntityLookAndMove + 0x27 => EntityLook + 0x28 => Entity + 0x29 => VehicleTeleport + 0x2a => SignEditorOpen + 0x2b => PlayerAbilities + 0x2c => CombatEvent + 0x2d => PlayerInfo + 0x2e => TeleportPlayer + 0x2f => EntityUsedBed + 0x30 => EntityDestroy + 0x31 => EntityRemoveEffect + 0x32 => ResourcePackSend + 0x33 => Respawn + 0x34 => EntityHeadLook + 0x35 => WorldBorder + 0x36 => Camera + 0x37 => SetCurrentHotbarSlot + 0x38 => ScoreboardDisplay + 0x39 => EntityMetadata + 0x3a => EntityAttach + 0x3b => EntityVelocity + 0x3c => EntityEquipment + 0x3d => SetExperience + 0x3e => UpdateHealth + 0x3f => ScoreboardObjective + 0x40 => SetPassengers + 0x41 => Teams + 0x42 => UpdateScore + 0x43 => SpawnPosition + 0x44 => TimeUpdate + 0x45 => Title_notext + 0x46 => SoundEffect + 0x47 => PlayerListHeaderFooter + 0x48 => CollectItem_nocount + 0x49 => EntityTeleport + 0x4a => EntityProperties + 0x4b => EntityEffect + } + } + 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 + } + } +); + + diff --git a/src/protocol/versions/v1_11_2.rs b/src/protocol/versions/v1_11_2.rs index 02dc201..2bd0271 100644 --- a/src/protocol/versions/v1_11_2.rs +++ b/src/protocol/versions/v1_11_2.rs @@ -36,7 +36,7 @@ protocol_packet_ids!( 0x19 => SetSign 0x1a => ArmSwing 0x1b => SpectateTeleport - 0x1c => PlayerBlockPlacement + 0x1c => PlayerBlockPlacement_f32 0x1d => UseItem } clientbound Clientbound { diff --git a/src/protocol/versions/v1_12_2.rs b/src/protocol/versions/v1_12_2.rs index d4ceb8d..39a7539 100644 --- a/src/protocol/versions/v1_12_2.rs +++ b/src/protocol/versions/v1_12_2.rs @@ -39,7 +39,7 @@ protocol_packet_ids!( 0x1c => SetSign 0x1d => ArmSwing 0x1e => SpectateTeleport - 0x1f => PlayerBlockPlacement + 0x1f => PlayerBlockPlacement_f32 0x20 => UseItem } clientbound Clientbound { diff --git a/src/server/mod.rs b/src/server/mod.rs index 0230c92..5880096 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -41,6 +41,7 @@ pub mod target; pub struct Server { uuid: protocol::UUID, conn: Option, + protocol_version: i32, read_queue: Option>>, pub disconnect_reason: Option, just_disconnected: bool, @@ -137,7 +138,7 @@ impl Server { read.state = protocol::State::Play; write.state = protocol::State::Play; let rx = Self::spawn_reader(read); - return Ok(Server::new(protocol::UUID::from_str(&val.uuid), resources, Some(write), Some(rx))); + return Ok(Server::new(protocol_version, protocol::UUID::from_str(&val.uuid), resources, Some(write), Some(rx))); } protocol::packet::Packet::LoginDisconnect(val) => return Err(protocol::Error::Disconnect(val.reason)), val => return Err(protocol::Error::Err(format!("Wrong packet: {:?}", val))), @@ -191,7 +192,7 @@ impl Server { let rx = Self::spawn_reader(read); - Ok(Server::new(protocol::UUID::from_str(&uuid), resources, Some(write), Some(rx))) + Ok(Server::new(protocol_version, protocol::UUID::from_str(&uuid), resources, Some(write), Some(rx))) } fn spawn_reader(mut read: protocol::Conn) -> mpsc::Receiver> { @@ -212,7 +213,7 @@ impl Server { } pub fn dummy_server(resources: Arc>) -> Server { - let mut server = Server::new(protocol::UUID::default(), resources, None, None); + let mut server = Server::new(protocol::SUPPORTED_PROTOCOLS[0], protocol::UUID::default(), resources, None, None); let mut rng = rand::thread_rng(); for x in -7*16 .. 7*16 { for z in -7*16 .. 7*16 { @@ -248,6 +249,7 @@ impl Server { } fn new( + protocol_version: i32, uuid: protocol::UUID, resources: Arc>, conn: Option, read_queue: Option>> @@ -263,6 +265,7 @@ impl Server { Server { uuid, conn, + protocol_version, read_queue, disconnect_reason: None, just_disconnected: false, @@ -513,22 +516,41 @@ impl Server { use crate::shared::Direction; if self.player.is_some() { if let Some((pos, _, face, at)) = target::trace_ray(&self.world, 4.0, renderer.camera.pos.to_vec(), renderer.view_vector.cast().unwrap(), target::test_block) { - self.write_packet(packet::play::serverbound::PlayerBlockPlacement { - location: pos, - face: protocol::VarInt(match face { - Direction::Down => 0, - Direction::Up => 1, - Direction::North => 2, - Direction::South => 3, - Direction::West => 4, - Direction::East => 5, - _ => unreachable!(), - }), - hand: protocol::VarInt(0), - cursor_x: at.x as f32, - cursor_y: at.y as f32, - cursor_z: at.z as f32 - }); + if self.protocol_version >= 315 { + self.write_packet(packet::play::serverbound::PlayerBlockPlacement_f32 { + location: pos, + face: protocol::VarInt(match face { + Direction::Down => 0, + Direction::Up => 1, + Direction::North => 2, + Direction::South => 3, + Direction::West => 4, + Direction::East => 5, + _ => unreachable!(), + }), + hand: protocol::VarInt(0), + cursor_x: at.x as f32, + cursor_y: at.y as f32, + cursor_z: at.z as f32, + }); + } else { + self.write_packet(packet::play::serverbound::PlayerBlockPlacement_u8 { + location: pos, + face: protocol::VarInt(match face { + Direction::Down => 0, + Direction::Up => 1, + Direction::North => 2, + Direction::South => 3, + Direction::West => 4, + Direction::East => 5, + _ => unreachable!(), + }), + hand: protocol::VarInt(0), + cursor_x: (at.x * 16.0) as u8, + cursor_y: (at.y * 16.0) as u8, + cursor_z: (at.z * 16.0) as u8, + }); + } } } }