use mcquery::Query; use std::{ io::{ Result, Error, ErrorKind, }, time::Duration, env::args, }; #[tokio::main] async fn main() -> Result<()> { // get address let address = args() .nth(1).unwrap(); // initialize buffer let mut buffer = vec![ 0; args().nth(2) .unwrap_or("1024".to_owned()) .parse().map_err(|e| Error::new(ErrorKind::InvalidInput, e))? ]; // get initial status let mut response = match Query::get_full(address.clone(), Duration::from_secs(3), &mut buffer).await? { Query::Full(r) => r, _ => unreachable!() }; // running v println!("{} running {} v{}", address, response.software.unwrap_or("Minecraft".to_owned()), response.kv["version"] ); // MOTD println!("{}", response.kv["hostname"]); // Players (/): println!("Players ({:>width$}/{}): {}", response.kv["numplayers"], response.kv["maxplayers"], response.players.join(" "), width=response.kv["maxplayers"].len() ); // update status every second let mut interval = tokio::time::interval(Duration::from_secs(10)); loop { interval.tick().await; // get the new status let new_response = match Query::get_full(address.clone(), Duration::from_secs(3), &mut buffer).await? { Query::Full(r) => r, _ => unreachable!() }; // initialize player joining/leaving log let mut player_log = Vec::<(String, bool)>::new(); // reference buffer let mut player_ref = response.players.clone(); // figure out player joining/leaving sequence from order in response { let mut i = 0; loop { if i >= new_response.players.len() { player_log.extend(player_ref.drain(new_response.players.len()..).map(|p| (p, false))); break; } else if i == player_ref.len() { player_ref.push(new_response.players[i].clone()); player_log.push((new_response.players[i].clone(), true)); } else if player_ref[i] == new_response.players[i] { i += 1; } else if player_ref.len() > i { player_log.push((player_ref.remove(i), false)); } } } // if data is correct, print player joining/leaving log if player_ref == new_response.players { for (player, online) in player_log { println!("{} {} the game", player, if online { "joined" } else { "left" }); } } else { eprintln!("Error when parsing player joining/leaving"); } if response.players != new_response.players { response = new_response; } } }