From 8d49c50cc5a14859e2ccdc4278dfb3115be5c466 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 2 Jun 2020 18:51:18 -0600 Subject: [PATCH] async EntityGateway --- Cargo.toml | 3 +- src/bin/main.rs | 85 +++++++-------- src/common/mainloop.rs | 2 +- src/common/serverstate.rs | 9 +- src/entity/gateway/entitygateway.rs | 29 ++--- src/entity/gateway/inmemory.rs | 41 ++++---- src/login/character.rs | 57 +++++----- src/login/login.rs | 13 +-- src/patch/patch.rs | 3 +- src/ship/drops/mod.rs | 1 + src/ship/items.rs | 91 ++++++++++------ src/ship/packet/handler/auth.rs | 10 +- src/ship/packet/handler/communication.rs | 4 +- src/ship/packet/handler/direct_message.rs | 123 +++++++++++++++++----- src/ship/packet/handler/lobby.rs | 4 +- src/ship/packet/handler/message.rs | 22 ++-- src/ship/packet/handler/settings.rs | 4 +- src/ship/ship.rs | 29 ++--- 18 files changed, 320 insertions(+), 210 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 577f89f..268e8ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] libpso = { git = "http://git.sharnoth.com/jake/libpso" } async-std = { version = "1.5.0", features = ["unstable"] } -futures = "0.3.4" +futures = "0.3.5" rand = "0.7.3" rand_chacha = "0.2.2" mio = "0.6" @@ -27,4 +27,5 @@ enum-utils = "0.1.2" derive_more = { version = "0.99.3", features = ["display"]} thiserror = "1.0.15" ages-prs = "0.1" +async-trait = "0.1.31" diff --git a/src/bin/main.rs b/src/bin/main.rs index a55a86c..cf6f702 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -44,52 +44,53 @@ fn setup_logger() { fn main() { setup_logger(); - let mut entity_gateway = InMemoryGateway::new(); + async_std::task::block_on(async move { + let mut entity_gateway = InMemoryGateway::new(); - for i in 0..5 { - let fake_user = NewUserAccountEntity { - username: if i == 0 { "hi".to_string() } else { format!("hi{}", i+1) }, - password: bcrypt::hash("qwer", 5).unwrap(), - guildcard: i + 1, - team_id: None, - banned: false, - muted_until: SystemTime::now(), - created_at: SystemTime::now(), - flags: 0, - }; - let fake_user = entity_gateway.create_user(fake_user).unwrap(); - entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)); - let mut character = NewCharacterEntity::new(fake_user.id); - character.name = format!("Test Char {}", i*2); - entity_gateway.create_character(character); - let mut character = NewCharacterEntity::new(fake_user.id); - character.slot = 2; - character.name = "no progress".into(); - character.exp = 80000000; - let character = entity_gateway.create_character(character).unwrap(); + for i in 0..5 { + let fake_user = NewUserAccountEntity { + username: if i == 0 { "hi".to_string() } else { format!("hi{}", i+1) }, + password: bcrypt::hash("qwer", 5).unwrap(), + guildcard: i + 1, + team_id: None, + banned: false, + muted_until: SystemTime::now(), + created_at: SystemTime::now(), + flags: 0, + }; + let fake_user = entity_gateway.create_user(fake_user).await.unwrap(); + entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await; + let mut character = NewCharacterEntity::new(fake_user.id); + character.name = format!("Test Char {}", i*2); + entity_gateway.create_character(character).await; + let mut character = NewCharacterEntity::new(fake_user.id); + character.slot = 2; + character.name = "no progress".into(); + character.exp = 80000000; + character.meseta = 999999; + let character = entity_gateway.create_character(character).await.unwrap(); - entity_gateway.create_item( - NewItemEntity { - item: ItemDetail::Weapon( - item::weapon::Weapon { - weapon: item::weapon::WeaponType::Raygun, - grind: 5, - special: Some(item::weapon::WeaponSpecial::Hell), - attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}), - Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}), - None,], - tekked: true, + entity_gateway.create_item( + NewItemEntity { + item: ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Raygun, + grind: 5, + special: Some(item::weapon::WeaponSpecial::Hell), + attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 40}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}), + None,], + tekked: false, + } + ), + location: ItemLocation::Inventory { + character_id: character.id, + slot: 0, + equipped: true, } - ), - location: ItemLocation::Inventory { - character_id: character.id, - slot: 0, - equipped: true, - } - }); - } + }).await; + } - async_std::task::block_on(async move { let patch = async_std::task::spawn(async { info!("[patch] starting server"); let patch_config = load_config(); diff --git a/src/common/mainloop.rs b/src/common/mainloop.rs index 3f16227..38a9c50 100644 --- a/src/common/mainloop.rs +++ b/src/common/mainloop.rs @@ -165,7 +165,7 @@ async fn server_state_loop(mut state: STATE, } }, ClientAction::Packet(client_id, pkt) => { - let pkts = state.handle(client_id, &pkt); + let pkts = state.handle(client_id, &pkt).await; match pkts { Ok(pkts) => { for (client_id, pkt) in pkts { diff --git a/src/common/serverstate.rs b/src/common/serverstate.rs index 2bf0dad..8417f7a 100644 --- a/src/common/serverstate.rs +++ b/src/common/serverstate.rs @@ -9,22 +9,23 @@ pub enum OnConnect { Cipher((Box, Box)), } -pub trait RecvServerPacket: Sized { +pub trait RecvServerPacket: Sized + Sync { fn from_bytes(data: &[u8]) -> Result; } -pub trait SendServerPacket: Sized { +pub trait SendServerPacket: Sized + Sync { fn as_bytes(&self) -> Vec; } +#[async_trait::async_trait] pub trait ServerState { type SendPacket: SendServerPacket; type RecvPacket: RecvServerPacket; type PacketError; fn on_connect(&mut self, id: ClientId) -> Vec>; - fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) - -> Result + Send>, Self::PacketError>; + async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) + -> Result + Send>, Self::PacketError>; fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>; } diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index 9e0bd42..fda3a9c 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -2,28 +2,29 @@ use crate::entity::account::*; use crate::entity::character::*; use crate::entity::item::*; -pub trait EntityGateway { - fn create_user(&mut self, _user: NewUserAccountEntity) -> Option { +#[async_trait::async_trait] +pub trait EntityGateway: Send + Sync + Clone { + async fn create_user(&mut self, _user: NewUserAccountEntity) -> Option { unimplemented!() } - fn get_user_by_id(&self, _id: UserAccountId) -> Option { + async fn get_user_by_id(&self, _id: UserAccountId) -> Option { unimplemented!(); } - fn get_user_by_name(&self, _username: String) -> Option { + async fn get_user_by_name(&self, _username: String) -> Option { unimplemented!(); } - fn save_user(&mut self, _user: &UserAccountEntity) { + async fn save_user(&mut self, _user: &UserAccountEntity) { unimplemented!(); } - fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Option { + async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Option { unimplemented!(); } - fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option { + async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option { unimplemented!(); } @@ -31,31 +32,31 @@ pub trait EntityGateway { unimplemented!(); } - fn create_character(&mut self, _char: NewCharacterEntity) -> Option { + async fn create_character(&mut self, _char: NewCharacterEntity) -> Option { unimplemented!(); } - fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option; 4] { + async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option; 4] { unimplemented!(); } - fn save_character(&mut self, _char: &CharacterEntity) { + async fn save_character(&mut self, _char: &CharacterEntity) { unimplemented!(); } - fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity { + async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity { unimplemented!(); } - fn create_item(&mut self, _item: NewItemEntity) -> Option { + async fn create_item(&mut self, _item: NewItemEntity) -> Option { unimplemented!(); } - fn save_item(&mut self, _item: &ItemEntity) { + async fn save_item(&mut self, _item: &ItemEntity) { unimplemented!(); } - fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec { + async fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec { unimplemented!(); } } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 1e10dad..fbaafd1 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -26,8 +26,9 @@ impl InMemoryGateway { } } +#[async_trait::async_trait] impl EntityGateway for InMemoryGateway { - fn create_user(&mut self, user: NewUserAccountEntity) -> Option { + async fn create_user(&mut self, user: NewUserAccountEntity) -> Option { let mut users = self.users.lock().unwrap(); let id = users .iter() @@ -48,12 +49,12 @@ impl EntityGateway for InMemoryGateway { Some(user) } - fn get_user_by_id(&self, id: UserAccountId) -> Option { + async fn get_user_by_id(&self, id: UserAccountId) -> Option { let users = self.users.lock().unwrap(); users.get(&id).map(|k| k.clone()) } - fn get_user_by_name(&self, username: String) -> Option { + async fn get_user_by_name(&self, username: String) -> Option { let users = self.users.lock().unwrap(); users .iter() @@ -61,20 +62,12 @@ impl EntityGateway for InMemoryGateway { .map(|(_, k)| k.clone()) } - fn save_user(&mut self, user: &UserAccountEntity) { + async fn save_user(&mut self, user: &UserAccountEntity) { let mut users = self.users.lock().unwrap(); users.insert(user.id, user.clone()); } - fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option { - let user_settings = self.user_settings.lock().unwrap(); - user_settings - .iter() - .find(|(_, k)| k.user_id == user.id) - .map(|(_, k)| k.clone()) - } - - fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option { + async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option { let mut user_settings = self.user_settings.lock().unwrap(); let id = user_settings .iter() @@ -89,7 +82,15 @@ impl EntityGateway for InMemoryGateway { Some(new_settings) } - fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option; 4] { + async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option { + let user_settings = self.user_settings.lock().unwrap(); + user_settings + .iter() + .find(|(_, k)| k.user_id == user.id) + .map(|(_, k)| k.clone()) + } + + async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option; 4] { let characters = self.characters.lock().unwrap(); let mut chars = [None; 4]; characters @@ -99,7 +100,7 @@ impl EntityGateway for InMemoryGateway { chars } - fn create_character(&mut self, character: NewCharacterEntity) -> Option { + async fn create_character(&mut self, character: NewCharacterEntity) -> Option { let mut characters = self.characters.lock().unwrap(); let id = characters .iter() @@ -126,16 +127,16 @@ impl EntityGateway for InMemoryGateway { Some(new_character) } - fn save_character(&mut self, char: &CharacterEntity) { + async fn save_character(&mut self, char: &CharacterEntity) { let mut characters = self.characters.lock().unwrap(); characters.insert(char.id, char.clone()); } - fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity { + async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity { GuildCardDataEntity::new(user.id) } - fn create_item(&mut self, item: NewItemEntity) -> Option { + async fn create_item(&mut self, item: NewItemEntity) -> Option { let mut items = self.items.lock().unwrap(); let id = items .iter() @@ -150,12 +151,12 @@ impl EntityGateway for InMemoryGateway { Some(new_item) } - fn save_item(&mut self, item: &ItemEntity) { + async fn save_item(&mut self, item: &ItemEntity) { let mut items = self.items.lock().unwrap(); items.insert(item.id, item.clone()); } - fn get_items_by_character(&self, character: &CharacterEntity) -> Vec { + async fn get_items_by_character(&self, character: &CharacterEntity) -> Vec { let items = self.items.lock().unwrap(); items .iter() diff --git a/src/login/character.rs b/src/login/character.rs index 67b6293..eeacf94 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -190,7 +190,7 @@ pub struct CharacterServerState { } -fn new_character(entity_gateway: &mut EG, user: &UserAccountEntity, preview: &CharacterPreview) { +async fn new_character(entity_gateway: &mut EG, user: &UserAccountEntity, preview: &CharacterPreview) { //let mut character = entity_gateway.new_character_by_user(&user); //new_character_from_preview(&mut char, preview); let mut character = new_character_from_preview(user, preview); @@ -201,7 +201,7 @@ fn new_character(entity_gateway: &mut EG, user: &UserAccountE character.meseta = 300; - let character = entity_gateway.create_character(character).unwrap(); + let character = entity_gateway.create_character(character).await.unwrap(); let new_weapon = match character.char_class { CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => item::weapon::WeaponType::Saber, @@ -224,7 +224,7 @@ fn new_character(entity_gateway: &mut EG, user: &UserAccountE character_id: character.id, slot: 0, equipped: true, - }}); + }}).await; entity_gateway.create_item( NewItemEntity { @@ -239,7 +239,7 @@ fn new_character(entity_gateway: &mut EG, user: &UserAccountE character_id: character.id, slot: 1, equipped: true, - }}); + }}).await; entity_gateway.create_item( NewItemEntity { @@ -259,7 +259,7 @@ fn new_character(entity_gateway: &mut EG, user: &UserAccountE character_id: character.id, slot: 2, equipped: true, - }}); + }}).await; for _ in 0..4 { entity_gateway.create_item( @@ -272,7 +272,7 @@ fn new_character(entity_gateway: &mut EG, user: &UserAccountE character_id: character.id, slot: 3, equipped: false, - }}); + }}).await; entity_gateway.create_item( NewItemEntity { item: ItemDetail::Tool ( @@ -283,7 +283,7 @@ fn new_character(entity_gateway: &mut EG, user: &UserAccountE character_id: character.id, slot: 4, equipped: false, - }}); + }}).await; } } @@ -307,9 +307,9 @@ impl CharacterServerState { } } - fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, CharacterError> { + async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; - Ok(match get_login_status(&self.entity_gateway, pkt) { + Ok(match get_login_status(&self.entity_gateway, pkt).await { Ok(user) => { let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); response.guildcard = user.guildcard; @@ -337,16 +337,16 @@ impl CharacterServerState { ]) } - fn get_settings(&mut self, id: ClientId) -> Result, CharacterError> { + async fn get_settings(&mut self, id: ClientId) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let user = client.user.as_ref().unwrap(); // TODO: this should error (data should be added on account creation, why did I copy this silly sylv logic?) - let settings = match self.entity_gateway.get_user_settings_by_user(&user) { + let settings = match self.entity_gateway.get_user_settings_by_user(&user).await { Some(settings) => settings, None => { let user_settings = NewUserSettingsEntity::new(user.id); - self.entity_gateway.create_user_settings(user_settings).unwrap() + self.entity_gateway.create_user_settings(user_settings).await.unwrap() } }; @@ -357,10 +357,10 @@ impl CharacterServerState { Ok(vec![pkt]) } - fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result, CharacterError> { + async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; if client.characters.is_none() { - client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap())); + client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await); } if select.reason == 0 { @@ -403,9 +403,9 @@ impl CharacterServerState { })] } - fn guildcard_data_header(&mut self, id: ClientId) -> Result, CharacterError> { + async fn guildcard_data_header(&mut self, id: ClientId) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; - let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()); + let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await; let bytes = guildcard_data.guildcard.as_bytes(); let mut crc = crc32::Digest::new(crc32::IEEE); @@ -431,11 +431,11 @@ impl CharacterServerState { }) } - fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result, CharacterError> { + async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); user.flags = setflag.flags; - self.entity_gateway.save_user(&user); + self.entity_gateway.save_user(&user).await; Ok(None.into_iter()) } @@ -460,11 +460,11 @@ impl CharacterServerState { // TODO: move USERFLAGS over to SessionAction - fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result, CharacterError> { + async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); if user.flags == USERFLAG_NEWCHAR { - new_character(&mut self.entity_gateway, &user, preview) + new_character(&mut self.entity_gateway, &user, preview).await } if user.flags == USERFLAG_DRESSINGROOM { // TODO: dressing room stuff @@ -473,7 +473,7 @@ impl CharacterServerState { client.session.action = SessionAction::SelectCharacter; client.session.character_slot = preview.slot as u8; user.flags = 0; - self.entity_gateway.save_user(&user); + self.entity_gateway.save_user(&user).await; Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard, user.team_id.unwrap_or(1), client.session)), @@ -495,6 +495,7 @@ impl CharacterServerState { } } +#[async_trait::async_trait] impl ServerState for CharacterServerState { type SendPacket = SendCharacterPacket; type RecvPacket = RecvCharacterPacket; @@ -516,7 +517,7 @@ impl ServerState for CharacterServerState { ] } - fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket) + async fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket) -> Result + Send>, CharacterError> { Ok(match pkt { RecvCharacterPacket::Login(login) => { @@ -524,20 +525,20 @@ impl ServerState for CharacterServerState { Box::new(self.send_ship_list(id, login)?.into_iter().map(move |pkt| (id, pkt))) } else { - Box::new(self.validate_login(id, login)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(self.validate_login(id, login).await?.into_iter().map(move |pkt| (id, pkt))) } }, RecvCharacterPacket::RequestSettings(_req) => { - Box::new(self.get_settings(id)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(self.get_settings(id).await?.into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::CharSelect(sel) => { - Box::new(self.char_select(id, sel)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(self.char_select(id, sel).await?.into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::Checksum(_checksum) => { Box::new(self.validate_checksum().into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::GuildcardDataRequest(_request) => { - Box::new(self.guildcard_data_header(id)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(self.guildcard_data_header(id).await?.into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::GuildcardDataChunkRequest(request) => { Box::new(self.guildcard_data_chunk(id, request.chunk, request.again)?.into_iter().map(move |pkt| (id, pkt))) @@ -546,13 +547,13 @@ impl ServerState for CharacterServerState { Box::new(vec![SendCharacterPacket::ParamDataHeader(self.param_header.clone())].into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::SetFlag(flag) => { - Box::new(self.set_flag(id, flag)?.map(move |pkt| (id, pkt))) + Box::new(self.set_flag(id, flag).await?.map(move |pkt| (id, pkt))) }, RecvCharacterPacket::ParamDataChunkRequest(request) => { Box::new(self.param_data_chunk_request(id, request)?.into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::CharacterPreview(preview) => { - Box::new(self.character_preview(id, preview)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(self.character_preview(id, preview).await?.into_iter().map(move |pkt| (id, pkt))) }, RecvCharacterPacket::MenuSelect(menuselect) => { Box::new(self.select_ship(menuselect)?.into_iter().map(move |pkt| (id, pkt))) diff --git a/src/login/login.rs b/src/login/login.rs index b7ce2d7..9b6d27d 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -56,10 +56,10 @@ impl SendServerPacket for SendLoginPacket { } -pub fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result { +pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result { let username = array_to_utf8(pkt.username).map_err(|_err| AccountStatus::Error)?; let password = array_to_utf8(pkt.password).map_err(|_err| AccountStatus::Error)?; - let user = entity_gateway.get_user_by_name(username).ok_or(AccountStatus::InvalidUser)?; + let user = entity_gateway.get_user_by_name(username).await.ok_or(AccountStatus::InvalidUser)?; let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?; match verified { true => if user.banned { @@ -84,8 +84,8 @@ impl LoginServerState { } } - fn validate_login(&mut self, pkt: &Login) -> Vec { - match get_login_status(&self.entity_gateway, pkt) { + async fn validate_login(&mut self, pkt: &Login) -> Vec { + match get_login_status(&self.entity_gateway, pkt).await { Ok(_user) => { let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session)); let ip = net::Ipv4Addr::new(127,0,0,1); @@ -100,6 +100,7 @@ impl LoginServerState { } } +#[async_trait::async_trait] impl ServerState for LoginServerState { type SendPacket = SendLoginPacket; type RecvPacket = RecvLoginPacket; @@ -119,11 +120,11 @@ impl ServerState for LoginServerState { ] } - fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) + async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) -> Result + Send>, LoginError> { Ok(match pkt { RecvLoginPacket::Login(login) => { - Box::new(self.validate_login(login) + Box::new(self.validate_login(login).await .into_iter() .map(move |pkt| { (id, pkt) diff --git a/src/patch/patch.rs b/src/patch/patch.rs index a5603c8..6c18876 100644 --- a/src/patch/patch.rs +++ b/src/patch/patch.rs @@ -154,6 +154,7 @@ impl PatchServerState { } } +#[async_trait::async_trait] impl ServerState for PatchServerState { type SendPacket = SendPatchPacket; type RecvPacket = RecvPatchPacket; @@ -169,7 +170,7 @@ impl ServerState for PatchServerState { ] } - fn handle(&mut self, id: ClientId, pkt: &RecvPatchPacket) + async fn handle(&mut self, id: ClientId, pkt: &RecvPatchPacket) -> Result + Send>, PatchError> { Ok(match pkt { RecvPatchPacket::PatchWelcomeReply(_pkt) => { diff --git a/src/ship/drops/mod.rs b/src/ship/drops/mod.rs index 05f966c..620b4b7 100644 --- a/src/ship/drops/mod.rs +++ b/src/ship/drops/mod.rs @@ -91,6 +91,7 @@ pub enum ItemDropType { Meseta(u32), } +#[derive(Clone, Debug)] pub struct ItemDrop { pub map_area: MapArea, pub x: f32, diff --git a/src/ship/items.rs b/src/ship/items.rs index 16f7b81..1eb9dfd 100644 --- a/src/ship/items.rs +++ b/src/ship/items.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, BTreeMap}; -use libpso::character::character;//::InventoryItem; use thiserror::Error; +use futures::future::join_all; +use libpso::character::character;//::InventoryItem; use crate::entity::gateway::EntityGateway; use crate::entity::character::{CharacterEntity, CharacterEntityId}; use crate::entity::item::{ItemEntityId, ItemEntity, ItemDetail, ItemLocation}; @@ -189,8 +190,8 @@ impl ItemManager { } // TODO: Result - pub fn load_character(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) { - let items = entity_gateway.get_items_by_character(&character); + pub async fn load_character(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) { + let items = entity_gateway.get_items_by_character(&character).await; let inventory_items = items.into_iter() .filter_map(|item| { match item.location { @@ -289,7 +290,7 @@ impl ItemManager { .map(Clone::clone) } - pub fn character_picks_up_item(&mut self, entity_gateway: &mut EG, character: &mut CharacterEntity, floor_item: FloorItem) -> Result { + pub async fn character_picks_up_item(&mut self, entity_gateway: &mut EG, character: &mut CharacterEntity, floor_item: FloorItem) -> Result { let local_floor = self.character_floor.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; @@ -356,7 +357,7 @@ impl ItemManager { slot: inventory.len(), equipped: false, }, - }); // TODO: error check + }).await; // TODO: error check inventory.push(inventory_item); } // else something went very wrong TODO: log it TriggerCreateItem::Yes @@ -411,14 +412,14 @@ impl ItemManager { slot: inventory.len(), equipped: false, }, - }); // TODO: error check + }).await; // TODO: error check }; } // else something went very wrong TODO: log it trigger_create }, FloorItemType::Meseta(meseta) => { character.meseta = std::cmp::min(character.meseta + meseta.0, 999999); - entity_gateway.save_character(&character); + entity_gateway.save_character(&character).await; TriggerCreateItem::No } }; @@ -426,7 +427,7 @@ impl ItemManager { Ok(trigger_create) } - pub fn enemy_drop_item_on_local_floor(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, item_drop: ItemDrop) -> Result<&FloorItem, ItemManagerError> { + pub async fn enemy_drop_item_on_local_floor(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, item_drop: ItemDrop) -> Result<&FloorItem, ItemManagerError> { let item = match item_drop.item { ItemDropType::Weapon(w) => FloorItemType::Individual(ItemDetail::Weapon(w)), ItemDropType::Armor(w) => FloorItemType::Individual(ItemDetail::Armor(w)), @@ -440,6 +441,8 @@ impl ItemManager { ItemDropType::Meseta(m) => FloorItemType::Meseta(Meseta(m)) }; + + //let eg = Arc::new(Mutex::new(entity_gateway.clone())) let entity_id = match &item { FloorItemType::Individual(i) => { let entity = entity_gateway.create_item(NewItemEntity { @@ -451,26 +454,37 @@ impl ItemManager { y: item_drop.y, z: item_drop.z, } - }).ok_or(ItemManagerError::EntityGatewayError)?; + }).await.ok_or(ItemManagerError::EntityGatewayError)?; ActiveItemEntityId::Individual(entity.id) }, FloorItemType::Stacked(tool, count) => { - let entities = (0..*count).map(|_| { - entity_gateway.create_item(NewItemEntity { - item: ItemDetail::Tool(*tool), - location: ItemLocation::LocalFloor { - character_id: character.id, - map_area: item_drop.map_area, - x: item_drop.x, - y: item_drop.y, - z: item_drop.z, - } - })}) + let entities = (0..*count) + .map(|_| { + let mut eg = entity_gateway.clone(); + let item_drop = item_drop.clone(); + async move { + eg.create_item(NewItemEntity { + item: ItemDetail::Tool(*tool), + location: ItemLocation::LocalFloor { + character_id: character.id, + map_area: item_drop.map_area, + x: item_drop.x, + y: item_drop.y, + z: item_drop.z, + } + }).await + }}); + let entities = join_all(entities).await.into_iter() .map(|entity| -> Result { let e = entity.ok_or(ItemManagerError::EntityGatewayError)?; + // I am not able to manually specify a closure return type when also using the async keyword Ok(e.id) + //let result: Result = Ok(e.id); + //result }); + //ActiveItemEntityId::Stacked(join_all(entities).await.into_iter().collect::, _>>()?) ActiveItemEntityId::Stacked(entities.collect::, _>>()?) + //ActiveItemEntityId::Stacked(entities.collect().await?) }, FloorItemType::Meseta(m) => ActiveItemEntityId::Meseta(m.clone()), }; @@ -492,7 +506,7 @@ impl ItemManager { self.character_floor.get(&character.id).ok_or(ItemManagerError::Idunnoman)?.last().ok_or(ItemManagerError::Idunnoman) } - pub fn player_drop_item_on_shared_floor(&mut self, + pub async fn player_drop_item_on_shared_floor(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, inventory_item: InventoryItem, @@ -532,7 +546,7 @@ impl ItemManager { y: item_drop_location.2, z: item_drop_location.3, } - }); // TODO: error check + }).await; // TODO: error check } // else something went very wrong: TODO: log it }, FloorItemType::Stacked(tool, _count) => { @@ -547,7 +561,7 @@ impl ItemManager { y: item_drop_location.2, z: item_drop_location.3, }, - }); // TODO: error check + }).await; // TODO: error check } } // else something went very wrong TODO: log it }, @@ -558,7 +572,7 @@ impl ItemManager { Ok(()) } - pub fn player_drops_meseta_on_shared_floor(&mut self, + pub async fn player_drops_meseta_on_shared_floor(&mut self, entity_gateway: &mut EG, character: &mut CharacterEntity, drop_location: ItemDropLocation, @@ -570,7 +584,7 @@ impl ItemManager { return Err(ItemManagerError::CouldNotDropMeseta) } character.meseta -= amount; - entity_gateway.save_character(&character); + entity_gateway.save_character(&character).await; let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?(); let floor_item = FloorItem { @@ -587,7 +601,7 @@ impl ItemManager { Ok(floor_item) } - pub fn player_drops_partial_stack_on_shared_floor(&mut self, + pub async fn player_drops_partial_stack_on_shared_floor(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, inventory_item: InventoryItem, @@ -611,9 +625,26 @@ impl ItemManager { let dropped_entities = entity_ids.drain(..amount).collect::>(); - dropped_entities.iter().for_each(|entity_id| { + /* + dropped_entities.iter().map(|entity_id| { + let mut eg = entity_gateway.clone(); + let tool = tool.clone(); + async move { + eg.save_item(&ItemEntity { + id: *entity_id, + item: ItemDetail::Tool(tool), + location: ItemLocation::SharedFloor { + map_area: drop_location.map_area, + x: drop_location.x, + y: 0.0, + z: drop_location.z, + } + }).await + }}).await; + */ + for de in dropped_entities.iter() { entity_gateway.save_item(&ItemEntity { - id: *entity_id, + id: *de, item: ItemDetail::Tool(*tool), location: ItemLocation::SharedFloor { map_area: drop_location.map_area, @@ -621,8 +652,8 @@ impl ItemManager { y: 0.0, z: drop_location.z, } - }) - }); + }).await + } let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?(); let floor_item = FloorItem { diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index e05ed8b..a0cb15e 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -6,28 +6,28 @@ use crate::login::login::get_login_status; use crate::entity::gateway::EntityGateway; use crate::ship::items::ItemManager; -pub fn validate_login(id: ClientId, +pub async fn validate_login(id: ClientId, pkt: &Login, entity_gateway: &mut EG, clients: &mut Clients, item_manager: &mut ItemManager, ship_name: &String) -> Result, ShipError> { - Ok(match get_login_status(entity_gateway, pkt) { + 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; - let characters = entity_gateway.get_characters_by_user(&user); + 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))? .clone(); - let settings = entity_gateway.get_user_settings_by_user(&user) + let settings = entity_gateway.get_user_settings_by_user(&user).await .ok_or(ShipError::ClientNotFound(id))?; - item_manager.load_character(entity_gateway, &character); + item_manager.load_character(entity_gateway, &character).await; clients.insert(id, ClientState::new(user, settings, character, pkt.session)); vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] }, diff --git a/src/ship/packet/handler/communication.rs b/src/ship/packet/handler/communication.rs index 57a9a79..0f8e81a 100644 --- a/src/ship/packet/handler/communication.rs +++ b/src/ship/packet/handler/communication.rs @@ -35,13 +35,13 @@ pub fn request_infoboard(id: ClientId, Box::new(vec![(id, SendShipPacket::ViewInfoboardResponse(ViewInfoboardResponse {response: r}))].into_iter()) } -pub fn write_infoboard(id: ClientId, +pub async fn write_infoboard(id: ClientId, new_infoboard: &WriteInfoboard, clients: &mut Clients, entity_gateway: &mut EG) -> Box + Send> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); client.character.info_board.update_infoboard(new_infoboard); - entity_gateway.save_character(&client.character); + entity_gateway.save_character(&client.character).await; Box::new(None.into_iter()) } diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index 4823cac..9b50805 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -44,14 +44,14 @@ pub fn guildcard_send(id: ClientId, send_to_client(id, target as u8, msg, &client_location) } -pub fn request_item(id: ClientId, - request_item: &RequestItem, - entity_gateway: &mut EG, - client_location: &ClientLocation, - clients: &mut Clients, - rooms: &mut Rooms, - item_manager: &mut ItemManager) - -> Result + Send>, ShipError> +pub async fn request_item(id: ClientId, + request_item: &RequestItem, + entity_gateway: &mut EG, + client_location: &ClientLocation, + clients: &mut Clients, + rooms: &mut Rooms, + item_manager: &mut ItemManager) + -> Result + Send>, ShipError> where EG: EntityGateway { @@ -68,6 +68,7 @@ where let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; + /* let item_drop_packets = clients_in_area.into_iter() .filter_map(|area_client| { room.drop_table.get_drop(&monster.map_area, &monster.monster).map(|item_drop_type| { @@ -75,7 +76,7 @@ where (area_client, item_drop_type) }) }) - .map(|(area_client, item_drop_type)| -> Result<_, ShipError> { + .map(|(area_client, item_drop_type)| async { let item_drop = ItemDrop { map_area: monster.map_area, x: request_item.x, @@ -84,26 +85,62 @@ where item: item_drop_type, }; let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; - let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).unwrap(); // TODO: unwrap + let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?; - Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))) + + // I am not able to manually specify a closure return type when also using the async keyword + let result: Result<(ClientId, SendShipPacket), ShipError> = Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))); + result }) + .map(|item_drop_pkt| async { + item_drop_pkt.await + }); + + let item_drop_packets = join_all(item_drop_packets).await.into_iter() .filter_map(|item_drop_pkt| { // TODO: log errors here item_drop_pkt.ok() - }) - .collect::>(); // TODO: can EntityGateway be Sync? + }); + + //.collect::>(); // TODO: can EntityGateway be Sync? + + Ok(Box::new(item_drop_packets)) + */ + + let client_and_drop = clients_in_area.into_iter() + .filter_map(|area_client| { + room.drop_table.get_drop(&monster.map_area, &monster.monster).map(|item_drop_type| { + warn!("drop is? {:?}", item_drop_type); + (area_client, item_drop_type) + }) + }); + + let mut item_drop_packets = Vec::new(); + for (area_client, item_drop) in client_and_drop { + let item_drop = ItemDrop { + map_area: monster.map_area, + x: request_item.x, + y: request_item.y, + z: request_item.z, + item: item_drop, + }; + let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; + let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap + let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?; + + item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))); + } Ok(Box::new(item_drop_packets.into_iter())) } -pub fn pickup_item(id: ClientId, - pickup_item: &PickupItem, - entity_gateway: &mut EG, - client_location: &ClientLocation, - clients: &mut Clients, - item_manager: &mut ItemManager) - -> Result + Send>, ShipError> +pub async fn pickup_item(id: ClientId, + pickup_item: &PickupItem, + entity_gateway: &mut EG, + client_location: &ClientLocation, + clients: &mut Clients, + item_manager: &mut ItemManager) + -> Result + Send>, ShipError> where EG: EntityGateway { @@ -118,7 +155,7 @@ where _ => Some(builder::message::create_item(area_client, &item)?), }; - match item_manager.character_picks_up_item(entity_gateway, &mut client.character, item) { + match item_manager.character_picks_up_item(entity_gateway, &mut client.character, item).await { Ok(trigger_create_item) => { Ok(Box::new(Vec::new().into_iter() .chain(clients_in_area.clone().into_iter() @@ -142,7 +179,7 @@ where } } -pub fn request_box_item(id: ClientId, +pub async fn request_box_item(id: ClientId, box_drop_request: &BoxDropRequest, entity_gateway: &mut EG, client_location: &ClientLocation, @@ -166,14 +203,14 @@ EG: EntityGateway let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; - let item_drop_packets = clients_in_area.into_iter() + /*let item_drop_packets = clients_in_area.into_iter() .filter_map(|area_client| { room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| { warn!("drop is? {:?}", item_drop_type); (area_client, item_drop_type) }) }) - .map(|(area_client, item_drop_type)| -> Result<_, ShipError> { + .map(async move |(area_client, item_drop_type)| -> Result<_, ShipError> { let item_drop = ItemDrop { map_area: box_object.map, x: box_drop_request.x, @@ -182,15 +219,47 @@ EG: EntityGateway item: item_drop_type, }; let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; - let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).unwrap(); // TODO: unwrap + let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?; Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))) }) - .filter_map(|item_drop_pkt| { + /*.filter_map(|item_drop_pkt| { // TODO: log errors here item_drop_pkt.ok() }) - .collect::>(); // TODO: can EntityGateway be Sync? + .collect::>(); // TODO: can EntityGateway be Sync?*/ + ; + let item_drop_packets = join_all(item_drop_packets).await.into_iter() + .filter_map(|item_drop_pkt| { + // TODO: log errors here + item_drop_pkt.ok() + }); + + Ok(Box::new(item_drop_packets)) + */ + + let client_and_drop = clients_in_area.into_iter() + .filter_map(|area_client| { + room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| { + warn!("drop is? {:?}", item_drop_type); + (area_client, item_drop_type) + }) + }); + + let mut item_drop_packets = Vec::new(); + for (area_client, item_drop) in client_and_drop { + let item_drop = ItemDrop { + map_area: box_object.map, + x: box_drop_request.x, + y: 0.0, + z: box_drop_request.z, + item: item_drop, + }; + let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; + let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await?; // TODO: unwrap + let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?; + item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))) + } Ok(Box::new(item_drop_packets.into_iter())) } diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index c43dcfc..5751f6a 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -60,7 +60,7 @@ pub fn send_player_to_lobby(id: ClientId, .map(|c| (c.client, SendShipPacket::AddToLobby(addto.clone())))).collect()) } -pub fn change_lobby(id: ClientId, +pub async fn change_lobby(id: ClientId, requested_lobby: u32, client_location: &mut ClientLocation, clients: &Clients, @@ -98,7 +98,7 @@ pub fn change_lobby(id: ClientId, } } } - item_manager.load_character(entity_gateway, &client.character); + item_manager.load_character(entity_gateway, &client.character).await; let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_manager, level_table)?; let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_manager, level_table)?; let neighbors = client_location.get_client_neighbors(id).unwrap(); diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index b950511..52f22e2 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -25,7 +25,7 @@ pub fn request_exp(id: ClientId, Box::new(None.into_iter()) } -pub fn player_drop_item(id: ClientId, +pub async fn player_drop_item(id: ClientId, player_drop_item: &PlayerDropItem, entity_gateway: &mut EG, client_location: &ClientLocation, @@ -44,7 +44,7 @@ where .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; let area = MapArea::from_value(&room.mode.episode(), player_drop_item.area as u32)?; let item = item_manager.get_inventory_item_by_id(&client.character, ClientItemId(player_drop_item.item_id))?; - item_manager.player_drop_item_on_shared_floor(entity_gateway, &client.character, item, (area, player_drop_item.x, player_drop_item.y, player_drop_item.z))?; + item_manager.player_drop_item_on_shared_floor(entity_gateway, &client.character, item, (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 pdi = player_drop_item.clone(); Ok(Box::new(clients_in_area.into_iter() @@ -77,13 +77,13 @@ pub fn drop_coordinates(id: ClientId, Ok(Box::new(None.into_iter())) } -pub fn split_item_stack(id: ClientId, - split_item_stack: &PlayerSplitItemStack, - entity_gateway: &mut EG, - client_location: &ClientLocation, - clients: &mut Clients, - item_manager: &mut ItemManager) - -> Result + Send>, ShipError> +pub async fn split_item_stack(id: ClientId, + split_item_stack: &PlayerSplitItemStack, + entity_gateway: &mut EG, + client_location: &ClientLocation, + clients: &mut Clients, + item_manager: &mut ItemManager) + -> Result + Send>, ShipError> where EG: EntityGateway { @@ -97,7 +97,7 @@ where } if split_item_stack.item_id == 0xFFFFFFFF { - let dropped_meseta = item_manager.player_drops_meseta_on_shared_floor(entity_gateway, &mut client.character, drop_location, split_item_stack.amount as u32)?; + let dropped_meseta = item_manager.player_drops_meseta_on_shared_floor(entity_gateway, &mut client.character, drop_location, split_item_stack.amount as u32).await?; let dropped_meseta_pkt = builder::message::drop_split_stack(area_client, &dropped_meseta)?; client.item_drop_location = None; @@ -110,7 +110,7 @@ where } else { let item_to_split = item_manager.get_inventory_item_by_id(&client.character, drop_location.item_id)?; - let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, item_to_split, drop_location, split_item_stack.amount as usize)?; + let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, item_to_split, drop_location, split_item_stack.amount as usize).await?; let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item)?; client.item_drop_location = None; diff --git a/src/ship/packet/handler/settings.rs b/src/ship/packet/handler/settings.rs index 4d69e70..109c26b 100644 --- a/src/ship/packet/handler/settings.rs +++ b/src/ship/packet/handler/settings.rs @@ -3,13 +3,13 @@ use crate::common::serverstate::ClientId; use crate::ship::ship::{SendShipPacket, ShipError, Clients}; use crate::entity::gateway::EntityGateway; -pub fn update_config(id: ClientId, +pub async fn update_config(id: ClientId, update_config: &UpdateConfig, clients: &mut Clients, entity_gateway: &mut EG) -> Box + Send> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); client.character.config.update(update_config); - entity_gateway.save_character(&client.character); + entity_gateway.save_character(&client.character).await; Box::new(None.into_iter()) } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 9749178..97c4aa4 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -261,19 +261,19 @@ impl ShipServerState { } } - fn message(&mut self, id: ClientId, msg: &Message) -> Result + Send>, ShipError> { + async fn message(&mut self, id: ClientId, msg: &Message) -> Result + Send>, ShipError> { match &msg.msg { GameMessage::RequestExp(request_exp) => { Ok(handler::message::request_exp(id, request_exp, &self.client_location, &self.rooms)) }, GameMessage::PlayerDropItem(player_drop_item) => { - handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager) + handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await }, GameMessage::DropCoordinates(drop_coordinates) => { handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms) }, GameMessage::PlayerSplitItemStack(split_item_stack) => { - handler::message::split_item_stack(id, split_item_stack, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager) + handler::message::split_item_stack(id, split_item_stack, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await }, _ => { let cmsg = msg.clone(); @@ -285,20 +285,20 @@ impl ShipServerState { } } - fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result + Send>, ShipError> { + async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result + Send>, ShipError> { let target = msg.flag; match &msg.msg { GameMessage::GuildcardSend(guildcard_send) => { Ok(handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients)) }, GameMessage::RequestItem(request_item) => { - handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager) + handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await }, GameMessage::PickupItem(pickup_item) => { - handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager) + handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await }, GameMessage::BoxDropRequest(box_drop_request) => { - handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager) + handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await } _ => { let cmsg = msg.clone(); @@ -312,6 +312,7 @@ impl ShipServerState { } } +#[async_trait::async_trait] impl ServerState for ShipServerState { type SendPacket = SendShipPacket; type RecvPacket = RecvShipPacket; @@ -331,11 +332,11 @@ impl ServerState for ShipServerState { ] } - fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket) + async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket) -> Result + Send>, ShipError> { Ok(match pkt { RecvShipPacket::Login(login) => { - Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.name)?.into_iter().map(move |pkt| (id, pkt))) + Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.name).await?.into_iter().map(move |pkt| (id, pkt))) }, RecvShipPacket::QuestDetailRequest(questdetailrequest) => { match questdetailrequest.menu { @@ -375,10 +376,10 @@ impl ServerState for ShipServerState { Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut self.client_location, &self.clients, &self.item_manager, &self.level_table)?.into_iter()) }, RecvShipPacket::Message(msg) => { - self.message(id, msg)? + self.message(id, msg).await? }, RecvShipPacket::DirectMessage(msg) => { - self.direct_message(id, msg)? + self.direct_message(id, msg).await? }, RecvShipPacket::PlayerChat(msg) => { Box::new(handler::communication::player_chat(id, msg, &self.client_location, &self.clients)?.into_iter()) @@ -390,13 +391,13 @@ impl ServerState for ShipServerState { handler::room::room_name_request(id, &self.client_location, &self.rooms) }, RecvShipPacket::UpdateConfig(pkt) => { - handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway) + handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await }, RecvShipPacket::ViewInfoboardRequest(_pkt) => { handler::communication::request_infoboard(id, &self.client_location, &self.clients) }, RecvShipPacket::WriteInfoboard(pkt) => { - handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway) + handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway).await }, RecvShipPacket::RoomListRequest(_req) => { handler::room::request_room_list(id, &self.client_location, &self.rooms) @@ -415,7 +416,7 @@ impl ServerState for ShipServerState { handler::room::done_bursting(id, &self.client_location, &mut self.rooms) }, RecvShipPacket::LobbySelect(pkt) => { - Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut self.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms, &mut self.entity_gateway)?.into_iter()) + Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut self.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms, &mut self.entity_gateway).await?.into_iter()) }, RecvShipPacket::RequestQuestList(_) => { handler::quest::send_quest_category_list(id, &self.quests)?