Compare commits

...

7 Commits

Author SHA1 Message Date
4e4f5e4ee2 clippy
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-06 23:16:46 -07:00
1028120048 test withdrawing a bit more 2023-02-06 23:16:28 -07:00
b8f05a0ea5 shared bank tests 2023-02-06 23:08:09 -07:00
7c3acc8b3d properly order bank items before assigning item ids 2023-02-06 22:38:13 -07:00
a7c1968a48 properly commit shared bank meseta in inmemory transaction 2023-02-06 20:42:48 -07:00
1bd88fdaaf itembuilder to clean up item creation in tests 2023-02-06 18:07:13 -07:00
9f91ada947 fix inmemory get_bank_meseta 2023-02-06 18:06:25 -07:00
11 changed files with 549 additions and 74 deletions

View File

@ -200,6 +200,7 @@ impl EntityGatewayTransaction for InMemoryGatewayTransaction {
self.original_gateway.characters.lock().await.extend(self.working_gateway.characters.lock().await.clone());
self.original_gateway.character_meseta.lock().await.extend(self.working_gateway.character_meseta.lock().await.clone());
self.original_gateway.bank_meseta.lock().await.extend(self.working_gateway.bank_meseta.lock().await.clone());
self.original_gateway.shared_bank_meseta.lock().await.extend(self.working_gateway.shared_bank_meseta.lock().await.clone());
self.original_gateway.items.lock().await.extend(self.working_gateway.items.lock().await.clone());
self.original_gateway.inventories.lock().await.extend(self.working_gateway.inventories.lock().await.clone());
self.original_gateway.character_banks.lock().await.extend(self.working_gateway.character_banks.lock().await.clone());
@ -735,7 +736,7 @@ impl EntityGateway for InMemoryGateway {
Ok(*meseta)
}
else {
Err(GatewayError::Error)
Ok(Meseta(0))
}
}
}

View File

@ -650,13 +650,13 @@ impl From<ItemNote> for PgItemNoteDetail {
ItemNote::Withdraw{character_id, bank} => {
PgItemNoteDetail::Withdraw {
character_id: character_id.0,
bank: bank,
bank,
}
},
ItemNote::Deposit{character_id, bank} => {
PgItemNoteDetail::Deposit {
character_id: character_id.0,
bank: bank,
bank,
}
}
}
@ -697,11 +697,11 @@ impl From<PgItemNoteDetail> for ItemNote {
},
PgItemNoteDetail::Withdraw{character_id, bank} => ItemNote::Withdraw {
character_id: CharacterEntityId(character_id),
bank: bank,
bank,
},
PgItemNoteDetail::Deposit{character_id, bank} => ItemNote::Deposit {
character_id: CharacterEntityId(character_id),
bank: bank,
bank,
},
}
}

View File

@ -635,7 +635,7 @@ async fn get_bank_meseta(conn: &mut sqlx::PgConnection, char_id: &CharacterEntit
.bind(&bank_name.0)
.fetch_optional(conn)
.await?
.unwrap_or_else(|| PgMeseta(0))
.unwrap_or(PgMeseta(0))
}
};
Ok(Meseta(meseta.0 as u32))

View File

@ -23,7 +23,7 @@ use libpso::{utf8_to_array, utf8_to_utf16_array};
use crate::entity::gateway::{EntityGateway, GatewayError};
use crate::entity::account::{UserAccountId, UserAccountEntity, NewUserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM};
use crate::entity::item::{NewItemEntity, ItemDetail, ItemNote, InventoryItemEntity, InventoryEntity, BankEntity, BankName, BankIdentifier, EquippedEntity, Meseta};
use crate::entity::item::{NewItemEntity, ItemDetail, ItemNote, InventoryItemEntity, InventoryEntity, BankEntity, BankIdentifier, EquippedEntity, Meseta};
use crate::entity::item::weapon::Weapon;
use crate::entity::item::armor::Armor;
use crate::entity::item::tech::Technique;

View File

