buy items from shop
This commit is contained in:
parent
ce09c93940
commit
b5c821f1ae
@ -9,8 +9,9 @@ use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction};
|
||||
use crate::ship::items::state::{ItemState, ItemStateProxy, ItemStateAction, ItemAction, ItemStateError, FloorItem, InventoryItem, AddItemResult, FloorItemDetail,
|
||||
StackedItemDetail, BankItem, BankItemDetail, InventoryItemDetail, IndividualItemDetail};
|
||||
use crate::ship::items::apply_item::apply_item;
|
||||
use crate::entity::item::ItemDetail;
|
||||
use crate::entity::item::{ItemDetail, ItemEntity, NewItemEntity};
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::ship::shops::ShopItem;
|
||||
|
||||
|
||||
|
||||
@ -701,3 +702,88 @@ where
|
||||
Ok((transaction, ()))
|
||||
}).await
|
||||
}
|
||||
|
||||
|
||||
fn add_bought_item_to_inventory<'a>(character_id: CharacterEntityId,
|
||||
shop_item: &'a (dyn ShopItem + Send + Sync),
|
||||
item_id: ClientItemId,
|
||||
amount: u32)
|
||||
-> impl Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), ())
|
||||
-> Pin<Box<dyn Future<Output=Result<((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), InventoryItem), ItemStateError>> + Send + 'a>>
|
||||
{
|
||||
move |(mut item_state, mut transaction), _| {
|
||||
Box::pin(async move {
|
||||
let mut inventory = item_state.inventory(&character_id)?;
|
||||
let bought_item = shop_item.as_item();
|
||||
|
||||
let inventory_item = match bought_item {
|
||||
ItemDetail::Tool(tool) if tool.is_stackable() => {
|
||||
let mut item_entities = Vec::new();
|
||||
for _ in 0..amount {
|
||||
let item_entity = transaction.gateway().create_item(NewItemEntity {
|
||||
item: ItemDetail::Tool(tool),
|
||||
}).await?;
|
||||
transaction.gateway().add_item_note(&item_entity.id, ItemNote::BoughtAtShop {
|
||||
character_id: character_id,
|
||||
}).await?;
|
||||
item_entities.push(item_entity);
|
||||
}
|
||||
|
||||
let inventory_item = InventoryItem {
|
||||
item_id,
|
||||
item: InventoryItemDetail::Stacked(StackedItemDetail {
|
||||
entity_ids: item_entities.into_iter().map(|i| i.id).collect(),
|
||||
tool: tool,
|
||||
})
|
||||
};
|
||||
inventory.add_item(inventory_item)?.1
|
||||
},
|
||||
item_detail => {
|
||||
let item_entity = transaction.gateway().create_item(NewItemEntity {
|
||||
item: item_detail.clone(),
|
||||
}).await?;
|
||||
transaction.gateway().add_item_note(&item_entity.id, ItemNote::BoughtAtShop {
|
||||
character_id: character_id,
|
||||
}).await?;
|
||||
|
||||
let inventory_item = InventoryItem {
|
||||
item_id,
|
||||
item: InventoryItemDetail::Individual(IndividualItemDetail {
|
||||
entity_id: item_entity.id,
|
||||
item: item_detail,
|
||||
})
|
||||
};
|
||||
inventory.add_item(inventory_item)?.1
|
||||
},
|
||||
};
|
||||
|
||||
transaction.gateway().set_character_inventory(&character_id, &inventory.as_inventory_entity(&character_id)).await?;
|
||||
item_state.set_inventory(inventory);
|
||||
Ok(((item_state, transaction), inventory_item))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn buy_shop_item<'a, EG> (
|
||||
item_state: &'a mut ItemState,
|
||||
entity_gateway: &mut EG,
|
||||
character: &CharacterEntity,
|
||||
shop_item: &'a (dyn ShopItem + Send + Sync),
|
||||
item_id: ClientItemId,
|
||||
amount: u32,
|
||||
) -> Result<InventoryItem, ItemStateError>
|
||||
where
|
||||
EG: EntityGateway,
|
||||
{
|
||||
let item_price = shop_item.price() as u32 * amount;
|
||||
entity_gateway.with_transaction(|transaction| async move {
|
||||
let item_state_proxy = ItemStateProxy::new(item_state);
|
||||
let ((item_state_proxy, transaction), result) = ItemStateAction::default()
|
||||
.act(take_meseta_from_inventory(character.id, item_price))
|
||||
.act(add_bought_item_to_inventory(character.id, shop_item, item_id, amount))
|
||||
.commit((item_state_proxy, transaction))
|
||||
.await?;
|
||||
item_state_proxy.commit();
|
||||
Ok((transaction, result))
|
||||
}).await
|
||||
}
|
||||
|
@ -600,7 +600,7 @@ impl InventoryState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_item(&mut self, item: InventoryItem) -> Result<AddItemResult, InventoryError> {
|
||||
pub fn add_item(&mut self, item: InventoryItem) -> Result<(AddItemResult, InventoryItem), InventoryError> {
|
||||
match &item.item {
|
||||
InventoryItemDetail::Individual(_) => {
|
||||
if self.inventory.0.len() >= 30 {
|
||||
@ -608,7 +608,13 @@ impl InventoryState {
|
||||
}
|
||||
else {
|
||||
self.inventory.0.push(item);
|
||||
Ok(AddItemResult::NewItem)
|
||||
Ok((
|
||||
AddItemResult::NewItem,
|
||||
self.inventory.0
|
||||
.last()
|
||||
.unwrap()
|
||||
.clone()
|
||||
))
|
||||
}
|
||||
},
|
||||
InventoryItemDetail::Stacked(sitem) => {
|
||||
@ -625,7 +631,15 @@ impl InventoryState {
|
||||
}
|
||||
else {
|
||||
existing_stack.entity_ids.append(&mut sitem.entity_ids.clone());
|
||||
Ok(AddItemResult::AddToStack)
|
||||
Ok((
|
||||
AddItemResult::AddToStack,
|
||||
self.inventory.0[self.inventory.0
|
||||
.iter()
|
||||
.filter_map(|item| item.item.stacked())
|
||||
.position(|item| item.tool == sitem.tool)
|
||||
.unwrap()]
|
||||
.clone()
|
||||
))
|
||||
}
|
||||
},
|
||||
None => {
|
||||
@ -634,7 +648,13 @@ impl InventoryState {
|
||||
}
|
||||
else {
|
||||
self.inventory.0.push(item);
|
||||
Ok(AddItemResult::NewItem)
|
||||
Ok((
|
||||
AddItemResult::NewItem,
|
||||
self.inventory.0
|
||||
.last()
|
||||
.unwrap()
|
||||
.clone()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,13 +68,13 @@ pub fn create_meseta(area_client: AreaClient, amount: usize) -> CreateItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_withdrawn_inventory_item(area_client: AreaClient, item: &InventoryItem) -> Result<CreateItem, ShipError> {
|
||||
let bytes = item.as_client_bytes();
|
||||
pub fn create_withdrawn_inventory_item(area_client: AreaClient, item: &InventoryItem2) -> Result<CreateItem, ShipError> {
|
||||
let bytes = item.item.as_client_bytes();
|
||||
Ok(CreateItem {
|
||||
client: area_client.local_client.id(),
|
||||
target: 0,
|
||||
item_data: bytes[0..12].try_into()?,
|
||||
item_id: item.item_id().0,
|
||||
item_id: item.item_id.0,
|
||||
item_data2: bytes[12..16].try_into()?,
|
||||
unknown: 0,
|
||||
})
|
||||
|
@ -15,7 +15,7 @@ use libpso::utf8_to_utf16_array;
|
||||
use crate::ship::packet::builder;
|
||||
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
||||
use crate::ship::items::state::{ItemState, FloorType, FloorItemDetail};
|
||||
use crate::ship::items::actions::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, TriggerCreateItem};
|
||||
use crate::ship::items::actions::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, TriggerCreateItem};
|
||||
|
||||
const BANK_ACTION_DEPOSIT: u8 = 0;
|
||||
const BANK_ACTION_WITHDRAW: u8 = 1;
|
||||
@ -347,7 +347,7 @@ pub async fn buy_item<EG>(id: ClientId,
|
||||
entity_gateway: &mut EG,
|
||||
client_location: &ClientLocation,
|
||||
clients: &mut Clients,
|
||||
item_manager: &mut ItemManager)
|
||||
item_state: &mut ItemState)
|
||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||
where
|
||||
EG: EntityGateway
|
||||
@ -355,7 +355,6 @@ 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, 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)?, false)
|
||||
@ -375,16 +374,8 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
let character_meseta = item_manager.get_character_meseta_mut(&client.character.id)?;
|
||||
if character_meseta.0 < (item.price() * buy_item.amount as usize) as u32 {
|
||||
return Err(ShipError::ShopError.into())
|
||||
}
|
||||
|
||||
character_meseta.0 -= (item.price() * buy_item.amount as usize) as u32;
|
||||
entity_gateway.set_character_meseta(&client.character.id, *character_meseta).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)?;
|
||||
let inventory_item = buy_shop_item(item_state, entity_gateway, &mut client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as u32).await?;
|
||||
let create = builder::message::create_withdrawn_inventory_item(area_client, &inventory_item)?;
|
||||
|
||||
if remove {
|
||||
match buy_item.shop_type {
|
||||
|
@ -395,17 +395,16 @@ where
|
||||
}
|
||||
|
||||
pub async fn player_sells_item<EG> (id: ClientId,
|
||||
sold_item: &PlayerSoldItem,
|
||||
entity_gateway: &mut EG,
|
||||
// client_location: &ClientLocation,
|
||||
clients: &mut Clients,
|
||||
item_manager: &mut ItemManager)
|
||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||
sold_item: &PlayerSoldItem,
|
||||
entity_gateway: &mut EG,
|
||||
clients: &mut Clients,
|
||||
item_state: &mut ItemState)
|
||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||
where
|
||||
EG: EntityGateway
|
||||
{
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
item_manager.player_sells_item(entity_gateway, &mut client.character, ClientItemId(sold_item.item_id), sold_item.amount as usize).await?;
|
||||
//item_manager.player_sells_item(entity_gateway, &mut client.character, ClientItemId(sold_item.item_id), sold_item.amount as usize).await?;
|
||||
// TODO: send the packet to other clients
|
||||
Ok(Box::new(None.into_iter()))
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &self.clients, &mut self.item_state).await?
|
||||
},
|
||||
GameMessage::PlayerSoldItem(player_sold_item) => {
|
||||
handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await?
|
||||
handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_state).await?
|
||||
},
|
||||
_ => {
|
||||
let cmsg = msg.clone();
|
||||
@ -560,7 +560,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &self.level_table, &mut self.shops).await?
|
||||
},
|
||||
GameMessage::BuyItem(buy_item) => {
|
||||
handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
|
||||
handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await?
|
||||
},
|
||||
GameMessage::TekRequest(tek_request) => {
|
||||
handler::direct_message::request_tek_item(id, tek_request, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await?
|
||||
|
Loading…
x
Reference in New Issue
Block a user