diff --git a/server/Cargo.toml b/server/Cargo.toml index f2b66cf..d0c08c2 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -25,6 +25,7 @@ tap = "1.0.1" config = "0.13.4" dot_vox = "5.1.1" rand = "0.8.5" +ping-rs = "0.1.2" [lints] workspace = true \ No newline at end of file diff --git a/server/src/addon/command_manager.rs b/server/src/addon/command_manager.rs index b01753a..695923d 100644 --- a/server/src/addon/command_manager.rs +++ b/server/src/addon/command_manager.rs @@ -33,6 +33,7 @@ impl CommandManager { manager.register(Who); manager.register(WhoIp); manager.register(Player); + manager.register(Ping); manager.register(Xp); manager.register(Level); manager.register(Countdown); diff --git a/server/src/addon/command_manager/commands.rs b/server/src/addon/command_manager/commands.rs index 06c7b6e..4f682d4 100644 --- a/server/src/addon/command_manager/commands.rs +++ b/server/src/addon/command_manager/commands.rs @@ -15,6 +15,7 @@ mod test; mod team; mod act; mod heal; +mod ping; #[derive(Debug, PartialEq, Eq, Hash, Clone, Default)] pub struct Who; @@ -22,6 +23,8 @@ pub struct Who; pub struct WhoIp; #[derive(Debug, PartialEq, Eq, Hash, Clone, Default)] pub struct Player; +#[derive(Debug, PartialEq, Eq, Hash, Clone, Default)] +pub struct Ping; #[derive(Debug, PartialEq, Eq, Hash, Clone, Default)] pub struct Xp; diff --git a/server/src/addon/command_manager/commands/ping.rs b/server/src/addon/command_manager/commands/ping.rs new file mode 100644 index 0000000..72d0995 --- /dev/null +++ b/server/src/addon/command_manager/commands/ping.rs @@ -0,0 +1,28 @@ +use std::str::SplitWhitespace; +use std::sync::Arc; +use std::time::Duration; + +use crate::addon::command_manager::{Command, CommandResult}; +use crate::addon::command_manager::commands::Ping; +use crate::server::player::Player; +use crate::server::Server; +use ping_rs::*; + +impl Command for Ping { + const LITERAL: &'static str = "ping"; + const ADMIN_ONLY: bool = false; + + #[expect(clippy::significant_drop_in_scrutinee, clippy::significant_drop_tightening, reason = "cannot drop any earlier")] + async fn execute<'fut>(&'fut self, server: &'fut Server, caller: Option<&'fut Player>, params: &'fut mut SplitWhitespace<'fut>) -> CommandResult { + let target = server + .find_player(params.next().ok_or("no target specified")?).await + .ok_or("target not found")?; + let target_ip = target.address.ip(); + + let ping_reply = send_ping_async(&target_ip, Duration::from_secs(5), Arc::new(&[]), None) + .await.map_err(|_|"ping TimedOut or was ignored by the firewall")?; + let display = format!("{} round trip latency: {}ms", target.character.read().await.name, ping_reply.rtt); + + Ok(Some(display)) + } +} \ No newline at end of file