entitygateway uses results for its functions now
This commit is contained in:
parent
69374ea424
commit
2351b31125
@ -1,80 +1,91 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
|
|
||||||
// TODO: all these Options should be Results
|
|
||||||
|
// TODO: better granularity?
|
||||||
|
//#[derive(Error, Debug)]
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
#[error("")]
|
||||||
|
pub enum GatewayError {
|
||||||
|
Error,
|
||||||
|
PgError(#[from] sqlx::Error)
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait EntityGateway: Send + Sync + Clone {
|
pub trait EntityGateway: Send + Sync + Clone {
|
||||||
async fn create_user(&mut self, _user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
async fn create_user(&mut self, _user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, _id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, _id: UserAccountId) -> Result<UserAccountEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_name(&self, _username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, _username: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user(&mut self, _user: &UserAccountEntity) {
|
async fn save_user(&mut self, _user: &UserAccountEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user_settings(&mut self, _settings: &UserSettingsEntity) {
|
async fn save_user_settings(&mut self, _settings: &UserSettingsEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_character(&mut self, _char: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, _char: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: just make this a vec sorted by slot order?
|
// TODO: just make this a vec sorted by slot order?
|
||||||
async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_character(&mut self, _char: &CharacterEntity) {
|
async fn save_character(&mut self, _char: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_item(&mut self, _item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, _item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_item(&mut self, _item: &ItemEntity) {
|
async fn save_item(&mut self, _item: &ItemEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) {
|
async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn feed_mag(&mut self, _mag_item_id: &ItemEntityId, _tool_item_id: &ItemEntityId) {
|
async fn feed_mag(&mut self, _mag_item_id: &ItemEntityId, _tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) {
|
async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn use_mag_cell(&mut self, _mag_item_id: &ItemEntityId, _mag_cell_id: &ItemEntityId) {
|
async fn use_mag_cell(&mut self, _mag_item_id: &ItemEntityId, _mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, _char: &CharacterEntity) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::convert::TryInto;
|
|||||||
|
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@ -31,7 +31,7 @@ impl InMemoryGateway {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for InMemoryGateway {
|
impl EntityGateway for InMemoryGateway {
|
||||||
async fn create_user(&mut self, user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let mut users = self.users.lock().unwrap();
|
let mut users = self.users.lock().unwrap();
|
||||||
let id = users
|
let id = users
|
||||||
.iter()
|
.iter()
|
||||||
@ -47,30 +47,33 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
muted_until: user.muted_until,
|
muted_until: user.muted_until,
|
||||||
created_at: user.created_at,
|
created_at: user.created_at,
|
||||||
flags: user.flags,
|
flags: user.flags,
|
||||||
|
activated: true,
|
||||||
};
|
};
|
||||||
users.insert(user.id, user.clone());
|
users.insert(user.id, user.clone());
|
||||||
Some(user)
|
Ok(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, id: UserAccountId) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let users = self.users.lock().unwrap();
|
let users = self.users.lock().unwrap();
|
||||||
users.get(&id).map(|k| k.clone())
|
users.get(&id).map(|k| k.clone()).ok_or(GatewayError::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_name(&self, username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, username: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let users = self.users.lock().unwrap();
|
let users = self.users.lock().unwrap();
|
||||||
users
|
users
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_, k)| k.username == username)
|
.find(|(_, k)| k.username == username)
|
||||||
.map(|(_, k)| k.clone())
|
.map(|(_, k)| k.clone())
|
||||||
|
.ok_or(GatewayError::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user(&mut self, user: &UserAccountEntity) {
|
async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> {
|
||||||
let mut users = self.users.lock().unwrap();
|
let mut users = self.users.lock().unwrap();
|
||||||
users.insert(user.id, user.clone());
|
users.insert(user.id, user.clone());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let mut user_settings = self.user_settings.lock().unwrap();
|
let mut user_settings = self.user_settings.lock().unwrap();
|
||||||
let id = user_settings
|
let id = user_settings
|
||||||
.iter()
|
.iter()
|
||||||
@ -82,28 +85,29 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
settings: settings.settings,
|
settings: settings.settings,
|
||||||
};
|
};
|
||||||
user_settings.insert(new_settings.id, new_settings.clone());
|
user_settings.insert(new_settings.id, new_settings.clone());
|
||||||
Some(new_settings)
|
Ok(new_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let user_settings = self.user_settings.lock().unwrap();
|
let user_settings = self.user_settings.lock().unwrap();
|
||||||
user_settings
|
user_settings
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_, k)| k.user_id == user.id)
|
.find(|(_, k)| k.user_id == user.id)
|
||||||
.map(|(_, k)| k.clone())
|
.map(|(_, k)| k.clone())
|
||||||
|
.ok_or(GatewayError::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
||||||
let characters = self.characters.lock().unwrap();
|
let characters = self.characters.lock().unwrap();
|
||||||
let mut chars = [None; 4];
|
let mut chars = [None; 4];
|
||||||
characters
|
characters
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.user_id == user.id)
|
.filter(|(_, c)| c.user_id == user.id)
|
||||||
.for_each(|(_, c)| chars[c.slot as usize] = Some(c.clone()));
|
.for_each(|(_, c)| chars[c.slot as usize] = Some(c.clone()));
|
||||||
chars
|
Ok(chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_character(&mut self, character: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, character: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> {
|
||||||
let mut characters = self.characters.lock().unwrap();
|
let mut characters = self.characters.lock().unwrap();
|
||||||
let id = characters
|
let id = characters
|
||||||
.iter()
|
.iter()
|
||||||
@ -130,19 +134,20 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
option_flags: character.option_flags,
|
option_flags: character.option_flags,
|
||||||
};
|
};
|
||||||
characters.insert(new_character.id, new_character.clone());
|
characters.insert(new_character.id, new_character.clone());
|
||||||
Some(new_character)
|
Ok(new_character)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_character(&mut self, char: &CharacterEntity) {
|
async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
let mut characters = self.characters.lock().unwrap();
|
let mut characters = self.characters.lock().unwrap();
|
||||||
characters.insert(char.id, char.clone());
|
characters.insert(char.id, char.clone());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> {
|
||||||
GuildCardDataEntity::new(user.id)
|
Ok(GuildCardDataEntity::new(user.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_item(&mut self, item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
|
||||||
let mut items = self.items.lock().unwrap();
|
let mut items = self.items.lock().unwrap();
|
||||||
let id = items
|
let id = items
|
||||||
.iter()
|
.iter()
|
||||||
@ -154,47 +159,52 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
item: item.item,
|
item: item.item,
|
||||||
};
|
};
|
||||||
items.insert(ItemEntityId(id), new_item.clone());
|
items.insert(ItemEntityId(id), new_item.clone());
|
||||||
Some(new_item)
|
Ok(new_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_item(&mut self, item: &ItemEntity) {
|
async fn save_item(&mut self, item: &ItemEntity) -> Result<(), GatewayError> {
|
||||||
let mut items = self.items.lock().unwrap();
|
let mut items = self.items.lock().unwrap();
|
||||||
items.insert(item.id, item.clone());
|
items.insert(item.id, item.clone());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) {
|
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
self.items.lock().unwrap().get_mut(&item_id)
|
self.items.lock().unwrap().get_mut(&item_id)
|
||||||
.map(|item_entity| {
|
.map(|item_entity| {
|
||||||
item_entity.location = item_location
|
item_entity.location = item_location
|
||||||
});
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) {
|
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
self.mag_modifiers.lock().unwrap()
|
self.mag_modifiers.lock().unwrap()
|
||||||
.entry(*mag_item_id)
|
.entry(*mag_item_id)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(mag::MagModifier::FeedMag {
|
.push(mag::MagModifier::FeedMag {
|
||||||
food: *tool_item_id
|
food: *tool_item_id
|
||||||
});
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) {
|
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
self.mag_modifiers.lock().unwrap()
|
self.mag_modifiers.lock().unwrap()
|
||||||
.entry(*mag_item_id)
|
.entry(*mag_item_id)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(mag::MagModifier::OwnerChange(character.char_class, character.section_id));
|
.push(mag::MagModifier::OwnerChange(character.char_class, character.section_id));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) {
|
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
self.mag_modifiers.lock().unwrap()
|
self.mag_modifiers.lock().unwrap()
|
||||||
.entry(*mag_item_id)
|
.entry(*mag_item_id)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push(mag::MagModifier::MagCell(mag_cell_id.clone()));
|
.push(mag::MagModifier::MagCell(mag_cell_id.clone()));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_items_by_character(&self, character: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, character: &CharacterEntity) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
let items = self.items.lock().unwrap();
|
let items = self.items.lock().unwrap();
|
||||||
items
|
Ok(items
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, k)| {
|
.filter(|(_, k)| {
|
||||||
match k.location {
|
match k.location {
|
||||||
@ -241,6 +251,6 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
};
|
};
|
||||||
item
|
item
|
||||||
})
|
})
|
||||||
.collect()
|
.collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,6 @@ pub mod entitygateway;
|
|||||||
pub mod inmemory;
|
pub mod inmemory;
|
||||||
pub mod postgres;
|
pub mod postgres;
|
||||||
|
|
||||||
pub use entitygateway::EntityGateway;
|
pub use entitygateway::{EntityGateway, GatewayError};
|
||||||
pub use inmemory::InMemoryGateway;
|
pub use inmemory::InMemoryGateway;
|
||||||
pub use self::postgres::PostgresGateway;
|
pub use self::postgres::PostgresGateway;
|
||||||
|
@ -9,7 +9,7 @@ use libpso::character::{settings, guildcard};
|
|||||||
use libpso::util::vec_to_array;
|
use libpso::util::vec_to_array;
|
||||||
use crate::entity::account::*;
|
use crate::entity::account::*;
|
||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
use super::models::*;
|
use super::models::*;
|
||||||
|
|
||||||
@ -99,30 +99,30 @@ impl PostgresGateway {
|
|||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for PostgresGateway {
|
impl EntityGateway for PostgresGateway {
|
||||||
async fn create_user(&mut self, user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let new_user = sqlx::query_as::<_, PgUserAccount>("insert into user_accounts (email, username, password) values ($1, $2, $3) returning *;")
|
let new_user = sqlx::query_as::<_, PgUserAccount>("insert into user_accounts (email, username, password) values ($1, $2, $3) returning *;")
|
||||||
.bind(user.email)
|
.bind(user.email)
|
||||||
.bind(user.username)
|
.bind(user.username)
|
||||||
.bind(user.password)
|
.bind(user.password)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(new_user.into())
|
Ok(new_user.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_id(&self, id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, id: UserAccountId) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where id = $1")
|
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where id = $1")
|
||||||
.bind(id.0)
|
.bind(id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(user.into())
|
Ok(user.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_name(&self, username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, username: String) -> Result<UserAccountEntity, GatewayError> {
|
||||||
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where username = $1")
|
let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where username = $1")
|
||||||
.bind(username)
|
.bind(username)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(user.into())
|
Ok(user.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user(&mut self, user: &UserAccountEntity) {
|
async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> {
|
||||||
sqlx::query("UPDATE user_accounts set name=$1, password=$2, banned=$3, muted=$4, flags=$5 where id=$6")
|
sqlx::query("UPDATE user_accounts set name=$1, password=$2, banned=$3, muted=$4, flags=$5 where id=$6")
|
||||||
.bind(&user.username)
|
.bind(&user.username)
|
||||||
.bind(&user.password)
|
.bind(&user.password)
|
||||||
@ -130,10 +130,11 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(&user.muted_until)
|
.bind(&user.muted_until)
|
||||||
.bind(&user.flags)
|
.bind(&user.flags)
|
||||||
.bind(&user.id.0)
|
.bind(&user.id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name)
|
let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name)
|
||||||
values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;")
|
values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;")
|
||||||
.bind(settings.user_id.0)
|
.bind(settings.user_id.0)
|
||||||
@ -144,18 +145,18 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(settings.settings.shortcuts.to_vec())
|
.bind(settings.settings.shortcuts.to_vec())
|
||||||
.bind(settings.settings.symbol_chats.to_vec())
|
.bind(settings.settings.symbol_chats.to_vec())
|
||||||
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(new_settings.into())
|
Ok(new_settings.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
|
||||||
let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where id = $1")
|
let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where id = $1")
|
||||||
.bind(user.id.0)
|
.bind(user.id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
Some(settings.into())
|
Ok(settings.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_user_settings(&mut self, settings: &UserSettingsEntity) {
|
async fn save_user_settings(&mut self, settings: &UserSettingsEntity) -> Result<(), GatewayError> {
|
||||||
sqlx::query("update user_settings set blocked_users=$1, key_config=$2, joystick_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8")
|
sqlx::query("update user_settings set blocked_users=$1, key_config=$2, joystick_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8")
|
||||||
.bind(settings.settings.blocked_users.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
.bind(settings.settings.blocked_users.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
||||||
.bind(&settings.settings.key_config.to_vec())
|
.bind(&settings.settings.key_config.to_vec())
|
||||||
@ -165,10 +166,11 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(&settings.settings.symbol_chats.to_vec())
|
.bind(&settings.settings.symbol_chats.to_vec())
|
||||||
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
.bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::<Vec<u8>>())
|
||||||
.bind(&settings.id.0)
|
.bind(&settings.id.0)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_character(&mut self, char: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, char: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> {
|
||||||
let q = r#"insert into player_character
|
let q = r#"insert into player_character
|
||||||
(user_account, slot, name, exp, class, section_id, costume, skin, face, head, hair, hair_r, hair_g, hair_b, prop_x, prop_y, techs,
|
(user_account, slot, name, exp, class, section_id, costume, skin, face, head, hair, hair_r, hair_g, hair_b, prop_x, prop_y, techs,
|
||||||
config, infoboard, guildcard, power, mind, def, evade, luck, hp, tp, tech_menu, meseta, bank_meseta, option_flags)
|
config, infoboard, guildcard, power, mind, def, evade, luck, hp, tp, tech_menu, meseta, bank_meseta, option_flags)
|
||||||
@ -208,28 +210,28 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(char.meseta as i32)
|
.bind(char.meseta as i32)
|
||||||
.bind(char.bank_meseta as i32)
|
.bind(char.bank_meseta as i32)
|
||||||
.bind(char.option_flags as i32)
|
.bind(char.option_flags as i32)
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&self.pool).await?;
|
||||||
|
|
||||||
sqlx::query("insert into inventory_slots (pchar) values ($1)")
|
sqlx::query("insert into inventory_slots (pchar) values ($1)")
|
||||||
.bind(character.id)
|
.bind(character.id)
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
Some(character.into())
|
Ok(character.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
||||||
let mut stream = sqlx::query_as::<_, PgCharacter>("select * from player_character where user_account = $1 and slot < 4 order by slot")
|
let mut stream = sqlx::query_as::<_, PgCharacter>("select * from player_character where user_account = $1 and slot < 4 order by slot")
|
||||||
.bind(user.id.0)
|
.bind(user.id.0)
|
||||||
.fetch(&self.pool);
|
.fetch(&self.pool);
|
||||||
let mut result = [None; 4];
|
let mut result = [None; 4];
|
||||||
while let Some(character) = stream.try_next().await.unwrap() {
|
while let Some(character) = stream.try_next().await? {
|
||||||
let index = character.slot as usize;
|
let index = character.slot as usize;
|
||||||
result[index] = Some(character.into())
|
result[index] = Some(character.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_character(&mut self, char: &CharacterEntity) {
|
async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
let q = r#"update player_character set
|
let q = r#"update player_character set
|
||||||
user_account=$1, slot=$2, name=$3, exp=$4, class=$5, section_id=$6, costume=$7, skin=$8, face=$9, head=$10, hair=$11, hair_r=$12,
|
user_account=$1, slot=$2, name=$3, exp=$4, class=$5, section_id=$6, costume=$7, skin=$8, face=$9, head=$10, hair=$11, hair_r=$12,
|
||||||
hair_g=$13, hair_b=$14, prop_x=$15, prop_y=$16, techs=$17, config=$18, infoboard=$19, guildcard=$20, power=$21, mind=$22, def=$23,
|
hair_g=$13, hair_b=$14, prop_x=$15, prop_y=$16, techs=$17, config=$18, infoboard=$19, guildcard=$20, power=$21, mind=$22, def=$23,
|
||||||
@ -267,31 +269,33 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.bind(char.meseta as i32)
|
.bind(char.meseta as i32)
|
||||||
.bind(char.bank_meseta as i32)
|
.bind(char.bank_meseta as i32)
|
||||||
.bind(char.id.0 as i32)
|
.bind(char.id.0 as i32)
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> {
|
||||||
GuildCardDataEntity {
|
Ok(GuildCardDataEntity {
|
||||||
id: GuildCardDataId(0),
|
id: GuildCardDataId(0),
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
guildcard: guildcard::GuildCardData::default(),
|
guildcard: guildcard::GuildCardData::default(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_item(&mut self, item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
|
||||||
|
let mut tx = self.pool.begin().await?;
|
||||||
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
|
let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;")
|
||||||
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
|
.bind(sqlx::types::Json(PgItemDetail::from(item.item)))
|
||||||
.fetch_one(&self.pool).await.unwrap();
|
.fetch_one(&mut tx).await?;
|
||||||
let location = if let ItemLocation::Inventory{character_id, slot, ..} = &item.location {
|
let location = if let ItemLocation::Inventory{character_id, slot, ..} = &item.location {
|
||||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location.clone())))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location.clone())))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.bind(*slot as i32)
|
.bind(*slot as i32)
|
||||||
.bind(character_id.0 as i32)
|
.bind(character_id.0 as i32)
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
sqlx::query_as::<_, PgItemLocation>(r#"select
|
sqlx::query_as::<_, PgItemLocation>(r#"select
|
||||||
item_location.item,
|
item_location.item,
|
||||||
jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb) as location,
|
jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb) as location,
|
||||||
@ -303,70 +307,77 @@ impl EntityGateway for PostgresGateway {
|
|||||||
order by item_location.created_at
|
order by item_location.created_at
|
||||||
limit 1"#)
|
limit 1"#)
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.fetch_one(&self.pool).await.unwrap()
|
.fetch_one(&mut tx).await?
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *")
|
sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *")
|
||||||
.bind(new_item.id)
|
.bind(new_item.id)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item.location)))
|
||||||
.fetch_one(&self.pool).await.unwrap()
|
.fetch_one(&mut tx).await?
|
||||||
};
|
};
|
||||||
Some(ItemEntity {
|
tx.commit().await?;
|
||||||
|
Ok(ItemEntity {
|
||||||
id: ItemEntityId(new_item.id as u32),
|
id: ItemEntityId(new_item.id as u32),
|
||||||
item: new_item.item.0.into(),
|
item: new_item.item.0.into(),
|
||||||
location: location.location.0.into(),
|
location: location.location.0.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) {
|
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
|
let mut tx = self.pool.begin().await?;
|
||||||
if let ItemLocation::Inventory{character_id, slot, ..} = &item_location {
|
if let ItemLocation::Inventory{character_id, slot, ..} = &item_location {
|
||||||
sqlx::query("update inventory_slots set items[array_position(items, $1)] = null where pchar = $2 and items[array_position(items, $1)] is not null")
|
sqlx::query("update inventory_slots set items[array_position(items, $1)] = null where pchar = $2 and items[array_position(items, $1)] is not null")
|
||||||
.bind(item_id.0 as i32)
|
.bind(item_id.0 as i32)
|
||||||
.bind(character_id.0 as i32)
|
.bind(character_id.0 as i32)
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3")
|
||||||
.bind(item_id.0 as i32)
|
.bind(item_id.0 as i32)
|
||||||
.bind(*slot as i32)
|
.bind(*slot as i32)
|
||||||
.bind(character_id.0 as i32)
|
.bind(character_id.0 as i32)
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
sqlx::query(r#"insert into item_location (item, location)
|
sqlx::query(r#"insert into item_location (item, location)
|
||||||
select $1, $2
|
select $1, $2
|
||||||
where (select jsonb_object_keys(location) from item_location where item=$1
|
where (select jsonb_object_keys(location) from item_location where item=$1
|
||||||
order by created_at desc limit 1) != 'Inventory'"#)
|
order by created_at desc limit 1) != 'Inventory'"#)
|
||||||
.bind(item_id.0)
|
.bind(item_id.0)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||||
.bind(item_id.0)
|
.bind(item_id.0)
|
||||||
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
.bind(sqlx::types::Json(PgItemLocationDetail::from(item_location)))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&mut tx).await?;
|
||||||
}
|
}
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) {
|
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
||||||
.bind(mag_item_id.0)
|
.bind(mag_item_id.0)
|
||||||
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::FeedMag{food: *tool_item_id})))
|
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::FeedMag{food: *tool_item_id})))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) {
|
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
||||||
.bind(mag_item_id.0)
|
.bind(mag_item_id.0)
|
||||||
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::OwnerChange(character.char_class, character.section_id))))
|
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::OwnerChange(character.char_class, character.section_id))))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) {
|
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> {
|
||||||
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);")
|
||||||
.bind(mag_item_id.0)
|
.bind(mag_item_id.0)
|
||||||
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::MagCell(*mag_cell_id))))
|
.bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::MagCell(*mag_cell_id))))
|
||||||
.execute(&self.pool).await.unwrap();
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_items_by_character(&self, char: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, char: &CharacterEntity) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
let q = r#"select * from (
|
let q = r#"select * from (
|
||||||
select distinct on (item_location.item)
|
select distinct on (item_location.item)
|
||||||
item.id,
|
item.id,
|
||||||
@ -388,20 +399,20 @@ impl EntityGateway for PostgresGateway {
|
|||||||
let items = sqlx::query_as::<_, PgItemWithLocation>(q)
|
let items = sqlx::query_as::<_, PgItemWithLocation>(q)
|
||||||
.bind(char.id.0)
|
.bind(char.id.0)
|
||||||
.fetch(&self.pool);
|
.fetch(&self.pool);
|
||||||
join_all(items
|
Ok(join_all(items
|
||||||
.filter_map(|item: Result<PgItemWithLocation, _>| {
|
.filter_map(|item: Result<PgItemWithLocation, _>| {
|
||||||
let item = item.ok()?;
|
let item = item.ok()?;
|
||||||
Some(ItemEntity {
|
Some(ItemEntity {
|
||||||
id: ItemEntityId(item.id as u32),
|
id: ItemEntityId(item.id as u32),
|
||||||
item: item.item.0.into(),
|
item: item.item.0.into(),
|
||||||
location: item.location.0.into()
|
location: item.location.0.into()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(|item: ItemEntity| {
|
.map(|item: ItemEntity| {
|
||||||
self.apply_item_modifications(item)
|
self.apply_item_modifications(item)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.await
|
.await
|
||||||
).await
|
).await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@ const SHIP_MENU_ID: u32 = 1;
|
|||||||
pub enum CharacterError {
|
pub enum CharacterError {
|
||||||
InvalidMenuSelection(u32, u32),
|
InvalidMenuSelection(u32, u32),
|
||||||
ClientNotFound(ClientId),
|
ClientNotFound(ClientId),
|
||||||
|
CouldNotLoadSettings,
|
||||||
|
CouldNotLoadCharacters,
|
||||||
|
CouldNotLoadGuildcard,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -310,12 +313,11 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||||
let user = client.user.as_ref().unwrap();
|
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).await {
|
let settings = match self.entity_gateway.get_user_settings_by_user(&user).await {
|
||||||
Some(settings) => settings,
|
Ok(settings) => settings,
|
||||||
None => {
|
Err(_) => {
|
||||||
let user_settings = NewUserSettingsEntity::new(user.id);
|
let user_settings = NewUserSettingsEntity::new(user.id);
|
||||||
self.entity_gateway.create_user_settings(user_settings).await.unwrap()
|
self.entity_gateway.create_user_settings(user_settings).await.map_err(|_| CharacterError::CouldNotLoadSettings)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -329,7 +331,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
||||||
if client.characters.is_none() {
|
if client.characters.is_none() {
|
||||||
client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await);
|
client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadCharacters)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if select.reason == 0 {
|
if select.reason == 0 {
|
||||||
@ -374,7 +376,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
|
|
||||||
async fn guildcard_data_header(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn guildcard_data_header(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
||||||
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
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()).await;
|
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();
|
let bytes = guildcard_data.guildcard.as_bytes();
|
||||||
let mut crc = crc32::Digest::new(crc32::IEEE);
|
let mut crc = crc32::Digest::new(crc32::IEEE);
|
||||||
|
@ -60,7 +60,7 @@ impl SendServerPacket for SendLoginPacket {
|
|||||||
pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result<UserAccountEntity, AccountStatus> {
|
pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result<UserAccountEntity, AccountStatus> {
|
||||||
let username = array_to_utf8(pkt.username).map_err(|_err| AccountStatus::Error)?;
|
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 password = array_to_utf8(pkt.password).map_err(|_err| AccountStatus::Error)?;
|
||||||
let user = entity_gateway.get_user_by_name(username).await.ok_or(AccountStatus::InvalidUser)?;
|
let user = entity_gateway.get_user_by_name(username).await.map_err(|_| AccountStatus::InvalidUser)?;
|
||||||
let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?;
|
let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?;
|
||||||
match verified {
|
match verified {
|
||||||
true => if user.banned_until.map(|banned| banned > chrono::Utc::now()).unwrap_or(false) {
|
true => if user.banned_until.map(|banned| banned > chrono::Utc::now()).unwrap_or(false) {
|
||||||
|
@ -48,10 +48,12 @@ pub enum ItemManagerError {
|
|||||||
CannotGetIndividualItem,
|
CannotGetIndividualItem,
|
||||||
InvalidSlot(u8, u8), // slots available, slot attempted
|
InvalidSlot(u8, u8), // slots available, slot attempted
|
||||||
NoArmorEquipped,
|
NoArmorEquipped,
|
||||||
|
ItemIdNotInInventory(ClientItemId),
|
||||||
|
GatewayError(#[from] crate::entity::gateway::GatewayError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, character: &CharacterEntity, inventory: &CharacterInventory) {
|
async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, character: &CharacterEntity, inventory: &CharacterInventory) -> Result<(), ItemManagerError> {
|
||||||
for (slot, item) in inventory.iter().enumerate() {
|
for (slot, item) in inventory.iter().enumerate() {
|
||||||
match item {
|
match item {
|
||||||
InventoryItem::Individual(individual_inventory_item) => {
|
InventoryItem::Individual(individual_inventory_item) => {
|
||||||
@ -62,7 +64,7 @@ async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, char
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: individual_inventory_item.equipped,
|
equipped: individual_inventory_item.equipped,
|
||||||
}
|
}
|
||||||
).await
|
).await?
|
||||||
},
|
},
|
||||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||||
for entity_id in stacked_inventory_item.entity_ids.iter() {
|
for entity_id in stacked_inventory_item.entity_ids.iter() {
|
||||||
@ -72,10 +74,12 @@ async fn update_inventory_slots<EG: EntityGateway>(entity_gateway: &mut EG, char
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;
|
}).await?
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,8 +115,8 @@ impl ItemManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Result
|
// TODO: Result
|
||||||
pub async fn load_character<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) {
|
pub async fn load_character<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) -> Result<(), ItemManagerError> {
|
||||||
let items = entity_gateway.get_items_by_character(&character).await;
|
let items = entity_gateway.get_items_by_character(&character).await?;
|
||||||
let inventory_items = items.clone().into_iter()
|
let inventory_items = items.clone().into_iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
match item.location {
|
match item.location {
|
||||||
@ -204,6 +208,7 @@ impl ItemManager {
|
|||||||
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
|
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
|
||||||
self.character_inventory.insert(character.id, inventory);
|
self.character_inventory.insert(character.id, inventory);
|
||||||
self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new())));
|
self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new())));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
|
pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
|
||||||
@ -392,7 +397,7 @@ impl ItemManager {
|
|||||||
y: item_drop.y,
|
y: item_drop.y,
|
||||||
z: item_drop.z,
|
z: item_drop.z,
|
||||||
}
|
}
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
FloorItem::Individual(IndividualFloorItem {
|
FloorItem::Individual(IndividualFloorItem {
|
||||||
entity_id: entity.id,
|
entity_id: entity.id,
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -413,7 +418,7 @@ impl ItemManager {
|
|||||||
y: item_drop.y,
|
y: item_drop.y,
|
||||||
z: item_drop.z,
|
z: item_drop.z,
|
||||||
}
|
}
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
FloorItem::Stacked(StackedFloorItem {
|
FloorItem::Stacked(StackedFloorItem {
|
||||||
entity_ids: vec![entity.id],
|
entity_ids: vec![entity.id],
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -483,7 +488,7 @@ impl ItemManager {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
update_inventory_slots(entity_gateway, character, &inventory).await;
|
update_inventory_slots(entity_gateway, character, &inventory).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,7 +818,7 @@ impl ItemManager {
|
|||||||
item_entities.push(entity_gateway.create_item(NewItemEntity {
|
item_entities.push(entity_gateway.create_item(NewItemEntity {
|
||||||
location: ItemLocation::Shop,
|
location: ItemLocation::Shop,
|
||||||
item: ItemDetail::Tool(tool),
|
item: ItemDetail::Tool(tool),
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?);
|
}).await?);
|
||||||
}
|
}
|
||||||
let floor_item = StackedFloorItem {
|
let floor_item = StackedFloorItem {
|
||||||
entity_ids: item_entities.into_iter().map(|i| i.id).collect(),
|
entity_ids: item_entities.into_iter().map(|i| i.id).collect(),
|
||||||
@ -843,7 +848,7 @@ impl ItemManager {
|
|||||||
let item_entity = entity_gateway.create_item(NewItemEntity {
|
let item_entity = entity_gateway.create_item(NewItemEntity {
|
||||||
location: ItemLocation::Shop,
|
location: ItemLocation::Shop,
|
||||||
item: ItemDetail::Tool(tool),
|
item: ItemDetail::Tool(tool),
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
let floor_item = IndividualFloorItem {
|
let floor_item = IndividualFloorItem {
|
||||||
entity_id: item_entity.id,
|
entity_id: item_entity.id,
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -861,7 +866,7 @@ impl ItemManager {
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot.0,
|
slot: slot.0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;//.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
picked_up_item.item_id
|
picked_up_item.item_id
|
||||||
};
|
};
|
||||||
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
||||||
@ -871,7 +876,7 @@ impl ItemManager {
|
|||||||
let item_entity = entity_gateway.create_item(NewItemEntity {
|
let item_entity = entity_gateway.create_item(NewItemEntity {
|
||||||
location: ItemLocation::Shop,
|
location: ItemLocation::Shop,
|
||||||
item: item_detail.clone(),
|
item: item_detail.clone(),
|
||||||
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
let floor_item = IndividualFloorItem {
|
let floor_item = IndividualFloorItem {
|
||||||
entity_id: item_entity.id,
|
entity_id: item_entity.id,
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@ -889,7 +894,7 @@ impl ItemManager {
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: slot.0,
|
slot: slot.0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}).await;//.ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await?;
|
||||||
picked_up_item.item_id
|
picked_up_item.item_id
|
||||||
};
|
};
|
||||||
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?
|
||||||
|
@ -18,7 +18,7 @@ use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState
|
|||||||
use crate::common::leveltable::CharacterLevelTable;
|
use crate::common::leveltable::CharacterLevelTable;
|
||||||
use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage};
|
||||||
|
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
|
use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
|
||||||
use crate::entity::character::{CharacterEntity, SectionID};
|
use crate::entity::character::{CharacterEntity, SectionID};
|
||||||
|
|
||||||
@ -62,6 +62,7 @@ pub enum ShipError {
|
|||||||
IoError(#[from] std::io::Error),
|
IoError(#[from] std::io::Error),
|
||||||
NotEnoughMeseta(ClientId, u32),
|
NotEnoughMeseta(ClientId, u32),
|
||||||
ShopError,
|
ShopError,
|
||||||
|
GatewayError(#[from] GatewayError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user