diff --git a/src/common/interserver.rs b/src/common/interserver.rs index a645f95..1f6e0ff 100644 --- a/src/common/interserver.rs +++ b/src/common/interserver.rs @@ -1,5 +1,4 @@ use std::net::Ipv4Addr; -use async_std::sync::Arc; use async_std::channel; use serde::{Serialize, Deserialize}; use serde::de::DeserializeOwned; diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index cad8959..c7a378b 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -675,18 +675,18 @@ impl From for ItemNote { fn from(other: PgItemNoteDetail) -> ItemNote { match other { PgItemNoteDetail::CharacterCreation{character_id} => ItemNote::CharacterCreation { - character_id: CharacterEntityId(character_id as u32), + character_id: CharacterEntityId(character_id), }, PgItemNoteDetail::EnemyDrop{character_id, map_area, x, y, z} => ItemNote::EnemyDrop { - character_id: CharacterEntityId(character_id as u32), + character_id: CharacterEntityId(character_id), map_area, x,y,z, }, PgItemNoteDetail::Pickup{character_id} => ItemNote::Pickup { - character_id: CharacterEntityId(character_id as u32), + character_id: CharacterEntityId(character_id), }, PgItemNoteDetail::PlayerDrop{character_id, map_area, x, y, z} => ItemNote::PlayerDrop { - character_id: CharacterEntityId(character_id as u32), + character_id: CharacterEntityId(character_id), map_area, x,y,z, }, @@ -699,16 +699,16 @@ impl From for ItemNote { }, PgItemNoteDetail::SoldToShop => ItemNote::SoldToShop, PgItemNoteDetail::Trade {trade_id, character_to, character_from} => ItemNote::Trade { - trade_id: TradeId(trade_id as u32), - character_to: CharacterEntityId(character_to as u32), - character_from: CharacterEntityId(character_from as u32), + trade_id: TradeId(trade_id), + character_to: CharacterEntityId(character_to), + character_from: CharacterEntityId(character_from), }, PgItemNoteDetail::Withdraw{character_id, bank} => ItemNote::Withdraw { - character_id: CharacterEntityId(character_id as u32), + character_id: CharacterEntityId(character_id), bank: BankName(bank), }, PgItemNoteDetail::Deposit{character_id, bank} => ItemNote::Deposit { - character_id: CharacterEntityId(character_id as u32), + character_id: CharacterEntityId(character_id), bank: BankName(bank), }, } diff --git a/src/login/character.rs b/src/login/character.rs index 109681b..87a3c4a 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -2,7 +2,7 @@ use std::io::Read; use std::collections::{BTreeMap, BTreeSet, HashMap}; -use async_std::sync::Arc; +use async_std::sync::{Arc, RwLock}; use async_std::channel; use rand::Rng; @@ -186,16 +186,14 @@ struct ConnectedClient { pub struct CharacterServerState { entity_gateway: EG, param_header: ParamDataHeader, - param_data: Vec, - clients: HashMap, - ships: BTreeMap, - //level_table: CharacterLevelTable, + param_data: Arc>, + clients: Arc>>, + ships: Arc>>, auth_token: AuthToken, - connected_clients: BTreeMap, - authenticated_ships: BTreeSet, - //ship_sender: BTreeMap Box> + Send>>>, - ship_sender: BTreeMap>, + connected_clients: Arc>>, + authenticated_ships: Arc>>, + ship_sender: Arc>>>, } @@ -318,21 +316,21 @@ impl CharacterServerState { CharacterServerState { entity_gateway, param_header, - param_data, - clients: HashMap::new(), - ships: BTreeMap::new(), + param_data: Arc::new(param_data), + clients: Default::default(), + ships: Default::default(), //level_table: CharacterLevelTable::default(), auth_token, - authenticated_ships: BTreeSet::new(), - ship_sender: BTreeMap::new(), - connected_clients: BTreeMap::new(), + authenticated_ships: Default::default(), + ship_sender: Default::default(), + connected_clients: Default::default(), } } async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, anyhow::Error> { match get_login_status(&mut self.entity_gateway, pkt).await { Ok(user) => { - if let Some(connected_client) = self.connected_clients.get(&user.id) { + if let Some(connected_client) = self.connected_clients.read().await.get(&user.id) { if let Some(expires) = connected_client.expires { if expires > chrono::Utc::now() { return Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_status(AccountStatus::AlreadyOnline, Session::new()))]); @@ -345,11 +343,12 @@ impl CharacterServerState { let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); response.guildcard = user.guildcard; - response.team_id = user.team_id.map_or(0, |ti| ti) as u32; + response.team_id = user.team_id.map_or(0, |ti| ti); - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; - self.connected_clients.insert(user.id, ConnectedClient { + self.connected_clients.write().await.insert(user.id, ConnectedClient { ship_id: None, expires: None, //Some(chrono::Utc::now() + chrono::Duration::minutes(1)), }); @@ -364,9 +363,9 @@ impl CharacterServerState { } } - fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result, anyhow::Error> { + async fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result, anyhow::Error> { Ok(vec![SendCharacterPacket::Timestamp(Timestamp::new(chrono::Utc::now())), - SendCharacterPacket::ShipList(ShipList::new(self.ships.iter().map(|(i, s)| { + SendCharacterPacket::ShipList(ShipList::new(self.ships.read().await.iter().map(|(i, s)| { ShipListEntry { menu: SHIP_MENU_ID, item: i.0 as u32, @@ -378,7 +377,8 @@ impl CharacterServerState { } async fn get_settings(&mut self, id: ClientId) -> Result, anyhow::Error> { - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; let user = client.user.as_ref().unwrap(); let settings = match self.entity_gateway.get_user_settings_by_user(user).await { @@ -397,7 +397,8 @@ impl CharacterServerState { } async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result, anyhow::Error> { - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; if client.characters.is_none() { client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadCharacters)?); } @@ -443,7 +444,8 @@ impl CharacterServerState { } async fn guildcard_data_header(&mut self, id: ClientId) -> Result, anyhow::Error> { - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadGuildcard)?; let bytes = guildcard_data.guildcard.as_bytes(); @@ -454,15 +456,16 @@ impl CharacterServerState { Ok(vec![SendCharacterPacket::GuildcardDataHeader(GuildcardDataHeader::new(bytes.len(), crc.sum32()))]) } - fn guildcard_data_chunk(&mut self, id: ClientId, chunk: u32, again: u32) -> Result, anyhow::Error> { - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + async fn guildcard_data_chunk(&mut self, id: ClientId, chunk: u32, again: u32) -> Result, anyhow::Error> { + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; Ok(if again != 0 { let start = chunk as usize * GUILD_CARD_CHUNK_SIZE; - let len = std::cmp::min(GUILD_CARD_CHUNK_SIZE, client.guildcard_data_buffer.as_ref().unwrap().len() as usize - start); + let len = std::cmp::min(GUILD_CARD_CHUNK_SIZE, client.guildcard_data_buffer.as_ref().unwrap().len() - start); let end = start + len; - let mut buf = [0u8; GUILD_CARD_CHUNK_SIZE as usize]; - buf[..len as usize].copy_from_slice(&client.guildcard_data_buffer.as_ref().unwrap()[start..end]); + let mut buf = [0u8; GUILD_CARD_CHUNK_SIZE]; + buf[..len].copy_from_slice(&client.guildcard_data_buffer.as_ref().unwrap()[start..end]); vec![SendCharacterPacket::GuildcardDataChunk(Box::new(GuildcardDataChunk::new(chunk, buf, len)))] } else { @@ -471,15 +474,17 @@ impl CharacterServerState { } async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result, anyhow::Error> { - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); user.flags = setflag.flags; self.entity_gateway.save_user(user).await.unwrap(); Ok(None.into_iter()) } - fn param_data_chunk_request(&mut self, id: ClientId, _request: &ParamDataChunkRequest) -> Result, anyhow::Error> { - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + async fn param_data_chunk_request(&mut self, id: ClientId, _request: &ParamDataChunkRequest) -> Result, anyhow::Error> { + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; let chunk = client.param_index; client.param_index += 1; @@ -500,7 +505,8 @@ impl CharacterServerState { // TODO: move USERFLAGS over to SessionAction async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result, anyhow::Error> { - let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; + let mut client = self.clients.write().await; + let client = client.get_mut(&id).ok_or_else(|| CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); if user.flags == USERFLAG_NEWCHAR { new_character(&mut self.entity_gateway, user, preview).await? @@ -523,26 +529,30 @@ impl CharacterServerState { ]) } - fn select_ship(&mut self, id: ClientId, menuselect: &MenuSelect) -> Result, anyhow::Error> { + async fn select_ship(&mut self, id: ClientId, menuselect: &MenuSelect) -> Result, anyhow::Error> { if menuselect.menu != SHIP_MENU_ID { return Err(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item).into()); } - if let Some(client) = self.clients.get(&id) { + if let Some(client) = self.clients.read().await.get(&id) { if let Some(user) = &client.user { - if let Some(cc) = self.connected_clients.get_mut(&user.id) { + if let Some(cc) = self.connected_clients.write().await.get_mut(&user.id) { cc.ship_id = Some(ServerId(menuselect.item as usize)); } } } - let ship = self.ships.get(&ServerId(menuselect.item as usize)) - .ok_or(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?; + let ship = self.ships.read().await; + let ship = ship.get(&ServerId(menuselect.item as usize)) + .ok_or_else(|| CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?; Ok(vec![SendCharacterPacket::RedirectClient(RedirectClient::new(u32::from_le_bytes(ship.ip.octets()), ship.port))]) } - fn ship_detail(&mut self, menudetail: &MenuDetail) -> Result, anyhow::Error> { - let players = self.connected_clients.iter() + async fn ship_detail(&mut self, menudetail: &MenuDetail) -> Result, anyhow::Error> { + let players = self.connected_clients + .read() + .await + .iter() .filter(|(_, client)| { client.ship_id == Some(ServerId(menudetail.item as usize)) }) @@ -560,7 +570,7 @@ impl ServerState for CharacterServerState { type PacketError = anyhow::Error; async fn on_connect(&mut self, id: ClientId) -> Result>, anyhow::Error> { - self.clients.insert(id, ClientState::new()); + self.clients.write().await.insert(id, ClientState::new()); let mut rng = rand::thread_rng(); @@ -581,7 +591,7 @@ impl ServerState for CharacterServerState { Ok(match pkt { RecvCharacterPacket::Login(login) => { if login.session.action == SessionAction::SelectCharacter { - self.send_ship_list(id, &login)?.into_iter().map(move |pkt| (id, pkt)).collect() + self.send_ship_list(id, &login).await?.into_iter().map(move |pkt| (id, pkt)).collect() } else { self.validate_login(id, &login).await?.into_iter().map(move |pkt| (id, pkt)).collect() @@ -600,7 +610,7 @@ impl ServerState for CharacterServerState { self.guildcard_data_header(id).await?.into_iter().map(move |pkt| (id, pkt)).collect() }, RecvCharacterPacket::GuildcardDataChunkRequest(request) => { - self.guildcard_data_chunk(id, request.chunk, request.again)?.into_iter().map(move |pkt| (id, pkt)).collect() + self.guildcard_data_chunk(id, request.chunk, request.again).await?.into_iter().map(move |pkt| (id, pkt)).collect() }, RecvCharacterPacket::ParamDataRequest(_request) => { vec![SendCharacterPacket::ParamDataHeader(self.param_header.clone())].into_iter().map(move |pkt| (id, pkt)).collect() @@ -609,17 +619,17 @@ impl ServerState for CharacterServerState { self.set_flag(id, &flag).await?.map(move |pkt| (id, pkt)).collect() }, RecvCharacterPacket::ParamDataChunkRequest(request) => { - self.param_data_chunk_request(id, &request)?.into_iter().map(move |pkt| (id, pkt)).collect() + self.param_data_chunk_request(id, &request).await?.into_iter().map(move |pkt| (id, pkt)).collect() }, RecvCharacterPacket::CharacterPreview(preview) => { self.character_preview(id, &preview).await?.into_iter().map(move |pkt| (id, pkt)).collect() }, RecvCharacterPacket::MenuSelect(menuselect) => { - self.select_ship(id, &menuselect)?.into_iter().map(move |pkt| (id, pkt)).collect() + self.select_ship(id, &menuselect).await?.into_iter().map(move |pkt| (id, pkt)).collect() }, RecvCharacterPacket::MenuDetail(menudetail) => { match menudetail.menu { - SHIP_MENU_ID => self.ship_detail(&menudetail)?.into_iter().map(move |pkt| (id, pkt)).collect(), + SHIP_MENU_ID => self.ship_detail(&menudetail).await?.into_iter().map(move |pkt| (id, pkt)).collect(), _ => Vec::new() } } @@ -627,9 +637,9 @@ impl ServerState for CharacterServerState { } async fn on_disconnect(&mut self, id: ClientId) -> Result, anyhow::Error> { - if let Some(client) = self.clients.remove(&id) { + if let Some(client) = self.clients.write().await.remove(&id) { if let Some(user) = client.user { - self.connected_clients.remove(&user.id); + self.connected_clients.write().await.remove(&user.id); } } Ok(Vec::new()) @@ -647,20 +657,25 @@ impl InterserverActor for CharacterServerState { } async fn on_action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result, Self::Error> { + dbg!(&id, &msg); match msg { ShipMessage::Authenticate(auth_token) => { if self.auth_token == auth_token { - self.authenticated_ships.insert(id); + self.authenticated_ships.write().await.insert(id); } Ok(Vec::new()) }, ShipMessage::NewShip(new_ship) => { - if self.authenticated_ships.contains(&id) { - self.ships.insert(id, new_ship); + dbg!("adding ship", &id, &new_ship); + if self.authenticated_ships.read().await.contains(&id) { + self.ships.write().await.insert(id, new_ship); } + dbg!("ship list", &self.authenticated_ships); - let ships = self.ships.iter().map(|(_, s)| s).cloned().collect::>(); + let ships = self.ships.read().await.iter().map(|(_, s)| s).cloned().collect::>(); Ok(self.ships + .read() + .await .iter() .map(|(id, _)| { (*id, LoginMessage::ShipList{ ships: ships.clone() }) @@ -668,8 +683,8 @@ impl InterserverActor for CharacterServerState { .collect()) }, ShipMessage::AddUser(new_user) => { - if self.authenticated_ships.contains(&id) { - self.connected_clients.insert(new_user, ConnectedClient { + if self.authenticated_ships.read().await.contains(&id) { + self.connected_clients.write().await.insert(new_user, ConnectedClient { ship_id: Some(id), expires: None, }); @@ -677,15 +692,18 @@ impl InterserverActor for CharacterServerState { Ok(Vec::new()) }, ShipMessage::RemoveUser(new_user) => { - if self.authenticated_ships.contains(&id) { - self.connected_clients.remove(&new_user); + if self.authenticated_ships.read().await.contains(&id) { + self.connected_clients.write().await.remove(&new_user); } Ok(Vec::new()) }, ShipMessage::RequestShipList => { - if self.authenticated_ships.contains(&id) { + dbg!("request ship list", &self.authenticated_ships); + if self.authenticated_ships.read().await.contains(&id) { Ok(vec![(id, LoginMessage::ShipList { ships: self.ships + .read() + .await .iter() .map(|(_, ship)| { ship @@ -705,18 +723,19 @@ impl InterserverActor for CharacterServerState { } async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { - self.ships.remove(&id); - self.ship_sender.remove(&id); - self.connected_clients = self.connected_clients.clone().into_iter() - .filter(|(_, client)| { + self.ships.write().await.remove(&id); + self.ship_sender.write().await.remove(&id); + self.connected_clients + .write() + .await + .retain(|_, client| { client.ship_id != Some(id) - }) - .collect(); + }); Vec::new() } - fn set_sender(&mut self, server_id: ServerId, sender: channel::Sender) { - self.ship_sender.insert(server_id, sender); + async fn set_sender(&mut self, server_id: ServerId, sender: channel::Sender) { + self.ship_sender.write().await.insert(server_id, sender); } } @@ -845,7 +864,7 @@ mod test { at_character: false, at_ship: false, }); - server.clients.insert(ClientId(5), clientstate); + server.clients.write().await.insert(ClientId(5), clientstate); let send = server.handle(ClientId(5), RecvCharacterPacket::RequestSettings(RequestSettings{})).await.unwrap(); assert!(send.len() == 1); @@ -892,7 +911,7 @@ mod test { }); let mut server = CharacterServerState::new(test_data.clone(), AuthToken("".into())); - server.clients.insert(ClientId(1), fake_user.clone()); + server.clients.write().await.insert(ClientId(1), fake_user.clone()); let mut send = server.handle(ClientId(1), RecvCharacterPacket::SetFlag(SetFlag {flags: 1})).await.unwrap(); assert!(test_data.get_user_by_id(UserAccountId(3)).await.unwrap().flags == 1); send = server.handle(ClientId(1), RecvCharacterPacket::CharacterPreview(CharacterPreview {slot: 1, character: character::SelectScreenCharacter { diff --git a/src/patch/patch.rs b/src/patch/patch.rs index a7b0715..230c5bf 100644 --- a/src/patch/patch.rs +++ b/src/patch/patch.rs @@ -190,9 +190,8 @@ impl ServerState for PatchServerState { .collect() }, RecvPatchPacket::FileInfoReply(pkt) => { - self.patch_file_info.push(pkt.clone()); + self.patch_file_info.push(pkt); Vec::new() - //None.into_iter().map(move |pkt| (id, pkt)) }, RecvPatchPacket::FileInfoListEnd(_pkt) => { let need_update = self.patch_file_info.iter() diff --git a/src/ship/character.rs b/src/ship/character.rs index 454b2c8..348f8ac 100644 --- a/src/ship/character.rs +++ b/src/ship/character.rs @@ -77,7 +77,7 @@ impl<'a> CharacterBytesBuilder<'a> { prop_y: character.appearance.prop_y, config: character.config.as_bytes(), techniques: character.techs.as_bytes(), - meseta: meseta.0 as u32, + meseta: meseta.0, exp: character.exp, ..character::Character::default() } diff --git a/src/ship/items/actions.rs b/src/ship/items/actions.rs index 541077c..e19c4ab 100644 --- a/src/ship/items/actions.rs +++ b/src/ship/items/actions.rs @@ -30,7 +30,7 @@ pub(super) fn take_item_from_floor(character_id: CharacterEntityId, item_id: Cli move |(mut item_state, transaction): (ItemStateProxy<'_>, Box) , _| { Box::pin(async move { let mut floor = item_state.floor(&character_id).await?; - let item = floor.take_item(&item_id).ok_or(ItemStateError::NoFloorItem(item_id))?; + let item = floor.take_item(&item_id).ok_or_else(|| ItemStateError::NoFloorItem(item_id))?; item_state.set_floor(floor).await; Ok(((item_state, transaction), item)) @@ -88,7 +88,7 @@ pub(super) fn take_item_from_inventory(character_id: CharacterEntityId, item_id: move |(mut item_state, mut transaction), _| { Box::pin(async move { let mut inventory = item_state.inventory(&character_id).await?; - let item = inventory.take_item(&item_id, amount).ok_or (ItemStateError::NoFloorItem(item_id))?; + let item = inventory.take_item(&item_id, amount).ok_or_else(|| ItemStateError::NoFloorItem(item_id))?; transaction.gateway().set_character_inventory(&character_id, &inventory.as_inventory_entity(&character_id)).await?; item_state.set_inventory(inventory); @@ -238,7 +238,7 @@ pub(super) fn take_item_from_bank(character_id: CharacterEntityId, item_id: Clie move |(mut item_state, mut transaction), _| { Box::pin(async move { let mut bank = item_state.bank(&character_id).await?; - let item = bank.take_item(&item_id, amount).ok_or(ItemStateError::NoBankItem(item_id))?; + let item = bank.take_item(&item_id, amount).ok_or_else(|| ItemStateError::NoBankItem(item_id))?; transaction.gateway().set_character_bank(&character_id, &bank.as_bank_entity(), &bank.name).await?; item_state.set_bank(bank); @@ -407,10 +407,10 @@ pub(super) fn feed_mag_item(character: CharacterEntity, mag_item_id: ClientItemI Box::pin(async move { let mut inventory = item_state.inventory(&character.id).await?; let mag_entity = inventory.get_by_client_id_mut(&mag_item_id) - .ok_or(ItemStateError::InvalidItemId(mag_item_id))? + .ok_or_else(|| ItemStateError::InvalidItemId(mag_item_id))? .item .as_individual_mut() - .ok_or(ItemStateError::NotAMag(mag_item_id))?; + .ok_or_else(|| ItemStateError::NotAMag(mag_item_id))?; let mag_entity_id = mag_entity.entity_id; let mut transaction = tool.with_entity_id(transaction, |mut transaction, entity_id| { @@ -426,13 +426,13 @@ pub(super) fn feed_mag_item(character: CharacterEntity, mag_item_id: ClientItemI let food_tool = tool .item .stacked() - .ok_or(ItemStateError::NotMagFood(tool.item_id))? + .ok_or_else(|| ItemStateError::NotMagFood(tool.item_id))? .tool .tool; let mag_entity = mag_entity .as_mag_mut() - .ok_or(ItemStateError::NotAMag(mag_item_id))?; + .ok_or_else(|| ItemStateError::NotAMag(mag_item_id))?; mag_entity.feed(food_tool); diff --git a/src/ship/items/state.rs b/src/ship/items/state.rs index 5341921..8c95391 100644 --- a/src/ship/items/state.rs +++ b/src/ship/items/state.rs @@ -1,23 +1,19 @@ use std::collections::HashMap; use async_std::sync::{Arc, RwLock}; -use crate::ship::items::ClientItemId; -use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, InventoryItemEntity, BankItemEntity, BankName}; - use futures::future::join_all; - - -use crate::ship::location::{AreaClient, RoomId}; -use crate::entity::character::{CharacterEntity, CharacterEntityId}; use crate::entity::gateway::{EntityGateway, GatewayError}; +use crate::entity::character::{CharacterEntity, CharacterEntityId}; +use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, InventoryItemEntity, BankItemEntity, BankName}; use crate::entity::item::tool::Tool; use crate::entity::item::weapon::Weapon; use crate::entity::item::mag::Mag; use crate::ship::drops::ItemDrop; - +use crate::ship::items::ClientItemId; use crate::ship::items::inventory::{Inventory, InventoryItem, InventoryItemDetail, InventoryError, InventoryState}; use crate::ship::items::floor::{FloorState, FloorItem, LocalFloor, SharedFloor, FloorType}; use crate::ship::items::bank::{Bank, BankState, BankItem, BankItemDetail, BankError}; +use crate::ship::location::{AreaClient, RoomId}; #[derive(thiserror::Error, Debug)] pub enum ItemStateError { @@ -27,55 +23,38 @@ pub enum ItemStateError { NoRoom(RoomId), #[error("floor item {0} not found")] NoFloorItem(ClientItemId), - #[error("expected {0} to be a tool")] NotATool(ClientItemId), - #[error("bank item {0} not found")] NoBankItem(ClientItemId), - #[error("inventory error {0}")] InventoryError(#[from] InventoryError), - #[error("bank error {0}")] BankError(#[from] BankError), - #[error("invalid item id {0}")] InvalidItemId(ClientItemId), - #[error("invalid drop? {0:?} (this shouldn't occur)")] BadItemDrop(ItemDrop), - #[error("idk")] Dummy, - #[error("gateway")] GatewayError(#[from] GatewayError), - #[error("tried to remove more meseta than exists: {0}")] InvalidMesetaRemoval(u32), - #[error("tried to add meseta when there is no more room")] FullOfMeseta, - #[error("stacked item")] StackedItemError(Vec), - #[error("apply item {0}")] ApplyItemError(#[from] crate::ship::items::apply_item::ApplyItemError), - #[error("item is not a mag {0}")] NotAMag(ClientItemId), - #[error("item is not mag food {0}")] NotMagFood(ClientItemId), - #[error("item is not sellable")] ItemNotSellable, - #[error("could not modify item")] InvalidModifier, - #[error("wrong item type ")] WrongItemType(ClientItemId), } @@ -137,7 +116,6 @@ impl StackedItemDetail { } - #[derive(Clone)] pub enum AddItemResult { NewItem, @@ -177,7 +155,7 @@ impl ItemState { .read() .await .get(&character.id) - .ok_or(ItemStateError::NoCharacter(character.id))? + .ok_or_else(|| ItemStateError::NoCharacter(character.id))? .read() .await .clone()) @@ -188,7 +166,7 @@ impl ItemState { .read() .await .get(&character.id) - .ok_or(ItemStateError::NoCharacter(character.id))? + .ok_or_else(|| ItemStateError::NoCharacter(character.id))? .read() .await .clone()) @@ -197,7 +175,6 @@ impl ItemState { impl ItemState { async fn new_item_id(&mut self) -> Result { - //self.room_item_id_counter += 1; *self.room_item_id_counter .write() .await += 1; @@ -300,7 +277,6 @@ impl ItemState { pub async fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) { let base_inventory_id = ((area_client.local_client.id() as u32) << 21) | 0x10000; - //let inventory = self.character_inventory.get_mut(&character.id).unwrap(); self.character_inventory .read() .await @@ -309,9 +285,7 @@ impl ItemState { .write() .await .initialize_item_ids(base_inventory_id); - //inventory.initialize_item_ids(base_inventory_id); let base_bank_id = ((area_client.local_client.id() as u32) << 21) | 0x20000; - //let default_bank = self.character_bank.get_mut(&character.id); self.character_bank .read() .await @@ -320,9 +294,6 @@ impl ItemState { .write() .await .initialize_item_ids(base_bank_id); - //if let Some(default_bank) = default_bank { - //default_bank.initialize_item_ids(base_bank_id); - //} self.character_room .write() .await @@ -369,7 +340,7 @@ impl ItemState { .await; let local_floor = local_floors .get(character_id) - .ok_or(ItemStateError::NoCharacter(*character_id))? + .ok_or_else(|| ItemStateError::NoCharacter(*character_id))? .read() .await; let rooms = self.character_room @@ -377,13 +348,13 @@ impl ItemState { .await; let room = rooms .get(character_id) - .ok_or(ItemStateError::NoCharacter(*character_id))?; + .ok_or_else(||ItemStateError::NoCharacter(*character_id))?; let shared_floors = self.room_floor .read() .await; let shared_floor = shared_floors .get(room) - .ok_or(ItemStateError::NoCharacter(*character_id))? + .ok_or_else(||ItemStateError::NoCharacter(*character_id))? .read() .await; @@ -397,7 +368,7 @@ impl ItemState { .find(|item| item.item_id == *item_id) .map(|item| (item.clone(), FloorType::Shared)) }) - .ok_or(ItemStateError::NoFloorItem(*item_id)) + .ok_or_else(|| ItemStateError::NoFloorItem(*item_id)) } } @@ -415,12 +386,10 @@ struct ProxiedItemState { pub struct ItemStateProxy<'a> { item_state: &'a mut ItemState, proxied_state: ProxiedItemState, - //_a: std::marker::PhantomData<&'a ()>, // TODO: remove } impl<'a> ItemStateProxy<'a> { pub async fn commit(self) { - async fn copy_back(master: &Arc>>>, proxy: HashMap) where @@ -443,43 +412,6 @@ impl<'a> ItemStateProxy<'a> { //copy_back(self.item_state.character_room, self.proxied_state.character_room).await; copy_back(&self.item_state.character_floor, self.proxied_state.character_floor).await; copy_back(&self.item_state.room_floor, self.proxied_state.room_floor).await; - - - /* - self.item_state.character_inventory - .write() - .await - .extend(self.proxied_state.character_inventory.clone()); - self.item_state.character_bank - .write() - .await - .extend(self.proxied_state.character_bank.clone()); - self.item_state.character_room - .write() - .await - .extend(self.proxied_state.character_room.clone()); - self.item_state.character_floor - .write() - .await - .extend(self.proxied_state.character_floor.clone()); - self.item_state.room_floor - .write() - .await - .extend(self.proxied_state.room_floor); - */ - /* - for (character_id, character_inventory) in self.proxied_state.character_inventory { - if let Some(inventory) = self.item_state.character_inventory - .read() - .await - .get(&character_id) { - *inventory - .write() - .await = character_inventory; - } - } - */ - } } @@ -492,11 +424,6 @@ where K: Eq + std::hash::Hash + Copy, V: Clone { - /* - let existing_element = master.get(&key).ok_or_else(|| err(key))?; - Ok(proxy.entry(key) - .or_insert_with(|| existing_element.clone()).clone()) - */ let existing_element = master .read() .await @@ -516,7 +443,6 @@ impl<'a> ItemStateProxy<'a> { ItemStateProxy { item_state, proxied_state: Default::default(), - //_a: Default::default(), } } @@ -543,7 +469,6 @@ impl<'a> ItemStateProxy<'a> { } pub async fn floor(&mut self, character_id: &CharacterEntityId) -> Result { - //let room_id = get_or_clone(&self.item_state.character_room, &mut self.proxied_state.character_room, *character_id, ItemStateError::NoCharacter)?; let room_id = *self.item_state.character_room.read().await.get(character_id).unwrap(); Ok(FloorState { character_id: *character_id, @@ -553,7 +478,6 @@ impl<'a> ItemStateProxy<'a> { } pub async fn set_floor(&mut self, floor: FloorState) { - //let room_id = get_or_clone(&self.item_state.character_room, &mut self.proxied_state.character_room, floor.character_id, ItemStateError::NoCharacter).unwrap(); let room_id = *self.item_state.character_room.read().await.get(&floor.character_id).unwrap(); self.proxied_state.character_floor.insert(floor.character_id, floor.local); self.proxied_state.room_floor.insert(room_id, floor.shared); diff --git a/src/ship/map/area.rs b/src/ship/map/area.rs index 4cb22ee..02361c3 100644 --- a/src/ship/map/area.rs +++ b/src/ship/map/area.rs @@ -320,7 +320,7 @@ pub struct MapAreaLookup(HashMap); impl MapAreaLookup { pub fn get_area_map(&self, map_area: u16) -> Result { self.0.get(&map_area) - .map(|a| *a) + .copied() .ok_or(MapAreaError::UnknownMapArea(map_area)) } diff --git a/src/ship/packet/builder/lobby.rs b/src/ship/packet/builder/lobby.rs index 86da981..2571766 100644 --- a/src/ship/packet/builder/lobby.rs +++ b/src/ship/packet/builder/lobby.rs @@ -43,7 +43,7 @@ pub async fn join_lobby(id: ClientId, block: client_block, event: 0, padding: 0, - playerinfo: playerinfo, + playerinfo, }) } diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index 1ae4137..ddbfeeb 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -23,20 +23,21 @@ where Ok(match get_login_status(entity_gateway, &pkt).await { Ok(user) => { let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); - response.guildcard = user.id.0 as u32; - response.team_id = user.team_id.map_or(31, |ti| ti) as u32; + response.guildcard = user.id.0; + response.team_id = user.team_id.map_or(31, |ti| ti); let characters = entity_gateway.get_characters_by_user(&user).await?; let character = characters .get(pkt.session.character_slot as usize) - .ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref() - .ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? + .ok_or_else(|| ShipError::InvalidSlot(id, pkt.session.character_slot as u32))? + .as_ref() + .ok_or_else(|| ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? .clone(); let settings = entity_gateway.get_user_settings_by_user(&user).await?; item_state.load_character(entity_gateway, &character).await?; if let Some(shipgate_sender) = shipgate_sender.as_ref() { - shipgate_sender.send(ShipMessage::AddUser(user.id)).await; + shipgate_sender.send(ShipMessage::AddUser(user.id)).await?; } clients.add(id, ClientState::new(user, settings, character, pkt.session)).await; vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(ship_name, num_blocks))] diff --git a/src/ship/packet/handler/communication.rs b/src/ship/packet/handler/communication.rs index eb16508..0a80304 100644 --- a/src/ship/packet/handler/communication.rs +++ b/src/ship/packet/handler/communication.rs @@ -17,7 +17,7 @@ pub async fn player_chat(id: ClientId, Ok(client_location.get_all_clients_by_client(id).await.unwrap().into_iter() .map(move |client| { - (client.client, SendShipPacket::PlayerChat(cmsg.clone()).clone()) + (client.client, SendShipPacket::PlayerChat(cmsg.clone())) }) .collect()) } diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index 29c64cf..f565d41 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -6,7 +6,7 @@ use libpso::packet::messages::*; use crate::common::leveltable::LEVEL_TABLE; use crate::common::serverstate::ClientId; use crate::ship::ship::{SendShipPacket, ShipError, Clients, ItemShops}; -use crate::ship::location::{ClientLocation, ClientLocationError}; +use crate::ship::location::ClientLocation; use crate::ship::drops::ItemDrop; use crate::ship::room::Rooms; use crate::ship::items::ClientItemId; @@ -86,16 +86,16 @@ pub async fn request_item(id: ClientId, where EG: EntityGateway { - let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let room_id = client_location.get_room(id).await?; let monster = rooms.with(room_id, |room| Box::pin(async move { room.maps.enemy_by_id(request_item.enemy_id as usize) })).await??; if monster.dropped_item { - return Err(ShipError::MonsterAlreadyDroppedItem(id, request_item.enemy_id).into()) + return Err(ShipError::MonsterAlreadyDroppedItem(id, request_item.enemy_id)) } - let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let clients_in_area = client_location.get_clients_in_room(room_id).await?; let client_and_drop = rooms.with_mut(room_id, |room| Box::pin(async move { clients_in_area.into_iter() .filter_map(move |area_client| { @@ -138,9 +138,9 @@ pub async fn pickup_item(id: ClientId, where EG: EntityGateway + Clone + 'static, { - let area_client = client_location.get_local_client(id).await.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).await.map_err(|err| -> ClientLocationError { err.into() })?; + let area_client = client_location.get_local_client(id).await?; + let room_id = client_location.get_room(id).await?; + let clients_in_area = client_location.get_clients_in_room(room_id).await?; clients.with(id, |client| { let mut entity_gateway = entity_gateway.clone(); @@ -197,16 +197,16 @@ pub async fn request_box_item(id: ClientId, where EG: EntityGateway + Clone + 'static { - let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let room_id = client_location.get_room(id).await?; let box_object = rooms.with(room_id, |room| Box::pin(async move { room.maps.object_by_id(box_drop_request.object_id as usize) })).await??; if box_object.dropped_item { - return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id).into()) + return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id)) } - let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let clients_in_area = client_location.get_clients_in_room(room_id).await?; let client_and_drop = rooms.with_mut(room_id, |room| Box::pin(async move { clients_in_area.into_iter() @@ -266,8 +266,8 @@ pub async fn bank_interaction(id: ClientId, where EG: EntityGateway + Clone + 'static, { - 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).await.map_err(|err| -> ClientLocationError { err.into() })?; + let area_client = client_location.get_local_client(id).await?; + let other_clients_in_area = client_location.get_all_clients_by_client(id).await?; let bank_action_pkts = clients.with(id, |client| { let mut entity_gateway = entity_gateway.clone(); @@ -323,7 +323,7 @@ pub async fn shop_request(id: ClientId, -> Result, ShipError> { //let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; - let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let room_id = client_location.get_room(id).await?; /* let room = rooms.get(room_id.0) .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? @@ -401,7 +401,7 @@ pub async fn buy_item(id: ClientId, where EG: EntityGateway + Clone + 'static, { - let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let area_client = client_location.get_local_client(id).await?; let create = clients.with_mut(id, |client| { let mut entity_gateway = entity_gateway.clone(); @@ -422,7 +422,7 @@ where (item, remove) }, _ => { - return Err(ShipError::ShopError.into()) + return Err(ShipError::ShopError) } }; @@ -442,7 +442,7 @@ where builder::message::create_withdrawn_inventory_item(area_client, &inventory_item) })}).await??; - let other_clients_in_area = client_location.get_client_neighbors(id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let other_clients_in_area = client_location.get_client_neighbors(id).await?; Ok(other_clients_in_area.into_iter() .map(move |c| { (c.client, SendShipPacket::Message(Message::new(GameMessage::CreateItem(create.clone())))) @@ -489,11 +489,11 @@ where let inventory = item_state.get_character_inventory(&client.character).await?; let item = inventory.get_by_client_id(&ClientItemId(tek_request.item_id)) - .ok_or(ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?; + .ok_or_else(|| ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?; let mut weapon = *item.item.as_individual() - .ok_or(ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))? + .ok_or_else(|| ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))? .as_weapon() - .ok_or(ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?; + .ok_or_else(|| ItemStateError::WrongItemType(ClientItemId(tek_request.item_id)))?; weapon.apply_modifier(&item::weapon::WeaponModifier::Tekked { special: special_mod, @@ -519,8 +519,8 @@ pub async fn accept_tek_item(id: ClientId, where EG: EntityGateway + Clone + 'static, { - let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?; - let neighbors = client_location.get_client_neighbors(id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let area_client = client_location.get_local_client(id).await?; + let neighbors = client_location.get_client_neighbors(id).await?; clients.with(id, |client| { let mut entity_gateway = entity_gateway.clone(); diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index 692740e..287ea41 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -146,45 +146,17 @@ pub async fn remove_from_lobby(id: ClientId, pub async fn get_room_tab_info(id: ClientId, pkt: MenuDetail, client_location: &mut ClientLocation, - clients: &Clients, - rooms: &mut Rooms) + clients: &Clients) -> Result, ShipError> { - /* let room_id = RoomId(pkt.item as usize); - if let Some(_room) = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))? { - let mut room_info = String::new(); - 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 { - let cs = clients.get(&client.client).ok_or(ShipError::ClientNotFound(client.client))?; - let gc = cs.user.guildcard; - let name = &cs.character.name; - let cc = cs.character.char_class; - let lv = LEVEL_TABLE.get_level_from_exp(cc, cs.character.exp); - let floor = cs.area.unwrap_or(MapArea::Pioneer2Ep1); - - room_info += format!("{} Lv{} {}\n{} {}\n", gc,lv,name,cc,floor).as_str(); - } - Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new(room_info)))]) - } else { - Ok(vec![(id, SendShipPacket::SmallLeftDialog(SmallLeftDialog::new("Game is no longer active".into())))]) - } - */ - dbg!("a"); - let room_id = RoomId(pkt.item as usize); - dbg!("b"); let clients_in_room = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?; - dbg!("c"); - let room_info = if clients_in_room.len() == 0 { - dbg!("d"); + let room_info = if clients_in_room.is_empty() { String::from("Game is no longer active") } else { - dbg!("d2"); join_all(clients_in_room.iter() .map(|clientl| async move { - dbg!("e"); clients.with(clientl.client, |client| Box::pin(async move { - dbg!("f"); format!("{} Lv{} {}\n{} {}", client.character.name, LEVEL_TABLE.get_level_from_exp(client.character.char_class, client.character.exp), diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index 823b83b..df8b7d0 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -28,7 +28,7 @@ where let enemy_id = request_exp.enemy_id as usize; let enemy_exp = rooms.with(room_id, |room| Box::pin(async move { let monster = room.maps.enemy_by_id(enemy_id)?; - let monster_stats = room.monster_stats.get(&monster.monster).ok_or(ShipError::UnknownMonster(monster.monster))?; + let monster_stats = room.monster_stats.get(&monster.monster).ok_or_else(|| ShipError::UnknownMonster(monster.monster))?; Ok::<_, ShipError>(monster_stats.exp) })).await??; @@ -150,7 +150,7 @@ where })).await?; if let Some(drop_location) = drop_location { 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)); } if no_longer_has_item.item_id == 0xFFFFFFFF { @@ -163,7 +163,7 @@ where })}).await??; let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta)?; - 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); let clients_in_area = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?; Ok(clients_in_area.into_iter() @@ -218,7 +218,7 @@ where .collect()) } else { - Err(ShipError::InvalidItem(ClientItemId(no_longer_has_item.item_id)).into()) + Err(ShipError::InvalidItem(ClientItemId(no_longer_has_item.item_id))) } } @@ -292,7 +292,7 @@ pub async fn update_player_position(id: ClientId, _ => {}, } Ok::<_, ShipError>(()) - })}).await?; + })}).await??; } Ok(client_location.get_client_neighbors(id).await?.into_iter() .map(move |client| { diff --git a/src/ship/packet/handler/quest.rs b/src/ship/packet/handler/quest.rs index 8df47fd..9df89b9 100644 --- a/src/ship/packet/handler/quest.rs +++ b/src/ship/packet/handler/quest.rs @@ -8,7 +8,6 @@ use crate::ship::location::{ClientLocation, ClientLocationError}; use crate::ship::packet::builder::quest; use libpso::util::array_to_utf8; -// TOOD: enum enum QuestFileType { Bin, Dat @@ -44,16 +43,6 @@ pub async fn send_quest_category_list(id: ClientId, rooms: &Rooms) -> Result, ShipError> { let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?; - /* - let mut 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))? - .write() - .await; - let qcl = quest::quest_category_list(&room.quests[rql.flag.clamp(0, (room.quests.len() - 1) as u32) as usize]); - room.set_quest_group(rql.flag as usize); - Ok(Box::new(vec![(id, SendShipPacket::QuestCategoryList(qcl))].into_iter())) - */ let rql = rql.clone(); rooms.with_mut(room_id, |room| Box::pin(async move { let qcl = quest::quest_category_list(&room.quests[rql.flag.clamp(0, (room.quests.len() - 1) as u32) as usize]); @@ -71,7 +60,7 @@ pub async fn select_quest_category(id: ClientId, rooms.with(room_id, |room| Box::pin(async move { let (_, category_quests) = room.quests[room.quest_group.value()].iter() .nth(menuselect.item as usize) - .ok_or(ShipError::InvalidQuestCategory(menuselect.item))?; + .ok_or_else(|| ShipError::InvalidQuestCategory(menuselect.item as u16))?; let ql = quest::quest_list(menuselect.item, category_quests); Ok(vec![(id, SendShipPacket::QuestOptionList(ql))]) @@ -88,12 +77,12 @@ pub async fn quest_detail(id: ClientId, rooms.with(room_id, |room| Box::pin(async move { let (_, category_quests) = room.quests[room.quest_group.value()].iter() .nth(questdetailrequest.category as usize) - .ok_or(ShipError::InvalidQuestCategory(questdetailrequest.category as u32))?; + .ok_or_else(|| ShipError::InvalidQuestCategory(questdetailrequest.category))?; let quest = category_quests.iter() .find(|q| { - q.id == questdetailrequest.quest as u16 - }).ok_or(ShipError::InvalidQuest(questdetailrequest.quest as u32))?; + q.id == questdetailrequest.quest + }).ok_or_else(|| ShipError::InvalidQuest(questdetailrequest.quest))?; let qd = quest::quest_detail(quest); @@ -116,13 +105,13 @@ pub async fn player_chose_quest(id: ClientId, Box::pin(async move { let quest = room.quests[room.quest_group.value()].iter() .nth(questmenuselect.category as usize) - .ok_or(ShipError::InvalidQuestCategory(questmenuselect.category as u32))? + .ok_or_else(|| ShipError::InvalidQuestCategory(questmenuselect.category))? .1 .iter() .find(|q| { - q.id == questmenuselect.quest as u16 + q.id == questmenuselect.quest }) - .ok_or(ShipError::InvalidQuest(questmenuselect.quest as u32))? + .ok_or_else(|| ShipError::InvalidQuest(questmenuselect.quest))? .clone(); let rare_monster_drops = room.rare_monster_table.clone(); @@ -138,11 +127,6 @@ pub async fn player_chose_quest(id: ClientId, client.done_loading_quest = false; })).await?; } - //area_clients.iter().for_each(|c| { - //if let Some(client) = clients.get_mut(&c.client) { - // client.done_loading_quest = false; - //} - //}); Ok(area_clients .into_iter() .flat_map(move |c| { @@ -150,53 +134,6 @@ pub async fn player_chose_quest(id: ClientId, }) .collect()) })}).await? - /* - let mut room = rooms.get(room_id.0) - .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? - .as_ref() - .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? - .write() - .await; - /* - let (_, category_quests) = room.quests[room.quest_group.value()].iter() - .nth(questmenuselect.category as usize) - .ok_or(ShipError::InvalidQuestCategory(questmenuselect.category as u32))?; - - let quest = category_quests.iter() - .find(|q| { - q.id == questmenuselect.quest as u16 -}).ok_or(ShipError::InvalidQuest(questmenuselect.quest as u32))? - .clone(); - */ - - let quest = room.quests[room.quest_group.value()].iter() - .nth(questmenuselect.category as usize) - .ok_or(ShipError::InvalidQuestCategory(questmenuselect.category as u32))? - .1 - .iter() - .find(|q| { - q.id == questmenuselect.quest as u16 -}) - .ok_or(ShipError::InvalidQuest(questmenuselect.quest as u32))? - .clone(); - - let rare_monster_drops = room.rare_monster_table.clone(); - room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone(), &rare_monster_drops); - room.map_areas = quest.map_areas.clone(); - - let bin = quest::quest_header(questmenuselect, &quest.bin_blob, "bin"); - let dat = quest::quest_header(questmenuselect, &quest.dat_blob, "dat"); - - let area_clients = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?; - area_clients.iter().for_each(|c| { - if let Some(client) = clients.get_mut(&c.client) { - client.done_loading_quest = false; -} -}); - Ok(Box::new(area_clients.into_iter().flat_map(move |c| { - vec![(c.client, SendShipPacket::QuestHeader(bin.clone())), (c.client, SendShipPacket::QuestHeader(dat.clone()))] -}))) - */ } pub async fn quest_file_request(id: ClientId, @@ -212,12 +149,12 @@ pub async fn quest_file_request(id: ClientId, let (category_id, quest_id, datatype) = parse_filename(&quest_file_request.filename)?; let (_, category_quests) = room.quests[room.quest_group.value()].iter() .nth(category_id as usize) - .ok_or(ShipError::InvalidQuestCategory(category_id as u32))?; + .ok_or_else(|| ShipError::InvalidQuestCategory(category_id))?; let quest = category_quests.iter() .find(|q| { - q.id == quest_id as u16 - }).ok_or(ShipError::InvalidQuest(quest_id as u32))?; + q.id == quest_id + }).ok_or_else(|| ShipError::InvalidQuest(quest_id))?; let blob = match datatype { QuestFileType::Bin => &quest.bin_blob, @@ -245,12 +182,12 @@ pub async fn quest_chunk_ack(id: ClientId, let (category_id, quest_id, datatype) = parse_filename(&quest_chunk_ack.filename)?; let (_, category_quests) = room.quests[room.quest_group.value()].iter() .nth(category_id as usize) - .ok_or(ShipError::InvalidQuestCategory(category_id as u32))?; + .ok_or_else(|| ShipError::InvalidQuestCategory(category_id))?; let quest = category_quests.iter() .find(|q| { q.id == quest_id - }).ok_or(ShipError::InvalidQuest(quest_id as u32))?; + }).ok_or_else(|| ShipError::InvalidQuest(quest_id))?; let blob = match datatype { QuestFileType::Bin => &quest.bin_blob, @@ -268,41 +205,6 @@ pub async fn quest_chunk_ack(id: ClientId, Ok(vec![(id, SendShipPacket::QuestChunk(qc))]) })).await? - - /* - let mut room = rooms.get(room_id.0) - .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? - .write() - .await - .as_ref() - .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; - - let (category_id, quest_id, datatype) = parse_filename(&quest_chunk_ack.filename)?; - let (_, category_quests) = room.quests[room.quest_group.value()].iter() - .nth(category_id as usize) - .ok_or(ShipError::InvalidQuestCategory(category_id as u32))?; - - let quest = category_quests.iter() - .find(|q| { - q.id == quest_id -}).ok_or(ShipError::InvalidQuest(quest_id as u32))?; - - let blob = match datatype { - QuestFileType::Bin => &quest.bin_blob, - QuestFileType::Dat => &quest.dat_blob, -}; - - let mut blob_cursor = Cursor::new(&**blob); - blob_cursor.seek(SeekFrom::Start((quest_chunk_ack.chunk_num as u64 + 1) * 0x400))?; - let mut subblob = [0u8; 0x400]; - let blob_length = blob_cursor.read(&mut subblob)?; - if blob_length == 0 { - return Ok(Box::new(None.into_iter())); -} - let qc = quest::quest_chunk(quest_chunk_ack.chunk_num + 1, quest_chunk_ack.filename, subblob, blob_length); - - Ok(Box::new(vec![(id, SendShipPacket::QuestChunk(qc))].into_iter())) - */ } pub async fn done_loading_quest(id: ClientId, @@ -315,14 +217,14 @@ pub async fn done_loading_quest(id: ClientId, let area_clients = client_location.get_all_clients_by_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?; let all_loaded = area_clients.iter() - .map(|client| async { - clients.with(client.client, |client| Box::pin(async move { - client.done_loading_quest - })) - }) + .map(|client| + clients.with(client.client, |client| Box::pin(async move { + client.done_loading_quest + })) + ) .collect::>() .all(|c| async move { - c.await.unwrap_or(false) + c.unwrap_or(false) }).await; if all_loaded { diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index ab3e79a..7653abc 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -1,16 +1,16 @@ +use std::convert::{TryFrom, Into}; +use futures::stream::StreamExt; + use libpso::packet::ship::*; use libpso::packet::messages::*; use crate::common::serverstate::ClientId; use crate::common::leveltable::LEVEL_TABLE; use crate::ship::ship::{SendShipPacket, ShipError, Clients}; use crate::ship::room::Rooms; -use crate::ship::location::{ClientLocation, RoomId, RoomLobby, ClientLocationError, GetAreaError}; +use crate::ship::location::{ClientLocation, RoomId, RoomLobby, GetAreaError}; use crate::ship::packet::builder; use crate::ship::room; use crate::ship::items::state::ItemState; -use std::convert::{TryFrom, Into}; -use async_std::sync::{Arc, RwLock}; -use futures::stream::{FuturesOrdered, StreamExt}; pub async fn create_room(id: ClientId, create_room: CreateRoom, @@ -39,7 +39,6 @@ pub async fn create_room(id: ClientId, let area_client = client_location.get_local_client(id).await?; let lobby_neighbors = client_location.get_client_neighbors(id).await?; - //let room_id = client_location.create_new_room(id).await.map_err(Into::::into)?; let room_id = client_location.create_new_room(id).await?; let room = clients.with(id, |client| { let mut item_state = item_state.clone(); @@ -66,7 +65,6 @@ pub async fn create_room(id: ClientId, Ok(result) } -// TODO: remove unwraps pub async fn room_name_request(id: ClientId, client_location: &ClientLocation, rooms: &Rooms) @@ -81,7 +79,6 @@ pub async fn room_name_request(id: ClientId, })).await }, RoomLobby::Lobby(_) => Err(GetAreaError::NotInRoom.into()) - //RoomLobby::Lobby(_) => Err(ShipError::ClientLocationError(GetAreaError::NotInRoom)) } } @@ -125,8 +122,7 @@ pub async fn join_room(id: ClientId, let original_room_clients = client_location.get_clients_in_room(room_id).await?; client_location.add_client_to_room(id, room_id).await?; let area_client = client_location.get_local_client(id).await?; - //let original_leader = client_location.get_area_leader(original_area).await.unwrap(); - let room_leader = client_location.get_room_leader(room_id).await.unwrap(); + let room_leader = client_location.get_room_leader(room_id).await?; clients.with(id, |client| { let mut item_state = item_state.clone(); @@ -138,14 +134,13 @@ pub async fn join_room(id: ClientId, let clients = clients.clone(); let client_location = client_location.clone(); Box::pin(async move { - builder::room::join_room(id, &clients, &client_location, room_id, &room).await + builder::room::join_room(id, &clients, &client_location, room_id, room).await })}).await??; let add_to = clients.with(id, |client| { let item_state = item_state.clone(); Box::pin(async move { builder::room::add_to_room(id, client, &area_client, &room_leader, &item_state, room_id).await })}).await??; - //let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), original_leader.local_client.id())); rooms.with_mut(room_id, |room| Box::pin(async move { room.bursting = true; @@ -161,7 +156,7 @@ pub async fn join_room(id: ClientId, async move { client_location.get_area_leader(original_area).await.ok().map(|leader| { let leave_lobby = SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())); - (c.client, leave_lobby.clone()) + (c.client, leave_lobby) }) } }) @@ -169,37 +164,6 @@ pub async fn join_room(id: ClientId, .await ) .collect()) - - /* - 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())); - result.extend(original_neighbors.into_iter() - .map(move |c| (c.client, leave_lobby.clone()))) - } - */ - - //Ok(result) - /* - - if let Some(room) = &mut *rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.write().await { - let mut result: Box + Send> = Box::new( - vec![(id, SendShipPacket::JoinRoom(join_room))] - .into_iter() - .chain(original_room_clients.into_iter() - .map(move |c| (c.client, SendShipPacket::AddToRoom(add_to.clone()))) - )); - - 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())); - result = Box::new(result.chain(original_neighbors.into_iter() - .map(move |c| (c.client, leave_lobby.clone())))) - } - - Ok(result.collect()) - } else { - Ok(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Game is no longer active".into())))]) - } - */ } pub async fn done_bursting(id: ClientId, @@ -230,7 +194,6 @@ pub async fn request_room_list(id: ClientId, client_location: &ClientLocation, rooms: &Rooms) -> Vec<(ClientId, SendShipPacket)> { - //let active_room_list = futures::stream::iter(rooms.iter()) let active_room_list = rooms.stream() .enumerate() .filter_map(|(i, r)| async move { @@ -270,17 +233,16 @@ pub async fn request_room_list(id: ClientId, pub async fn cool_62(id: ClientId, cool_62: Like62ButCooler, client_location: &ClientLocation) - -> Vec<(ClientId, SendShipPacket)> { + -> Result, ShipError> { let target = cool_62.flag as u8; let cool_62 = cool_62.clone(); - client_location + Ok(client_location .get_client_neighbors(id) - .await - .unwrap() + .await? .into_iter() .filter(move |client| client.local_client.id() == target) .map(move |client| { (client.client, SendShipPacket::Like62ButCooler(cool_62.clone())) }) - .collect() + .collect()) } diff --git a/src/ship/packet/handler/ship.rs b/src/ship/packet/handler/ship.rs index b9505f3..b393e61 100644 --- a/src/ship/packet/handler/ship.rs +++ b/src/ship/packet/handler/ship.rs @@ -15,7 +15,7 @@ pub fn block_list(id: ClientId, shipname: &str, num_blocks: usize) -> Vec<(Clien pub fn selected_ship(id: ClientId, menuselect: MenuSelect, ship_list: &[Ship]) -> Result, ShipError> { - let ship = ship_list.get(menuselect.item as usize).ok_or(ShipError::InvalidShip(menuselect.item as usize))?; + let ship = ship_list.get(menuselect.item as usize).ok_or_else(|| ShipError::InvalidShip(menuselect.item as usize))?; let ip = u32::from_ne_bytes(ship.ip.octets()); Ok(vec![(id, SendShipPacket::RedirectClient(RedirectClient::new(ip, ship.port)))]) } diff --git a/src/ship/packet/handler/trade.rs b/src/ship/packet/handler/trade.rs index b7b6cd5..f369f96 100644 --- a/src/ship/packet/handler/trade.rs +++ b/src/ship/packet/handler/trade.rs @@ -154,7 +154,7 @@ pub async fn trade_request(id: ClientId, this.meseta += amount as usize; } else { - let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?; + let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?; match &item.item { InventoryItemDetail::Individual(_) => { @@ -192,7 +192,7 @@ pub async fn trade_request(id: ClientId, this.meseta -= amount as usize; } else { - let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?; + let item = inventory.get_by_client_id(&ClientItemId(item_id)).ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?; match &item.item { InventoryItemDetail::Individual(_) => { @@ -207,9 +207,9 @@ pub async fn trade_request(id: ClientId, }) .ok_or(TradeError::InvalidItemId(ClientItemId(item_id)))?; - match this.items[trade_item_index].stacked().ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1.cmp(&(amount as usize)) { + match this.items[trade_item_index].stacked().ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1.cmp(&(amount as usize)) { std::cmp::Ordering::Greater => { - *this.items[trade_item_index].stacked_mut().ok_or(ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1 -= amount as usize; + *this.items[trade_item_index].stacked_mut().ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item_id)))?.1 -= amount as usize; }, std::cmp::Ordering::Equal => { this.items.remove(trade_item_index); @@ -314,7 +314,7 @@ async fn inner_items_to_trade(id: ClientId, Ok::<_, ShipError>((this, other_inventory)) })}).await??; - if items_to_trade.count as usize != (this.items.len() + (if this.meseta != 0 { 1 } else { 0 })) { + if items_to_trade.count as usize != (this.items.len() + usize::from(this.meseta != 0)) { return Err(TradeError::MismatchedTradeItems.into()) } @@ -342,7 +342,7 @@ async fn inner_items_to_trade(id: ClientId, } else { let real_item = this_inventory.get_by_client_id(&ClientItemId(item.item_id)) - .ok_or(ItemStateError::InvalidItemId(ClientItemId(item.item_id)))?; + .ok_or_else(|| ItemStateError::InvalidItemId(ClientItemId(item.item_id)))?; let real_trade_item = this.items .iter() .find(|i| i.item_id() == ClientItemId(item.item_id)) diff --git a/src/ship/room.rs b/src/ship/room.rs index 44b4e42..9758064 100644 --- a/src/ship/room.rs +++ b/src/ship/room.rs @@ -1,16 +1,13 @@ use std::collections::HashMap; use std::convert::{From, Into, TryFrom, TryInto}; use std::path::PathBuf; - -use async_std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use std::future::Future; -use futures::stream::{Stream, StreamExt, FuturesOrdered}; +use async_std::sync::{Arc, RwLock, RwLockReadGuard}; use futures::future::BoxFuture; +use futures::stream::{FuturesOrdered, Stream}; use thiserror::Error; -use std::ops::Deref; - use rand::Rng; + use crate::ship::map::Maps; use crate::ship::drops::DropTable; use crate::entity::character::SectionID; @@ -19,8 +16,7 @@ use crate::ship::map::area::MapAreaLookup; use crate::ship::map::enemy::RareMonsterAppearTable; use crate::ship::quests; use crate::ship::ship::ShipError; - -use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError, RoomId}; +use crate::ship::location::{MAX_ROOMS, RoomId}; #[derive(Clone)] @@ -32,28 +28,11 @@ impl Default for Rooms { } } - -/* -#[derive(escher::Rebindable)] -struct BorrowedRoom<'a> { - lock: RwLockReadGuard<'a, Option>, - room: &'a Option, -} - -impl<'a> std::ops::Deref for BorrowedRoom<'a> { - type Target = RoomState; - fn deref(&self) -> &Self::Target { - &self.room - } -} -*/ - - impl Rooms { pub async fn add(&self, room_id: RoomId, room: RoomState) -> Result<(), ShipError> { *self.0 .get(room_id.0) - .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? .write() .await = Some(room); Ok(()) @@ -86,7 +65,7 @@ impl Rooms { { let room = self.0 .get(room_id.0) - .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? .read() .await; if let Some(room) = room.as_ref() { @@ -104,7 +83,7 @@ impl Rooms { { let mut room = self.0 .get(room_id.0) - .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? .write() .await; @@ -116,7 +95,7 @@ impl Rooms { } } - pub async fn get<'a>(&'a self, room_id: RoomId) -> RwLockReadGuard<'a, Option> { + pub async fn get(&self, room_id: RoomId) -> RwLockReadGuard> { self.0 .get(room_id.0) .unwrap() @@ -124,7 +103,7 @@ impl Rooms { .await } - pub fn stream<'a>(&'a self) -> impl Stream>> + 'a { + pub fn stream(&self) -> impl Stream>> { self.0 .iter() .map(|room| async move { @@ -136,11 +115,6 @@ impl Rooms { } } - - - - - #[derive(Debug, Error)] #[error("")] pub enum RoomCreationError { diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 77f762d..4dcd8c7 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -9,7 +9,7 @@ use rand::Rng; use thiserror::Error; use libpso::packet::ship::*; -use libpso::packet::login::{RedirectClient, Login, LoginResponse, Session, ShipList}; +use libpso::packet::login::{RedirectClient, Login, LoginResponse, ShipList}; use libpso::packet::messages::*; use libpso::{PacketParseError, PSOPacket}; use libpso::crypto::bb::PSOBBCipher; @@ -24,17 +24,15 @@ use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, Lo use crate::login::character::SHIP_MENU_ID; use crate::entity::gateway::{EntityGateway, GatewayError}; -use crate::entity::account::{UserAccountEntity, UserSettingsEntity}; -use crate::entity::character::{CharacterEntity, SectionID}; -use crate::entity::item; +use crate::entity::character::SectionID; -use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError, RoomId}; +use crate::ship::location::{ClientLocation, RoomLobby, ClientLocationError, RoomId}; use crate::ship::items; use crate::ship::room; -use crate::ship::map::{MapsError, MapAreaError, MapArea}; +use crate::ship::map::{MapsError, MapAreaError}; use crate::ship::packet::handler; -use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem}; +use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop}; use crate::ship::trade::TradeState; // TODO: remove once stuff settles down @@ -56,16 +54,7 @@ pub enum ShipError { #[error("too many clients")] TooManyClients, #[error("client error location {0}")] - //ClientLocationError(#[from] ClientLocationError), ClientLocationError(ClientLocationError), - /* - #[error("get neighbor error {0}")] - GetNeighborError(#[from] GetNeighborError), - #[error("get clients error {0}")] - GetClientsError(#[from] GetClientsError), - #[error("get area error {0}")] - GetAreaError(#[from] GetAreaError), - */ #[error("maps error {0}")] MapsError(#[from] MapsError), #[error("map area error {0}")] @@ -89,9 +78,9 @@ pub enum ShipError { #[error("box already dropped item {0} {1}")] BoxAlreadyDroppedItem(ClientId, u16), #[error("invalid quest category {0}")] - InvalidQuestCategory(u32), + InvalidQuestCategory(u16), #[error("invalid quest {0}")] - InvalidQuest(u32), + InvalidQuest(u16), #[error("invalid quest filename {0}")] InvalidQuestFilename(String), #[error("io error {0}")] @@ -118,24 +107,10 @@ pub enum ShipError { MessageError(#[from] crate::ship::packet::handler::direct_message::MessageError), #[error("room creation error {0}")] RoomCreationError(#[from] room::RoomCreationError), + #[error("channel send error {0}")] + SendError(#[from] async_std::channel::SendError), } -/* -impl From for ShipError { - fn from(other: &ClientLocationError) -> ShipError { - - } -} - */ - -/* -impl> Into for I { - fn into(other: I) -> ShipError { - ShipError::ClientLocationError(other.into()) - } -} - */ - impl> From for ShipError { fn from(other: I) -> ShipError { ShipError::ClientLocationError(other.into()) @@ -420,45 +395,23 @@ impl ShipServerStateBuilder { } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct Block { client_location: ClientLocation, pub rooms: room::Rooms, } -impl Default for Block { - fn default() -> Block { - Block { - client_location: ClientLocation::default(), - rooms: room::Rooms::default(), - //rooms: core::array::from_fn(|_| Arc::new(RwLock::new(None))), - } - } -} - -/* -impl Block { - fn with(&self, func: F) -> T - where - T: Send, - F: FnOnce(&Block) -> T, - { - func(self) - } -} -*/ - #[derive(Clone)] pub struct Blocks(pub Vec); impl Blocks { - async fn from_client(&mut self, id: ClientId, clients: &Clients) -> Result<&mut Block, ShipError> { + async fn get_from_client(&mut self, id: ClientId, clients: &Clients) -> Result<&mut Block, ShipError> { let block = clients.with(id, |client| Box::pin(async move { client.block })).await?; self.0 .get_mut(block) - .ok_or(ShipError::InvalidBlock(block)) + .ok_or_else(|| ShipError::InvalidBlock(block)) } } @@ -477,7 +430,6 @@ pub struct ShipServerState { auth_token: AuthToken, ship_list: Vec, - //shipgate_sender: Option>, shipgate_sender: Option>, trades: TradeState, } @@ -490,42 +442,42 @@ impl ShipServerState { async fn message(&mut self, id: ClientId, msg: Message) -> Result, anyhow::Error> { Ok(match msg.msg { GameMessage::RequestExp(request_exp) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms).await? }, GameMessage::PlayerDropItem(player_drop_item) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms, &mut self.item_state).await? }, GameMessage::DropCoordinates(drop_coordinates) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &mut self.clients, &block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::message::drop_coordinates(id, drop_coordinates, &block.client_location, &self.clients, &block.rooms).await? }, GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::message::no_longer_has_item(id, no_longer_has_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::message::no_longer_has_item(id, no_longer_has_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? }, GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) | GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) | GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) | GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::message::update_player_position(id, msg, &mut self.clients, &block.client_location, &block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::message::update_player_position(id, msg, &self.clients, &block.client_location, &block.rooms).await? }, GameMessage::ChargeAttack(charge_attack) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::message::charge_attack(id, charge_attack, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::message::charge_attack(id, charge_attack, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? }, GameMessage::PlayerUseItem(player_use_item) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::message::player_uses_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::message::player_uses_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? }, GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? }, GameMessage::PlayerFeedMag(player_feed_mag) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::message::player_feed_mag(id, player_feed_mag, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? }, GameMessage::PlayerEquipItem(player_equip_item) => { @@ -538,11 +490,11 @@ impl ShipServerState { handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &self.clients, &mut self.item_state).await? }, GameMessage::PlayerSoldItem(player_sold_item) => { - handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_state).await? + handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await? }, _ => { let cmsg = msg.clone(); - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; block.client_location.get_client_neighbors(id).await.unwrap().into_iter() .map(move |client| { (client.client, SendShipPacket::Message(cmsg.clone())) @@ -554,7 +506,7 @@ impl ShipServerState { async fn direct_message(&mut self, id: ClientId, msg: DirectMessage) -> Result, anyhow::Error> { let target = msg.flag; - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; Ok(match msg.msg { GameMessage::GuildcardSend(guildcard_send) => { handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients).await? @@ -575,7 +527,7 @@ impl ShipServerState { handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? }, GameMessage::ShopRequest(shop_request) => { - handler::direct_message::shop_request(id, shop_request, &block.client_location, &self.clients, &block.rooms, &mut self.shops).await? + handler::direct_message::shop_request(id, shop_request, &block.client_location, &self.clients, &block.rooms, &self.shops).await? }, GameMessage::BuyItem(buy_item) => { handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? @@ -630,11 +582,6 @@ impl ServerState for ShipServerState { })).await { self.entity_gateway.set_character_playtime(&char_id, char_playtime).await?; } - /* - if let Some(client) = self.clients.get_mut(&id) { - client.update_playtime(); - self.entity_gateway.set_character_playtime(&client.character.id, client.character.playtime).await?; - }*/ Ok(match pkt { RecvShipPacket::Login(login) => { @@ -645,14 +592,14 @@ impl ServerState for ShipServerState { .collect() }, RecvShipPacket::QuestDetailRequest(questdetailrequest) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; match questdetailrequest.menu { - QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &block.client_location, &mut block.rooms).await?, + QUEST_SELECT_MENU_ID => handler::quest::quest_detail(id, questdetailrequest, &block.client_location, &block.rooms).await?, _ => unreachable!(), } }, RecvShipPacket::MenuSelect(menuselect) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; match menuselect.menu { SHIP_MENU_ID => { let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).await.into_iter().into_iter().flatten(); @@ -664,73 +611,39 @@ impl ServerState for ShipServerState { let select_block = handler::lobby::block_selected(id, menuselect, &self.clients, &self.item_state).await?.into_iter(); leave_lobby.chain(select_block).collect() } - ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &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).await?, + ROOM_MENU_ID => handler::room::join_room(id, menuselect, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms).await?, + QUEST_CATEGORY_MENU_ID => handler::quest::select_quest_category(id, menuselect, &block.client_location, &block.rooms).await?, _ => unreachable!(), } }, RecvShipPacket::QuestMenuSelect(questmenuselect) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::quest::player_chose_quest(id, questmenuselect, &mut self.clients, &block.client_location, &mut block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::quest::player_chose_quest(id, questmenuselect, &self.clients, &block.client_location, &block.rooms).await? }, RecvShipPacket::MenuDetail(menudetail) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients, &mut block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::lobby::get_room_tab_info(id, menudetail, &mut block.client_location, &self.clients).await? }, RecvShipPacket::RoomPasswordReq(room_password_req) => { - let block = self.blocks.from_client(id, &self.clients).await?; - - /* - let password = room_password_req.password; - let correct_password = block.rooms.with(RoomId(room_password_req.item as usize), |room| Box::pin(async move { - password == room.password - })).await?; - */ + let block = self.blocks.get_from_client(id, &self.clients).await?; let room_password = block.rooms.with(RoomId(room_password_req.item as usize), |room| Box::pin(async move { room.password })).await?; - /* - let correct_password = room_password_req.password == block.rooms - .get(RoomId(room_password_req.item as usize)) - .await - .map(|room| room.password) - .unwrap_or_else(false); - */ - - //if correct_password { if room_password_req.password == room_password { let menuselect = MenuSelect { menu: room_password_req.menu, 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).await? + handler::room::join_room(id, menuselect, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms).await? } else { vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))] } - - /* - if room_password_req.password == block.rooms[room_password_req.item as usize] - .read() - .await - .as_ref() - .ok_or(ShipError::InvalidRoom(room_password_req.item))? - .password { - let menuselect = MenuSelect { - menu: room_password_req.menu, - 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).await? - } - else { - Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("Incorrect password".into())))].into_iter()) - } - */ }, RecvShipPacket::CharData(chardata) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::lobby::send_player_to_lobby(id, chardata, &mut block.client_location, &self.clients, &self.item_state).await? }, RecvShipPacket::Message(msg) => { @@ -740,65 +653,65 @@ impl ServerState for ShipServerState { self.direct_message(id, msg).await? }, RecvShipPacket::PlayerChat(msg) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::communication::player_chat(id, msg, &block.client_location, &self.clients).await? }, RecvShipPacket::CreateRoom(create_room) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_state, &mut block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::room::create_room(id, create_room, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms).await? }, RecvShipPacket::RoomNameRequest(_req) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::room::room_name_request(id, &block.client_location, &block.rooms).await? }, RecvShipPacket::UpdateConfig(pkt) => { - handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await? + handler::settings::update_config(id, pkt, &self.clients, &mut self.entity_gateway).await? }, RecvShipPacket::ViewInfoboardRequest(_pkt) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::communication::request_infoboard(id, &block.client_location, &self.clients).await? }, RecvShipPacket::WriteInfoboard(pkt) => { handler::communication::write_infoboard(id, pkt, &self.clients, &mut self.entity_gateway).await? }, RecvShipPacket::RoomListRequest(_req) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::room::request_room_list(id, &block.client_location, &block.rooms).await }, RecvShipPacket::Like62ButCooler(cool62) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::room::cool_62(id, cool62, &block.client_location).await + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::room::cool_62(id, cool62, &block.client_location).await? }, RecvShipPacket::ClientCharacterData(_) => { // TOOD: validate this in some way? Vec::new() }, RecvShipPacket::DoneBursting(_) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::room::done_bursting(id, &block.client_location, &mut block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::room::done_bursting(id, &block.client_location, &block.rooms).await? }, RecvShipPacket::DoneBursting2(_) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::room::done_bursting(id, &block.client_location, &mut block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::room::done_bursting(id, &block.client_location, &block.rooms).await? }, RecvShipPacket::LobbySelect(pkt) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &mut block.rooms, &mut self.entity_gateway).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &block.rooms, &mut self.entity_gateway).await? }, RecvShipPacket::RequestQuestList(rql) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::quest::send_quest_category_list(id, rql, &block.client_location, &mut block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::quest::send_quest_category_list(id, rql, &block.client_location, &block.rooms).await? }, RecvShipPacket::QuestFileRequest(quest_file_request) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::quest::quest_file_request(id, quest_file_request, &block.client_location, &mut block.rooms).await? }, RecvShipPacket::QuestChunkAck(quest_chunk_ack) => { - let block = self.blocks.from_client(id, &self.clients).await?; - handler::quest::quest_chunk_ack(id, quest_chunk_ack, &block.client_location, &mut block.rooms).await? + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::quest::quest_chunk_ack(id, quest_chunk_ack, &block.client_location, &block.rooms).await? }, RecvShipPacket::DoneLoadingQuest(_) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::quest::done_loading_quest(id, &self.clients, &block.client_location).await? }, RecvShipPacket::FullCharacterData(_full_character_data) => { @@ -814,11 +727,11 @@ impl ServerState for ShipServerState { handler::ship::block_list(id, &self.name, self.blocks.0.len()) }, RecvShipPacket::ItemsToTrade(items_to_trade) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::trade::items_to_trade(id, items_to_trade, &block.client_location, &self.clients, &mut self.item_state, &mut self.trades).await? }, RecvShipPacket::TradeConfirmed(_) => { - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; handler::trade::trade_confirmed(id, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state, &mut self.trades).await? }, RecvShipPacket::KeyboardConfig(keyboard_config) => { @@ -832,7 +745,7 @@ impl ServerState for ShipServerState { async fn on_disconnect(&mut self, id: ClientId) -> Result, anyhow::Error> { //let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; - let block = self.blocks.from_client(id, &self.clients).await?; + let block = self.blocks.get_from_client(id, &self.clients).await?; let area_client = block.client_location.get_local_client(id).await?; let neighbors = block.client_location.get_client_neighbors(id).await?; @@ -886,7 +799,7 @@ impl InterserverActor for ShipServerState { async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { vec![ (id, ShipMessage::Authenticate(self.auth_token.clone())), - (id, ShipMessage::NewShip(Ship { + (id, ShipMessage::NewShip(Ship { name: self.name.clone(), ip: self.ip, port: self.port, @@ -896,7 +809,7 @@ impl InterserverActor for ShipServerState { ] } - async fn on_action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result, Self::Error> { + async fn on_action(&mut self, _id: ServerId, msg: Self::RecvMessage) -> Result, Self::Error> { match msg { LoginMessage::SendMail{..} => { Ok(Vec::new()) diff --git a/src/ship/shops/armor.rs b/src/ship/shops/armor.rs index b85fe12..d1d8b47 100644 --- a/src/ship/shops/armor.rs +++ b/src/ship/shops/armor.rs @@ -78,7 +78,7 @@ impl ShopItem for ArmorShopItem { armor: frame.armor, dfp: 0, evp: 0, - slots: frame.slots as u8, + slots: frame.slots, }) }, ArmorShopItem::Barrier(barrier) => { diff --git a/tests/test_exp_gain.rs b/tests/test_exp_gain.rs index 6821ad0..4584571 100644 --- a/tests/test_exp_gain.rs +++ b/tests/test_exp_gain.rs @@ -49,7 +49,7 @@ async fn test_character_gains_exp() { ship.clients.with(ClientId(1), |client| Box::pin(async move { assert!(exp == client.character.exp); - })).await; + })).await.unwrap(); } #[async_std::test] @@ -133,9 +133,9 @@ async fn test_character_levels_up_multiple_times() { assert!(matches!(levelup_pkt[1].1, SendShipPacket::Message(Message {msg: GameMessage::PlayerLevelUp(PlayerLevelUp {lvl: 8, ..})}))); - let c1 = ship.clients.with(ClientId(1), |client| Box::pin(async move { + ship.clients.with(ClientId(1), |client| Box::pin(async move { assert!(exp == client.character.exp); - })).await; + })).await.unwrap(); } #[async_std::test]