From e5547945b1e6417cfbcf1cb813f5abebb080d327 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sat, 6 Aug 2022 17:39:50 -0700 Subject: [PATCH 01/16] Copy 1.19 (759) from 1.18.2 (758) --- protocol/src/protocol/mod.rs | 6 +- protocol/src/protocol/versions.rs | 3 + protocol/src/protocol/versions/v1_19.rs | 191 ++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 protocol/src/protocol/versions/v1_19.rs diff --git a/protocol/src/protocol/mod.rs b/protocol/src/protocol/mod.rs index 043d1808..1c3c6a1b 100644 --- a/protocol/src/protocol/mod.rs +++ b/protocol/src/protocol/mod.rs @@ -39,9 +39,9 @@ use std::io::{Read, Write}; use std::net::TcpStream; use std::sync::atomic::{AtomicBool, AtomicI32, Ordering}; -pub const SUPPORTED_PROTOCOLS: [i32; 27] = [ - 758, 757, 756, 754, 753, 751, 736, 735, 578, 575, 498, 490, 485, 480, 477, 452, 451, 404, 340, - 316, 315, 210, 109, 107, 74, 47, 5, +pub const SUPPORTED_PROTOCOLS: [i32; 28] = [ + 759, 758, 757, 756, 754, 753, 751, 736, 735, 578, 575, 498, 490, 485, 480, 477, 452, 451, 404, + 340, 316, 315, 210, 109, 107, 74, 47, 5, ]; static CURRENT_PROTOCOL_VERSION: AtomicI32 = AtomicI32::new(SUPPORTED_PROTOCOLS[0]); diff --git a/protocol/src/protocol/versions.rs b/protocol/src/protocol/versions.rs index 0bb9b4be..a57e9d59 100644 --- a/protocol/src/protocol/versions.rs +++ b/protocol/src/protocol/versions.rs @@ -18,6 +18,7 @@ mod v1_16_4; mod v1_17_1; mod v1_18_1; mod v1_18_2; +mod v1_19; mod v1_7_10; mod v1_8_9; mod v1_9; @@ -29,6 +30,7 @@ mod v1_9_2; pub fn protocol_name_to_protocol_version(s: String) -> i32 { match s.as_ref() { "" => SUPPORTED_PROTOCOLS[0], + "1.19" => 759, "1.18.2" => 758, "1.18.1" => 757, "1.17.1" => 756, @@ -75,6 +77,7 @@ pub fn translate_internal_packet_id_for_version( to_internal: bool, ) -> i32 { match version { + 759 => v1_19::translate_internal_packet_id(state, dir, id, to_internal), 758 => v1_18_2::translate_internal_packet_id(state, dir, id, to_internal), 757 => v1_18_1::translate_internal_packet_id(state, dir, id, to_internal), 756 => v1_17_1::translate_internal_packet_id(state, dir, id, to_internal), diff --git a/protocol/src/protocol/versions/v1_19.rs b/protocol/src/protocol/versions/v1_19.rs new file mode 100644 index 00000000..fc330b78 --- /dev/null +++ b/protocol/src/protocol/versions/v1_19.rs @@ -0,0 +1,191 @@ +protocol_packet_ids!( + handshake Handshaking { + serverbound Serverbound { + 0x00 => Handshake + } + clientbound Clientbound { + } + } + play Play { + serverbound Serverbound { + 0x00 => TeleportConfirm + 0x01 => QueryBlockNBT + 0x02 => SetDifficulty + 0x03 => ChatMessage + 0x04 => ClientStatus + 0x05 => ClientSettings_Filtering + 0x06 => TabComplete + 0x07 => ClickWindowButton + 0x08 => ClickWindow_State + 0x09 => CloseWindow + 0x0a => PluginMessageServerbound + 0x0b => EditBook_Pages + 0x0c => QueryEntityNBT + 0x0d => UseEntity_Sneakflag + 0x0e => GenerateStructure + 0x0f => KeepAliveServerbound_i64 + 0x10 => LockDifficulty + 0x11 => PlayerPosition + 0x12 => PlayerPositionLook + 0x13 => PlayerLook + 0x14 => Player + 0x15 => VehicleMove + 0x16 => SteerBoat + 0x17 => PickItem + 0x18 => CraftRecipeRequest + 0x19 => ClientAbilities_u8 + 0x1a => PlayerDigging + 0x1b => PlayerAction + 0x1c => SteerVehicle + 0x1d => WindowPong + 0x1e => SetDisplayedRecipe + 0x1f => SetRecipeBookState + 0x20 => NameItem + 0x21 => ResourcePackStatus + 0x22 => AdvancementTab + 0x23 => SelectTrade + 0x24 => SetBeaconEffect + 0x25 => HeldItemChange + 0x26 => UpdateCommandBlock + 0x27 => UpdateCommandBlockMinecart + 0x28 => CreativeInventoryAction + 0x29 => UpdateJigsawBlock_Joint + 0x2a => UpdateStructureBlock + 0x2b => SetSign + 0x2c => ArmSwing + 0x2d => SpectateTeleport + 0x2e => PlayerBlockPlacement_insideblock + 0x2f => UseItem + } + clientbound Clientbound { + 0x00 => SpawnObject_VarInt + 0x01 => SpawnExperienceOrb + 0x02 => SpawnMob_NoMeta + 0x03 => SpawnPainting_VarInt + 0x04 => SpawnPlayer_f64_NoMeta + 0x05 => SculkVibrationSignal + 0x06 => Animation + 0x07 => Statistics + 0x08 => AcknowledgePlayerDigging + 0x09 => BlockBreakAnimation + 0x0a => UpdateBlockEntity_VarInt + 0x0b => BlockAction + 0x0c => BlockChange_VarInt + 0x0d => BossBar + 0x0e => ServerDifficulty_Locked + 0x0f => ServerMessage_Sender + 0x10 => ClearTitles + 0x11 => TabCompleteReply + 0x12 => DeclareCommands + 0x13 => WindowClose + 0x14 => WindowItems_StateCarry + 0x15 => WindowProperty + 0x16 => WindowSetSlot_State + 0x17 => SetCooldown + 0x18 => PluginMessageClientbound + 0x19 => NamedSoundEffect + 0x1a => Disconnect + 0x1b => EntityAction + 0x1c => Explosion_VarInt + 0x1d => ChunkUnload + 0x1e => ChangeGameState + 0x1f => WindowOpenHorse + 0x20 => WorldBorderInit + 0x21 => KeepAliveClientbound_i64 + 0x22 => ChunkData_AndLight + 0x23 => Effect + 0x24 => Particle_f64 + 0x25 => UpdateLight_Arrays + 0x26 => JoinGame_WorldNames_IsHard_SimDist + 0x27 => Maps + 0x28 => TradeList_WithRestock + 0x29 => EntityMove_i16 + 0x2a => EntityLookAndMove_i16 + 0x2b => EntityLook_VarInt + 0x2c => VehicleTeleport + 0x2d => OpenBook + 0x2e => WindowOpen_VarInt + 0x2f => SignEditorOpen + 0x30 => WindowPing + 0x31 => CraftRecipeResponse + 0x32 => PlayerAbilities + 0x33 => CombatEventEnd + 0x34 => CombatEventEnter + 0x35 => CombatEventDeath + 0x36 => PlayerInfo + 0x37 => FacePlayer + 0x38 => TeleportPlayer_WithDismount + 0x39 => UnlockRecipes_WithBlastSmoker + 0x3a => EntityDestroy + 0x3b => EntityRemoveEffect_VarInt + 0x3c => ResourcePackSend_Prompt + 0x3d => Respawn_NBT + 0x3e => EntityHeadLook + 0x3f => MultiBlockChange_Packed + 0x40 => SelectAdvancementTab + 0x41 => ActionBar + 0x42 => WorldBorderCenter + 0x43 => WorldBorderLerpSize + 0x44 => WorldBorderSize + 0x45 => WorldBorderWarningDelay + 0x46 => WorldBorderWarningReach + 0x47 => Camera + 0x48 => SetCurrentHotbarSlot + 0x49 => UpdateViewPosition + 0x4a => UpdateViewDistance + 0x4b => SpawnPosition_Angle + 0x4c => ScoreboardDisplay + 0x4d => EntityMetadata + 0x4e => EntityAttach + 0x4f => EntityVelocity + 0x50 => EntityEquipment_Array + 0x51 => SetExperience + 0x52 => UpdateHealth + 0x53 => ScoreboardObjective + 0x54 => SetPassengers + 0x55 => Teams_VarInt + 0x56 => UpdateScore_VarInt + 0x57 => UpdateSimulationDistance + 0x58 => TitleSubtitle + 0x59 => TimeUpdate + 0x5a => Title + 0x5b => TitleTimes + 0x5c => EntitySoundEffect + 0x5d => SoundEffect + 0x5e => StopSound + 0x5f => PlayerListHeaderFooter + 0x60 => NBTQueryResponse + 0x61 => CollectItem + 0x62 => EntityTeleport_f64 + 0x63 => Advancements + 0x64 => EntityProperties_VarIntVarInt + 0x65 => EntityEffect_VarInt + 0x66 => DeclareRecipes + 0x67 => Tags_Nested + } + } + login Login { + serverbound Serverbound { + 0x00 => LoginStart + 0x01 => EncryptionResponse + 0x02 => LoginPluginResponse + } + clientbound Clientbound { + 0x00 => LoginDisconnect + 0x01 => EncryptionRequest + 0x02 => LoginSuccess_UUID + 0x03 => SetInitialCompression + 0x04 => LoginPluginRequest + } + } + status Status { + serverbound Serverbound { + 0x00 => StatusRequest + 0x01 => StatusPing + } + clientbound Clientbound { + 0x00 => StatusResponse + 0x01 => StatusPong + } + } +); From 7531ea7b315416507c564f31ec8a5a3b52005145 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 12:42:06 -0700 Subject: [PATCH 02/16] Add LoginStart_Sig, EncryptionResponse_Sig --- protocol/src/protocol/packet.rs | 21 ++++++++++++++++++- protocol/src/protocol/versions/v1_19.rs | 4 ++-- src/server/mod.rs | 28 +++++++++++++++++++++---- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index eacd6928..07214ab6 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -2359,15 +2359,34 @@ state_packets!( } login Login { serverbound Serverbound { - /// LoginStart is sent immeditately after switching into the login + /// LoginStart is sent immediately after switching into the login /// state. The passed username is used by the server to authenticate /// the player in online mode. + packet LoginStart_Sig { + field username: String =, + field has_sign_data: bool =, + field timestamp: Option = when(|p: &LoginStart_Sig| p.has_sign_data), + field public_key: Option> = when(|p: &LoginStart_Sig| p.has_sign_data), + field signature: Option> = when(|p: &LoginStart_Sig| p.has_sign_data), + } packet LoginStart { field username: String =, } /// EncryptionResponse is sent as a reply to EncryptionRequest. All /// packets following this one must be encrypted with AES/CFB8 /// encryption. + packet EncryptionResponse_Sig { + /// The key for the AES/CFB8 cipher encrypted with the + /// public key + field shared_secret: LenPrefixedBytes =, + /// Whether or not the Verify Token should be sent. If not, then the salt and signature will be sent. + field has_verify_token: bool =, + /// The verify token from the request encrypted with the + /// public key + field verify_token: Option> = when(|p: &EncryptionResponse_Sig| p.has_verify_token), + field salt: Option = when(|p: &EncryptionResponse_Sig| !p.has_verify_token), + field signature: Option> = when(|p: &EncryptionResponse_Sig| !p.has_verify_token), + } packet EncryptionResponse { /// The key for the AES/CFB8 cipher encrypted with the /// public key diff --git a/protocol/src/protocol/versions/v1_19.rs b/protocol/src/protocol/versions/v1_19.rs index fc330b78..04af7393 100644 --- a/protocol/src/protocol/versions/v1_19.rs +++ b/protocol/src/protocol/versions/v1_19.rs @@ -166,8 +166,8 @@ protocol_packet_ids!( } login Login { serverbound Serverbound { - 0x00 => LoginStart - 0x01 => EncryptionResponse + 0x00 => LoginStart_Sig + 0x01 => EncryptionResponse_Sig 0x02 => LoginPluginResponse } clientbound Clientbound { diff --git a/src/server/mod.rs b/src/server/mod.rs index 54731bc6..093f9aec 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -132,9 +132,19 @@ impl Server { next: protocol::VarInt(2), })?; conn.state = protocol::State::Login; - conn.write_packet(protocol::packet::login::serverbound::LoginStart { - username: profile.username.clone(), - })?; + if protocol_version >= 759 { + conn.write_packet(protocol::packet::login::serverbound::LoginStart_Sig { + username: profile.username.clone(), + has_sign_data: false, + public_key: None, + signature: None, + timestamp: None, + })?; + } else { + conn.write_packet(protocol::packet::login::serverbound::LoginStart { + username: profile.username.clone(), + })?; + } use std::rc::Rc; let (server_id, public_key, verify_token); @@ -207,7 +217,17 @@ impl Server { profile.join_server(&server_id, &shared, &public_key)?; } - if protocol_version >= 47 { + if protocol_version >= 759 { + conn.write_packet( + protocol::packet::login::serverbound::EncryptionResponse_Sig { + shared_secret: protocol::LenPrefixedBytes::new(shared_e), + verify_token: Some(protocol::LenPrefixedBytes::new(token_e)), + has_verify_token: true, + salt: None, + signature: None, + }, + )?; + } else if protocol_version >= 47 { conn.write_packet(protocol::packet::login::serverbound::EncryptionResponse { shared_secret: protocol::LenPrefixedBytes::new(shared_e), verify_token: protocol::LenPrefixedBytes::new(token_e), From de5503fe533a4829568a7b6693e31195a42a21e9 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 13:01:16 -0700 Subject: [PATCH 03/16] Add LoginSuccess_Sig, with LoginProperty --- protocol/src/protocol/packet.rs | 43 +++++++++++++++++++++++++ protocol/src/protocol/versions/v1_19.rs | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index 07214ab6..d02c741e 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -2433,6 +2433,12 @@ state_packets!( /// LoginSuccess is sent by the server if the player successfully /// authenicates with the session servers (online mode) or straight /// after LoginStart (offline mode). + packet LoginSuccess_Sig { + /// String encoding of a uuid (with hyphens) + field uuid: String =, + field username: String =, + field properties: LenPrefixed =, + } packet LoginSuccess_String { /// String encoding of a uuid (with hyphens) field uuid: String =, @@ -2510,6 +2516,43 @@ state_packets!( } ); +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct LoginProperty { + pub name: String, + pub value: String, + pub is_signed: bool, + pub signature: Option, +} +impl Serializable for LoginProperty { + fn read_from(buf: &mut R) -> Result { + let name: String = Serializable::read_from(buf)?; + let value: String = Serializable::read_from(buf)?; + let is_signed: bool = Serializable::read_from(buf)?; + let signature: Option = + if is_signed { + Some(Serializable::read_from(buf)?) + } else { + None + }; + + Ok(LoginProperty { + name, + value, + is_signed, + signature, + }) + } + + fn write_to(&self, buf: &mut W) -> Result<(), Error> { + self.name.write_to(buf)?; + self.value.write_to(buf)?; + if self.is_signed { + self.signature.as_ref().unwrap().write_to(buf)?; + } + Ok(()) + } +} + #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct SpawnProperty { pub name: String, diff --git a/protocol/src/protocol/versions/v1_19.rs b/protocol/src/protocol/versions/v1_19.rs index 04af7393..61251cdc 100644 --- a/protocol/src/protocol/versions/v1_19.rs +++ b/protocol/src/protocol/versions/v1_19.rs @@ -173,7 +173,7 @@ protocol_packet_ids!( clientbound Clientbound { 0x00 => LoginDisconnect 0x01 => EncryptionRequest - 0x02 => LoginSuccess_UUID + 0x02 => LoginSuccess_Sig 0x03 => SetInitialCompression 0x04 => LoginPluginRequest } From e8ae214a2c0575333695f136840bc22f360fe643 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 13:21:56 -0700 Subject: [PATCH 04/16] Update for packet ID shifts --- protocol/src/protocol/versions/v1_19.rs | 259 ++++++++++++------------ 1 file changed, 131 insertions(+), 128 deletions(-) diff --git a/protocol/src/protocol/versions/v1_19.rs b/protocol/src/protocol/versions/v1_19.rs index 61251cdc..25fedfe4 100644 --- a/protocol/src/protocol/versions/v1_19.rs +++ b/protocol/src/protocol/versions/v1_19.rs @@ -11,129 +11,131 @@ protocol_packet_ids!( 0x00 => TeleportConfirm 0x01 => QueryBlockNBT 0x02 => SetDifficulty - 0x03 => ChatMessage - 0x04 => ClientStatus - 0x05 => ClientSettings_Filtering - 0x06 => TabComplete - 0x07 => ClickWindowButton - 0x08 => ClickWindow_State - 0x09 => CloseWindow - 0x0a => PluginMessageServerbound - 0x0b => EditBook_Pages - 0x0c => QueryEntityNBT - 0x0d => UseEntity_Sneakflag - 0x0e => GenerateStructure - 0x0f => KeepAliveServerbound_i64 - 0x10 => LockDifficulty - 0x11 => PlayerPosition - 0x12 => PlayerPositionLook - 0x13 => PlayerLook - 0x14 => Player - 0x15 => VehicleMove - 0x16 => SteerBoat - 0x17 => PickItem - 0x18 => CraftRecipeRequest - 0x19 => ClientAbilities_u8 - 0x1a => PlayerDigging - 0x1b => PlayerAction - 0x1c => SteerVehicle - 0x1d => WindowPong - 0x1e => SetDisplayedRecipe - 0x1f => SetRecipeBookState - 0x20 => NameItem - 0x21 => ResourcePackStatus - 0x22 => AdvancementTab - 0x23 => SelectTrade - 0x24 => SetBeaconEffect - 0x25 => HeldItemChange - 0x26 => UpdateCommandBlock - 0x27 => UpdateCommandBlockMinecart - 0x28 => CreativeInventoryAction - 0x29 => UpdateJigsawBlock_Joint - 0x2a => UpdateStructureBlock - 0x2b => SetSign - 0x2c => ArmSwing - 0x2d => SpectateTeleport - 0x2e => PlayerBlockPlacement_insideblock - 0x2f => UseItem + //TODO 0x03 => ChatCommand + 0x04 => ChatMessage + //TODO 0x05 => ChatPreview + //TODO 0x06 => ClientCommand + 0x07 => ClientSettings_Filtering + 0x08 => TabComplete + 0x09 => ClickWindowButton + 0x0a => ClickWindow_State + 0x0b => CloseWindow + 0x0c => PluginMessageServerbound + 0x0d => EditBook_Pages + 0x0e => QueryEntityNBT + 0x0f => UseEntity_Sneakflag + 0x10 => GenerateStructure + 0x11 => KeepAliveServerbound_i64 + 0x12 => LockDifficulty + 0x13 => PlayerPosition + 0x14 => PlayerPositionLook + 0x15 => PlayerLook + 0x16 => Player + 0x17 => VehicleMove + 0x18 => SteerBoat + 0x19 => PickItem + 0x1a => CraftRecipeRequest + 0x1b => ClientAbilities_u8 + 0x1c => PlayerDigging + 0x1d => PlayerAction + 0x1e => SteerVehicle + 0x1f => WindowPong + 0x20 => SetDisplayedRecipe + 0x21 => SetRecipeBookState + 0x22 => NameItem + 0x23 => ResourcePackStatus + 0x24 => AdvancementTab + 0x25 => SelectTrade + 0x26 => SetBeaconEffect + 0x27 => HeldItemChange + 0x28 => UpdateCommandBlock + 0x29 => UpdateCommandBlockMinecart + 0x2a => CreativeInventoryAction + 0x2b => UpdateJigsawBlock_Joint + 0x2c => UpdateStructureBlock + 0x2d => SetSign + 0x2e => ArmSwing + 0x2f => SpectateTeleport + 0x30 => PlayerBlockPlacement_insideblock + 0x31 => UseItem } clientbound Clientbound { 0x00 => SpawnObject_VarInt 0x01 => SpawnExperienceOrb - 0x02 => SpawnMob_NoMeta - 0x03 => SpawnPainting_VarInt - 0x04 => SpawnPlayer_f64_NoMeta - 0x05 => SculkVibrationSignal - 0x06 => Animation - 0x07 => Statistics - 0x08 => AcknowledgePlayerDigging - 0x09 => BlockBreakAnimation - 0x0a => UpdateBlockEntity_VarInt - 0x0b => BlockAction - 0x0c => BlockChange_VarInt - 0x0d => BossBar - 0x0e => ServerDifficulty_Locked - 0x0f => ServerMessage_Sender - 0x10 => ClearTitles - 0x11 => TabCompleteReply - 0x12 => DeclareCommands - 0x13 => WindowClose - 0x14 => WindowItems_StateCarry - 0x15 => WindowProperty - 0x16 => WindowSetSlot_State - 0x17 => SetCooldown - 0x18 => PluginMessageClientbound - 0x19 => NamedSoundEffect - 0x1a => Disconnect - 0x1b => EntityAction - 0x1c => Explosion_VarInt - 0x1d => ChunkUnload - 0x1e => ChangeGameState - 0x1f => WindowOpenHorse - 0x20 => WorldBorderInit - 0x21 => KeepAliveClientbound_i64 - 0x22 => ChunkData_AndLight - 0x23 => Effect - 0x24 => Particle_f64 - 0x25 => UpdateLight_Arrays - 0x26 => JoinGame_WorldNames_IsHard_SimDist - 0x27 => Maps - 0x28 => TradeList_WithRestock - 0x29 => EntityMove_i16 - 0x2a => EntityLookAndMove_i16 - 0x2b => EntityLook_VarInt - 0x2c => VehicleTeleport - 0x2d => OpenBook - 0x2e => WindowOpen_VarInt - 0x2f => SignEditorOpen - 0x30 => WindowPing - 0x31 => CraftRecipeResponse - 0x32 => PlayerAbilities - 0x33 => CombatEventEnd - 0x34 => CombatEventEnter - 0x35 => CombatEventDeath - 0x36 => PlayerInfo - 0x37 => FacePlayer - 0x38 => TeleportPlayer_WithDismount - 0x39 => UnlockRecipes_WithBlastSmoker - 0x3a => EntityDestroy - 0x3b => EntityRemoveEffect_VarInt - 0x3c => ResourcePackSend_Prompt - 0x3d => Respawn_NBT - 0x3e => EntityHeadLook - 0x3f => MultiBlockChange_Packed - 0x40 => SelectAdvancementTab - 0x41 => ActionBar - 0x42 => WorldBorderCenter - 0x43 => WorldBorderLerpSize - 0x44 => WorldBorderSize - 0x45 => WorldBorderWarningDelay - 0x46 => WorldBorderWarningReach - 0x47 => Camera - 0x48 => SetCurrentHotbarSlot - 0x49 => UpdateViewPosition - 0x4a => UpdateViewDistance - 0x4b => SpawnPosition_Angle + 0x02 => SpawnPlayer_f64_NoMeta + 0x03 => Animation + 0x04 => Statistics + 0x05 => AcknowledgePlayerDigging // TODO: Acknowledge Block Change + 0x06 => BlockBreakAnimation + 0x07 => UpdateBlockEntity_VarInt + 0x08 => BlockAction + 0x09 => BlockChange_VarInt + 0x0a => BossBar + 0x0b => ServerDifficulty_Locked + 0x0c => ServerMessage_Sender // TODO: Chat Preview + 0x0d => ClearTitles + 0x0e => TabCompleteReply + 0x0f => DeclareCommands + 0x10 => WindowClose + 0x11 => WindowItems_StateCarry + 0x12 => WindowProperty + 0x13 => WindowSetSlot_State + 0x14 => SetCooldown + 0x15 => PluginMessageClientbound + 0x16 => NamedSoundEffect + 0x17 => Disconnect + 0x18 => EntityAction + 0x19 => Explosion_VarInt + 0x1a => ChunkUnload + 0x1b => ChangeGameState + 0x1c => WindowOpenHorse + 0x1d => WorldBorderInit + 0x1e => KeepAliveClientbound_i64 + 0x1f => ChunkData_AndLight + 0x20 => Effect + 0x21 => Particle_f64 + 0x22 => UpdateLight_Arrays + 0x23 => JoinGame_WorldNames_IsHard_SimDist + 0x24 => Maps + 0x25 => TradeList_WithRestock + 0x26 => EntityMove_i16 + 0x27 => EntityLookAndMove_i16 + 0x28 => EntityLook_VarInt + 0x29 => VehicleTeleport + 0x2a => OpenBook + 0x2b => WindowOpen_VarInt + 0x2c => SignEditorOpen + 0x2d => WindowPing + 0x2e => CraftRecipeResponse + 0x2f => PlayerAbilities + //0x30 => PlayerChatMessage // TODO + 0x31 => CombatEventEnd + 0x32 => CombatEventEnter + 0x33 => CombatEventDeath + 0x34 => PlayerInfo + 0x35 => FacePlayer + 0x36 => TeleportPlayer_WithDismount + 0x37 => UnlockRecipes_WithBlastSmoker + 0x38 => EntityDestroy + 0x39 => EntityRemoveEffect_VarInt + 0x3a => ResourcePackSend_Prompt + 0x3b => Respawn_NBT + 0x3c => EntityHeadLook + 0x3d => MultiBlockChange_Packed + 0x3e => SelectAdvancementTab + //0x3f => ServerData // TODO + 0x40 => ActionBar + 0x41 => WorldBorderCenter + 0x42 => WorldBorderLerpSize + 0x43 => WorldBorderSize + 0x44 => WorldBorderWarningDelay + 0x45 => WorldBorderWarningReach + 0x46 => Camera + 0x47 => SetCurrentHotbarSlot + 0x48 => UpdateViewPosition + 0x49 => UpdateViewDistance + 0x4a => SpawnPosition_Angle + //0x4b => SetDisplayChatPreview // TODO 0x4c => ScoreboardDisplay 0x4d => EntityMetadata 0x4e => EntityAttach @@ -153,15 +155,16 @@ protocol_packet_ids!( 0x5c => EntitySoundEffect 0x5d => SoundEffect 0x5e => StopSound - 0x5f => PlayerListHeaderFooter - 0x60 => NBTQueryResponse - 0x61 => CollectItem - 0x62 => EntityTeleport_f64 - 0x63 => Advancements - 0x64 => EntityProperties_VarIntVarInt - 0x65 => EntityEffect_VarInt - 0x66 => DeclareRecipes - 0x67 => Tags_Nested + //0x5f => SystemChatMessage // TODO + 0x60 => PlayerListHeaderFooter + 0x61 => NBTQueryResponse + 0x62 => CollectItem + 0x63 => EntityTeleport_f64 + 0x64 => Advancements + 0x65 => EntityProperties_VarIntVarInt + 0x66 => EntityEffect_VarInt + 0x67 => DeclareRecipes + 0x68 => Tags_Nested } } login Login { From bd5df45e724284dbf82116a2b92fad0d826849cb Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 16:08:03 -0700 Subject: [PATCH 05/16] Fix login packet UUID type --- protocol/src/protocol/packet.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index d02c741e..61cf9275 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -2434,8 +2434,7 @@ state_packets!( /// authenicates with the session servers (online mode) or straight /// after LoginStart (offline mode). packet LoginSuccess_Sig { - /// String encoding of a uuid (with hyphens) - field uuid: String =, + field uuid: UUID =, field username: String =, field properties: LenPrefixed =, } From c230070bb4feefccc1d28ee2bfc7e693f18ccc20 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 16:08:09 -0700 Subject: [PATCH 06/16] server: handle LoginSuccess_Sig --- src/server/mod.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/server/mod.rs b/src/server/mod.rs index 093f9aec..bf8840aa 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -199,6 +199,23 @@ impl Server { Some(rx), )); } + protocol::packet::Packet::LoginSuccess_Sig(val) => { + warn!("Server is running in offline mode"); + debug!("Login: {} {:?} {:?}", val.username, val.uuid, val.properties); + let mut read = conn.clone(); + let mut write = conn; + read.state = protocol::State::Play; + write.state = protocol::State::Play; + let rx = Self::spawn_reader(read); + return Ok(Server::new( + protocol_version, + forge_mods, + val.uuid, + resources, + Some(write), + Some(rx), + )); + } protocol::packet::Packet::LoginDisconnect(val) => { return Err(protocol::Error::Disconnect(val.reason)) } @@ -269,6 +286,13 @@ impl Server { write.state = protocol::State::Play; break; } + protocol::packet::Packet::LoginSuccess_Sig(val) => { + debug!("Login: {} {:?} {:?}", val.username, val.uuid, val.properties); + uuid = val.uuid; + read.state = protocol::State::Play; + write.state = protocol::State::Play; + break; + } protocol::packet::Packet::LoginDisconnect(val) => { return Err(protocol::Error::Disconnect(val.reason)) } From 915d45bbc3778569145b73775d488e027e7eddcc Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 16:32:21 -0700 Subject: [PATCH 07/16] Add JoinGame variant and handling, dimension type (with min_y) is now nested within registry codecs --- protocol/src/protocol/packet.rs | 45 +++++++++++++++++++++++-- protocol/src/protocol/versions/v1_19.rs | 4 +-- src/server/mod.rs | 32 ++++++++++++++++-- src/world/mod.rs | 14 +++++--- 4 files changed, 83 insertions(+), 12 deletions(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index 61cf9275..ae57115f 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -1344,6 +1344,48 @@ state_packets!( } /// JoinGame is sent after completing the login process. This /// sets the initial state for the client. + packet JoinGame_WorldNames_IsHard_SimDist_HasDeath { + /// The entity id the client will be referenced by + field entity_id: i32 =, + /// Whether hardcore mode is enabled + field is_hardcore: bool =, + /// The starting gamemode of the client + field gamemode: u8 =, + /// The previous gamemode of the client + field previous_gamemode: u8 =, + /// Identifiers for all worlds on the server + field world_names: LenPrefixed =, + /// Represents a dimension registry + field registry_codec: Option =, + /// Name of the dimension type being spawned into + field dimension_type: String =, + /// The world being spawned into + field world_name: String =, + /// Truncated SHA-256 hash of world's seed + field hashed_seed: i64 =, + /// The max number of players on the server + field max_players: VarInt =, + /// The render distance (2-32) + field view_distance: VarInt =, + /// The distance the client will process entities + field simulation_distance: VarInt =, + /// Whether the client should reduce the amount of debug + /// information it displays in F3 mode + field reduced_debug_info: bool =, + /// Whether to prompt or immediately respawn + field enable_respawn_screen: bool =, + /// Whether the world is in debug mode + field is_debug: bool =, + /// Whether the world is a superflat world + field is_flat: bool =, + /// If true, then the next two fields are present. + field has_death_location: bool =, + /// Name of the dimension the player died in + field death_dimension_name: String = when(|p: &JoinGame_WorldNames_IsHard_SimDist_HasDeath| p.has_death_location), + /// The location that the player died at + field death_location: Position = when(|p: &JoinGame_WorldNames_IsHard_SimDist_HasDeath| p.has_death_location), + } + packet JoinGame_WorldNames_IsHard_SimDist { /// The entity id the client will be referenced by field entity_id: i32 =, @@ -2527,8 +2569,7 @@ impl Serializable for LoginProperty { let name: String = Serializable::read_from(buf)?; let value: String = Serializable::read_from(buf)?; let is_signed: bool = Serializable::read_from(buf)?; - let signature: Option = - if is_signed { + let signature: Option = if is_signed { Some(Serializable::read_from(buf)?) } else { None diff --git a/protocol/src/protocol/versions/v1_19.rs b/protocol/src/protocol/versions/v1_19.rs index 25fedfe4..a4970302 100644 --- a/protocol/src/protocol/versions/v1_19.rs +++ b/protocol/src/protocol/versions/v1_19.rs @@ -11,7 +11,7 @@ protocol_packet_ids!( 0x00 => TeleportConfirm 0x01 => QueryBlockNBT 0x02 => SetDifficulty - //TODO 0x03 => ChatCommand + //TODO 0x03 => ChatCommand 0x04 => ChatMessage //TODO 0x05 => ChatPreview //TODO 0x06 => ClientCommand @@ -95,7 +95,7 @@ protocol_packet_ids!( 0x20 => Effect 0x21 => Particle_f64 0x22 => UpdateLight_Arrays - 0x23 => JoinGame_WorldNames_IsHard_SimDist + 0x23 => JoinGame_WorldNames_IsHard_SimDist_HasDeath 0x24 => Maps 0x25 => TradeList_WithRestock 0x26 => EntityMove_i16 diff --git a/src/server/mod.rs b/src/server/mod.rs index bf8840aa..05210328 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -15,6 +15,7 @@ use crate::ecs; use crate::entity; use crate::format; +use crate::nbt; use crate::protocol::{self, forge, mojang, packet}; use crate::render; use crate::resources; @@ -201,7 +202,10 @@ impl Server { } protocol::packet::Packet::LoginSuccess_Sig(val) => { warn!("Server is running in offline mode"); - debug!("Login: {} {:?} {:?}", val.username, val.uuid, val.properties); + debug!( + "Login: {} {:?} {:?}", + val.username, val.uuid, val.properties + ); let mut read = conn.clone(); let mut write = conn; read.state = protocol::State::Play; @@ -287,7 +291,10 @@ impl Server { break; } protocol::packet::Packet::LoginSuccess_Sig(val) => { - debug!("Login: {} {:?} {:?}", val.username, val.uuid, val.properties); + debug!( + "Login: {} {:?} {:?}", + val.username, val.uuid, val.properties + ); uuid = val.uuid; read.state = protocol::State::Play; write.state = protocol::State::Play; @@ -625,6 +632,7 @@ impl Server { self pck { PluginMessageClientbound_i16 => on_plugin_message_clientbound_i16, PluginMessageClientbound => on_plugin_message_clientbound_1, + JoinGame_WorldNames_IsHard_SimDist_HasDeath => on_game_join_worldnames_ishard_simdist_hasdeath, JoinGame_WorldNames_IsHard_SimDist => on_game_join_worldnames_ishard_simdist, JoinGame_WorldNames_IsHard => on_game_join_worldnames_ishard, JoinGame_WorldNames => on_game_join_worldnames, @@ -1102,6 +1110,24 @@ impl Server { .write_plugin_message(channel, data); // TODO handle errors } + fn on_game_join_worldnames_ishard_simdist_hasdeath( + &mut self, + join: packet::play::clientbound::JoinGame_WorldNames_IsHard_SimDist_HasDeath, + ) { + if let Some(nbt::NamedTag(_, nbt::Tag::Compound(registries))) = join.registry_codec { + if let Some(nbt::Tag::Compound(dimension_type)) = + registries.get("minecraft:dimension_type") + { + self.world.load_dimension_type_tags(dimension_type); + } + + let _biome_registry = registries.get("minecraft:worldgen/biome"); + let _chat_type_registry = registries.get("minecraft:chat_type"); + } + + self.on_game_join(join.gamemode, join.entity_id) + } + fn on_game_join_worldnames_ishard_simdist( &mut self, join: packet::play::clientbound::JoinGame_WorldNames_IsHard_SimDist, @@ -1984,7 +2010,7 @@ impl Server { self.received_chat_at = Some(Instant::now()); } - fn load_block_entities(&mut self, block_entities: Vec>) { + fn load_block_entities(&mut self, block_entities: Vec>) { for block_entity in block_entities.into_iter().flatten() { let x = block_entity.1.get("x").unwrap().as_int().unwrap(); let y = block_entity.1.get("y").unwrap().as_int().unwrap(); diff --git a/src/world/mod.rs b/src/world/mod.rs index e51aff61..b2c4a2f2 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -1009,13 +1009,17 @@ impl World { pub fn load_dimension_type(&mut self, dimension_tags: Option) { if let Some(crate::nbt::NamedTag(_, crate::nbt::Tag::Compound(tags))) = dimension_tags { - info!("Dimension type: {:?}", tags); + self.load_dimension_type_tags(&tags); + } + } - if let Some(crate::nbt::Tag::Int(min_y)) = tags.get("min_y") { - self.min_y = *min_y; - } - // TODO: More tags https://wiki.vg/Protocol#Login_.28play.29 + pub fn load_dimension_type_tags(&mut self, tags: &HashMap) { + info!("Dimension type: {:?}", tags); + + if let Some(crate::nbt::Tag::Int(min_y)) = tags.get("min_y") { + self.min_y = *min_y; } + // TODO: More tags https://wiki.vg/Protocol#Login_.28play.29 } #[allow(clippy::or_fun_call)] From 0c74fb29a79319d2050a9de5382052e19b78321f Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 16:54:48 -0700 Subject: [PATCH 08/16] CommandNode: use debug description in parse error --- protocol/src/protocol/packet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index ae57115f..45b31dc9 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -3662,7 +3662,7 @@ impl Serializable for CommandNode { "forge:enum" => CommandProperty::ForgeEnum { cls: Serializable::read_from(buf)?, }, - _ => panic!("unsupported command node parser {}", parse), + _ => panic!("unsupported command node parser {:?}", parse), }) } else { None From bb9cb7a8373ee95a6095604d9455a26c8ce1670c Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 17:03:36 -0700 Subject: [PATCH 09/16] 1.18.2: add resource/_or_tag CommandNodes, from https://wiki.vg/index.php?title=Command_Data&oldid=17429 --- protocol/src/protocol/packet.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index 45b31dc9..2df27674 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -3525,6 +3525,12 @@ pub enum CommandProperty { EntitySummon, Dimension, UUID, + ResourceOrTag { + registry: String, + }, + Resource { + registry: String, + }, ForgeModId, ForgeEnum { cls: String, @@ -3658,6 +3664,12 @@ impl Serializable for CommandNode { "minecraft:entity_summon" => CommandProperty::EntitySummon, "minecraft:dimension" => CommandProperty::Dimension, "minecraft:uuid" => CommandProperty::UUID, + "minecraft:resource_or_tag" => CommandProperty::ResourceOrTag { + registry: Serializable::read_from(buf)?, + }, + "minecraft:resource" => CommandProperty::Resource { + registry: Serializable::read_from(buf)?, + }, "forge:modid" => CommandProperty::ForgeModId, "forge:enum" => CommandProperty::ForgeEnum { cls: Serializable::read_from(buf)?, From 773e35cac6df28a791182e4069340ce7d55c3c87 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 17:31:36 -0700 Subject: [PATCH 10/16] CommandNode: add 1.19 parsing where parsers are VarInt IDs instead of strings --- protocol/src/protocol/packet.rs | 69 ++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index 2df27674..300cc0da 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -3564,8 +3564,75 @@ impl Serializable for CommandNode { } else { None }; + let parser: Option = if node_type == CommandNodeType::Argument { - Serializable::read_from(buf)? + if super::current_protocol_version() >= 759 { + let parser_id: VarInt = Serializable::read_from(buf)?; + // https://wiki.vg/Command_Data#Parsers + // "In 1.19, Parsers are identified by a varint id. + // Pre-1.19, parsers are identified by a string id." + // Map ID to string + let parsers = [ + "brigadier:bool", + "brigadier:float", + "brigadier:double", + "brigadier:integer", + "brigadier:long", + "brigadier:string", + "minecraft:entity", + "minecraft:game_profile", + "minecraft:block_pos", + "minecraft:column_pos", + "minecraft:vec3", + "minecraft:vec2", + "minecraft:block_state", + "minecraft:block_predicate", + "minecraft:item_stack", + "minecraft:item_predicate", + "minecraft:color", + "minecraft:component", + "minecraft:message", + "minecraft:nbt", + "minecraft:nbt_tag", + "minecraft:nbt_path", + "minecraft:objective", + "minecraft:objective_criteria", + "minecraft:operation", + "minecraft:particle", + "minecraft:angle", + "minecraft:rotation", + "minecraft:scoreboard_slot", + "minecraft:score_holder", + "minecraft:swizzle", + "minecraft:team", + "minecraft:item_slot", + "minecraft:resource_location", + "minecraft:mob_effect", + "minecraft:function", + "minecraft:entity_anchor", + "minecraft:int_range", + "minecraft:float_range", + "minecraft:item_enchantment", + "minecraft:entity_summon", + "minecraft:dimension", + "minecraft:time", + "minecraft:resource_or_tag", + "minecraft:resource", + "(added in 1.19) Template mirror", + "(added in 1.19) Template rotation", + "minecraft:uuid", + ]; + if parser_id.0 < 0 || parser_id.0 > parsers.len().try_into().unwrap() { + panic!( + "command node identifier out of range {} > {}", + parser_id.0, + parsers.len() + ); + } + Some(parsers[parser_id.0 as usize].to_string()) + } else { + Serializable::read_from(buf)? + } } else { None }; From e8dd8f0d933b18e2986ee068e9bbd884acee4b7b Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 17:54:03 -0700 Subject: [PATCH 11/16] PlayerInfo has signature data in 1.19 Since this is deep inside a complex packet structure, conditionalize https://wiki.vg/index.php?title=Protocol&oldid=17706#Player_Info https://wiki.vg/index.php?title=Protocol&oldid=17499#Player_Info --- protocol/src/protocol/packet.rs | 39 +++++++++++++++++++++++++-------- src/server/mod.rs | 3 +++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index 300cc0da..3ff39c52 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -3071,19 +3071,37 @@ impl Serializable for PlayerInfoData { } props.push(prop); } + + let gamemode: VarInt = Serializable::read_from(buf)?; + let ping: VarInt = Serializable::read_from(buf)?; + let display: Option = if bool::read_from(buf)? { + Some(Serializable::read_from(buf)?) + } else { + None + }; + let mut timestamp: Option = None; + let mut public_key: Option> = None; + let mut signature: Option> = None; + + if super::current_protocol_version() >= 759 { + let has_sig_data: bool = Serializable::read_from(buf)?; + if has_sig_data { + timestamp = Some(Serializable::read_from(buf)?); + public_key = Some(Serializable::read_from(buf)?); + signature = Some(Serializable::read_from(buf)?); + } + } + let p = PlayerDetail::Add { uuid, name, properties: props, - gamemode: Serializable::read_from(buf)?, - ping: Serializable::read_from(buf)?, - display: { - if bool::read_from(buf)? { - Some(Serializable::read_from(buf)?) - } else { - None - } - }, + gamemode, + ping, + display, + timestamp, + public_key, + signature, }; m.players.push(p); } @@ -3135,6 +3153,9 @@ pub enum PlayerDetail { gamemode: VarInt, ping: VarInt, display: Option, + timestamp: Option, + public_key: Option>, + signature: Option>, }, UpdateGamemode { uuid: UUID, diff --git a/src/server/mod.rs b/src/server/mod.rs index 05210328..b822f9dc 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1900,6 +1900,9 @@ impl Server { display, gamemode, ping, + timestamp: _, + public_key: _, + signature: _, } => { let info = self.players.entry(uuid.clone()).or_insert(PlayerInfo { name: name.clone(), From a27d40ce3d3b3a5110be8e303f65148de26ad753 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 18:02:11 -0700 Subject: [PATCH 12/16] Add new ServerData packet --- protocol/src/protocol/packet.rs | 7 +++++++ protocol/src/protocol/versions/v1_19.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index 3ff39c52..abc9a702 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -1920,6 +1920,13 @@ state_packets!( field has_id: bool =, field tab_id: String = when(|p: &SelectAdvancementTab| p.has_id), } + packet ServerData { + field has_motd: bool =, + field motd: Option = when(|p: &ServerData| p.has_motd), + field has_icon: bool =, + field icon: Option = when(|p: &ServerData| p.has_icon), + field previews_chat: bool =, + } packet ActionBar { field text: String =, } diff --git a/protocol/src/protocol/versions/v1_19.rs b/protocol/src/protocol/versions/v1_19.rs index a4970302..1cf03800 100644 --- a/protocol/src/protocol/versions/v1_19.rs +++ b/protocol/src/protocol/versions/v1_19.rs @@ -123,7 +123,7 @@ protocol_packet_ids!( 0x3c => EntityHeadLook 0x3d => MultiBlockChange_Packed 0x3e => SelectAdvancementTab - //0x3f => ServerData // TODO + 0x3f => ServerData 0x40 => ActionBar 0x41 => WorldBorderCenter 0x42 => WorldBorderLerpSize From dfa6fa34b5733d5569d3b65ef70b3c6f9cd7ded6 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 18:06:32 -0700 Subject: [PATCH 13/16] server: show MOTD from ServerData --- src/server/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server/mod.rs b/src/server/mod.rs index b822f9dc..5192ce1c 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -641,6 +641,7 @@ impl Server { JoinGame_i32 => on_game_join_i32, JoinGame_i8 => on_game_join_i8, JoinGame_i8_NoDebug => on_game_join_i8_nodebug, + ServerData => on_server_data, Respawn_Gamemode => on_respawn_gamemode, Respawn_HashedSeed => on_respawn_hashedseed, Respawn_WorldName => on_respawn_worldname, @@ -1209,6 +1210,13 @@ impl Server { } } + fn on_server_data(&mut self, server_data: packet::play::clientbound::ServerData) { + if let Some(motd) = server_data.motd { + info!("Server MOTD: {:?}", motd); + } + // TODO: show server_data.icon (base64 string) + } + fn on_respawn_hashedseed(&mut self, respawn: packet::play::clientbound::Respawn_HashedSeed) { self.respawn(respawn.gamemode) } From 4eea97520c69bcc071f122cdc9c7fe96066b346a Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 18:19:09 -0700 Subject: [PATCH 14/16] Add new SystemChatMessage and handle in server --- protocol/src/protocol/packet.rs | 7 +++++++ protocol/src/protocol/versions/v1_19.rs | 2 +- src/server/mod.rs | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/protocol/src/protocol/packet.rs b/protocol/src/protocol/packet.rs index abc9a702..20befa63 100644 --- a/protocol/src/protocol/packet.rs +++ b/protocol/src/protocol/packet.rs @@ -911,6 +911,13 @@ state_packets!( field nodes: LenPrefixed =, field root_index: VarInt =, } + /// SystemChatMessage is sent by the server for system messages, the system/chat + /// distinction exists to respect the user's chat visibility settings. + packet SystemChatMessage { + field message: format::Component =, + /// Whether the message is an actionbar or chat message + field overlay: bool =, + } /// ServerMessage is a message sent by the server. It could be from a player /// or just a system message. The Type field controls the location the /// message is displayed at and when the message is displayed. diff --git a/protocol/src/protocol/versions/v1_19.rs b/protocol/src/protocol/versions/v1_19.rs index 1cf03800..0b881292 100644 --- a/protocol/src/protocol/versions/v1_19.rs +++ b/protocol/src/protocol/versions/v1_19.rs @@ -155,7 +155,7 @@ protocol_packet_ids!( 0x5c => EntitySoundEffect 0x5d => SoundEffect 0x5e => StopSound - //0x5f => SystemChatMessage // TODO + 0x5f => SystemChatMessage 0x60 => PlayerListHeaderFooter 0x61 => NBTQueryResponse 0x62 => CollectItem diff --git a/src/server/mod.rs b/src/server/mod.rs index 5192ce1c..cc3d2773 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -680,6 +680,7 @@ impl Server { UpdateSign_u16 => on_sign_update_u16, PlayerInfo => on_player_info, PlayerInfo_String => on_player_info_string, + SystemChatMessage => on_system_chat_message, ServerMessage_NoPosition => on_servermessage_noposition, ServerMessage_Position => on_servermessage_position, ServerMessage_Sender => on_servermessage_sender, @@ -1996,6 +1997,14 @@ impl Server { } } + fn on_system_chat_message( + &mut self, + m: packet::play::clientbound::SystemChatMessage, + ) { + // TODO: flag as system message (vs chat message) + self.on_servermessage(&m.message, None, None); + } + fn on_servermessage_noposition( &mut self, m: packet::play::clientbound::ServerMessage_NoPosition, From ad5beac20590444238e66062bf357898c8bb4818 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 18:37:33 -0700 Subject: [PATCH 15/16] server: fix getting correct dimension types for logged in world --- src/server/mod.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/server/mod.rs b/src/server/mod.rs index cc3d2773..7d9cec94 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1117,10 +1117,30 @@ impl Server { join: packet::play::clientbound::JoinGame_WorldNames_IsHard_SimDist_HasDeath, ) { if let Some(nbt::NamedTag(_, nbt::Tag::Compound(registries))) = join.registry_codec { - if let Some(nbt::Tag::Compound(dimension_type)) = + if let Some(nbt::Tag::Compound(dimension_types)) = registries.get("minecraft:dimension_type") { - self.world.load_dimension_type_tags(dimension_type); + println!("world_name = {:?}", join.world_name); + println!("dimension_types = {:?}", dimension_types); + if let Some(nbt::Tag::List(list)) = dimension_types.get("value") { + println!("list = {:?}", list); + for item in list { + if let nbt::Tag::Compound(item) = item { + println!("item = {:?}", item); + if let Some(nbt::Tag::String(name)) = item.get("name") { + println!("name = {:?}", name); + if name == &join.world_name { + if let Some(nbt::Tag::Compound(dimension_type)) = + item.get("element") + { + self.world.load_dimension_type_tags(dimension_type); + } + } + println!("match? {:?} ", name == &join.world_name); + } + } + } + } } let _biome_registry = registries.get("minecraft:worldgen/biome"); @@ -1997,10 +2017,7 @@ impl Server { } } - fn on_system_chat_message( - &mut self, - m: packet::play::clientbound::SystemChatMessage, - ) { + fn on_system_chat_message(&mut self, m: packet::play::clientbound::SystemChatMessage) { // TODO: flag as system message (vs chat message) self.on_servermessage(&m.message, None, None); } From 400565f050df31af0068470cecd2918e40f186da Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 7 Aug 2022 18:44:48 -0700 Subject: [PATCH 16/16] Cleanup debugging in loading dimension --- src/server/mod.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/server/mod.rs b/src/server/mod.rs index 7d9cec94..0d401a01 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1116,27 +1116,24 @@ impl Server { &mut self, join: packet::play::clientbound::JoinGame_WorldNames_IsHard_SimDist_HasDeath, ) { + let mut found_dimension = false; if let Some(nbt::NamedTag(_, nbt::Tag::Compound(registries))) = join.registry_codec { if let Some(nbt::Tag::Compound(dimension_types)) = registries.get("minecraft:dimension_type") { - println!("world_name = {:?}", join.world_name); - println!("dimension_types = {:?}", dimension_types); if let Some(nbt::Tag::List(list)) = dimension_types.get("value") { - println!("list = {:?}", list); for item in list { if let nbt::Tag::Compound(item) = item { - println!("item = {:?}", item); if let Some(nbt::Tag::String(name)) = item.get("name") { - println!("name = {:?}", name); + debug!("Dimension {:?} = {:?}", name, item); if name == &join.world_name { if let Some(nbt::Tag::Compound(dimension_type)) = item.get("element") { self.world.load_dimension_type_tags(dimension_type); + found_dimension = true; } } - println!("match? {:?} ", name == &join.world_name); } } } @@ -1146,6 +1143,10 @@ impl Server { let _biome_registry = registries.get("minecraft:worldgen/biome"); let _chat_type_registry = registries.get("minecraft:chat_type"); } + if !found_dimension { + warn!("Failed to find world name {} in dimension types of JoinGame - expect broken offsets", join.world_name); + //self.world.min_y = -64; + } self.on_game_join(join.gamemode, join.entity_id) }