chore: initial commit for phase06
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{info, warn};
|
||||
use super::rcon::RconClient;
|
||||
|
||||
/// Player information from Minecraft RCON.
|
||||
pub struct MinecraftPlayer {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Query Minecraft server for active players using RCON `list` command.
|
||||
pub async fn get_players(rcon_address: &str, rcon_password: &str) -> Result<(Vec<MinecraftPlayer>, u32)> {
|
||||
let mut client = RconClient::connect(rcon_address, rcon_password).await?;
|
||||
let response = client.command("list").await?;
|
||||
|
||||
// Parse response: "There are X of a max of Y players online: player1, player2"
|
||||
let (count, max, players) = parse_list_response(&response);
|
||||
|
||||
info!(
|
||||
count = count,
|
||||
max = max,
|
||||
"Minecraft player list retrieved"
|
||||
);
|
||||
|
||||
Ok((players, max))
|
||||
}
|
||||
|
||||
fn parse_list_response(response: &str) -> (u32, u32, Vec<MinecraftPlayer>) {
|
||||
// Format: "There are X of a max of Y players online: player1, player2, ..."
|
||||
// Or: "There are X of a max Y players online:"
|
||||
let parts: Vec<&str> = response.splitn(2, ':').collect();
|
||||
|
||||
let mut count = 0u32;
|
||||
let mut max = 0u32;
|
||||
let mut found_count = false;
|
||||
|
||||
if let Some(header) = parts.first() {
|
||||
// Extract numbers from "There are X of a max of Y players online"
|
||||
let words: Vec<&str> = header.split_whitespace().collect();
|
||||
for word in words.iter() {
|
||||
if let Ok(n) = word.parse::<u32>() {
|
||||
if !found_count {
|
||||
count = n;
|
||||
found_count = true;
|
||||
} else {
|
||||
max = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut players = Vec::new();
|
||||
if parts.len() > 1 {
|
||||
let player_list = parts[1].trim();
|
||||
if !player_list.is_empty() {
|
||||
for name in player_list.split(',') {
|
||||
let name = name.trim();
|
||||
if !name.is_empty() {
|
||||
players.push(MinecraftPlayer {
|
||||
name: name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(count, max, players)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_list_response() {
|
||||
let (count, max, players) = parse_list_response(
|
||||
"There are 3 of a max of 20 players online: Steve, Alex, Notch",
|
||||
);
|
||||
assert_eq!(count, 3);
|
||||
assert_eq!(max, 20);
|
||||
assert_eq!(players.len(), 3);
|
||||
assert_eq!(players[0].name, "Steve");
|
||||
assert_eq!(players[1].name, "Alex");
|
||||
assert_eq!(players[2].name, "Notch");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_empty_list() {
|
||||
let (count, max, players) = parse_list_response(
|
||||
"There are 0 of a max of 20 players online:",
|
||||
);
|
||||
assert_eq!(count, 0);
|
||||
assert_eq!(max, 20);
|
||||
assert_eq!(players.len(), 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user