use std::{ str::FromStr, time::{Duration, Instant}, }; use elytra_ping::{ connect, parse::JavaServerInfo, protocol::{Frame, ProtocolError, SlpProtocol}, }; async fn next_frame(connection: &mut SlpProtocol) -> Result { Ok(connection .read_frame(None) .await? .expect("Connection closed before response was received")) } #[tokio::main] async fn main() -> Result<(), ProtocolError> { let args = std::env::args().collect::>(); let host = args .get(1) .map(String::to_string) .expect("address required"); let port = args .get(2) .map(|port| port.parse().expect("invalid port")) .unwrap_or(25565); println!("Connecting to {}:{}", host, port); let mut connection = connect((host, port)).await?; println!("Connected."); connection .write_frame(connection.create_handshake_frame()) .await?; println!("Sent handshake frame"); tokio::time::sleep(Duration::from_millis(250)).await; connection .write_frame(elytra_ping::protocol::Frame::StatusRequest) .await?; println!("Requested status"); let frame = next_frame(&mut connection).await?; if let Frame::StatusResponse { json } = frame { println!("JSON: {json}"); match JavaServerInfo::from_str(&json) { Ok(info) => println!("Server info: {:#?}", info), Err(error) => { println!("Error parsing server info: {error}"); } } } else { println!("Error: received invalid response: {:?}", frame); } let ping_time = Instant::now(); // the payload can be anything - it will be sent back by the server let ping_payload: i64 = 999; connection .write_frame(Frame::PingRequest { payload: ping_payload, }) .await?; println!("Checking latency"); let frame = next_frame(&mut connection).await?; if let Frame::PingResponse { payload } = frame { assert_eq!( payload, ping_payload, "server's ping response did not match our request" ); println!("Latency: {}ms", ping_time.elapsed().as_millis()); } else { println!("Error: received invalid response: {:?}", frame); } connection.disconnect().await?; println!("Disconnected"); Ok(()) }