make ClientLocation Clone-able
This commit is contained in:
parent
2d880d8cf0
commit
58c26301bf
@ -34,3 +34,7 @@ strum = "0.19.5"
|
|||||||
strum_macros = "0.19"
|
strum_macros = "0.19"
|
||||||
anyhow = { version = "1.0.47", features = ["backtrace"] }
|
anyhow = { version = "1.0.47", features = ["backtrace"] }
|
||||||
fix-hidden-lifetime-bug = "0.2.4"
|
fix-hidden-lifetime-bug = "0.2.4"
|
||||||
|
|
||||||
|
|
||||||
|
[patch."http://git.sharnoth.com/jake/libpso"]
|
||||||
|
libpso = { path = "../libpso" }
|
@ -3,6 +3,8 @@
|
|||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
|
#![feature(pin_macro)]
|
||||||
|
|
||||||
|
|
||||||
extern crate fix_hidden_lifetime_bug;
|
extern crate fix_hidden_lifetime_bug;
|
||||||
|
|
||||||
|
@ -575,7 +575,6 @@ where
|
|||||||
move |(item_state, transaction), arg| {
|
move |(item_state, transaction), arg| {
|
||||||
let input = input.clone();
|
let input = input.clone();
|
||||||
let func = func.clone();
|
let func = func.clone();
|
||||||
println!("i {:?} {:?}", input, arg);
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let (state, result) = iterate_inner((item_state, transaction), input, func, arg.clone()).await?;
|
let (state, result) = iterate_inner((item_state, transaction), input, func, arg.clone()).await?;
|
||||||
Ok((state, result))
|
Ok((state, result))
|
||||||
@ -622,7 +621,6 @@ where
|
|||||||
T: Clone + Send + Sync,
|
T: Clone + Send + Sync,
|
||||||
{
|
{
|
||||||
move |(item_state, transaction), items| {
|
move |(item_state, transaction), items| {
|
||||||
println!("fe {:?}", items);
|
|
||||||
let func = func.clone();
|
let func = func.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let (state, result) = foreach_inner((item_state, transaction), items, func).await?;
|
let (state, result) = foreach_inner((item_state, transaction), items, func).await?;
|
||||||
|
@ -4,6 +4,10 @@ use std::time::SystemTime;
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
|
|
||||||
|
use async_std::sync::{Arc, RwLock};
|
||||||
|
use futures::{stream, StreamExt};
|
||||||
|
use std::pin::pin;
|
||||||
|
|
||||||
pub const MAX_ROOMS: usize = 128;
|
pub const MAX_ROOMS: usize = 128;
|
||||||
|
|
||||||
pub enum AreaType {
|
pub enum AreaType {
|
||||||
@ -133,33 +137,48 @@ pub enum RoomLobby {
|
|||||||
Lobby(LobbyId),
|
Lobby(LobbyId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
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],
|
||||||
client_location: HashMap<ClientId, RoomLobby>,
|
client_location: Arc<RwLock<HashMap<ClientId, RoomLobby>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ClientLocation {
|
impl Default for ClientLocation {
|
||||||
fn default() -> ClientLocation {
|
fn default() -> ClientLocation {
|
||||||
|
//const RNONE: Option<Arc<RwLock<Room>>> = None;
|
||||||
|
//const LINIT: Arc<RwLock<Lobby>> = Arc::new(RwLock::new(Lobby([None; 12])));
|
||||||
ClientLocation {
|
ClientLocation {
|
||||||
lobbies: [Lobby([None; 12]); 15],
|
//lobbies: [LINIT; 15],
|
||||||
rooms: [None; MAX_ROOMS],
|
lobbies: core::array::from_fn(|_| Arc::new(RwLock::new(Lobby([None; 12])))),
|
||||||
client_location: HashMap::new(),
|
rooms: core::array::from_fn(|_| None),
|
||||||
|
//rooms: [RNONE; MAX_ROOMS],
|
||||||
|
client_location: Arc::new(RwLock::new(HashMap::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl ClientLocation {
|
impl ClientLocation {
|
||||||
pub fn add_client_to_lobby(&mut self, id: ClientId, lobby: LobbyId) -> Result<(), JoinLobbyError> {
|
pub async fn add_client_to_lobby(&self, id: ClientId, lobby_id: LobbyId) -> Result<(), JoinLobbyError> {
|
||||||
let l = self.lobbies.get_mut(lobby.0).ok_or(JoinLobbyError::LobbyDoesNotExist)?;
|
{
|
||||||
if l.0.iter().filter(|c| c.is_none()).count() == 0 {
|
let lobby = self.lobbies
|
||||||
return Err(JoinLobbyError::LobbyFull);
|
.get(lobby_id.0)
|
||||||
|
.ok_or(JoinLobbyError::LobbyDoesNotExist)?
|
||||||
|
.read()
|
||||||
|
.await;
|
||||||
|
if lobby.0.iter().all(|c| c.is_some()) {
|
||||||
|
return Err(JoinLobbyError::LobbyFull);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.remove_client_from_area(id);
|
self.remove_client_from_area(id).await;
|
||||||
|
|
||||||
let l = self.lobbies.get_mut(lobby.0).ok_or(JoinLobbyError::LobbyDoesNotExist)?;
|
let mut lobby = self.lobbies
|
||||||
let (index, empty_slot) = l.0.iter_mut()
|
.get(lobby_id.0)
|
||||||
|
.ok_or(JoinLobbyError::LobbyDoesNotExist)?
|
||||||
|
.write()
|
||||||
|
.await;
|
||||||
|
let (index, empty_slot) = lobby.0.iter_mut()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, k)| k.is_none())
|
.find(|(_, k)| k.is_none())
|
||||||
.ok_or(JoinLobbyError::LobbyFull)?;
|
.ok_or(JoinLobbyError::LobbyFull)?;
|
||||||
@ -168,40 +187,45 @@ impl ClientLocation {
|
|||||||
local_client: LocalClientId(index),
|
local_client: LocalClientId(index),
|
||||||
time_join: SystemTime::now(),
|
time_join: SystemTime::now(),
|
||||||
});
|
});
|
||||||
self.client_location.insert(id, RoomLobby::Lobby(lobby));
|
self.client_location
|
||||||
|
.write()
|
||||||
|
.await
|
||||||
|
.insert(id, RoomLobby::Lobby(lobby_id));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_client_to_next_available_lobby(&mut self, id: ClientId, lobby: LobbyId) -> Result<LobbyId, JoinLobbyError> {
|
pub async fn add_client_to_next_available_lobby(&self, id: ClientId, lobby: LobbyId) -> Result<LobbyId, JoinLobbyError> {
|
||||||
let l = (0..15)
|
pin!(stream::iter(0..15)
|
||||||
.map(|lobby_index| {
|
.filter_map(|lobby_index| async move {
|
||||||
let new_lobby = LobbyId((lobby.0 + lobby_index) % 15);
|
let new_lobby = LobbyId((lobby.0 + lobby_index) % 15);
|
||||||
(new_lobby, self.add_client_to_lobby(id, new_lobby))
|
Some((new_lobby, self.add_client_to_lobby(id, new_lobby).await.ok()?))
|
||||||
})
|
}))
|
||||||
.find(|(_, lobby_option)| {
|
.next()
|
||||||
lobby_option.is_ok()
|
.await
|
||||||
})
|
.map(|l| l.0)
|
||||||
.ok_or(JoinLobbyError::LobbyFull)?;
|
.ok_or(JoinLobbyError::LobbyFull)
|
||||||
|
|
||||||
Ok(l.0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_new_room(&mut self, id: ClientId) -> Result<RoomId, CreateRoomError> {
|
pub async fn create_new_room(&mut self, id: ClientId) -> Result<RoomId, CreateRoomError> {
|
||||||
let (index, empty_slot) = self.rooms.iter_mut()
|
let (index, empty_slot) = self.rooms.iter_mut()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, r)| r.is_none())
|
.find(|(_, r)| r.is_none())
|
||||||
.ok_or(CreateRoomError::NoOpenSlots)?;
|
.ok_or(CreateRoomError::NoOpenSlots)?;
|
||||||
*empty_slot = Some(Room([None; 4]));
|
*empty_slot = Some(Arc::new(RwLock::new(Room([None; 4]))));
|
||||||
self.add_client_to_room(id, RoomId(index)).map_err(|_err| CreateRoomError::JoinError)?;
|
self.add_client_to_room(id, RoomId(index))
|
||||||
|
.await
|
||||||
|
.map_err(|_err| CreateRoomError::JoinError)?;
|
||||||
|
|
||||||
Ok(RoomId(index))
|
Ok(RoomId(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_client_to_room(&mut self, id: ClientId, room: RoomId) -> Result<(), JoinRoomError> {
|
pub async fn add_client_to_room(&mut self, id: ClientId, room: RoomId) -> Result<(), JoinRoomError> {
|
||||||
let r = self.rooms.get_mut(room.0)
|
let mut r = self.rooms.get(room.0)
|
||||||
.ok_or(JoinRoomError::RoomDoesNotExist)?
|
.ok_or(JoinRoomError::RoomDoesNotExist)?
|
||||||
.as_mut()
|
.as_ref()
|
||||||
.ok_or(JoinRoomError::RoomDoesNotExist)?;
|
.ok_or(JoinRoomError::RoomDoesNotExist)?
|
||||||
|
.write()
|
||||||
|
.await;
|
||||||
let (index, empty_slot) = r.0.iter_mut()
|
let (index, empty_slot) = r.0.iter_mut()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, k)| k.is_none())
|
.find(|(_, k)| k.is_none())
|
||||||
@ -211,38 +235,51 @@ impl ClientLocation {
|
|||||||
local_client: LocalClientId(index),
|
local_client: LocalClientId(index),
|
||||||
time_join: SystemTime::now(),
|
time_join: SystemTime::now(),
|
||||||
});
|
});
|
||||||
self.remove_client_from_area(id);
|
self.remove_client_from_area(id).await;
|
||||||
self.client_location.insert(id, RoomLobby::Room(room));
|
self.client_location
|
||||||
|
.write()
|
||||||
|
.await
|
||||||
|
.insert(id, RoomLobby::Room(room));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_clients_by_client(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
|
pub async fn get_all_clients_by_client(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
|
||||||
let area = self.client_location.get(&id).ok_or(GetNeighborError::InvalidClient)?;
|
let area = self.client_location
|
||||||
|
.read()
|
||||||
|
.await;
|
||||||
|
let area = area
|
||||||
|
.get(&id)
|
||||||
|
.ok_or(GetNeighborError::InvalidClient)?;
|
||||||
match area {
|
match area {
|
||||||
RoomLobby::Room(room) => {
|
RoomLobby::Room(room) => {
|
||||||
Ok(self.get_clients_in_room(*room).map_err(|_| GetNeighborError::InvalidArea)?
|
Ok(self.get_clients_in_room(*room).await.map_err(|_| GetNeighborError::InvalidArea)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect())
|
.collect())
|
||||||
},
|
},
|
||||||
RoomLobby::Lobby(lobby) => {
|
RoomLobby::Lobby(lobby) => {
|
||||||
Ok(self.get_clients_in_lobby(*lobby).map_err(|_| GetNeighborError::InvalidArea)?
|
Ok(self.get_clients_in_lobby(*lobby).await.map_err(|_| GetNeighborError::InvalidArea)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_client_neighbors(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
|
pub async fn get_client_neighbors(&self, id: ClientId) -> Result<Vec<AreaClient>, GetNeighborError> {
|
||||||
let area = self.client_location.get(&id).ok_or(GetNeighborError::InvalidClient)?;
|
let area = self.client_location
|
||||||
|
.read()
|
||||||
|
.await;
|
||||||
|
let area = area
|
||||||
|
.get(&id)
|
||||||
|
.ok_or(GetNeighborError::InvalidClient)?;
|
||||||
match area {
|
match area {
|
||||||
RoomLobby::Room(room) => {
|
RoomLobby::Room(room) => {
|
||||||
Ok(self.get_clients_in_room(*room).map_err(|_| GetNeighborError::InvalidArea)?
|
Ok(self.get_clients_in_room(*room).await.map_err(|_| GetNeighborError::InvalidArea)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|c| c.client != id)
|
.filter(|c| c.client != id)
|
||||||
.collect())
|
.collect())
|
||||||
},
|
},
|
||||||
RoomLobby::Lobby(lobby) => {
|
RoomLobby::Lobby(lobby) => {
|
||||||
Ok(self.get_clients_in_lobby(*lobby).map_err(|_| GetNeighborError::InvalidArea)?
|
Ok(self.get_clients_in_lobby(*lobby).await.map_err(|_| GetNeighborError::InvalidArea)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|c| c.client != id)
|
.filter(|c| c.client != id)
|
||||||
.collect())
|
.collect())
|
||||||
@ -250,51 +287,72 @@ impl ClientLocation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_room_leader(&self, room: RoomId) -> Result<AreaClient, GetLeaderError> {
|
pub async fn get_room_leader(&self, room: RoomId) -> Result<AreaClient, GetLeaderError> {
|
||||||
let mut r = self.rooms[room.0]
|
let r = self.rooms[room.0]
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(GetLeaderError::InvalidArea)?
|
.ok_or(GetLeaderError::InvalidArea)?
|
||||||
.0.iter().flatten()
|
.read()
|
||||||
|
.await;
|
||||||
|
let mut r = r
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
r.sort_by_key(|k| k.time_join);
|
r.sort_by_key(|k| k.time_join);
|
||||||
let c = r.get(0).ok_or(GetLeaderError::NoClientInArea)?;
|
let c = r.get(0)
|
||||||
|
.ok_or(GetLeaderError::NoClientInArea)?;
|
||||||
Ok(**c)
|
Ok(**c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_lobby_leader(&self, lobby: LobbyId) -> Result<AreaClient, GetLeaderError> {
|
pub async fn get_lobby_leader(&self, lobby: LobbyId) -> Result<AreaClient, GetLeaderError> {
|
||||||
let mut l = self.lobbies[lobby.0]
|
let l = self.lobbies[lobby.0]
|
||||||
.0.iter().flatten()
|
.read()
|
||||||
|
.await;
|
||||||
|
let mut l = l
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
l.sort_by_key(|k| k.time_join);
|
l.sort_by_key(|k| k.time_join);
|
||||||
let c = l.get(0).ok_or(GetLeaderError::NoClientInArea)?;
|
let c = l.get(0).ok_or(GetLeaderError::NoClientInArea)?;
|
||||||
Ok(**c)
|
Ok(**c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_area_leader(&self, roomlobby: RoomLobby) -> Result<AreaClient, GetLeaderError> {
|
pub async fn get_area_leader(&self, roomlobby: RoomLobby) -> Result<AreaClient, GetLeaderError> {
|
||||||
match roomlobby {
|
match roomlobby {
|
||||||
RoomLobby::Room(room) => {
|
RoomLobby::Room(room) => {
|
||||||
self.get_room_leader(room)
|
self.get_room_leader(room).await
|
||||||
},
|
},
|
||||||
RoomLobby::Lobby(lobby) => {
|
RoomLobby::Lobby(lobby) => {
|
||||||
self.get_lobby_leader(lobby)
|
self.get_lobby_leader(lobby).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_leader_by_client(&self, id: ClientId) -> Result<AreaClient, GetLeaderError> {
|
pub async fn get_leader_by_client(&self, id: ClientId) -> Result<AreaClient, GetLeaderError> {
|
||||||
let area = self.client_location.get(&id).ok_or(GetLeaderError::InvalidClient)?;
|
let area = self.client_location
|
||||||
|
.read()
|
||||||
|
.await;
|
||||||
|
let area = area
|
||||||
|
.get(&id)
|
||||||
|
.ok_or(GetLeaderError::InvalidClient)?;
|
||||||
match area {
|
match area {
|
||||||
RoomLobby::Room(room) => {
|
RoomLobby::Room(room) => {
|
||||||
self.get_room_leader(*room)
|
self.get_room_leader(*room).await
|
||||||
},
|
},
|
||||||
RoomLobby::Lobby(lobby) => {
|
RoomLobby::Lobby(lobby) => {
|
||||||
self.get_lobby_leader(*lobby)
|
self.get_lobby_leader(*lobby).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_clients_in_lobby(&self, lobby: LobbyId) -> Result<Vec<AreaClient>, GetClientsError> {
|
pub async fn get_clients_in_lobby(&self, lobby: LobbyId) -> Result<Vec<AreaClient>, GetClientsError> {
|
||||||
Ok(self.lobbies.get(lobby.0).ok_or(GetClientsError::InvalidArea)?.0
|
Ok(self.lobbies
|
||||||
|
.get(lobby.0)
|
||||||
|
.ok_or(GetClientsError::InvalidArea)?
|
||||||
|
.read()
|
||||||
|
.await
|
||||||
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|client| {
|
.filter_map(|client| {
|
||||||
client.map(|c| {
|
client.map(|c| {
|
||||||
@ -303,10 +361,14 @@ impl ClientLocation {
|
|||||||
}).collect())
|
}).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_clients_in_room(&self, room: RoomId) -> Result<Vec<AreaClient>, GetClientsError> {
|
pub async fn get_clients_in_room(&self, room: RoomId) -> Result<Vec<AreaClient>, GetClientsError> {
|
||||||
Ok(self.rooms.get(room.0)
|
Ok(self.rooms.get(room.0)
|
||||||
.ok_or(GetClientsError::InvalidArea)?
|
.ok_or(GetClientsError::InvalidArea)?
|
||||||
.ok_or(GetClientsError::InvalidArea)?.0
|
.as_ref()
|
||||||
|
.ok_or(GetClientsError::InvalidArea)?
|
||||||
|
.read()
|
||||||
|
.await
|
||||||
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|client| {
|
.filter_map(|client| {
|
||||||
client.map(|c| {
|
client.map(|c| {
|
||||||
@ -315,17 +377,26 @@ impl ClientLocation {
|
|||||||
}).collect())
|
}).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_local_client(&self, id: ClientId) -> Result<AreaClient, GetClientsError> {
|
pub async fn get_local_client(&self, id: ClientId) -> Result<AreaClient, GetClientsError> {
|
||||||
let area = self.client_location.get(&id).ok_or(GetClientsError::InvalidClient)?;
|
let area = self.client_location
|
||||||
|
.read()
|
||||||
|
.await;
|
||||||
|
let area = area
|
||||||
|
.get(&id)
|
||||||
|
.ok_or(GetClientsError::InvalidClient)?;
|
||||||
match area {
|
match area {
|
||||||
RoomLobby::Room(room) => {
|
RoomLobby::Room(room) => {
|
||||||
self.get_clients_in_room(*room).map_err(|_| GetClientsError::InvalidArea)?
|
self.get_clients_in_room(*room)
|
||||||
|
.await
|
||||||
|
.map_err(|_| GetClientsError::InvalidArea)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|c| c.client == id)
|
.find(|c| c.client == id)
|
||||||
.ok_or(GetClientsError::InvalidClient)
|
.ok_or(GetClientsError::InvalidClient)
|
||||||
},
|
},
|
||||||
RoomLobby::Lobby(lobby) => {
|
RoomLobby::Lobby(lobby) => {
|
||||||
self.get_clients_in_lobby(*lobby).map_err(|_| GetClientsError::InvalidArea)?
|
self.get_clients_in_lobby(*lobby)
|
||||||
|
.await
|
||||||
|
.map_err(|_| GetClientsError::InvalidArea)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|c| c.client == id)
|
.find(|c| c.client == id)
|
||||||
.ok_or(GetClientsError::InvalidClient)
|
.ok_or(GetClientsError::InvalidClient)
|
||||||
@ -333,14 +404,17 @@ impl ClientLocation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_area(&self, id: ClientId) -> Result<RoomLobby, GetAreaError> {
|
pub async fn get_area(&self, id: ClientId) -> Result<RoomLobby, GetAreaError> {
|
||||||
self.client_location.get(&id)
|
self.client_location
|
||||||
|
.read()
|
||||||
|
.await
|
||||||
|
.get(&id)
|
||||||
.ok_or(GetAreaError::InvalidClient)
|
.ok_or(GetAreaError::InvalidClient)
|
||||||
.map(Clone::clone)
|
.map(Clone::clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_room(&self, id: ClientId) -> Result<RoomId, GetAreaError> {
|
pub async fn get_room(&self, id: ClientId) -> Result<RoomId, GetAreaError> {
|
||||||
if let RoomLobby::Room(room) = self.client_location.get(&id).ok_or(GetAreaError::InvalidClient)? {
|
if let RoomLobby::Room(room) = self.client_location.read().await.get(&id).ok_or(GetAreaError::InvalidClient)? {
|
||||||
Ok(*room)
|
Ok(*room)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -348,8 +422,8 @@ impl ClientLocation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_lobby(&self, id: ClientId) -> Result<LobbyId, GetAreaError> {
|
pub async fn get_lobby(&self, id: ClientId) -> Result<LobbyId, GetAreaError> {
|
||||||
if let RoomLobby::Lobby(lobby) = self.client_location.get(&id).ok_or(GetAreaError::InvalidClient)? {
|
if let RoomLobby::Lobby(lobby) = self.client_location.read().await.get(&id).ok_or(GetAreaError::InvalidClient)? {
|
||||||
Ok(*lobby)
|
Ok(*lobby)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -357,31 +431,41 @@ impl ClientLocation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_client_from_area(&mut self, id: ClientId) -> Result<(), ClientRemovalError> {
|
pub async fn remove_client_from_area(&self, id: ClientId) -> Result<(), ClientRemovalError> {
|
||||||
let area = self.client_location.get_mut(&id).ok_or(ClientRemovalError::ClientNotInArea)?;
|
fn remove_client<const N: usize>(id: ClientId, client_list : &mut [Option<AreaClient>; N]) {
|
||||||
let client_list = match area {
|
client_list
|
||||||
RoomLobby::Room(room) => {
|
.iter_mut()
|
||||||
self.rooms[room.0]
|
.filter(|client| {
|
||||||
.as_mut()
|
client.map_or(false, |c| {
|
||||||
.map(|r| {
|
c.client == id
|
||||||
r.0.iter_mut()
|
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
.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) => {
|
||||||
|
let r = self.rooms.get(room.0).ok_or(ClientRemovalError::InvalidArea)?;
|
||||||
|
if let Some(r) = r {
|
||||||
|
remove_client(id, &mut r.write().await.0)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Err(ClientRemovalError::InvalidArea)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
RoomLobby::Lobby(lobby) => {
|
RoomLobby::Lobby(lobby) => {
|
||||||
Some(self.lobbies[lobby.0].0.iter_mut())
|
remove_client(id, &mut self.lobbies[lobby.0].write().await.0)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
client_list
|
|
||||||
.ok_or(ClientRemovalError::InvalidArea)?
|
|
||||||
.filter(|client| {
|
|
||||||
client.map_or(false, |c| {
|
|
||||||
c.client == id
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.for_each(|client| {
|
|
||||||
*client = None
|
|
||||||
});
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,173 +481,174 @@ impl ClientLocation {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_add_client_to_lobby() {
|
async fn test_add_client_to_lobby() {
|
||||||
let mut cl = ClientLocation::default();
|
let cl = ClientLocation::default();
|
||||||
cl.add_client_to_lobby(ClientId(12), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await.unwrap();
|
||||||
cl.add_client_to_lobby(ClientId(13), LobbyId(1));
|
cl.add_client_to_lobby(ClientId(13), LobbyId(1)).await.unwrap();
|
||||||
cl.add_client_to_lobby(ClientId(14), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(14), LobbyId(0)).await.unwrap();
|
||||||
|
|
||||||
assert!(cl.get_clients_in_lobby(LobbyId(0)).into_iter().flatten().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
assert!(cl.get_clients_in_lobby(LobbyId(0)).await.into_iter().flatten().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
||||||
(ClientId(12), LocalClientId(0)),
|
(ClientId(12), LocalClientId(0)),
|
||||||
(ClientId(14), LocalClientId(1)),
|
(ClientId(14), LocalClientId(1)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_add_client_to_full_lobby() {
|
async fn test_add_client_to_full_lobby() {
|
||||||
let mut cl = ClientLocation::default();
|
let cl = ClientLocation::default();
|
||||||
(0..12).for_each(|i| {
|
for i in 0..12 {
|
||||||
cl.add_client_to_lobby(ClientId(i), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(i), LobbyId(0)).await.unwrap();
|
||||||
});
|
}
|
||||||
assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(0)) == Err(JoinLobbyError::LobbyFull));
|
assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(0)).await == Err(JoinLobbyError::LobbyFull));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_add_client_to_next_available_lobby() {
|
async fn test_add_client_to_next_available_lobby() {
|
||||||
let mut cl = ClientLocation::default();
|
let cl = ClientLocation::default();
|
||||||
(1..4).for_each(|lobby| {
|
for lobby in 1..4 {
|
||||||
(0..12).for_each(|i| {
|
for i in 0..12 {
|
||||||
cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby));
|
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)) == Ok(LobbyId(4)));
|
assert!(cl.add_client_to_next_available_lobby(ClientId(99), LobbyId(1)).await == Ok(LobbyId(4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_add_to_lobby_when_all_are_full() {
|
async fn test_add_to_lobby_when_all_are_full() {
|
||||||
let mut cl = ClientLocation::default();
|
let cl = ClientLocation::default();
|
||||||
(0..15).for_each(|lobby| {
|
for lobby in 0..15 {
|
||||||
(0..12).for_each(|i| {
|
for i in 0..12 {
|
||||||
cl.add_client_to_lobby(ClientId(lobby*12+i), LobbyId(lobby));
|
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)) == Err(JoinLobbyError::LobbyFull));
|
assert_eq!(cl.add_client_to_next_available_lobby(ClientId(99), LobbyId(1)).await, Err(JoinLobbyError::LobbyFull));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_new_room() {
|
async fn test_new_room() {
|
||||||
let mut cl = ClientLocation::default();
|
let mut cl = ClientLocation::default();
|
||||||
assert!(cl.create_new_room(ClientId(12)) == Ok(RoomId(0)));
|
assert!(cl.create_new_room(ClientId(12)).await == Ok(RoomId(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_add_client_to_room() {
|
async fn test_add_client_to_room() {
|
||||||
let mut cl = ClientLocation::default();
|
let mut cl = ClientLocation::default();
|
||||||
let room = cl.create_new_room(ClientId(12)).unwrap();
|
let room = cl.create_new_room(ClientId(12)).await.unwrap();
|
||||||
assert!(cl.add_client_to_room(ClientId(234), room) == Ok(()));
|
assert!(cl.add_client_to_room(ClientId(234), room).await == Ok(()));
|
||||||
assert!(cl.get_clients_in_room(room).unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
||||||
(ClientId(12), LocalClientId(0)),
|
(ClientId(12), LocalClientId(0)),
|
||||||
(ClientId(234), LocalClientId(1)),
|
(ClientId(234), LocalClientId(1)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_no_new_room_slots() {
|
async fn test_no_new_room_slots() {
|
||||||
let mut cl = ClientLocation::default();
|
let mut cl = ClientLocation::default();
|
||||||
for i in 0..128 {
|
for i in 0..128 {
|
||||||
cl.create_new_room(ClientId(i));
|
cl.create_new_room(ClientId(i)).await;
|
||||||
}
|
}
|
||||||
assert!(cl.create_new_room(ClientId(234)) == Err(CreateRoomError::NoOpenSlots));
|
assert!(cl.create_new_room(ClientId(234)).await == Err(CreateRoomError::NoOpenSlots));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_joining_full_room() {
|
async fn test_joining_full_room() {
|
||||||
let mut cl = ClientLocation::default();
|
let mut cl = ClientLocation::default();
|
||||||
let room = cl.create_new_room(ClientId(0)).unwrap();
|
let room = cl.create_new_room(ClientId(0)).await.unwrap();
|
||||||
assert!(cl.add_client_to_room(ClientId(1), room) == Ok(()));
|
assert!(cl.add_client_to_room(ClientId(1), room).await == Ok(()));
|
||||||
assert!(cl.add_client_to_room(ClientId(2), room) == Ok(()));
|
assert!(cl.add_client_to_room(ClientId(2), room).await == Ok(()));
|
||||||
assert!(cl.add_client_to_room(ClientId(3), room) == Ok(()));
|
assert!(cl.add_client_to_room(ClientId(3), room).await == Ok(()));
|
||||||
assert!(cl.add_client_to_room(ClientId(234), room) == Err(JoinRoomError::RoomFull));
|
assert!(cl.add_client_to_room(ClientId(234), room).await == Err(JoinRoomError::RoomFull));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_adding_client_to_room_removes_from_lobby() {
|
async fn test_adding_client_to_room_removes_from_lobby() {
|
||||||
let mut cl = ClientLocation::default();
|
let mut cl = ClientLocation::default();
|
||||||
cl.add_client_to_lobby(ClientId(93), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await;
|
||||||
cl.add_client_to_lobby(ClientId(23), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await;
|
||||||
cl.add_client_to_lobby(ClientId(51), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await;
|
||||||
cl.add_client_to_lobby(ClientId(12), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await;
|
||||||
|
|
||||||
let room = cl.create_new_room(ClientId(51)).unwrap();
|
let room = cl.create_new_room(ClientId(51)).await.unwrap();
|
||||||
assert!(cl.add_client_to_room(ClientId(93), room) == Ok(()));
|
assert!(cl.add_client_to_room(ClientId(93), room).await == Ok(()));
|
||||||
assert!(cl.get_clients_in_lobby(LobbyId(0)).unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
assert!(cl.get_clients_in_lobby(LobbyId(0)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
||||||
(ClientId(23), LocalClientId(1)),
|
(ClientId(23), LocalClientId(1)),
|
||||||
(ClientId(12), LocalClientId(3)),
|
(ClientId(12), LocalClientId(3)),
|
||||||
]);
|
]);
|
||||||
assert!(cl.get_clients_in_room(room).unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
||||||
(ClientId(51), LocalClientId(0)),
|
(ClientId(51), LocalClientId(0)),
|
||||||
(ClientId(93), LocalClientId(1)),
|
(ClientId(93), LocalClientId(1)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_getting_neighbors() {
|
async fn test_getting_neighbors() {
|
||||||
let mut cl = ClientLocation::default();
|
let cl = ClientLocation::default();
|
||||||
cl.add_client_to_lobby(ClientId(93), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await.unwrap();
|
||||||
cl.add_client_to_lobby(ClientId(23), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await.unwrap();
|
||||||
cl.add_client_to_lobby(ClientId(51), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await.unwrap();
|
||||||
cl.add_client_to_lobby(ClientId(12), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await.unwrap();
|
||||||
|
|
||||||
assert!(cl.get_client_neighbors(ClientId(23)).unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
assert!(cl.get_client_neighbors(ClientId(23)).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
||||||
(ClientId(93), LocalClientId(0)),
|
(ClientId(93), LocalClientId(0)),
|
||||||
(ClientId(51), LocalClientId(2)),
|
(ClientId(51), LocalClientId(2)),
|
||||||
(ClientId(12), LocalClientId(3)),
|
(ClientId(12), LocalClientId(3)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_failing_to_join_lobby_does_not_remove_from_current_area() {
|
async fn test_failing_to_join_lobby_does_not_remove_from_current_area() {
|
||||||
let mut cl = ClientLocation::default();
|
let cl = ClientLocation::default();
|
||||||
(0..12).for_each(|i| {
|
for i in 0..12 {
|
||||||
cl.add_client_to_lobby(ClientId(i), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(i), LobbyId(0)).await.unwrap();
|
||||||
});
|
}
|
||||||
cl.add_client_to_lobby(ClientId(99), LobbyId(1));
|
assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(1)).await.is_ok());
|
||||||
cl.add_client_to_lobby(ClientId(99), LobbyId(0));
|
assert!(cl.add_client_to_lobby(ClientId(99), LobbyId(0)).await.is_err());
|
||||||
assert!(cl.get_clients_in_lobby(LobbyId(0)).unwrap().len() == 12);
|
assert_eq!(cl.get_clients_in_lobby(LobbyId(0)).await.unwrap().len(), 12);
|
||||||
assert!(cl.get_clients_in_lobby(LobbyId(1)).unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
assert_eq!(
|
||||||
(ClientId(99), LocalClientId(0)),
|
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))]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_get_leader() {
|
async fn test_get_leader() {
|
||||||
let mut cl = ClientLocation::default();
|
let cl = ClientLocation::default();
|
||||||
cl.add_client_to_lobby(ClientId(93), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(93), LobbyId(0)).await;
|
||||||
cl.add_client_to_lobby(ClientId(23), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(23), LobbyId(0)).await;
|
||||||
cl.add_client_to_lobby(ClientId(51), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(51), LobbyId(0)).await;
|
||||||
cl.add_client_to_lobby(ClientId(12), LobbyId(0));
|
cl.add_client_to_lobby(ClientId(12), LobbyId(0)).await;
|
||||||
|
|
||||||
assert!(cl.get_leader_by_client(ClientId(51)).map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(0))));
|
assert!(cl.get_leader_by_client(ClientId(51)).await.map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_remove_client_from_room() {
|
async fn test_remove_client_from_room() {
|
||||||
let mut cl = ClientLocation::default();
|
let mut cl = ClientLocation::default();
|
||||||
let room = cl.create_new_room(ClientId(51)).unwrap();
|
let room = cl.create_new_room(ClientId(51)).await.unwrap();
|
||||||
cl.add_client_to_room(ClientId(93), room);
|
cl.add_client_to_room(ClientId(93), room).await;
|
||||||
cl.add_client_to_room(ClientId(23), room);
|
cl.add_client_to_room(ClientId(23), room).await;
|
||||||
cl.remove_client_from_area(ClientId(51));
|
cl.remove_client_from_area(ClientId(51)).await;
|
||||||
cl.add_client_to_room(ClientId(12), room);
|
cl.add_client_to_room(ClientId(12), room).await;
|
||||||
|
|
||||||
assert!(cl.get_clients_in_room(room).unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
assert!(cl.get_clients_in_room(room).await.unwrap().into_iter().map(|c| (c.client, c.local_client)).collect::<Vec<_>>() == vec![
|
||||||
(ClientId(12), LocalClientId(0)),
|
(ClientId(12), LocalClientId(0)),
|
||||||
(ClientId(93), LocalClientId(1)),
|
(ClientId(93), LocalClientId(1)),
|
||||||
(ClientId(23), LocalClientId(2)),
|
(ClientId(23), LocalClientId(2)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_leader_changes_on_leader_leaving() {
|
async fn test_leader_changes_on_leader_leaving() {
|
||||||
let mut cl = ClientLocation::default();
|
let mut cl = ClientLocation::default();
|
||||||
let room = cl.create_new_room(ClientId(51)).unwrap();
|
let room = cl.create_new_room(ClientId(51)).await.unwrap();
|
||||||
cl.add_client_to_room(ClientId(93), room);
|
cl.add_client_to_room(ClientId(93), room).await.unwrap();
|
||||||
cl.add_client_to_room(ClientId(23), room);
|
cl.add_client_to_room(ClientId(23), room).await.unwrap();
|
||||||
cl.remove_client_from_area(ClientId(51));
|
cl.remove_client_from_area(ClientId(51)).await.unwrap();
|
||||||
cl.add_client_to_room(ClientId(12), room);
|
cl.add_client_to_room(ClientId(12), room).await.unwrap();
|
||||||
cl.remove_client_from_area(ClientId(23));
|
cl.remove_client_from_area(ClientId(23)).await.unwrap();
|
||||||
cl.add_client_to_room(ClientId(99), room);
|
cl.add_client_to_room(ClientId(99), room).await.unwrap();
|
||||||
|
|
||||||
assert!(cl.get_leader_by_client(ClientId(12)).map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(1))));
|
assert!(cl.get_leader_by_client(ClientId(12)).await.map(|c| (c.client, c.local_client)) == Ok((ClientId(93), LocalClientId(1))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@ use crate::ship::packet::builder::{player_info};
|
|||||||
use crate::ship::items::state::ItemState;
|
use crate::ship::items::state::ItemState;
|
||||||
|
|
||||||
|
|
||||||
pub fn join_lobby(id: ClientId,
|
pub async fn join_lobby(id: ClientId,
|
||||||
lobby: LobbyId,
|
lobby: LobbyId,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &Clients,
|
clients: &Clients,
|
||||||
item_state: &ItemState)
|
item_state: &ItemState)
|
||||||
-> Result<JoinLobby, anyhow::Error> {
|
-> Result<JoinLobby, anyhow::Error> {
|
||||||
let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| -> ClientLocationError { err.into() })?;
|
let lobby_clients = client_location.get_clients_in_lobby(lobby).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let playerinfo = lobby_clients.iter()
|
let playerinfo = lobby_clients.iter()
|
||||||
.map(|area_client| {
|
.map(|area_client| {
|
||||||
let client = clients.get(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client)).unwrap();
|
let client = clients.get(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client)).unwrap();
|
||||||
@ -20,8 +20,8 @@ pub fn join_lobby(id: ClientId,
|
|||||||
});
|
});
|
||||||
|
|
||||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let leader = client_location.get_lobby_leader(lobby).map_err(|err| -> ClientLocationError { err.into() })?;
|
let leader = client_location.get_lobby_leader(lobby).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(JoinLobby {
|
Ok(JoinLobby {
|
||||||
client: area_client.local_client.id(),
|
client: area_client.local_client.id(),
|
||||||
leader: leader.local_client.id(),
|
leader: leader.local_client.id(),
|
||||||
@ -34,15 +34,15 @@ pub fn join_lobby(id: ClientId,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_to_lobby(id: ClientId,
|
pub async fn add_to_lobby(id: ClientId,
|
||||||
lobby: LobbyId,
|
lobby: LobbyId,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &Clients,
|
clients: &Clients,
|
||||||
item_state: &ItemState)
|
item_state: &ItemState)
|
||||||
-> Result<AddToLobby, ShipError> {
|
-> Result<AddToLobby, ShipError> {
|
||||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let leader = client_location.get_lobby_leader(lobby).map_err(|err| -> ClientLocationError { err.into() })?;
|
let leader = client_location.get_lobby_leader(lobby).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(AddToLobby {
|
Ok(AddToLobby {
|
||||||
flag: 1,
|
flag: 1,
|
||||||
client: area_client.local_client.id(),
|
client: area_client.local_client.id(),
|
||||||
@ -56,12 +56,16 @@ pub fn add_to_lobby(id: ClientId,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_from_lobby(id: ClientId,
|
pub async fn remove_from_lobby(id: ClientId,
|
||||||
client_location: &ClientLocation)
|
client_location: &ClientLocation)
|
||||||
-> Result<LeaveLobby, ShipError> {
|
-> Result<LeaveLobby, ShipError> {
|
||||||
let prev_area_index = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?.local_client.id();
|
let prev_area_index = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?.local_client.id();
|
||||||
let prev_area_leader_index = client_location.get_area_leader(client_location.get_area(id)
|
let prev_area_leader_index = client_location
|
||||||
.map_err(|err| -> ClientLocationError { err.into() })?)
|
.get_area_leader(client_location
|
||||||
|
.get_area(id)
|
||||||
|
.await
|
||||||
|
.map_err(|err| -> ClientLocationError { err.into() })?)
|
||||||
|
.await
|
||||||
.map_err(|err| -> ClientLocationError { err.into() })?.local_client.id();
|
.map_err(|err| -> ClientLocationError { err.into() })?.local_client.id();
|
||||||
Ok(LeaveLobby {
|
Ok(LeaveLobby {
|
||||||
client: prev_area_index,
|
client: prev_area_index,
|
||||||
|
@ -7,26 +7,28 @@ use crate::ship::items::state::ItemState;
|
|||||||
use crate::ship::packet::builder::{player_header, player_info};
|
use crate::ship::packet::builder::{player_header, player_info};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub fn join_room(id: ClientId,
|
use futures::stream::StreamExt;
|
||||||
clients: &Clients,
|
|
||||||
client_location: &ClientLocation,
|
pub async fn join_room(id: ClientId,
|
||||||
room_id: RoomId,
|
clients: &Clients,
|
||||||
room: &RoomState)
|
client_location: &ClientLocation,
|
||||||
-> Result<JoinRoom, ShipError> {
|
room_id: RoomId,
|
||||||
let all_clients = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
room: &RoomState)
|
||||||
let players = all_clients.iter()
|
-> Result<JoinRoom, ShipError> {
|
||||||
|
let all_clients = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
let players = futures::stream::iter(all_clients.iter())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.fold(Ok([PlayerHeader::default(); 4]), |acc, (i, c)| -> Result<_, ShipError> {
|
.fold::<Result<_, ShipError>, _, _>(Ok([PlayerHeader::default(); 4]), |acc, (i, c)| async move {
|
||||||
let header_client = clients.get(&c.client).ok_or(ShipError::ClientNotFound(id))?;
|
let header_client = clients.get(&c.client).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let header_area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let header_area_client = client_location.get_local_client(id).await.map_err(|err| ShipError::ClientLocationError(err.into()))?;
|
||||||
acc.map(|mut a| {
|
acc.map(|mut a| {
|
||||||
a[i] = player_header(0x10000, header_client, &header_area_client);
|
a[i] = player_header(0x10000, header_client, &header_area_client);
|
||||||
a
|
a
|
||||||
})
|
})
|
||||||
})?;
|
}).await?;
|
||||||
|
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let leader = client_location.get_room_leader(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(JoinRoom {
|
Ok(JoinRoom {
|
||||||
flag: all_clients.len() as u32,
|
flag: all_clients.len() as u32,
|
||||||
maps: room.maps.map_headers(),
|
maps: room.maps.map_headers(),
|
||||||
|
@ -4,24 +4,24 @@ use crate::ship::ship::{SendShipPacket, ShipError, Clients};
|
|||||||
use crate::ship::location::{ClientLocation};
|
use crate::ship::location::{ClientLocation};
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::EntityGateway;
|
||||||
|
|
||||||
pub fn player_chat(id: ClientId,
|
pub async fn player_chat(id: ClientId,
|
||||||
msg: &PlayerChat,
|
msg: &PlayerChat,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &Clients) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
clients: &Clients) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let cmsg = PlayerChat::new(client.user.id.0, msg.message.clone());
|
let cmsg = PlayerChat::new(client.user.id.0, msg.message.clone());
|
||||||
|
|
||||||
Ok(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
Ok(Box::new(client_location.get_all_clients_by_client(id).await.unwrap().into_iter()
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::PlayerChat(cmsg.clone()))
|
(client.client, SendShipPacket::PlayerChat(cmsg.clone()))
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_infoboard(id: ClientId,
|
pub async fn request_infoboard(id: ClientId,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &Clients)
|
clients: &Clients)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let area_clients = client_location.get_client_neighbors(id).unwrap();
|
let area_clients = client_location.get_client_neighbors(id).await.unwrap();
|
||||||
let r = area_clients.iter()
|
let r = area_clients.iter()
|
||||||
.filter_map(|c| {
|
.filter_map(|c| {
|
||||||
clients.get(&c.client)
|
clients.get(&c.client)
|
||||||
|
@ -34,21 +34,24 @@ pub enum MessageError {
|
|||||||
MismatchedTekIds(ClientItemId, ClientItemId),
|
MismatchedTekIds(ClientItemId, ClientItemId),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_to_client(id: ClientId, target: u8, msg: DirectMessage, client_location: &ClientLocation)
|
async fn send_to_client(id: ClientId,
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
target: u8,
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
msg: DirectMessage,
|
||||||
|
client_location: &ClientLocation)
|
||||||
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
|
Box::new(client_location.get_all_clients_by_client(id).await.unwrap().into_iter()
|
||||||
.filter(move |client| client.local_client.id() == target)
|
.filter(move |client| client.local_client.id() == target)
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::DirectMessage(msg.clone()))
|
(client.client, SendShipPacket::DirectMessage(msg.clone()))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn guildcard_send(id: ClientId,
|
pub async fn guildcard_send(id: ClientId,
|
||||||
guildcard_send: &GuildcardSend,
|
guildcard_send: &GuildcardSend,
|
||||||
target: u32,
|
target: u32,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &Clients)
|
clients: &Clients)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let client = clients.get(&id).unwrap();
|
let client = clients.get(&id).unwrap();
|
||||||
let msg = DirectMessage{
|
let msg = DirectMessage{
|
||||||
flag: target,
|
flag: target,
|
||||||
@ -65,7 +68,7 @@ pub fn guildcard_send(id: ClientId,
|
|||||||
class: client.character.char_class.into(),
|
class: client.character.char_class.into(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
send_to_client(id, target as u8, msg, client_location)
|
send_to_client(id, target as u8, msg, client_location).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_item<EG>(id: ClientId,
|
pub async fn request_item<EG>(id: ClientId,
|
||||||
@ -79,7 +82,7 @@ pub async fn request_item<EG>(id: ClientId,
|
|||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||||
.as_mut()
|
.as_mut()
|
||||||
@ -90,7 +93,7 @@ where
|
|||||||
return Err(ShipError::MonsterAlreadyDroppedItem(id, request_item.enemy_id).into())
|
return Err(ShipError::MonsterAlreadyDroppedItem(id, request_item.enemy_id).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
let client_and_drop = clients_in_area.into_iter()
|
let client_and_drop = clients_in_area.into_iter()
|
||||||
.filter_map(|area_client| {
|
.filter_map(|area_client| {
|
||||||
@ -129,9 +132,9 @@ where
|
|||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
let (item, floor_type) = item_state.get_floor_item(&client.character.id, &ClientItemId(pickup_item.item_id))?;
|
let (item, floor_type) = item_state.get_floor_item(&client.character.id, &ClientItemId(pickup_item.item_id))?;
|
||||||
let remove_item = builder::message::remove_item_from_floor(area_client, item)?;
|
let remove_item = builder::message::remove_item_from_floor(area_client, item)?;
|
||||||
@ -173,17 +176,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_box_item<EG>(id: ClientId,
|
pub async fn request_box_item<EG>(id: ClientId,
|
||||||
box_drop_request: &BoxDropRequest,
|
box_drop_request: &BoxDropRequest,
|
||||||
mut entity_gateway: EG,
|
mut entity_gateway: EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
rooms: &mut Rooms,
|
rooms: &mut Rooms,
|
||||||
item_state: &mut ItemState)
|
item_state: &mut ItemState)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||||
.as_mut()
|
.as_mut()
|
||||||
@ -194,7 +197,7 @@ EG: EntityGateway
|
|||||||
return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id).into())
|
return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
let client_and_drop = clients_in_area.into_iter()
|
let client_and_drop = clients_in_area.into_iter()
|
||||||
.filter_map(|area_client| {
|
.filter_map(|area_client| {
|
||||||
@ -245,8 +248,8 @@ where
|
|||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let other_clients_in_area = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let other_clients_in_area = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let bank_action_pkts = match bank_interaction.action {
|
let bank_action_pkts = match bank_interaction.action {
|
||||||
BANK_ACTION_DEPOSIT => {
|
BANK_ACTION_DEPOSIT => {
|
||||||
if bank_interaction.item_id == 0xFFFFFFFF {
|
if bank_interaction.item_id == 0xFFFFFFFF {
|
||||||
@ -294,7 +297,7 @@ pub async fn shop_request(id: ClientId,
|
|||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get(room_id.0)
|
let room = rooms.get(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -335,7 +338,7 @@ where
|
|||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
let (item, remove): (&(dyn ShopItem + Send + Sync), bool) = match buy_item.shop_type {
|
let (item, remove): (&(dyn ShopItem + Send + Sync), bool) = match buy_item.shop_type {
|
||||||
SHOP_OPTION_WEAPON => {
|
SHOP_OPTION_WEAPON => {
|
||||||
@ -371,7 +374,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let other_clients_in_area = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let other_clients_in_area = client_location.get_client_neighbors(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(Box::new(other_clients_in_area.into_iter()
|
Ok(Box::new(other_clients_in_area.into_iter()
|
||||||
.map(move |c| {
|
.map(move |c| {
|
||||||
(c.client, SendShipPacket::Message(Message::new(GameMessage::CreateItem(create.clone()))))
|
(c.client, SendShipPacket::Message(Message::new(GameMessage::CreateItem(create.clone()))))
|
||||||
@ -400,6 +403,7 @@ where
|
|||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
|
|
||||||
|
// TODO: secids have different mod rates
|
||||||
let (grind_mod, special_mod, percent_mod) = {
|
let (grind_mod, special_mod, percent_mod) = {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
@ -443,7 +447,7 @@ where
|
|||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
if let Some((item_id, special_mod, percent_mod, grind_mod)) = client.tek {
|
if let Some((item_id, special_mod, percent_mod, grind_mod)) = client.tek {
|
||||||
if item_id.0 != tek_accept.item_id {
|
if item_id.0 != tek_accept.item_id {
|
||||||
@ -459,7 +463,7 @@ where
|
|||||||
|
|
||||||
let create_item_pkt = builder::message::create_individual_item(area_client, item_id, &weapon)?;
|
let create_item_pkt = builder::message::create_individual_item(area_client, item_id, &weapon)?;
|
||||||
|
|
||||||
let neighbors = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let neighbors = client_location.get_client_neighbors(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(Box::new(neighbors.into_iter()
|
Ok(Box::new(neighbors.into_iter()
|
||||||
.map(move |c| {
|
.map(move |c| {
|
||||||
(c.client, SendShipPacket::Message(Message::new(GameMessage::CreateItem(create_item_pkt.clone()))))
|
(c.client, SendShipPacket::Message(Message::new(GameMessage::CreateItem(create_item_pkt.clone()))))
|
||||||
|
@ -46,16 +46,16 @@ pub fn block_selected(id: ClientId,
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_player_to_lobby(id: ClientId,
|
pub async fn send_player_to_lobby(id: ClientId,
|
||||||
_pkt: &CharData,
|
_pkt: &CharData,
|
||||||
client_location: &mut ClientLocation,
|
client_location: &mut ClientLocation,
|
||||||
clients: &Clients,
|
clients: &Clients,
|
||||||
item_state: &ItemState)
|
item_state: &ItemState)
|
||||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||||
let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?;
|
let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).await.map_err(|_| ShipError::TooManyClients)?;
|
||||||
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state)?;
|
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state).await?;
|
||||||
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state)?;
|
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state).await?;
|
||||||
let neighbors = client_location.get_client_neighbors(id).unwrap();
|
let neighbors = client_location.get_client_neighbors(id).await.unwrap();
|
||||||
Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))]
|
Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(neighbors.into_iter()
|
.chain(neighbors.into_iter()
|
||||||
@ -72,7 +72,7 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId,
|
|||||||
mut entity_gateway: EG)
|
mut entity_gateway: EG)
|
||||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let prev_area = client_location.get_area(id).map_err(|err| -> ClientLocationError {err.into()})?;
|
let prev_area = client_location.get_area(id).await.map_err(|err| -> ClientLocationError {err.into()})?;
|
||||||
match prev_area {
|
match prev_area {
|
||||||
RoomLobby::Lobby(old_lobby) => {
|
RoomLobby::Lobby(old_lobby) => {
|
||||||
if old_lobby.0 == requested_lobby as usize {
|
if old_lobby.0 == requested_lobby as usize {
|
||||||
@ -80,30 +80,30 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
RoomLobby::Room(old_room) => {
|
RoomLobby::Room(old_room) => {
|
||||||
if client_location.get_client_neighbors(id)?.is_empty() {
|
if client_location.get_client_neighbors(id).await?.is_empty() {
|
||||||
ship_rooms[old_room.0] = None;
|
ship_rooms[old_room.0] = None;
|
||||||
}
|
}
|
||||||
item_state.remove_character_from_room(&client.character);
|
item_state.remove_character_from_room(&client.character);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
let leave_lobby = packet::builder::lobby::remove_from_lobby(id, client_location)?;
|
let leave_lobby = packet::builder::lobby::remove_from_lobby(id, client_location).await?;
|
||||||
let old_neighbors = client_location.get_client_neighbors(id).unwrap();
|
let old_neighbors = client_location.get_client_neighbors(id).await.unwrap();
|
||||||
let mut lobby = LobbyId(requested_lobby as usize);
|
let mut lobby = LobbyId(requested_lobby as usize);
|
||||||
if client_location.add_client_to_lobby(id, lobby).is_err() {
|
if client_location.add_client_to_lobby(id, lobby).await.is_err() {
|
||||||
match prev_area {
|
match prev_area {
|
||||||
RoomLobby::Lobby(_lobby) => {
|
RoomLobby::Lobby(_lobby) => {
|
||||||
let dialog = SmallDialog::new(String::from("Lobby is full."));
|
let dialog = SmallDialog::new(String::from("Lobby is full."));
|
||||||
return Ok(vec![(id, SendShipPacket::SmallDialog(dialog))])
|
return Ok(vec![(id, SendShipPacket::SmallDialog(dialog))])
|
||||||
}
|
}
|
||||||
RoomLobby::Room(_room) => {
|
RoomLobby::Room(_room) => {
|
||||||
lobby = client_location.add_client_to_next_available_lobby(id, lobby).map_err(|_| ShipError::TooManyClients)?;
|
lobby = client_location.add_client_to_next_available_lobby(id, lobby).await.map_err(|_| ShipError::TooManyClients)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item_state.load_character(&mut entity_gateway, &client.character).await?;
|
item_state.load_character(&mut entity_gateway, &client.character).await?;
|
||||||
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state)?;
|
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state).await?;
|
||||||
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state)?;
|
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state).await?;
|
||||||
let neighbors = client_location.get_client_neighbors(id).unwrap();
|
let neighbors = client_location.get_client_neighbors(id).await.unwrap();
|
||||||
Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))]
|
Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(neighbors.into_iter()
|
.chain(neighbors.into_iter()
|
||||||
@ -113,30 +113,30 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId,
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_from_lobby(id: ClientId,
|
pub async fn remove_from_lobby(id: ClientId,
|
||||||
client_location: &mut ClientLocation)
|
client_location: &mut ClientLocation)
|
||||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||||
let area_client = client_location.get_local_client(id)?;
|
let area_client = client_location.get_local_client(id).await?;
|
||||||
let neighbors = client_location.get_client_neighbors(id)?;
|
let neighbors = client_location.get_client_neighbors(id).await?;
|
||||||
let leader = client_location.get_leader_by_client(id)?;
|
let leader = client_location.get_leader_by_client(id).await?;
|
||||||
let leave_lobby_pkt = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
let leave_lobby_pkt = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||||
|
|
||||||
client_location.remove_client_from_area(id)?;
|
client_location.remove_client_from_area(id).await?;
|
||||||
Ok(neighbors.into_iter().map(|n| {
|
Ok(neighbors.into_iter().map(|n| {
|
||||||
(n.client, leave_lobby_pkt.clone())
|
(n.client, leave_lobby_pkt.clone())
|
||||||
}).collect())
|
}).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_room_tab_info(id: ClientId,
|
pub async fn get_room_tab_info(id: ClientId,
|
||||||
pkt: &MenuDetail,
|
pkt: &MenuDetail,
|
||||||
client_location: &mut ClientLocation,
|
client_location: &mut ClientLocation,
|
||||||
clients: &Clients,
|
clients: &Clients,
|
||||||
rooms: &mut Rooms)
|
rooms: &mut Rooms)
|
||||||
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
-> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||||
let room_id = RoomId(pkt.item as usize);
|
let room_id = RoomId(pkt.item as usize);
|
||||||
if let Some(_room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? {
|
if let Some(_room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? {
|
||||||
let mut room_info = String::new();
|
let mut room_info = String::new();
|
||||||
let clients_in_room = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_room = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
for client in clients_in_room {
|
for client in clients_in_room {
|
||||||
let cs = clients.get(&client.client).ok_or(ShipError::ClientNotFound(client.client))?;
|
let cs = clients.get(&client.client).ok_or(ShipError::ClientNotFound(client.client))?;
|
||||||
let gc = cs.user.guildcard;
|
let gc = cs.user.guildcard;
|
||||||
|
@ -19,8 +19,8 @@ pub async fn request_exp<EG: EntityGateway>(id: ClientId,
|
|||||||
rooms: &mut Rooms)
|
rooms: &mut Rooms)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||||
.as_mut()
|
.as_mut()
|
||||||
@ -36,7 +36,7 @@ pub async fn request_exp<EG: EntityGateway>(id: ClientId,
|
|||||||
((monster_stats.exp as f32) * 0.8) as u32
|
((monster_stats.exp as f32) * 0.8) as u32
|
||||||
};
|
};
|
||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let gain_exp_pkt = builder::message::character_gained_exp(area_client, exp_gain);
|
let gain_exp_pkt = builder::message::character_gained_exp(area_client, exp_gain);
|
||||||
let mut exp_pkts: Box<dyn Iterator<Item = _> + Send> = Box::new(clients_in_area.clone().into_iter()
|
let mut exp_pkts: Box<dyn Iterator<Item = _> + Send> = Box::new(clients_in_area.clone().into_iter()
|
||||||
.map(move |c| {
|
.map(move |c| {
|
||||||
@ -76,14 +76,14 @@ where
|
|||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
let area = room.map_areas.get_area_map(player_drop_item.map_area)?;
|
let area = room.map_areas.get_area_map(player_drop_item.map_area)?;
|
||||||
drop_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(player_drop_item.item_id), *area, (player_drop_item.x, player_drop_item.y, player_drop_item.z)).await?;
|
drop_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(player_drop_item.item_id), *area, (player_drop_item.x, player_drop_item.y, player_drop_item.z)).await?;
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let pdi = player_drop_item.clone();
|
let pdi = player_drop_item.clone();
|
||||||
Ok(Box::new(clients_in_area.into_iter()
|
Ok(Box::new(clients_in_area.into_iter()
|
||||||
.map(move |c| {
|
.map(move |c| {
|
||||||
@ -91,15 +91,15 @@ where
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drop_coordinates(id: ClientId,
|
pub async fn drop_coordinates(id: ClientId,
|
||||||
drop_coordinates: &DropCoordinates,
|
drop_coordinates: &DropCoordinates,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
rooms: &Rooms)
|
rooms: &Rooms)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get(room_id.0)
|
let room = rooms.get(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -126,8 +126,8 @@ where
|
|||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
if let Some(drop_location) = client.item_drop_location {
|
if let Some(drop_location) = client.item_drop_location {
|
||||||
if drop_location.item_id.0 != no_longer_has_item.item_id {
|
if drop_location.item_id.0 != no_longer_has_item.item_id {
|
||||||
return Err(ShipError::DropInvalidItemId(no_longer_has_item.item_id).into());
|
return Err(ShipError::DropInvalidItemId(no_longer_has_item.item_id).into());
|
||||||
@ -140,7 +140,7 @@ where
|
|||||||
let no_longer_has_meseta_pkt = builder::message::player_no_longer_has_meseta(area_client, no_longer_has_item.amount as u32);
|
let no_longer_has_meseta_pkt = builder::message::player_no_longer_has_meseta(area_client, no_longer_has_item.amount as u32);
|
||||||
client.item_drop_location = None;
|
client.item_drop_location = None;
|
||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(Box::new(clients_in_area.into_iter()
|
Ok(Box::new(clients_in_area.into_iter()
|
||||||
.flat_map(move |c| {
|
.flat_map(move |c| {
|
||||||
std::iter::once((c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_meseta_pkt.clone())))))
|
std::iter::once((c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_meseta_pkt.clone())))))
|
||||||
@ -163,7 +163,7 @@ where
|
|||||||
let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item)?;
|
let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item)?;
|
||||||
client.item_drop_location = None;
|
client.item_drop_location = None;
|
||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(Box::new(clients_in_area.into_iter()
|
Ok(Box::new(clients_in_area.into_iter()
|
||||||
.map(move |c| {
|
.map(move |c| {
|
||||||
(c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_item_pkt.clone()))))
|
(c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_item_pkt.clone()))))
|
||||||
@ -171,7 +171,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if let Some(_tek) = client.tek {
|
else if let Some(_tek) = client.tek {
|
||||||
let neighbors = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let neighbors = client_location.get_client_neighbors(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let no_longer_has_item = no_longer_has_item.clone();
|
let no_longer_has_item = no_longer_has_item.clone();
|
||||||
Ok(Box::new(neighbors.into_iter()
|
Ok(Box::new(neighbors.into_iter()
|
||||||
.map(move |c| {
|
.map(move |c| {
|
||||||
@ -183,14 +183,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_player_position(id: ClientId,
|
pub async fn update_player_position(id: ClientId,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
rooms: &Rooms)
|
rooms: &Rooms)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
if let Ok(room_id) = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() }) {
|
if let Ok(room_id) = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() }) {
|
||||||
let room = rooms.get(room_id.0)
|
let room = rooms.get(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -250,7 +250,7 @@ pub fn update_player_position(id: ClientId,
|
|||||||
}
|
}
|
||||||
} else {}
|
} else {}
|
||||||
let m = message.clone();
|
let m = message.clone();
|
||||||
Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter()
|
Ok(Box::new(client_location.get_client_neighbors(id).await.unwrap().into_iter()
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::Message(m.clone()))
|
(client.client, SendShipPacket::Message(m.clone()))
|
||||||
})))
|
})))
|
||||||
@ -272,7 +272,7 @@ where
|
|||||||
take_meseta(item_state, &mut entity_gateway, &client.character.id, Meseta(charge.meseta)).await?;
|
take_meseta(item_state, &mut entity_gateway, &client.character.id, Meseta(charge.meseta)).await?;
|
||||||
|
|
||||||
let charge = charge.clone();
|
let charge = charge.clone();
|
||||||
Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter()
|
Ok(Box::new(client_location.get_client_neighbors(id).await.unwrap().into_iter()
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::Message(Message::new(GameMessage::ChargeAttack(charge.clone()))))
|
(client.client, SendShipPacket::Message(Message::new(GameMessage::ChargeAttack(charge.clone()))))
|
||||||
})))
|
})))
|
||||||
@ -308,7 +308,7 @@ where
|
|||||||
take_meseta(item_state, &mut entity_gateway, &client.character.id, Meseta(10)).await?;
|
take_meseta(item_state, &mut entity_gateway, &client.character.id, Meseta(10)).await?;
|
||||||
|
|
||||||
let pumc = pumc.clone();
|
let pumc = pumc.clone();
|
||||||
Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter()
|
Ok(Box::new(client_location.get_client_neighbors(id).await.unwrap().into_iter()
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::Message(Message::new(GameMessage::PlayerUsedMedicalCenter(pumc.clone()))))
|
(client.client, SendShipPacket::Message(Message::new(GameMessage::PlayerUsedMedicalCenter(pumc.clone()))))
|
||||||
})))
|
})))
|
||||||
@ -329,7 +329,7 @@ where
|
|||||||
feed_mag(item_state, &mut entity_gateway, &client.character, &ClientItemId(mag_feed.mag_id), &ClientItemId(mag_feed.item_id)).await?;
|
feed_mag(item_state, &mut entity_gateway, &client.character, &ClientItemId(mag_feed.mag_id), &ClientItemId(mag_feed.item_id)).await?;
|
||||||
|
|
||||||
let mag_feed = mag_feed.clone();
|
let mag_feed = mag_feed.clone();
|
||||||
Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter()
|
Ok(Box::new(client_location.get_client_neighbors(id).await.unwrap().into_iter()
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::Message(Message::new(GameMessage::PlayerFeedMag(mag_feed.clone()))))
|
(client.client, SendShipPacket::Message(Message::new(GameMessage::PlayerFeedMag(mag_feed.clone()))))
|
||||||
})))
|
})))
|
||||||
|
@ -36,8 +36,8 @@ fn parse_filename(filename_bytes: &[u8; 16]) -> Result<(u16, u16, QuestFileType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn send_quest_category_list(id: ClientId, rql: &RequestQuestList, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
pub async fn send_quest_category_list(id: ClientId, rql: &RequestQuestList, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
@ -46,8 +46,8 @@ pub fn send_quest_category_list(id: ClientId, rql: &RequestQuestList, client_loc
|
|||||||
Ok(Box::new(vec![(id, SendShipPacket::QuestCategoryList(qcl))].into_iter()))
|
Ok(Box::new(vec![(id, SendShipPacket::QuestCategoryList(qcl))].into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_quest_category(id: ClientId, menuselect: &MenuSelect, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
pub async fn select_quest_category(id: ClientId, menuselect: &MenuSelect, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
@ -63,8 +63,8 @@ pub fn select_quest_category(id: ClientId, menuselect: &MenuSelect, client_locat
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn quest_detail(id: ClientId, questdetailrequest: &QuestDetailRequest, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
pub async fn quest_detail(id: ClientId, questdetailrequest: &QuestDetailRequest, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
@ -82,9 +82,9 @@ pub fn quest_detail(id: ClientId, questdetailrequest: &QuestDetailRequest, clien
|
|||||||
Ok(Box::new(vec![(id, SendShipPacket::QuestDetail(qd))].into_iter()))
|
Ok(Box::new(vec![(id, SendShipPacket::QuestDetail(qd))].into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn player_chose_quest(id: ClientId, questmenuselect: &QuestMenuSelect, clients: &mut Clients, client_location: &ClientLocation, rooms: &mut Rooms)
|
pub async fn player_chose_quest(id: ClientId, questmenuselect: &QuestMenuSelect, clients: &mut Clients, client_location: &ClientLocation, rooms: &mut Rooms)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
@ -103,7 +103,7 @@ pub fn player_chose_quest(id: ClientId, questmenuselect: &QuestMenuSelect, clien
|
|||||||
let bin = quest::quest_header(questmenuselect, &quest.bin_blob, "bin");
|
let bin = quest::quest_header(questmenuselect, &quest.bin_blob, "bin");
|
||||||
let dat = quest::quest_header(questmenuselect, &quest.dat_blob, "dat");
|
let dat = quest::quest_header(questmenuselect, &quest.dat_blob, "dat");
|
||||||
|
|
||||||
let area_clients = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_clients = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
area_clients.iter().for_each(|c| {
|
area_clients.iter().for_each(|c| {
|
||||||
if let Some(client) = clients.get_mut(&c.client) {
|
if let Some(client) = clients.get_mut(&c.client) {
|
||||||
client.done_loading_quest = false;
|
client.done_loading_quest = false;
|
||||||
@ -114,8 +114,8 @@ pub fn player_chose_quest(id: ClientId, questmenuselect: &QuestMenuSelect, clien
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
pub async fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
@ -143,8 +143,8 @@ pub fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, c
|
|||||||
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quest_chunk_ack(id: ClientId, quest_chunk_ack: &QuestChunkAck, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
pub async fn quest_chunk_ack(id: ClientId, quest_chunk_ack: &QuestChunkAck, client_location: &ClientLocation, rooms: &mut Rooms) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room = rooms.get_mut(room_id.0)
|
let room = rooms.get_mut(room_id.0)
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut()
|
||||||
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or(ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
@ -176,11 +176,11 @@ pub fn quest_chunk_ack(id: ClientId, quest_chunk_ack: &QuestChunkAck, client_loc
|
|||||||
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn done_loading_quest(id: ClientId, clients: &mut Clients, client_location: &ClientLocation)
|
pub async fn done_loading_quest(id: ClientId, clients: &mut Clients, client_location: &ClientLocation)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
client.done_loading_quest = true;
|
client.done_loading_quest = true;
|
||||||
let area_clients = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_clients = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let all_loaded = area_clients.iter().all(|c| {
|
let all_loaded = area_clients.iter().all(|c| {
|
||||||
clients.get(&c.client)
|
clients.get(&c.client)
|
||||||
.map(|client| {
|
.map(|client| {
|
||||||
|
@ -8,14 +8,15 @@ use crate::ship::packet::builder;
|
|||||||
use crate::ship::room;
|
use crate::ship::room;
|
||||||
use crate::ship::items::state::ItemState;
|
use crate::ship::items::state::ItemState;
|
||||||
use std::convert::{TryFrom};
|
use std::convert::{TryFrom};
|
||||||
|
use futures::StreamExt;
|
||||||
|
|
||||||
pub fn create_room(id: ClientId,
|
pub async fn create_room(id: ClientId,
|
||||||
create_room: &CreateRoom,
|
create_room: &CreateRoom,
|
||||||
client_location: &mut ClientLocation,
|
client_location: &mut ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_state: &mut ItemState,
|
item_state: &mut ItemState,
|
||||||
rooms: &mut Rooms)
|
rooms: &mut Rooms)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
||||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp);
|
let level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp);
|
||||||
match room::Difficulty::try_from(create_room.difficulty)? {
|
match room::Difficulty::try_from(create_room.difficulty)? {
|
||||||
@ -37,22 +38,22 @@ pub fn create_room(id: ClientId,
|
|||||||
room::Difficulty::Normal => {},
|
room::Difficulty::Normal => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
let area = client_location.get_area(id).unwrap();
|
let area = client_location.get_area(id).await.unwrap();
|
||||||
let area_client = client_location.get_local_client(id).unwrap();
|
let area_client = client_location.get_local_client(id).await.unwrap();
|
||||||
let lobby_neighbors = client_location.get_client_neighbors(id).unwrap();
|
let lobby_neighbors = client_location.get_client_neighbors(id).await.unwrap();
|
||||||
let room_id = client_location.create_new_room(id).unwrap();
|
let room_id = client_location.create_new_room(id).await.unwrap();
|
||||||
let mut room = room::RoomState::from_create_room(create_room, client.character.section_id).unwrap();
|
let mut room = room::RoomState::from_create_room(create_room, client.character.section_id).unwrap();
|
||||||
room.bursting = true;
|
room.bursting = true;
|
||||||
|
|
||||||
item_state.add_character_to_room(room_id, &client.character, area_client);
|
item_state.add_character_to_room(room_id, &client.character, area_client);
|
||||||
|
|
||||||
let join_room = builder::room::join_room(id, clients, client_location, room_id, &room)?;
|
let join_room = builder::room::join_room(id, clients, client_location, room_id, &room).await?;
|
||||||
rooms[room_id.0] = Some(room);
|
rooms[room_id.0] = Some(room);
|
||||||
|
|
||||||
let mut result: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = Box::new(
|
let mut result: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = Box::new(
|
||||||
vec![(id, SendShipPacket::JoinRoom(join_room))].into_iter()
|
vec![(id, SendShipPacket::JoinRoom(join_room))].into_iter()
|
||||||
);
|
);
|
||||||
if let Ok(leader) = client_location.get_area_leader(area) {
|
if let Ok(leader) = client_location.get_area_leader(area).await {
|
||||||
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||||
result = Box::new(result.chain(lobby_neighbors
|
result = Box::new(result.chain(lobby_neighbors
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -64,24 +65,24 @@ pub fn create_room(id: ClientId,
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn room_name_request(id: ClientId,
|
pub async fn room_name_request(id: ClientId,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
rooms: &Rooms)
|
rooms: &Rooms)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let area = client_location.get_area(id).unwrap();
|
let area = client_location.get_area(id).await.unwrap();
|
||||||
match area {
|
match area {
|
||||||
RoomLobby::Room(room) => Box::new(vec![(id, SendShipPacket::RoomNameResponse(RoomNameResponse {name: rooms[room.0].as_ref().unwrap().name.clone()}))].into_iter()),
|
RoomLobby::Room(room) => Box::new(vec![(id, SendShipPacket::RoomNameResponse(RoomNameResponse {name: rooms[room.0].as_ref().unwrap().name.clone()}))].into_iter()),
|
||||||
RoomLobby::Lobby(_) => panic!()
|
RoomLobby::Lobby(_) => panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join_room(id: ClientId,
|
pub async fn join_room(id: ClientId,
|
||||||
pkt: &MenuSelect,
|
pkt: &MenuSelect,
|
||||||
client_location: &mut ClientLocation,
|
client_location: &mut ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_state: &mut ItemState,
|
item_state: &mut ItemState,
|
||||||
rooms: &mut Rooms)
|
rooms: &mut Rooms)
|
||||||
-> Result<Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send>, ShipError> {
|
-> Result<Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp);
|
let level = LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp);
|
||||||
// let room = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref().unwrap(); // clippy look what you made me do
|
// let room = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref().unwrap(); // clippy look what you made me do
|
||||||
@ -106,22 +107,22 @@ pub fn join_room(id: ClientId,
|
|||||||
_ => {},
|
_ => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
let original_area = client_location.get_area(id).unwrap();
|
let original_area = client_location.get_area(id).await.unwrap();
|
||||||
let original_neighbors = client_location.get_client_neighbors(id).unwrap();
|
let original_neighbors = client_location.get_client_neighbors(id).await.unwrap();
|
||||||
if room.bursting {
|
if room.bursting {
|
||||||
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))].into_iter()))
|
return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))].into_iter()))
|
||||||
}
|
}
|
||||||
let room_id = RoomId(pkt.item as usize);
|
let room_id = RoomId(pkt.item as usize);
|
||||||
let original_room_clients = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let original_room_clients = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
client_location.add_client_to_room(id, room_id).unwrap(); // TODO: show room full error or whatever
|
client_location.add_client_to_room(id, room_id).await.unwrap(); // TODO: show room full error or whatever
|
||||||
|
|
||||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
item_state.add_character_to_room(room_id, &client.character, area_client);
|
item_state.add_character_to_room(room_id, &client.character, area_client);
|
||||||
|
|
||||||
let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let leader = client_location.get_room_leader(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let join_room = builder::room::join_room(id, clients, client_location, room_id, room)?;
|
let join_room = builder::room::join_room(id, clients, client_location, room_id, room).await?;
|
||||||
let add_to = builder::room::add_to_room(id, client, &area_client, &leader, item_state, room_id)?;
|
let add_to = builder::room::add_to_room(id, client, &area_client, &leader, item_state, room_id)?;
|
||||||
|
|
||||||
let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap();
|
let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap();
|
||||||
@ -134,7 +135,7 @@ pub fn join_room(id: ClientId,
|
|||||||
.map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone())))
|
.map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone())))
|
||||||
));
|
));
|
||||||
|
|
||||||
if let Ok(leader) = client_location.get_area_leader(original_area) {
|
if let Ok(leader) = client_location.get_area_leader(original_area).await {
|
||||||
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()));
|
||||||
result = Box::new(result.chain(original_neighbors.into_iter()
|
result = Box::new(result.chain(original_neighbors.into_iter()
|
||||||
.map(move |c| (c.client, leave_lobby.clone()))))
|
.map(move |c| (c.client, leave_lobby.clone()))))
|
||||||
@ -146,11 +147,11 @@ pub fn join_room(id: ClientId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn done_bursting(id: ClientId,
|
pub async fn done_bursting(id: ClientId,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
rooms: &mut Rooms)
|
rooms: &mut Rooms)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let area = client_location.get_area(id).unwrap();
|
let area = client_location.get_area(id).await.unwrap();
|
||||||
let mut rare_monster_list: Option<Vec<u16>> = None;
|
let mut rare_monster_list: Option<Vec<u16>> = None;
|
||||||
if let RoomLobby::Room(room_id) = area {
|
if let RoomLobby::Room(room_id) = area {
|
||||||
if let Some(room) = rooms.get_mut(room_id.0).unwrap().as_mut() {
|
if let Some(room) = rooms.get_mut(room_id.0).unwrap().as_mut() {
|
||||||
@ -158,9 +159,9 @@ pub fn done_bursting(id: ClientId,
|
|||||||
rare_monster_list = Some(room.maps.get_rare_monster_list());
|
rare_monster_list = Some(room.maps.get_rare_monster_list());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let area_client = client_location.get_local_client(id).unwrap(); // TODO: unwrap
|
let area_client = client_location.get_local_client(id).await.unwrap(); // TODO: unwrap
|
||||||
let mut result: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = Box::new(
|
let mut result: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = Box::new(
|
||||||
client_location.get_client_neighbors(id).unwrap().into_iter() // TODO: unwrap
|
client_location.get_client_neighbors(id).await.unwrap().into_iter() // TODO: unwrap
|
||||||
.flat_map(move |client| {
|
.flat_map(move |client| {
|
||||||
vec![
|
vec![
|
||||||
(client.client, SendShipPacket::Message(Message::new(GameMessage::BurstDone(BurstDone {
|
(client.client, SendShipPacket::Message(Message::new(GameMessage::BurstDone(BurstDone {
|
||||||
@ -180,19 +181,19 @@ pub fn done_bursting(id: ClientId,
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_room_list(id: ClientId,
|
pub async fn request_room_list(id: ClientId,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
rooms: &Rooms)
|
rooms: &Rooms)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let active_room_list = rooms.iter()
|
let active_room_list = futures::stream::iter(rooms.iter())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, r)| {
|
.filter_map(|(i, r)| async move {
|
||||||
r.as_ref().map(|room| {
|
r.as_ref().map(|room| async move {
|
||||||
RoomList {
|
RoomList {
|
||||||
menu_id: ROOM_MENU_ID,
|
menu_id: ROOM_MENU_ID,
|
||||||
item_id: i as u32,
|
item_id: i as u32,
|
||||||
difficulty: room.get_difficulty_for_room_list(),
|
difficulty: room.get_difficulty_for_room_list(),
|
||||||
players: client_location.get_clients_in_room(RoomId(i)).unwrap().len() as u8,
|
players: client_location.get_clients_in_room(RoomId(i)).await.unwrap().len() as u8,
|
||||||
name: libpso::utf8_to_utf16_array!(room.name, 16),
|
name: libpso::utf8_to_utf16_array!(room.name, 16),
|
||||||
episode: room.get_episode_for_room_list(),
|
episode: room.get_episode_for_room_list(),
|
||||||
flags: room.get_flags_for_room_list(),
|
flags: room.get_flags_for_room_list(),
|
||||||
@ -211,17 +212,17 @@ pub fn request_room_list(id: ClientId,
|
|||||||
|
|
||||||
Box::new(vec![(id, SendShipPacket::RoomListResponse(RoomListResponse {
|
Box::new(vec![(id, SendShipPacket::RoomListResponse(RoomListResponse {
|
||||||
baseroom,
|
baseroom,
|
||||||
rooms: active_room_list.collect()
|
rooms: futures::future::join_all(active_room_list.collect::<Vec<_>>().await).await
|
||||||
}))].into_iter())
|
}))].into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cool_62(id: ClientId,
|
pub async fn cool_62(id: ClientId,
|
||||||
cool_62: &Like62ButCooler,
|
cool_62: &Like62ButCooler,
|
||||||
client_location: &ClientLocation)
|
client_location: &ClientLocation)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let target = cool_62.flag as u8;
|
let target = cool_62.flag as u8;
|
||||||
let cool_62 = cool_62.clone();
|
let cool_62 = cool_62.clone();
|
||||||
Box::new(client_location.get_client_neighbors(id).unwrap().into_iter()
|
Box::new(client_location.get_client_neighbors(id).await.unwrap().into_iter()
|
||||||
.filter(move |client| client.local_client.id() == target)
|
.filter(move |client| client.local_client.id() == target)
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::Like62ButCooler(cool_62.clone()))
|
(client.client, SendShipPacket::Like62ButCooler(cool_62.clone()))
|
||||||
|
@ -13,6 +13,7 @@ use crate::ship::packet::builder;
|
|||||||
use crate::ship::items::tasks::trade_items;
|
use crate::ship::items::tasks::trade_items;
|
||||||
use crate::ship::location::{AreaClient, RoomId};
|
use crate::ship::location::{AreaClient, RoomId};
|
||||||
use crate::entity::item::Meseta;
|
use crate::entity::item::Meseta;
|
||||||
|
use crate::ship::trade::ClientTradeState;
|
||||||
|
|
||||||
pub const MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFF01);
|
pub const MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFF01);
|
||||||
pub const OTHER_MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFFFF);
|
pub const OTHER_MESETA_ITEM_ID: ClientItemId = ClientItemId(0xFFFFFFFF);
|
||||||
@ -48,15 +49,47 @@ pub enum TradeError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn do_trade_action<F>(id: ClientId,
|
||||||
|
pkt: TradeRequest,
|
||||||
|
client_location: &ClientLocation,
|
||||||
|
target: u32,
|
||||||
|
this: &mut ClientTradeState,
|
||||||
|
other: &mut ClientTradeState,
|
||||||
|
action: F) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
|
where
|
||||||
|
F: Fn(&mut ClientTradeState, &mut ClientTradeState) -> Result<(), ShipError>,
|
||||||
|
{
|
||||||
|
Ok(match action(this, other) {
|
||||||
|
Ok(_) => {
|
||||||
|
Box::new(client_location.get_all_clients_by_client(id).await?.into_iter()
|
||||||
|
.filter(move |client| client.local_client.id() == target as u8)
|
||||||
|
.map(move |client| {
|
||||||
|
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(pkt.clone()))))
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// TODO: some sort of error logging?
|
||||||
|
Box::new(client_location.get_all_clients_by_client(id).await?.into_iter()
|
||||||
|
.filter(move |client| client.local_client.id() == target as u8)
|
||||||
|
.map(move |client| {
|
||||||
|
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
||||||
|
})
|
||||||
|
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {})))))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: remove target
|
// TODO: remove target
|
||||||
pub async fn trade_request(id: ClientId,
|
pub async fn trade_request(id: ClientId,
|
||||||
trade_request: &TradeRequest,
|
trade_request: &TradeRequest,
|
||||||
target: u32,
|
target: u32,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_state: &mut ItemState,
|
item_state: &mut ItemState,
|
||||||
trades: &mut TradeState)
|
trades: &mut TradeState)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
{
|
{
|
||||||
let trade_request = trade_request.clone(); // TODO: make this function take ownership of packet
|
let trade_request = trade_request.clone(); // TODO: make this function take ownership of packet
|
||||||
match trade_request.trade {
|
match trade_request.trade {
|
||||||
@ -66,7 +99,7 @@ pub async fn trade_request(id: ClientId,
|
|||||||
if trades.in_trade(&id) {
|
if trades.in_trade(&id) {
|
||||||
return Err(TradeError::ClientAlreadyInTrade.into())
|
return Err(TradeError::ClientAlreadyInTrade.into())
|
||||||
}
|
}
|
||||||
let trade_partner = client_location.get_client_neighbors(id)?
|
let trade_partner = client_location.get_client_neighbors(id).await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|ac| {
|
.find(|ac| {
|
||||||
ac.local_client.id() == target as u8 //trade_request.client
|
ac.local_client.id() == target as u8 //trade_request.client
|
||||||
@ -76,204 +109,155 @@ pub async fn trade_request(id: ClientId,
|
|||||||
return Err(TradeError::OtherAlreadyInTrade.into())
|
return Err(TradeError::OtherAlreadyInTrade.into())
|
||||||
}
|
}
|
||||||
trades.new_trade(&id, &trade_partner.client);
|
trades.new_trade(&id, &trade_partner.client);
|
||||||
Ok(Box::new(client_location.get_all_clients_by_client(id)?.into_iter()
|
Ok(Box::new(client_location.get_all_clients_by_client(id).await?.into_iter()
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
.filter(move |client| client.local_client.id() == target as u8)
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(trade_request.clone()))))
|
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(trade_request.clone()))))
|
||||||
})))
|
})))
|
||||||
},
|
},
|
||||||
TradeRequestInitializeCommand::Respond => {
|
TradeRequestInitializeCommand::Respond => {
|
||||||
Ok(trades
|
trades
|
||||||
.with(&id, |this, other| -> Option<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>> {
|
.with(&id, |mut this, mut other| {
|
||||||
if this.status == TradeStatus::ReceivedRequest && other.status == TradeStatus::SentRequest {
|
let trade_request = trade_request.clone();
|
||||||
this.status = TradeStatus::Trading;
|
async move {
|
||||||
other.status = TradeStatus::Trading;
|
do_trade_action(id, trade_request, client_location, target, &mut this, &mut other, |this, other| {
|
||||||
|
if this.status == TradeStatus::ReceivedRequest && other.status == TradeStatus::SentRequest {
|
||||||
let trade_request = trade_request.clone();
|
this.status = TradeStatus::Trading;
|
||||||
Some(Box::new(client_location.get_all_clients_by_client(id).ok()?.into_iter()
|
other.status = TradeStatus::Trading;
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
Ok(())
|
||||||
.map(move |client| {
|
}
|
||||||
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(trade_request.clone()))))
|
else {
|
||||||
})))
|
Err(TradeError::MismatchedStatus.into())
|
||||||
}
|
}
|
||||||
else {
|
}).await
|
||||||
None
|
}}).await?
|
||||||
}
|
|
||||||
})?
|
|
||||||
.unwrap_or_else(|| -> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
|
||||||
trades.remove_trade(&id);
|
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
|
||||||
.map(move |client| {
|
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
|
||||||
})
|
|
||||||
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {})))))
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TradeRequestCommand::AddItem(item_id, amount) => {
|
TradeRequestCommand::AddItem(item_id, amount) => {
|
||||||
Ok(trades
|
trades
|
||||||
.with(&id, |this, other| -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
.with(&id, |mut this, mut other| {
|
||||||
if this.status == TradeStatus::Trading && other.status == TradeStatus::Trading {
|
let trade_request = trade_request.clone();
|
||||||
let client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
|
async move {
|
||||||
let inventory = item_state.get_character_inventory(&client.character)?;
|
do_trade_action(id, trade_request, client_location, target, &mut this, &mut other, |this, other| {
|
||||||
if ClientItemId(item_id) == MESETA_ITEM_ID {
|
if this.status == TradeStatus::Trading && other.status == TradeStatus::Trading {
|
||||||
this.meseta += amount as usize;
|
let client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
|
||||||
}
|
let inventory = item_state.get_character_inventory(&client.character)?;
|
||||||
else {
|
if ClientItemId(item_id) == MESETA_ITEM_ID {
|
||||||
let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?;
|
this.meseta += amount as usize;
|
||||||
|
}
|
||||||
match &item.item {
|
else {
|
||||||
InventoryItemDetail::Individual(_) => {
|
let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?;
|
||||||
this.items.push(TradeItem::Individual(ClientItemId(item_id)));
|
|
||||||
},
|
match &item.item {
|
||||||
InventoryItemDetail::Stacked(stacked_item) => {
|
InventoryItemDetail::Individual(_) => {
|
||||||
if stacked_item.count() < amount as usize {
|
this.items.push(TradeItem::Individual(ClientItemId(item_id)));
|
||||||
return Err(TradeError::InvalidStackAmount(ClientItemId(item_id), amount as usize).into());
|
},
|
||||||
|
InventoryItemDetail::Stacked(stacked_item) => {
|
||||||
|
if stacked_item.count() < amount as usize {
|
||||||
|
return Err(TradeError::InvalidStackAmount(ClientItemId(item_id), amount as usize).into());
|
||||||
|
}
|
||||||
|
this.items.push(TradeItem::Stacked(ClientItemId(item_id), amount as usize));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
this.items.push(TradeItem::Stacked(ClientItemId(item_id), amount as usize));
|
}
|
||||||
},
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
Err(TradeError::MismatchedStatus.into())
|
||||||
let trade_request = trade_request.clone();
|
}
|
||||||
Ok(Box::new(client_location.get_all_clients_by_client(id)?.into_iter()
|
}).await
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
}}).await?
|
||||||
.map(move |client| {
|
|
||||||
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(trade_request.clone()))))
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Err(TradeError::MismatchedStatus.into())
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
.unwrap_or_else(|_err| {
|
|
||||||
trades.remove_trade(&id);
|
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
|
||||||
.map(move |client| {
|
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
|
||||||
})
|
|
||||||
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {})))))
|
|
||||||
}))
|
|
||||||
},
|
},
|
||||||
TradeRequestCommand::RemoveItem(item_id, amount) => {
|
TradeRequestCommand::RemoveItem(item_id, amount) => {
|
||||||
Ok(trades
|
trades
|
||||||
.with(&id, |this, other| -> Option<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>> {
|
.with(&id, |mut this, mut other| {
|
||||||
if this.status == TradeStatus::Trading && other.status == TradeStatus::Trading {
|
let trade_request = trade_request.clone();
|
||||||
let client = clients.get(&this.client())?; //.ok_or(ShipError::ClientNotFound(id)).ok()?;
|
async move {
|
||||||
let inventory = item_state.get_character_inventory(&client.character).ok()?;
|
do_trade_action(id, trade_request, client_location, target, &mut this, &mut other, |this, other| {
|
||||||
if ClientItemId(item_id) == MESETA_ITEM_ID {
|
if this.status == TradeStatus::Trading && other.status == TradeStatus::Trading {
|
||||||
this.meseta -= amount as usize;
|
let client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
|
||||||
}
|
let inventory = item_state.get_character_inventory(&client.character)?;
|
||||||
else {
|
if ClientItemId(item_id) == MESETA_ITEM_ID {
|
||||||
let item = inventory.get_by_client_id(&ClientItemId(item_id))?;
|
this.meseta -= amount as usize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?;
|
||||||
|
|
||||||
match &item.item {
|
match &item.item {
|
||||||
InventoryItemDetail::Individual(_) => {
|
InventoryItemDetail::Individual(_) => {
|
||||||
this.items.retain(|item| {
|
this.items.retain(|item| {
|
||||||
item.item_id() != ClientItemId(item_id)
|
item.item_id() != ClientItemId(item_id)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
InventoryItemDetail::Stacked(_stacked_item) => {
|
InventoryItemDetail::Stacked(_stacked_item) => {
|
||||||
let trade_item_index = this.items.iter()
|
let trade_item_index = this.items.iter()
|
||||||
.position(|item| {
|
.position(|item| {
|
||||||
item.item_id() == ClientItemId(item_id)
|
item.item_id() == ClientItemId(item_id)
|
||||||
})?;
|
})
|
||||||
|
.ok_or(TradeError::InvalidItemId(ClientItemId(item_id)))?;
|
||||||
|
|
||||||
match this.items[trade_item_index].stacked()?.1.cmp(&(amount as usize)) {
|
match this.items[trade_item_index].stacked().ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1.cmp(&(amount as usize)) {
|
||||||
std::cmp::Ordering::Greater => {
|
std::cmp::Ordering::Greater => {
|
||||||
*this.items[trade_item_index].stacked_mut()?.1 -= amount as usize;
|
*this.items[trade_item_index].stacked_mut().ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1 -= amount as usize;
|
||||||
|
},
|
||||||
|
std::cmp::Ordering::Equal => {
|
||||||
|
this.items.remove(trade_item_index);
|
||||||
|
},
|
||||||
|
std::cmp::Ordering::Less => {
|
||||||
|
return Err(TradeError::SketchyTrade.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
std::cmp::Ordering::Equal => {
|
|
||||||
this.items.remove(trade_item_index);
|
|
||||||
},
|
|
||||||
std::cmp::Ordering::Less => {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
let trade_request = trade_request.clone();
|
Err(TradeError::MismatchedStatus.into())
|
||||||
Some(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
}
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
|
||||||
.map(move |client| {
|
}).await
|
||||||
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(trade_request.clone()))))
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
else {
|
}).await?
|
||||||
None
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
trades.remove_trade(&id);
|
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
|
||||||
.map(move |client| {
|
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
|
||||||
})
|
|
||||||
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {})))))
|
|
||||||
}))
|
|
||||||
},
|
},
|
||||||
TradeRequestCommand::Confirm => {
|
TradeRequestCommand::Confirm => {
|
||||||
Ok(trades
|
trades
|
||||||
.with(&id, |this, other| -> Option<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>> {
|
.with(&id, |mut this, mut other| {
|
||||||
if status_is(&this.status, &[TradeStatus::Trading]) && status_is(&other.status, &[TradeStatus::Trading, TradeStatus::Confirmed]) {
|
let trade_request = trade_request.clone();
|
||||||
this.status = TradeStatus::Confirmed;
|
async move {
|
||||||
|
do_trade_action(id, trade_request, client_location, target, &mut this, &mut other, |this, other| {
|
||||||
let trade_request = trade_request.clone();
|
if status_is(&this.status, &[TradeStatus::Trading]) && status_is(&other.status, &[TradeStatus::Trading, TradeStatus::Confirmed]) {
|
||||||
Some(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
this.status = TradeStatus::Confirmed;
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
Ok(())
|
||||||
.map(move |client| {
|
}
|
||||||
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(trade_request.clone()))))
|
else {
|
||||||
})))
|
Err(TradeError::MismatchedStatus.into())
|
||||||
|
}
|
||||||
|
}).await
|
||||||
}
|
}
|
||||||
else {
|
}).await?
|
||||||
None
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
trades.remove_trade(&id);
|
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
|
||||||
.map(move |client| {
|
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
|
||||||
})
|
|
||||||
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {})))))
|
|
||||||
}))
|
|
||||||
},
|
},
|
||||||
TradeRequestCommand::FinalConfirm => {
|
TradeRequestCommand::FinalConfirm => {
|
||||||
Ok(trades
|
trades
|
||||||
.with(&id, |this, other| -> Option<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>> {
|
.with(&id, |mut this, mut other| {
|
||||||
if this.status == TradeStatus::Confirmed && (other.status == TradeStatus::Confirmed || other.status == TradeStatus::FinalConfirm) {
|
let trade_request = trade_request.clone();
|
||||||
this.status = TradeStatus::FinalConfirm;
|
async move {
|
||||||
|
do_trade_action(id, trade_request, client_location, target, &mut this, &mut other, |this, other| {
|
||||||
let trade_request = trade_request.clone();
|
if this.status == TradeStatus::Confirmed && (other.status == TradeStatus::Confirmed || other.status == TradeStatus::FinalConfirm) {
|
||||||
Some(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
this.status = TradeStatus::FinalConfirm;
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
Ok(())
|
||||||
.map(move |client| {
|
}
|
||||||
(client.client, SendShipPacket::DirectMessage(DirectMessage::new(target, GameMessage::TradeRequest(trade_request.clone()))))
|
else {
|
||||||
})))
|
Err(TradeError::MismatchedStatus.into())
|
||||||
|
}
|
||||||
|
}).await
|
||||||
}
|
}
|
||||||
else {
|
}).await?
|
||||||
None
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
trades.remove_trade(&id);
|
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
|
||||||
.map(move |client| {
|
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
|
||||||
})
|
|
||||||
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {})))))
|
|
||||||
}))
|
|
||||||
},
|
},
|
||||||
TradeRequestCommand::Cancel => {
|
TradeRequestCommand::Cancel => {
|
||||||
trades.remove_trade(&id);
|
trades.remove_trade(&id);
|
||||||
Ok(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
Ok(Box::new(client_location.get_all_clients_by_client(id).await?.into_iter()
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
.filter(move |client| client.local_client.id() == target as u8)
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
||||||
@ -298,10 +282,10 @@ pub async fn inner_items_to_trade(id: ClientId,
|
|||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_state: &mut ItemState,
|
item_state: &mut ItemState,
|
||||||
trades: &mut TradeState)
|
trades: &mut TradeState)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
{
|
{
|
||||||
Ok(trades
|
let pkts: Result<Box<dyn Iterator<Item=_> + Send>, ShipError> = trades
|
||||||
.with(&id, |this, other| -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
.with(&id, |mut this, other| async move {
|
||||||
if status_is_not(&this.status, &[TradeStatus::FinalConfirm]) || status_is_not(&other.status, &[TradeStatus::FinalConfirm, TradeStatus::ItemsChecked]) {
|
if status_is_not(&this.status, &[TradeStatus::FinalConfirm]) || status_is_not(&other.status, &[TradeStatus::FinalConfirm, TradeStatus::ItemsChecked]) {
|
||||||
return Err(TradeError::MismatchedStatus.into())
|
return Err(TradeError::MismatchedStatus.into())
|
||||||
}
|
}
|
||||||
@ -379,29 +363,32 @@ pub async fn inner_items_to_trade(id: ClientId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, anyhow::Error>>()?;
|
.collect::<Result<Vec<_>, ShipError>>()?;
|
||||||
|
|
||||||
this.status = TradeStatus::ItemsChecked;
|
this.status = TradeStatus::ItemsChecked;
|
||||||
if this.status == TradeStatus::ItemsChecked && other.status == TradeStatus::ItemsChecked {
|
if this.status == TradeStatus::ItemsChecked && other.status == TradeStatus::ItemsChecked {
|
||||||
Ok(Box::new(vec![
|
Ok(Box::new(vec![
|
||||||
(this.client(), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {})),
|
(this.client(), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {})),
|
||||||
(other.client(), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {})),
|
(other.client(), SendShipPacket::AcknowledgeTrade(AcknowledgeTrade {})),
|
||||||
].into_iter()))
|
].into_iter()) as Box<dyn Iterator<Item=_> + Send>)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Ok(Box::new(None.into_iter()))
|
Ok(Box::new(Vec::new().into_iter()) as Box<dyn Iterator<Item=_> + Send>)
|
||||||
}
|
}
|
||||||
})?
|
}).await?;
|
||||||
.unwrap_or_else(|err| {
|
match pkts {
|
||||||
log::warn!("trade error: {:?}", err);
|
Ok(pkts) => Ok(pkts),
|
||||||
let (_this, other) = trades.remove_trade(&id);
|
Err(err) => {
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
log::warn!("trade error: {:?}", err);
|
||||||
.filter(move |client| other.as_ref().map(|other| client.client == other.client() ).unwrap_or_else(|| false))
|
let (_this, other) = trades.remove_trade(&id);
|
||||||
.map(move |client| {
|
Ok(Box::new(client_location.get_all_clients_by_client(id).await?.into_iter()
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
.filter(move |client| other.as_ref().map(|other| client.client == other.client() ).unwrap_or_else(|| false))
|
||||||
})
|
.map(move |client| {
|
||||||
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {})))))
|
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
||||||
}))
|
})
|
||||||
|
.chain(std::iter::once((id, SendShipPacket::CancelTrade(CancelTrade {}))))))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn items_to_trade(id: ClientId,
|
pub async fn items_to_trade(id: ClientId,
|
||||||
@ -418,7 +405,7 @@ pub async fn items_to_trade(id: ClientId,
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::warn!("atrade error: {:?}", err);
|
log::warn!("atrade error: {:?}", err);
|
||||||
let (_this, other) = trades.remove_trade(&id);
|
let (_this, other) = trades.remove_trade(&id);
|
||||||
Ok(Box::new(client_location.get_all_clients_by_client(id)?.into_iter()
|
Ok(Box::new(client_location.get_all_clients_by_client(id).await?.into_iter()
|
||||||
.filter(move |client| other.as_ref().map(|other| client.client == other.client()).unwrap_or_else(|| false))
|
.filter(move |client| other.as_ref().map(|other| client.client == other.client()).unwrap_or_else(|| false))
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
||||||
@ -428,13 +415,13 @@ pub async fn items_to_trade(id: ClientId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn trade_confirmed<EG>(id: ClientId,
|
pub async fn trade_confirmed_inner<EG>(id: ClientId,
|
||||||
mut entity_gateway: EG,
|
mut entity_gateway: EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_state: &mut ItemState,
|
item_state: &mut ItemState,
|
||||||
trades: &mut TradeState)
|
trades: &mut TradeState)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
@ -445,123 +432,136 @@ where
|
|||||||
(AreaClient, &'a crate::ship::ship::ClientState, crate::ship::trade::ClientTradeState)),
|
(AreaClient, &'a crate::ship::ship::ClientState, crate::ship::trade::ClientTradeState)),
|
||||||
}
|
}
|
||||||
|
|
||||||
let trade_instructions = trades
|
let trade = trades
|
||||||
.with(&id, |this, other| -> Result<_, anyhow::Error> {
|
.with(&id, |mut this, other| {
|
||||||
if status_is_not(&this.status, &[TradeStatus::ItemsChecked]) || status_is_not(&other.status, &[TradeStatus::ItemsChecked, TradeStatus::TradeComplete]) {
|
async move {
|
||||||
return Err(TradeError::MismatchedStatus.into())
|
if status_is_not(&this.status, &[TradeStatus::ItemsChecked]) || status_is_not(&other.status, &[TradeStatus::ItemsChecked, TradeStatus::TradeComplete]) {
|
||||||
|
return Err(ShipError::TradeError(TradeError::MismatchedStatus))
|
||||||
|
}
|
||||||
|
this.status = TradeStatus::TradeComplete;
|
||||||
|
|
||||||
|
if this.status == TradeStatus::TradeComplete && other.status == TradeStatus::TradeComplete {
|
||||||
|
let this_client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
|
||||||
|
let other_client = clients.get(&other.client()).ok_or_else(|| ShipError::ClientNotFound(other.client()))?;
|
||||||
|
let this_local_client = client_location.get_local_client(this.client()).await?;
|
||||||
|
let other_local_client = client_location.get_local_client(other.client()).await?;
|
||||||
|
let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
|
Ok(TradeReady::BothPlayers(room_id,
|
||||||
|
(this_local_client, this_client, this.clone()),
|
||||||
|
(other_local_client, other_client, other.clone())))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Ok(TradeReady::OnePlayer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.status = TradeStatus::TradeComplete;
|
}).await??;
|
||||||
|
|
||||||
if this.status == TradeStatus::TradeComplete && other.status == TradeStatus::TradeComplete {
|
match trade {
|
||||||
let this_client = clients.get(&this.client()).ok_or_else(|| ShipError::ClientNotFound(this.client()))?;
|
TradeReady::OnePlayer => {
|
||||||
let other_client = clients.get(&other.client()).ok_or_else(|| ShipError::ClientNotFound(other.client()))?;
|
Ok(Box::new(None.into_iter()) as Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>)
|
||||||
let this_local_client = client_location.get_local_client(this.client())?;
|
},
|
||||||
let other_local_client = client_location.get_local_client(other.client())?;
|
TradeReady::BothPlayers(_room_id, (this_local_client, this_client, this), (other_local_client, other_client, other)) => {
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let remove_item_packets = this.items
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(move |item| {
|
||||||
|
(this_local_client, item)
|
||||||
|
})
|
||||||
|
.chain(other.items
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(move |item| {
|
||||||
|
(other_local_client, item)
|
||||||
|
}))
|
||||||
|
.map(|(client, item)| {
|
||||||
|
GameMessage::PlayerNoLongerHasItem(builder::message::player_no_longer_has_item(client, item.item_id(), item.amount() as u32))
|
||||||
|
});
|
||||||
|
|
||||||
Ok(TradeReady::BothPlayers(room_id,
|
let (this_new_items, other_new_items) = trade_items(item_state,
|
||||||
(this_local_client, this_client, this.clone()),
|
&mut entity_gateway,
|
||||||
(other_local_client, other_client, other.clone())))
|
(&this_local_client, &this_client.character, &this.items, Meseta(this.meseta as u32)),
|
||||||
}
|
(&other_local_client, &other_client.character, &other.items, Meseta(other.meseta as u32))).await?;
|
||||||
else {
|
|
||||||
Ok(TradeReady::OnePlayer)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: this match needs to handle errors better
|
let create_item_packets = this_new_items
|
||||||
match trade_instructions {
|
.into_iter()
|
||||||
Ok(Ok(trade)) => {
|
.map(move |item| {
|
||||||
match trade {
|
(this_local_client, item)
|
||||||
TradeReady::OnePlayer => {
|
})
|
||||||
Ok(Box::new(None.into_iter()) as Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>)
|
.chain(other_new_items
|
||||||
},
|
.into_iter()
|
||||||
TradeReady::BothPlayers(_room_id, (this_local_client, this_client, this), (other_local_client, other_client, other)) => {
|
.map(move |item| {
|
||||||
let remove_item_packets = this.items
|
(other_local_client, item)
|
||||||
|
}))
|
||||||
|
.map(|(client, item)| {
|
||||||
|
match item.item {
|
||||||
|
InventoryItemDetail::Individual(individual_item) => {
|
||||||
|
GameMessage::CreateItem(builder::message::create_individual_item(client, item.item_id, &individual_item).unwrap())
|
||||||
|
},
|
||||||
|
InventoryItemDetail::Stacked(stacked_item) => {
|
||||||
|
GameMessage::CreateItem(builder::message::create_stacked_item(client, item.item_id, &stacked_item.tool, stacked_item.count()).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let meseta_packets = vec![(this_local_client, other_local_client, this.meseta), (other_local_client, this_local_client, other.meseta)]
|
||||||
|
.into_iter()
|
||||||
|
.filter(|(_, _, meseta)| *meseta != 0)
|
||||||
|
.flat_map(|(this, other, meseta)| {
|
||||||
|
[
|
||||||
|
GameMessage::PlayerNoLongerHasItem(builder::message::player_no_longer_has_item(this, MESETA_ITEM_ID, meseta as u32)),
|
||||||
|
GameMessage::CreateItem(builder::message::create_meseta(other, meseta)),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
let clients_in_room = client_location.get_all_clients_by_client(id).await?;
|
||||||
|
let traded_item_packets = remove_item_packets
|
||||||
|
.chain(create_item_packets)
|
||||||
|
.chain(meseta_packets)
|
||||||
|
.flat_map(move |packet| {
|
||||||
|
clients_in_room
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |item| {
|
.filter_map(move |client| {
|
||||||
(this_local_client, item)
|
match packet {
|
||||||
})
|
GameMessage::PlayerNoLongerHasItem(ref no_longer) => {
|
||||||
.chain(other.items
|
if client.local_client == no_longer.client {
|
||||||
.clone()
|
None
|
||||||
.into_iter()
|
|
||||||
.map(move |item| {
|
|
||||||
(other_local_client, item)
|
|
||||||
}))
|
|
||||||
.map(|(client, item)| {
|
|
||||||
GameMessage::PlayerNoLongerHasItem(builder::message::player_no_longer_has_item(client, item.item_id(), item.amount() as u32))
|
|
||||||
});
|
|
||||||
|
|
||||||
let (this_new_items, other_new_items) = trade_items(item_state,
|
|
||||||
&mut entity_gateway,
|
|
||||||
(&this_local_client, &this_client.character, &this.items, Meseta(this.meseta as u32)),
|
|
||||||
(&other_local_client, &other_client.character, &other.items, Meseta(other.meseta as u32))).await?;
|
|
||||||
|
|
||||||
let create_item_packets = this_new_items
|
|
||||||
.into_iter()
|
|
||||||
.map(move |item| {
|
|
||||||
(this_local_client, item)
|
|
||||||
})
|
|
||||||
.chain(other_new_items
|
|
||||||
.into_iter()
|
|
||||||
.map(move |item| {
|
|
||||||
(other_local_client, item)
|
|
||||||
}))
|
|
||||||
.map(|(client, item)| {
|
|
||||||
match item.item {
|
|
||||||
InventoryItemDetail::Individual(individual_item) => {
|
|
||||||
GameMessage::CreateItem(builder::message::create_individual_item(client, item.item_id, &individual_item).unwrap())
|
|
||||||
},
|
|
||||||
InventoryItemDetail::Stacked(stacked_item) => {
|
|
||||||
GameMessage::CreateItem(builder::message::create_stacked_item(client, item.item_id, &stacked_item.tool, stacked_item.count()).unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let meseta_packets = vec![(this_local_client, other_local_client, this.meseta), (other_local_client, this_local_client, other.meseta)]
|
|
||||||
.into_iter()
|
|
||||||
.filter(|(_, _, meseta)| *meseta != 0)
|
|
||||||
.flat_map(|(this, other, meseta)| {
|
|
||||||
[
|
|
||||||
GameMessage::PlayerNoLongerHasItem(builder::message::player_no_longer_has_item(this, MESETA_ITEM_ID, meseta as u32)),
|
|
||||||
GameMessage::CreateItem(builder::message::create_meseta(other, meseta)),
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
let clients_in_room = client_location.get_all_clients_by_client(id)?;
|
|
||||||
let traded_item_packets = remove_item_packets
|
|
||||||
.chain(create_item_packets)
|
|
||||||
.chain(meseta_packets)
|
|
||||||
.flat_map(move |packet| {
|
|
||||||
clients_in_room
|
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(move |client| {
|
|
||||||
match packet {
|
|
||||||
GameMessage::PlayerNoLongerHasItem(ref no_longer) => {
|
|
||||||
if client.local_client == no_longer.client {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Some((client.client, SendShipPacket::Message(Message::new(packet.clone()))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Some((client.client, SendShipPacket::Message(Message::new(packet.clone()))))
|
|
||||||
}
|
}
|
||||||
})
|
else {
|
||||||
});
|
Some((client.client, SendShipPacket::Message(Message::new(packet.clone()))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Some((client.client, SendShipPacket::Message(Message::new(packet.clone()))))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
let close_trade = vec![
|
let close_trade = vec![
|
||||||
(this.client(), SendShipPacket::TradeSuccessful(TradeSuccessful::default())),
|
(this.client(), SendShipPacket::TradeSuccessful(TradeSuccessful::default())),
|
||||||
(other.client(), SendShipPacket::TradeSuccessful(TradeSuccessful::default()))
|
(other.client(), SendShipPacket::TradeSuccessful(TradeSuccessful::default()))
|
||||||
].into_iter();
|
].into_iter();
|
||||||
Ok(Box::new(traded_item_packets.chain(close_trade)))
|
Ok(Box::new(traded_item_packets.chain(close_trade)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {
|
|
||||||
|
|
||||||
|
pub async fn trade_confirmed<EG>(id: ClientId,
|
||||||
|
entity_gateway: EG,
|
||||||
|
client_location: &ClientLocation,
|
||||||
|
clients: &mut Clients,
|
||||||
|
item_state: &mut ItemState,
|
||||||
|
trades: &mut TradeState)
|
||||||
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
|
where
|
||||||
|
EG: EntityGateway
|
||||||
|
{
|
||||||
|
match trade_confirmed_inner(id, entity_gateway, client_location, clients, item_state, trades).await {
|
||||||
|
Ok(result) => Ok(result),
|
||||||
|
Err(_err) => {
|
||||||
let (_this, other) = trades.remove_trade(&id);
|
let (_this, other) = trades.remove_trade(&id);
|
||||||
Ok(Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
Ok(Box::new(client_location.get_all_clients_by_client(id).await?.into_iter()
|
||||||
.filter(move |client| other.as_ref().map(|other| client.client == other.client()).unwrap_or_else(|| false))
|
.filter(move |client| other.as_ref().map(|other| client.client == other.client()).unwrap_or_else(|| false))
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
(client.client, SendShipPacket::CancelTrade(CancelTrade {}))
|
||||||
|
@ -190,7 +190,7 @@ impl RecvServerPacket for RecvShipPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum SendShipPacket {
|
pub enum SendShipPacket {
|
||||||
ShipWelcome(ShipWelcome),
|
ShipWelcome(ShipWelcome),
|
||||||
LoginResponse(LoginResponse),
|
LoginResponse(LoginResponse),
|
||||||
@ -514,7 +514,7 @@ impl<EG: EntityGateway + Clone> ShipServerState<EG> {
|
|||||||
},
|
},
|
||||||
GameMessage::DropCoordinates(drop_coordinates) => {
|
GameMessage::DropCoordinates(drop_coordinates) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &mut self.clients, &block.rooms)?
|
handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &mut self.clients, &block.rooms).await?
|
||||||
},
|
},
|
||||||
GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
|
GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
@ -525,7 +525,7 @@ impl<EG: EntityGateway + Clone> ShipServerState<EG> {
|
|||||||
GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) |
|
GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) |
|
||||||
GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => {
|
GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::message::update_player_position(id, msg, &mut self.clients, &block.client_location, &block.rooms)?
|
handler::message::update_player_position(id, msg, &mut self.clients, &block.client_location, &block.rooms).await?
|
||||||
},
|
},
|
||||||
GameMessage::ChargeAttack(charge_attack) => {
|
GameMessage::ChargeAttack(charge_attack) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
@ -558,7 +558,7 @@ impl<EG: EntityGateway + Clone> ShipServerState<EG> {
|
|||||||
_ => {
|
_ => {
|
||||||
let cmsg = msg.clone();
|
let cmsg = msg.clone();
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
Box::new(block.client_location.get_client_neighbors(id).unwrap().into_iter()
|
Box::new(block.client_location.get_client_neighbors(id).await.unwrap().into_iter()
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::Message(cmsg.clone()))
|
(client.client, SendShipPacket::Message(cmsg.clone()))
|
||||||
}))
|
}))
|
||||||
@ -571,7 +571,7 @@ impl<EG: EntityGateway + Clone> ShipServerState<EG> {
|
|||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
Ok(match &msg.msg {
|
Ok(match &msg.msg {
|
||||||
GameMessage::GuildcardSend(guildcard_send) => {
|
GameMessage::GuildcardSend(guildcard_send) => {
|
||||||
handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients)
|
handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients).await
|
||||||
},
|
},
|
||||||
GameMessage::RequestItem(request_item) => {
|
GameMessage::RequestItem(request_item) => {
|
||||||
handler::direct_message::request_item(id, request_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await?
|
handler::direct_message::request_item(id, request_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await?
|
||||||
@ -605,7 +605,7 @@ impl<EG: EntityGateway + Clone> ShipServerState<EG> {
|
|||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let cmsg = msg.clone();
|
let cmsg = msg.clone();
|
||||||
Box::new(block.client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
Box::new(block.client_location.get_all_clients_by_client(id).await.unwrap().into_iter()
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
.filter(move |client| client.local_client.id() == target as u8)
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
(client.client, SendShipPacket::DirectMessage(cmsg.clone()))
|
(client.client, SendShipPacket::DirectMessage(cmsg.clone()))
|
||||||
@ -650,7 +650,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
|
RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
match questdetailrequest.menu {
|
match questdetailrequest.menu {
|
||||||
QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &block.client_location, &mut block.rooms)?,
|
QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &block.client_location, &mut block.rooms).await?,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -658,27 +658,27 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
match menuselect.menu {
|
match menuselect.menu {
|
||||||
SHIP_MENU_ID => {
|
SHIP_MENU_ID => {
|
||||||
let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).into_iter().into_iter().flatten();
|
let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).await.into_iter().into_iter().flatten();
|
||||||
let select_ship = handler::ship::selected_ship(id, menuselect, &self.ship_list)?;
|
let select_ship = handler::ship::selected_ship(id, menuselect, &self.ship_list)?;
|
||||||
Box::new(leave_lobby.chain(select_ship))
|
Box::new(leave_lobby.chain(select_ship))
|
||||||
}
|
}
|
||||||
BLOCK_MENU_ID => {
|
BLOCK_MENU_ID => {
|
||||||
let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).into_iter().into_iter().flatten();
|
let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).await.into_iter().into_iter().flatten();
|
||||||
let select_block = handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.item_state)?.into_iter();
|
let select_block = handler::lobby::block_selected(id, menuselect, &mut self.clients, &self.item_state)?.into_iter();
|
||||||
Box::new(leave_lobby.chain(select_block))
|
Box::new(leave_lobby.chain(select_block))
|
||||||
}
|
}
|
||||||
ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms)?,
|
ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms).await?,
|
||||||
QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &mut block.rooms)?,
|
QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &mut block.rooms).await?,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RecvShipPacket::QuestMenuSelect(questmenuselect) => {
|
RecvShipPacket::QuestMenuSelect(questmenuselect) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::quest::player_chose_quest(id, questmenuselect, &mut self.clients, &block.client_location, &mut block.rooms)?
|
handler::quest::player_chose_quest(id, questmenuselect, &mut self.clients, &block.client_location, &mut block.rooms).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::MenuDetail(menudetail) => {
|
RecvShipPacket::MenuDetail(menudetail) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
Box::new(handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients, &mut block.rooms)?.into_iter())
|
Box::new(handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients, &mut block.rooms).await?.into_iter())
|
||||||
},
|
},
|
||||||
RecvShipPacket::RoomPasswordReq(room_password_req) => {
|
RecvShipPacket::RoomPasswordReq(room_password_req) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
@ -689,7 +689,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
menu: room_password_req.menu,
|
menu: room_password_req.menu,
|
||||||
item: room_password_req.item,
|
item: room_password_req.item,
|
||||||
};
|
};
|
||||||
handler::room::join_room(id, &menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms)?
|
handler::room::join_room(id, &menuselect, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms).await?
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter())
|
Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter())
|
||||||
@ -697,7 +697,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
},
|
},
|
||||||
RecvShipPacket::CharData(chardata) => {
|
RecvShipPacket::CharData(chardata) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_state)?.into_iter())
|
Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_state).await?.into_iter())
|
||||||
},
|
},
|
||||||
RecvShipPacket::Message(msg) => {
|
RecvShipPacket::Message(msg) => {
|
||||||
self.message(id, msg).await?
|
self.message(id, msg).await?
|
||||||
@ -707,33 +707,33 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
},
|
},
|
||||||
RecvShipPacket::PlayerChat(msg) => {
|
RecvShipPacket::PlayerChat(msg) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
Box::new(handler::communication::player_chat(id, msg, &block.client_location, &self.clients)?)
|
Box::new(handler::communication::player_chat(id, msg, &block.client_location, &self.clients).await?)
|
||||||
},
|
},
|
||||||
RecvShipPacket::CreateRoom(create_room) => {
|
RecvShipPacket::CreateRoom(create_room) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms)?
|
handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::RoomNameRequest(_req) => {
|
RecvShipPacket::RoomNameRequest(_req) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::room::room_name_request(id, &block.client_location, &block.rooms)
|
handler::room::room_name_request(id, &block.client_location, &block.rooms).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::UpdateConfig(pkt) => {
|
RecvShipPacket::UpdateConfig(pkt) => {
|
||||||
handler::settings::update_config(id, pkt, &mut self.clients, self.entity_gateway.clone()).await
|
handler::settings::update_config(id, pkt, &mut self.clients, self.entity_gateway.clone()).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::ViewInfoboardRequest(_pkt) => {
|
RecvShipPacket::ViewInfoboardRequest(_pkt) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::communication::request_infoboard(id, &block.client_location, &self.clients)
|
handler::communication::request_infoboard(id, &block.client_location, &self.clients).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::WriteInfoboard(pkt) => {
|
RecvShipPacket::WriteInfoboard(pkt) => {
|
||||||
handler::communication::write_infoboard(id, pkt, &mut self.clients, self.entity_gateway.clone()).await
|
handler::communication::write_infoboard(id, pkt, &mut self.clients, self.entity_gateway.clone()).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::RoomListRequest(_req) => {
|
RecvShipPacket::RoomListRequest(_req) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::room::request_room_list(id, &block.client_location, &block.rooms)
|
handler::room::request_room_list(id, &block.client_location, &block.rooms).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::Like62ButCooler(cool62) => {
|
RecvShipPacket::Like62ButCooler(cool62) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::room::cool_62(id, cool62, &block.client_location)
|
handler::room::cool_62(id, cool62, &block.client_location).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::ClientCharacterData(_) => {
|
RecvShipPacket::ClientCharacterData(_) => {
|
||||||
// TOOD: validate this in some way?
|
// TOOD: validate this in some way?
|
||||||
@ -741,11 +741,11 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
},
|
},
|
||||||
RecvShipPacket::DoneBursting(_) => {
|
RecvShipPacket::DoneBursting(_) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::room::done_bursting(id, &block.client_location, &mut block.rooms)
|
handler::room::done_bursting(id, &block.client_location, &mut block.rooms).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::DoneBursting2(_) => {
|
RecvShipPacket::DoneBursting2(_) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::room::done_bursting(id, &block.client_location, &mut block.rooms)
|
handler::room::done_bursting(id, &block.client_location, &mut block.rooms).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::LobbySelect(pkt) => {
|
RecvShipPacket::LobbySelect(pkt) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
@ -753,19 +753,19 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
},
|
},
|
||||||
RecvShipPacket::RequestQuestList(rql) => {
|
RecvShipPacket::RequestQuestList(rql) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::quest::send_quest_category_list(id, rql, &block.client_location, &mut block.rooms)?
|
handler::quest::send_quest_category_list(id, rql, &block.client_location, &mut block.rooms).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::QuestFileRequest(quest_file_request) => {
|
RecvShipPacket::QuestFileRequest(quest_file_request) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::quest::quest_file_request(id, quest_file_request, &block.client_location, &mut block.rooms)?
|
handler::quest::quest_file_request(id, quest_file_request, &block.client_location, &mut block.rooms).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::QuestChunkAck(quest_chunk_ack) => {
|
RecvShipPacket::QuestChunkAck(quest_chunk_ack) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::quest::quest_chunk_ack(id, quest_chunk_ack, &block.client_location, &mut block.rooms)?
|
handler::quest::quest_chunk_ack(id, quest_chunk_ack, &block.client_location, &mut block.rooms).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::DoneLoadingQuest(_) => {
|
RecvShipPacket::DoneLoadingQuest(_) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::quest::done_loading_quest(id, &mut self.clients, &block.client_location)?
|
handler::quest::done_loading_quest(id, &mut self.clients, &block.client_location).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::FullCharacterData(_full_character_data) => {
|
RecvShipPacket::FullCharacterData(_full_character_data) => {
|
||||||
Box::new(None.into_iter())
|
Box::new(None.into_iter())
|
||||||
@ -799,19 +799,19 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> {
|
||||||
let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
let area_client = block.client_location.get_local_client(id)?;
|
let area_client = block.client_location.get_local_client(id).await?;
|
||||||
let neighbors = block.client_location.get_client_neighbors(id)?;
|
let neighbors = block.client_location.get_client_neighbors(id).await?;
|
||||||
|
|
||||||
let pkt = match block.client_location.get_area(id)? {
|
let pkt = match block.client_location.get_area(id).await? {
|
||||||
RoomLobby::Room(room) => {
|
RoomLobby::Room(room) => {
|
||||||
if neighbors.is_empty() {
|
if neighbors.is_empty() {
|
||||||
block.rooms[room.0] = None;
|
block.rooms[room.0] = None;
|
||||||
}
|
}
|
||||||
let leader = block.client_location.get_room_leader(room)?;
|
let leader = block.client_location.get_room_leader(room).await?;
|
||||||
SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id()))
|
SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id()))
|
||||||
},
|
},
|
||||||
RoomLobby::Lobby(lobby) => {
|
RoomLobby::Lobby(lobby) => {
|
||||||
let leader = block.client_location.get_lobby_leader(lobby)?;
|
let leader = block.client_location.get_lobby_leader(lobby).await?;
|
||||||
SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))
|
SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id()))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -820,7 +820,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
|
|||||||
shipgate_sender(ShipMessage::RemoveUser(client.user.id));
|
shipgate_sender(ShipMessage::RemoveUser(client.user.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
block.client_location.remove_client_from_area(id);
|
block.client_location.remove_client_from_area(id).await;
|
||||||
self.item_state.remove_character_from_room(&client.character);
|
self.item_state.remove_character_from_room(&client.character);
|
||||||
|
|
||||||
if let Some(mut client) = self.clients.remove(&id) {
|
if let Some(mut client) = self.clients.remove(&id) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
use crate::common::serverstate::ClientId;
|
use crate::common::serverstate::ClientId;
|
||||||
use crate::ship::items;
|
use crate::ship::items;
|
||||||
|
use async_std::sync::{Mutex, MutexGuard};
|
||||||
|
use futures::future::Future;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TradeItem {
|
pub enum TradeItem {
|
||||||
@ -67,7 +67,7 @@ impl ClientTradeState {
|
|||||||
pub fn client(&self) -> ClientId {
|
pub fn client(&self) -> ClientId {
|
||||||
self.client
|
self.client
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn other_client(&self) -> ClientId {
|
pub fn other_client(&self) -> ClientId {
|
||||||
self.other_client
|
self.other_client
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ pub enum TradeStateError {
|
|||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct TradeState {
|
pub struct TradeState {
|
||||||
trades: HashMap<ClientId, RefCell<ClientTradeState>>,
|
trades: HashMap<ClientId, Mutex<ClientTradeState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TradeState {
|
impl TradeState {
|
||||||
@ -95,7 +95,7 @@ impl TradeState {
|
|||||||
meseta: 0,
|
meseta: 0,
|
||||||
status: TradeStatus::SentRequest,
|
status: TradeStatus::SentRequest,
|
||||||
};
|
};
|
||||||
self.trades.insert(*sender, RefCell::new(state));
|
self.trades.insert(*sender, Mutex::new(state));
|
||||||
|
|
||||||
let state = ClientTradeState {
|
let state = ClientTradeState {
|
||||||
client: *receiver,
|
client: *receiver,
|
||||||
@ -104,26 +104,26 @@ impl TradeState {
|
|||||||
meseta: 0,
|
meseta: 0,
|
||||||
status: TradeStatus::ReceivedRequest,
|
status: TradeStatus::ReceivedRequest,
|
||||||
};
|
};
|
||||||
self.trades.insert(*receiver, RefCell::new(state));
|
self.trades.insert(*receiver, Mutex::new(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_trade(&self, client: &ClientId) -> bool {
|
pub fn in_trade(&self, client: &ClientId) -> bool {
|
||||||
self.trades.contains_key(client)
|
self.trades.contains_key(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with<T, F> (&self, client: &ClientId, func: F) -> Result<T, TradeStateError>
|
pub async fn with<'a, T, F, Fut> (&'a self, client: &ClientId, func: F) -> Result<T, TradeStateError>
|
||||||
where
|
where
|
||||||
F: Fn(&mut ClientTradeState, &mut ClientTradeState) -> T
|
F: FnOnce(MutexGuard<'a, ClientTradeState>, MutexGuard<'a, ClientTradeState>) -> Fut + 'a,
|
||||||
|
Fut: Future<Output=T>
|
||||||
{
|
{
|
||||||
let mut c1 = self.trades.get(client).ok_or(TradeStateError::ClientNotInTrade(*client))?.borrow_mut();
|
let c1 = self.trades.get(client).ok_or(TradeStateError::ClientNotInTrade(*client))?.lock().await;
|
||||||
let mut c2 = self.trades.get(&c1.other_client).ok_or(TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut();
|
let c2 = self.trades.get(&c1.other_client).ok_or(TradeStateError::ClientNotInTrade(c1.other_client))?.lock().await;
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if c1.client != c2.other_client {
|
if c1.client != c2.other_client {
|
||||||
return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
|
return Err(TradeStateError::MismatchedTrade(c1.client, c2.client));
|
||||||
}
|
}
|
||||||
|
Ok(func(c1, c2).await)
|
||||||
Ok(func(&mut c1, &mut c2))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: is it possible for this to not return Options?
|
// TODO: is it possible for this to not return Options?
|
||||||
|
@ -2251,8 +2251,14 @@ async fn test_trade_not_enough_inventory_space_individual() {
|
|||||||
assert_eq!(ack.len(), 0);
|
assert_eq!(ack.len(), 0);
|
||||||
|
|
||||||
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
||||||
})).await.err().unwrap();
|
})).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::InventoryFull)));
|
|
||||||
|
assert_eq!(ack,
|
||||||
|
vec![
|
||||||
|
(ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
(ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.items.len(), 2);
|
assert_eq!(p1_items.items.len(), 2);
|
||||||
@ -2363,8 +2369,13 @@ async fn test_trade_not_enough_inventory_space_stacked() {
|
|||||||
assert_eq!(ack.len(), 0);
|
assert_eq!(ack.len(), 0);
|
||||||
|
|
||||||
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
||||||
})).await.err().unwrap();
|
})).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::InventoryFull)));
|
|
||||||
|
assert_eq!(ack,
|
||||||
|
vec![
|
||||||
|
(ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
(ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
]);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.items.len(), 1);
|
assert_eq!(p1_items.items.len(), 1);
|
||||||
@ -2472,8 +2483,13 @@ async fn test_trade_stack_too_big() {
|
|||||||
assert_eq!(ack.len(), 0);
|
assert_eq!(ack.len(), 0);
|
||||||
|
|
||||||
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
||||||
})).await.err().unwrap();
|
})).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::StackFull)));
|
|
||||||
|
assert_eq!(ack,
|
||||||
|
vec![
|
||||||
|
(ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
(ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
]);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.items.len(), 1);
|
assert_eq!(p1_items.items.len(), 1);
|
||||||
@ -3094,8 +3110,13 @@ async fn test_invalid_trade_when_both_inventories_are_full() {
|
|||||||
assert_eq!(ack.len(), 0);
|
assert_eq!(ack.len(), 0);
|
||||||
|
|
||||||
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
let ack = ship.handle(ClientId(2), &RecvShipPacket::TradeConfirmed(TradeConfirmed {
|
||||||
})).await.err().unwrap();
|
})).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::InventoryError(InventoryError::InventoryFull)));
|
|
||||||
|
assert_eq!(ack,
|
||||||
|
vec![
|
||||||
|
(ClientId(1), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
(ClientId(2), SendShipPacket::CancelTrade(CancelTrade {})),
|
||||||
|
]);
|
||||||
|
|
||||||
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
|
||||||
assert_eq!(p1_items.items.len(), 30);
|
assert_eq!(p1_items.items.len(), 30);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user