remove player from area when they leave
This commit is contained in:
parent
a7cb592471
commit
e451eb88b5
src
@ -5,3 +5,17 @@ pub mod client;
|
|||||||
pub mod clientpool;
|
pub mod clientpool;
|
||||||
pub mod mainloop;
|
pub mod mainloop;
|
||||||
pub mod leveltable;
|
pub mod leveltable;
|
||||||
|
|
||||||
|
// https://www.reddit.com/r/rust/comments/33xhhu/how_to_create_an_array_of_structs_that_havent/
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! init_array(
|
||||||
|
($ty:ty, $len:expr, $val:expr) => (
|
||||||
|
{
|
||||||
|
let mut array: [$ty; $len] = unsafe { std::mem::uninitialized() };
|
||||||
|
for i in array.iter_mut() {
|
||||||
|
unsafe { ::std::ptr::write(i, $val); }
|
||||||
|
}
|
||||||
|
array
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
// TODO: room passwords?
|
// TODO: room passwords?
|
||||||
@ -11,7 +13,6 @@ pub struct AreaClient {
|
|||||||
time_join: SystemTime,
|
time_join: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct InnerClientArea<const N: usize> {
|
pub struct InnerClientArea<const N: usize> {
|
||||||
clients: [Option<AreaClient>; N],
|
clients: [Option<AreaClient>; N],
|
||||||
@ -80,23 +81,36 @@ 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>;
|
||||||
|
|
||||||
trait ClientArea<'a> {
|
trait ClientArea {
|
||||||
fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>>;
|
fn clients(&self) -> std::slice::Iter<'_, Option<AreaClient>>;
|
||||||
|
fn remove(&mut self, id: ClientId) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> ClientArea<'a> for Lobby {
|
impl ClientArea for Lobby {
|
||||||
fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>> {
|
fn clients(& self) -> std::slice::Iter<'_, Option<AreaClient>> {
|
||||||
self.clients.iter()
|
self.clients.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove(&mut self, id: ClientId) -> bool {
|
||||||
|
self.remove(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ClientArea<'a> for Room {
|
impl<'a> ClientArea for Room {
|
||||||
fn clients(&'a self) -> std::slice::Iter<'_, Option<AreaClient>> {
|
fn clients(& self) -> std::slice::Iter<'_, Option<AreaClient>> {
|
||||||
self.clients.iter()
|
self.clients.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove(&mut self, id: ClientId) -> bool {
|
||||||
|
self.remove(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum AreaType {
|
||||||
|
Lobby,
|
||||||
|
Room,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ClientAtLocation {
|
pub struct ClientAtLocation {
|
||||||
@ -104,21 +118,22 @@ pub struct ClientAtLocation {
|
|||||||
pub index: usize,
|
pub index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Area {
|
||||||
pub struct Area<'a> {
|
pub area_type: AreaType,
|
||||||
area: &'a dyn ClientArea<'a>,
|
area: Arc<RwLock<dyn ClientArea>>,
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Area<'a> {
|
impl Area {
|
||||||
fn new(area: &'a dyn ClientArea<'a>, index: usize) -> Area<'a> {
|
fn new(area_type: AreaType, area: Arc<RwLock<dyn ClientArea>>, index: usize) -> Area {
|
||||||
Area {
|
Area {
|
||||||
|
area_type: area_type,
|
||||||
area: area,
|
area: area,
|
||||||
index: index,
|
index: index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn clients(&'a self) -> Vec<ClientAtLocation> {
|
pub fn clients(&self) -> Vec<ClientAtLocation> {
|
||||||
self.area.clients()
|
self.area.read().unwrap().clients()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(_i, k)| k.is_some())
|
.filter(|(_i, k)| k.is_some())
|
||||||
.map(|(i, k)| (i, k.unwrap()) )
|
.map(|(i, k)| (i, k.unwrap()) )
|
||||||
@ -129,9 +144,9 @@ impl<'a> Area<'a> {
|
|||||||
}
|
}
|
||||||
// TODO: Result in cases where no one is in the area?
|
// TODO: Result in cases where no one is in the area?
|
||||||
pub fn leader(&self) -> ClientAtLocation {
|
pub fn leader(&self) -> ClientAtLocation {
|
||||||
self.area.clients()
|
self.area.read().unwrap().clients()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(i, k)| k.is_some())
|
.filter(|(_i, k)| k.is_some())
|
||||||
.map(|(i, k)| (i, k.unwrap()) )
|
.map(|(i, k)| (i, k.unwrap()) )
|
||||||
.fold((ClientAtLocation {
|
.fold((ClientAtLocation {
|
||||||
client_id: ClientId(0),
|
client_id: ClientId(0),
|
||||||
@ -150,6 +165,10 @@ impl<'a> Area<'a> {
|
|||||||
}).0
|
}).0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, id: ClientId) -> bool {
|
||||||
|
self.area.write().unwrap().remove(id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> usize {
|
pub fn id(&self) -> usize {
|
||||||
self.index
|
self.index
|
||||||
}
|
}
|
||||||
@ -176,25 +195,26 @@ pub enum JoinLobbyError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClientLocation {
|
pub struct ClientLocation {
|
||||||
lobbies: [Lobby; 15],
|
lobbies: [Arc<RwLock<Lobby>>; 15],
|
||||||
rooms: [Option<Room>; MAX_ROOMS],
|
rooms: [Option<Arc<RwLock<Room>>>; MAX_ROOMS],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientLocation {
|
impl ClientLocation {
|
||||||
pub fn new() -> ClientLocation {
|
pub fn new() -> ClientLocation {
|
||||||
ClientLocation {
|
ClientLocation {
|
||||||
lobbies: [Lobby::new(); 15],
|
//lobbies: [Arc::new(RwLock::new(Lobby::new())); 15],
|
||||||
|
lobbies: crate::init_array!(Arc<RwLock<Lobby>>, 15, Arc::new(RwLock::new(Lobby::new()))),
|
||||||
rooms: [None; MAX_ROOMS],
|
rooms: [None; MAX_ROOMS],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn err_if_client_is_in_area<E>(&mut self, id: ClientId, err: E) -> Result<(), E> {
|
fn err_if_client_is_in_area<E>(&mut self, id: ClientId, err: E) -> Result<(), E> {
|
||||||
let in_lobby = self.lobbies.iter()
|
let in_lobby = self.lobbies.iter()
|
||||||
.any(|k| k.contains(id));
|
.any(|k| k.read().unwrap().contains(id));
|
||||||
let in_room = self.rooms.iter()
|
let in_room = self.rooms.iter()
|
||||||
.filter(|k| k.is_some())
|
.filter(|k| k.is_some())
|
||||||
.map(|k| k.unwrap())
|
.map(|k| k.as_ref().unwrap())
|
||||||
.any(|k| k.contains(id));
|
.any(|k| k.read().unwrap().contains(id));
|
||||||
|
|
||||||
if in_lobby || in_room {
|
if in_lobby || in_room {
|
||||||
Err(err)
|
Err(err)
|
||||||
@ -208,6 +228,7 @@ impl ClientLocation {
|
|||||||
self.err_if_client_is_in_area(id, JoinLobbyError::ClientInAreaAlready)?;
|
self.err_if_client_is_in_area(id, JoinLobbyError::ClientInAreaAlready)?;
|
||||||
self.lobbies.get_mut(lobby.0)
|
self.lobbies.get_mut(lobby.0)
|
||||||
.ok_or(JoinLobbyError::LobbyDoesNotExist)?
|
.ok_or(JoinLobbyError::LobbyDoesNotExist)?
|
||||||
|
.write().unwrap()
|
||||||
.add(id)
|
.add(id)
|
||||||
.ok_or(JoinLobbyError::LobbyFull)
|
.ok_or(JoinLobbyError::LobbyFull)
|
||||||
}
|
}
|
||||||
@ -222,7 +243,7 @@ impl ClientLocation {
|
|||||||
|
|
||||||
let mut new_room = Room::new();
|
let mut new_room = Room::new();
|
||||||
new_room.add(id);
|
new_room.add(id);
|
||||||
*empty_room = Some(new_room);
|
*empty_room = Some(Arc::new(RwLock::new(new_room)));
|
||||||
|
|
||||||
Ok(RoomId(room_id))
|
Ok(RoomId(room_id))
|
||||||
}
|
}
|
||||||
@ -233,21 +254,22 @@ impl ClientLocation {
|
|||||||
.ok_or(JoinRoomError::RoomDoesNotExist)?
|
.ok_or(JoinRoomError::RoomDoesNotExist)?
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.ok_or(JoinRoomError::RoomDoesNotExist)?
|
.ok_or(JoinRoomError::RoomDoesNotExist)?
|
||||||
|
.write().unwrap()
|
||||||
.add(id)
|
.add(id)
|
||||||
.ok_or(JoinRoomError::RoomFull)
|
.ok_or(JoinRoomError::RoomFull)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_area_by_user(&self, id: ClientId) -> Area {
|
pub fn get_area_by_user(&mut self, id: ClientId) -> Area {
|
||||||
for (i, lobby) in self.lobbies.iter().enumerate() {
|
for (i, lobby) in self.lobbies.iter().enumerate() {
|
||||||
if lobby.contains(id) {
|
if lobby.read().unwrap().contains(id) {
|
||||||
return Area::new(lobby, i);
|
return Area::new(AreaType::Lobby, lobby.clone(), i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, room) in self.rooms.iter().enumerate() {
|
for (i, room) in self.rooms.iter().enumerate() {
|
||||||
if let Some(room) = room {
|
if let Some(room) = room {
|
||||||
if room.contains(id){
|
if room.read().unwrap().contains(id){
|
||||||
return Area::new(room, i);
|
return Area::new(AreaType::Room, room.clone(), i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +279,7 @@ impl ClientLocation {
|
|||||||
|
|
||||||
pub fn remove_from_location(&mut self, id: ClientId) {
|
pub fn remove_from_location(&mut self, id: ClientId) {
|
||||||
let in_lobby = self.lobbies.iter_mut()
|
let in_lobby = self.lobbies.iter_mut()
|
||||||
.map(|lobby| lobby.remove(id))
|
.map(|lobby| lobby.write().unwrap().remove(id))
|
||||||
.any(|k| k);
|
.any(|k| k);
|
||||||
|
|
||||||
if in_lobby {
|
if in_lobby {
|
||||||
@ -266,8 +288,8 @@ impl ClientLocation {
|
|||||||
|
|
||||||
self.rooms.iter_mut()
|
self.rooms.iter_mut()
|
||||||
.filter(|lobby| lobby.is_some())
|
.filter(|lobby| lobby.is_some())
|
||||||
.map(|lobby| lobby.unwrap())
|
.map(|lobby| lobby.as_ref().unwrap())
|
||||||
.map(|mut lobby| lobby.remove(id))
|
.map(|mut lobby| lobby.write().unwrap().remove(id))
|
||||||
.any(|k| k);
|
.any(|k| k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,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, LobbyId, RoomId};
|
use crate::ship::location::{ClientLocation, LobbyId, RoomId, AreaType};
|
||||||
use crate::ship::character::{CharacterBuilder, FullCharacterBuilder};
|
use crate::ship::character::{CharacterBuilder, FullCharacterBuilder};
|
||||||
use crate::ship::room;
|
use crate::ship::room;
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ impl RecvServerPacket for RecvShipPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum SendShipPacket {
|
pub enum SendShipPacket {
|
||||||
ShipWelcome(ShipWelcome),
|
ShipWelcome(ShipWelcome),
|
||||||
LoginResponse(LoginResponse),
|
LoginResponse(LoginResponse),
|
||||||
@ -74,6 +74,8 @@ pub enum SendShipPacket {
|
|||||||
SmallDialog(SmallDialog),
|
SmallDialog(SmallDialog),
|
||||||
JoinRoom(JoinRoom),
|
JoinRoom(JoinRoom),
|
||||||
AddToRoom(AddToRoom),
|
AddToRoom(AddToRoom),
|
||||||
|
LeaveLobby(LeaveLobby),
|
||||||
|
LeaveRoom(LeaveRoom),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SendServerPacket for SendShipPacket {
|
impl SendServerPacket for SendShipPacket {
|
||||||
@ -92,6 +94,8 @@ impl SendServerPacket for SendShipPacket {
|
|||||||
SendShipPacket::SmallDialog(pkt) => pkt.as_bytes(),
|
SendShipPacket::SmallDialog(pkt) => pkt.as_bytes(),
|
||||||
SendShipPacket::JoinRoom(pkt) => pkt.as_bytes(),
|
SendShipPacket::JoinRoom(pkt) => pkt.as_bytes(),
|
||||||
SendShipPacket::AddToRoom(pkt) => pkt.as_bytes(),
|
SendShipPacket::AddToRoom(pkt) => pkt.as_bytes(),
|
||||||
|
SendShipPacket::LeaveLobby(pkt) => pkt.as_bytes(),
|
||||||
|
SendShipPacket::LeaveRoom(pkt) => pkt.as_bytes(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -430,7 +434,25 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendShipPacket)> {
|
fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendShipPacket)> {
|
||||||
warn!("disconnected!");
|
let mut area = self.client_location.get_area_by_user(id);
|
||||||
Vec::new()
|
let client = area.clients().into_iter().filter(|client| {
|
||||||
|
client.client_id == id
|
||||||
|
//}).collect::<Vec<_>>()[0];
|
||||||
|
}).next().unwrap();
|
||||||
|
let other_clients = area.clients().into_iter().filter(|client| {
|
||||||
|
client.client_id != id
|
||||||
|
});
|
||||||
|
//self.client_location.remove_from_location(id);
|
||||||
|
area.remove(id);
|
||||||
|
let leader = area.leader();
|
||||||
|
|
||||||
|
let pkt = match area.area_type {
|
||||||
|
AreaType::Lobby => SendShipPacket::LeaveLobby(LeaveLobby::new(client.index as u8, leader.index as u8)),
|
||||||
|
AreaType::Room => SendShipPacket::LeaveRoom(LeaveRoom::new(client.index as u8, leader.index as u8)),
|
||||||
|
};
|
||||||
|
|
||||||
|
other_clients.map(|client| {
|
||||||
|
(client.client_id, pkt.clone())
|
||||||
|
}).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user