Compare commits
5 Commits
fe472eaae2
...
13c6592438
Author | SHA1 | Date | |
---|---|---|---|
13c6592438 | |||
7bd385d580 | |||
f09c73611f | |||
d495ec97f2 | |||
31ebc1af32 |
@ -64,12 +64,12 @@ fn main() {
|
|||||||
};
|
};
|
||||||
let fake_user = entity_gateway.create_user(fake_user).await.unwrap();
|
let fake_user = entity_gateway.create_user(fake_user).await.unwrap();
|
||||||
entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await.unwrap();
|
entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await.unwrap();
|
||||||
let mut character = NewCharacterEntity::new(fake_user.id, 1);
|
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||||
character.name = format!("Test Char {}", i*2);
|
character.name = format!("Test Char {}", i*2);
|
||||||
let character = entity_gateway.create_character(character).await.unwrap();
|
let character = entity_gateway.create_character(character).await.unwrap();
|
||||||
entity_gateway.set_character_meseta(&character.id, item::Meseta(999999)).await.unwrap();
|
entity_gateway.set_character_meseta(&character.id, item::Meseta(999999)).await.unwrap();
|
||||||
entity_gateway.set_bank_meseta(&character.id, &item::BankName("".into()), item::Meseta(999999)).await.unwrap();
|
entity_gateway.set_bank_meseta(&character.id, &item::BankName("".into()), item::Meseta(999999)).await.unwrap();
|
||||||
let mut character = NewCharacterEntity::new(fake_user.id, 1);
|
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||||
character.slot = 2;
|
character.slot = 2;
|
||||||
character.name = "ItemRefactor".into();
|
character.name = "ItemRefactor".into();
|
||||||
character.exp = 80000000;
|
character.exp = 80000000;
|
||||||
|
@ -157,7 +157,7 @@ pub struct CharacterAppearance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct TechLevel(pub u8);
|
pub struct TechLevel(pub u8);
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
@ -167,16 +167,14 @@ pub struct CharacterTechniques {
|
|||||||
|
|
||||||
impl CharacterTechniques {
|
impl CharacterTechniques {
|
||||||
pub fn set_tech(&mut self, tech: Technique, level: TechLevel) {
|
pub fn set_tech(&mut self, tech: Technique, level: TechLevel) {
|
||||||
self.techs.insert(tech, TechLevel(level.0 - 1));
|
self.techs.insert(tech, TechLevel(level.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// from_bytes
|
|
||||||
|
|
||||||
pub fn as_bytes(&self) -> [u8; 20] {
|
pub fn as_bytes(&self) -> [u8; 20] {
|
||||||
self.techs.iter()
|
self.techs.iter()
|
||||||
.fold([0xFF; 20], |mut techlist, (tech, level)| {
|
.fold([0xFF; 20], |mut techlist, (tech, level)| {
|
||||||
let index = tech.as_value();
|
let index = tech.as_value();
|
||||||
techlist[index as usize] = level.0;
|
techlist[index as usize] = level.0 - 1;
|
||||||
techlist
|
techlist
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -264,82 +262,6 @@ pub struct CharacterMaterials {
|
|||||||
pub tp: u32,
|
pub tp: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct CharacterKeyboardConfig {
|
|
||||||
pub keyboard_config: [u8; 0x16C],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CharacterKeyboardConfig {
|
|
||||||
fn default() -> CharacterKeyboardConfig {
|
|
||||||
CharacterKeyboardConfig {
|
|
||||||
keyboard_config: DEFAULT_KEYBOARD_CONFIG1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CharacterKeyboardConfig {
|
|
||||||
fn new(preset: usize) -> CharacterKeyboardConfig {
|
|
||||||
match preset {
|
|
||||||
1 => {
|
|
||||||
CharacterKeyboardConfig {
|
|
||||||
keyboard_config: DEFAULT_KEYBOARD_CONFIG1,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
CharacterKeyboardConfig {
|
|
||||||
keyboard_config: DEFAULT_KEYBOARD_CONFIG2,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
3 => {
|
|
||||||
CharacterKeyboardConfig {
|
|
||||||
keyboard_config: DEFAULT_KEYBOARD_CONFIG3,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
4 => {
|
|
||||||
CharacterKeyboardConfig {
|
|
||||||
keyboard_config: DEFAULT_KEYBOARD_CONFIG4,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
CharacterKeyboardConfig {
|
|
||||||
keyboard_config: DEFAULT_KEYBOARD_CONFIG1,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, new_config: &KeyboardConfig) {
|
|
||||||
self.keyboard_config = new_config.keyboard_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_bytes(&self) -> [u8; 0x16C] {
|
|
||||||
self.keyboard_config
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct CharacterGamepadConfig {
|
|
||||||
pub gamepad_config: [u8; 0x38],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CharacterGamepadConfig {
|
|
||||||
fn default() -> CharacterGamepadConfig {
|
|
||||||
CharacterGamepadConfig {
|
|
||||||
gamepad_config: DEFAULT_GAMEPAD_CONFIG,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CharacterGamepadConfig {
|
|
||||||
pub fn update(&mut self, new_config: &GamepadConfig) {
|
|
||||||
self.gamepad_config = new_config.gamepad_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_bytes(&self) -> [u8; 0x38] {
|
|
||||||
self.gamepad_config
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default, derive_more::Display)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default, derive_more::Display)]
|
||||||
pub struct CharacterEntityId(pub u32);
|
pub struct CharacterEntityId(pub u32);
|
||||||
|
|
||||||
@ -363,12 +285,10 @@ pub struct NewCharacterEntity {
|
|||||||
|
|
||||||
pub tech_menu: CharacterTechMenu,
|
pub tech_menu: CharacterTechMenu,
|
||||||
pub option_flags: u32,
|
pub option_flags: u32,
|
||||||
pub keyboard_config: CharacterKeyboardConfig,
|
|
||||||
pub gamepad_config: CharacterGamepadConfig,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NewCharacterEntity {
|
impl NewCharacterEntity {
|
||||||
pub fn new(user: UserAccountId, keyboard_config_preset: usize,) -> NewCharacterEntity {
|
pub fn new(user: UserAccountId) -> NewCharacterEntity {
|
||||||
NewCharacterEntity {
|
NewCharacterEntity {
|
||||||
user_id: user,
|
user_id: user,
|
||||||
slot: 0,
|
slot: 0,
|
||||||
@ -384,8 +304,6 @@ impl NewCharacterEntity {
|
|||||||
materials: CharacterMaterials::default(),
|
materials: CharacterMaterials::default(),
|
||||||
tech_menu: CharacterTechMenu::default(),
|
tech_menu: CharacterTechMenu::default(),
|
||||||
option_flags: 0,
|
option_flags: 0,
|
||||||
keyboard_config: CharacterKeyboardConfig::new(keyboard_config_preset),
|
|
||||||
gamepad_config: CharacterGamepadConfig::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -411,8 +329,6 @@ pub struct CharacterEntity {
|
|||||||
|
|
||||||
pub tech_menu: CharacterTechMenu,
|
pub tech_menu: CharacterTechMenu,
|
||||||
pub option_flags: u32,
|
pub option_flags: u32,
|
||||||
pub keyboard_config: CharacterKeyboardConfig,
|
|
||||||
pub gamepad_config: CharacterGamepadConfig,
|
|
||||||
|
|
||||||
pub playtime: u32,
|
pub playtime: u32,
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,10 @@ impl EntityGateway for InMemoryGatewayTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn save_user_settings(&mut self, settings: &UserSettingsEntity) -> Result<(), GatewayError> {
|
||||||
|
self.original_gateway.save_user_settings(settings).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> {
|
async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> {
|
||||||
copy_if_needed(&mut *self.working_gateway.characters.lock().await,
|
copy_if_needed(&mut *self.working_gateway.characters.lock().await,
|
||||||
&*self.original_gateway.characters.lock().await,
|
&*self.original_gateway.characters.lock().await,
|
||||||
@ -418,6 +422,12 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
.ok_or(GatewayError::Error)
|
.ok_or(GatewayError::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn save_user_settings(&mut self, settings: &UserSettingsEntity) -> Result<(), GatewayError> {
|
||||||
|
let mut user_settings = self.user_settings.lock().await;
|
||||||
|
user_settings.insert(settings.id, settings.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_characters_by_user(&mut self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
async fn get_characters_by_user(&mut self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
|
||||||
let characters = self.characters.lock().await;
|
let characters = self.characters.lock().await;
|
||||||
const NONE: Option<CharacterEntity> = None;
|
const NONE: Option<CharacterEntity> = None;
|
||||||
@ -452,8 +462,6 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
materials: character.materials,
|
materials: character.materials,
|
||||||
tech_menu: character.tech_menu,
|
tech_menu: character.tech_menu,
|
||||||
option_flags: character.option_flags,
|
option_flags: character.option_flags,
|
||||||
keyboard_config: character.keyboard_config,
|
|
||||||
gamepad_config: character.gamepad_config,
|
|
||||||
playtime: 0,
|
playtime: 0,
|
||||||
};
|
};
|
||||||
characters.insert(new_character.id, new_character.clone());
|
characters.insert(new_character.id, new_character.clone());
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
alter table player_character
|
||||||
|
drop column keyboard_config,
|
||||||
|
drop column gamepad_config;
|
@ -217,8 +217,6 @@ pub struct PgCharacter {
|
|||||||
tp: i16,
|
tp: i16,
|
||||||
|
|
||||||
tech_menu: Vec<u8>,
|
tech_menu: Vec<u8>,
|
||||||
keyboard_config: Vec<u8>,
|
|
||||||
gamepad_config: Vec<u8>,
|
|
||||||
|
|
||||||
playtime: i32,
|
playtime: i32,
|
||||||
}
|
}
|
||||||
@ -270,12 +268,6 @@ impl From<PgCharacter> for CharacterEntity {
|
|||||||
tech_menu: CharacterTechMenu {
|
tech_menu: CharacterTechMenu {
|
||||||
tech_menu: vec_to_array(other.tech_menu)
|
tech_menu: vec_to_array(other.tech_menu)
|
||||||
},
|
},
|
||||||
keyboard_config: CharacterKeyboardConfig {
|
|
||||||
keyboard_config: vec_to_array(other.keyboard_config)
|
|
||||||
},
|
|
||||||
gamepad_config: CharacterGamepadConfig {
|
|
||||||
gamepad_config: vec_to_array(other.gamepad_config)
|
|
||||||
},
|
|
||||||
playtime: other.playtime as u32,
|
playtime: other.playtime as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ async fn save_user_settings(conn: &mut sqlx::PgConnection, settings: &UserSettin
|
|||||||
.bind(&settings.settings.symbol_chats.to_vec())
|
.bind(&settings.settings.symbol_chats.to_vec())
|
||||||
.bind(settings.settings.team_name.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::<Vec<u8>>())
|
.bind(settings.settings.team_name.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::<Vec<u8>>())
|
||||||
.bind(settings.id.0)
|
.bind(settings.id.0)
|
||||||
.fetch_one(conn).await?;
|
.execute(conn).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,16 +229,14 @@ async fn create_character(conn: &mut sqlx::PgConnection, char: NewCharacterEntit
|
|||||||
hair, hair_r, hair_g, hair_b, prop_x,
|
hair, hair_r, hair_g, hair_b, prop_x,
|
||||||
prop_y, techs, config, infoboard, guildcard,
|
prop_y, techs, config, infoboard, guildcard,
|
||||||
power, mind, def, evade, luck,
|
power, mind, def, evade, luck,
|
||||||
hp, tp, tech_menu, option_flags, keyboard_config,
|
hp, tp, tech_menu, option_flags, playtime)
|
||||||
gamepad_config, playtime)
|
|
||||||
values
|
values
|
||||||
($1, $2, $3, $4, $5,
|
($1, $2, $3, $4, $5,
|
||||||
$6, $7, $8, $9, $10,
|
$6, $7, $8, $9, $10,
|
||||||
$11, $12, $13, $14, $15,
|
$11, $12, $13, $14, $15,
|
||||||
$16, $17, $18, $19, $20,
|
$16, $17, $18, $19, $20,
|
||||||
$21, $22, $23, $24, $25,
|
$21, $22, $23, $24, $25,
|
||||||
$26, $27, $28, $29, $30,
|
$26, $27, $28, $29, $30)
|
||||||
$31, $32)
|
|
||||||
returning *;"#;
|
returning *;"#;
|
||||||
let character = sqlx::query_as::<_, PgCharacter>(q)
|
let character = sqlx::query_as::<_, PgCharacter>(q)
|
||||||
.bind(char.user_id.0)
|
.bind(char.user_id.0)
|
||||||
@ -270,8 +268,6 @@ async fn create_character(conn: &mut sqlx::PgConnection, char: NewCharacterEntit
|
|||||||
.bind(char.materials.tp as i16)
|
.bind(char.materials.tp as i16)
|
||||||
.bind(char.tech_menu.tech_menu.to_vec())
|
.bind(char.tech_menu.tech_menu.to_vec())
|
||||||
.bind(char.option_flags as i32)
|
.bind(char.option_flags as i32)
|
||||||
.bind(&char.keyboard_config.keyboard_config.to_vec())
|
|
||||||
.bind(&char.gamepad_config.gamepad_config.to_vec())
|
|
||||||
.bind(0)
|
.bind(0)
|
||||||
.fetch_one(conn).await?;
|
.fetch_one(conn).await?;
|
||||||
|
|
||||||
@ -298,8 +294,8 @@ async fn save_character(conn: &mut sqlx::PgConnection, char: &CharacterEntity) -
|
|||||||
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,
|
||||||
evade=$24, luck=$25, hp=$26, tp=$27, tech_menu=$28, option_flags=$29, keyboard_config=$30, gamepad_config=$31, playtime=$32
|
evade=$24, luck=$25, hp=$26, tp=$27, tech_menu=$28, option_flags=$29, playtime=$30
|
||||||
where id=$33;"#;
|
where id=$31;"#;
|
||||||
sqlx::query(q)
|
sqlx::query(q)
|
||||||
.bind(char.user_id.0) // $1
|
.bind(char.user_id.0) // $1
|
||||||
.bind(char.slot as i16) // $2
|
.bind(char.slot as i16) // $2
|
||||||
@ -330,10 +326,8 @@ async fn save_character(conn: &mut sqlx::PgConnection, char: &CharacterEntity) -
|
|||||||
.bind(char.materials.tp as i16) // $27
|
.bind(char.materials.tp as i16) // $27
|
||||||
.bind(char.tech_menu.tech_menu.to_vec()) // $28
|
.bind(char.tech_menu.tech_menu.to_vec()) // $28
|
||||||
.bind(char.option_flags as i32) // $29
|
.bind(char.option_flags as i32) // $29
|
||||||
.bind(&char.keyboard_config.keyboard_config.to_vec()) // $30
|
.bind(char.playtime as i32) // $30
|
||||||
.bind(&char.gamepad_config.gamepad_config.to_vec()) // $31
|
.bind(char.id.0 as i32) // $31
|
||||||
.bind(char.playtime as i32) // $32
|
|
||||||
.bind(char.id.0 as i32) // $33
|
|
||||||
.execute(conn).await?;
|
.execute(conn).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -747,7 +747,7 @@ impl<EG: EntityGateway + Clone> InterserverActor for CharacterServerState<EG> {
|
|||||||
|
|
||||||
|
|
||||||
fn new_character_from_preview(user: &UserAccountEntity, preview: &CharacterPreview) -> NewCharacterEntity {
|
fn new_character_from_preview(user: &UserAccountEntity, preview: &CharacterPreview) -> NewCharacterEntity {
|
||||||
let mut character = NewCharacterEntity::new(user.id, 1); // it should not be possible for the client to specify the kbm config preset from the char create screen
|
let mut character = NewCharacterEntity::new(user.id);
|
||||||
character.slot = preview.slot;
|
character.slot = preview.slot;
|
||||||
character.name = String::from_utf16_lossy(&preview.character.name).trim_matches(char::from(0)).into();
|
character.name = String::from_utf16_lossy(&preview.character.name).trim_matches(char::from(0)).into();
|
||||||
character.section_id = preview.character.section_id.into();
|
character.section_id = preview.character.section_id.into();
|
||||||
|
@ -113,7 +113,7 @@ where
|
|||||||
move |(mut item_state, mut transaction), _| {
|
move |(mut item_state, mut transaction), _| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let mut inventory = item_state.inventory(&character_id).await?;
|
let mut inventory = item_state.inventory(&character_id).await?;
|
||||||
let item = inventory.take_item(&item_id, amount).ok_or_else(|| ItemStateError::NoFloorItem(item_id))?;
|
let item = inventory.take_item(&item_id, amount).ok_or_else(|| ItemStateError::NoInventoryItem(item_id))?;
|
||||||
|
|
||||||
transaction.gateway().set_character_inventory(&character_id, &inventory.as_inventory_entity(&character_id)).await?;
|
transaction.gateway().set_character_inventory(&character_id, &inventory.as_inventory_entity(&character_id)).await?;
|
||||||
item_state.set_inventory(inventory).await;
|
item_state.set_inventory(inventory).await;
|
||||||
@ -245,6 +245,7 @@ where
|
|||||||
let mut bank = item_state.bank(&character_id).await?;
|
let mut bank = item_state.bank(&character_id).await?;
|
||||||
bank.remove_meseta(amount)?;
|
bank.remove_meseta(amount)?;
|
||||||
transaction.gateway().set_bank_meseta(&character_id, &bank.name, bank.meseta).await?;
|
transaction.gateway().set_bank_meseta(&character_id, &bank.name, bank.meseta).await?;
|
||||||
|
item_state.set_bank(bank).await;
|
||||||
|
|
||||||
Ok(((item_state, transaction), ()))
|
Ok(((item_state, transaction), ()))
|
||||||
})
|
})
|
||||||
@ -286,6 +287,7 @@ where
|
|||||||
let mut bank = item_state.bank(&character_id).await?;
|
let mut bank = item_state.bank(&character_id).await?;
|
||||||
bank.add_meseta(amount)?;
|
bank.add_meseta(amount)?;
|
||||||
transaction.gateway().set_bank_meseta(&character_id, &bank.name, bank.meseta).await?;
|
transaction.gateway().set_bank_meseta(&character_id, &bank.name, bank.meseta).await?;
|
||||||
|
item_state.set_bank(bank).await;
|
||||||
|
|
||||||
Ok(((item_state, transaction), ()))
|
Ok(((item_state, transaction), ()))
|
||||||
})
|
})
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use anyhow::Context;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
use rand::distributions::{WeightedIndex, Distribution};
|
use rand::distributions::{WeightedIndex, Distribution};
|
||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::character::CharacterEntity;
|
use crate::entity::character::{CharacterEntity, TechLevel};
|
||||||
use crate::entity::item::mag::{MagCell, MagCellError};
|
use crate::entity::item::mag::{MagCell, MagCellError};
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use crate::entity::item::tool::{Tool, ToolType};
|
||||||
|
use crate::entity::item::tech::{TechniqueDisk, Technique};
|
||||||
use crate::entity::item::{ItemDetail, ItemEntityId};
|
use crate::entity::item::{ItemDetail, ItemEntityId};
|
||||||
use crate::ship::items::state::{ItemStateProxy, ItemStateError};
|
use crate::ship::items::state::{ItemStateProxy, ItemStateError};
|
||||||
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
||||||
@ -18,7 +20,7 @@ pub enum ApplyItemError {
|
|||||||
NoCharacter,
|
NoCharacter,
|
||||||
#[error("item not equipped")]
|
#[error("item not equipped")]
|
||||||
ItemNotEquipped,
|
ItemNotEquipped,
|
||||||
#[error("invalid item")]
|
#[error("could not use item invalid item")]
|
||||||
InvalidItem,
|
InvalidItem,
|
||||||
#[error("gateway error {0}")]
|
#[error("gateway error {0}")]
|
||||||
GatewayError(#[from] GatewayError),
|
GatewayError(#[from] GatewayError),
|
||||||
@ -307,6 +309,21 @@ where
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn apply_tech<'a, EG>(item_state: &mut ItemStateProxy,
|
||||||
|
entity_gateway: &mut EG,
|
||||||
|
character: &mut CharacterEntity,
|
||||||
|
_entity_id: ItemEntityId,
|
||||||
|
tech: TechniqueDisk)
|
||||||
|
-> Result<Vec<ApplyItemAction>, anyhow::Error>
|
||||||
|
where
|
||||||
|
EG: EntityGateway + ?Sized,
|
||||||
|
{
|
||||||
|
// TODO: make sure the class can learn that specific tech
|
||||||
|
character.techs.set_tech(tech.tech, TechLevel(tech.level as u8));
|
||||||
|
entity_gateway.save_character(character).await.unwrap();
|
||||||
|
Ok(vec![ApplyItemAction::UpdateCharacter(Box::new(character.clone()))])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn apply_item<'a, EG>(item_state: &mut ItemStateProxy,
|
pub async fn apply_item<'a, EG>(item_state: &mut ItemStateProxy,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
@ -320,7 +337,11 @@ where
|
|||||||
InventoryItemDetail::Individual(individual_item) => {
|
InventoryItemDetail::Individual(individual_item) => {
|
||||||
match individual_item.item {
|
match individual_item.item {
|
||||||
ItemDetail::Tool(tool) => apply_tool(item_state, entity_gateway, character, individual_item.entity_id, tool.tool).await,
|
ItemDetail::Tool(tool) => apply_tool(item_state, entity_gateway, character, individual_item.entity_id, tool.tool).await,
|
||||||
_ => Err(ApplyItemError::InvalidItem.into())
|
ItemDetail::TechniqueDisk(tech) => apply_tech(item_state, entity_gateway, character, individual_item.entity_id, tech).await,
|
||||||
|
_ => Err(anyhow::Error::from(ApplyItemError::InvalidItem))
|
||||||
|
.with_context(|| {
|
||||||
|
format!("item {:?}", individual_item)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InventoryItemDetail::Stacked(stacked_item) => {
|
InventoryItemDetail::Stacked(stacked_item) => {
|
||||||
|
@ -64,10 +64,10 @@ pub struct BankItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BankItem {
|
impl BankItem {
|
||||||
pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, ItemStateError>
|
pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, anyhow::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(T, ItemEntityId) -> Fut,
|
F: FnMut(T, ItemEntityId) -> Fut,
|
||||||
Fut: Future<Output=Result<T, ItemStateError>>,
|
Fut: Future<Output=Result<T, anyhow::Error>>,
|
||||||
{
|
{
|
||||||
match &self.item {
|
match &self.item {
|
||||||
BankItemDetail::Individual(individual_item) => {
|
BankItemDetail::Individual(individual_item) => {
|
||||||
@ -125,27 +125,27 @@ impl BankState {
|
|||||||
self.item_id_counter = base_item_id + self.bank.0.len() as u32;
|
self.item_id_counter = base_item_id + self.bank.0.len() as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_meseta(&mut self, amount: u32) -> Result<(), ItemStateError> {
|
pub fn add_meseta(&mut self, amount: u32) -> Result<(), anyhow::Error> {
|
||||||
if self.meseta.0 + amount > 999999 {
|
if self.meseta.0 + amount > 999999 {
|
||||||
return Err(ItemStateError::FullOfMeseta)
|
return Err(ItemStateError::FullOfMeseta.into())
|
||||||
}
|
}
|
||||||
self.meseta.0 += amount;
|
self.meseta.0 += amount;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_meseta(&mut self, amount: u32) -> Result<(), ItemStateError> {
|
pub fn remove_meseta(&mut self, amount: u32) -> Result<(), anyhow::Error> {
|
||||||
if amount > self.meseta.0 {
|
if amount > self.meseta.0 {
|
||||||
return Err(ItemStateError::InvalidMesetaRemoval(amount))
|
return Err(ItemStateError::InvalidMesetaRemoval(amount).into())
|
||||||
}
|
}
|
||||||
self.meseta.0 -= amount;
|
self.meseta.0 -= amount;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_inventory_item(&mut self, item: InventoryItem) -> Result<AddItemResult, BankError> {
|
pub fn add_inventory_item(&mut self, item: InventoryItem) -> Result<AddItemResult, anyhow::Error> {
|
||||||
match item.item {
|
match item.item {
|
||||||
InventoryItemDetail::Individual(iitem) => {
|
InventoryItemDetail::Individual(iitem) => {
|
||||||
if self.bank.0.len() >= 30 {
|
if self.bank.0.len() >= 30 {
|
||||||
Err(BankError::BankFull)
|
Err(BankError::BankFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.bank.0.push(BankItem {
|
self.bank.0.push(BankItem {
|
||||||
@ -166,7 +166,7 @@ impl BankState {
|
|||||||
match existing_stack {
|
match existing_stack {
|
||||||
Some(existing_stack) => {
|
Some(existing_stack) => {
|
||||||
if existing_stack.entity_ids.len() + sitem.entity_ids.len() > sitem.tool.max_stack() {
|
if existing_stack.entity_ids.len() + sitem.entity_ids.len() > sitem.tool.max_stack() {
|
||||||
Err(BankError::StackFull)
|
Err(BankError::StackFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
existing_stack.entity_ids.append(&mut sitem.entity_ids.clone());
|
existing_stack.entity_ids.append(&mut sitem.entity_ids.clone());
|
||||||
@ -175,7 +175,7 @@ impl BankState {
|
|||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
if self.bank.0.len() >= 30 {
|
if self.bank.0.len() >= 30 {
|
||||||
Err(BankError::BankFull)
|
Err(BankError::BankFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.bank.0.push(BankItem {
|
self.bank.0.push(BankItem {
|
||||||
|
@ -33,7 +33,7 @@ pub struct FloorItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FloorItem {
|
impl FloorItem {
|
||||||
pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, ItemStateError>
|
pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, anyhow::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(T, ItemEntityId) -> Fut,
|
F: FnMut(T, ItemEntityId) -> Fut,
|
||||||
Fut: Future<Output=Result<T, ItemStateError>>,
|
Fut: Future<Output=Result<T, ItemStateError>>,
|
||||||
@ -53,10 +53,10 @@ impl FloorItem {
|
|||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn with_mag<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, ItemStateError>
|
pub async fn with_mag<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, anyhow::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(T, ItemEntityId, Mag) -> Fut,
|
F: FnMut(T, ItemEntityId, Mag) -> Fut,
|
||||||
Fut: Future<Output=Result<T, ItemStateError>>,
|
Fut: Future<Output=Result<T, anyhow::Error>>,
|
||||||
{
|
{
|
||||||
if let FloorItemDetail::Individual(individual_item) = &self.item {
|
if let FloorItemDetail::Individual(individual_item) = &self.item {
|
||||||
if let ItemDetail::Mag(mag) = &individual_item.item {
|
if let ItemDetail::Mag(mag) = &individual_item.item {
|
||||||
|
@ -60,7 +60,7 @@ impl InventoryItemDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this should probably go somewhere a bit more fundamental like ItemDetail
|
// TODO: this should probably go somewhere a bit more fundamental like ItemDetail
|
||||||
pub fn sell_price(&self) -> Result<u32, ItemStateError> {
|
pub fn sell_price(&self) -> Result<u32, anyhow::Error> {
|
||||||
match self {
|
match self {
|
||||||
InventoryItemDetail::Individual(individual_item) => {
|
InventoryItemDetail::Individual(individual_item) => {
|
||||||
match &individual_item.item {
|
match &individual_item.item {
|
||||||
@ -102,7 +102,7 @@ impl InventoryItemDetail {
|
|||||||
Ok((ToolShopItem::from(d).price() / 8) as u32)
|
Ok((ToolShopItem::from(d).price() / 8) as u32)
|
||||||
},
|
},
|
||||||
ItemDetail::Mag(_m) => {
|
ItemDetail::Mag(_m) => {
|
||||||
Err(ItemStateError::ItemNotSellable)
|
Err(ItemStateError::ItemNotSellable.into())
|
||||||
},
|
},
|
||||||
ItemDetail::ESWeapon(_e) => {
|
ItemDetail::ESWeapon(_e) => {
|
||||||
Ok(10u32)
|
Ok(10u32)
|
||||||
@ -126,10 +126,10 @@ pub struct InventoryItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl InventoryItem {
|
impl InventoryItem {
|
||||||
pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, ItemStateError>
|
pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, anyhow::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(T, ItemEntityId) -> Fut,
|
F: FnMut(T, ItemEntityId) -> Fut,
|
||||||
Fut: Future<Output=Result<T, ItemStateError>>,
|
Fut: Future<Output=Result<T, anyhow::Error>>,
|
||||||
{
|
{
|
||||||
match &self.item {
|
match &self.item {
|
||||||
InventoryItemDetail::Individual(individual_item) => {
|
InventoryItemDetail::Individual(individual_item) => {
|
||||||
@ -145,10 +145,10 @@ impl InventoryItem {
|
|||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn with_mag<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, ItemStateError>
|
pub async fn with_mag<F, Fut, T>(&self, mut param: T, mut func: F) -> Result<T, anyhow::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(T, ItemEntityId, Mag) -> Fut,
|
F: FnMut(T, ItemEntityId, Mag) -> Fut,
|
||||||
Fut: Future<Output=Result<T, ItemStateError>>,
|
Fut: Future<Output=Result<T, anyhow::Error>>,
|
||||||
{
|
{
|
||||||
if let InventoryItemDetail::Individual(individual_item) = &self.item {
|
if let InventoryItemDetail::Individual(individual_item) = &self.item {
|
||||||
if let ItemDetail::Mag(mag) = &individual_item.item {
|
if let ItemDetail::Mag(mag) = &individual_item.item {
|
||||||
@ -205,11 +205,11 @@ impl InventoryState {
|
|||||||
self.inventory.0.len()
|
self.inventory.0.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_floor_item(&mut self, item: FloorItem) -> Result<AddItemResult, InventoryError> {
|
pub fn add_floor_item(&mut self, item: FloorItem) -> Result<AddItemResult, anyhow::Error> {
|
||||||
match item.item {
|
match item.item {
|
||||||
FloorItemDetail::Individual(iitem) => {
|
FloorItemDetail::Individual(iitem) => {
|
||||||
if self.inventory.0.len() >= 30 {
|
if self.inventory.0.len() >= 30 {
|
||||||
Err(InventoryError::InventoryFull)
|
Err(InventoryError::InventoryFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.inventory.0.push(InventoryItem {
|
self.inventory.0.push(InventoryItem {
|
||||||
@ -229,7 +229,7 @@ impl InventoryState {
|
|||||||
match existing_stack {
|
match existing_stack {
|
||||||
Some(existing_stack) => {
|
Some(existing_stack) => {
|
||||||
if existing_stack.entity_ids.len() + sitem.entity_ids.len() > sitem.tool.max_stack() {
|
if existing_stack.entity_ids.len() + sitem.entity_ids.len() > sitem.tool.max_stack() {
|
||||||
Err(InventoryError::StackFull)
|
Err(InventoryError::StackFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
existing_stack.entity_ids.append(&mut sitem.entity_ids.clone());
|
existing_stack.entity_ids.append(&mut sitem.entity_ids.clone());
|
||||||
@ -238,7 +238,7 @@ impl InventoryState {
|
|||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
if self.inventory.0.len() >= 30 {
|
if self.inventory.0.len() >= 30 {
|
||||||
Err(InventoryError::InventoryFull)
|
Err(InventoryError::InventoryFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.inventory.0.push(InventoryItem {
|
self.inventory.0.push(InventoryItem {
|
||||||
@ -253,7 +253,7 @@ impl InventoryState {
|
|||||||
},
|
},
|
||||||
FloorItemDetail::Meseta(meseta) => {
|
FloorItemDetail::Meseta(meseta) => {
|
||||||
if self.meseta == Meseta(999999) {
|
if self.meseta == Meseta(999999) {
|
||||||
Err(InventoryError::MesetaFull)
|
Err(InventoryError::MesetaFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.meseta.0 = std::cmp::min(self.meseta.0 + meseta.0, 999999);
|
self.meseta.0 = std::cmp::min(self.meseta.0 + meseta.0, 999999);
|
||||||
@ -263,11 +263,11 @@ impl InventoryState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_item(&mut self, item: InventoryItem) -> Result<(AddItemResult, InventoryItem), InventoryError> {
|
pub fn add_item(&mut self, item: InventoryItem) -> Result<(AddItemResult, InventoryItem), anyhow::Error> {
|
||||||
match &item.item {
|
match &item.item {
|
||||||
InventoryItemDetail::Individual(_) => {
|
InventoryItemDetail::Individual(_) => {
|
||||||
if self.inventory.0.len() >= 30 {
|
if self.inventory.0.len() >= 30 {
|
||||||
Err(InventoryError::InventoryFull)
|
Err(InventoryError::InventoryFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.inventory.0.push(item);
|
self.inventory.0.push(item);
|
||||||
@ -290,7 +290,7 @@ impl InventoryState {
|
|||||||
match existing_stack {
|
match existing_stack {
|
||||||
Some(existing_stack) => {
|
Some(existing_stack) => {
|
||||||
if existing_stack.entity_ids.len() + sitem.entity_ids.len() > sitem.tool.max_stack() {
|
if existing_stack.entity_ids.len() + sitem.entity_ids.len() > sitem.tool.max_stack() {
|
||||||
Err(InventoryError::StackFull)
|
Err(InventoryError::StackFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
existing_stack.entity_ids.append(&mut sitem.entity_ids.clone());
|
existing_stack.entity_ids.append(&mut sitem.entity_ids.clone());
|
||||||
@ -307,7 +307,7 @@ impl InventoryState {
|
|||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
if self.inventory.0.len() >= 30 {
|
if self.inventory.0.len() >= 30 {
|
||||||
Err(InventoryError::InventoryFull)
|
Err(InventoryError::InventoryFull.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.inventory.0.push(item);
|
self.inventory.0.push(item);
|
||||||
@ -370,25 +370,25 @@ impl InventoryState {
|
|||||||
.find(|i| i.item_id == *item_id)
|
.find(|i| i.item_id == *item_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_meseta(&mut self, amount: u32) -> Result<(), ItemStateError> {
|
pub fn add_meseta(&mut self, amount: u32) -> Result<(), anyhow::Error> {
|
||||||
if self.meseta.0 == 999999 {
|
if self.meseta.0 == 999999 {
|
||||||
return Err(ItemStateError::FullOfMeseta)
|
return Err(ItemStateError::FullOfMeseta.into())
|
||||||
}
|
}
|
||||||
self.meseta.0 = std::cmp::min(self.meseta.0 + amount, 999999);
|
self.meseta.0 = std::cmp::min(self.meseta.0 + amount, 999999);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_meseta_no_overflow(&mut self, amount: u32) -> Result<(), ItemStateError> {
|
pub fn add_meseta_no_overflow(&mut self, amount: u32) -> Result<(), anyhow::Error> {
|
||||||
if self.meseta.0 + amount > 999999 {
|
if self.meseta.0 + amount > 999999 {
|
||||||
return Err(ItemStateError::FullOfMeseta)
|
return Err(ItemStateError::FullOfMeseta.into())
|
||||||
}
|
}
|
||||||
self.meseta.0 += amount;
|
self.meseta.0 += amount;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_meseta(&mut self, amount: u32) -> Result<(), ItemStateError> {
|
pub fn remove_meseta(&mut self, amount: u32) -> Result<(), anyhow::Error> {
|
||||||
if amount > self.meseta.0 {
|
if amount > self.meseta.0 {
|
||||||
return Err(ItemStateError::InvalidMesetaRemoval(amount))
|
return Err(ItemStateError::InvalidMesetaRemoval(amount).into())
|
||||||
}
|
}
|
||||||
self.meseta.0 -= amount;
|
self.meseta.0 -= amount;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -22,6 +22,8 @@ pub enum ItemStateError {
|
|||||||
NoCharacter(CharacterEntityId),
|
NoCharacter(CharacterEntityId),
|
||||||
#[error("room {0} not found")]
|
#[error("room {0} not found")]
|
||||||
NoRoom(RoomId),
|
NoRoom(RoomId),
|
||||||
|
#[error("inventory item {0} not found")]
|
||||||
|
NoInventoryItem(ClientItemId),
|
||||||
#[error("floor item {0} not found")]
|
#[error("floor item {0} not found")]
|
||||||
NoFloorItem(ClientItemId),
|
NoFloorItem(ClientItemId),
|
||||||
#[error("expected {0} to be a tool")]
|
#[error("expected {0} to be a tool")]
|
||||||
|
@ -34,8 +34,8 @@ pub async fn block_selected(id: ClientId,
|
|||||||
.meseta(inventory.meseta)
|
.meseta(inventory.meseta)
|
||||||
.inventory(&inventory)
|
.inventory(&inventory)
|
||||||
.bank(&bank)
|
.bank(&bank)
|
||||||
.keyboard_config(&client.character.keyboard_config.as_bytes())
|
.keyboard_config(&client.settings.settings.keyboard_config)
|
||||||
.gamepad_config(&client.character.gamepad_config.as_bytes())
|
.gamepad_config(&client.settings.settings.gamepad_config)
|
||||||
.symbol_chat(&client.settings.settings.symbol_chats)
|
.symbol_chat(&client.settings.settings.symbol_chats)
|
||||||
.tech_menu(&client.character.tech_menu.as_bytes())
|
.tech_menu(&client.character.tech_menu.as_bytes())
|
||||||
.option_flags(client.character.option_flags)
|
.option_flags(client.character.option_flags)
|
||||||
|
@ -48,8 +48,8 @@ where
|
|||||||
clients.with_mut(id, |client| {
|
clients.with_mut(id, |client| {
|
||||||
let mut entity_gateway = entity_gateway.clone();
|
let mut entity_gateway = entity_gateway.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
client.character.keyboard_config.update(&keyboard_config);
|
client.settings.settings.keyboard_config = keyboard_config.keyboard_config;
|
||||||
entity_gateway.save_character(&client.character).await
|
entity_gateway.save_user_settings(&client.settings).await
|
||||||
})}).await??;
|
})}).await??;
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
@ -65,8 +65,8 @@ where
|
|||||||
clients.with_mut(id, |client| {
|
clients.with_mut(id, |client| {
|
||||||
let mut entity_gateway = entity_gateway.clone();
|
let mut entity_gateway = entity_gateway.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
client.character.gamepad_config.update(&gamepad_config);
|
client.settings.settings.gamepad_config = gamepad_config.gamepad_config;
|
||||||
entity_gateway.save_character(&client.character).await
|
entity_gateway.save_user_settings(&client.settings).await
|
||||||
})}).await??;
|
})}).await??;
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use libpso::packet::login::{Login, Session};
|
|||||||
use libpso::{utf8_to_array, utf8_to_utf16_array};
|
use libpso::{utf8_to_array, utf8_to_utf16_array};
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: remove kb_conf_preset
|
||||||
pub async fn new_user_character<EG: EntityGateway + Clone>(entity_gateway: &mut EG, username: &str, password: &str, kb_conf_preset: usize) -> (UserAccountEntity, CharacterEntity) {
|
pub async fn new_user_character<EG: EntityGateway + Clone>(entity_gateway: &mut EG, username: &str, password: &str, kb_conf_preset: usize) -> (UserAccountEntity, CharacterEntity) {
|
||||||
let new_user = NewUserAccountEntity {
|
let new_user = NewUserAccountEntity {
|
||||||
email: format!("{}@pso.com", username),
|
email: format!("{}@pso.com", username),
|
||||||
@ -26,7 +27,7 @@ pub async fn new_user_character<EG: EntityGateway + Clone>(entity_gateway: &mut
|
|||||||
let user = entity_gateway.create_user(new_user).await.unwrap();
|
let user = entity_gateway.create_user(new_user).await.unwrap();
|
||||||
let new_settings = NewUserSettingsEntity::new(user.id);
|
let new_settings = NewUserSettingsEntity::new(user.id);
|
||||||
let _settings = entity_gateway.create_user_settings(new_settings).await.unwrap();
|
let _settings = entity_gateway.create_user_settings(new_settings).await.unwrap();
|
||||||
let new_character = NewCharacterEntity::new(user.id, kb_conf_preset);
|
let new_character = NewCharacterEntity::new(user.id);
|
||||||
let character = entity_gateway.create_character(new_character).await.unwrap();
|
let character = entity_gateway.create_character(new_character).await.unwrap();
|
||||||
entity_gateway.set_character_meseta(&character.id, Meseta(0)).await.unwrap();
|
entity_gateway.set_character_meseta(&character.id, Meseta(0)).await.unwrap();
|
||||||
entity_gateway.set_bank_meseta(&character.id, &BankName("".into()), Meseta(0)).await.unwrap();
|
entity_gateway.set_bank_meseta(&character.id, &BankName("".into()), Meseta(0)).await.unwrap();
|
||||||
|
@ -31,26 +31,6 @@ async fn test_save_options() {
|
|||||||
assert!(char.option_flags == 12345);
|
assert!(char.option_flags == 12345);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
async fn test_default3_keyboard_mappings() {
|
|
||||||
/*
|
|
||||||
check if keyboard is set to default3 when specified. this will only occur for things like creating characters from the web page.
|
|
||||||
normal client behaviour will simply use default1 when creating a character.
|
|
||||||
gamepad only has 1 default config
|
|
||||||
*/
|
|
||||||
let mut entity_gateway = InMemoryGateway::default();
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 3).await;
|
|
||||||
assert!(char1.keyboard_config.as_bytes() == DEFAULT_KEYBOARD_CONFIG3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
async fn test_invalid_keyboard_preset_value() {
|
|
||||||
// check if keyboard_config self-corrects to DEFAULT1 if an invalid value (>4) is given
|
|
||||||
let mut entity_gateway = InMemoryGateway::default();
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 10).await;
|
|
||||||
assert!(char1.keyboard_config.as_bytes() == DEFAULT_KEYBOARD_CONFIG1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn test_change_keyboard_mappings() {
|
async fn test_change_keyboard_mappings() {
|
||||||
let mut entity_gateway = InMemoryGateway::default();
|
let mut entity_gateway = InMemoryGateway::default();
|
||||||
@ -63,7 +43,8 @@ async fn test_change_keyboard_mappings() {
|
|||||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
join_lobby(&mut ship, ClientId(1)).await;
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
|
|
||||||
assert!(char1.keyboard_config.as_bytes() == DEFAULT_KEYBOARD_CONFIG2);
|
let settings = entity_gateway.get_user_settings_by_user(&user1).await.unwrap();
|
||||||
|
assert!(settings.settings.keyboard_config == DEFAULT_KEYBOARD_CONFIG1);
|
||||||
|
|
||||||
// update from default2 to default4
|
// update from default2 to default4
|
||||||
// the client simply sends the full 364 bytes...
|
// the client simply sends the full 364 bytes...
|
||||||
@ -95,8 +76,6 @@ async fn test_change_keyboard_mappings() {
|
|||||||
],
|
],
|
||||||
})).await.unwrap();
|
})).await.unwrap();
|
||||||
|
|
||||||
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
let settings = entity_gateway.get_user_settings_by_user(&user1).await.unwrap();
|
||||||
let char = characters[0].as_ref().unwrap();
|
assert!(settings.settings.keyboard_config == DEFAULT_KEYBOARD_CONFIG4);
|
||||||
|
|
||||||
assert!(char.keyboard_config.as_bytes() == DEFAULT_KEYBOARD_CONFIG4);
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use elseware::common::serverstate::{ClientId, ServerState};
|
|||||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
|
use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
|
||||||
use elseware::entity::item;
|
use elseware::entity::item;
|
||||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
|
||||||
|
use elseware::entity::character::TechLevel;
|
||||||
//use elseware::ship::items::{ClientItemId, ActiveItemEntityId, HeldItemType, FloorItemType};
|
//use elseware::ship::items::{ClientItemId, ActiveItemEntityId, HeldItemType, FloorItemType};
|
||||||
|
|
||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
@ -304,6 +305,92 @@ async fn test_jackolantern() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_use_barta_1() {
|
||||||
|
let mut entity_gateway = InMemoryGateway::default();
|
||||||
|
|
||||||
|
let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
|
||||||
|
|
||||||
|
/*
|
||||||
|
let mut p1_inv = Vec::new();
|
||||||
|
for tool in vec![item::tool::ToolType::PowerMaterial, item::tool::ToolType::].into_iter() {
|
||||||
|
let mut item = Vec::new();
|
||||||
|
for _ in 0..5usize {
|
||||||
|
item.push(entity_gateway.create_item(
|
||||||
|
item::NewItemEntity {
|
||||||
|
item: item::ItemDetail::Tool(
|
||||||
|
item::tool::Tool {
|
||||||
|
tool: tool
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}).await.unwrap());
|
||||||
|
}
|
||||||
|
p1_inv.push(item::InventoryItemEntity::Stacked(item));
|
||||||
|
}*/
|
||||||
|
let inv = vec![
|
||||||
|
entity_gateway.create_item(
|
||||||
|
item::NewItemEntity {
|
||||||
|
item: item::ItemDetail::TechniqueDisk(
|
||||||
|
item::tech::TechniqueDisk {
|
||||||
|
tech: item::tech::Technique::Foie,
|
||||||
|
level: 3,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
).await.unwrap(),
|
||||||
|
entity_gateway.create_item(
|
||||||
|
item::NewItemEntity {
|
||||||
|
item: item::ItemDetail::TechniqueDisk(
|
||||||
|
item::tech::TechniqueDisk {
|
||||||
|
tech: item::tech::Technique::Barta,
|
||||||
|
level: 4,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
).await.unwrap(),
|
||||||
|
entity_gateway.create_item(
|
||||||
|
item::NewItemEntity {
|
||||||
|
item: item::ItemDetail::TechniqueDisk(
|
||||||
|
item::tech::TechniqueDisk {
|
||||||
|
tech: item::tech::Technique::Zonde,
|
||||||
|
level: 5,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
).await.unwrap()
|
||||||
|
];
|
||||||
|
|
||||||
|
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(inv)).await.unwrap();
|
||||||
|
|
||||||
|
let mut ship = Box::new(ShipServerState::builder()
|
||||||
|
.gateway(entity_gateway.clone())
|
||||||
|
.build());
|
||||||
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
|
|
||||||
|
ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerUseItem(PlayerUseItem {
|
||||||
|
client: 0,
|
||||||
|
target: 0,
|
||||||
|
item_id: 0x10000,
|
||||||
|
})))).await.unwrap();
|
||||||
|
|
||||||
|
ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerUseItem(PlayerUseItem {
|
||||||
|
client: 0,
|
||||||
|
target: 0,
|
||||||
|
item_id: 0x10002,
|
||||||
|
})))).await.unwrap();
|
||||||
|
|
||||||
|
let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap();
|
||||||
|
let char = characters[0].as_ref().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(char.techs.techs.len(), 2);
|
||||||
|
assert_eq!(char.techs.techs.get(&item::tech::Technique::Foie).unwrap(), &TechLevel(3));
|
||||||
|
assert_eq!(char.techs.techs.get(&item::tech::Technique::Zonde).unwrap(), &TechLevel(5));
|
||||||
|
assert!(char.techs.techs.get(&item::tech::Technique::Barta).is_none());
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: tests for ALL ITEMS WOW
|
// TODO: tests for ALL ITEMS WOW
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user