add bank depositing
This commit is contained in:
parent
755ff575cc
commit
1867fee78b
@ -2,6 +2,9 @@ use crate::ship::items::ClientItemId;
|
||||
use libpso::character::character;//::InventoryItem;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail};
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::ship::items::inventory::{InventoryItemHandle, InventoryItem};
|
||||
|
||||
const BANK_CAPACITY: usize = 200;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IndividualBankItem {
|
||||
@ -39,7 +42,7 @@ impl std::cmp::PartialEq for BankItem {
|
||||
|
||||
let self_value = u32::from_be_bytes(self_bytes);
|
||||
let other_value = u32::from_be_bytes(other_bytes);
|
||||
|
||||
|
||||
self_value.eq(&other_value)
|
||||
}
|
||||
}
|
||||
@ -58,7 +61,7 @@ impl std::cmp::PartialOrd for BankItem {
|
||||
|
||||
let self_value = u32::from_be_bytes(self_bytes);
|
||||
let other_value = u32::from_be_bytes(other_bytes);
|
||||
|
||||
|
||||
self_value.partial_cmp(&other_value)
|
||||
}
|
||||
}
|
||||
@ -75,7 +78,7 @@ impl std::cmp::Ord for BankItem {
|
||||
|
||||
let self_value = u32::from_le_bytes(self_bytes);
|
||||
let other_value = u32::from_le_bytes(other_bytes);
|
||||
|
||||
|
||||
self_value.cmp(&other_value)
|
||||
}
|
||||
}
|
||||
@ -123,22 +126,29 @@ impl BankItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CharacterBank(Vec<BankItem>);
|
||||
pub struct CharacterBank {
|
||||
item_id_counter: u32,
|
||||
items: Vec<BankItem>
|
||||
}
|
||||
|
||||
impl CharacterBank {
|
||||
pub fn new(mut items: Vec<BankItem>) -> CharacterBank {
|
||||
items.sort();
|
||||
CharacterBank(items)
|
||||
CharacterBank {
|
||||
item_id_counter: 0,
|
||||
items: items,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_item_ids(&mut self, base_item_id: u32) {
|
||||
for (i, item) in self.0.iter_mut().enumerate() {
|
||||
for (i, item) in self.items.iter_mut().enumerate() {
|
||||
item.set_item_id(ClientItemId(base_item_id + i as u32));
|
||||
}
|
||||
self.item_id_counter = base_item_id + self.items.len() as u32 + 1;
|
||||
}
|
||||
|
||||
|
||||
pub fn as_client_bank_items(&self) -> character::Bank {
|
||||
self.0.iter()
|
||||
self.items.iter()
|
||||
.enumerate()
|
||||
.fold(character::Bank::default(), |mut bank, (slot, item)| {
|
||||
bank.item_count = (slot + 1) as u32;
|
||||
@ -152,7 +162,7 @@ impl CharacterBank {
|
||||
}
|
||||
|
||||
pub fn as_client_bank_request(&self) -> Vec<character::BankItem> {
|
||||
self.0.iter()
|
||||
self.items.iter()
|
||||
.map(|item| {
|
||||
let bytes = item.as_client_bytes();
|
||||
let mut data1 = [0; 12];
|
||||
@ -179,7 +189,65 @@ impl CharacterBank {
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
self.0.len()
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
pub fn deposit_item(&mut self, mut inventory_item: InventoryItemHandle, amount: usize) -> Option<&BankItem> {
|
||||
let remove = match inventory_item.item_mut()? {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
if self.items.len() >= BANK_CAPACITY {
|
||||
return None
|
||||
}
|
||||
self.items.push(BankItem::Individual(IndividualBankItem {
|
||||
entity_id: individual_inventory_item.entity_id,
|
||||
item_id: individual_inventory_item.item_id,
|
||||
item: individual_inventory_item.item.clone(),
|
||||
}));
|
||||
true
|
||||
},
|
||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||
let existing_bank_item = self.items.iter_mut()
|
||||
.find_map(|item| {
|
||||
if let BankItem::Stacked(stacked_bank_item) = item {
|
||||
if stacked_bank_item.tool == stacked_inventory_item.tool {
|
||||
return Some(stacked_bank_item)
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
match existing_bank_item {
|
||||
Some(stacked_bank_item) => {
|
||||
if stacked_bank_item.count() + stacked_inventory_item.count() > stacked_inventory_item.tool.max_stack() {
|
||||
return None
|
||||
}
|
||||
|
||||
let mut deposited_entity_ids = stacked_inventory_item.take_entity_ids(amount)?;
|
||||
stacked_bank_item.entity_ids.append(&mut deposited_entity_ids);
|
||||
}
|
||||
None => {
|
||||
if self.items.len() >= BANK_CAPACITY {
|
||||
return None
|
||||
}
|
||||
let deposited_entity_ids = stacked_inventory_item.take_entity_ids(amount)?;
|
||||
|
||||
self.item_id_counter += 1;
|
||||
self.items.push(BankItem::Stacked(StackedBankItem {
|
||||
entity_ids: deposited_entity_ids,
|
||||
item_id: ClientItemId(self.item_id_counter),
|
||||
tool: stacked_inventory_item.tool,
|
||||
}))
|
||||
}
|
||||
}
|
||||
stacked_inventory_item.count() == 0
|
||||
}
|
||||
};
|
||||
|
||||
if remove {
|
||||
inventory_item.remove_from_inventory();
|
||||
}
|
||||
|
||||
self.items.last()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,9 +228,9 @@ impl RoomFloorItems {
|
||||
pub fn drop_partial_stacked_inventory_item(&mut self, inventory_item: InventoryItemHandle, amount: usize, new_item_id: ClientItemId, item_drop_location: (MapArea, f32, f32, f32)) -> Option<&StackedFloorItem> {
|
||||
let consumed_item = inventory_item.consume(amount).ok()?;
|
||||
|
||||
if let ItemDetail::Tool(tool) = consumed_item.item {
|
||||
if let ItemDetail::Tool(tool) = consumed_item.item() {
|
||||
self.0.push(FloorItem::Stacked(StackedFloorItem {
|
||||
entity_ids: consumed_item.entity_ids,
|
||||
entity_ids: consumed_item.entity_ids(),
|
||||
item_id: new_item_id,
|
||||
tool: tool,
|
||||
map_area: item_drop_location.0,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::cmp::Ordering;
|
||||
use thiserror::Error;
|
||||
use libpso::character::character;//::InventoryItem;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail};
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemType};
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::ship::items::ClientItemId;
|
||||
use crate::ship::items::floor::{IndividualFloorItem, StackedFloorItem};
|
||||
@ -29,6 +29,15 @@ impl StackedInventoryItem {
|
||||
pub fn count(&self) -> usize {
|
||||
self.entity_ids.len()
|
||||
}
|
||||
|
||||
pub fn take_entity_ids(&mut self, amount: usize) -> Option<Vec<ItemEntityId>> {
|
||||
if amount <= self.count() {
|
||||
Some(self.entity_ids.drain(..amount).collect())
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -68,6 +77,18 @@ impl InventoryItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_type(&self) -> ItemType {
|
||||
match self {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
individual_inventory_item.item.item_type()
|
||||
},
|
||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||
ItemType::Tool(stacked_inventory_item.tool.tool)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TOOD: delete?
|
||||
pub fn are_same_stackable_tool(&self, other_stacked_item: &StackedFloorItem) -> bool {
|
||||
match self {
|
||||
InventoryItem::Stacked(self_stacked_item) => {
|
||||
@ -78,6 +99,7 @@ impl InventoryItem {
|
||||
}
|
||||
}
|
||||
|
||||
// TOOD: delete?
|
||||
pub fn can_combine_stacks(&self, other_stacked_item: &StackedFloorItem) -> bool {
|
||||
match self {
|
||||
InventoryItem::Stacked(self_stacked_item) => {
|
||||
@ -90,6 +112,7 @@ impl InventoryItem {
|
||||
}
|
||||
|
||||
// TODO: result
|
||||
// TOOD: delete?
|
||||
pub fn combine_stacks(&mut self, other_stacked_item: &mut StackedFloorItem) {
|
||||
match self {
|
||||
InventoryItem::Stacked(self_stacked_item) => {
|
||||
@ -164,7 +187,7 @@ pub enum InventoryItemConsumeError {
|
||||
}
|
||||
|
||||
pub struct IndividualConsumedItem {
|
||||
pub entity_ids: ItemEntityId,
|
||||
pub entity_id: ItemEntityId,
|
||||
pub item: ItemDetail,
|
||||
}
|
||||
|
||||
@ -185,7 +208,18 @@ impl ConsumedItem {
|
||||
vec![individual_consumed_item.entity_id]
|
||||
},
|
||||
ConsumedItem::Stacked(stacked_consumed_item) => {
|
||||
stacked_consumed_item.entity_ids
|
||||
stacked_consumed_item.entity_ids.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item(&self) -> ItemDetail {
|
||||
match self {
|
||||
ConsumedItem::Individual(individual_consumed_item) => {
|
||||
individual_consumed_item.item.clone()
|
||||
},
|
||||
ConsumedItem::Stacked(stacked_consumed_item) => {
|
||||
ItemDetail::Tool(stacked_consumed_item.tool)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,6 +236,10 @@ impl<'a> InventoryItemHandle<'a> {
|
||||
self.inventory.0.get(self.slot)
|
||||
}
|
||||
|
||||
pub fn item_mut(&mut self) -> Option<&mut InventoryItem> {
|
||||
self.inventory.0.get_mut(self.slot)
|
||||
}
|
||||
|
||||
pub fn remove_from_inventory(self) {
|
||||
self.inventory.0.remove(self.slot);
|
||||
}
|
||||
@ -216,7 +254,7 @@ impl<'a> InventoryItemHandle<'a> {
|
||||
let remove_method = match inventory_item {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
RemoveMethod::EntireThing(ConsumedItem::Individual(IndividualConsumedItem {
|
||||
entity_ids: individual_inventory_item.entity_id,
|
||||
entity_id: individual_inventory_item.entity_id,
|
||||
item: individual_inventory_item.item.clone()
|
||||
}))
|
||||
},
|
||||
|
@ -32,15 +32,18 @@ pub enum ItemManagerError {
|
||||
Idunnoman,
|
||||
CouldNotSplitItem(ClientItemId),
|
||||
CouldNotDropMeseta,
|
||||
InvalidBankName(BankName),
|
||||
NotEnoughTools(Tool, usize, usize), // have, expected
|
||||
InventoryItemConsumeError(#[from] InventoryItemConsumeError),
|
||||
BankFull,
|
||||
}
|
||||
|
||||
pub struct ItemManager {
|
||||
id_counter: u32,
|
||||
|
||||
character_inventory: HashMap<CharacterEntityId, CharacterInventory>,
|
||||
character_bank: HashMap<CharacterEntityId, BTreeMap<BankName, CharacterBank>>,
|
||||
//character_bank: HashMap<CharacterEntityId, BTreeMap<BankName, CharacterBank>>,
|
||||
character_bank: HashMap<CharacterEntityId, CharacterBank>,
|
||||
character_floor: HashMap<CharacterEntityId, RoomFloorItems>,
|
||||
|
||||
character_room: HashMap<CharacterEntityId, RoomId>,
|
||||
@ -101,7 +104,8 @@ impl ItemManager {
|
||||
acc
|
||||
});
|
||||
|
||||
let bank_items = items.into_iter()
|
||||
// TODO: not using BankName anymore, clean this up
|
||||
let mut bank_items = items.into_iter()
|
||||
.filter_map(|item| {
|
||||
match item.location {
|
||||
ItemLocation::Bank{name, ..} => Some((item.id, item.item, name)),
|
||||
@ -158,7 +162,7 @@ impl ItemManager {
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
|
||||
self.character_inventory.insert(character.id, inventory);
|
||||
self.character_bank.insert(character.id, bank_items);
|
||||
self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new())));
|
||||
}
|
||||
|
||||
pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
|
||||
@ -166,7 +170,7 @@ impl ItemManager {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).unwrap();
|
||||
inventory.initialize_item_ids(base_inventory_id);
|
||||
let base_bank_id = ((area_client.local_client.id() as u32) << 21) | 0x20000;
|
||||
let default_bank = self.character_bank.get_mut(&character.id).unwrap().get_mut(&BankName("".to_string()));
|
||||
let default_bank = self.character_bank.get_mut(&character.id);//.unwrap().get_mut(&BankName("".to_string()));
|
||||
match default_bank {
|
||||
Some(default_bank) => {
|
||||
default_bank.initialize_item_ids(base_bank_id);
|
||||
@ -192,11 +196,20 @@ impl ItemManager {
|
||||
pub fn get_character_bank(&self, character: &CharacterEntity) -> Result<&CharacterBank, ItemManagerError> {
|
||||
Ok(self.character_bank
|
||||
.get(&character.id)
|
||||
.ok_or(ItemManagerError::NoCharacter(character.id))?
|
||||
.get(&BankName("".to_string()))
|
||||
.unwrap()) // TODO: make an error
|
||||
.ok_or(ItemManagerError::NoCharacter(character.id))?)
|
||||
//.get(&BankName("".to_string()))
|
||||
//.ok_or(ItemManagerError::InvalidBankName(BankName("".to_string())))?)
|
||||
}
|
||||
|
||||
/*pub fn get_character_bank_mut(&mut self, character: &CharacterEntity) -> Result<&CharacterBank, ItemManagerError> {
|
||||
Ok(self.character_bank
|
||||
.get_mut(&character.id)
|
||||
.ok_or(ItemManagerError::NoCharacter(character.id))?
|
||||
.entry(BankName("".to_string()))
|
||||
.or_insert(CharacterBank::new(Vec::new())))
|
||||
//.ok_or(ItemManagerError::InvalidBankName(BankName("".to_string())))?)
|
||||
}*/
|
||||
|
||||
pub fn remove_character_from_room(&mut self, character: &CharacterEntity) {
|
||||
self.character_inventory.remove(&character.id);
|
||||
self.character_floor.remove(&character.id);
|
||||
@ -256,7 +269,6 @@ impl ItemManager {
|
||||
},
|
||||
Some(FloorItem::Stacked(stacked_floor_item)) => {
|
||||
let new_inventory_item = inventory.pick_up_stacked_floor_item(&stacked_floor_item);
|
||||
println!("new inv item! {:?}", new_inventory_item);
|
||||
|
||||
match new_inventory_item {
|
||||
Some((new_inventory_item, slot)) => {
|
||||
@ -506,15 +518,42 @@ impl ItemManager {
|
||||
ItemLocation::Consumed).await;
|
||||
}
|
||||
|
||||
Ok(consumed_item.item)
|
||||
Ok(consumed_item.item())
|
||||
}
|
||||
|
||||
pub async fn player_deposits_item<EG: EntityGateway>(&mut self,
|
||||
_entity_gateway: &mut EG,
|
||||
_character: &CharacterEntity,
|
||||
_item_id: ClientItemId,
|
||||
_amount: usize)
|
||||
entity_gateway: &mut EG,
|
||||
character: &CharacterEntity,
|
||||
item_id: ClientItemId,
|
||||
amount: usize)
|
||||
-> Result<(), ItemManagerError> {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
let bank = self.character_bank
|
||||
.get_mut(&character.id)
|
||||
.ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
|
||||
let item_to_deposit = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
|
||||
let bank_item = bank.deposit_item(item_to_deposit, amount).ok_or(ItemManagerError::Idunnoman)?;
|
||||
|
||||
match bank_item {
|
||||
BankItem::Individual(individual_bank_item) => {
|
||||
entity_gateway.change_item_location(&individual_bank_item.entity_id,
|
||||
ItemLocation::Bank {
|
||||
character_id: character.id,
|
||||
name: BankName("".to_string())
|
||||
}).await;
|
||||
},
|
||||
BankItem::Stacked(stacked_bank_item) => {
|
||||
for entity_id in &stacked_bank_item.entity_ids {
|
||||
entity_gateway.change_item_location(entity_id,
|
||||
ItemLocation::Bank {
|
||||
character_id: character.id,
|
||||
name: BankName("".to_string())
|
||||
}).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -524,6 +563,7 @@ impl ItemManager {
|
||||
_item_id: ClientItemId,
|
||||
_amount: usize)
|
||||
-> Result<(), ItemManagerError> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use libpso::packet::messages::*;
|
||||
use libpso::packet::ship::*;
|
||||
use crate::common::leveltable::CharacterStats;
|
||||
use crate::ship::ship::{ShipError};
|
||||
use crate::ship::items::{StackedFloorItem, FloorItem, CharacterBank};
|
||||
use crate::ship::items::{ClientItemId, StackedFloorItem, FloorItem, CharacterBank};
|
||||
use crate::ship::location::AreaClient;
|
||||
use std::convert::TryInto;
|
||||
|
||||
@ -118,3 +118,12 @@ pub fn bank_item_list(bank: &CharacterBank) -> BankItemList {
|
||||
items: bank.as_client_bank_request()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn player_no_longer_has_item(area_client: AreaClient, item_id: ClientItemId, amount: u32) -> PlayerNoLongerHasItem {
|
||||
PlayerNoLongerHasItem {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
item_id: item_id.0,
|
||||
amount: amount,
|
||||
}
|
||||
}
|
||||
|
@ -72,45 +72,6 @@ where
|
||||
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
|
||||
/*
|
||||
let item_drop_packets = clients_in_area.into_iter()
|
||||
.filter_map(|area_client| {
|
||||
room.drop_table.get_drop(&monster.map_area, &monster.monster).map(|item_drop_type| {
|
||||
warn!("drop is? {:?}", item_drop_type);
|
||||
(area_client, item_drop_type)
|
||||
})
|
||||
})
|
||||
.map(|(area_client, item_drop_type)| async {
|
||||
let item_drop = ItemDrop {
|
||||
map_area: monster.map_area,
|
||||
x: request_item.x,
|
||||
y: request_item.y,
|
||||
z: request_item.z,
|
||||
item: item_drop_type,
|
||||
};
|
||||
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
||||
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap
|
||||
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
|
||||
|
||||
// I am not able to manually specify a closure return type when also using the async keyword
|
||||
let result: Result<(ClientId, SendShipPacket), ShipError> = Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))));
|
||||
result
|
||||
})
|
||||
.map(|item_drop_pkt| async {
|
||||
item_drop_pkt.await
|
||||
});
|
||||
|
||||
let item_drop_packets = join_all(item_drop_packets).await.into_iter()
|
||||
.filter_map(|item_drop_pkt| {
|
||||
// TODO: log errors here
|
||||
item_drop_pkt.ok()
|
||||
});
|
||||
|
||||
//.collect::<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| {
|
||||
@ -209,41 +170,6 @@ EG: EntityGateway
|
||||
|
||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
|
||||
/*let item_drop_packets = clients_in_area.into_iter()
|
||||
.filter_map(|area_client| {
|
||||
room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| {
|
||||
warn!("drop is? {:?}", item_drop_type);
|
||||
(area_client, item_drop_type)
|
||||
})
|
||||
})
|
||||
.map(async move |(area_client, item_drop_type)| -> Result<_, ShipError> {
|
||||
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_type,
|
||||
};
|
||||
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
|
||||
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap
|
||||
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?;
|
||||
Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))
|
||||
})
|
||||
/*.filter_map(|item_drop_pkt| {
|
||||
// TODO: log errors here
|
||||
item_drop_pkt.ok()
|
||||
})
|
||||
.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| {
|
||||
@ -287,6 +213,7 @@ pub async fn send_bank_list(id: ClientId,
|
||||
pub async fn bank_interaction<EG>(id: ClientId,
|
||||
bank_interaction: &BankInteraction,
|
||||
entity_gateway: &mut EG,
|
||||
client_location: &ClientLocation,
|
||||
clients: &mut Clients,
|
||||
item_manager: &mut ItemManager)
|
||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||
@ -294,32 +221,50 @@ where
|
||||
EG: EntityGateway
|
||||
{
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
match bank_interaction.action {
|
||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let clients_in_area = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let bank_action_pkts = match bank_interaction.action {
|
||||
BANK_ACTION_DEPOSIT => {
|
||||
if bank_interaction.item_id == 0xFFFFFFFF {
|
||||
if client.character.meseta < bank_interaction.meseta_amount && client.character.bank_meseta <= 999999 {
|
||||
client.character.meseta += bank_interaction.meseta_amount;
|
||||
if client.character.meseta > bank_interaction.meseta_amount && (bank_interaction.meseta_amount + client.character.bank_meseta) <= 999999 {
|
||||
client.character.meseta -= bank_interaction.meseta_amount;
|
||||
client.character.bank_meseta += bank_interaction.meseta_amount;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
else {
|
||||
//let inventory_item = item_manager.get_inventory_item_by_id(&client.character, ClientItemId(bank_interaction.item_id))?;
|
||||
item_manager.player_deposits_item(entity_gateway, &client.character, ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as usize).await?;
|
||||
let player_no_longer_has_item = builder::message::player_no_longer_has_item(area_client, ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as u32);
|
||||
vec![SendShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)))]
|
||||
}
|
||||
},
|
||||
BANK_ACTION_WITHDRAW => {
|
||||
if bank_interaction.item_id == 0xFFFFFFFF {
|
||||
if client.character.meseta + bank_interaction.meseta_amount <= 999999 {
|
||||
client.character.meseta += bank_interaction.meseta_amount;
|
||||
client.character.bank_meseta -= bank_interaction.meseta_amount;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
else {
|
||||
//let bank_item = item_manager.get_bank_item_by_id(&client.character, ClientItemId(bank_interaction.item_id))?;
|
||||
item_manager.player_withdraws_item(entity_gateway, &client.character, ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as usize).await?;
|
||||
Vec::new()
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
Ok(Box::new(None.into_iter()))
|
||||
_ => {
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Box::new(clients_in_area.into_iter()
|
||||
.map(move |c| {
|
||||
bank_action_pkts.clone().into_iter()
|
||||
.map(move |pkt| {
|
||||
(c.client, pkt)
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
))
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ pub fn drop_coordinates(id: ClientId,
|
||||
}
|
||||
|
||||
pub async fn split_item_stack<EG>(id: ClientId,
|
||||
split_item_stack: &PlayerSplitItemStack,
|
||||
no_longer_has_item: &PlayerNoLongerHasItem,
|
||||
entity_gateway: &mut EG,
|
||||
client_location: &ClientLocation,
|
||||
clients: &mut Clients,
|
||||
@ -131,12 +131,12 @@ where
|
||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
let drop_location = client.item_drop_location.ok_or(ShipError::ItemDropLocationNotSet)?;
|
||||
|
||||
if drop_location.item_id.0 != split_item_stack.item_id {
|
||||
return Err(ShipError::DropInvalidItemId(split_item_stack.item_id));
|
||||
if drop_location.item_id.0 != no_longer_has_item.item_id {
|
||||
return Err(ShipError::DropInvalidItemId(no_longer_has_item.item_id));
|
||||
}
|
||||
|
||||
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).await?;
|
||||
if no_longer_has_item.item_id == 0xFFFFFFFF {
|
||||
let dropped_meseta = item_manager.player_drops_meseta_on_shared_floor(entity_gateway, &mut client.character, drop_location, no_longer_has_item.amount as u32).await?;
|
||||
|
||||
let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta)?;
|
||||
client.item_drop_location = None;
|
||||
@ -148,7 +148,7 @@ where
|
||||
})))
|
||||
}
|
||||
else {
|
||||
let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, drop_location.item_id, drop_location, split_item_stack.amount as usize).await?;
|
||||
let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, drop_location.item_id, drop_location, no_longer_has_item.amount as usize).await?;
|
||||
|
||||
let dropped_item_pkt = builder::message::drop_split_stack(area_client, dropped_item)?;
|
||||
client.item_drop_location = None;
|
||||
|
@ -283,8 +283,8 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
GameMessage::DropCoordinates(drop_coordinates) => {
|
||||
handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms)
|
||||
},
|
||||
GameMessage::PlayerSplitItemStack(split_item_stack) => {
|
||||
handler::message::split_item_stack(id, split_item_stack, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
|
||||
GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
|
||||
handler::message::split_item_stack(id, no_longer_has_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
|
||||
},
|
||||
GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) |
|
||||
GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) |
|
||||
@ -327,7 +327,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await
|
||||
},
|
||||
GameMessage::BankInteraction(bank_interaction) => {
|
||||
handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await
|
||||
handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await
|
||||
},
|
||||
_ => {
|
||||
let cmsg = msg.clone();
|
||||
|
@ -197,7 +197,6 @@ async fn test_request_bank_items_sorted() {
|
||||
unknown: 0,
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
println!("{:?}", packets);
|
||||
assert!(matches!(&packets[0], (_, SendShipPacket::BankItemList (bank_item_list))
|
||||
if bank_item_list.item_count == 3
|
||||
&& bank_item_list.size == 0x18 * 3 + 0x14
|
||||
@ -208,12 +207,781 @@ async fn test_request_bank_items_sorted() {
|
||||
}
|
||||
|
||||
|
||||
//test_deposit_individual_item
|
||||
//test_deposit_stacked_item
|
||||
//test_deposit_stacked_item_with_stack_already_in_bank
|
||||
//test_deposit_stacked_item_when_full_stack_in_bank
|
||||
//test_deposit_individual_item_in_full_bank
|
||||
//test_deposit_stacked_item_in_full_bank
|
||||
//test_deposit_meseta
|
||||
//test_deposit_too_much_meseta
|
||||
//test_deposit_when_bank_has_max_meseta
|
||||
#[async_std::test]
|
||||
async fn test_deposit_individual_item() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
weapon: item::weapon::WeaponType::Saber,
|
||||
grind: 0,
|
||||
special: None,
|
||||
attrs: [None, None, None],
|
||||
tekked: true,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
weapon: item::weapon::WeaponType::Handgun,
|
||||
grind: 0,
|
||||
special: None,
|
||||
attrs: [None, None, None],
|
||||
tekked: true,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
let packets = 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().collect::<Vec<_>>();
|
||||
|
||||
assert!(packets.len() == 1);
|
||||
assert!(matches!(&packets[0], (_, SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
|
||||
if player_no_longer_has_item.item_id == 0x10001
|
||||
&& player_no_longer_has_item.amount == 0
|
||||
));
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids == vec![item::ItemEntityId(2)]);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_stacked_item() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for _ in 0..3 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
action: 0,
|
||||
item_amount: 3,
|
||||
meseta_amount: 0,
|
||||
unknown: 0,
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
assert!(packets.len() == 1);
|
||||
assert!(matches!(&packets[0], (_, SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
|
||||
if player_no_longer_has_item.item_id == 0x10000
|
||||
&& player_no_longer_has_item.amount == 3
|
||||
));
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids == vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3)]);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_partial_stacked_item() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for _ in 0..3 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
action: 0,
|
||||
item_amount: 2,
|
||||
meseta_amount: 0,
|
||||
unknown: 0,
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
assert!(packets.len() == 1);
|
||||
assert!(matches!(&packets[0], (_, SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
|
||||
if player_no_longer_has_item.item_id == 0x10000
|
||||
&& player_no_longer_has_item.amount == 2
|
||||
));
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids == vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
|
||||
|
||||
let inventory_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Inventory {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(inventory_item_ids == vec![item::ItemEntityId(3)]);
|
||||
}
|
||||
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_stacked_item_with_stack_already_in_bank() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for _ in 0..2 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: char1.id,
|
||||
name: item::BankName("".into()),
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
action: 0,
|
||||
item_amount: 2,
|
||||
meseta_amount: 0,
|
||||
unknown: 0,
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
assert!(packets.len() == 1);
|
||||
assert!(matches!(&packets[0], (_, SendShipPacket::Message(Message {msg: GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)}))
|
||||
if player_no_longer_has_item.item_id == 0x10000
|
||||
&& player_no_longer_has_item.amount == 2
|
||||
));
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids == vec![item::ItemEntityId(1), item::ItemEntityId(2), item::ItemEntityId(3), item::ItemEntityId(4)]);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_stacked_item_with_full_stack_in_bank() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for _ in 0..2 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
for _ in 0..10 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: char1.id,
|
||||
name: item::BankName("".into()),
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
action: 0,
|
||||
item_amount: 2,
|
||||
meseta_amount: 0,
|
||||
unknown: 0,
|
||||
})))).await;
|
||||
|
||||
assert!(packets.is_err());
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids.len() == 10);
|
||||
|
||||
let inventory_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Inventory {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(inventory_item_ids == vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_individual_item_in_full_bank() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
weapon: item::weapon::WeaponType::Vulcan,
|
||||
grind: 0,
|
||||
special: None,
|
||||
attrs: [None, None, None],
|
||||
tekked: true,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
|
||||
for _ in 0..200 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
weapon: item::weapon::WeaponType::Vulcan,
|
||||
grind: 0,
|
||||
special: None,
|
||||
attrs: [None, None, None],
|
||||
tekked: true,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: char1.id,
|
||||
name: item::BankName("".to_string())
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
let packets = 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;
|
||||
|
||||
assert!(packets.is_err());
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids.len() == 200);
|
||||
|
||||
let inventory_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Inventory {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(inventory_item_ids == vec![item::ItemEntityId(1)]);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_stacked_item_in_full_bank() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for _ in 0..2 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
for _ in 0..200 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
weapon: item::weapon::WeaponType::Vulcan,
|
||||
grind: 0,
|
||||
special: None,
|
||||
attrs: [None, None, None],
|
||||
tekked: true,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: char1.id,
|
||||
name: item::BankName("".to_string())
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
action: 0,
|
||||
item_amount: 2,
|
||||
meseta_amount: 0,
|
||||
unknown: 0,
|
||||
})))).await;
|
||||
|
||||
assert!(packets.is_err());
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids.len() == 200);
|
||||
|
||||
let inventory_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Inventory {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(inventory_item_ids == vec![item::ItemEntityId(1), item::ItemEntityId(2)]);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
for _ in 0..2 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
for _ in 0..199 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Weapon(
|
||||
item::weapon::Weapon {
|
||||
weapon: item::weapon::WeaponType::Vulcan,
|
||||
grind: 0,
|
||||
special: None,
|
||||
attrs: [None, None, None],
|
||||
tekked: true,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: char1.id,
|
||||
name: item::BankName("".to_string())
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
for _ in 0..2 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Bank {
|
||||
character_id: char1.id,
|
||||
name: item::BankName("".to_string())
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BankInteraction(BankInteraction {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
action: 0,
|
||||
item_amount: 2,
|
||||
meseta_amount: 0,
|
||||
unknown: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let bank_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Bank {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(bank_item_ids.len() == 203);
|
||||
|
||||
let inventory_item_ids = items.iter()
|
||||
.filter_map(|item| {
|
||||
if let item::ItemLocation::Inventory {..} = item.location {
|
||||
Some(item.id)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(inventory_item_ids.len() == 0);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_meseta() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
char1.meseta = 300;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
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().for_each(drop);
|
||||
|
||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
||||
let char = characters[0].as_ref().unwrap();
|
||||
println!("meseta {}", char.meseta);
|
||||
assert!(char.meseta == 277);
|
||||
assert!(char.bank_meseta == 23);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_too_much_meseta() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
char1.meseta = 300;
|
||||
char1.bank_meseta = 999980;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
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().for_each(drop);
|
||||
|
||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
||||
let char = characters[0].as_ref().unwrap();
|
||||
println!("meseta {}", char.meseta);
|
||||
assert!(char.meseta == 300);
|
||||
assert!(char.bank_meseta == 999980);
|
||||
}
|
||||
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_deposit_meseta_when_bank_is_maxed() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
char1.meseta = 300;
|
||||
char1.bank_meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
|
||||
let mut ship = ShipServerState::new(entity_gateway.clone());
|
||||
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().for_each(drop);
|
||||
|
||||
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().for_each(drop);
|
||||
|
||||
let characters = entity_gateway.get_characters_by_user(&user1).await;
|
||||
let char = characters[0].as_ref().unwrap();
|
||||
println!("meseta {}", char.meseta);
|
||||
assert!(char.meseta == 300);
|
||||
assert!(char.bank_meseta == 999999);
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ async fn test_pick_up_meseta_when_inventory_full() {
|
||||
z: 0.0,
|
||||
})))).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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0xFFFFFFFF,
|
||||
@ -445,7 +445,7 @@ async fn test_can_not_drop_more_meseta_than_is_held() {
|
||||
z: 0.0,
|
||||
})))).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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0xFFFFFFFF,
|
||||
@ -565,7 +565,7 @@ async fn test_can_not_pick_up_meseta_when_full() {
|
||||
z: 0.0,
|
||||
})))).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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0xFFFFFFFF,
|
||||
@ -579,7 +579,6 @@ async fn test_can_not_pick_up_meseta_when_full() {
|
||||
map_area: 0,
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
println!("pkts {:?}", packets);
|
||||
assert!(packets.len() == 0);
|
||||
|
||||
let characters1 = entity_gateway.get_characters_by_user(&user1).await;
|
||||
@ -622,7 +621,7 @@ async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() {
|
||||
z: 0.0,
|
||||
})))).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::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0xFFFFFFFF,
|
||||
@ -688,7 +687,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() {
|
||||
z: 0.0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSplitItemStack(PlayerSplitItemStack {
|
||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
|
Loading…
x
Reference in New Issue
Block a user