@ -7,15 +7,13 @@ use crate::ship::items::state::ItemState;
use crate::entity::item::{BankName, BankIdentifier};
use crate::ship::packet::builder::message::bank_item_list;
async fn default_bank<'a, EG, T>(id: ClientId,
tokens: T,
entity_gateway: &mut EG,
clients: &Clients,
item_state: &mut ItemState)
-> Result<Vec<(ClientId, SendShipPacket)>, String>
async fn default_bank<'a, EG>(id: ClientId,
entity_gateway: &mut EG,
clients: &Clients,
item_state: &mut ItemState)
-> Result<Vec<(ClientId, SendShipPacket)>, String>
where
EG: EntityGateway + Clone + 'static,
T: Iterator<Item = &'a str> + 'a,
{
let bank = clients
.with_mut(id, |client| {
@ -28,8 +26,8 @@ where
})
})
.await
.map_err(|err| format!("an error occured\n{:?}", err))?
.map_err(|err| format!("an error occured\n{:?}", err))?;
.map_err(|err| format!("an error occured\n{err:?}"))?
.map_err(|err| format!("an error occured\n{err:?}"))?;
let bank_items_pkt = bank_item_list(&bank);
Ok(vec![(id, SendShipPacket::BankItemList(bank_items_pkt))])
@ -45,8 +43,7 @@ where
EG: EntityGateway + Clone + 'static,
T: Iterator<Item = &'a str> + 'a,
{
let bank_name = BankName(tokens.next().unwrap_or(&"").into());
let bank_name = BankName(tokens.next().unwrap_or("").into());
let bank = clients
.with_mut(id, |client| {
let mut item_state = item_state.clone();
@ -58,8 +55,8 @@ where
})
})
.await
.map_err(|err| format!("an error occured\n{:?}", err))?
.map_err(|err| format!("an error occured\n{:?}", err))?;
.map_err(|err| format!("an error occured\n{err:?}"))?
.map_err(|err| format!("an error occured\n{err:?}"))?;
let bank_items_pkt = bank_item_list(&bank);
Ok(vec![(id, SendShipPacket::BankItemList(bank_items_pkt))])
@ -76,11 +73,11 @@ where
let mut tokens = message.message
.trim_start_matches("\tJ")
.trim_start_matches("\tE")
.trim_end_matches("\0")
.trim_end_matches('\0')
.split_whitespace();
let cmd = tokens.next()?;
match cmd {
"/bank" => Some(default_bank(id, tokens, &mut state.entity_gateway, &state.clients, &mut state.item_state).await),
"/bank" => Some(default_bank(id, &mut state.entity_gateway, &state.clients, &mut state.item_state).await),
"/sbank" => Some(switch_bank(id, tokens, &mut state.entity_gateway, &state.clients, &mut state.item_state).await),
_ => None,

View File

@ -424,7 +424,6 @@ where
transaction.gateway().set_character_bank(&character_id, &bank.as_bank_entity(), &bank.identifier).await?;
item_state.set_bank(bank).await;
Ok(((item_state, transaction), ()))
})
}

View File

