Add example for tracking joining/leaving players
This commit is contained in:
parent
e5a289ea73
commit
8e99a7016e
102
examples/watch.rs
Normal file
102
examples/watch.rs
Normal file
@ -0,0 +1,102 @@
|
||||
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!()
|
||||
};
|
||||
|
||||
// <address:port> running <software> v<version>
|
||||
println!("{} running {} v{}",
|
||||
address,
|
||||
response.software.unwrap_or("Minecraft".to_owned()),
|
||||
response.kv["version"]
|
||||
);
|
||||
|
||||
// MOTD
|
||||
println!("{}", response.kv["hostname"]);
|
||||
|
||||
// Players (<online>/<max>): <player+>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user