elseware/src/ship/location.rs

677 lines
22 KiB
Rust
Raw Normal View History

#![allow(dead_code, unused_must_use)]
2020-04-05 22:56:48 -07:00
use std::collections::HashMap;
2019-12-15 23:18:21 -08:00
use std::time::SystemTime;
2020-04-25 22:16:40 -06:00
use thiserror::Error;
2019-11-23 19:01:03 -08:00
use crate::common::serverstate::ClientId;
2022-09-18 21:01:32 -06:00
use async_std::sync::{Arc, RwLock};
use futures::{stream, StreamExt};
use std::pin::pin;
2020-01-02 20:24:17 -08:00
pub const MAX_ROOMS: usize = 128;
2020-04-06 23:40:39 -07:00
pub enum AreaType {
Room,
Lobby,
2019-12-15 23:18:21 -08:00
}
2019-11-23 19:01:03 -08:00
2020-04-05 22:56:48 -07:00
2022-07-19 12:34:07 -06:00
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2020-01-02 20:24:17 -08:00
pub struct LobbyId(pub usize);
2021-12-10 23:41:17 -07:00
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)]
2020-01-02 20:24:17 -08:00
pub struct RoomId(pub usize);
2019-11-23 19:01:03 -08:00
2020-04-06 23:40:39 -07:00
impl LobbyId {
pub fn id(&self) -> u8 {
self.0 as u8
}
2019-12-15 23:18:21 -08:00
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
2020-01-02 20:24:17 -08:00
pub enum CreateRoomError {
2023-01-28 20:12:20 -07:00
#[error("no open slots")]
2020-01-02 20:24:17 -08:00
NoOpenSlots,
2023-01-28 20:12:20 -07:00
#[error("client already in area")]
2020-01-02 20:24:17 -08:00
ClientInAreaAlready,
2023-01-28 20:12:20 -07:00
#[error("join error")]
2020-04-05 22:56:48 -07:00
JoinError,
2020-01-02 20:24:17 -08:00
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
pub enum JoinRoomError {
2023-01-28 20:12:20 -07:00
#[error("room does not exist")]
2019-11-23 19:01:03 -08:00
RoomDoesNotExist,
2023-01-28 20:12:20 -07:00
#[error("room is full")]
2019-11-23 19:01:03 -08:00
RoomFull,
2023-01-28 20:12:20 -07:00
#[error("client already in area")]
2020-01-02 20:24:17 -08:00
ClientInAreaAlready,
2019-11-23 19:01:03 -08:00
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
pub enum JoinLobbyError {
2023-01-28 20:12:20 -07:00
#[error("lobby does not exist")]
2019-11-23 19:01:03 -08:00
LobbyDoesNotExist,
2023-01-28 20:12:20 -07:00
#[error("lobby is full")]
2019-11-23 19:01:03 -08:00
LobbyFull,
2023-01-28 20:12:20 -07:00
#[error("client already in area")]
2020-01-02 20:24:17 -08:00
ClientInAreaAlready,
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
2020-04-25 22:16:40 -06:00
pub enum GetAreaError {
2023-01-28 20:12:20 -07:00
#[error("not in a room")]
NotInRoom,
2023-01-28 20:12:20 -07:00
#[error("not in a lobby")]
NotInLobby,
2023-01-28 20:12:20 -07:00
#[error("get area: invalid client")]
2020-04-25 22:16:40 -06:00
InvalidClient,
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
2020-04-25 22:16:40 -06:00
pub enum ClientRemovalError {
2023-01-28 20:12:20 -07:00
#[error("client removal: client not in area")]
2020-04-25 22:16:40 -06:00
ClientNotInArea,
2023-01-28 20:12:20 -07:00
#[error("client removal: invalid area")]
2020-04-25 22:16:40 -06:00
InvalidArea,
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
2020-04-25 22:16:40 -06:00
pub enum GetClientsError {
2022-10-22 14:05:38 -06:00
#[error("invalid client")]
2020-04-25 22:16:40 -06:00
InvalidClient,
2022-10-22 14:05:38 -06:00
#[error("invalid area")]
2020-04-25 22:16:40 -06:00
InvalidArea,
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
2020-04-25 22:16:40 -06:00
pub enum GetNeighborError {
2023-01-28 20:12:20 -07:00
#[error("get neighbor: invalid client")]
2020-04-25 22:16:40 -06:00
InvalidClient,
2023-01-28 20:12:20 -07:00
#[error("get neighbor: invalid area")]
2020-04-25 22:16:40 -06:00
InvalidArea,
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
2020-04-25 22:16:40 -06:00
pub enum GetLeaderError {
2023-01-28 20:12:20 -07:00
#[error("get leader: invalid client")]
2020-04-25 22:16:40 -06:00
InvalidClient,
2023-01-28 20:12:20 -07:00
#[error("get leader: invalid area")]
2020-04-25 22:16:40 -06:00
InvalidArea,
2023-01-28 20:12:20 -07:00
#[error("get leader: client not in area")]
2020-04-25 22:16:40 -06:00
NoClientInArea,
}
2022-07-19 12:34:07 -06:00
#[derive(Error, Debug, PartialEq, Eq)]
2020-04-25 22:16:40 -06:00
pub enum ClientLocationError {
2022-10-18 04:46:21 -06:00
#[error("create room error {0}")]
2020-04-25 22:16:40 -06:00
CreateRoomError(#[from] CreateRoomError),
2022-10-18 04:46:21 -06:00
#[error("join room error {0}")]
2020-04-25 22:16:40 -06:00
JoinRoomError(#[from] JoinRoomError),
2022-10-18 04:46:21 -06:00
#[error("join lobby error {0}")]
2020-04-25 22:16:40 -06:00
JoinLobbyError(#[from] JoinLobbyError),
2022-10-18 04:46:21 -06:00
#[error("get area error {0}")]
2020-04-25 22:16:40 -06:00
GetAreaError(#[from] GetAreaError),
2022-10-18 04:46:21 -06:00
#[error("client removal error {0}")]
2020-04-25 22:16:40 -06:00
ClientRemovalError(#[from] ClientRemovalError),
2022-10-18 04:46:21 -06:00
#[error("get clients error {0}")]
2020-04-25 22:16:40 -06:00
GetClientsError(#[from] GetClientsError),
2022-10-18 04:46:21 -06:00
#[error("get neighbor error {0}")]
2020-04-25 22:16:40 -06:00
GetNeighborError(#[from] GetNeighborError),
2022-10-18 04:46:21 -06:00
#[error("get leader error {0}")]
2020-04-25 22:16:40 -06:00
GetLeaderError(#[from] GetLeaderError)
}
2022-07-19 12:34:07 -06:00
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2020-04-05 22:56:48 -07:00
pub struct LocalClientId(usize);
2020-04-06 23:40:39 -07:00
impl LocalClientId {
pub fn id(&self) -> u8 {
self.0 as u8
}
2020-04-05 22:56:48 -07:00
}
2021-12-10 13:20:20 -07:00
impl PartialEq<u8> for LocalClientId {
fn eq(&self, other: &u8) -> bool {
self.0 == *other as usize
}
}
2022-07-19 12:34:07 -06:00
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2020-04-06 23:40:39 -07:00
pub struct AreaClient {
pub client: ClientId,
pub local_client: LocalClientId,
2020-04-05 22:56:48 -07:00
time_join: SystemTime,
}
2022-07-19 12:34:07 -06:00
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2020-04-06 23:40:39 -07:00
struct Lobby([Option<AreaClient>; 12]);
2022-07-19 12:34:07 -06:00
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2020-04-06 23:40:39 -07:00
struct Room([Option<AreaClient>; 4]);
2020-04-05 22:56:48 -07:00
2022-07-19 12:34:07 -06:00
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2020-04-06 23:40:39 -07:00
pub enum RoomLobby {
2020-04-05 22:56:48 -07:00
Room(RoomId),
Lobby(LobbyId),
}
2022-09-18 21:01:32 -06:00
#[derive(Clone, Debug)]
2020-04-06 23:40:39 -07:00
pub struct ClientLocation {
2022-09-18 21:01:32 -06:00
lobbies: [Arc<RwLock<Lobby>>; 15],
2022-10-22 02:15:08 -06:00
rooms: [Arc<RwLock<Option<Room>>>; MAX_ROOMS],
2022-09-18 21:01:32 -06:00
client_location: Arc<RwLock<HashMap<ClientId, RoomLobby>>>,
2020-04-05 22:56:48 -07:00
}
2020-11-24 23:17:42 -07:00
impl Default for ClientLocation {
fn default() -> ClientLocation {
2020-04-06 23:40:39 -07:00
ClientLocation {
2022-09-18 21:01:32 -06:00
lobbies: core::array::from_fn(|_| Arc::new(RwLock::new(Lobby([None; 12])))),
2022-10-22 02:15:08 -06:00
rooms: core::array::from_fn(|_| Arc::new(RwLock::new(None))),
2022-09-18 21:01:32 -06:00
client_location: Arc::new(RwLock::new(HashMap::new())),
2020-04-05 22:56:48 -07:00
}
}
2020-11-24 23:17:42 -07:00
}
2020-04-05 22:56:48 -07:00
2020-11-24 23:17:42 -07:00
impl ClientLocation {
2022-09-18 21:01:32 -06:00
pub async fn add_client_to_lobby(&self, id: ClientId, lobby_id: LobbyId) -> Result<(), JoinLobbyError> {
{
let lobby = self.lobbies
.get(lobby_id.0)
.ok_or(JoinLobbyError::LobbyDoesNotExist)?
.read()
.await;
if lobby.0.iter().all(|c| c.is_some()) {
return Err(JoinLobbyError::LobbyFull);
}
2020-11-25 22:02:16 -07:00
}
2022-09-18 21:01:32 -06:00
self.remove_client_from_area(id).await;
let mut lobby = self.lobbies
.get(lobby_id.0)
.ok_or(JoinLobbyError::LobbyDoesNotExist)?
.write()
.await;
let (index, empty_slot) = lobby.0.iter_mut()
2020-04-05 22:56:48 -07:00
.enumerate()
2021-06-18 17:38:36 -06:00
.find(|(_, k)| k.is_none())
2020-04-05 22:56:48 -07:00
.ok_or(JoinLobbyError::LobbyFull)?;
2020-04-06 23:40:39 -07:00
*empty_slot = Some(AreaClient {
2020-04-05 22:56:48 -07:00
client: id,
local_client: LocalClientId(index),
time_join: SystemTime::now(),
});
2022-09-18 21:01:32 -06:00
self.client_location
.write()
.await
.insert(id, RoomLobby::Lobby(lobby_id));
2020-04-05 22:56:48 -07:00
Ok(())
}
2022-09-18 21:01:32 -06:00
pub async fn add_client_to_next_available_lobby(&self, id: ClientId, lobby: LobbyId) -> Result<LobbyId, JoinLobbyError> {
pin!(stream::iter(0..15)
.filter_map(|lobby_index| async move {
2020-04-05 22:56:48 -07:00
let new_lobby = LobbyId((lobby.0 + lobby_index) % 15);
2022-09-18 21:01:32 -06:00
Some((new_lobby, self.add_client_to_lobby(id, new_lobby).await.ok()?))
}))
.next()
.await
.map(|l| l.0)
.ok_or(JoinLobbyError::LobbyFull)
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
pub async fn create_new_room(&mut self, id: ClientId) -> Result<RoomId, CreateRoomError> {
2022-10-22 02:15:08 -06:00
let (index, empty_slot) = Box::pin(stream::iter(self.rooms.iter())
2020-04-05 22:56:48 -07:00
.enumerate()
2022-10-22 02:15:08 -06:00
.filter(|(_, r)| async {r.read().await.is_none()}))
.next()
.await
2020-04-05 22:56:48 -07:00
.ok_or(CreateRoomError::NoOpenSlots)?;
2022-10-22 02:15:08 -06:00
*empty_slot.write().await = Some(Room([None; 4]));
2022-09-18 21:01:32 -06:00
self.add_client_to_room(id, RoomId(index))
.await
.map_err(|_err| CreateRoomError::JoinError)?;
2020-04-05 22:56:48 -07:00
Ok(RoomId(index))
}
2022-09-18 21:01:32 -06:00
pub async fn add_client_to_room(&mut self, id: ClientId, room: RoomId) -> Result<(), JoinRoomError> {
let mut r = self.rooms.get(room.0)
2020-04-05 22:56:48 -07:00
.ok_or(JoinRoomError::RoomDoesNotExist)?
2022-09-18 21:01:32 -06:00
.as_ref()
.write()
.await;
2022-10-22 02:15:08 -06:00
let r = r.as_mut()
.ok_or(JoinRoomError::RoomDoesNotExist)?;
2020-04-05 22:56:48 -07:00
let (index, empty_slot) = r.0.iter_mut()
.enumerate()
2021-06-18 17:38:36 -06:00
.find(|(_, k)| k.is_none())
2020-04-05 22:56:48 -07:00
.ok_or(JoinRoomError::RoomFull)?;
2020-04-06 23:40:39 -07:00
*empty_slot = Some(AreaClient {
2020-04-05 22:56:48 -07:00
client: id,
local_client: LocalClientId(index),
time_join: SystemTime::now(),
});
2022-09-18 21:01:32 -06:00
self.remove_client_from_area(id).await;
self.client_location
.write()
.await
.insert(id, RoomLobby::Room(room));
2020-04-05 22:56:48 -07:00
Ok(())
}
2022-09-18 21:01:32 -06:00
pub async fn get_all_clients_by_client(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
let area = self.client_location
.read()
.await;
let area = area
.get(&id)
.ok_or(GetNeighborError::InvalidClient)?;
2020-04-05 22:56:48 -07:00
match area {
RoomLobby::Room(room) => {
2022-09-18 21:01:32 -06:00
Ok(self.get_clients_in_room(*room).await.map_err(|_| GetNeighborError::InvalidArea)?
2020-04-06 23:40:39 -07:00
.into_iter()
.collect())
2020-04-05 22:56:48 -07:00
},
RoomLobby::Lobby(lobby) => {
2022-09-18 21:01:32 -06:00
Ok(self.get_clients_in_lobby(*lobby).await.map_err(|_| GetNeighborError::InvalidArea)?
2020-04-06 23:40:39 -07:00
.into_iter()
.collect())
2020-04-05 22:56:48 -07:00
}
}
}
2022-09-18 21:01:32 -06:00
pub async fn get_client_neighbors(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
let area = self.client_location
.read()
.await;
let area = area
.get(&id)
.ok_or(GetNeighborError::InvalidClient)?;
2020-04-06 23:40:39 -07:00
match area {
RoomLobby::Room(room) => {
2022-09-18 21:01:32 -06:00
Ok(self.get_clients_in_room(*room).await.map_err(|_| GetNeighborError::InvalidArea)?
2020-04-06 23:40:39 -07:00
.into_iter()
.filter(|c| c.client != id)
.collect())
},
RoomLobby::Lobby(lobby) => {
2022-09-18 21:01:32 -06:00
Ok(self.get_clients_in_lobby(*lobby).await.map_err(|_| GetNeighborError::InvalidArea)?
2020-04-06 23:40:39 -07:00
.into_iter()
.filter(|c| c.client != id)
.collect())
}
}
}
2022-09-18 21:01:32 -06:00
pub async fn get_room_leader(&self, room: RoomId) -> Result<AreaClient, GetLeaderError> {
let r = self.rooms[room.0]
2020-04-06 23:40:39 -07:00
.as_ref()
2022-09-18 21:01:32 -06:00
.read()
2022-10-22 02:15:08 -06:00
.await
.ok_or(GetLeaderError::InvalidArea)?;
2022-09-18 21:01:32 -06:00
let mut r = r
.0
.iter()
.flatten()
2020-04-06 23:40:39 -07:00
.collect::<Vec<_>>();
r.sort_by_key(|k| k.time_join);
2022-09-18 21:01:32 -06:00
let c = r.get(0)
.ok_or(GetLeaderError::NoClientInArea)?;
2020-04-06 23:40:39 -07:00
Ok(**c)
}
2022-09-18 21:01:32 -06:00
pub async fn get_lobby_leader(&self, lobby: LobbyId) -> Result<AreaClient, GetLeaderError> {
let l = self.lobbies[lobby.0]
.read()
.await;
let mut l = l
.0
.iter()
.flatten()
2020-04-06 23:40:39 -07:00
.collect::<Vec<_>>();
l.sort_by_key(|k| k.time_join);
let c = l.get(0).ok_or(GetLeaderError::NoClientInArea)?;
Ok(**c)
}
2022-09-18 21:01:32 -06:00
pub async fn get_area_leader(&self, roomlobby: RoomLobby) -> Result<AreaClient, GetLeaderError> {
2020-04-06 23:40:39 -07:00
match roomlobby {
RoomLobby::Room(room) => {
2022-09-18 21:01:32 -06:00
self.get_room_leader(room).await
2020-04-06 23:40:39 -07:00
},
RoomLobby::Lobby(lobby) => {
2022-09-18 21:01:32 -06:00
self.get_lobby_leader(lobby).await
2020-04-06 23:40:39 -07:00
}
}
}
2022-09-18 21:01:32 -06:00
pub async fn get_leader_by_client(&self, id: ClientId) -> Result<AreaClient, GetLeaderError> {
let area = self.client_location
.read()
.await;
let area = area
.get(&id)
.ok_or(GetLeaderError::InvalidClient)?;
2020-04-05 22:56:48 -07:00
match area {
RoomLobby::Room(room) => {
2022-09-18 21:01:32 -06:00
self.get_room_leader(*room).await
2020-04-05 22:56:48 -07:00
},
RoomLobby::Lobby(lobby) => {
2022-09-18 21:01:32 -06:00
self.get_lobby_leader(*lobby).await
2020-04-05 22:56:48 -07:00
}
}
}
2022-09-18 21:01:32 -06:00
pub async fn get_clients_in_lobby(&self, lobby: LobbyId) -> Result<Vec<AreaClient>, GetClientsError> {
Ok(self.lobbies
.get(lobby.0)
.ok_or(GetClientsError::InvalidArea)?
.read()
.await
.0
2020-04-05 22:56:48 -07:00
.iter()
2020-04-06 23:40:39 -07:00
.filter_map(|client| {
client.map(|c| {
c
})
}).collect())
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
pub async fn get_clients_in_room(&self, room: RoomId) -> Result<Vec<AreaClient>, GetClientsError> {
2020-04-05 22:56:48 -07:00
Ok(self.rooms.get(room.0)
.ok_or(GetClientsError::InvalidArea)?
2022-09-18 21:01:32 -06:00
.as_ref()
.read()
.await
2022-10-22 02:15:08 -06:00
.ok_or(GetClientsError::InvalidArea)?
2022-09-18 21:01:32 -06:00
.0
2020-04-05 22:56:48 -07:00
.iter()
2020-04-06 23:40:39 -07:00
.filter_map(|client| {
client.map(|c| {
c
})
}).collect())
}
2022-09-18 21:01:32 -06:00
pub async fn get_local_client(&self, id: ClientId) -> Result<AreaClient, GetClientsError> {
let area = self.client_location
.read()
.await;
let area = area
.get(&id)
.ok_or(GetClientsError::InvalidClient)?;
2020-04-06 23:40:39 -07:00
match area {
RoomLobby::Room(room) => {
2022-09-18 21:01:32 -06:00
self.get_clients_in_room(*room)
.await
.map_err(|_| GetClientsError::InvalidArea)?
2020-04-06 23:40:39 -07:00
.into_iter()
2021-06-18 17:38:36 -06:00
.find(|c| c.client == id)
2020-04-06 23:40:39 -07:00
.ok_or(GetClientsError::InvalidClient)
},
RoomLobby::Lobby(lobby) => {
2022-09-18 21:01:32 -06:00
self.get_clients_in_lobby(*lobby)
.await
.map_err(|_| GetClientsError::InvalidArea)?
2020-04-06 23:40:39 -07:00
.into_iter()
2021-06-18 17:38:36 -06:00
.find(|c| c.client == id)
2020-04-06 23:40:39 -07:00
.ok_or(GetClientsError::InvalidClient)
}
}
}
2022-09-18 21:01:32 -06:00
pub async fn get_area(&self, id: ClientId) -> Result<RoomLobby, GetAreaError> {
self.client_location
.read()
.await
.get(&id)
2020-04-06 23:40:39 -07:00
.ok_or(GetAreaError::InvalidClient)
.map(Clone::clone)
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
pub async fn get_room(&self, id: ClientId) -> Result<RoomId, GetAreaError> {
if let RoomLobby::Room(room) = self.client_location.read().await.get(&id).ok_or(GetAreaError::InvalidClient)? {
Ok(*room)
}
else {
Err(GetAreaError::NotInRoom)
}
}
2022-09-18 21:01:32 -06:00
pub async fn get_lobby(&self, id: ClientId) -> Result<LobbyId, GetAreaError> {
if let RoomLobby::Lobby(lobby) = self.client_location.read().await.get(&id).ok_or(GetAreaError::InvalidClient)? {
Ok(*lobby)
}
else {
Err(GetAreaError::NotInLobby)
}
}
2022-09-18 21:01:32 -06:00
pub async fn remove_client_from_area(&self, id: ClientId) -> Result<(), ClientRemovalError> {
fn remove_client<const N: usize>(id: ClientId, client_list : &mut [Option<AreaClient>; N]) {
client_list
.iter_mut()
.filter(|client| {
client.map_or(false, |c| {
c.client == id
2021-06-18 17:38:36 -06:00
})
2022-09-18 21:01:32 -06:00
})
.for_each(|client| {
*client = None
});
}
let area = self.client_location
.read()
.await;
let area = area
.get(&id)
.ok_or(ClientRemovalError::ClientNotInArea)?;
match area {
RoomLobby::Room(room) => {
2022-10-22 02:15:08 -06:00
let mut r = self.rooms.get(room.0)
.ok_or(ClientRemovalError::InvalidArea)?
.as_ref()
.write()
.await;
if let Some(r) = r.as_mut() {
remove_client(id, &mut r.0)
2022-09-18 21:01:32 -06:00
}
else {
return Err(ClientRemovalError::InvalidArea)
}
2020-04-05 22:56:48 -07:00
},
RoomLobby::Lobby(lobby) => {
2022-09-18 21:01:32 -06:00
remove_client(id, &mut self.lobbies[lobby.0].write().await.0)
2020-04-05 22:56:48 -07:00
}
};
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_add_client_to_lobby() {
let cl = ClientLocation::default();
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await.unwrap();
cl.add_client_to_lobby(ClientId(13), LobbyId(1)).await.unwrap();
cl.add_client_to_lobby(ClientId(14), LobbyId(0)).await.unwrap();
2020-04-05 22:56:48 -07:00
2022-09-18 21:01:32 -06:00
assert!(cl.get_clients_in_lobby(LobbyId(0)).await.into_iter().flatten().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
2020-04-05 22:56:48 -07:00
(ClientId(12), LocalClientId(0)),
(ClientId(14), LocalClientId(1)),
2020-04-06 23:40:39 -07:00
]);
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_add_client_to_full_lobby() {
let cl = ClientLocation::default();
for i in 0..12 {
cl.add_client_to_lobby(ClientId(i), LobbyId(0)).await.unwrap();
}
assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(0)).await == Err(JoinLobbyError::LobbyFull));
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_add_client_to_next_available_lobby() {
let cl = ClientLocation::default();
for lobby in 1..4 {
for i in 0..12 {
cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby)).await.unwrap();
}
}
assert!(cl.add_client_to_next_available_lobby(ClientId(99), LobbyId(1)).await == Ok(LobbyId(4)));
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_add_to_lobby_when_all_are_full() {
let cl = ClientLocation::default();
for lobby in 0..15 {
for i in 0..12 {
cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby)).await.unwrap();
}
}
assert_eq!(cl.add_client_to_next_available_lobby(ClientId(99), LobbyId(1)).await, Err(JoinLobbyError::LobbyFull));
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_new_room() {
2020-11-24 23:17:42 -07:00
let mut cl = ClientLocation::default();
2022-09-18 21:01:32 -06:00
assert!(cl.create_new_room(ClientId(12)).await == Ok(RoomId(0)));
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_add_client_to_room() {
2020-11-24 23:17:42 -07:00
let mut cl = ClientLocation::default();
2022-09-18 21:01:32 -06:00
let room = cl.create_new_room(ClientId(12)).await.unwrap();
assert!(cl.add_client_to_room(ClientId(234), room).await == Ok(()));
assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
2020-04-05 22:56:48 -07:00
(ClientId(12), LocalClientId(0)),
(ClientId(234), LocalClientId(1)),
2020-04-06 23:40:39 -07:00
]);
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_no_new_room_slots() {
2020-11-24 23:17:42 -07:00
let mut cl = ClientLocation::default();
2020-04-05 22:56:48 -07:00
for i in 0..128 {
2022-09-18 21:01:32 -06:00
cl.create_new_room(ClientId(i)).await;
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
assert!(cl.create_new_room(ClientId(234)).await == Err(CreateRoomError::NoOpenSlots));
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_joining_full_room() {
2020-11-24 23:17:42 -07:00
let mut cl = ClientLocation::default();
2022-09-18 21:01:32 -06:00
let room = cl.create_new_room(ClientId(0)).await.unwrap();
assert!(cl.add_client_to_room(ClientId(1), room).await == Ok(()));
assert!(cl.add_client_to_room(ClientId(2), room).await == Ok(()));
assert!(cl.add_client_to_room(ClientId(3), room).await == Ok(()));
assert!(cl.add_client_to_room(ClientId(234), room).await == Err(JoinRoomError::RoomFull));
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_adding_client_to_room_removes_from_lobby() {
2020-11-24 23:17:42 -07:00
let mut cl = ClientLocation::default();
2022-09-18 21:01:32 -06:00
cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await;
cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await;
cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await;
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await;
let room = cl.create_new_room(ClientId(51)).await.unwrap();
assert!(cl.add_client_to_room(ClientId(93), room).await == Ok(()));
assert!(cl.get_clients_in_lobby(LobbyId(0)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
2020-04-05 22:56:48 -07:00
(ClientId(23), LocalClientId(1)),
(ClientId(12), LocalClientId(3)),
2020-04-06 23:40:39 -07:00
]);
2022-09-18 21:01:32 -06:00
assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
2020-04-05 22:56:48 -07:00
(ClientId(51), LocalClientId(0)),
(ClientId(93), LocalClientId(1)),
2020-04-06 23:40:39 -07:00
]);
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_getting_neighbors() {
let cl = ClientLocation::default();
cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await.unwrap();
cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await.unwrap();
cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await.unwrap();
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await.unwrap();
2020-04-05 22:56:48 -07:00
2022-09-18 21:01:32 -06:00
assert!(cl.get_client_neighbors(ClientId(23)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
2020-04-05 22:56:48 -07:00
(ClientId(93), LocalClientId(0)),
(ClientId(51), LocalClientId(2)),
(ClientId(12), LocalClientId(3)),
2020-04-06 23:40:39 -07:00
]);
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_failing_to_join_lobby_does_not_remove_from_current_area() {
let cl = ClientLocation::default();
for i in 0..12 {
cl.add_client_to_lobby(ClientId(i), LobbyId(0)).await.unwrap();
}
assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(1)).await.is_ok());
assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(0)).await.is_err());
assert_eq!(cl.get_clients_in_lobby(LobbyId(0)).await.unwrap().len(), 12);
assert_eq!(
cl.get_clients_in_lobby(LobbyId(1)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>(),
vec![(ClientId(99), LocalClientId(0))]
);
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_get_leader() {
let cl = ClientLocation::default();
cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await;
cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await;
cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await;
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await;
2020-04-05 22:56:48 -07:00
2022-09-18 21:01:32 -06:00
assert!(cl.get_leader_by_client(ClientId(51)).await.map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(0))));
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_remove_client_from_room() {
2020-11-24 23:17:42 -07:00
let mut cl = ClientLocation::default();
2022-09-18 21:01:32 -06:00
let room = cl.create_new_room(ClientId(51)).await.unwrap();
cl.add_client_to_room(ClientId(93), room).await;
cl.add_client_to_room(ClientId(23), room).await;
cl.remove_client_from_area(ClientId(51)).await;
cl.add_client_to_room(ClientId(12), room).await;
2020-04-05 22:56:48 -07:00
2022-09-18 21:01:32 -06:00
assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
2020-04-05 22:56:48 -07:00
(ClientId(12), LocalClientId(0)),
(ClientId(93), LocalClientId(1)),
(ClientId(23), LocalClientId(2)),
2020-04-06 23:40:39 -07:00
]);
2020-04-05 22:56:48 -07:00
}
2022-09-18 21:01:32 -06:00
#[async_std::test]
async fn test_leader_changes_on_leader_leaving() {
2020-11-24 23:17:42 -07:00
let mut cl = ClientLocation::default();
2022-09-18 21:01:32 -06:00
let room = cl.create_new_room(ClientId(51)).await.unwrap();
cl.add_client_to_room(ClientId(93), room).await.unwrap();
cl.add_client_to_room(ClientId(23), room).await.unwrap();
cl.remove_client_from_area(ClientId(51)).await.unwrap();
cl.add_client_to_room(ClientId(12), room).await.unwrap();
cl.remove_client_from_area(ClientId(23)).await.unwrap();
cl.add_client_to_room(ClientId(99), room).await.unwrap();
assert!(cl.get_leader_by_client(ClientId(12)).await.map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(1))));
2020-04-05 22:56:48 -07:00
}
}