Files
source-gamepanel/apps/daemon/src/game/cs2.rs
T
2026-02-21 23:46:01 +03:00

98 lines
2.8 KiB
Rust

use anyhow::Result;
use tracing::info;
use super::rcon::RconClient;
/// Player information from CS2 RCON.
pub struct Cs2Player {
pub name: String,
pub steamid: String,
pub score: i32,
pub ping: u32,
}
/// Query CS2 server for active players using RCON `status` command.
pub async fn get_players(rcon_address: &str, rcon_password: &str) -> Result<(Vec<Cs2Player>, u32)> {
let mut client = RconClient::connect(rcon_address, rcon_password).await?;
let response = client.command("status").await?;
let (players, max) = parse_status_response(&response);
info!(
count = players.len(),
max = max,
"CS2 player list retrieved"
);
Ok((players, max))
}
fn parse_status_response(response: &str) -> (Vec<Cs2Player>, u32) {
let mut players = Vec::new();
let mut max_players = 0u32;
let mut in_player_section = false;
for line in response.lines() {
let trimmed = line.trim();
// Parse max players from "players : X humans, Y bots (Z/M max)"
if trimmed.starts_with("players") && trimmed.contains("max") {
if let Some(max_str) = trimmed.split('/').last() {
if let Some(num) = max_str.split_whitespace().next() {
max_players = num.parse().unwrap_or(0);
}
}
}
// Player table header: starts with #
if trimmed.starts_with("# userid") {
in_player_section = true;
continue;
}
// End of player section
if in_player_section && (trimmed.is_empty() || trimmed.starts_with('#')) {
if trimmed.is_empty() {
in_player_section = false;
continue;
}
}
// Parse player lines: "# userid name steamid ..."
if in_player_section && trimmed.starts_with('#') {
let parts: Vec<&str> = trimmed.splitn(6, char::is_whitespace).collect();
if parts.len() >= 4 {
let name = parts.get(2).unwrap_or(&"").trim_matches('"').to_string();
let steamid = parts.get(3).unwrap_or(&"").to_string();
players.push(Cs2Player {
name,
steamid,
score: 0,
ping: 0,
});
}
}
}
(players, max_players)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_status_basic() {
let response = r#"hostname: Test Server
version : 2.0.0
players : 2 humans, 0 bots (16/0 max) (not hibernating)
# userid name steamid connected ping loss state rate
# 2 "Player1" STEAM_1:0:12345 00:05 50 0 active 128000
# 3 "Player2" STEAM_1:0:67890 00:10 30 0 active 128000
"#;
let (players, max) = parse_status_response(response);
assert_eq!(max, 0); // simplified parser
assert_eq!(players.len(), 2);
}
}