diff --git a/pumpkin-protocol/src/bedrock/client/handshake.rs b/pumpkin-protocol/src/bedrock/client/handshake.rs new file mode 100644 index 000000000..0dd5a1256 --- /dev/null +++ b/pumpkin-protocol/src/bedrock/client/handshake.rs @@ -0,0 +1,14 @@ +use pumpkin_macros::packet; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +#[packet(0x03)] +pub struct CHandshake { + jwt_data: String, +} + +impl CHandshake { + pub fn new(jwt_data: String) -> Self { + Self { jwt_data } + } +} diff --git a/pumpkin-protocol/src/bedrock/client/mod.rs b/pumpkin-protocol/src/bedrock/client/mod.rs index 0722e07a1..6f8dd5af7 100644 --- a/pumpkin-protocol/src/bedrock/client/mod.rs +++ b/pumpkin-protocol/src/bedrock/client/mod.rs @@ -1,2 +1,6 @@ +pub mod handshake; pub mod network_settings; +pub mod play_status; pub mod raknet; +pub mod resource_pack_stack; +pub mod resource_packs_info; diff --git a/pumpkin-protocol/src/bedrock/client/network_settings.rs b/pumpkin-protocol/src/bedrock/client/network_settings.rs index 26bbcbf44..a97b80428 100644 --- a/pumpkin-protocol/src/bedrock/client/network_settings.rs +++ b/pumpkin-protocol/src/bedrock/client/network_settings.rs @@ -2,7 +2,7 @@ use pumpkin_macros::packet; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] -#[packet(0x8F)] +#[packet(143)] pub struct CNetworkSettings { compression_threshold: u16, compression_method: u16, diff --git a/pumpkin-protocol/src/bedrock/client/play_status.rs b/pumpkin-protocol/src/bedrock/client/play_status.rs new file mode 100644 index 000000000..d2838e404 --- /dev/null +++ b/pumpkin-protocol/src/bedrock/client/play_status.rs @@ -0,0 +1,46 @@ +use pumpkin_macros::packet; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize)] +#[packet(0x02)] +pub struct CPlayStatus { + status: i32, +} + +impl CPlayStatus { + pub fn new(status: PlayStatus) -> Self { + Self { + status: status.to_index(), + } + } +} + +pub enum PlayStatus { + LoginSuccess, + OutdatedClient, + OutdatedServer, + PlayerSpawn, + InvalidTenant, + EditionMismatchEduToVanilla, + EditionMismatchVanillaToEdu, + ServerFullSubClient, + EditorMismatchEditorToVanilla, + EditorMismatchVanillaToEditor, +} + +impl PlayStatus { + pub fn to_index(&self) -> i32 { + match self { + PlayStatus::LoginSuccess => 0, + PlayStatus::OutdatedClient => 1, + PlayStatus::OutdatedServer => 2, + PlayStatus::PlayerSpawn => 3, + PlayStatus::InvalidTenant => 4, + PlayStatus::EditionMismatchEduToVanilla => 5, + PlayStatus::EditionMismatchVanillaToEdu => 6, + PlayStatus::ServerFullSubClient => 7, + PlayStatus::EditorMismatchEditorToVanilla => 8, + PlayStatus::EditorMismatchVanillaToEditor => 9, + } + } +} diff --git a/pumpkin-protocol/src/bedrock/client/raknet/connection.rs b/pumpkin-protocol/src/bedrock/client/raknet/connection.rs index c2294f656..74c4d40c6 100644 --- a/pumpkin-protocol/src/bedrock/client/raknet/connection.rs +++ b/pumpkin-protocol/src/bedrock/client/raknet/connection.rs @@ -3,6 +3,22 @@ use serde::{Deserialize, Serialize}; use crate::codec::socket_address::SocketAddress; +#[derive(Serialize, Deserialize)] +#[packet(0x03)] +pub struct CConnectedPong { + ping_time: u64, + pong_time: u64, +} + +impl CConnectedPong { + pub fn new(ping_time: u64, pong_time: u64) -> Self { + Self { + ping_time, + pong_time, + } + } +} + #[derive(Serialize, Deserialize)] #[packet(0x10)] pub struct CConnectionRequestAccepted { diff --git a/pumpkin-protocol/src/bedrock/client/resource_pack_stack.rs b/pumpkin-protocol/src/bedrock/client/resource_pack_stack.rs new file mode 100644 index 000000000..d65263254 --- /dev/null +++ b/pumpkin-protocol/src/bedrock/client/resource_pack_stack.rs @@ -0,0 +1,20 @@ +use pumpkin_macros::packet; +use serde::{Deserialize, Serialize}; + +use crate::codec::var_uint::VarUInt; + +#[derive(Serialize, Deserialize)] +#[packet(0x07)] +pub struct CResourcePackStackPacket { + resource_pack_required: bool, + addons_list_size: VarUInt, +} + +impl CResourcePackStackPacket { + pub fn new(resource_pack_required: bool, addons_list_size: VarUInt) -> Self { + Self { + resource_pack_required, + addons_list_size, + } + } +} diff --git a/pumpkin-protocol/src/bedrock/client/resource_packs_info.rs b/pumpkin-protocol/src/bedrock/client/resource_packs_info.rs new file mode 100644 index 000000000..90f87ae0d --- /dev/null +++ b/pumpkin-protocol/src/bedrock/client/resource_packs_info.rs @@ -0,0 +1,21 @@ +use pumpkin_macros::packet; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +#[packet(0x06)] +pub struct CResourcePacksInfo { + resource_pack_required: bool, + has_addon_packs: bool, + has_scripts: bool, + // TODO: Add more +} + +impl CResourcePacksInfo { + pub fn new(resource_pack_required: bool, has_addon_packs: bool, has_scripts: bool) -> Self { + Self { + resource_pack_required, + has_addon_packs, + has_scripts, + } + } +} diff --git a/pumpkin-protocol/src/bedrock/packet_decoder.rs b/pumpkin-protocol/src/bedrock/packet_decoder.rs index 1a9719143..2d1e5351c 100644 --- a/pumpkin-protocol/src/bedrock/packet_decoder.rs +++ b/pumpkin-protocol/src/bedrock/packet_decoder.rs @@ -131,7 +131,6 @@ impl UDPNetworkDecoder { })?; let packet_len = packet_len.0 as u64; - dbg!(packet_len); // This is the default MTU size if !(0..=1492).contains(&packet_len) { diff --git a/pumpkin-protocol/src/bedrock/server/login.rs b/pumpkin-protocol/src/bedrock/server/login.rs new file mode 100644 index 000000000..48a654c65 --- /dev/null +++ b/pumpkin-protocol/src/bedrock/server/login.rs @@ -0,0 +1,9 @@ +use pumpkin_macros::packet; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +#[packet(0x01)] +pub struct SLogin { + pub protocol_version: i32, + pub connection_request: String, +} diff --git a/pumpkin-protocol/src/bedrock/server/mod.rs b/pumpkin-protocol/src/bedrock/server/mod.rs index dd43eb6f6..b4e8adb94 100644 --- a/pumpkin-protocol/src/bedrock/server/mod.rs +++ b/pumpkin-protocol/src/bedrock/server/mod.rs @@ -1,2 +1,3 @@ +pub mod login; pub mod raknet; pub mod request_network_settings; diff --git a/pumpkin-protocol/src/bedrock/server/raknet/connection.rs b/pumpkin-protocol/src/bedrock/server/raknet/connection.rs index b05b631b0..c9b643f57 100644 --- a/pumpkin-protocol/src/bedrock/server/raknet/connection.rs +++ b/pumpkin-protocol/src/bedrock/server/raknet/connection.rs @@ -3,6 +3,13 @@ use serde::{Deserialize, Serialize}; use crate::codec::socket_address::SocketAddress; +#[derive(Serialize, Deserialize)] +#[packet(0x00)] +pub struct SConnectedPing { + /// Time since start + pub time: u64, +} + #[derive(Serialize, Deserialize)] #[packet(0x09)] pub struct SConnectionRequest { diff --git a/pumpkin/src/net/bedrock/connection.rs b/pumpkin/src/net/bedrock/connection.rs index 2f6d25ab6..664dfed4c 100644 --- a/pumpkin/src/net/bedrock/connection.rs +++ b/pumpkin/src/net/bedrock/connection.rs @@ -7,8 +7,8 @@ use pumpkin_protocol::{ ConnectionState, bedrock::{ RakReliability, - client::raknet::connection::CConnectionRequestAccepted, - server::raknet::connection::{SConnectionRequest, SNewIncomingConnection}, + client::raknet::connection::{CConnectedPong, CConnectionRequestAccepted}, + server::raknet::connection::{SConnectedPing, SConnectionRequest, SNewIncomingConnection}, }, codec::socket_address::SocketAddress, }; @@ -44,4 +44,21 @@ impl Client { dbg!(packet.pong_time); self.connection_state.store(ConnectionState::Login); } + + pub async fn handle_connected_ping( + &self, + bedrock: &BedrockClientPlatform, + packet: SConnectedPing, + ) { + bedrock + .send_framed_packet( + self, + &CConnectedPong::new( + packet.time, + UNIX_EPOCH.elapsed().unwrap().as_millis() as u64, + ), + RakReliability::Unreliable, + ) + .await; + } } diff --git a/pumpkin/src/net/bedrock/login.rs b/pumpkin/src/net/bedrock/login.rs index 25b97e70b..218695103 100644 --- a/pumpkin/src/net/bedrock/login.rs +++ b/pumpkin/src/net/bedrock/login.rs @@ -1,6 +1,15 @@ -use pumpkin_protocol::bedrock::{ - RakReliability, client::network_settings::CNetworkSettings, - server::request_network_settings::SRequestNetworkSettings, +use pumpkin_protocol::{ + bedrock::{ + RakReliability, + client::{ + network_settings::CNetworkSettings, + play_status::{CPlayStatus, PlayStatus}, + resource_pack_stack::CResourcePackStackPacket, + resource_packs_info::CResourcePacksInfo, + }, + server::{login::SLogin, request_network_settings::SRequestNetworkSettings}, + }, + codec::var_uint::VarUInt, }; use crate::net::{Client, bedrock::BedrockClientPlatform}; @@ -24,4 +33,37 @@ impl Client { ) .await; } + pub async fn handle_login(&self, bedrock: &BedrockClientPlatform, _packet: SLogin) { + dbg!("received login"); + // TODO: Enable encryption + // bedrock + // .send_game_packet( + // self, + // &CHandshake::new(packet.connection_request), + // RakReliability::Unreliable, + // ) + // .await; + // TODO: Batch these + bedrock + .send_game_packet( + self, + &CPlayStatus::new(PlayStatus::LoginSuccess), + RakReliability::Unreliable, + ) + .await; + bedrock + .send_game_packet( + self, + &CResourcePacksInfo::new(false, false, false), + RakReliability::Unreliable, + ) + .await; + bedrock + .send_game_packet( + self, + &CResourcePackStackPacket::new(false, VarUInt(0)), + RakReliability::Unreliable, + ) + .await; + } } diff --git a/pumpkin/src/net/bedrock/mod.rs b/pumpkin/src/net/bedrock/mod.rs index 1b233b210..a8caf10ac 100644 --- a/pumpkin/src/net/bedrock/mod.rs +++ b/pumpkin/src/net/bedrock/mod.rs @@ -17,8 +17,11 @@ use pumpkin_protocol::{ packet_decoder::UDPNetworkDecoder, packet_encoder::UDPNetworkEncoder, server::{ + login::SLogin, raknet::{ - connection::{SConnectionRequest, SDisconnect, SNewIncomingConnection}, + connection::{ + SConnectedPing, SConnectionRequest, SDisconnect, SNewIncomingConnection, + }, open_connection::{SOpenConnectionRequest1, SOpenConnectionRequest2}, unconnected_ping::SUnconnectedPing, }, @@ -274,9 +277,7 @@ impl BedrockClientPlatform { Ok(()) } - fn handle_ack(_ack: &Ack) { - dbg!("received ack"); - } + fn handle_ack(_ack: &Ack) {} async fn handle_frame_set(&self, client: &Client, server: &Server, frame_set: FrameSet) { dbg!("set", frame_set.sequence.0); @@ -297,7 +298,6 @@ impl BedrockClientPlatform { mut frame: Frame, ) -> Result<(), ReadingError> { if frame.split_size > 0 { - dbg!("oh yes, frame is split, not TODO"); let fragment_index = frame.split_index as usize; let compound_id = frame.split_id; let mut compounds = self.compounds.lock().await; @@ -336,8 +336,6 @@ impl BedrockClientPlatform { frame.split_size = 0; } - dbg!(frame.reliability); - let mut payload = &frame.payload[..]; let id = payload.get_u8()?; self.handle_raknet_packet(client, server, i32::from(id), payload) @@ -351,13 +349,15 @@ impl BedrockClientPlatform { packet: RawPacket, ) -> Result<(), ReadingError> { let payload = &packet.payload[..]; - dbg!("payload", payload); match packet.id { SRequestNetworkSettings::PACKET_ID => { client .handle_request_network_settings(self, SRequestNetworkSettings::read(payload)?) .await; } + SLogin::PACKET_ID => { + client.handle_login(self, SLogin::read(payload)?).await; + } _ => { log::warn!("Bedrock: Received Unknown Game packet: {}", packet.id); } @@ -381,14 +381,17 @@ impl BedrockClientPlatform { SNewIncomingConnection::PACKET_ID => { client.handle_new_incoming_connection(&SNewIncomingConnection::read(payload)?); } + SConnectedPing::PACKET_ID => { + client + .handle_connected_ping(self, SConnectedPing::read(payload)?) + .await; + } SDisconnect::PACKET_ID => { dbg!("Bedrock client disconnected"); client.close(); } RAKNET_GAME_PACKET => { - dbg!("game packet"); - dbg!(payload.len()); let game_packet = self .network_reader .lock()