@ -1,7 +1,7 @@
use std::cmp::Ordering;
use libpso::character::character;
use crate::ship::items::ClientItemId;
use crate::entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, BankEntity, BankItemEntity, BankName};
use crate::entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, BankEntity, BankItemEntity};
use std::future::Future;
use async_std::sync::{Arc, Mutex};
@ -305,12 +305,14 @@ impl BankState {
}
}
impl std::cmp::PartialEq for BankItem {
fn eq(&self, other: &BankItem) -> bool {
impl std::cmp::PartialEq for BankItemDetail {
fn eq(&self, other: &BankItemDetail) -> bool {
let mut self_bytes = [0u8; 4];
let mut other_bytes = [0u8; 4];
self_bytes.copy_from_slice(&self.item.as_client_bytes()[0..4]);
other_bytes.copy_from_slice(&other.item.as_client_bytes()[0..4]);
self_bytes.copy_from_slice(&self.as_client_bytes()[0..4]);
other_bytes.copy_from_slice(&other.as_client_bytes()[0..4]);
let self_value = u32::from_be_bytes(self_bytes);
let other_value = u32::from_be_bytes(other_bytes);
@ -319,15 +321,14 @@ impl std::cmp::PartialEq for BankItem {
}
}
impl std::cmp::Eq for BankItem {}
impl std::cmp::Eq for BankItemDetail {}
impl std::cmp::PartialOrd for BankItem {
fn partial_cmp(&self, other: &BankItem) -> Option<std::cmp::Ordering> {
impl std::cmp::PartialOrd for BankItemDetail {
fn partial_cmp(&self, other: &BankItemDetail) -> Option<std::cmp::Ordering> {
let mut self_bytes = [0u8; 4];
let mut other_bytes = [0u8; 4];
self_bytes.copy_from_slice(&self.item.as_client_bytes()[0..4]);
other_bytes.copy_from_slice(&other.item.as_client_bytes()[0..4]);
self_bytes.copy_from_slice(&self.as_client_bytes()[0..4]);
other_bytes.copy_from_slice(&other.as_client_bytes()[0..4]);
let self_value = u32::from_be_bytes(self_bytes);
let other_value = u32::from_be_bytes(other_bytes);
@ -336,13 +337,12 @@ impl std::cmp::PartialOrd for BankItem {
}
}
impl std::cmp::Ord for BankItem {
fn cmp(&self, other: &BankItem) -> std::cmp::Ordering {
impl std::cmp::Ord for BankItemDetail {
fn cmp(&self, other: &BankItemDetail) -> std::cmp::Ordering {
let mut self_bytes = [0u8; 4];
let mut other_bytes = [0u8; 4];
self_bytes.copy_from_slice(&self.item.as_client_bytes()[0..4]);
other_bytes.copy_from_slice(&other.item.as_client_bytes()[0..4]);
self_bytes.copy_from_slice(&self.as_client_bytes()[0..4]);
other_bytes.copy_from_slice(&other.as_client_bytes()[0..4]);
let self_value = u32::from_le_bytes(self_bytes);
let other_value = u32::from_le_bytes(other_bytes);
@ -351,3 +351,24 @@ impl std::cmp::Ord for BankItem {
}
}
impl std::cmp::PartialEq for BankItem {
fn eq(&self, other: &BankItem) -> bool {
self.item.eq(&other.item)
}
}
impl std::cmp::Eq for BankItem {}
impl std::cmp::PartialOrd for BankItem {
fn partial_cmp(&self, other: &BankItem) -> Option<std::cmp::Ordering> {
self.item.partial_cmp(&other.item)
}
}
impl std::cmp::Ord for BankItem {
fn cmp(&self, other: &BankItem) -> std::cmp::Ordering {
self.item.cmp(&other.item)
}
}

View File

@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::collections::{HashMap, BinaryHeap};
use std::cmp::Reverse;
use async_std::sync::{Arc, RwLock, Mutex};
use futures::future::join_all;
use futures::stream::{FuturesOrdered, StreamExt};
use anyhow::Context;
use crate::entity::gateway::{EntityGateway, GatewayError};
@ -270,39 +271,43 @@ impl ItemState {
pub async fn load_character_bank<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, bank_identifier: BankIdentifier) -> Result<(), anyhow::Error> {
let bank = entity_gateway.get_character_bank(&character.id, &bank_identifier).await?;
let bank_items = join_all(
bank.items.into_iter()
.map(|item| {
let mut citem_state = self.clone();
async move {
Ok(match item {
BankItemEntity::Individual(item) => {
BankItem {
item_id: citem_state.new_item_id().await?,
item: BankItemDetail::Individual(IndividualItemDetail {
entity_id: item.id,
item: item.item,
})
}
},
BankItemEntity::Stacked(items) => {
BankItem {
item_id: citem_state.new_item_id().await?,
item: BankItemDetail::Stacked(StackedItemDetail {
entity_ids: items.iter().map(|i| i.id).collect(),
tool: items.get(0)
.ok_or_else(|| ItemStateError::StackedItemError(items.clone()))?
.item
.clone()
.as_tool()
.ok_or_else(|| ItemStateError::StackedItemError(items.clone()))?
})
}
},
let bank_items = bank.items
.into_iter()
.map(|item| {
Ok(Reverse(match item {
BankItemEntity::Individual(item) => {
BankItemDetail::Individual(IndividualItemDetail {
entity_id: item.id,
item: item.item,
})
}})
.collect::<Vec<_>>())
.await
},
BankItemEntity::Stacked(items) => {
BankItemDetail::Stacked(StackedItemDetail {
entity_ids: items.iter().map(|i| i.id).collect(),
tool: items.get(0)
.ok_or_else(|| ItemStateError::StackedItemError(items.clone()))?
.item
.clone()
.as_tool()
.ok_or_else(|| ItemStateError::StackedItemError(items.clone()))?
})
}
}))
})
.collect::<Result<BinaryHeap<_>, anyhow::Error>>()?
.into_iter()
.map(|item| {
let mut citem_state = self.clone();
async move {
Ok(BankItem {
item_id: citem_state.new_item_id().await?,
item: item.0,
})
}
})
.collect::<FuturesOrdered<_>>()
.collect::<Vec<_>>()
.await
.into_iter()
.collect::<Result<Vec<_>, anyhow::Error>>()?;

View File

@ -736,7 +736,7 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
self.direct_message(id, msg).await?
},
RecvShipPacket::PlayerChat(msg) => {
match chatcommand::handle_chat_command(id, msg.clone(), &mut self).await {
match chatcommand::handle_chat_command(id, msg.clone(), self).await {
Some(ccmd) => {
match ccmd {
Ok(pkts) => pkts,

View File

@ -8,6 +8,8 @@ use elseware::entity::item::{Meseta, BankName, BankIdentifier};
use elseware::ship::ship::{ShipServerState, RecvShipPacket};
use elseware::ship::room::Difficulty;
use elseware::entity::item;
use libpso::packet::ship::*;
use libpso::packet::login::{Login, Session};
use libpso::{utf8_to_array, utf8_to_utf16_array};
@ -92,3 +94,44 @@ pub async fn join_room<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>
})).await.unwrap();
ship.handle(id, RecvShipPacket::DoneBursting(DoneBursting {})).await.unwrap();
}
pub struct WeaponBuilder {
weapon: item::weapon::WeaponType,
grind: u8,
}
impl WeaponBuilder {
pub fn grind(self, grind: u8) -> WeaponBuilder {
WeaponBuilder {
grind,
..self
}
}
pub fn as_new(self) -> item::NewItemEntity {
item::NewItemEntity {
item: item::ItemDetail::Weapon(
item::weapon::Weapon {
weapon: self.weapon,
grind: self.grind,
special: None,
attrs: [None, None, None],
tekked: true,
}
)
}
}
}
pub struct ItemBuilder;
impl ItemBuilder {
pub fn weapon(weapon: item::weapon::WeaponType) -> WeaponBuilder {
WeaponBuilder {
weapon,
grind: 0,
}
}
}

View File

@ -1633,3 +1633,412 @@ async fn test_withdraw_meseta_and_buy_a_few_monomates_with_it() {
//assert!(c1_meseta.0 == 23);
//assert!(c1_bank_meseta.0 == 277);
}
#[async_std::test]
async fn test_deposit_items_into_shared_banks() {
let mut entity_gateway = InMemoryGateway::default();
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
let item0 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Saber).as_new()).await.unwrap();
let item1 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Buster).as_new()).await.unwrap();
let item2 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Rifle).as_new()).await.unwrap();
let item3 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Handgun).as_new()).await.unwrap();
let item4 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Autogun).as_new()).await.unwrap();
let item5 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Calibur).as_new()).await.unwrap();
entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![item0, item1, item2, item3, item4, item5])).await.unwrap();
let mut ship = Box::new(ShipServerState::builder()
.gateway(entity_gateway.clone())
.build());
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
join_lobby(&mut ship, ClientId(1)).await;
create_room(&mut ship, ClientId(1), "room", "").await;
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x10000,
action: 0,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank asdf".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x10001,
action: 0,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x10002,
action: 0,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank qwer".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x10003,
action: 0,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/bank".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x10004,
action: 0,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
let bank_items = entity_gateway.get_character_bank(&char1.id, &item::BankIdentifier::Shared(item::BankName("asdf".into()))).await.unwrap();
assert_eq!(bank_items.items.len(), 2);
bank_items.items[0].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(2));
}).unwrap();
bank_items.items[1].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(3));
}).unwrap();
let bank_items = entity_gateway.get_character_bank(&char1.id, &item::BankIdentifier::Shared(item::BankName("qwer".into()))).await.unwrap();
assert_eq!(bank_items.items.len(), 1);
bank_items.items[0].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(4));
}).unwrap();
let bank_items = entity_gateway.get_character_bank(&char1.id, &item::BankIdentifier::Character).await.unwrap();
assert_eq!(bank_items.items.len(), 2);
bank_items.items[0].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(1));
}).unwrap();
bank_items.items[1].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(5));
}).unwrap();
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
assert_eq!(inventory_items.items.len(), 1);
inventory_items.items[0].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(6));
}).unwrap();
}
#[async_std::test]
async fn test_deposit_meseta_into_shared_banks() {
let mut entity_gateway = InMemoryGateway::default();
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
entity_gateway.set_character_meseta(&char1.id, item::Meseta(300)).await.unwrap();
let mut ship = Box::new(ShipServerState::builder()
.gateway(entity_gateway.clone())
.build());
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
join_lobby(&mut ship, ClientId(1)).await;
create_room(&mut ship, ClientId(1), "room", "").await;
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0xFFFFFFFF,
action: 0,
item_amount: 0,
meseta_amount: 23,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank asdf".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0xFFFFFFFF,
action: 0,
item_amount: 0,
meseta_amount: 55,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank qwer".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0xFFFFFFFF,
action: 0,
item_amount: 0,
meseta_amount: 32,
unknown: 0,
})))).await.unwrap();
let meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
assert_eq!(meseta.0, 300-23-55-32);
let bank_meseta = entity_gateway.get_bank_meseta(&char1.id, &item::BankIdentifier::Character).await.unwrap();
assert_eq!(bank_meseta.0, 23);
let bank_meseta = entity_gateway.get_bank_meseta(&char1.id, &item::BankIdentifier::Shared(item::BankName("asdf".into()))).await.unwrap();
assert_eq!(bank_meseta.0, 55);
let bank_meseta = entity_gateway.get_bank_meseta(&char1.id, &item::BankIdentifier::Shared(item::BankName("qwer".into()))).await.unwrap();
assert_eq!(bank_meseta.0, 32);
}
#[async_std::test]
async fn test_withdraw_items_from_shared_banks() {
let mut entity_gateway = InMemoryGateway::default();
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
let item0 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Saber).as_new()).await.unwrap();
let item1 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Buster).as_new()).await.unwrap();
let item2 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Rifle).as_new()).await.unwrap();
let item3 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Handgun).as_new()).await.unwrap();
let item4 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Autogun).as_new()).await.unwrap();
let item5 = entity_gateway.create_item(ItemBuilder::weapon(item::weapon::WeaponType::Calibur).as_new()).await.unwrap();
entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![item0, item1]), &item::BankIdentifier::Character).await.unwrap();
entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![item2, item3]), &item::BankIdentifier::Shared(item::BankName("asdf".into()))).await.unwrap();
entity_gateway.set_character_bank(&char1.id, &item::BankEntity::new(vec![item4, item5]), &item::BankIdentifier::Shared(item::BankName("qwer".into()))).await.unwrap();
let mut ship = Box::new(ShipServerState::builder()
.gateway(entity_gateway.clone())
.build());
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
join_lobby(&mut ship, ClientId(1)).await;
create_room(&mut ship, ClientId(1), "room", "").await;
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x20000, // saber (1)
action: 1,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank asdf".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x810003, // handgun (4)
action: 1,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x810004, // rifle (3)
action: 1,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank qwer".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0x810006, // autogun (5)
action: 1,
item_amount: 0,
meseta_amount: 0,
unknown: 0,
})))).await.unwrap();
let bank_items = entity_gateway.get_character_bank(&char1.id, &item::BankIdentifier::Shared(item::BankName("asdf".into()))).await.unwrap();
assert_eq!(bank_items.items.len(), 0);
let bank_items = entity_gateway.get_character_bank(&char1.id, &item::BankIdentifier::Shared(item::BankName("qwer".into()))).await.unwrap();
assert_eq!(bank_items.items.len(), 1);
bank_items.items[0].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(6));
}).unwrap();
let bank_items = entity_gateway.get_character_bank(&char1.id, &item::BankIdentifier::Character).await.unwrap();
assert_eq!(bank_items.items.len(), 1);
bank_items.items[0].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(2));
}).unwrap();
let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap();
assert_eq!(inventory_items.items.len(), 4);
inventory_items.items[0].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(1));
}).unwrap();
inventory_items.items[1].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(4));
}).unwrap();
inventory_items.items[2].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(3));
}).unwrap();
inventory_items.items[3].with_individual(|item| {
assert_eq!(item.id, item::ItemEntityId(5));
}).unwrap();
}
#[async_std::test]
async fn test_withdraw_meseta_from_shared_banks() {
let mut entity_gateway = InMemoryGateway::default();
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
entity_gateway.set_bank_meseta(&char1.id, &item::BankIdentifier::Character, item::Meseta(300)).await.unwrap();
entity_gateway.set_bank_meseta(&char1.id, &item::BankIdentifier::Shared(item::BankName("asdf".into())), item::Meseta(300)).await.unwrap();
entity_gateway.set_bank_meseta(&char1.id, &item::BankIdentifier::Shared(item::BankName("qwer".into())), item::Meseta(300)).await.unwrap();
let mut ship = Box::new(ShipServerState::builder()
.gateway(entity_gateway.clone())
.build());
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
join_lobby(&mut ship, ClientId(1)).await;
create_room(&mut ship, ClientId(1), "room", "").await;
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0xFFFFFFFF,
action: 1,
item_amount: 0,
meseta_amount: 23,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank asdf".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0xFFFFFFFF,
action: 1,
item_amount: 0,
meseta_amount: 55,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/sbank qwer".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0xFFFFFFFF,
action: 1,
item_amount: 0,
meseta_amount: 32,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::PlayerChat(PlayerChat::new(0, "\tE/bank".into()))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankRequest(BankRequest {
client: 0,
target: 0,
unknown: 0,
})))).await.unwrap();
ship.handle(ClientId(1), RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
client: 0,
target: 0,
item_id: 0xFFFFFFFF,
action: 1,
item_amount: 0,
meseta_amount: 5,
unknown: 0,
})))).await.unwrap();
let meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
let bank_meseta1 = entity_gateway.get_bank_meseta(&char1.id, &item::BankIdentifier::Character).await.unwrap();
let bank_meseta2 = entity_gateway.get_bank_meseta(&char1.id, &item::BankIdentifier::Shared(item::BankName("asdf".into()))).await.unwrap();
let bank_meseta3 = entity_gateway.get_bank_meseta(&char1.id, &item::BankIdentifier::Shared(item::BankName("qwer".into()))).await.unwrap();
assert_eq!(meseta.0, 23+55+32+5);
assert_eq!(bank_meseta1.0, 300-23-5);
assert_eq!(bank_meseta2.0, 300-55);
assert_eq!(bank_meseta3.0, 300-32);
}