Browse Source

add clientlocation functions

pbs
jake 5 years ago
committed by Jake Probst
parent
commit
c2ceb034d8
  1. 83
      src/ship/location.rs
  2. 4
      src/ship/ship.rs

83
src/ship/location.rs

@ -3,6 +3,8 @@ use crate::common::serverstate::ClientId;
// TODO: room passwords? // TODO: room passwords?
// TODO: remove clients from areas (or upon insert, remove that id from anywhere else) // TODO: remove clients from areas (or upon insert, remove that id from anywhere else)
pub const MAX_ROOMS: usize = 128;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct AreaClient { pub struct AreaClient {
client_id: ClientId, client_id: ClientId,
@ -42,14 +44,16 @@ impl<const N: usize> InnerClientArea<{N}> {
} }
return None; return None;
} }
fn remove(&mut self, id: ClientId) {
fn remove(&mut self, id: ClientId) -> bool {
for areaclient in self.clients.iter_mut() { for areaclient in self.clients.iter_mut() {
if let Some(client) = *areaclient { if let Some(client) = *areaclient {
if client.client_id == id { if client.client_id == id {
*areaclient = None; *areaclient = None;
return true;
} }
} }
} }
false
} }
fn contains(&self, id: ClientId) -> bool { fn contains(&self, id: ClientId) -> bool {
@ -70,17 +74,12 @@ impl<const N: usize> InnerClientArea<{N}> {
} }
} }
pub type LobbyId = usize;
pub type RoomId = usize;
pub struct LobbyId(pub usize);
pub struct RoomId(pub usize);
pub type Lobby = InnerClientArea<12>; pub type Lobby = InnerClientArea<12>;
pub type Room = InnerClientArea<4>; pub type Room = InnerClientArea<4>;
pub struct ClientLocation {
lobbies: [Lobby; 15],
rooms: [Option<Room>; 128],
}
trait ClientArea<'a> { trait ClientArea<'a> {
fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>>; fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>>;
} }
@ -156,35 +155,81 @@ impl<'a> Area<'a> {
} }
} }
#[derive(Debug)]
pub enum CreateRoomError {
NoOpenSlots,
ClientInAreaAlready,
}
#[derive(Debug)] #[derive(Debug)]
pub enum JoinRoomError { pub enum JoinRoomError {
RoomDoesNotExist, RoomDoesNotExist,
RoomFull, RoomFull,
ClientInAreaAlready,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum JoinLobbyError { pub enum JoinLobbyError {
LobbyDoesNotExist, LobbyDoesNotExist,
LobbyFull, LobbyFull,
ClientInAreaAlready,
}
pub struct ClientLocation {
lobbies: [Lobby; 15],
rooms: [Option<Room>; MAX_ROOMS],
} }
impl ClientLocation { impl ClientLocation {
pub fn new() -> ClientLocation { pub fn new() -> ClientLocation {
ClientLocation { ClientLocation {
lobbies: [Lobby::new(); 15], lobbies: [Lobby::new(); 15],
rooms: [None; 128],
rooms: [None; MAX_ROOMS],
}
}
fn err_if_client_is_in_area<E>(&mut self, id: ClientId, err: E) -> Result<(), E> {
let in_lobby = self.lobbies.iter()
.any(|k| k.contains(id));
let in_room = self.rooms.iter()
.filter(|k| k.is_none())
.map(|k| k.unwrap())
.any(|k| k.contains(id));
if in_lobby || in_room {
Err(err)
}
else {
Ok(())
} }
} }
pub fn add_to_lobby(&mut self, id: ClientId, lobby: LobbyId) -> Result<usize, JoinLobbyError> { pub fn add_to_lobby(&mut self, id: ClientId, lobby: LobbyId) -> Result<usize, JoinLobbyError> {
self.lobbies.get_mut(lobby)
self.err_if_client_is_in_area(id, JoinLobbyError::ClientInAreaAlready)?;
self.lobbies.get_mut(lobby.0)
.ok_or(JoinLobbyError::LobbyDoesNotExist)? .ok_or(JoinLobbyError::LobbyDoesNotExist)?
.add(id) .add(id)
.ok_or(JoinLobbyError::LobbyFull) .ok_or(JoinLobbyError::LobbyFull)
} }
pub fn new_room(&mut self, id: ClientId) -> Result<RoomId, CreateRoomError> {
self.err_if_client_is_in_area(id, CreateRoomError::ClientInAreaAlready)?;
let (room_id, empty_room) = self.rooms.iter_mut()
.enumerate()
.filter(|(_, k)| k.is_none())
.nth(0)
.ok_or(CreateRoomError::NoOpenSlots)?;
let mut new_room = Room::new();
new_room.add(id);
*empty_room = Some(new_room);
Ok(RoomId(room_id))
}
pub fn add_to_room(&mut self, id: ClientId, room: RoomId) -> Result<usize, JoinRoomError> { pub fn add_to_room(&mut self, id: ClientId, room: RoomId) -> Result<usize, JoinRoomError> {
self.rooms.get_mut(room)
self.err_if_client_is_in_area(id, JoinRoomError::ClientInAreaAlready)?;
self.rooms.get_mut(room.0)
.ok_or(JoinRoomError::RoomDoesNotExist)? .ok_or(JoinRoomError::RoomDoesNotExist)?
.as_mut() .as_mut()
.ok_or(JoinRoomError::RoomDoesNotExist)? .ok_or(JoinRoomError::RoomDoesNotExist)?
@ -209,4 +254,20 @@ impl ClientLocation {
panic!("client is not in a room/lobby") panic!("client is not in a room/lobby")
} }
pub fn remove_from_location(&mut self, id: ClientId) {
let in_lobby = self.lobbies.iter_mut()
.map(|lobby| lobby.remove(id))
.any(|k| k);
if in_lobby {
return;
}
self.rooms.iter_mut()
.filter(|lobby| lobby.is_none())
.map(|lobby| lobby.unwrap())
.map(|mut lobby| lobby.remove(id))
.any(|k| k);
}
} }

4
src/ship/ship.rs

@ -19,7 +19,7 @@ use crate::entity::account::{UserAccount, UserSettings, USERFLAG_NEWCHAR, USERFL
use crate::entity::character::Character; use crate::entity::character::Character;
use crate::entity::item::ItemLocation; use crate::entity::item::ItemLocation;
use crate::login::login::get_login_status; use crate::login::login::get_login_status;
use crate::ship::location::ClientLocation;
use crate::ship::location::{ClientLocation, LobbyId, RoomId};
use crate::ship::character::{CharacterBuilder, FullCharacterBuilder}; use crate::ship::character::{CharacterBuilder, FullCharacterBuilder};
pub const SHIP_PORT: u16 = 23423; pub const SHIP_PORT: u16 = 23423;
@ -197,7 +197,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
} }
fn send_player_to_lobby(&mut self, id: ClientId, _pkt: &CharData) -> Result<Vec<(ClientId, SendShipPacket)>, ShipError> { fn send_player_to_lobby(&mut self, id: ClientId, _pkt: &CharData) -> Result<Vec<(ClientId, SendShipPacket)>, ShipError> {
self.client_location.add_to_lobby(id, 0).unwrap();
self.client_location.add_to_lobby(id, LobbyId(0)).unwrap();
let lobby = self.client_location.get_area_by_user(id); let lobby = self.client_location.get_area_by_user(id);
let clients = lobby.clients(); let clients = lobby.clients();

Loading…
Cancel
Save