You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

664 lines
22 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #![allow(dead_code, unused_must_use)]
  2. use std::collections::HashMap;
  3. use std::time::SystemTime;
  4. use thiserror::Error;
  5. use crate::common::serverstate::ClientId;
  6. use async_std::sync::{Arc, RwLock};
  7. use futures::{stream, StreamExt};
  8. use std::pin::pin;
  9. pub const MAX_ROOMS: usize = 128;
  10. pub enum AreaType {
  11. Room,
  12. Lobby,
  13. }
  14. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  15. pub struct LobbyId(pub usize);
  16. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)]
  17. pub struct RoomId(pub usize);
  18. impl LobbyId {
  19. pub fn id(&self) -> u8 {
  20. self.0 as u8
  21. }
  22. }
  23. #[derive(Error, Debug, PartialEq, Eq)]
  24. #[error("create room")]
  25. pub enum CreateRoomError {
  26. NoOpenSlots,
  27. ClientInAreaAlready,
  28. JoinError,
  29. }
  30. #[derive(Error, Debug, PartialEq, Eq)]
  31. #[error("join room")]
  32. pub enum JoinRoomError {
  33. RoomDoesNotExist,
  34. RoomFull,
  35. ClientInAreaAlready,
  36. }
  37. #[derive(Error, Debug, PartialEq, Eq)]
  38. #[error("join lobby")]
  39. pub enum JoinLobbyError {
  40. LobbyDoesNotExist,
  41. LobbyFull,
  42. ClientInAreaAlready,
  43. }
  44. #[derive(Error, Debug, PartialEq, Eq)]
  45. #[error("get area")]
  46. pub enum GetAreaError {
  47. NotInRoom,
  48. NotInLobby,
  49. InvalidClient,
  50. }
  51. #[derive(Error, Debug, PartialEq, Eq)]
  52. #[error("client removal")]
  53. pub enum ClientRemovalError {
  54. ClientNotInArea,
  55. InvalidArea,
  56. }
  57. #[derive(Error, Debug, PartialEq, Eq)]
  58. pub enum GetClientsError {
  59. #[error("invalid client")]
  60. InvalidClient,
  61. #[error("invalid area")]
  62. InvalidArea,
  63. }
  64. #[derive(Error, Debug, PartialEq, Eq)]
  65. #[error("get neighbor")]
  66. pub enum GetNeighborError {
  67. InvalidClient,
  68. InvalidArea,
  69. }
  70. #[derive(Error, Debug, PartialEq, Eq)]
  71. #[error("get leader")]
  72. pub enum GetLeaderError {
  73. InvalidClient,
  74. InvalidArea,
  75. NoClientInArea,
  76. }
  77. #[derive(Error, Debug, PartialEq, Eq)]
  78. pub enum ClientLocationError {
  79. #[error("create room error {0}")]
  80. CreateRoomError(#[from] CreateRoomError),
  81. #[error("join room error {0}")]
  82. JoinRoomError(#[from] JoinRoomError),
  83. #[error("join lobby error {0}")]
  84. JoinLobbyError(#[from] JoinLobbyError),
  85. #[error("get area error {0}")]
  86. GetAreaError(#[from] GetAreaError),
  87. #[error("client removal error {0}")]
  88. ClientRemovalError(#[from] ClientRemovalError),
  89. #[error("get clients error {0}")]
  90. GetClientsError(#[from] GetClientsError),
  91. #[error("get neighbor error {0}")]
  92. GetNeighborError(#[from] GetNeighborError),
  93. #[error("get leader error {0}")]
  94. GetLeaderError(#[from] GetLeaderError)
  95. }
  96. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  97. pub struct LocalClientId(usize);
  98. impl LocalClientId {
  99. pub fn id(&self) -> u8 {
  100. self.0 as u8
  101. }
  102. }
  103. impl PartialEq<u8> for LocalClientId {
  104. fn eq(&self, other: &u8) -> bool {
  105. self.0 == *other as usize
  106. }
  107. }
  108. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  109. pub struct AreaClient {
  110. pub client: ClientId,
  111. pub local_client: LocalClientId,
  112. time_join: SystemTime,
  113. }
  114. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  115. struct Lobby([Option<AreaClient>; 12]);
  116. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  117. struct Room([Option<AreaClient>; 4]);
  118. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  119. pub enum RoomLobby {
  120. Room(RoomId),
  121. Lobby(LobbyId),
  122. }
  123. #[derive(Clone, Debug)]
  124. pub struct ClientLocation {
  125. lobbies: [Arc<RwLock<Lobby>>; 15],
  126. rooms: [Arc<RwLock<Option<Room>>>; MAX_ROOMS],
  127. client_location: Arc<RwLock<HashMap<ClientId, RoomLobby>>>,
  128. }
  129. impl Default for ClientLocation {
  130. fn default() -> ClientLocation {
  131. ClientLocation {
  132. lobbies: core::array::from_fn(|_| Arc::new(RwLock::new(Lobby([None; 12])))),
  133. rooms: core::array::from_fn(|_| Arc::new(RwLock::new(None))),
  134. client_location: Arc::new(RwLock::new(HashMap::new())),
  135. }
  136. }
  137. }
  138. impl ClientLocation {
  139. pub async fn add_client_to_lobby(&self, id: ClientId, lobby_id: LobbyId) -> Result<(), JoinLobbyError> {
  140. {
  141. let lobby = self.lobbies
  142. .get(lobby_id.0)
  143. .ok_or(JoinLobbyError::LobbyDoesNotExist)?
  144. .read()
  145. .await;
  146. if lobby.0.iter().all(|c| c.is_some()) {
  147. return Err(JoinLobbyError::LobbyFull);
  148. }
  149. }
  150. self.remove_client_from_area(id).await;
  151. let mut lobby = self.lobbies
  152. .get(lobby_id.0)
  153. .ok_or(JoinLobbyError::LobbyDoesNotExist)?
  154. .write()
  155. .await;
  156. let (index, empty_slot) = lobby.0.iter_mut()
  157. .enumerate()
  158. .find(|(_, k)| k.is_none())
  159. .ok_or(JoinLobbyError::LobbyFull)?;
  160. *empty_slot = Some(AreaClient {
  161. client: id,
  162. local_client: LocalClientId(index),
  163. time_join: SystemTime::now(),
  164. });
  165. self.client_location
  166. .write()
  167. .await
  168. .insert(id, RoomLobby::Lobby(lobby_id));
  169. Ok(())
  170. }
  171. pub async fn add_client_to_next_available_lobby(&self, id: ClientId, lobby: LobbyId) -> Result<LobbyId, JoinLobbyError> {
  172. pin!(stream::iter(0..15)
  173. .filter_map(|lobby_index| async move {
  174. let new_lobby = LobbyId((lobby.0 + lobby_index) % 15);
  175. Some((new_lobby, self.add_client_to_lobby(id, new_lobby).await.ok()?))
  176. }))
  177. .next()
  178. .await
  179. .map(|l| l.0)
  180. .ok_or(JoinLobbyError::LobbyFull)
  181. }
  182. pub async fn create_new_room(&mut self, id: ClientId) -> Result<RoomId, CreateRoomError> {
  183. let (index, empty_slot) = Box::pin(stream::iter(self.rooms.iter())
  184. .enumerate()
  185. .filter(|(_, r)| async {r.read().await.is_none()}))
  186. .next()
  187. .await
  188. .ok_or(CreateRoomError::NoOpenSlots)?;
  189. *empty_slot.write().await = Some(Room([None; 4]));
  190. self.add_client_to_room(id, RoomId(index))
  191. .await
  192. .map_err(|_err| CreateRoomError::JoinError)?;
  193. Ok(RoomId(index))
  194. }
  195. pub async fn add_client_to_room(&mut self, id: ClientId, room: RoomId) -> Result<(), JoinRoomError> {
  196. let mut r = self.rooms.get(room.0)
  197. .ok_or(JoinRoomError::RoomDoesNotExist)?
  198. .as_ref()
  199. .write()
  200. .await;
  201. let r = r.as_mut()
  202. .ok_or(JoinRoomError::RoomDoesNotExist)?;
  203. let (index, empty_slot) = r.0.iter_mut()
  204. .enumerate()
  205. .find(|(_, k)| k.is_none())
  206. .ok_or(JoinRoomError::RoomFull)?;
  207. *empty_slot = Some(AreaClient {
  208. client: id,
  209. local_client: LocalClientId(index),
  210. time_join: SystemTime::now(),
  211. });
  212. self.remove_client_from_area(id).await;
  213. self.client_location
  214. .write()
  215. .await
  216. .insert(id, RoomLobby::Room(room));
  217. Ok(())
  218. }
  219. pub async fn get_all_clients_by_client(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
  220. let area = self.client_location
  221. .read()
  222. .await;
  223. let area = area
  224. .get(&id)
  225. .ok_or(GetNeighborError::InvalidClient)?;
  226. match area {
  227. RoomLobby::Room(room) => {
  228. Ok(self.get_clients_in_room(*room).await.map_err(|_| GetNeighborError::InvalidArea)?
  229. .into_iter()
  230. .collect())
  231. },
  232. RoomLobby::Lobby(lobby) => {
  233. Ok(self.get_clients_in_lobby(*lobby).await.map_err(|_| GetNeighborError::InvalidArea)?
  234. .into_iter()
  235. .collect())
  236. }
  237. }
  238. }
  239. pub async fn get_client_neighbors(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
  240. let area = self.client_location
  241. .read()
  242. .await;
  243. let area = area
  244. .get(&id)
  245. .ok_or(GetNeighborError::InvalidClient)?;
  246. match area {
  247. RoomLobby::Room(room) => {
  248. Ok(self.get_clients_in_room(*room).await.map_err(|_| GetNeighborError::InvalidArea)?
  249. .into_iter()
  250. .filter(|c| c.client != id)
  251. .collect())
  252. },
  253. RoomLobby::Lobby(lobby) => {
  254. Ok(self.get_clients_in_lobby(*lobby).await.map_err(|_| GetNeighborError::InvalidArea)?
  255. .into_iter()
  256. .filter(|c| c.client != id)
  257. .collect())
  258. }
  259. }
  260. }
  261. pub async fn get_room_leader(&self, room: RoomId) -> Result<AreaClient, GetLeaderError> {
  262. let r = self.rooms[room.0]
  263. .as_ref()
  264. .read()
  265. .await
  266. .ok_or(GetLeaderError::InvalidArea)?;
  267. let mut r = r
  268. .0
  269. .iter()
  270. .flatten()
  271. .collect::<Vec<_>>();
  272. r.sort_by_key(|k| k.time_join);
  273. let c = r.get(0)
  274. .ok_or(GetLeaderError::NoClientInArea)?;
  275. Ok(**c)
  276. }
  277. pub async fn get_lobby_leader(&self, lobby: LobbyId) -> Result<AreaClient, GetLeaderError> {
  278. let l = self.lobbies[lobby.0]
  279. .read()
  280. .await;
  281. let mut l = l
  282. .0
  283. .iter()
  284. .flatten()
  285. .collect::<Vec<_>>();
  286. l.sort_by_key(|k| k.time_join);
  287. let c = l.get(0).ok_or(GetLeaderError::NoClientInArea)?;
  288. Ok(**c)
  289. }
  290. pub async fn get_area_leader(&self, roomlobby: RoomLobby) -> Result<AreaClient, GetLeaderError> {
  291. match roomlobby {
  292. RoomLobby::Room(room) => {
  293. self.get_room_leader(room).await
  294. },
  295. RoomLobby::Lobby(lobby) => {
  296. self.get_lobby_leader(lobby).await
  297. }
  298. }
  299. }
  300. pub async fn get_leader_by_client(&self, id: ClientId) -> Result<AreaClient, GetLeaderError> {
  301. let area = self.client_location
  302. .read()
  303. .await;
  304. let area = area
  305. .get(&id)
  306. .ok_or(GetLeaderError::InvalidClient)?;
  307. match area {
  308. RoomLobby::Room(room) => {
  309. self.get_room_leader(*room).await
  310. },
  311. RoomLobby::Lobby(lobby) => {
  312. self.get_lobby_leader(*lobby).await
  313. }
  314. }
  315. }
  316. pub async fn get_clients_in_lobby(&self, lobby: LobbyId) -> Result<Vec<AreaClient>, GetClientsError> {
  317. Ok(self.lobbies
  318. .get(lobby.0)
  319. .ok_or(GetClientsError::InvalidArea)?
  320. .read()
  321. .await
  322. .0
  323. .iter()
  324. .filter_map(|client| {
  325. client.map(|c| {
  326. c
  327. })
  328. }).collect())
  329. }
  330. pub async fn get_clients_in_room(&self, room: RoomId) -> Result<Vec<AreaClient>, GetClientsError> {
  331. Ok(self.rooms.get(room.0)
  332. .ok_or(GetClientsError::InvalidArea)?
  333. .as_ref()
  334. .read()
  335. .await
  336. .ok_or(GetClientsError::InvalidArea)?
  337. .0
  338. .iter()
  339. .filter_map(|client| {
  340. client.map(|c| {
  341. c
  342. })
  343. }).collect())
  344. }
  345. pub async fn get_local_client(&self, id: ClientId) -> Result<AreaClient, GetClientsError> {
  346. let area = self.client_location
  347. .read()
  348. .await;
  349. let area = area
  350. .get(&id)
  351. .ok_or(GetClientsError::InvalidClient)?;
  352. match area {
  353. RoomLobby::Room(room) => {
  354. self.get_clients_in_room(*room)
  355. .await
  356. .map_err(|_| GetClientsError::InvalidArea)?
  357. .into_iter()
  358. .find(|c| c.client == id)
  359. .ok_or(GetClientsError::InvalidClient)
  360. },
  361. RoomLobby::Lobby(lobby) => {
  362. self.get_clients_in_lobby(*lobby)
  363. .await
  364. .map_err(|_| GetClientsError::InvalidArea)?
  365. .into_iter()
  366. .find(|c| c.client == id)
  367. .ok_or(GetClientsError::InvalidClient)
  368. }
  369. }
  370. }
  371. pub async fn get_area(&self, id: ClientId) -> Result<RoomLobby, GetAreaError> {
  372. self.client_location
  373. .read()
  374. .await
  375. .get(&id)
  376. .ok_or(GetAreaError::InvalidClient)
  377. .map(Clone::clone)
  378. }
  379. pub async fn get_room(&self, id: ClientId) -> Result<RoomId, GetAreaError> {
  380. if let RoomLobby::Room(room) = self.client_location.read().await.get(&id).ok_or(GetAreaError::InvalidClient)? {
  381. Ok(*room)
  382. }
  383. else {
  384. Err(GetAreaError::NotInRoom)
  385. }
  386. }
  387. pub async fn get_lobby(&self, id: ClientId) -> Result<LobbyId, GetAreaError> {
  388. if let RoomLobby::Lobby(lobby) = self.client_location.read().await.get(&id).ok_or(GetAreaError::InvalidClient)? {
  389. Ok(*lobby)
  390. }
  391. else {
  392. Err(GetAreaError::NotInLobby)
  393. }
  394. }
  395. pub async fn remove_client_from_area(&self, id: ClientId) -> Result<(), ClientRemovalError> {
  396. fn remove_client<const N: usize>(id: ClientId, client_list : &mut [Option<AreaClient>; N]) {
  397. client_list
  398. .iter_mut()
  399. .filter(|client| {
  400. client.map_or(false, |c| {
  401. c.client == id
  402. })
  403. })
  404. .for_each(|client| {
  405. *client = None
  406. });
  407. }
  408. let area = self.client_location
  409. .read()
  410. .await;
  411. let area = area
  412. .get(&id)
  413. .ok_or(ClientRemovalError::ClientNotInArea)?;
  414. match area {
  415. RoomLobby::Room(room) => {
  416. let mut r = self.rooms.get(room.0)
  417. .ok_or(ClientRemovalError::InvalidArea)?
  418. .as_ref()
  419. .write()
  420. .await;
  421. if let Some(r) = r.as_mut() {
  422. remove_client(id, &mut r.0)
  423. }
  424. else {
  425. return Err(ClientRemovalError::InvalidArea)
  426. }
  427. },
  428. RoomLobby::Lobby(lobby) => {
  429. remove_client(id, &mut self.lobbies[lobby.0].write().await.0)
  430. }
  431. };
  432. Ok(())
  433. }
  434. }
  435. #[cfg(test)]
  436. mod test {
  437. use super::*;
  438. #[async_std::test]
  439. async fn test_add_client_to_lobby() {
  440. let cl = ClientLocation::default();
  441. cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await.unwrap();
  442. cl.add_client_to_lobby(ClientId(13), LobbyId(1)).await.unwrap();
  443. cl.add_client_to_lobby(ClientId(14), LobbyId(0)).await.unwrap();
  444. assert!(cl.get_clients_in_lobby(LobbyId(0)).await.into_iter().flatten().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
  445. (ClientId(12), LocalClientId(0)),
  446. (ClientId(14), LocalClientId(1)),
  447. ]);
  448. }
  449. #[async_std::test]
  450. async fn test_add_client_to_full_lobby() {
  451. let cl = ClientLocation::default();
  452. for i in 0..12 {
  453. cl.add_client_to_lobby(ClientId(i), LobbyId(0)).await.unwrap();
  454. }
  455. assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(0)).await == Err(JoinLobbyError::LobbyFull));
  456. }
  457. #[async_std::test]
  458. async fn test_add_client_to_next_available_lobby() {
  459. let cl = ClientLocation::default();
  460. for lobby in 1..4 {
  461. for i in 0..12 {
  462. cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby)).await.unwrap();
  463. }
  464. }
  465. assert!(cl.add_client_to_next_available_lobby(ClientId(99), LobbyId(1)).await == Ok(LobbyId(4)));
  466. }
  467. #[async_std::test]
  468. async fn test_add_to_lobby_when_all_are_full() {
  469. let cl = ClientLocation::default();
  470. for lobby in 0..15 {
  471. for i in 0..12 {
  472. cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby)).await.unwrap();
  473. }
  474. }
  475. assert_eq!(cl.add_client_to_next_available_lobby(ClientId(99), LobbyId(1)).await, Err(JoinLobbyError::LobbyFull));
  476. }
  477. #[async_std::test]
  478. async fn test_new_room() {
  479. let mut cl = ClientLocation::default();
  480. assert!(cl.create_new_room(ClientId(12)).await == Ok(RoomId(0)));
  481. }
  482. #[async_std::test]
  483. async fn test_add_client_to_room() {
  484. let mut cl = ClientLocation::default();
  485. let room = cl.create_new_room(ClientId(12)).await.unwrap();
  486. assert!(cl.add_client_to_room(ClientId(234), room).await == Ok(()));
  487. assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
  488. (ClientId(12), LocalClientId(0)),
  489. (ClientId(234), LocalClientId(1)),
  490. ]);
  491. }
  492. #[async_std::test]
  493. async fn test_no_new_room_slots() {
  494. let mut cl = ClientLocation::default();
  495. for i in 0..128 {
  496. cl.create_new_room(ClientId(i)).await;
  497. }
  498. assert!(cl.create_new_room(ClientId(234)).await == Err(CreateRoomError::NoOpenSlots));
  499. }
  500. #[async_std::test]
  501. async fn test_joining_full_room() {
  502. let mut cl = ClientLocation::default();
  503. let room = cl.create_new_room(ClientId(0)).await.unwrap();
  504. assert!(cl.add_client_to_room(ClientId(1), room).await == Ok(()));
  505. assert!(cl.add_client_to_room(ClientId(2), room).await == Ok(()));
  506. assert!(cl.add_client_to_room(ClientId(3), room).await == Ok(()));
  507. assert!(cl.add_client_to_room(ClientId(234), room).await == Err(JoinRoomError::RoomFull));
  508. }
  509. #[async_std::test]
  510. async fn test_adding_client_to_room_removes_from_lobby() {
  511. let mut cl = ClientLocation::default();
  512. cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await;
  513. cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await;
  514. cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await;
  515. cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await;
  516. let room = cl.create_new_room(ClientId(51)).await.unwrap();
  517. assert!(cl.add_client_to_room(ClientId(93), room).await == Ok(()));
  518. assert!(cl.get_clients_in_lobby(LobbyId(0)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
  519. (ClientId(23), LocalClientId(1)),
  520. (ClientId(12), LocalClientId(3)),
  521. ]);
  522. assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
  523. (ClientId(51), LocalClientId(0)),
  524. (ClientId(93), LocalClientId(1)),
  525. ]);
  526. }
  527. #[async_std::test]
  528. async fn test_getting_neighbors() {
  529. let cl = ClientLocation::default();
  530. cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await.unwrap();
  531. cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await.unwrap();
  532. cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await.unwrap();
  533. cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await.unwrap();
  534. assert!(cl.get_client_neighbors(ClientId(23)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
  535. (ClientId(93), LocalClientId(0)),
  536. (ClientId(51), LocalClientId(2)),
  537. (ClientId(12), LocalClientId(3)),
  538. ]);
  539. }
  540. #[async_std::test]
  541. async fn test_failing_to_join_lobby_does_not_remove_from_current_area() {
  542. let cl = ClientLocation::default();
  543. for i in 0..12 {
  544. cl.add_client_to_lobby(ClientId(i), LobbyId(0)).await.unwrap();
  545. }
  546. assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(1)).await.is_ok());
  547. assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(0)).await.is_err());
  548. assert_eq!(cl.get_clients_in_lobby(LobbyId(0)).await.unwrap().len(), 12);
  549. assert_eq!(
  550. cl.get_clients_in_lobby(LobbyId(1)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>(),
  551. vec![(ClientId(99), LocalClientId(0))]
  552. );
  553. }
  554. #[async_std::test]
  555. async fn test_get_leader() {
  556. let cl = ClientLocation::default();
  557. cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await;
  558. cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await;
  559. cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await;
  560. cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await;
  561. assert!(cl.get_leader_by_client(ClientId(51)).await.map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(0))));
  562. }
  563. #[async_std::test]
  564. async fn test_remove_client_from_room() {
  565. let mut cl = ClientLocation::default();
  566. let room = cl.create_new_room(ClientId(51)).await.unwrap();
  567. cl.add_client_to_room(ClientId(93), room).await;
  568. cl.add_client_to_room(ClientId(23), room).await;
  569. cl.remove_client_from_area(ClientId(51)).await;
  570. cl.add_client_to_room(ClientId(12), room).await;
  571. assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
  572. (ClientId(12), LocalClientId(0)),
  573. (ClientId(93), LocalClientId(1)),
  574. (ClientId(23), LocalClientId(2)),
  575. ]);
  576. }
  577. #[async_std::test]
  578. async fn test_leader_changes_on_leader_leaving() {
  579. let mut cl = ClientLocation::default();
  580. let room = cl.create_new_room(ClientId(51)).await.unwrap();
  581. cl.add_client_to_room(ClientId(93), room).await.unwrap();
  582. cl.add_client_to_room(ClientId(23), room).await.unwrap();
  583. cl.remove_client_from_area(ClientId(51)).await.unwrap();
  584. cl.add_client_to_room(ClientId(12), room).await.unwrap();
  585. cl.remove_client_from_area(ClientId(23)).await.unwrap();
  586. cl.add_client_to_room(ClientId(99), room).await.unwrap();
  587. assert!(cl.get_leader_by_client(ClientId(12)).await.map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(1))));
  588. }
  589. }