gn_matchmaking_state_types/
lib.rs

1use std::{collections::HashMap, time::SystemTime};
2
3use gn_redisadapter_derive::{
4    RedisIdentifiable, RedisInsertWriter, RedisOutputReader, RedisUpdater,
5};
6use serde::Deserialize;
7
8#[cfg(feature = "redis")]
9use gn_matchmaking_state::adapters::redis::RedisFilter;
10
11#[derive(Debug, Clone, PartialEq, Deserialize, RedisInsertWriter, RedisIdentifiable)]
12#[name("game_servers")]
13pub struct GameServer {
14    pub region: String,
15    pub game: String,
16    pub mode: String,
17    pub server_pub: String,
18    pub server_priv: String,
19    pub healthy: bool,
20    pub min_players: u32,
21    pub max_players: u32,
22}
23
24#[derive(Debug, Clone, RedisOutputReader, RedisIdentifiable)]
25#[name("game_servers")]
26pub struct DBGameServer {
27    #[cfg_attr(feature = "redis", uuid)]
28    pub uuid: String,
29    pub region: String,
30    pub game: String,
31    pub mode: String,
32    pub server_pub: String,
33    pub server_priv: String,
34    pub healthy: bool,
35    pub min_players: u32,
36    pub max_players: u32,
37}
38
39impl PartialEq for DBGameServer {
40    fn eq(&self, other: &Self) -> bool {
41        self.uuid == other.uuid
42    }
43}
44
45#[derive(Debug, Clone, Default, RedisUpdater)]
46#[name("game_servers")]
47pub struct GameServerUpdater {
48    pub game: Option<String>,
49    pub mode: Option<String>,
50    pub region: Option<String>,
51    pub server_pub: Option<String>,
52    pub server_priv: Option<String>,
53    pub healthy: Option<bool>,
54    pub min_players: Option<u32>,
55    pub max_players: Option<u32>,
56}
57
58#[derive(Debug, Default)]
59pub struct GameServerFilter {
60    pub game: Option<String>,
61}
62
63#[cfg(feature = "redis")]
64impl RedisFilter<DBGameServer> for GameServerFilter {
65    fn is_ok(&self, check: &DBGameServer) -> bool {
66        if self.game.is_none() {
67            return true;
68        }
69        return self.game.clone().unwrap() == check.game;
70    }
71}
72
73#[derive(Debug, Clone, RedisInsertWriter, RedisIdentifiable)]
74#[name("host_requests")]
75
76pub struct HostRequest {
77    pub player_id: String,
78    pub mode: String,
79    pub game: String,
80    pub region: String,
81    pub join_token: String,
82    pub joined_players: Vec<String>,
83    pub start_requested: bool,
84    pub min_players: u32,
85    pub max_players: u32,
86    pub wait_start: SystemTime,
87}
88
89#[derive(Debug, Clone, RedisOutputReader, RedisIdentifiable)]
90#[name("host_requests")]
91pub struct HostRequestDB {
92    #[cfg_attr(feature = "redis", uuid)]
93    pub uuid: String,
94    pub player_id: String,
95    pub mode: String,
96    pub game: String,
97    pub region: String,
98    pub join_token: String,
99    pub joined_players: Vec<String>,
100    pub start_requested: bool,
101    pub min_players: u32,
102    pub max_players: u32,
103    pub wait_start: SystemTime,
104}
105
106#[derive(Debug, Clone, Default, RedisUpdater)]
107#[name("host_requests")]
108pub struct HostRequestUpdate {
109    pub player_id: Option<String>,
110    pub mode: Option<String>,
111    pub game: Option<String>,
112    pub region: Option<String>,
113    pub join_token: Option<String>,
114    pub joined_players: Option<Vec<String>>,
115    pub start_requested: Option<bool>,
116    pub min_players: Option<u32>,
117    pub max_players: Option<u32>,
118    pub wait_start: Option<SystemTime>,
119}
120#[derive(Debug, Clone, RedisInsertWriter, RedisIdentifiable)]
121#[name("searchers")]
122pub struct Searcher {
123    pub player_id: String,
124    pub elo: u32,
125    pub mode: String,
126    pub ai: Option<String>,
127    pub game: String,
128    pub region: String,
129    pub min_players: u32,
130    pub max_players: u32,
131    pub wait_start: SystemTime,
132}
133
134#[derive(Debug, Clone, RedisUpdater)]
135#[name("searchers")]
136pub struct SearcherUpdate {
137    pub player_id: Option<String>,
138    pub elo: Option<u32>,
139    pub mode: Option<String>,
140    pub ai: Option<Option<String>>,
141    pub game: Option<String>,
142    pub region: Option<String>,
143    pub wait_start: Option<SystemTime>,
144}
145
146#[derive(Debug, Clone, RedisOutputReader, RedisIdentifiable)]
147#[name("searchers")]
148pub struct DBSearcher {
149    #[cfg_attr(feature = "redis", uuid)]
150    pub uuid: String,
151    pub player_id: String,
152    pub elo: u32,
153    pub mode: String,
154    pub ai: Option<String>,
155    pub game: String,
156    pub region: String,
157    pub min_players: u32,
158    pub max_players: u32,
159    pub wait_start: SystemTime,
160}
161
162#[derive(Debug, Default)]
163pub struct SearcherFilter {
164    pub game: Option<String>,
165    pub mode: Option<String>,
166}
167
168#[cfg(feature = "redis")]
169#[derive(Debug, Clone, RedisInsertWriter, RedisOutputReader, RedisIdentifiable)]
170#[name("config")]
171#[single_instance(true)]
172pub struct SearcherMatchConfig {
173    pub max_elo_diff: u32,
174    pub wait_time_to_elo_factor: f32,
175    pub wait_time_to_server_factor: f32,
176}
177
178#[derive(Debug, Clone, RedisInsertWriter, RedisIdentifiable)]
179#[name("active_matches")]
180pub struct ActiveMatch {
181    pub game: String,
182    pub mode: String,
183    pub ai: bool,
184    pub server_pub: String,
185    pub server_priv: String,
186    pub region: String,
187    pub read: String,
188    pub player_write: HashMap<String, String>,
189    pub chat_id: String
190}
191
192#[derive(Debug, Clone, RedisOutputReader, RedisIdentifiable)]
193#[name("active_matches")]
194pub struct ActiveMatchDB {
195    #[cfg_attr(feature = "redis", uuid)]
196    pub uuid: String,
197    pub game: String,
198    pub mode: String,
199    pub ai: bool,
200    pub server_pub: String,
201    pub server_priv: String,
202    pub region: String,
203    pub read: String,
204    pub player_write: HashMap<String, String>,
205    pub chat_id: String
206}
207
208#[derive(Debug, Clone, RedisInsertWriter, RedisIdentifiable)]
209#[name("ai_players")]
210pub struct AIPlayer {
211    pub game: String,
212    pub mode: String,
213    pub elo: u32,
214    pub display_name: String,
215}
216
217#[derive(Debug, Clone, RedisOutputReader, RedisIdentifiable)]
218#[name("ai_players")]
219pub struct AIPlayerDB {
220    #[uuid]
221    pub uuid: String,
222    pub game: String,
223    pub mode: String,
224    pub elo: u32,
225    pub display_name: String,
226}
227
228#[cfg(test)]
229mod tests {
230    use std::error::Error;
231
232    use gn_matchmaking_state::adapters::{Gettable, Insertable, Removable, Updateable};
233
234    #[test]
235
236    fn test_redis_adapter_insert_game_server() {
237        use super::*;
238        use gn_matchmaking_state::adapters::redis::publisher::native::RedisInfoPublisher;
239        use gn_matchmaking_state::adapters::redis::RedisAdapter;
240        use gn_matchmaking_state::adapters::Insertable;
241
242        let adapter = RedisAdapter::connect("redis://0.0.0.0:6379").unwrap();
243        let publisher = RedisInfoPublisher::new(adapter.client.get_connection().unwrap());
244        let adapter = adapter.with_publisher(publisher);
245
246        let game_server = GameServer {
247            region: "eu".to_owned(),
248            game: "Test Server".to_owned(),
249            mode: "Test Mode".to_owned(),
250            server_pub: "127.0.0.1:3456".to_owned(),
251            server_priv: "127.0.0.1:3456".to_owned(),
252            healthy: true,
253            min_players: 2,
254            max_players: 2,
255        };
256        adapter.insert(game_server).unwrap();
257    }
258
259    #[test]
260    fn test_redis_adapter_all_game_server() {
261        use super::*;
262        use gn_matchmaking_state::adapters::redis::publisher::native::RedisInfoPublisher;
263        use gn_matchmaking_state::adapters::redis::RedisAdapter;
264
265        let adapter = RedisAdapter::connect("redis://0.0.0.0:6379").unwrap();
266        let publisher = RedisInfoPublisher::new(adapter.client.get_connection().unwrap());
267        let adapter = adapter.with_publisher(publisher);
268
269        let game_server = GameServer {
270            region: "eu".to_owned(),
271            game: "Test Server".to_owned(),
272            mode: "Test Mode".to_owned(),
273            server_pub: "127.0.0.1:3456".to_owned(),
274            server_priv: "127.0.0.1:3456".to_owned(),
275            healthy: true,
276            min_players: 2,
277            max_players: 2,
278        };
279        adapter.insert(game_server.clone()).unwrap();
280
281        let found_server = adapter.all().unwrap().collect::<Vec<DBGameServer>>();
282
283        for game in &found_server {
284            println!("{:?}", game);
285        }
286
287        assert!(found_server.len() > 0);
288        assert!(found_server.iter().any(|x| x.game == game_server.game));
289    }
290
291    #[test]
292    fn test_redis_adapter_remove_game_server() {
293        use super::*;
294        use gn_matchmaking_state::adapters::redis::publisher::native::RedisInfoPublisher;
295        use gn_matchmaking_state::adapters::redis::RedisAdapter;
296
297        let adapter = RedisAdapter::connect("redis://0.0.0.0:6379").unwrap();
298        let publisher = RedisInfoPublisher::new(adapter.client.get_connection().unwrap());
299        let adapter = adapter.with_publisher(publisher);
300
301        let game_server = GameServer {
302            region: "eu".to_owned(),
303            game: "Test Server".to_owned(),
304            mode: "Test Mode".to_owned(),
305            server_pub: "127.0.0.1:3456".to_owned(),
306            server_priv: "127.0.0.1:3456".to_owned(),
307            healthy: true,
308            min_players: 2,
309            max_players: 2,
310        };
311        let uuid = adapter.insert(game_server.clone()).unwrap();
312
313        adapter.remove(&uuid).unwrap();
314
315        let game: Result<DBGameServer, Box<dyn Error>> = adapter.get(&uuid);
316        assert!(game.is_err());
317    }
318
319    #[test]
320    fn test_redis_adapter_update_game_server() {
321        use super::*;
322        use gn_matchmaking_state::adapters::redis::publisher::native::RedisInfoPublisher;
323        use gn_matchmaking_state::adapters::redis::RedisAdapter;
324
325        let adapter = RedisAdapter::connect("redis://0.0.0.0:6379").unwrap();
326        let publisher = RedisInfoPublisher::new(adapter.client.get_connection().unwrap());
327        let adapter = adapter.with_publisher(publisher);
328
329        let game_server = GameServer {
330            region: "eu".to_owned(),
331            game: "Test Server".to_owned(),
332            mode: "Test Mode".to_owned(),
333            server_pub: "127.0.0.1:3456".to_owned(),
334            server_priv: "127.0.0.1:3456".to_owned(),
335            healthy: true,
336            min_players: 2,
337            max_players: 2,
338        };
339        let uuid = adapter.insert(game_server.clone()).unwrap();
340
341        let mut update = GameServerUpdater::default();
342        update.game = Some("CSS Battle (Cum Sum Sus Battle)".to_owned());
343        adapter.update(&uuid, update).unwrap();
344
345        let result: DBGameServer = adapter.get(&uuid).unwrap();
346
347        assert!(result.game == "CSS Battle (Cum Sum Sus Battle)");
348    }
349}