From ddb1a5925ab15263f1c2e3d2896f1b10445a7716 Mon Sep 17 00:00:00 2001 From: GoodLucky777 Date: Sat, 3 Feb 2024 23:00:09 +0900 Subject: [PATCH 1/2] feat: Add more Motd fields, fix Reader for Motd, and impl FromStr for Gamemode --- src/protocol/mcpe/motd.rs | 75 +++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/src/protocol/mcpe/motd.rs b/src/protocol/mcpe/motd.rs index 6860075..dfbdb75 100644 --- a/src/protocol/mcpe/motd.rs +++ b/src/protocol/mcpe/motd.rs @@ -1,5 +1,6 @@ use binary_util::interfaces::{Reader, Writer}; use binary_util::io::{ByteReader, ByteWriter}; +use std::str::FromStr; #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -33,12 +34,30 @@ impl std::fmt::Display for Gamemode { } } +impl FromStr for Gamemode { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "Survival" => Ok(Gamemode::Survival), + "Creative" => Ok(Gamemode::Creative), + "Adventure" => Ok(Gamemode::Adventure), + "Spectator" => Ok(Gamemode::Spectator), + _ => Err(format!("Invalid gamemode {}", s)), + } + } +} + /// Protocol wise, motd is just a string /// However we're using this struct to represent the motd #[derive(Debug, Clone)] pub struct Motd { + /// The edition of the server (MCPE or MCEE) + pub edition: String, /// The name of the server pub name: String, + /// The second line of the server MOTD + pub sub_name: String, /// The protocol version pub protocol: u16, /// The version of the server @@ -51,17 +70,21 @@ pub struct Motd { pub gamemode: Gamemode, /// The server's GUID pub server_guid: u64, - /// The server's port + /// The server's IPv4 port pub port: String, /// The IPv6 port // TODO: Implement this pub ipv6_port: String, + /// Is Nintendo limited + pub nintendo_limited: bool, } impl Motd { pub fn new>(server_guid: u64, port: S) -> Self { Self { + edition: "MCPE".into(), name: "Netrex Server".into(), + sub_name: "Netrex".into(), player_count: 10, player_max: 100, protocol: 448, @@ -70,6 +93,7 @@ impl Motd { server_guid, port: port.into(), ipv6_port: "19133".into(), + nintendo_limited: false, } } @@ -77,16 +101,20 @@ impl Motd { /// MOTD buffer. pub fn write(&self) -> String { let props: Vec = vec![ - "MCPE".into(), + self.edition.clone(), self.name.clone(), self.protocol.to_string(), self.version.clone(), self.player_count.to_string(), self.player_max.to_string(), self.server_guid.to_string(), - "Netrex".to_string(), + self.sub_name.clone(), self.gamemode.as_str().to_string(), - "1".to_string(), + if self.nintendo_limited { + "0".into() + } else { + "1".into() + }, // TODO: Figure out why this is not working // self.gamemode.to_string(), self.port.to_string(), @@ -110,6 +138,14 @@ impl Reader for Motd { .map(|c| c.to_string()) .collect::>(); + let edition = parts + .get(0) + .ok_or(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Invalid motd edition", + ))? + .clone(); + let name = parts .get(1) .ok_or(std::io::Error::new( @@ -158,6 +194,14 @@ impl Reader for Motd { ))? .clone(); + let sub_name = parts + .get(7) + .ok_or(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Invalid motd sub name", + ))? + .clone(); + let gamemode = parts .get(8) .ok_or(std::io::Error::new( @@ -166,6 +210,14 @@ impl Reader for Motd { ))? .clone(); + let nintendo_limited = parts + .get(9) + .ok_or(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Invalid motd nintendo limited", + ))? + .clone(); + let port = parts .get(10) .ok_or(std::io::Error::new( @@ -183,23 +235,16 @@ impl Reader for Motd { .clone(); Ok(Motd { + edition, name, protocol: protocol.as_str().parse().unwrap(), version, player_count: player_count.parse().unwrap(), player_max: player_max.parse().unwrap(), server_guid: server_guid.parse().unwrap(), - gamemode: match gamemode - .as_str() - .parse::() - .expect("Gamemode is not a byte") - { - 0 => Gamemode::Survival, - 1 => Gamemode::Creative, - 2 => Gamemode::Adventure, - 3 => Gamemode::Spectator, - _ => Gamemode::Survival, - }, + sub_name, + gamemode: Gamemode::from_str(&gamemode).unwrap_or(Gamemode::Survival), + nintendo_limited: if nintendo_limited == "0" { true } else { false }, port, ipv6_port, }) From 4b3108e2457d02a75e162a8386c3b01ede0269a4 Mon Sep 17 00:00:00 2001 From: GoodLucky777 Date: Sat, 3 Feb 2024 23:00:18 +0900 Subject: [PATCH 2/2] fix: typo --- src/client/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 5343b1c..7c7bdea 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -170,7 +170,7 @@ pub struct Client { /// The receive queue is used internally to receive packets from the server. /// This is read from before sending recv_queue: Arc>, - /// The network recieve channel is used to receive raw packets from the server. + /// The network receive channel is used to receive raw packets from the server. network_recv: Option>>>>, /// The internal channel that is used to dispatch packets to a higher level. internal_recv: Receiver>, @@ -573,7 +573,7 @@ impl Client { match packet { RakPacket::Offline(offline) => match offline { OfflinePacket::UnconnectedPong(pong) => { - rakrs_debug!(true, "[CLIENT] Recieved pong packet!"); + rakrs_debug!(true, "[CLIENT] Received pong packet!"); return Ok(pong); } _ => {} @@ -582,7 +582,7 @@ impl Client { } } Err(_) => { - rakrs_debug!(true, "[CLIENT] Failed to recieve anything on netowrk channel, is there a sender?"); + rakrs_debug!(true, "[CLIENT] Failed to receive anything on network channel, is there a sender?"); continue; } } @@ -628,19 +628,19 @@ impl Client { ($pk_recv: expr) => { #[cfg(feature = "async_std")] if let Err(_) = $pk_recv { - rakrs_debug!(true, "[CLIENT] (recv_task) Failed to recieve anything on netowrk channel, is there a sender?"); + rakrs_debug!(true, "[CLIENT] (recv_task) Failed to receive anything on network channel, is there a sender?"); continue; } #[cfg(feature = "async_tokio")] if let None = $pk_recv { - rakrs_debug!(true, "[CLIENT] (recv_task) Failed to recieve anything on netowrk channel, is there a sender?"); + rakrs_debug!(true, "[CLIENT] (recv_task) Failed to receive anything on network channel, is there a sender?"); continue; } recv_time.store(current_epoch(), std::sync::atomic::Ordering::Relaxed); - rakrs_debug!(true, "[CLIENT] (recv_task) Recieved packet!"); + rakrs_debug!(true, "[CLIENT] (recv_task) Received packet!"); let mut client_state = state.lock().await; @@ -703,13 +703,13 @@ impl Client { // todo: add ping time to client rakrs_debug!( true, - "[CLIENT] Recieved pong packet!" + "[CLIENT] Received pong packet!" ); } OnlinePacket::Disconnect(_) => { rakrs_debug!( true, - "[CLIENT] Recieved disconnect packet!" + "[CLIENT] Received disconnect packet!" ); break 'task_loop; } @@ -727,7 +727,7 @@ impl Client { } }, RakPacket::Offline(_) => { - rakrs_debug!("[CLIENT] Recieved offline packet after handshake! In future versions this will kill the client."); + rakrs_debug!("[CLIENT] Received offline packet after handshake! In future versions this will kill the client."); } } } else {