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.

676 lines
22 KiB

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