buy items from shop
This commit is contained in:
		
							parent
							
								
									73a93c0957
								
							
						
					
					
						commit
						ad7572b726
					
				| @ -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; | ||||
| @ -353,7 +353,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 | ||||
| @ -361,7 +361,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) | ||||
| @ -381,16 +380,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,12 +395,11 @@ 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 | ||||
| { | ||||
|  | ||||
| @ -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? | ||||
|             }, | ||||
|             GameMessage::KillMonster(kill_monster) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
| @ -564,7 +564,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