From 3f5024d4ec901166b53af24e59fe4d94cc8ad2c4 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Mon, 3 Dec 2018 19:29:02 -0800 Subject: [PATCH] Add 15w39c (74) multiprotocol support (#56) Closes https://github.com/iceiix/steven/pull/17 This is the biggest multi-protocol change yet, adding many new packet variants and implementing the most, necessitating a respectable amount of refactoring. The last of the "easy" protocols (already implemented, and cribbed from Steven commit history). For https://github.com/iceiix/steven/issues/18 Enhance protocol support * Add 15w39c packet IDs * Add 15w39c packet changes * Implement EntityMove i16 and i8 packet variants * Implement EntityLookAndMove i16 and i8 packet variants * Implement TeleportPlayer no confirm / with confirm packet variants * Implement EntityTeleport f64 and i32 packet variants * Implement SpawnPlayer f64 and i32 packet variants --- src/protocol/mod.rs | 2 +- src/protocol/packet.rs | 153 ++++++++++++++++++++++++++++++- src/protocol/versions.rs | 4 + src/protocol/versions/v15w39c.rs | 141 ++++++++++++++++++++++++++++ src/protocol/versions/v1_10_2.rs | 10 +- src/protocol/versions/v1_11_2.rs | 10 +- src/protocol/versions/v1_12_2.rs | 10 +- src/protocol/versions/v1_9.rs | 10 +- src/protocol/versions/v1_9_2.rs | 10 +- src/server/mod.rs | 151 ++++++++++++++++++++---------- 10 files changed, 420 insertions(+), 81 deletions(-) create mode 100644 src/protocol/versions/v15w39c.rs diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 48f12db..5c337fb 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; 6] = [340, 316, 315, 210, 109, 107]; +pub const SUPPORTED_PROTOCOLS: [i32; 7] = [340, 316, 315, 210, 109, 107, 74]; /// Helper macro for defining packets diff --git a/src/protocol/packet.rs b/src/protocol/packet.rs index 23c234b..aea455f 100644 --- a/src/protocol/packet.rs +++ b/src/protocol/packet.rs @@ -61,6 +61,11 @@ state_packets!( field has_target: bool =, field target: Option = when(|p: &TabComplete| p.has_target), } + packet TabComplete_NoAssume { + field text: String =, + field has_target: bool =, + field target: Option = when(|p: &TabComplete_NoAssume| p.has_target), + } /// ChatMessage is sent by the client when it sends a chat message or /// executes a command (prefixed by '/'). packet ChatMessage { @@ -79,6 +84,14 @@ state_packets!( field displayed_skin_parts: u8 =, field main_hand: VarInt =, } + packet ClientSettings_u8 { + field locale: String =, + field view_distance: u8 =, + field chat_mode: u8 =, + field chat_colors: bool =, + field displayed_skin_parts: u8 =, + field main_hand: VarInt =, + } /// ConfirmTransactionServerbound is a reply to ConfirmTransaction. packet ConfirmTransactionServerbound { field id: u8 =, @@ -99,6 +112,14 @@ state_packets!( field mode: VarInt =, field clicked_item: Option =, } + packet ClickWindow_u8 { + field id: u8 =, + field slot: i16 =, + field button: u8 =, + field action_number: u16 =, + field mode: u8 =, + field clicked_item: Option =, + } /// CloseWindow is sent when the client closes a window. packet CloseWindow { field id: u8 =, @@ -189,6 +210,11 @@ state_packets!( field location: Position =, field face: u8 =, } + packet PlayerDigging_u8 { + field status: u8 =, + field location: Position =, + field face: u8 =, + } /// PlayerAction is sent when a player preforms various actions. packet PlayerAction { field entity_id: VarInt =, @@ -290,6 +316,20 @@ state_packets!( field velocity_y: i16 =, field velocity_z: i16 =, } + packet SpawnObject_i32 { + field entity_id: VarInt =, + field uuid: UUID =, + 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 =, + field velocity_y: i16 =, + field velocity_z: i16 =, + } /// 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. @@ -300,6 +340,13 @@ state_packets!( field z: f64 =, field count: i16 =, } + packet SpawnExperienceOrb_i32 { + field entity_id: VarInt =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field count: i16 =, + } /// SpawnGlobalEntity spawns an entity which is visible from anywhere in the /// world. Currently only used for lightning. packet SpawnGlobalEntity { @@ -309,6 +356,13 @@ state_packets!( field y: f64 =, field z: f64 =, } + packet SpawnGlobalEntity_i32 { + field entity_id: VarInt =, + field ty: u8 =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + } /// SpawnMob is used to spawn a living entity into the world when it is in /// range of the client. packet SpawnMob { @@ -341,6 +395,21 @@ state_packets!( field velocity_z: i16 =, field metadata: types::Metadata =, } + packet SpawnMob_u8_i32 { + field entity_id: VarInt =, + field uuid: UUID =, + 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::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 { @@ -350,10 +419,16 @@ state_packets!( field location: Position =, field direction: u8 =, } + packet SpawnPainting_NoUUID { + field entity_id: VarInt =, + field title: String =, + field location: Position =, + field direction: u8 =, + } /// SpawnPlayer is used to spawn a player when they are in range of the client. /// This packet alone isn't enough to display the player as the skin and username /// information is in the player information packet. - packet SpawnPlayer { + packet SpawnPlayer_f64 { field entity_id: VarInt =, field uuid: UUID =, field x: f64 =, @@ -363,6 +438,16 @@ state_packets!( field pitch: i8 =, field metadata: types::Metadata =, } + packet SpawnPlayer_i32 { + field entity_id: VarInt =, + field uuid: UUID =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field yaw: i8 =, + field pitch: i8 =, + field metadata: types::Metadata =, + } /// Animation is sent by the server to play an animation on a specific entity. packet Animation { field entity_id: VarInt =, @@ -506,6 +591,14 @@ state_packets!( field volume: f32 =, field pitch: u8 =, } + packet NamedSoundEffect_u8_NoCategory { + field name: String =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field volume: f32 =, + field pitch: u8 =, + } /// Disconnect causes the client to disconnect displaying the passed reason. packet Disconnect { field reason: format::Component =, @@ -534,6 +627,10 @@ state_packets!( field x: i32 =, field z: i32 =, } + /// SetCompression updates the compression threshold. + packet SetCompression { + field threshold: VarInt =, + } /// ChangeGameState is used to modify the game's state like gamemode or /// weather. packet ChangeGameState { @@ -641,15 +738,22 @@ state_packets!( field data: Option> = when(|p: &Maps| p.columns > 0), } /// EntityMove moves the entity with the id by the offsets provided. - packet EntityMove { + packet EntityMove_i16 { field entity_id: VarInt =, field delta_x: i16 =, field delta_y: i16 =, field delta_z: i16 =, field on_ground: bool =, } + packet EntityMove_i8 { + field entity_id: VarInt =, + field delta_x: i8 =, + field delta_y: i8 =, + field delta_z: i8 =, + field on_ground: bool =, + } /// EntityLookAndMove is a combination of EntityMove and EntityLook. - packet EntityLookAndMove { + packet EntityLookAndMove_i16 { field entity_id: VarInt =, field delta_x: i16 =, field delta_y: i16 =, @@ -658,6 +762,15 @@ state_packets!( field pitch: i8 =, field on_ground: bool =, } + packet EntityLookAndMove_i8 { + field entity_id: VarInt =, + field delta_x: i8 =, + field delta_y: i8 =, + field delta_z: i8 =, + field yaw: i8 =, + field pitch: i8 =, + field on_ground: bool =, + } /// EntityLook rotates the entity to the new angles provided. packet EntityLook { field entity_id: VarInt =, @@ -711,7 +824,7 @@ state_packets!( /// TeleportPlayer is sent to change the player's position. The client is expected /// to reply to the server with the same positions as contained in this packet /// otherwise will reject future packets. - packet TeleportPlayer { + packet TeleportPlayer_WithConfirm { field x: f64 =, field y: f64 =, field z: f64 =, @@ -720,6 +833,14 @@ state_packets!( field flags: u8 =, field teleport_id: VarInt =, } + packet TeleportPlayer_NoConfirm { + field x: f64 =, + field y: f64 =, + field z: f64 =, + field yaw: f32 =, + field pitch: f32 =, + field flags: u8 =, + } /// EntityUsedBed is sent by the server when a player goes to bed. packet EntityUsedBed { field entity_id: VarInt =, @@ -802,6 +923,11 @@ state_packets!( field entity_id: i32 =, field vehicle: i32 =, } + packet EntityAttach_leashed { + field entity_id: i32 =, + field vehicle: i32 =, + field leash: bool =, + } /// EntityVelocity sets the velocity of an entity in 1/8000 of a block /// per a tick. packet EntityVelocity { @@ -894,6 +1020,14 @@ state_packets!( field fade_stay: Option = when(|p: &Title_notext| p.action.0 == 2), field fade_out: Option = when(|p: &Title_notext| p.action.0 == 2), } + packet Title_notext_component { + field action: VarInt =, + field title: Option = when(|p: &Title_notext_component| p.action.0 == 0), + field sub_title: Option = when(|p: &Title_notext_component| p.action.0 == 1), + field fade_in: Option = when(|p: &Title_notext_component| p.action.0 == 2), + field fade_stay: Option = when(|p: &Title_notext_component| p.action.0 == 2), + field fade_out: Option = when(|p: &Title_notext_component| p.action.0 == 2), + } /// UpdateSign sets or changes the text on a sign. packet UpdateSign { field location: Position =, @@ -939,7 +1073,7 @@ state_packets!( } /// EntityTeleport teleports the entity to the target location. This is /// sent if the entity moves further than EntityMove allows. - packet EntityTeleport { + packet EntityTeleport_f64 { field entity_id: VarInt =, field x: f64 =, field y: f64 =, @@ -948,6 +1082,15 @@ state_packets!( field pitch: i8 =, field on_ground: bool =, } + packet EntityTeleport_i32 { + field entity_id: VarInt =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field yaw: i8 =, + field pitch: i8 =, + field on_ground: bool =, + } packet Advancements { field reset_clear: bool =, field mapping: LenPrefixed =, diff --git a/src/protocol/versions.rs b/src/protocol/versions.rs index ea8d955..259c5af 100644 --- a/src/protocol/versions.rs +++ b/src/protocol/versions.rs @@ -5,6 +5,7 @@ mod v1_11_2; mod v1_10_2; mod v1_9_2; mod v1_9; +mod v15w39c; pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 { match version { @@ -28,6 +29,9 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: // 1.9 107 => v1_9::translate_internal_packet_id(state, dir, id, to_internal), + // 15w39a/b/c + 74 => v15w39c::translate_internal_packet_id(state, dir, id, to_internal), + _ => panic!("unsupported protocol version"), } } diff --git a/src/protocol/versions/v15w39c.rs b/src/protocol/versions/v15w39c.rs new file mode 100644 index 0000000..35847be --- /dev/null +++ b/src/protocol/versions/v15w39c.rs @@ -0,0 +1,141 @@ +protocol_packet_ids!( + handshake Handshaking { + serverbound Serverbound { + 0x00 => Handshake + } + clientbound Clientbound { + } + } + play Play { + serverbound Serverbound { + 0x00 => TabComplete_NoAssume + 0x01 => ChatMessage + 0x02 => ClientStatus + 0x03 => ClientSettings_u8 + 0x04 => ConfirmTransactionServerbound + 0x05 => EnchantItem + 0x06 => ClickWindow_u8 + 0x07 => CloseWindow + 0x08 => PluginMessageServerbound + 0x09 => UseEntity + 0x0a => KeepAliveServerbound_VarInt + 0x0b => PlayerPosition + 0x0c => PlayerPositionLook + 0x0d => PlayerLook + 0x0e => Player + 0x0f => ClientAbilities + 0x10 => PlayerDigging_u8 + 0x11 => PlayerAction + 0x12 => SteerVehicle + 0x13 => ResourcePackStatus + 0x14 => HeldItemChange + 0x15 => CreativeInventoryAction + 0x16 => SetSign + 0x17 => ArmSwing + 0x18 => SpectateTeleport + 0x19 => PlayerBlockPlacement_u8 + 0x1a => UseItem + } + clientbound Clientbound { + 0x00 => SpawnObject_i32 + 0x01 => SpawnExperienceOrb_i32 + 0x02 => SpawnGlobalEntity_i32 + 0x03 => SpawnMob_u8_i32 + 0x04 => SpawnPainting_NoUUID + 0x05 => SpawnPlayer_i32 + 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 => Disconnect + 0x1a => EntityAction + 0x1b => Explosion + 0x1c => ChunkUnload + 0x1d => SetCompression + 0x1e => ChangeGameState + 0x1f => KeepAliveClientbound_VarInt + 0x20 => ChunkData_NoEntities + 0x21 => Effect + 0x22 => Particle + 0x23 => NamedSoundEffect_u8_NoCategory + 0x24 => JoinGame_i8 + 0x25 => Maps + 0x26 => EntityMove_i8 + 0x27 => EntityLookAndMove_i8 + 0x28 => EntityLook + 0x29 => Entity + 0x2a => SignEditorOpen + 0x2b => PlayerAbilities + 0x2c => CombatEvent + 0x2d => PlayerInfo + 0x2e => TeleportPlayer_NoConfirm + 0x2f => EntityUsedBed + 0x30 => EntityDestroy + 0x31 => EntityRemoveEffect + 0x32 => ResourcePackSend + 0x33 => Respawn + 0x34 => EntityHeadLook + 0x35 => WorldBorder + 0x36 => Camera + 0x37 => SetCurrentHotbarSlot + 0x38 => ScoreboardDisplay + 0x39 => EntityMetadata + 0x3a => EntityAttach_leashed + 0x3b => EntityVelocity + 0x3c => EntityEquipment + 0x3d => SetExperience + 0x3e => UpdateHealth + 0x3f => ScoreboardObjective + 0x40 => Teams + 0x41 => UpdateScore + 0x42 => SpawnPosition + 0x43 => TimeUpdate + 0x44 => Title_notext_component + 0x45 => UpdateSign + 0x46 => PlayerListHeaderFooter + 0x47 => CollectItem_nocount + 0x48 => EntityTeleport_i32 + 0x49 => EntityProperties + 0x4a => 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_10_2.rs b/src/protocol/versions/v1_10_2.rs index 7cbfed5..0be2deb 100644 --- a/src/protocol/versions/v1_10_2.rs +++ b/src/protocol/versions/v1_10_2.rs @@ -45,7 +45,7 @@ protocol_packet_ids!( 0x02 => SpawnGlobalEntity 0x03 => SpawnMob_u8 0x04 => SpawnPainting - 0x05 => SpawnPlayer + 0x05 => SpawnPlayer_f64 0x06 => Animation 0x07 => Statistics 0x08 => BlockBreakAnimation @@ -77,8 +77,8 @@ protocol_packet_ids!( 0x22 => Particle 0x23 => JoinGame_i32 0x24 => Maps - 0x25 => EntityMove - 0x26 => EntityLookAndMove + 0x25 => EntityMove_i16 + 0x26 => EntityLookAndMove_i16 0x27 => EntityLook 0x28 => Entity 0x29 => VehicleTeleport @@ -86,7 +86,7 @@ protocol_packet_ids!( 0x2b => PlayerAbilities 0x2c => CombatEvent 0x2d => PlayerInfo - 0x2e => TeleportPlayer + 0x2e => TeleportPlayer_WithConfirm 0x2f => EntityUsedBed 0x30 => EntityDestroy 0x31 => EntityRemoveEffect @@ -113,7 +113,7 @@ protocol_packet_ids!( 0x46 => SoundEffect 0x47 => PlayerListHeaderFooter 0x48 => CollectItem_nocount - 0x49 => EntityTeleport + 0x49 => EntityTeleport_f64 0x4a => EntityProperties 0x4b => EntityEffect } diff --git a/src/protocol/versions/v1_11_2.rs b/src/protocol/versions/v1_11_2.rs index 5f6cc60..fed44e4 100644 --- a/src/protocol/versions/v1_11_2.rs +++ b/src/protocol/versions/v1_11_2.rs @@ -45,7 +45,7 @@ protocol_packet_ids!( 0x02 => SpawnGlobalEntity 0x03 => SpawnMob 0x04 => SpawnPainting - 0x05 => SpawnPlayer + 0x05 => SpawnPlayer_f64 0x06 => Animation 0x07 => Statistics 0x08 => BlockBreakAnimation @@ -77,8 +77,8 @@ protocol_packet_ids!( 0x22 => Particle 0x23 => JoinGame_i32 0x24 => Maps - 0x25 => EntityMove - 0x26 => EntityLookAndMove + 0x25 => EntityMove_i16 + 0x26 => EntityLookAndMove_i16 0x27 => EntityLook 0x28 => Entity 0x29 => VehicleTeleport @@ -86,7 +86,7 @@ protocol_packet_ids!( 0x2b => PlayerAbilities 0x2c => CombatEvent 0x2d => PlayerInfo - 0x2e => TeleportPlayer + 0x2e => TeleportPlayer_WithConfirm 0x2f => EntityUsedBed 0x30 => EntityDestroy 0x31 => EntityRemoveEffect @@ -113,7 +113,7 @@ protocol_packet_ids!( 0x46 => SoundEffect 0x47 => PlayerListHeaderFooter 0x48 => CollectItem - 0x49 => EntityTeleport + 0x49 => EntityTeleport_f64 0x4a => EntityProperties 0x4b => EntityEffect } diff --git a/src/protocol/versions/v1_12_2.rs b/src/protocol/versions/v1_12_2.rs index 897447d..b5765eb 100644 --- a/src/protocol/versions/v1_12_2.rs +++ b/src/protocol/versions/v1_12_2.rs @@ -48,7 +48,7 @@ protocol_packet_ids!( 0x02 => SpawnGlobalEntity 0x03 => SpawnMob 0x04 => SpawnPainting - 0x05 => SpawnPlayer + 0x05 => SpawnPlayer_f64 0x06 => Animation 0x07 => Statistics 0x08 => BlockBreakAnimation @@ -81,8 +81,8 @@ protocol_packet_ids!( 0x23 => JoinGame_i32 0x24 => Maps 0x25 => Entity - 0x26 => EntityMove - 0x27 => EntityLookAndMove + 0x26 => EntityMove_i16 + 0x27 => EntityLookAndMove_i16 0x28 => EntityLook 0x29 => VehicleTeleport 0x2a => SignEditorOpen @@ -90,7 +90,7 @@ protocol_packet_ids!( 0x2c => PlayerAbilities 0x2d => CombatEvent 0x2e => PlayerInfo - 0x2f => TeleportPlayer + 0x2f => TeleportPlayer_WithConfirm 0x30 => EntityUsedBed 0x31 => UnlockRecipes 0x32 => EntityDestroy @@ -119,7 +119,7 @@ protocol_packet_ids!( 0x49 => SoundEffect 0x4a => PlayerListHeaderFooter 0x4b => CollectItem - 0x4c => EntityTeleport + 0x4c => EntityTeleport_f64 0x4d => Advancements 0x4e => EntityProperties 0x4f => EntityEffect diff --git a/src/protocol/versions/v1_9.rs b/src/protocol/versions/v1_9.rs index 74b8982..07ccb44 100644 --- a/src/protocol/versions/v1_9.rs +++ b/src/protocol/versions/v1_9.rs @@ -45,7 +45,7 @@ protocol_packet_ids!( 0x02 => SpawnGlobalEntity 0x03 => SpawnMob_u8 0x04 => SpawnPainting - 0x05 => SpawnPlayer + 0x05 => SpawnPlayer_f64 0x06 => Animation 0x07 => Statistics 0x08 => BlockBreakAnimation @@ -77,8 +77,8 @@ protocol_packet_ids!( 0x22 => Particle 0x23 => JoinGame_i8 0x24 => Maps - 0x25 => EntityMove - 0x26 => EntityLookAndMove + 0x25 => EntityMove_i16 + 0x26 => EntityLookAndMove_i16 0x27 => EntityLook 0x28 => Entity 0x29 => VehicleTeleport @@ -86,7 +86,7 @@ protocol_packet_ids!( 0x2b => PlayerAbilities 0x2c => CombatEvent 0x2d => PlayerInfo - 0x2e => TeleportPlayer + 0x2e => TeleportPlayer_WithConfirm 0x2f => EntityUsedBed 0x30 => EntityDestroy 0x31 => EntityRemoveEffect @@ -114,7 +114,7 @@ protocol_packet_ids!( 0x47 => SoundEffect_u8 0x48 => PlayerListHeaderFooter 0x49 => CollectItem_nocount - 0x4a => EntityTeleport + 0x4a => EntityTeleport_f64 0x4b => EntityProperties 0x4c => EntityEffect } diff --git a/src/protocol/versions/v1_9_2.rs b/src/protocol/versions/v1_9_2.rs index 2b9f603..524f42f 100644 --- a/src/protocol/versions/v1_9_2.rs +++ b/src/protocol/versions/v1_9_2.rs @@ -45,7 +45,7 @@ protocol_packet_ids!( 0x02 => SpawnGlobalEntity 0x03 => SpawnMob_u8 0x04 => SpawnPainting - 0x05 => SpawnPlayer + 0x05 => SpawnPlayer_f64 0x06 => Animation 0x07 => Statistics 0x08 => BlockBreakAnimation @@ -77,8 +77,8 @@ protocol_packet_ids!( 0x22 => Particle 0x23 => JoinGame_i32 0x24 => Maps - 0x25 => EntityMove - 0x26 => EntityLookAndMove + 0x25 => EntityMove_i16 + 0x26 => EntityLookAndMove_i16 0x27 => EntityLook 0x28 => Entity 0x29 => VehicleTeleport @@ -86,7 +86,7 @@ protocol_packet_ids!( 0x2b => PlayerAbilities 0x2c => CombatEvent 0x2d => PlayerInfo - 0x2e => TeleportPlayer + 0x2e => TeleportPlayer_WithConfirm 0x2f => EntityUsedBed 0x30 => EntityDestroy 0x31 => EntityRemoveEffect @@ -114,7 +114,7 @@ protocol_packet_ids!( 0x47 => SoundEffect_u8 0x48 => PlayerListHeaderFooter 0x49 => CollectItem_nocount - 0x4a => EntityTeleport + 0x4a => EntityTeleport_f64 0x4b => EntityProperties 0x4c => EntityEffect } diff --git a/src/server/mod.rs b/src/server/mod.rs index 83f273b..87e695c 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -385,7 +385,8 @@ impl Server { ChunkUnload => on_chunk_unload, BlockChange => on_block_change, MultiBlockChange => on_multi_block_change, - TeleportPlayer => on_teleport, + TeleportPlayer_WithConfirm => on_teleport_player_withconfirm, + TeleportPlayer_NoConfirm => on_teleport_player_noconfirm, TimeUpdate => on_time_update, ChangeGameState => on_game_state_change, UpdateBlockEntity => on_block_entity_update, @@ -394,11 +395,15 @@ impl Server { Disconnect => on_disconnect, // Entities EntityDestroy => on_entity_destroy, - SpawnPlayer => on_player_spawn, - EntityTeleport => on_entity_teleport, - EntityMove => on_entity_move, + SpawnPlayer_f64 => on_player_spawn_f64, + SpawnPlayer_i32 => on_player_spawn_i32, + EntityTeleport_f64 => on_entity_teleport_f64, + EntityTeleport_i32 => on_entity_teleport_i32, + EntityMove_i16 => on_entity_move_i16, + EntityMove_i8 => on_entity_move_i8, EntityLook => on_entity_look, - EntityLookAndMove => on_entity_look_and_move, + EntityLookAndMove_i16 => on_entity_look_and_move_i16, + EntityLookAndMove_i8 => on_entity_look_and_move_i8, } }, Err(err) => panic!("Err: {:?}", err), @@ -647,25 +652,41 @@ impl Server { } } - fn on_entity_teleport(&mut self, entity_telport: packet::play::clientbound::EntityTeleport) { + fn on_entity_teleport_f64(&mut self, entity_telport: packet::play::clientbound::EntityTeleport_f64) { + self.on_entity_teleport(entity_telport.entity_id.0, entity_telport.x, entity_telport.y, entity_telport.z, entity_telport.yaw as f64, entity_telport.pitch as f64, entity_telport.on_ground) + } + + fn on_entity_teleport_i32(&mut self, entity_telport: packet::play::clientbound::EntityTeleport_i32) { + self.on_entity_teleport(entity_telport.entity_id.0, entity_telport.x as f64, entity_telport.y as f64, entity_telport.z as f64, entity_telport.yaw as f64, entity_telport.pitch as f64, entity_telport.on_ground) + } + + fn on_entity_teleport(&mut self, entity_id: i32, x: f64, y: f64, z: f64, yaw: f64, pitch: f64, _on_ground: bool) { use std::f64::consts::PI; - if let Some(entity) = self.entity_map.get(&entity_telport.entity_id.0) { + if let Some(entity) = self.entity_map.get(&entity_id) { let target_position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); let target_rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap(); - target_position.position.x = entity_telport.x; - target_position.position.y = entity_telport.y; - target_position.position.z = entity_telport.z; - target_rotation.yaw = -((entity_telport.yaw as f64) / 256.0) * PI * 2.0; - target_rotation.pitch = -((entity_telport.pitch as f64) / 256.0) * PI * 2.0; + target_position.position.x = x; + target_position.position.y = y; + target_position.position.z = z; + target_rotation.yaw = -(yaw / 256.0) * PI * 2.0; + target_rotation.pitch = -(pitch / 256.0) * PI * 2.0; } } - fn on_entity_move(&mut self, m: packet::play::clientbound::EntityMove) { - if let Some(entity) = self.entity_map.get(&m.entity_id.0) { + fn on_entity_move_i16(&mut self, m: packet::play::clientbound::EntityMove_i16) { + self.on_entity_move(m.entity_id.0, m.delta_x as f64, m.delta_y as f64, m.delta_z as f64) + } + + fn on_entity_move_i8(&mut self, m: packet::play::clientbound::EntityMove_i8) { + self.on_entity_move(m.entity_id.0, m.delta_x as f64, m.delta_y as f64, m.delta_z as f64) + } + + fn on_entity_move(&mut self, entity_id: i32, delta_x: f64, delta_y: f64, delta_z: f64) { + if let Some(entity) = self.entity_map.get(&entity_id) { let position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); - position.position.x += m.delta_x as f64 / (32.0 * 128.0); - position.position.y += m.delta_y as f64 / (32.0 * 128.0); - position.position.z += m.delta_z as f64 / (32.0 * 128.0); + position.position.x += delta_x / (32.0 * 128.0); + position.position.y += delta_y / (32.0 * 128.0); + position.position.z += delta_z / (32.0 * 128.0); } } @@ -678,78 +699,108 @@ impl Server { } } - fn on_entity_look_and_move(&mut self, lookmove: packet::play::clientbound::EntityLookAndMove) { + fn on_entity_look_and_move_i16(&mut self, lookmove: packet::play::clientbound::EntityLookAndMove_i16) { + self.on_entity_look_and_move(lookmove.entity_id.0, + lookmove.delta_x as f64, lookmove.delta_y as f64, lookmove.delta_z as f64, + lookmove.yaw as f64, lookmove.pitch as f64) + } + + fn on_entity_look_and_move_i8(&mut self, lookmove: packet::play::clientbound::EntityLookAndMove_i8) { + self.on_entity_look_and_move(lookmove.entity_id.0, + lookmove.delta_x as f64, lookmove.delta_y as f64, lookmove.delta_z as f64, + lookmove.yaw as f64, lookmove.pitch as f64) + } + + fn on_entity_look_and_move(&mut self, entity_id: i32, delta_x: f64, delta_y: f64, delta_z: f64, yaw: f64, pitch: f64) { use std::f64::consts::PI; - if let Some(entity) = self.entity_map.get(&lookmove.entity_id.0) { + if let Some(entity) = self.entity_map.get(&entity_id) { let position = self.entities.get_component_mut(*entity, self.target_position).unwrap(); let rotation = self.entities.get_component_mut(*entity, self.target_rotation).unwrap(); - position.position.x += lookmove.delta_x as f64 / (32.0 * 128.0); - position.position.y += lookmove.delta_y as f64 / (32.0 * 128.0); - position.position.z += lookmove.delta_z as f64 / (32.0 * 128.0); - rotation.yaw = -((lookmove.yaw as f64) / 256.0) * PI * 2.0; - rotation.pitch = -((lookmove.pitch as f64) / 256.0) * PI * 2.0; + position.position.x += delta_x / (32.0 * 128.0); + position.position.y += delta_y / (32.0 * 128.0); + position.position.z += delta_z / (32.0 * 128.0); + rotation.yaw = -(yaw / 256.0) * PI * 2.0; + rotation.pitch = -(pitch / 256.0) * PI * 2.0; } } - fn on_player_spawn(&mut self, spawn: packet::play::clientbound::SpawnPlayer) { + fn on_player_spawn_f64(&mut self, spawn: packet::play::clientbound::SpawnPlayer_f64) { + self.on_player_spawn(spawn.entity_id.0, spawn.uuid, spawn.x, spawn.y, spawn.z, spawn.yaw as f64, spawn.pitch as f64) + } + + fn on_player_spawn_i32(&mut self, spawn: packet::play::clientbound::SpawnPlayer_i32) { + self.on_player_spawn(spawn.entity_id.0, spawn.uuid, spawn.x as f64, spawn.y as f64, spawn.z as f64, spawn.yaw as f64, spawn.pitch as f64) + } + + fn on_player_spawn(&mut self, entity_id: i32, uuid: protocol::UUID, x: f64, y: f64, z: f64, pitch: f64, yaw: f64) { use std::f64::consts::PI; - if let Some(entity) = self.entity_map.remove(&spawn.entity_id.0) { + if let Some(entity) = self.entity_map.remove(&entity_id) { self.entities.remove_entity(entity); } - let entity = entity::player::create_remote(&mut self.entities, self.players.get(&spawn.uuid).map_or("MISSING", |v| &v.name)); + let entity = entity::player::create_remote(&mut self.entities, self.players.get(&uuid).map_or("MISSING", |v| &v.name)); let position = self.entities.get_component_mut(entity, self.position).unwrap(); let target_position = self.entities.get_component_mut(entity, self.target_position).unwrap(); let rotation = self.entities.get_component_mut(entity, self.rotation).unwrap(); let target_rotation = self.entities.get_component_mut(entity, self.target_rotation).unwrap(); - position.position.x = spawn.x; - position.position.y = spawn.y; - position.position.z = spawn.z; - target_position.position.x = spawn.x; - target_position.position.y = spawn.y; - target_position.position.z = spawn.z; - rotation.yaw = -((spawn.yaw as f64) / 256.0) * PI * 2.0; - rotation.pitch = -((spawn.pitch as f64) / 256.0) * PI * 2.0; + position.position.x = x; + position.position.y = y; + position.position.z = z; + target_position.position.x = x; + target_position.position.y = y; + target_position.position.z = z; + rotation.yaw = -(yaw / 256.0) * PI * 2.0; + rotation.pitch = -(pitch / 256.0) * PI * 2.0; target_rotation.yaw = rotation.yaw; target_rotation.pitch = rotation.pitch; - if let Some(info) = self.players.get(&spawn.uuid) { + if let Some(info) = self.players.get(&uuid) { let model = self.entities.get_component_mut_direct::(entity).unwrap(); model.set_skin(info.skin_url.clone()); } - self.entity_map.insert(spawn.entity_id.0, entity); + self.entity_map.insert(entity_id, entity); } - fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) { + fn on_teleport_player_withconfirm(&mut self, teleport: packet::play::clientbound::TeleportPlayer_WithConfirm) { + self.on_teleport_player(teleport.x, teleport.y, teleport.z, teleport.yaw as f64, teleport.pitch as f64, teleport.flags, Some(teleport.teleport_id)) + } + + fn on_teleport_player_noconfirm(&mut self, teleport: packet::play::clientbound::TeleportPlayer_NoConfirm) { + self.on_teleport_player(teleport.x, teleport.y, teleport.z, teleport.yaw as f64, teleport.pitch as f64, teleport.flags, None) + } + + fn on_teleport_player(&mut self, x: f64, y: f64, z: f64, yaw: f64, pitch: f64, flags: u8, teleport_id: Option) { use std::f64::consts::PI; if let Some(player) = self.player { let position = self.entities.get_component_mut(player, self.target_position).unwrap(); let rotation = self.entities.get_component_mut(player, self.rotation).unwrap(); let velocity = self.entities.get_component_mut(player, self.velocity).unwrap(); - position.position.x = calculate_relative_teleport(TeleportFlag::RelX, teleport.flags, position.position.x, teleport.x); - position.position.y = calculate_relative_teleport(TeleportFlag::RelY, teleport.flags, position.position.y, teleport.y); - position.position.z = calculate_relative_teleport(TeleportFlag::RelZ, teleport.flags, position.position.z, teleport.z); - rotation.yaw = calculate_relative_teleport(TeleportFlag::RelYaw, teleport.flags, rotation.yaw, -teleport.yaw as f64 * (PI / 180.0)); + position.position.x = calculate_relative_teleport(TeleportFlag::RelX, flags, position.position.x, x); + position.position.y = calculate_relative_teleport(TeleportFlag::RelY, flags, position.position.y, y); + position.position.z = calculate_relative_teleport(TeleportFlag::RelZ, flags, position.position.z, z); + rotation.yaw = calculate_relative_teleport(TeleportFlag::RelYaw, flags, rotation.yaw, -yaw as f64 * (PI / 180.0)); rotation.pitch = -((calculate_relative_teleport( TeleportFlag::RelPitch, - teleport.flags, + flags, (-rotation.pitch) * (180.0 / PI) + 180.0, - teleport.pitch as f64 + pitch ) - 180.0) * (PI / 180.0)); - if (teleport.flags & (TeleportFlag::RelX as u8)) == 0 { + if (flags & (TeleportFlag::RelX as u8)) == 0 { velocity.velocity.x = 0.0; } - if (teleport.flags & (TeleportFlag::RelY as u8)) == 0 { + if (flags & (TeleportFlag::RelY as u8)) == 0 { velocity.velocity.y = 0.0; } - if (teleport.flags & (TeleportFlag::RelZ as u8)) == 0 { + if (flags & (TeleportFlag::RelZ as u8)) == 0 { velocity.velocity.z = 0.0; } - self.write_packet(packet::play::serverbound::TeleportConfirm { - teleport_id: teleport.teleport_id, - }); + if let Some(teleport_id) = teleport_id { + self.write_packet(packet::play::serverbound::TeleportConfirm { + teleport_id, + }); + } } }