Merge pull request 'async-ify entity gateway for future db impls' (#161) from async_entity_gateway into master
This commit is contained in:
commit
7a5e9c366d
@ -6,8 +6,8 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
libpso = { git = "http://git.sharnoth.com/jake/libpso" }
|
||||||
async-std = { version = "1.5.0", features = ["unstable"] }
|
async-std = { version = "1.5.0", features = ["unstable", "attributes"] }
|
||||||
futures = "0.3.4"
|
futures = "0.3.5"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
rand_chacha = "0.2.2"
|
rand_chacha = "0.2.2"
|
||||||
mio = "0.6"
|
mio = "0.6"
|
||||||
@ -27,4 +27,5 @@ enum-utils = "0.1.2"
|
|||||||
derive_more = { version = "0.99.3", features = ["display"]}
|
derive_more = { version = "0.99.3", features = ["display"]}
|
||||||
thiserror = "1.0.15"
|
thiserror = "1.0.15"
|
||||||
ages-prs = "0.1"
|
ages-prs = "0.1"
|
||||||
|
async-trait = "0.1.31"
|
||||||
|
|
||||||
|
@ -44,52 +44,53 @@ fn setup_logger() {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
setup_logger();
|
setup_logger();
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
|
||||||
|
|
||||||
for i in 0..5 {
|
|
||||||
let fake_user = NewUserAccountEntity {
|
|
||||||
username: if i == 0 { "hi".to_string() } else { format!("hi{}", i+1) },
|
|
||||||
password: bcrypt::hash("qwer", 5).unwrap(),
|
|
||||||
guildcard: i + 1,
|
|
||||||
team_id: None,
|
|
||||||
banned: false,
|
|
||||||
muted_until: SystemTime::now(),
|
|
||||||
created_at: SystemTime::now(),
|
|
||||||
flags: 0,
|
|
||||||
};
|
|
||||||
let fake_user = entity_gateway.create_user(fake_user).unwrap();
|
|
||||||
entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id));
|
|
||||||
let mut character = NewCharacterEntity::new(fake_user.id);
|
|
||||||
character.name = format!("Test Char {}", i*2);
|
|
||||||
entity_gateway.create_character(character);
|
|
||||||
let mut character = NewCharacterEntity::new(fake_user.id);
|
|
||||||
character.slot = 2;
|
|
||||||
character.name = "no progress".into();
|
|
||||||
character.exp = 80000000;
|
|
||||||
let character = entity_gateway.create_character(character).unwrap();
|
|
||||||
|
|
||||||
entity_gateway.create_item(
|
|
||||||
NewItemEntity {
|
|
||||||
item: ItemDetail::Weapon(
|
|
||||||
item::weapon::Weapon {
|
|
||||||
weapon: item::weapon::WeaponType::Raygun,
|
|
||||||
grind: 5,
|
|
||||||
special: Some(item::weapon::WeaponSpecial::Hell),
|
|
||||||
attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
|
|
||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
|
|
||||||
None,],
|
|
||||||
tekked: true,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
location: ItemLocation::Inventory {
|
|
||||||
character_id: character.id,
|
|
||||||
slot: 0,
|
|
||||||
equipped: true,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async_std::task::block_on(async move {
|
async_std::task::block_on(async move {
|
||||||
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
|
for i in 0..5 {
|
||||||
|
let fake_user = NewUserAccountEntity {
|
||||||
|
username: if i == 0 { "hi".to_string() } else { format!("hi{}", i+1) },
|
||||||
|
password: bcrypt::hash("qwer", 5).unwrap(),
|
||||||
|
guildcard: i + 1,
|
||||||
|
team_id: None,
|
||||||
|
banned: false,
|
||||||
|
muted_until: SystemTime::now(),
|
||||||
|
created_at: SystemTime::now(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let fake_user = entity_gateway.create_user(fake_user).await.unwrap();
|
||||||
|
entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await;
|
||||||
|
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||||
|
character.name = format!("Test Char {}", i*2);
|
||||||
|
entity_gateway.create_character(character).await;
|
||||||
|
let mut character = NewCharacterEntity::new(fake_user.id);
|
||||||
|
character.slot = 2;
|
||||||
|
character.name = "no progress".into();
|
||||||
|
character.exp = 80000000;
|
||||||
|
character.meseta = 999999;
|
||||||
|
let character = entity_gateway.create_character(character).await.unwrap();
|
||||||
|
|
||||||
|
entity_gateway.create_item(
|
||||||
|
NewItemEntity {
|
||||||
|
item: ItemDetail::Weapon(
|
||||||
|
item::weapon::Weapon {
|
||||||
|
weapon: item::weapon::WeaponType::Raygun,
|
||||||
|
grind: 5,
|
||||||
|
special: Some(item::weapon::WeaponSpecial::Hell),
|
||||||
|
attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 40}),
|
||||||
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
|
||||||
|
None,],
|
||||||
|
tekked: false,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
location: ItemLocation::Inventory {
|
||||||
|
character_id: character.id,
|
||||||
|
slot: 0,
|
||||||
|
equipped: true,
|
||||||
|
}
|
||||||
|
}).await;
|
||||||
|
}
|
||||||
|
|
||||||
let patch = async_std::task::spawn(async {
|
let patch = async_std::task::spawn(async {
|
||||||
info!("[patch] starting server");
|
info!("[patch] starting server");
|
||||||
let patch_config = load_config();
|
let patch_config = load_config();
|
||||||
|
@ -165,7 +165,7 @@ async fn server_state_loop<STATE, S, R, E>(mut state: STATE,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientAction::Packet(client_id, pkt) => {
|
ClientAction::Packet(client_id, pkt) => {
|
||||||
let pkts = state.handle(client_id, &pkt);
|
let pkts = state.handle(client_id, &pkt).await;
|
||||||
match pkts {
|
match pkts {
|
||||||
Ok(pkts) => {
|
Ok(pkts) => {
|
||||||
for (client_id, pkt) in pkts {
|
for (client_id, pkt) in pkts {
|
||||||
|
@ -9,22 +9,23 @@ pub enum OnConnect<S: SendServerPacket> {
|
|||||||
Cipher((Box<dyn PSOCipher + Send + Sync>, Box<dyn PSOCipher + Send + Sync>)),
|
Cipher((Box<dyn PSOCipher + Send + Sync>, Box<dyn PSOCipher + Send + Sync>)),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RecvServerPacket: Sized {
|
pub trait RecvServerPacket: Sized + Sync {
|
||||||
fn from_bytes(data: &[u8]) -> Result<Self, PacketParseError>;
|
fn from_bytes(data: &[u8]) -> Result<Self, PacketParseError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SendServerPacket: Sized {
|
pub trait SendServerPacket: Sized + Sync {
|
||||||
fn as_bytes(&self) -> Vec<u8>;
|
fn as_bytes(&self) -> Vec<u8>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
pub trait ServerState {
|
pub trait ServerState {
|
||||||
type SendPacket: SendServerPacket;
|
type SendPacket: SendServerPacket;
|
||||||
type RecvPacket: RecvServerPacket;
|
type RecvPacket: RecvServerPacket;
|
||||||
type PacketError;
|
type PacketError;
|
||||||
|
|
||||||
fn on_connect(&mut self, id: ClientId) -> Vec<OnConnect<Self::SendPacket>>;
|
fn on_connect(&mut self, id: ClientId) -> Vec<OnConnect<Self::SendPacket>>;
|
||||||
fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, Self::PacketError>;
|
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, Self::PacketError>;
|
||||||
fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>;
|
fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,28 +2,29 @@ use crate::entity::account::*;
|
|||||||
use crate::entity::character::*;
|
use crate::entity::character::*;
|
||||||
use crate::entity::item::*;
|
use crate::entity::item::*;
|
||||||
|
|
||||||
pub trait EntityGateway {
|
#[async_trait::async_trait]
|
||||||
fn create_user(&mut self, _user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
pub trait EntityGateway: Send + Sync + Clone {
|
||||||
|
async fn create_user(&mut self, _user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_by_id(&self, _id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, _id: UserAccountId) -> Option<UserAccountEntity> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_by_name(&self, _username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, _username: String) -> Option<UserAccountEntity> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_user(&mut self, _user: &UserAccountEntity) {
|
async fn save_user(&mut self, _user: &UserAccountEntity) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,31 +32,31 @@ pub trait EntityGateway {
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_character(&mut self, _char: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, _char: NewCharacterEntity) -> Option<CharacterEntity> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_character(&mut self, _char: &CharacterEntity) {
|
async fn save_character(&mut self, _char: &CharacterEntity) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_item(&mut self, _item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, _item: NewItemEntity) -> Option<ItemEntity> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_item(&mut self, _item: &ItemEntity) {
|
async fn save_item(&mut self, _item: &ItemEntity) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec<ItemEntity> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,9 @@ impl InMemoryGateway {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for InMemoryGateway {
|
impl EntityGateway for InMemoryGateway {
|
||||||
fn create_user(&mut self, user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
async fn create_user(&mut self, user: NewUserAccountEntity) -> Option<UserAccountEntity> {
|
||||||
let mut users = self.users.lock().unwrap();
|
let mut users = self.users.lock().unwrap();
|
||||||
let id = users
|
let id = users
|
||||||
.iter()
|
.iter()
|
||||||
@ -48,12 +49,12 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
Some(user)
|
Some(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_by_id(&self, id: UserAccountId) -> Option<UserAccountEntity> {
|
async fn get_user_by_id(&self, id: UserAccountId) -> Option<UserAccountEntity> {
|
||||||
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())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_by_name(&self, username: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, username: String) -> Option<UserAccountEntity> {
|
||||||
let users = self.users.lock().unwrap();
|
let users = self.users.lock().unwrap();
|
||||||
users
|
users
|
||||||
.iter()
|
.iter()
|
||||||
@ -61,20 +62,12 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
.map(|(_, k)| k.clone())
|
.map(|(_, k)| k.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_user(&mut self, user: &UserAccountEntity) {
|
async fn save_user(&mut self, user: &UserAccountEntity) {
|
||||||
let mut users = self.users.lock().unwrap();
|
let mut users = self.users.lock().unwrap();
|
||||||
users.insert(user.id, user.clone());
|
users.insert(user.id, user.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
||||||
let user_settings = self.user_settings.lock().unwrap();
|
|
||||||
user_settings
|
|
||||||
.iter()
|
|
||||||
.find(|(_, k)| k.user_id == user.id)
|
|
||||||
.map(|(_, k)| k.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option<UserSettingsEntity> {
|
|
||||||
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()
|
||||||
@ -89,7 +82,15 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
Some(new_settings)
|
Some(new_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
||||||
|
let user_settings = self.user_settings.lock().unwrap();
|
||||||
|
user_settings
|
||||||
|
.iter()
|
||||||
|
.find(|(_, k)| k.user_id == user.id)
|
||||||
|
.map(|(_, k)| k.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option<CharacterEntity>; 4] {
|
||||||
let characters = self.characters.lock().unwrap();
|
let characters = self.characters.lock().unwrap();
|
||||||
let mut chars = [None; 4];
|
let mut chars = [None; 4];
|
||||||
characters
|
characters
|
||||||
@ -99,7 +100,7 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
chars
|
chars
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_character(&mut self, character: NewCharacterEntity) -> Option<CharacterEntity> {
|
async fn create_character(&mut self, character: NewCharacterEntity) -> Option<CharacterEntity> {
|
||||||
let mut characters = self.characters.lock().unwrap();
|
let mut characters = self.characters.lock().unwrap();
|
||||||
let id = characters
|
let id = characters
|
||||||
.iter()
|
.iter()
|
||||||
@ -126,16 +127,16 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
Some(new_character)
|
Some(new_character)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_character(&mut self, char: &CharacterEntity) {
|
async fn save_character(&mut self, char: &CharacterEntity) {
|
||||||
let mut characters = self.characters.lock().unwrap();
|
let mut characters = self.characters.lock().unwrap();
|
||||||
characters.insert(char.id, char.clone());
|
characters.insert(char.id, char.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity {
|
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity {
|
||||||
GuildCardDataEntity::new(user.id)
|
GuildCardDataEntity::new(user.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_item(&mut self, item: NewItemEntity) -> Option<ItemEntity> {
|
async fn create_item(&mut self, item: NewItemEntity) -> Option<ItemEntity> {
|
||||||
let mut items = self.items.lock().unwrap();
|
let mut items = self.items.lock().unwrap();
|
||||||
let id = items
|
let id = items
|
||||||
.iter()
|
.iter()
|
||||||
@ -150,12 +151,12 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
Some(new_item)
|
Some(new_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_item(&mut self, item: &ItemEntity) {
|
async fn save_item(&mut self, item: &ItemEntity) {
|
||||||
let mut items = self.items.lock().unwrap();
|
let mut items = self.items.lock().unwrap();
|
||||||
items.insert(item.id, item.clone());
|
items.insert(item.id, item.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_items_by_character(&self, character: &CharacterEntity) -> Vec<ItemEntity> {
|
async fn get_items_by_character(&self, character: &CharacterEntity) -> Vec<ItemEntity> {
|
||||||
let items = self.items.lock().unwrap();
|
let items = self.items.lock().unwrap();
|
||||||
items
|
items
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -190,7 +190,7 @@ pub struct CharacterServerState<EG: EntityGateway> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountEntity, preview: &CharacterPreview) {
|
async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountEntity, preview: &CharacterPreview) {
|
||||||
//let mut character = entity_gateway.new_character_by_user(&user);
|
//let mut character = entity_gateway.new_character_by_user(&user);
|
||||||
//new_character_from_preview(&mut char, preview);
|
//new_character_from_preview(&mut char, preview);
|
||||||
let mut character = new_character_from_preview(user, preview);
|
let mut character = new_character_from_preview(user, preview);
|
||||||
@ -201,7 +201,7 @@ fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountE
|
|||||||
|
|
||||||
character.meseta = 300;
|
character.meseta = 300;
|
||||||
|
|
||||||
let character = entity_gateway.create_character(character).unwrap();
|
let character = entity_gateway.create_character(character).await.unwrap();
|
||||||
|
|
||||||
let new_weapon = match character.char_class {
|
let new_weapon = match character.char_class {
|
||||||
CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => item::weapon::WeaponType::Saber,
|
CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => item::weapon::WeaponType::Saber,
|
||||||
@ -224,7 +224,7 @@ fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountE
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}});
|
}}).await;
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
@ -239,7 +239,7 @@ fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountE
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 1,
|
slot: 1,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}});
|
}}).await;
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
@ -259,7 +259,7 @@ fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountE
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 2,
|
slot: 2,
|
||||||
equipped: true,
|
equipped: true,
|
||||||
}});
|
}}).await;
|
||||||
|
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -272,7 +272,7 @@ fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountE
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 3,
|
slot: 3,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}});
|
}}).await;
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
NewItemEntity {
|
NewItemEntity {
|
||||||
item: ItemDetail::Tool (
|
item: ItemDetail::Tool (
|
||||||
@ -283,7 +283,7 @@ fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAccountE
|
|||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
slot: 4,
|
slot: 4,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}});
|
}}).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,9 +307,9 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> 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))?;
|
||||||
Ok(match get_login_status(&self.entity_gateway, pkt) {
|
Ok(match get_login_status(&self.entity_gateway, pkt).await {
|
||||||
Ok(user) => {
|
Ok(user) => {
|
||||||
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
||||||
response.guildcard = user.guildcard;
|
response.guildcard = user.guildcard;
|
||||||
@ -337,16 +337,16 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_settings(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn get_settings(&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 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?)
|
// TODO: this should error (data should be added on account creation, why did I copy this silly sylv logic?)
|
||||||
let settings = match self.entity_gateway.get_user_settings_by_user(&user) {
|
let settings = match self.entity_gateway.get_user_settings_by_user(&user).await {
|
||||||
Some(settings) => settings,
|
Some(settings) => settings,
|
||||||
None => {
|
None => {
|
||||||
let user_settings = NewUserSettingsEntity::new(user.id);
|
let user_settings = NewUserSettingsEntity::new(user.id);
|
||||||
self.entity_gateway.create_user_settings(user_settings).unwrap()
|
self.entity_gateway.create_user_settings(user_settings).await.unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -357,10 +357,10 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
Ok(vec![pkt])
|
Ok(vec![pkt])
|
||||||
}
|
}
|
||||||
|
|
||||||
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()));
|
client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await);
|
||||||
}
|
}
|
||||||
|
|
||||||
if select.reason == 0 {
|
if select.reason == 0 {
|
||||||
@ -403,9 +403,9 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
})]
|
})]
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await;
|
||||||
|
|
||||||
let bytes = guildcard_data.guildcard.as_bytes();
|
let bytes = guildcard_data.guildcard.as_bytes();
|
||||||
let mut crc = crc32::Digest::new(crc32::IEEE);
|
let mut crc = crc32::Digest::new(crc32::IEEE);
|
||||||
@ -431,11 +431,11 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result<std::option::IntoIter<SendCharacterPacket>, CharacterError> {
|
async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result<std::option::IntoIter<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 mut user = client.user.as_mut().unwrap();
|
let mut user = client.user.as_mut().unwrap();
|
||||||
user.flags = setflag.flags;
|
user.flags = setflag.flags;
|
||||||
self.entity_gateway.save_user(&user);
|
self.entity_gateway.save_user(&user).await;
|
||||||
Ok(None.into_iter())
|
Ok(None.into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,11 +460,11 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
|
|
||||||
|
|
||||||
// TODO: move USERFLAGS over to SessionAction
|
// TODO: move USERFLAGS over to SessionAction
|
||||||
fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> 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 mut user = client.user.as_mut().unwrap();
|
let mut user = client.user.as_mut().unwrap();
|
||||||
if user.flags == USERFLAG_NEWCHAR {
|
if user.flags == USERFLAG_NEWCHAR {
|
||||||
new_character(&mut self.entity_gateway, &user, preview)
|
new_character(&mut self.entity_gateway, &user, preview).await
|
||||||
}
|
}
|
||||||
if user.flags == USERFLAG_DRESSINGROOM {
|
if user.flags == USERFLAG_DRESSINGROOM {
|
||||||
// TODO: dressing room stuff
|
// TODO: dressing room stuff
|
||||||
@ -473,7 +473,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
client.session.action = SessionAction::SelectCharacter;
|
client.session.action = SessionAction::SelectCharacter;
|
||||||
client.session.character_slot = preview.slot as u8;
|
client.session.character_slot = preview.slot as u8;
|
||||||
user.flags = 0;
|
user.flags = 0;
|
||||||
self.entity_gateway.save_user(&user);
|
self.entity_gateway.save_user(&user).await;
|
||||||
Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard,
|
Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard,
|
||||||
user.team_id.unwrap_or(1),
|
user.team_id.unwrap_or(1),
|
||||||
client.session)),
|
client.session)),
|
||||||
@ -495,6 +495,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
||||||
type SendPacket = SendCharacterPacket;
|
type SendPacket = SendCharacterPacket;
|
||||||
type RecvPacket = RecvCharacterPacket;
|
type RecvPacket = RecvCharacterPacket;
|
||||||
@ -516,7 +517,7 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendCharacterPacket)> + Send>, CharacterError> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendCharacterPacket)> + Send>, CharacterError> {
|
||||||
Ok(match pkt {
|
Ok(match pkt {
|
||||||
RecvCharacterPacket::Login(login) => {
|
RecvCharacterPacket::Login(login) => {
|
||||||
@ -524,20 +525,20 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
|||||||
Box::new(self.send_ship_list(id, login)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.send_ship_list(id, login)?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Box::new(self.validate_login(id, login)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.validate_login(id, login).await?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::RequestSettings(_req) => {
|
RecvCharacterPacket::RequestSettings(_req) => {
|
||||||
Box::new(self.get_settings(id)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.get_settings(id).await?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::CharSelect(sel) => {
|
RecvCharacterPacket::CharSelect(sel) => {
|
||||||
Box::new(self.char_select(id, sel)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.char_select(id, sel).await?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::Checksum(_checksum) => {
|
RecvCharacterPacket::Checksum(_checksum) => {
|
||||||
Box::new(self.validate_checksum().into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.validate_checksum().into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::GuildcardDataRequest(_request) => {
|
RecvCharacterPacket::GuildcardDataRequest(_request) => {
|
||||||
Box::new(self.guildcard_data_header(id)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.guildcard_data_header(id).await?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::GuildcardDataChunkRequest(request) => {
|
RecvCharacterPacket::GuildcardDataChunkRequest(request) => {
|
||||||
Box::new(self.guildcard_data_chunk(id, request.chunk, request.again)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.guildcard_data_chunk(id, request.chunk, request.again)?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
@ -546,13 +547,13 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> {
|
|||||||
Box::new(vec![SendCharacterPacket::ParamDataHeader(self.param_header.clone())].into_iter().map(move |pkt| (id, pkt)))
|
Box::new(vec![SendCharacterPacket::ParamDataHeader(self.param_header.clone())].into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::SetFlag(flag) => {
|
RecvCharacterPacket::SetFlag(flag) => {
|
||||||
Box::new(self.set_flag(id, flag)?.map(move |pkt| (id, pkt)))
|
Box::new(self.set_flag(id, flag).await?.map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::ParamDataChunkRequest(request) => {
|
RecvCharacterPacket::ParamDataChunkRequest(request) => {
|
||||||
Box::new(self.param_data_chunk_request(id, request)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.param_data_chunk_request(id, request)?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::CharacterPreview(preview) => {
|
RecvCharacterPacket::CharacterPreview(preview) => {
|
||||||
Box::new(self.character_preview(id, preview)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.character_preview(id, preview).await?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvCharacterPacket::MenuSelect(menuselect) => {
|
RecvCharacterPacket::MenuSelect(menuselect) => {
|
||||||
Box::new(self.select_ship(menuselect)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(self.select_ship(menuselect)?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
@ -657,13 +658,15 @@ mod test {
|
|||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use crate::entity::gateway::{InMemoryGateway};
|
use crate::entity::gateway::{InMemoryGateway};
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_option_send() {
|
async fn test_option_send() {
|
||||||
|
#[derive(Clone)]
|
||||||
struct TestData {
|
struct TestData {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option<UserSettingsEntity> {
|
||||||
Some(UserSettingsEntity {
|
Some(UserSettingsEntity {
|
||||||
id: UserSettingsId(0),
|
id: UserSettingsId(0),
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
@ -687,7 +690,7 @@ mod test {
|
|||||||
});
|
});
|
||||||
server.clients.insert(ClientId(5), clientstate);
|
server.clients.insert(ClientId(5), clientstate);
|
||||||
|
|
||||||
let send = server.handle(ClientId(5), &RecvCharacterPacket::RequestSettings(RequestSettings{}))
|
let send = server.handle(ClientId(5), &RecvCharacterPacket::RequestSettings(RequestSettings{})).await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert!(send.len() == 1);
|
assert!(send.len() == 1);
|
||||||
@ -698,22 +701,23 @@ mod test {
|
|||||||
assert!(bytes.len() == 0xAFC);
|
assert!(bytes.len() == 0xAFC);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_user_checksum() {
|
async fn test_user_checksum() {
|
||||||
|
#[derive(Clone)]
|
||||||
struct TestData;
|
struct TestData;
|
||||||
impl EntityGateway for TestData {}
|
impl EntityGateway for TestData {}
|
||||||
let mut server = CharacterServerState::new(TestData {});
|
let mut server = CharacterServerState::new(TestData {});
|
||||||
let send = server.handle(ClientId(1), &RecvCharacterPacket::Checksum(Checksum {checksum: 1234,
|
let send = server.handle(ClientId(1), &RecvCharacterPacket::Checksum(Checksum {checksum: 1234,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
})).unwrap().collect::<Vec<_>>();
|
})).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(send.len() == 1);
|
assert!(send.len() == 1);
|
||||||
|
|
||||||
let bytes = send[0].1.as_bytes();
|
let bytes = send[0].1.as_bytes();
|
||||||
assert!(bytes == [0xC, 0, 0xE8, 0x02, 0,0,0,0, 1,0,0,0]);
|
assert!(bytes == [0xC, 0, 0xE8, 0x02, 0,0,0,0, 1,0,0,0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_character_create() {
|
async fn test_character_create() {
|
||||||
let test_data = InMemoryGateway::new();
|
let test_data = InMemoryGateway::new();
|
||||||
let mut fake_user = ClientState::new();
|
let mut fake_user = ClientState::new();
|
||||||
fake_user.user = Some(UserAccountEntity {
|
fake_user.user = Some(UserAccountEntity {
|
||||||
@ -730,8 +734,8 @@ mod test {
|
|||||||
|
|
||||||
let mut server = CharacterServerState::new(test_data.clone());
|
let mut server = CharacterServerState::new(test_data.clone());
|
||||||
server.clients.insert(ClientId(1), fake_user.clone());
|
server.clients.insert(ClientId(1), fake_user.clone());
|
||||||
let mut send = server.handle(ClientId(1), &RecvCharacterPacket::SetFlag(SetFlag {flags: 1})).unwrap().collect::<Vec<_>>();
|
let mut send = server.handle(ClientId(1), &RecvCharacterPacket::SetFlag(SetFlag {flags: 1})).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(test_data.get_user_by_id(UserAccountId(3)).unwrap().flags == 1);
|
assert!(test_data.get_user_by_id(UserAccountId(3)).await.unwrap().flags == 1);
|
||||||
send = server.handle(ClientId(1), &RecvCharacterPacket::CharacterPreview(CharacterPreview {slot: 1, character: character::SelectScreenCharacter {
|
send = server.handle(ClientId(1), &RecvCharacterPacket::CharacterPreview(CharacterPreview {slot: 1, character: character::SelectScreenCharacter {
|
||||||
exp: 0,
|
exp: 0,
|
||||||
level: 0,
|
level: 0,
|
||||||
@ -758,10 +762,10 @@ mod test {
|
|||||||
prop_y: 0.0,
|
prop_y: 0.0,
|
||||||
name: [9, 69, 116, 101, 115, 116, 32, 110, 97, 109, 101, 0, 0, 0, 0, 0], // "\tEtest name"
|
name: [9, 69, 116, 101, 115, 116, 32, 110, 97, 109, 101, 0, 0, 0, 0, 0], // "\tEtest name"
|
||||||
play_time: 0,
|
play_time: 0,
|
||||||
} })).unwrap().collect::<Vec<_>>();
|
} })).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(send.len() == 2);
|
assert!(send.len() == 2);
|
||||||
|
|
||||||
let chars = test_data.get_characters_by_user(&fake_user.user.unwrap());
|
let chars = test_data.get_characters_by_user(&fake_user.user.unwrap()).await;
|
||||||
assert!(chars[1].as_ref().unwrap().name == "\tEtest name");
|
assert!(chars[1].as_ref().unwrap().name == "\tEtest name");
|
||||||
assert!(chars[0].is_none());
|
assert!(chars[0].is_none());
|
||||||
}
|
}
|
||||||
|
@ -56,10 +56,10 @@ impl SendServerPacket for SendLoginPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub 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).ok_or(AccountStatus::InvalidUser)?;
|
let user = entity_gateway.get_user_by_name(username).await.ok_or(AccountStatus::InvalidUser)?;
|
||||||
let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?;
|
let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?;
|
||||||
match verified {
|
match verified {
|
||||||
true => if user.banned {
|
true => if user.banned {
|
||||||
@ -84,8 +84,8 @@ impl<EG: EntityGateway> LoginServerState<EG> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_login(&mut self, pkt: &Login) -> Vec<SendLoginPacket> {
|
async fn validate_login(&mut self, pkt: &Login) -> Vec<SendLoginPacket> {
|
||||||
match get_login_status(&self.entity_gateway, pkt) {
|
match get_login_status(&self.entity_gateway, pkt).await {
|
||||||
Ok(_user) => {
|
Ok(_user) => {
|
||||||
let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session));
|
let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session));
|
||||||
let ip = net::Ipv4Addr::new(127,0,0,1);
|
let ip = net::Ipv4Addr::new(127,0,0,1);
|
||||||
@ -100,6 +100,7 @@ impl<EG: EntityGateway> LoginServerState<EG> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<EG: EntityGateway> ServerState for LoginServerState<EG> {
|
impl<EG: EntityGateway> ServerState for LoginServerState<EG> {
|
||||||
type SendPacket = SendLoginPacket;
|
type SendPacket = SendLoginPacket;
|
||||||
type RecvPacket = RecvLoginPacket;
|
type RecvPacket = RecvLoginPacket;
|
||||||
@ -119,11 +120,11 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, LoginError> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, LoginError> {
|
||||||
Ok(match pkt {
|
Ok(match pkt {
|
||||||
RecvLoginPacket::Login(login) => {
|
RecvLoginPacket::Login(login) => {
|
||||||
Box::new(self.validate_login(login)
|
Box::new(self.validate_login(login).await
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |pkt| {
|
.map(move |pkt| {
|
||||||
(id, pkt)
|
(id, pkt)
|
||||||
@ -167,13 +168,15 @@ mod test {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_correct_login() {
|
async fn test_correct_login() {
|
||||||
|
#[derive(Clone)]
|
||||||
struct TestData {
|
struct TestData {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
||||||
assert!(name == "testuser");
|
assert!(name == "testuser");
|
||||||
Some(UserAccountEntity {
|
Some(UserAccountEntity {
|
||||||
id: UserAccountId(1),
|
id: UserAccountId(1),
|
||||||
@ -187,11 +190,11 @@ mod test {
|
|||||||
flags: 0,
|
flags: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut server = LoginServerState::new(TestData {});
|
let mut server = LoginServerState::new(TestData {});
|
||||||
|
|
||||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).unwrap().collect::<Vec<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
||||||
status: AccountStatus::Ok,
|
status: AccountStatus::Ok,
|
||||||
@ -215,19 +218,21 @@ mod test {
|
|||||||
}))])
|
}))])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_login_bad_username() {
|
async fn test_login_bad_username() {
|
||||||
|
#[derive(Clone)]
|
||||||
struct TestData {
|
struct TestData {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
fn get_user_by_name(&self, _name: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, _name: String) -> Option<UserAccountEntity> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut server = LoginServerState::new(TestData {});
|
let mut server = LoginServerState::new(TestData {});
|
||||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).unwrap().collect::<Vec<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
|
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
||||||
@ -247,13 +252,15 @@ mod test {
|
|||||||
}))])
|
}))])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_login_bad_password() {
|
async fn test_login_bad_password() {
|
||||||
|
#[derive(Clone)]
|
||||||
struct TestData {
|
struct TestData {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
||||||
assert!(name == "testuser");
|
assert!(name == "testuser");
|
||||||
Some(UserAccountEntity {
|
Some(UserAccountEntity {
|
||||||
id: UserAccountId(1),
|
id: UserAccountId(1),
|
||||||
@ -270,7 +277,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut server = LoginServerState::new(TestData {});
|
let mut server = LoginServerState::new(TestData {});
|
||||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).unwrap().collect::<Vec<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
|
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
||||||
@ -290,13 +297,15 @@ mod test {
|
|||||||
}))])
|
}))])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_banned_user() {
|
async fn test_banned_user() {
|
||||||
|
#[derive(Clone)]
|
||||||
struct TestData {
|
struct TestData {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl EntityGateway for TestData {
|
impl EntityGateway for TestData {
|
||||||
fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
async fn get_user_by_name(&self, name: String) -> Option<UserAccountEntity> {
|
||||||
assert!(name == "testuser");
|
assert!(name == "testuser");
|
||||||
Some(UserAccountEntity {
|
Some(UserAccountEntity {
|
||||||
id: UserAccountId(1),
|
id: UserAccountId(1),
|
||||||
@ -313,7 +322,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut server = LoginServerState::new(TestData {});
|
let mut server = LoginServerState::new(TestData {});
|
||||||
let send = server.handle(ClientId(1), &LOGIN_PACKET).unwrap().collect::<Vec<_>>();
|
let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::<Vec<_>>();
|
||||||
|
|
||||||
assert!(send == vec![
|
assert!(send == vec![
|
||||||
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
(ClientId(1), SendLoginPacket::LoginResponse(LoginResponse {
|
||||||
|
@ -154,6 +154,7 @@ impl PatchServerState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl ServerState for PatchServerState {
|
impl ServerState for PatchServerState {
|
||||||
type SendPacket = SendPatchPacket;
|
type SendPacket = SendPatchPacket;
|
||||||
type RecvPacket = RecvPatchPacket;
|
type RecvPacket = RecvPatchPacket;
|
||||||
@ -169,7 +170,7 @@ impl ServerState for PatchServerState {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(&mut self, id: ClientId, pkt: &RecvPatchPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &RecvPatchPacket)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendPatchPacket)> + Send>, PatchError> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendPatchPacket)> + Send>, PatchError> {
|
||||||
Ok(match pkt {
|
Ok(match pkt {
|
||||||
RecvPatchPacket::PatchWelcomeReply(_pkt) => {
|
RecvPatchPacket::PatchWelcomeReply(_pkt) => {
|
||||||
|
@ -91,6 +91,7 @@ pub enum ItemDropType {
|
|||||||
Meseta(u32),
|
Meseta(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct ItemDrop {
|
pub struct ItemDrop {
|
||||||
pub map_area: MapArea,
|
pub map_area: MapArea,
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::collections::{HashMap, BTreeMap};
|
use std::collections::{HashMap, BTreeMap};
|
||||||
use libpso::character::character;//::InventoryItem;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use futures::future::join_all;
|
||||||
|
use libpso::character::character;//::InventoryItem;
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::EntityGateway;
|
||||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
||||||
use crate::entity::item::{ItemEntityId, ItemEntity, ItemDetail, ItemLocation};
|
use crate::entity::item::{ItemEntityId, ItemEntity, ItemDetail, ItemLocation};
|
||||||
@ -189,8 +190,8 @@ impl ItemManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Result
|
// TODO: Result
|
||||||
pub 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) {
|
||||||
let items = entity_gateway.get_items_by_character(&character);
|
let items = entity_gateway.get_items_by_character(&character).await;
|
||||||
let inventory_items = items.into_iter()
|
let inventory_items = items.into_iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
match item.location {
|
match item.location {
|
||||||
@ -289,7 +290,7 @@ impl ItemManager {
|
|||||||
.map(Clone::clone)
|
.map(Clone::clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn character_picks_up_item<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &mut CharacterEntity, floor_item: FloorItem) -> Result<TriggerCreateItem, ItemManagerError> {
|
pub async fn character_picks_up_item<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &mut CharacterEntity, floor_item: FloorItem) -> Result<TriggerCreateItem, ItemManagerError> {
|
||||||
let local_floor = self.character_floor.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
let local_floor = self.character_floor.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||||
let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||||
@ -356,7 +357,7 @@ impl ItemManager {
|
|||||||
slot: inventory.len(),
|
slot: inventory.len(),
|
||||||
equipped: false,
|
equipped: false,
|
||||||
},
|
},
|
||||||
}); // TODO: error check
|
}).await; // TODO: error check
|
||||||
inventory.push(inventory_item);
|
inventory.push(inventory_item);
|
||||||
} // else something went very wrong TODO: log it
|
} // else something went very wrong TODO: log it
|
||||||
TriggerCreateItem::Yes
|
TriggerCreateItem::Yes
|
||||||
@ -411,14 +412,14 @@ impl ItemManager {
|
|||||||
slot: inventory.len(),
|
slot: inventory.len(),
|
||||||
equipped: false,
|
equipped: false,
|
||||||
},
|
},
|
||||||
}); // TODO: error check
|
}).await; // TODO: error check
|
||||||
};
|
};
|
||||||
} // else something went very wrong TODO: log it
|
} // else something went very wrong TODO: log it
|
||||||
trigger_create
|
trigger_create
|
||||||
},
|
},
|
||||||
FloorItemType::Meseta(meseta) => {
|
FloorItemType::Meseta(meseta) => {
|
||||||
character.meseta = std::cmp::min(character.meseta + meseta.0, 999999);
|
character.meseta = std::cmp::min(character.meseta + meseta.0, 999999);
|
||||||
entity_gateway.save_character(&character);
|
entity_gateway.save_character(&character).await;
|
||||||
TriggerCreateItem::No
|
TriggerCreateItem::No
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -426,7 +427,7 @@ impl ItemManager {
|
|||||||
Ok(trigger_create)
|
Ok(trigger_create)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enemy_drop_item_on_local_floor<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, item_drop: ItemDrop) -> Result<&FloorItem, ItemManagerError> {
|
pub async fn enemy_drop_item_on_local_floor<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, item_drop: ItemDrop) -> Result<&FloorItem, ItemManagerError> {
|
||||||
let item = match item_drop.item {
|
let item = match item_drop.item {
|
||||||
ItemDropType::Weapon(w) => FloorItemType::Individual(ItemDetail::Weapon(w)),
|
ItemDropType::Weapon(w) => FloorItemType::Individual(ItemDetail::Weapon(w)),
|
||||||
ItemDropType::Armor(w) => FloorItemType::Individual(ItemDetail::Armor(w)),
|
ItemDropType::Armor(w) => FloorItemType::Individual(ItemDetail::Armor(w)),
|
||||||
@ -440,6 +441,8 @@ impl ItemManager {
|
|||||||
ItemDropType::Meseta(m) => FloorItemType::Meseta(Meseta(m))
|
ItemDropType::Meseta(m) => FloorItemType::Meseta(Meseta(m))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//let eg = Arc::new(Mutex::new(entity_gateway.clone()))
|
||||||
let entity_id = match &item {
|
let entity_id = match &item {
|
||||||
FloorItemType::Individual(i) => {
|
FloorItemType::Individual(i) => {
|
||||||
let entity = entity_gateway.create_item(NewItemEntity {
|
let entity = entity_gateway.create_item(NewItemEntity {
|
||||||
@ -451,26 +454,37 @@ impl ItemManager {
|
|||||||
y: item_drop.y,
|
y: item_drop.y,
|
||||||
z: item_drop.z,
|
z: item_drop.z,
|
||||||
}
|
}
|
||||||
}).ok_or(ItemManagerError::EntityGatewayError)?;
|
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
|
||||||
ActiveItemEntityId::Individual(entity.id)
|
ActiveItemEntityId::Individual(entity.id)
|
||||||
},
|
},
|
||||||
FloorItemType::Stacked(tool, count) => {
|
FloorItemType::Stacked(tool, count) => {
|
||||||
let entities = (0..*count).map(|_| {
|
let entities = (0..*count)
|
||||||
entity_gateway.create_item(NewItemEntity {
|
.map(|_| {
|
||||||
item: ItemDetail::Tool(*tool),
|
let mut eg = entity_gateway.clone();
|
||||||
location: ItemLocation::LocalFloor {
|
let item_drop = item_drop.clone();
|
||||||
character_id: character.id,
|
async move {
|
||||||
map_area: item_drop.map_area,
|
eg.create_item(NewItemEntity {
|
||||||
x: item_drop.x,
|
item: ItemDetail::Tool(*tool),
|
||||||
y: item_drop.y,
|
location: ItemLocation::LocalFloor {
|
||||||
z: item_drop.z,
|
character_id: character.id,
|
||||||
}
|
map_area: item_drop.map_area,
|
||||||
})})
|
x: item_drop.x,
|
||||||
|
y: item_drop.y,
|
||||||
|
z: item_drop.z,
|
||||||
|
}
|
||||||
|
}).await
|
||||||
|
}});
|
||||||
|
let entities = join_all(entities).await.into_iter()
|
||||||
.map(|entity| -> Result<ItemEntityId, ItemManagerError> {
|
.map(|entity| -> Result<ItemEntityId, ItemManagerError> {
|
||||||
let e = entity.ok_or(ItemManagerError::EntityGatewayError)?;
|
let e = entity.ok_or(ItemManagerError::EntityGatewayError)?;
|
||||||
|
// I am not able to manually specify a closure return type when also using the async keyword
|
||||||
Ok(e.id)
|
Ok(e.id)
|
||||||
|
//let result: Result<ItemEntityId, ItemManagerError> = Ok(e.id);
|
||||||
|
//result
|
||||||
});
|
});
|
||||||
|
//ActiveItemEntityId::Stacked(join_all(entities).await.into_iter().collect::<Result<Vec<_>, _>>()?)
|
||||||
ActiveItemEntityId::Stacked(entities.collect::<Result<Vec<_>, _>>()?)
|
ActiveItemEntityId::Stacked(entities.collect::<Result<Vec<_>, _>>()?)
|
||||||
|
//ActiveItemEntityId::Stacked(entities.collect().await?)
|
||||||
},
|
},
|
||||||
FloorItemType::Meseta(m) => ActiveItemEntityId::Meseta(m.clone()),
|
FloorItemType::Meseta(m) => ActiveItemEntityId::Meseta(m.clone()),
|
||||||
};
|
};
|
||||||
@ -492,7 +506,7 @@ impl ItemManager {
|
|||||||
self.character_floor.get(&character.id).ok_or(ItemManagerError::Idunnoman)?.last().ok_or(ItemManagerError::Idunnoman)
|
self.character_floor.get(&character.id).ok_or(ItemManagerError::Idunnoman)?.last().ok_or(ItemManagerError::Idunnoman)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn player_drop_item_on_shared_floor<EG: EntityGateway>(&mut self,
|
pub async fn player_drop_item_on_shared_floor<EG: EntityGateway>(&mut self,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
character: &CharacterEntity,
|
character: &CharacterEntity,
|
||||||
inventory_item: InventoryItem,
|
inventory_item: InventoryItem,
|
||||||
@ -532,7 +546,7 @@ impl ItemManager {
|
|||||||
y: item_drop_location.2,
|
y: item_drop_location.2,
|
||||||
z: item_drop_location.3,
|
z: item_drop_location.3,
|
||||||
}
|
}
|
||||||
}); // TODO: error check
|
}).await; // TODO: error check
|
||||||
} // else something went very wrong: TODO: log it
|
} // else something went very wrong: TODO: log it
|
||||||
},
|
},
|
||||||
FloorItemType::Stacked(tool, _count) => {
|
FloorItemType::Stacked(tool, _count) => {
|
||||||
@ -547,7 +561,7 @@ impl ItemManager {
|
|||||||
y: item_drop_location.2,
|
y: item_drop_location.2,
|
||||||
z: item_drop_location.3,
|
z: item_drop_location.3,
|
||||||
},
|
},
|
||||||
}); // TODO: error check
|
}).await; // TODO: error check
|
||||||
}
|
}
|
||||||
} // else something went very wrong TODO: log it
|
} // else something went very wrong TODO: log it
|
||||||
},
|
},
|
||||||
@ -558,7 +572,7 @@ impl ItemManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn player_drops_meseta_on_shared_floor<EG: EntityGateway>(&mut self,
|
pub async fn player_drops_meseta_on_shared_floor<EG: EntityGateway>(&mut self,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
character: &mut CharacterEntity,
|
character: &mut CharacterEntity,
|
||||||
drop_location: ItemDropLocation,
|
drop_location: ItemDropLocation,
|
||||||
@ -570,7 +584,7 @@ impl ItemManager {
|
|||||||
return Err(ItemManagerError::CouldNotDropMeseta)
|
return Err(ItemManagerError::CouldNotDropMeseta)
|
||||||
}
|
}
|
||||||
character.meseta -= amount;
|
character.meseta -= amount;
|
||||||
entity_gateway.save_character(&character);
|
entity_gateway.save_character(&character).await;
|
||||||
|
|
||||||
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
||||||
let floor_item = FloorItem {
|
let floor_item = FloorItem {
|
||||||
@ -587,7 +601,7 @@ impl ItemManager {
|
|||||||
Ok(floor_item)
|
Ok(floor_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn player_drops_partial_stack_on_shared_floor<EG: EntityGateway>(&mut self,
|
pub async fn player_drops_partial_stack_on_shared_floor<EG: EntityGateway>(&mut self,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
character: &CharacterEntity,
|
character: &CharacterEntity,
|
||||||
inventory_item: InventoryItem,
|
inventory_item: InventoryItem,
|
||||||
@ -611,9 +625,26 @@ impl ItemManager {
|
|||||||
|
|
||||||
let dropped_entities = entity_ids.drain(..amount).collect::<Vec<_>>();
|
let dropped_entities = entity_ids.drain(..amount).collect::<Vec<_>>();
|
||||||
|
|
||||||
dropped_entities.iter().for_each(|entity_id| {
|
/*
|
||||||
|
dropped_entities.iter().map(|entity_id| {
|
||||||
|
let mut eg = entity_gateway.clone();
|
||||||
|
let tool = tool.clone();
|
||||||
|
async move {
|
||||||
|
eg.save_item(&ItemEntity {
|
||||||
|
id: *entity_id,
|
||||||
|
item: ItemDetail::Tool(tool),
|
||||||
|
location: ItemLocation::SharedFloor {
|
||||||
|
map_area: drop_location.map_area,
|
||||||
|
x: drop_location.x,
|
||||||
|
y: 0.0,
|
||||||
|
z: drop_location.z,
|
||||||
|
}
|
||||||
|
}).await
|
||||||
|
}}).await;
|
||||||
|
*/
|
||||||
|
for de in dropped_entities.iter() {
|
||||||
entity_gateway.save_item(&ItemEntity {
|
entity_gateway.save_item(&ItemEntity {
|
||||||
id: *entity_id,
|
id: *de,
|
||||||
item: ItemDetail::Tool(*tool),
|
item: ItemDetail::Tool(*tool),
|
||||||
location: ItemLocation::SharedFloor {
|
location: ItemLocation::SharedFloor {
|
||||||
map_area: drop_location.map_area,
|
map_area: drop_location.map_area,
|
||||||
@ -621,8 +652,8 @@ impl ItemManager {
|
|||||||
y: 0.0,
|
y: 0.0,
|
||||||
z: drop_location.z,
|
z: drop_location.z,
|
||||||
}
|
}
|
||||||
})
|
}).await
|
||||||
});
|
}
|
||||||
|
|
||||||
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
||||||
let floor_item = FloorItem {
|
let floor_item = FloorItem {
|
||||||
|
@ -6,28 +6,28 @@ use crate::login::login::get_login_status;
|
|||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::EntityGateway;
|
||||||
use crate::ship::items::ItemManager;
|
use crate::ship::items::ItemManager;
|
||||||
|
|
||||||
pub fn validate_login<EG: EntityGateway>(id: ClientId,
|
pub async fn validate_login<EG: EntityGateway>(id: ClientId,
|
||||||
pkt: &Login,
|
pkt: &Login,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_manager: &mut ItemManager,
|
item_manager: &mut ItemManager,
|
||||||
ship_name: &String)
|
ship_name: &String)
|
||||||
-> Result<Vec<SendShipPacket>, ShipError> {
|
-> Result<Vec<SendShipPacket>, ShipError> {
|
||||||
Ok(match get_login_status(entity_gateway, pkt) {
|
Ok(match get_login_status(entity_gateway, pkt).await {
|
||||||
Ok(user) => {
|
Ok(user) => {
|
||||||
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new());
|
||||||
response.guildcard = user.id.0 as u32;
|
response.guildcard = user.id.0 as u32;
|
||||||
response.team_id = user.team_id.map_or(31, |ti| ti) as u32;
|
response.team_id = user.team_id.map_or(31, |ti| ti) as u32;
|
||||||
let characters = entity_gateway.get_characters_by_user(&user);
|
let characters = entity_gateway.get_characters_by_user(&user).await;
|
||||||
let character = characters
|
let character = characters
|
||||||
.get(pkt.session.character_slot as usize)
|
.get(pkt.session.character_slot as usize)
|
||||||
.ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref()
|
.ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref()
|
||||||
.ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))?
|
.ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))?
|
||||||
.clone();
|
.clone();
|
||||||
let settings = entity_gateway.get_user_settings_by_user(&user)
|
let settings = entity_gateway.get_user_settings_by_user(&user).await
|
||||||
.ok_or(ShipError::ClientNotFound(id))?;
|
.ok_or(ShipError::ClientNotFound(id))?;
|
||||||
|
|
||||||
item_manager.load_character(entity_gateway, &character);
|
item_manager.load_character(entity_gateway, &character).await;
|
||||||
clients.insert(id, ClientState::new(user, settings, character, pkt.session));
|
clients.insert(id, ClientState::new(user, settings, character, pkt.session));
|
||||||
vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))]
|
vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))]
|
||||||
},
|
},
|
||||||
|
@ -35,13 +35,13 @@ pub fn request_infoboard(id: ClientId,
|
|||||||
Box::new(vec![(id, SendShipPacket::ViewInfoboardResponse(ViewInfoboardResponse {response: r}))].into_iter())
|
Box::new(vec![(id, SendShipPacket::ViewInfoboardResponse(ViewInfoboardResponse {response: r}))].into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_infoboard<EG: EntityGateway>(id: ClientId,
|
pub async fn write_infoboard<EG: EntityGateway>(id: ClientId,
|
||||||
new_infoboard: &WriteInfoboard,
|
new_infoboard: &WriteInfoboard,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
entity_gateway: &mut EG)
|
entity_gateway: &mut EG)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||||
client.character.info_board.update_infoboard(new_infoboard);
|
client.character.info_board.update_infoboard(new_infoboard);
|
||||||
entity_gateway.save_character(&client.character);
|
entity_gateway.save_character(&client.character).await;
|
||||||
Box::new(None.into_iter())
|
Box::new(None.into_iter())
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,14 @@ pub fn guildcard_send(id: ClientId,
|
|||||||
send_to_client(id, target as u8, msg, &client_location)
|
send_to_client(id, target as u8, msg, &client_location)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_item<EG>(id: ClientId,
|
pub async fn request_item<EG>(id: ClientId,
|
||||||
request_item: &RequestItem,
|
request_item: &RequestItem,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
rooms: &mut Rooms,
|
rooms: &mut Rooms,
|
||||||
item_manager: &mut ItemManager)
|
item_manager: &mut ItemManager)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
@ -68,6 +68,7 @@ where
|
|||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
|
/*
|
||||||
let item_drop_packets = clients_in_area.into_iter()
|
let item_drop_packets = clients_in_area.into_iter()
|
||||||
.filter_map(|area_client| {
|
.filter_map(|area_client| {
|
||||||
room.drop_table.get_drop(&monster.map_area, &monster.monster).map(|item_drop_type| {
|
room.drop_table.get_drop(&monster.map_area, &monster.monster).map(|item_drop_type| {
|
||||||
@ -75,7 +76,7 @@ where
|
|||||||
(area_client, item_drop_type)
|
(area_client, item_drop_type)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(|(area_client, item_drop_type)| -> Result<_, ShipError> {
|
.map(|(area_client, item_drop_type)| async {
|
||||||
let item_drop = ItemDrop {
|
let item_drop = ItemDrop {
|
||||||
map_area: monster.map_area,
|
map_area: monster.map_area,
|
||||||
x: request_item.x,
|
x: request_item.x,
|
||||||
@ -84,26 +85,62 @@ where
|
|||||||
item: item_drop_type,
|
item: item_drop_type,
|
||||||
};
|
};
|
||||||
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
||||||
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).unwrap(); // TODO: unwrap
|
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap
|
||||||
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
|
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
|
||||||
Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))
|
|
||||||
|
// I am not able to manually specify a closure return type when also using the async keyword
|
||||||
|
let result: Result<(ClientId, SendShipPacket), ShipError> = Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))));
|
||||||
|
result
|
||||||
})
|
})
|
||||||
|
.map(|item_drop_pkt| async {
|
||||||
|
item_drop_pkt.await
|
||||||
|
});
|
||||||
|
|
||||||
|
let item_drop_packets = join_all(item_drop_packets).await.into_iter()
|
||||||
.filter_map(|item_drop_pkt| {
|
.filter_map(|item_drop_pkt| {
|
||||||
// TODO: log errors here
|
// TODO: log errors here
|
||||||
item_drop_pkt.ok()
|
item_drop_pkt.ok()
|
||||||
})
|
});
|
||||||
.collect::<Vec<_>>(); // TODO: can EntityGateway be Sync?
|
|
||||||
|
//.collect::<Vec<_>>(); // TODO: can EntityGateway be Sync?
|
||||||
|
|
||||||
|
Ok(Box::new(item_drop_packets))
|
||||||
|
*/
|
||||||
|
|
||||||
|
let client_and_drop = clients_in_area.into_iter()
|
||||||
|
.filter_map(|area_client| {
|
||||||
|
room.drop_table.get_drop(&monster.map_area, &monster.monster).map(|item_drop_type| {
|
||||||
|
warn!("drop is? {:?}", item_drop_type);
|
||||||
|
(area_client, item_drop_type)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut item_drop_packets = Vec::new();
|
||||||
|
for (area_client, item_drop) in client_and_drop {
|
||||||
|
let item_drop = ItemDrop {
|
||||||
|
map_area: monster.map_area,
|
||||||
|
x: request_item.x,
|
||||||
|
y: request_item.y,
|
||||||
|
z: request_item.z,
|
||||||
|
item: item_drop,
|
||||||
|
};
|
||||||
|
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
||||||
|
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap
|
||||||
|
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
|
||||||
|
|
||||||
|
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Box::new(item_drop_packets.into_iter()))
|
Ok(Box::new(item_drop_packets.into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pickup_item<EG>(id: ClientId,
|
pub async fn pickup_item<EG>(id: ClientId,
|
||||||
pickup_item: &PickupItem,
|
pickup_item: &PickupItem,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_manager: &mut ItemManager)
|
item_manager: &mut ItemManager)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
@ -118,7 +155,7 @@ where
|
|||||||
_ => Some(builder::message::create_item(area_client, &item)?),
|
_ => Some(builder::message::create_item(area_client, &item)?),
|
||||||
};
|
};
|
||||||
|
|
||||||
match item_manager.character_picks_up_item(entity_gateway, &mut client.character, item) {
|
match item_manager.character_picks_up_item(entity_gateway, &mut client.character, item).await {
|
||||||
Ok(trigger_create_item) => {
|
Ok(trigger_create_item) => {
|
||||||
Ok(Box::new(Vec::new().into_iter()
|
Ok(Box::new(Vec::new().into_iter()
|
||||||
.chain(clients_in_area.clone().into_iter()
|
.chain(clients_in_area.clone().into_iter()
|
||||||
@ -142,7 +179,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_box_item<EG>(id: ClientId,
|
pub async fn request_box_item<EG>(id: ClientId,
|
||||||
box_drop_request: &BoxDropRequest,
|
box_drop_request: &BoxDropRequest,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
@ -166,14 +203,14 @@ EG: EntityGateway
|
|||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
let item_drop_packets = clients_in_area.into_iter()
|
/*let item_drop_packets = clients_in_area.into_iter()
|
||||||
.filter_map(|area_client| {
|
.filter_map(|area_client| {
|
||||||
room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| {
|
room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| {
|
||||||
warn!("drop is? {:?}", item_drop_type);
|
warn!("drop is? {:?}", item_drop_type);
|
||||||
(area_client, item_drop_type)
|
(area_client, item_drop_type)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(|(area_client, item_drop_type)| -> Result<_, ShipError> {
|
.map(async move |(area_client, item_drop_type)| -> Result<_, ShipError> {
|
||||||
let item_drop = ItemDrop {
|
let item_drop = ItemDrop {
|
||||||
map_area: box_object.map,
|
map_area: box_object.map,
|
||||||
x: box_drop_request.x,
|
x: box_drop_request.x,
|
||||||
@ -182,15 +219,47 @@ EG: EntityGateway
|
|||||||
item: item_drop_type,
|
item: item_drop_type,
|
||||||
};
|
};
|
||||||
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
||||||
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).unwrap(); // TODO: unwrap
|
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap
|
||||||
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?;
|
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?;
|
||||||
Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))
|
Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))
|
||||||
})
|
})
|
||||||
.filter_map(|item_drop_pkt| {
|
/*.filter_map(|item_drop_pkt| {
|
||||||
// TODO: log errors here
|
// TODO: log errors here
|
||||||
item_drop_pkt.ok()
|
item_drop_pkt.ok()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(); // TODO: can EntityGateway be Sync?
|
.collect::<Vec<_>>(); // TODO: can EntityGateway be Sync?*/
|
||||||
|
;
|
||||||
|
let item_drop_packets = join_all(item_drop_packets).await.into_iter()
|
||||||
|
.filter_map(|item_drop_pkt| {
|
||||||
|
// TODO: log errors here
|
||||||
|
item_drop_pkt.ok()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Box::new(item_drop_packets))
|
||||||
|
*/
|
||||||
|
|
||||||
|
let client_and_drop = clients_in_area.into_iter()
|
||||||
|
.filter_map(|area_client| {
|
||||||
|
room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| {
|
||||||
|
warn!("drop is? {:?}", item_drop_type);
|
||||||
|
(area_client, item_drop_type)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut item_drop_packets = Vec::new();
|
||||||
|
for (area_client, item_drop) in client_and_drop {
|
||||||
|
let item_drop = ItemDrop {
|
||||||
|
map_area: box_object.map,
|
||||||
|
x: box_drop_request.x,
|
||||||
|
y: 0.0,
|
||||||
|
z: box_drop_request.z,
|
||||||
|
item: item_drop,
|
||||||
|
};
|
||||||
|
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
||||||
|
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await?; // TODO: unwrap
|
||||||
|
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?;
|
||||||
|
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Box::new(item_drop_packets.into_iter()))
|
Ok(Box::new(item_drop_packets.into_iter()))
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ pub fn send_player_to_lobby(id: ClientId,
|
|||||||
.map(|c| (c.client, SendShipPacket::AddToLobby(addto.clone())))).collect())
|
.map(|c| (c.client, SendShipPacket::AddToLobby(addto.clone())))).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_lobby<EG: EntityGateway>(id: ClientId,
|
pub async fn change_lobby<EG: EntityGateway>(id: ClientId,
|
||||||
requested_lobby: u32,
|
requested_lobby: u32,
|
||||||
client_location: &mut ClientLocation,
|
client_location: &mut ClientLocation,
|
||||||
clients: &Clients,
|
clients: &Clients,
|
||||||
@ -98,7 +98,7 @@ pub fn change_lobby<EG: EntityGateway>(id: ClientId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item_manager.load_character(entity_gateway, &client.character);
|
item_manager.load_character(entity_gateway, &client.character).await;
|
||||||
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_manager, level_table)?;
|
let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_manager, level_table)?;
|
||||||
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_manager, level_table)?;
|
let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_manager, level_table)?;
|
||||||
let neighbors = client_location.get_client_neighbors(id).unwrap();
|
let neighbors = client_location.get_client_neighbors(id).unwrap();
|
||||||
|
@ -25,7 +25,7 @@ pub fn request_exp(id: ClientId,
|
|||||||
Box::new(None.into_iter())
|
Box::new(None.into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn player_drop_item<EG>(id: ClientId,
|
pub async fn player_drop_item<EG>(id: ClientId,
|
||||||
player_drop_item: &PlayerDropItem,
|
player_drop_item: &PlayerDropItem,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
@ -44,7 +44,7 @@ where
|
|||||||
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?;
|
.ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?;
|
||||||
let area = MapArea::from_value(&room.mode.episode(), player_drop_item.area as u32)?;
|
let area = MapArea::from_value(&room.mode.episode(), player_drop_item.area as u32)?;
|
||||||
let item = item_manager.get_inventory_item_by_id(&client.character, ClientItemId(player_drop_item.item_id))?;
|
let item = item_manager.get_inventory_item_by_id(&client.character, ClientItemId(player_drop_item.item_id))?;
|
||||||
item_manager.player_drop_item_on_shared_floor(entity_gateway, &client.character, item, (area, player_drop_item.x, player_drop_item.y, player_drop_item.z))?;
|
item_manager.player_drop_item_on_shared_floor(entity_gateway, &client.character, item, (area, player_drop_item.x, player_drop_item.y, player_drop_item.z)).await?;
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let pdi = player_drop_item.clone();
|
let pdi = player_drop_item.clone();
|
||||||
Ok(Box::new(clients_in_area.into_iter()
|
Ok(Box::new(clients_in_area.into_iter()
|
||||||
@ -77,13 +77,13 @@ pub fn drop_coordinates(id: ClientId,
|
|||||||
Ok(Box::new(None.into_iter()))
|
Ok(Box::new(None.into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_item_stack<EG>(id: ClientId,
|
pub async fn split_item_stack<EG>(id: ClientId,
|
||||||
split_item_stack: &PlayerSplitItemStack,
|
split_item_stack: &PlayerSplitItemStack,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_manager: &mut ItemManager)
|
item_manager: &mut ItemManager)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
if split_item_stack.item_id == 0xFFFFFFFF {
|
if split_item_stack.item_id == 0xFFFFFFFF {
|
||||||
let dropped_meseta = item_manager.player_drops_meseta_on_shared_floor(entity_gateway, &mut client.character, drop_location, split_item_stack.amount as u32)?;
|
let dropped_meseta = item_manager.player_drops_meseta_on_shared_floor(entity_gateway, &mut client.character, drop_location, split_item_stack.amount as u32).await?;
|
||||||
|
|
||||||
let dropped_meseta_pkt = builder::message::drop_split_stack(area_client, &dropped_meseta)?;
|
let dropped_meseta_pkt = builder::message::drop_split_stack(area_client, &dropped_meseta)?;
|
||||||
client.item_drop_location = None;
|
client.item_drop_location = None;
|
||||||
@ -110,7 +110,7 @@ where
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let item_to_split = item_manager.get_inventory_item_by_id(&client.character, drop_location.item_id)?;
|
let item_to_split = item_manager.get_inventory_item_by_id(&client.character, drop_location.item_id)?;
|
||||||
let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, item_to_split, drop_location, split_item_stack.amount as usize)?;
|
let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, item_to_split, drop_location, split_item_stack.amount as usize).await?;
|
||||||
|
|
||||||
let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item)?;
|
let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item)?;
|
||||||
client.item_drop_location = None;
|
client.item_drop_location = None;
|
||||||
|
@ -3,13 +3,13 @@ use crate::common::serverstate::ClientId;
|
|||||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients};
|
use crate::ship::ship::{SendShipPacket, ShipError, Clients};
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::EntityGateway;
|
||||||
|
|
||||||
pub fn update_config<EG: EntityGateway>(id: ClientId,
|
pub async fn update_config<EG: EntityGateway>(id: ClientId,
|
||||||
update_config: &UpdateConfig,
|
update_config: &UpdateConfig,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
entity_gateway: &mut EG)
|
entity_gateway: &mut EG)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap();
|
||||||
client.character.config.update(update_config);
|
client.character.config.update(update_config);
|
||||||
entity_gateway.save_character(&client.character);
|
entity_gateway.save_character(&client.character).await;
|
||||||
Box::new(None.into_iter())
|
Box::new(None.into_iter())
|
||||||
}
|
}
|
||||||
|
@ -261,19 +261,19 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message(&mut self, id: ClientId, msg: &Message) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
async fn message(&mut self, id: ClientId, msg: &Message) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
match &msg.msg {
|
match &msg.msg {
|
||||||
GameMessage::RequestExp(request_exp) => {
|
GameMessage::RequestExp(request_exp) => {
|
||||||
Ok(handler::message::request_exp(id, request_exp, &self.client_location, &self.rooms))
|
Ok(handler::message::request_exp(id, request_exp, &self.client_location, &self.rooms))
|
||||||
},
|
},
|
||||||
GameMessage::PlayerDropItem(player_drop_item) => {
|
GameMessage::PlayerDropItem(player_drop_item) => {
|
||||||
handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager)
|
handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await
|
||||||
},
|
},
|
||||||
GameMessage::DropCoordinates(drop_coordinates) => {
|
GameMessage::DropCoordinates(drop_coordinates) => {
|
||||||
handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms)
|
handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms)
|
||||||
},
|
},
|
||||||
GameMessage::PlayerSplitItemStack(split_item_stack) => {
|
GameMessage::PlayerSplitItemStack(split_item_stack) => {
|
||||||
handler::message::split_item_stack(id, split_item_stack, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager)
|
handler::message::split_item_stack(id, split_item_stack, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let cmsg = msg.clone();
|
let cmsg = msg.clone();
|
||||||
@ -285,20 +285,20 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
let target = msg.flag;
|
let target = msg.flag;
|
||||||
match &msg.msg {
|
match &msg.msg {
|
||||||
GameMessage::GuildcardSend(guildcard_send) => {
|
GameMessage::GuildcardSend(guildcard_send) => {
|
||||||
Ok(handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients))
|
Ok(handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients))
|
||||||
},
|
},
|
||||||
GameMessage::RequestItem(request_item) => {
|
GameMessage::RequestItem(request_item) => {
|
||||||
handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager)
|
handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await
|
||||||
},
|
},
|
||||||
GameMessage::PickupItem(pickup_item) => {
|
GameMessage::PickupItem(pickup_item) => {
|
||||||
handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager)
|
handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
|
||||||
},
|
},
|
||||||
GameMessage::BoxDropRequest(box_drop_request) => {
|
GameMessage::BoxDropRequest(box_drop_request) => {
|
||||||
handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager)
|
handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let cmsg = msg.clone();
|
let cmsg = msg.clone();
|
||||||
@ -312,6 +312,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
||||||
type SendPacket = SendShipPacket;
|
type SendPacket = SendShipPacket;
|
||||||
type RecvPacket = RecvShipPacket;
|
type RecvPacket = RecvShipPacket;
|
||||||
@ -331,11 +332,11 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket)
|
async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> {
|
||||||
Ok(match pkt {
|
Ok(match pkt {
|
||||||
RecvShipPacket::Login(login) => {
|
RecvShipPacket::Login(login) => {
|
||||||
Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.name)?.into_iter().map(move |pkt| (id, pkt)))
|
Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.name).await?.into_iter().map(move |pkt| (id, pkt)))
|
||||||
},
|
},
|
||||||
RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
|
RecvShipPacket::QuestDetailRequest(questdetailrequest) => {
|
||||||
match questdetailrequest.menu {
|
match questdetailrequest.menu {
|
||||||
@ -375,10 +376,10 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut self.client_location, &self.clients, &self.item_manager, &self.level_table)?.into_iter())
|
Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut self.client_location, &self.clients, &self.item_manager, &self.level_table)?.into_iter())
|
||||||
},
|
},
|
||||||
RecvShipPacket::Message(msg) => {
|
RecvShipPacket::Message(msg) => {
|
||||||
self.message(id, msg)?
|
self.message(id, msg).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::DirectMessage(msg) => {
|
RecvShipPacket::DirectMessage(msg) => {
|
||||||
self.direct_message(id, msg)?
|
self.direct_message(id, msg).await?
|
||||||
},
|
},
|
||||||
RecvShipPacket::PlayerChat(msg) => {
|
RecvShipPacket::PlayerChat(msg) => {
|
||||||
Box::new(handler::communication::player_chat(id, msg, &self.client_location, &self.clients)?.into_iter())
|
Box::new(handler::communication::player_chat(id, msg, &self.client_location, &self.clients)?.into_iter())
|
||||||
@ -390,13 +391,13 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
handler::room::room_name_request(id, &self.client_location, &self.rooms)
|
handler::room::room_name_request(id, &self.client_location, &self.rooms)
|
||||||
},
|
},
|
||||||
RecvShipPacket::UpdateConfig(pkt) => {
|
RecvShipPacket::UpdateConfig(pkt) => {
|
||||||
handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway)
|
handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::ViewInfoboardRequest(_pkt) => {
|
RecvShipPacket::ViewInfoboardRequest(_pkt) => {
|
||||||
handler::communication::request_infoboard(id, &self.client_location, &self.clients)
|
handler::communication::request_infoboard(id, &self.client_location, &self.clients)
|
||||||
},
|
},
|
||||||
RecvShipPacket::WriteInfoboard(pkt) => {
|
RecvShipPacket::WriteInfoboard(pkt) => {
|
||||||
handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway)
|
handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway).await
|
||||||
},
|
},
|
||||||
RecvShipPacket::RoomListRequest(_req) => {
|
RecvShipPacket::RoomListRequest(_req) => {
|
||||||
handler::room::request_room_list(id, &self.client_location, &self.rooms)
|
handler::room::request_room_list(id, &self.client_location, &self.rooms)
|
||||||
@ -415,7 +416,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> {
|
|||||||
handler::room::done_bursting(id, &self.client_location, &mut self.rooms)
|
handler::room::done_bursting(id, &self.client_location, &mut self.rooms)
|
||||||
},
|
},
|
||||||
RecvShipPacket::LobbySelect(pkt) => {
|
RecvShipPacket::LobbySelect(pkt) => {
|
||||||
Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut self.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms, &mut self.entity_gateway)?.into_iter())
|
Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut self.client_location, &self.clients, &mut self.item_manager, &self.level_table, &mut self.rooms, &mut self.entity_gateway).await?.into_iter())
|
||||||
},
|
},
|
||||||
RecvShipPacket::RequestQuestList(_) => {
|
RecvShipPacket::RequestQuestList(_) => {
|
||||||
handler::quest::send_quest_category_list(id, &self.quests)?
|
handler::quest::send_quest_category_list(id, &self.quests)?
|
||||||
|
@ -15,7 +15,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};
|
||||||
|
|
||||||
|
|
||||||
pub fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, username: &str, password: &str) -> (UserAccountEntity, CharacterEntity) {
|
pub async fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, username: &str, password: &str) -> (UserAccountEntity, CharacterEntity) {
|
||||||
let new_user = NewUserAccountEntity {
|
let new_user = NewUserAccountEntity {
|
||||||
username: username.into(),
|
username: username.into(),
|
||||||
password: bcrypt::hash(password, 5).unwrap(),
|
password: bcrypt::hash(password, 5).unwrap(),
|
||||||
@ -27,16 +27,16 @@ pub fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, username:
|
|||||||
flags: 0,
|
flags: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = entity_gateway.create_user(new_user).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).unwrap();
|
let _settings = entity_gateway.create_user_settings(new_settings).await.unwrap();
|
||||||
let new_character = NewCharacterEntity::new(user.id);
|
let new_character = NewCharacterEntity::new(user.id);
|
||||||
let character = entity_gateway.create_character(new_character).unwrap();
|
let character = entity_gateway.create_character(new_character).await.unwrap();
|
||||||
|
|
||||||
(user, character)
|
(user, character)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_in_char<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, username: &str, password: &str) {
|
pub async fn log_in_char<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, username: &str, password: &str) {
|
||||||
let username = username.to_string();
|
let username = username.to_string();
|
||||||
let password = password.to_string();
|
let password = password.to_string();
|
||||||
ship.handle(id, &RecvShipPacket::Login(Login {
|
ship.handle(id, &RecvShipPacket::Login(Login {
|
||||||
@ -51,16 +51,16 @@ pub fn log_in_char<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: Client
|
|||||||
unknown3: [0; 40],
|
unknown3: [0; 40],
|
||||||
hwinfo: [0; 8],
|
hwinfo: [0; 8],
|
||||||
session: Session::new(),
|
session: Session::new(),
|
||||||
})).unwrap().for_each(drop);
|
})).await.unwrap().for_each(drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join_lobby<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId) {
|
pub async fn join_lobby<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId) {
|
||||||
ship.handle(id, &RecvShipPacket::CharData(CharData {
|
ship.handle(id, &RecvShipPacket::CharData(CharData {
|
||||||
_unknown: [0; 0x828]
|
_unknown: [0; 0x828]
|
||||||
})).unwrap().for_each(drop);
|
})).await.unwrap().for_each(drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, name: &str, password: &str) {
|
pub async fn create_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, name: &str, password: &str) {
|
||||||
ship.handle(id, &RecvShipPacket::CreateRoom(CreateRoom {
|
ship.handle(id, &RecvShipPacket::CreateRoom(CreateRoom {
|
||||||
unknown: [0; 2],
|
unknown: [0; 2],
|
||||||
name: utf8_to_utf16_array!(name, 16),
|
name: utf8_to_utf16_array!(name, 16),
|
||||||
@ -71,24 +71,24 @@ pub fn create_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: Client
|
|||||||
episode: 1,
|
episode: 1,
|
||||||
single_player: 0,
|
single_player: 0,
|
||||||
padding: [0; 3],
|
padding: [0; 3],
|
||||||
})).unwrap().for_each(drop);
|
})).await.unwrap().for_each(drop);
|
||||||
ship.handle(id, &RecvShipPacket::DoneBursting(DoneBursting {})).unwrap().for_each(drop);
|
ship.handle(id, &RecvShipPacket::DoneBursting(DoneBursting {})).await.unwrap().for_each(drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, room_id: u32) {
|
pub async fn join_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, room_id: u32) {
|
||||||
ship.handle(id, &RecvShipPacket::MenuSelect(MenuSelect {
|
ship.handle(id, &RecvShipPacket::MenuSelect(MenuSelect {
|
||||||
menu: ROOM_MENU_ID,
|
menu: ROOM_MENU_ID,
|
||||||
item: room_id,
|
item: room_id,
|
||||||
})).unwrap().for_each(drop);
|
})).await.unwrap().for_each(drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
async fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -102,7 +102,7 @@ fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
|
|
||||||
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() {
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
@ -118,19 +118,19 @@ fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -141,7 +141,7 @@ fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -149,7 +149,7 @@ fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
item_id: 0x210000,
|
item_id: 0x210000,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
||||||
assert!(p1_inventory.count() == 1);
|
assert!(p1_inventory.count() == 1);
|
||||||
@ -158,12 +158,12 @@ fn test_pick_up_item_stack_of_items_already_in_inventory() {
|
|||||||
assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 6));
|
assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_pick_up_item_stack_of_items_not_already_held() {
|
async fn test_pick_up_item_stack_of_items_not_already_held() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
@ -177,17 +177,17 @@ fn test_pick_up_item_stack_of_items_not_already_held() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -198,7 +198,7 @@ fn test_pick_up_item_stack_of_items_not_already_held() {
|
|||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -206,7 +206,7 @@ fn test_pick_up_item_stack_of_items_not_already_held() {
|
|||||||
item_id: 0x210000,
|
item_id: 0x210000,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
||||||
assert!(p1_inventory.count() == 1);
|
assert!(p1_inventory.count() == 1);
|
||||||
@ -215,12 +215,12 @@ fn test_pick_up_item_stack_of_items_not_already_held() {
|
|||||||
assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 1));
|
assert!(inventory_item.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_pick_up_meseta_when_inventory_full() {
|
async fn test_pick_up_meseta_when_inventory_full() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
for slot in 0..30 {
|
for slot in 0..30 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -239,21 +239,21 @@ fn test_pick_up_meseta_when_inventory_full() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
char2.meseta = 300;
|
char2.meseta = 300;
|
||||||
entity_gateway.save_character(&char2);
|
entity_gateway.save_character(&char2).await;
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -262,14 +262,14 @@ fn test_pick_up_meseta_when_inventory_full() {
|
|||||||
map_area: 0,
|
map_area: 0,
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
||||||
client: 0,
|
client: 0,
|
||||||
target: 0,
|
target: 0,
|
||||||
item_id: 0xFFFFFFFF,
|
item_id: 0xFFFFFFFF,
|
||||||
amount: 23,
|
amount: 23,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -277,7 +277,7 @@ fn test_pick_up_meseta_when_inventory_full() {
|
|||||||
item_id: 0xF0000001,
|
item_id: 0xF0000001,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
||||||
assert!(p1_inventory.count() == 30);
|
assert!(p1_inventory.count() == 30);
|
||||||
@ -288,12 +288,12 @@ fn test_pick_up_meseta_when_inventory_full() {
|
|||||||
assert!(c2.character.meseta == 277);
|
assert!(c2.character.meseta == 277);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
for slot in 0..29 {
|
for slot in 0..29 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -312,7 +312,7 @@ fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -327,7 +327,7 @@ fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
slot: 29,
|
slot: 29,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
item::NewItemEntity {
|
item::NewItemEntity {
|
||||||
item: item::ItemDetail::Tool(
|
item: item::ItemDetail::Tool(
|
||||||
@ -340,17 +340,17 @@ fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -361,7 +361,7 @@ fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -369,22 +369,21 @@ fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
item_id: 0x210000,
|
item_id: 0x210000,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
||||||
assert!(p1_inventory.count() == 30);
|
assert!(p1_inventory.count() == 30);
|
||||||
|
|
||||||
|
|
||||||
let monomates = p1_inventory.slot(29).unwrap();
|
let monomates = p1_inventory.slot(29).unwrap();
|
||||||
assert!(monomates.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 2));
|
assert!(monomates.item == HeldItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_can_not_pick_up_item_when_inventory_full() {
|
async fn test_can_not_pick_up_item_when_inventory_full() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
for slot in 0..30 {
|
for slot in 0..30 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -403,7 +402,7 @@ fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
slot: slot,
|
slot: slot,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -422,18 +421,17 @@ fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
}
|
}).await;
|
||||||
);
|
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -444,7 +442,7 @@ fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -452,7 +450,7 @@ fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
item_id: 0x210000,
|
item_id: 0x210000,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
||||||
assert!(p1_inventory.count() == 30);
|
assert!(p1_inventory.count() == 30);
|
||||||
@ -460,21 +458,21 @@ fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
assert!(floor_item.item_id == ClientItemId(0x210000));
|
assert!(floor_item.item_id == ClientItemId(0x210000));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_can_not_drop_more_meseta_than_is_held() {
|
async fn test_can_not_drop_more_meseta_than_is_held() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
|
|
||||||
char1.meseta = 300;
|
char1.meseta = 300;
|
||||||
entity_gateway.save_character(&char1);
|
entity_gateway.save_character(&char1).await;
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -483,14 +481,14 @@ fn test_can_not_drop_more_meseta_than_is_held() {
|
|||||||
map_area: 0,
|
map_area: 0,
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let split_attempt = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
let split_attempt = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
||||||
client: 0,
|
client: 0,
|
||||||
target: 0,
|
target: 0,
|
||||||
item_id: 0xFFFFFFFF,
|
item_id: 0xFFFFFFFF,
|
||||||
amount: 301,
|
amount: 301,
|
||||||
}))));
|
})))).await;
|
||||||
assert!(split_attempt.is_err());
|
assert!(split_attempt.is_err());
|
||||||
|
|
||||||
let c1 = ship.clients.get(&ClientId(1)).unwrap();
|
let c1 = ship.clients.get(&ClientId(1)).unwrap();
|
||||||
@ -498,12 +496,12 @@ fn test_can_not_drop_more_meseta_than_is_held() {
|
|||||||
assert!(ship.item_manager.get_floor_item_by_id(&char1, ClientItemId(0xF0000001)).is_err())
|
assert!(ship.item_manager.get_floor_item_by_id(&char1, ClientItemId(0xF0000001)).is_err())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
async fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
for _ in 0..6 {
|
for _ in 0..6 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -518,7 +516,7 @@ fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
}
|
}
|
||||||
for _ in 0..6 {
|
for _ in 0..6 {
|
||||||
entity_gateway.create_item(
|
entity_gateway.create_item(
|
||||||
@ -533,18 +531,18 @@ fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
slot: 0,
|
slot: 0,
|
||||||
equipped: false,
|
equipped: false,
|
||||||
}
|
}
|
||||||
});
|
}).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -555,7 +553,7 @@ fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -563,7 +561,7 @@ fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
item_id: 0x210000,
|
item_id: 0x210000,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
let p1_inventory = ship.item_manager.get_character_inventory(&char1).unwrap();
|
||||||
let monomates = p1_inventory.slot(0).unwrap();
|
let monomates = p1_inventory.slot(0).unwrap();
|
||||||
@ -572,27 +570,27 @@ fn test_pick_up_stack_that_would_exceed_stack_limit() {
|
|||||||
assert!(floor_monomates.item == FloorItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 6));
|
assert!(floor_monomates.item == FloorItemType::Stacked(item::tool::Tool {tool: item::tool::ToolType::Monomate}, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_can_not_pick_up_meseta_when_full() {
|
async fn test_can_not_pick_up_meseta_when_full() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
char1.meseta = 999999;
|
char1.meseta = 999999;
|
||||||
entity_gateway.save_character(&char1);
|
entity_gateway.save_character(&char1).await;
|
||||||
char2.meseta = 300;
|
char2.meseta = 300;
|
||||||
entity_gateway.save_character(&char2);
|
entity_gateway.save_character(&char2).await;
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -601,14 +599,14 @@ fn test_can_not_pick_up_meseta_when_full() {
|
|||||||
map_area: 0,
|
map_area: 0,
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
||||||
client: 0,
|
client: 0,
|
||||||
target: 0,
|
target: 0,
|
||||||
item_id: 0xFFFFFFFF,
|
item_id: 0xFFFFFFFF,
|
||||||
amount: 23,
|
amount: 23,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -616,7 +614,7 @@ fn test_can_not_pick_up_meseta_when_full() {
|
|||||||
item_id: 0xF0000001,
|
item_id: 0xF0000001,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let c1 = ship.clients.get(&ClientId(1)).unwrap();
|
let c1 = ship.clients.get(&ClientId(1)).unwrap();
|
||||||
let c2 = ship.clients.get(&ClientId(2)).unwrap();
|
let c2 = ship.clients.get(&ClientId(2)).unwrap();
|
||||||
@ -627,27 +625,27 @@ fn test_can_not_pick_up_meseta_when_full() {
|
|||||||
assert!(floor_meseta.item == FloorItemType::Meseta(item::Meseta(23)));
|
assert!(floor_meseta.item == FloorItemType::Meseta(item::Meseta(23)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[async_std::test]
|
||||||
fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
||||||
let mut entity_gateway = InMemoryGateway::new();
|
let mut entity_gateway = InMemoryGateway::new();
|
||||||
|
|
||||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a");
|
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||||
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a");
|
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||||
|
|
||||||
char1.meseta = 999998;
|
char1.meseta = 999998;
|
||||||
entity_gateway.save_character(&char1);
|
entity_gateway.save_character(&char1).await;
|
||||||
char2.meseta = 300;
|
char2.meseta = 300;
|
||||||
entity_gateway.save_character(&char2);
|
entity_gateway.save_character(&char2).await;
|
||||||
|
|
||||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||||
log_in_char(&mut ship, ClientId(1), "a1", "a");
|
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||||
log_in_char(&mut ship, ClientId(2), "a2", "a");
|
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||||
|
|
||||||
join_lobby(&mut ship, ClientId(1));
|
join_lobby(&mut ship, ClientId(1)).await;
|
||||||
join_lobby(&mut ship, ClientId(2));
|
join_lobby(&mut ship, ClientId(2)).await;
|
||||||
|
|
||||||
create_room(&mut ship, ClientId(1), "room", "");
|
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||||
join_room(&mut ship, ClientId(2), 0);
|
join_room(&mut ship, ClientId(2), 0).await;
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::DropCoordinates(DropCoordinates {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -656,14 +654,14 @@ fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
|||||||
map_area: 0,
|
map_area: 0,
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
z: 0.0,
|
z: 0.0,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
||||||
client: 0,
|
client: 0,
|
||||||
target: 0,
|
target: 0,
|
||||||
item_id: 0xFFFFFFFF,
|
item_id: 0xFFFFFFFF,
|
||||||
amount: 23,
|
amount: 23,
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||||
client: 0,
|
client: 0,
|
||||||
@ -671,7 +669,7 @@ fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
|||||||
item_id: 0xF0000001,
|
item_id: 0xF0000001,
|
||||||
area: 0,
|
area: 0,
|
||||||
unknown: [0; 3]
|
unknown: [0; 3]
|
||||||
})))).unwrap().for_each(drop);
|
})))).await.unwrap().for_each(drop);
|
||||||
|
|
||||||
let c1 = ship.clients.get(&ClientId(1)).unwrap();
|
let c1 = ship.clients.get(&ClientId(1)).unwrap();
|
||||||
let c2 = ship.clients.get(&ClientId(2)).unwrap();
|
let c2 = ship.clients.get(&ClientId(2)).unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user