steam_client/services/
gameservers.rs1use std::{collections::HashMap, net::Ipv4Addr};
6
7use steamid::SteamID;
8
9use crate::{error::SteamError, SteamClient};
10
11#[derive(Debug, Clone)]
13pub struct GameServer {
14 pub ip: String,
16 pub port: u16,
18 pub players: u32,
20 pub steamid: Option<SteamID>,
22 pub name: Option<String>,
24 pub map: Option<String>,
26 pub gamedir: Option<String>,
28 pub gamedesc: Option<String>,
30 pub appid: Option<u32>,
32 pub bots: Option<u32>,
34 pub max_players: Option<u32>,
36 pub password: Option<bool>,
38 pub secure: Option<bool>,
40 pub version: Option<String>,
42}
43
44impl SteamClient {
45 pub async fn server_query(&mut self, filter: &str) -> Result<Vec<GameServer>, SteamError> {
56 if !self.is_logged_in() {
57 return Err(SteamError::NotLoggedOn);
58 }
59
60 let msg = steam_protos::CMsgClientGMSServerQuery { filter_text: Some(filter.to_string()), ..Default::default() };
61
62 let response: steam_protos::CMsgGMSClientServerQueryResponse = self.send_request_and_wait(steam_enums::EMsg::ClientGMSServerQuery, &msg).await?;
63
64 if let Some(error) = response.error {
65 return Err(SteamError::Other(error));
66 }
67
68 let mut servers = Vec::new();
69 for server in response.servers {
70 let ip_str = if let Some(ip_addr) = server.server_ip {
71 if let Some(steam_protos::cmsg_ip_address::Ip::V4(v4)) = ip_addr.ip {
72 Ipv4Addr::from(v4).to_string()
73 } else {
74 continue; }
76 } else {
77 continue;
78 };
79
80 servers.push(GameServer {
81 ip: ip_str,
82 port: server.query_port.unwrap_or(0) as u16,
83 players: server.auth_players.unwrap_or(0),
84 steamid: None,
85 name: None,
86 map: None,
87 gamedir: None,
88 gamedesc: None,
89 appid: None,
90 bots: None,
91 max_players: None,
92 password: None,
93 secure: None,
94 version: None,
95 });
96 }
97
98 Ok(servers)
99 }
100
101 pub async fn get_server_list(&mut self, filter: &str, limit: u32) -> Result<Vec<GameServer>, SteamError> {
107 if !self.is_logged_in() {
108 return Err(SteamError::NotLoggedOn);
109 }
110
111 let msg = steam_protos::CGameServersGetServerListRequest { filter: Some(filter.to_string()), limit: Some(limit) };
112
113 let response: steam_protos::CGameServersGetServerListResponse = self.send_service_method_and_wait("GameServers.GetServerList#1", &msg).await?;
114
115 let mut servers = Vec::new();
116 for server in response.servers {
117 let parts: Vec<&str> = server.addr.as_deref().unwrap_or("").split(':').collect();
118 let ip = parts.first().unwrap_or(&"").to_string();
119 let port = parts.get(1).and_then(|p| p.parse().ok()).unwrap_or(0);
120
121 servers.push(GameServer {
122 ip,
123 port,
124 players: server.players.unwrap_or(0) as u32,
125 steamid: server.steamid.map(SteamID::from),
126 name: server.name,
127 map: server.map,
128 gamedir: server.gamedir,
129 gamedesc: server.gametype, appid: server.appid,
131 bots: server.bots.map(|b| b as u32),
132 max_players: server.max_players.map(|p| p as u32),
133 password: None, secure: server.secure,
135 version: server.version,
136 });
137 }
138
139 Ok(servers)
140 }
141
142 pub async fn get_server_steam_ids_by_ip(&mut self, ips: Vec<String>) -> Result<HashMap<String, SteamID>, SteamError> {
147 if !self.is_logged_in() {
148 return Err(SteamError::NotLoggedOn);
149 }
150
151 let msg = steam_protos::CGameServersGetServerSteamIDsByIPRequest { server_ips: ips };
152
153 let response: steam_protos::CGameServersIPsWithSteamIDsResponse = self.send_service_method_and_wait("GameServers.GetServerSteamIDsByIP#1", &msg).await?;
154
155 let mut result = HashMap::new();
156 for server in response.servers {
157 if let (Some(addr), Some(steamid)) = (server.addr, server.steamid) {
158 result.insert(addr, SteamID::from(steamid));
159 }
160 }
161
162 Ok(result)
163 }
164
165 pub async fn get_server_ips_by_steam_id(&mut self, steamids: Vec<SteamID>) -> Result<HashMap<SteamID, String>, SteamError> {
170 if !self.is_logged_in() {
171 return Err(SteamError::NotLoggedOn);
172 }
173
174 let msg = steam_protos::CGameServersGetServerIPsBySteamIDRequest { server_steamids: steamids.iter().map(|s| s.steam_id64()).collect() };
175
176 let response: steam_protos::CGameServersIPsWithSteamIDsResponse = self.send_service_method_and_wait("GameServers.GetServerIPsBySteamID#1", &msg).await?;
177
178 let mut result = HashMap::new();
179 for server in response.servers {
180 if let (Some(addr), Some(steamid)) = (server.addr, server.steamid) {
181 result.insert(SteamID::from(steamid), addr);
182 }
183 }
184
185 Ok(result)
186 }
187}