From 166079ab06ccb9ef2f028861aaffd55d149de48a Mon Sep 17 00:00:00 2001 From: ice_iix Date: Mon, 3 Dec 2018 15:40:57 -0800 Subject: [PATCH] Add 1.9.2 (109) multiprotocol support Closes https://github.com/iceiix/steven/pull/15 Enhances https://github.com/iceiix/steven/issues/18 --- src/protocol/mod.rs | 2 +- src/protocol/packet.rs | 37 ++++++++ src/protocol/versions.rs | 4 + src/protocol/versions/v1_9_2.rs | 146 ++++++++++++++++++++++++++++++++ src/server/mod.rs | 27 ++++++ 5 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 src/protocol/versions/v1_9_2.rs diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 8103dec..9e77afc 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; 4] = [340, 316, 315, 210]; +pub const SUPPORTED_PROTOCOLS: [i32; 5] = [340, 316, 315, 210, 109]; /// Helper macro for defining packets diff --git a/src/protocol/packet.rs b/src/protocol/packet.rs index 42ea33d..8cdac1a 100644 --- a/src/protocol/packet.rs +++ b/src/protocol/packet.rs @@ -214,6 +214,10 @@ state_packets!( packet ResourcePackStatus { field result: VarInt =, } + packet ResourcePackStatus_hash { + field hash: String =, + field result: VarInt =, + } // TODO: Document packet AdvancementTab { field action: VarInt =, @@ -493,6 +497,15 @@ state_packets!( field volume: f32 =, field pitch: f32 =, } + packet NamedSoundEffect_u8 { + field name: String =, + field category: VarInt =, + 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 =, @@ -547,6 +560,13 @@ state_packets!( field data: LenPrefixedBytes =, field block_entities: LenPrefixed> =, } + packet ChunkData_NoEntities { + field chunk_x: i32 =, + field chunk_z: i32 =, + field new: bool =, + field bitmask: VarInt =, + field data: LenPrefixedBytes =, + } /// 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. @@ -857,6 +877,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), } + /// UpdateSign sets or changes the text on a sign. + packet UpdateSign { + field location: Position =, + field line1: format::Component =, + field line2: format::Component =, + field line3: format::Component =, + field line4: format::Component =, + } /// SoundEffect plays the named sound at the target location. packet SoundEffect { field name: VarInt =, @@ -867,6 +895,15 @@ state_packets!( field volume: f32 =, field pitch: f32 =, } + packet SoundEffect_u8 { + field name: VarInt =, + field category: VarInt =, + field x: i32 =, + field y: i32 =, + field z: i32 =, + field volume: f32 =, + field pitch: u8 =, + } /// PlayerListHeaderFooter updates the header/footer of the player list. packet PlayerListHeaderFooter { field header: format::Component =, diff --git a/src/protocol/versions.rs b/src/protocol/versions.rs index 63bb6c1..c2f276a 100644 --- a/src/protocol/versions.rs +++ b/src/protocol/versions.rs @@ -3,6 +3,7 @@ use crate::protocol::*; mod v1_12_2; mod v1_11_2; mod v1_10_2; +mod v1_9_2; pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: Direction, id: i32, to_internal: bool) -> i32 { match version { @@ -20,6 +21,9 @@ pub fn translate_internal_packet_id_for_version(version: i32, state: State, dir: // 1.10.2 210 => v1_10_2::translate_internal_packet_id(state, dir, id, to_internal), + // 1.9.2 + 109 => v1_9_2::translate_internal_packet_id(state, dir, id, to_internal), + _ => panic!("unsupported protocol version"), } } diff --git a/src/protocol/versions/v1_9_2.rs b/src/protocol/versions/v1_9_2.rs new file mode 100644 index 0000000..faaaca9 --- /dev/null +++ b/src/protocol/versions/v1_9_2.rs @@ -0,0 +1,146 @@ +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_hash + 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_u8 + 0x1a => Disconnect + 0x1b => EntityAction + 0x1c => Explosion + 0x1d => ChunkUnload + 0x1e => ChangeGameState + 0x1f => KeepAliveClientbound_VarInt + 0x20 => ChunkData_NoEntities + 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 => UpdateSign + 0x47 => SoundEffect_u8 + 0x48 => PlayerListHeaderFooter + 0x49 => CollectItem_nocount + 0x4a => EntityTeleport + 0x4b => EntityProperties + 0x4c => 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/server/mod.rs b/src/server/mod.rs index 5880096..62299df 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -380,6 +380,7 @@ impl Server { KeepAliveClientbound_i64 => on_keep_alive_i64, KeepAliveClientbound_VarInt => on_keep_alive_varint, ChunkData => on_chunk_data, + ChunkData_NoEntities => on_chunk_data_no_entities, ChunkUnload => on_chunk_unload, BlockChange => on_block_change, MultiBlockChange => on_multi_block_change, @@ -387,6 +388,7 @@ impl Server { TimeUpdate => on_time_update, ChangeGameState => on_game_state_change, UpdateBlockEntity => on_block_entity_update, + UpdateSign => on_sign_update, PlayerInfo => on_player_info, Disconnect => on_disconnect, // Entities @@ -769,6 +771,21 @@ impl Server { } } + fn on_sign_update(&mut self, mut update_sign: packet::play::clientbound::UpdateSign) { + use crate::format; + format::convert_legacy(&mut update_sign.line1); + format::convert_legacy(&mut update_sign.line2); + format::convert_legacy(&mut update_sign.line3); + format::convert_legacy(&mut update_sign.line4); + self.world.add_block_entity_action(world::BlockEntityAction::UpdateSignText( + update_sign.location, + update_sign.line1, + update_sign.line2, + update_sign.line3, + update_sign.line4, + )); + } + fn on_player_info(&mut self, player_info: packet::play::clientbound::PlayerInfo) { use crate::protocol::packet::PlayerDetail::*; use base64; @@ -882,6 +899,16 @@ impl Server { } } + fn on_chunk_data_no_entities(&mut self, chunk_data: packet::play::clientbound::ChunkData_NoEntities) { + self.world.load_chunk( + chunk_data.chunk_x, + chunk_data.chunk_z, + chunk_data.new, + chunk_data.bitmask.0 as u16, + chunk_data.data.data + ).unwrap(); + } + fn on_chunk_unload(&mut self, chunk_unload: packet::play::clientbound::ChunkUnload) { self.world.unload_chunk(chunk_unload.x, chunk_unload.z, &mut self.entities); }