handle case where items are removed from shop after buying
This commit is contained in:
parent
d08db622e2
commit
cebb6a5f31
@ -763,7 +763,7 @@ impl ItemManager {
|
||||
shop_item: &(dyn ShopItem + Send + Sync),
|
||||
item_id: ClientItemId,
|
||||
amount: usize)
|
||||
-> Result<(&InventoryItem), ItemManagerError> {
|
||||
-> Result<&InventoryItem, ItemManagerError> {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
|
||||
let item_detail = shop_item.as_item();
|
||||
|
@ -10,7 +10,7 @@ use crate::ship::items::{ItemManager, ClientItemId, TriggerCreateItem, FloorItem
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use libpso::utf8_to_utf16_array;
|
||||
use crate::ship::packet::builder;
|
||||
use crate::ship::shops::ShopItem;
|
||||
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
||||
|
||||
const BANK_ACTION_DEPOSIT: u8 = 0;
|
||||
const BANK_ACTION_WITHDRAW: u8 = 1;
|
||||
@ -330,22 +330,33 @@ where
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
|
||||
let item: &(dyn ShopItem + Send + Sync) = match buy_item.shop_type {
|
||||
|
||||
let (item, remove): (&(dyn ShopItem + Send + Sync), bool) = match buy_item.shop_type {
|
||||
SHOP_OPTION_WEAPON => {
|
||||
client.weapon_shop.get(buy_item.shop_index as usize).ok_or(ShipError::ShopError)?
|
||||
(client.weapon_shop.get(buy_item.shop_index as usize).ok_or(ShipError::ShopError)?, false)
|
||||
},
|
||||
SHOP_OPTION_TOOL => {
|
||||
client.tool_shop.get(buy_item.shop_index as usize).ok_or(ShipError::ShopError)?
|
||||
let item = client.tool_shop.get(buy_item.shop_index as usize).ok_or(ShipError::ShopError)?;
|
||||
let remove = match item {
|
||||
ToolShopItem::Tech(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
(item, remove)
|
||||
},
|
||||
SHOP_OPTION_ARMOR => {
|
||||
client.armor_shop.get(buy_item.shop_index as usize).ok_or(ShipError::ShopError)?
|
||||
let item = client.armor_shop.get(buy_item.shop_index as usize).ok_or(ShipError::ShopError)?;
|
||||
let remove = match item {
|
||||
ArmorShopItem::Unit(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
(item, remove)
|
||||
},
|
||||
_ => {
|
||||
return Err(ShipError::ShopError)
|
||||
}
|
||||
};
|
||||
|
||||
if client.character.meseta < item.price() as u32{
|
||||
if client.character.meseta < item.price() as u32 {
|
||||
return Err(ShipError::ShopError)
|
||||
}
|
||||
|
||||
@ -353,9 +364,20 @@ where
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
|
||||
let inventory_item = item_manager.player_buys_item(entity_gateway, &client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as usize).await?;
|
||||
|
||||
let create = builder::message::create_withdrawn_inventory_item(area_client, inventory_item)?;
|
||||
|
||||
if remove {
|
||||
match buy_item.shop_type {
|
||||
SHOP_OPTION_TOOL => {
|
||||
client.tool_shop.remove(buy_item.shop_index as usize);
|
||||
},
|
||||
SHOP_OPTION_ARMOR => {
|
||||
client.armor_shop.remove(buy_item.shop_index as usize);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let other_clients_in_area = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||
Ok(Box::new(other_clients_in_area.into_iter()
|
||||
.map(move |c| {
|
||||
|
@ -360,7 +360,7 @@ async fn test_other_clients_see_stacked_purchase() {
|
||||
async fn test_buying_item_without_enough_mseseta() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
@ -445,5 +445,120 @@ async fn test_player_double_buys_from_tool_shop() {
|
||||
let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap();
|
||||
assert!(c1.meseta < 999999);
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
||||
assert_eq!(p1_items.len(), 10);
|
||||
assert_eq!(p1_items.len(), 9);
|
||||
}
|
||||
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_techs_disappear_from_shop_when_bought() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
char1.exp = 80000000;
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
|
||||
let mut ship = 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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
|
||||
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::ShopRequest(ShopRequest {
|
||||
client: 255,
|
||||
target: 255,
|
||||
shop_type: 0,
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
let first_tech = match &packets[0].1 {
|
||||
SendShipPacket::Message(Message {msg: GameMessage::ShopList(shop_list)}) => {
|
||||
shop_list.items.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, item)| {
|
||||
item.item_bytes[0] == 3 && item.item_bytes[1] == 2
|
||||
})
|
||||
.nth(0).unwrap().0
|
||||
},
|
||||
_ => panic!(""),
|
||||
};
|
||||
|
||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BuyItem(BuyItem {
|
||||
client: 255,
|
||||
target: 255,
|
||||
item_id: 0x10000,
|
||||
shop_type: 0,
|
||||
shop_index: first_tech as u8,
|
||||
amount: 1,
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BuyItem(BuyItem {
|
||||
client: 255,
|
||||
target: 255,
|
||||
item_id: 0x10001,
|
||||
shop_type: 0,
|
||||
shop_index: first_tech as u8,
|
||||
amount: 1,
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
||||
assert!(p1_items[0].item != p1_items[1].item);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_units_disappear_from_shop_when_bought() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
char1.exp = 80000000;
|
||||
char1.meseta = 999999;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
|
||||
let mut ship = 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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
|
||||
|
||||
let packets = ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::ShopRequest(ShopRequest {
|
||||
client: 255,
|
||||
target: 255,
|
||||
shop_type: 2,
|
||||
})))).await.unwrap().collect::<Vec<_>>();
|
||||
|
||||
let first_unit = match &packets[0].1 {
|
||||
SendShipPacket::Message(Message {msg: GameMessage::ShopList(shop_list)}) => {
|
||||
shop_list.items.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, item)| {
|
||||
item.item_bytes[0] == 1 && item.item_bytes[1] == 3
|
||||
})
|
||||
.nth(0).unwrap().0
|
||||
},
|
||||
_ => panic!(""),
|
||||
};
|
||||
|
||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BuyItem(BuyItem {
|
||||
client: 255,
|
||||
target: 255,
|
||||
item_id: 0x10000,
|
||||
shop_type: 2,
|
||||
shop_index: first_unit as u8,
|
||||
amount: 1,
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::BuyItem(BuyItem {
|
||||
client: 255,
|
||||
target: 255,
|
||||
item_id: 0x10001,
|
||||
shop_type: 2,
|
||||
shop_index: first_unit as u8,
|
||||
amount: 1,
|
||||
unknown1: 0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
||||
assert!(p1_items[0].item != p1_items[1].item);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user