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