move item state action functions to new file
This commit is contained in:
		
							parent
							
								
									e58aff7042
								
							
						
					
					
						commit
						916bb31671
					
				
							
								
								
									
										314
									
								
								src/ship/items/actions.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								src/ship/items/actions.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,314 @@ | ||||
| use std::collections::HashMap; | ||||
| use crate::ship::items::ClientItemId; | ||||
| use crate::entity::item::{Meseta, ItemEntityId, ItemDetail, ItemEntity, ItemType, InventoryEntity, InventoryItemEntity, EquippedEntity, ItemNote}; | ||||
| use std::cell::{RefMut, RefCell}; | ||||
| use std::ops::{Deref, DerefMut}; | ||||
| use std::convert::{From, Into}; | ||||
| use std::future::Future; | ||||
| use std::pin::Pin; | ||||
| use async_std::sync::{Arc, Mutex}; | ||||
| use std::borrow::BorrowMut; | ||||
| 
 | ||||
| use crate::ship::location::{AreaClient, RoomId}; | ||||
| use crate::entity::character::{CharacterEntity, CharacterEntityId, TechLevel}; | ||||
| use crate::entity::gateway::{EntityGateway, GatewayError}; | ||||
| use crate::entity::gateway::entitygateway::EntityGatewayTransaction; | ||||
| use crate::entity::item::tool::{Tool, ToolType}; | ||||
| use crate::ship::items::state::{ItemState, ItemStateProxy, ItemStateAction, ItemAction, ItemStateError, FloorItem, InventoryItem, AddItemResult}; | ||||
| 
 | ||||
| pub enum TriggerCreateItem {ItemAction, 
 | ||||
|     Yes, | ||||
|     No | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| fn take_item_from_floor(character_id: CharacterEntityId, item_id: ClientItemId) | ||||
|                         -> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), ()) | ||||
|                                            -> Pin<Box<dyn Future<Output=Result<((ItemStateProxy, Box<dyn EntityGatewayTransaction>), FloorItem), ItemStateError>> + Send + 'a>> | ||||
| { | ||||
|     move |(mut item_state, transaction), _| { | ||||
|         Box::pin(async move { | ||||
|             let mut floor = item_state.floor(&character_id)?; | ||||
|             let item = floor.take_item(&item_id).ok_or(ItemStateError::NoFloorItem(item_id))?; | ||||
|             item_state.set_floor(floor); | ||||
|             
 | ||||
|             Ok(((item_state, transaction), item)) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| fn take_item_from_floor(character_id: CharacterEntityId, item_id: ClientItemId) | ||||
|                         -> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), ()) | ||||
|                                                -> Pin<Box<dyn Future<Output=Result<((ItemStateProxy, Box<dyn EntityGatewayTransaction + 'a>), FloorItem), ItemStateError>> + Send + 'a>> | ||||
| { | ||||
|     move |(mut item_state, transaction), _| { | ||||
|         Box::pin(async move { | ||||
|             let mut floor = item_state.floor(&character_id)?; | ||||
|             let item = floor.take_item(&item_id).ok_or(ItemStateError::NoFloorItem(item_id))?; | ||||
|             item_state.set_floor(floor); | ||||
|             
 | ||||
|             Ok(((item_state, transaction), item)) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| fn take_item_from_floor<'a, F, Fut>(character_id: CharacterEntityId, item_id: ClientItemId) -> F | ||||
| where | ||||
|     F: Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), ()) -> Fut, | ||||
|     Fut: Future<Output=Result<((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), FloorItem), ItemStateError>> + Send | ||||
|     //Fut: Result<impl Future<Output=((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), FloorItem)> + Send, ItemStateError>
 | ||||
|     
 | ||||
| { | ||||
|     async move |(mut item_state, transaction): (ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), _: ()| { | ||||
|         let mut floor = item_state.floor(&character_id)?; | ||||
|         let item = floor.take_item(&item_id).ok_or(ItemStateError::NoFloorItem(item_id))?; | ||||
|         item_state.set_floor(floor); | ||||
|         
 | ||||
|         Ok(((item_state, transaction), item)) | ||||
|     } | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| fn add_floor_item_to_inventory<'a, Fut>(character: &CharacterEntity) | ||||
|                                            -> impl Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), FloorItem) -> Fut | ||||
| where | ||||
|     Fut: Future<Output=Result<((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), TriggerCreateItem), ItemStateError>> + Send | ||||
| { | ||||
|     let character = character.clone(); | ||||
|     move |(mut item_state, transaction): (ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), floor_item: FloorItem| { | ||||
|         let character = character.clone(); | ||||
|         async move { | ||||
|             let mut inventory = item_state.inventory(&character.id)?; | ||||
| 
 | ||||
|             let character_id = character.id; | ||||
|             let transaction = floor_item.with_entity_id(Ok(transaction), |mut transaction: Result<_, ItemStateError>, entity_id| { | ||||
|                 async move { | ||||
|                     if let Ok(transaction) = &mut transaction { | ||||
|                         transaction.gateway().add_item_note(&entity_id, ItemNote::Pickup { | ||||
|                             character_id | ||||
|                         }).await?; | ||||
|                     } | ||||
|                     transaction | ||||
|                 }}).await?; | ||||
| 
 | ||||
|             let mut transaction = floor_item.with_mag(Ok(transaction), |mut transaction: Result<_, ItemStateError>, entity_id, _mag| { | ||||
|                 let character = character.clone(); | ||||
|                 async move { | ||||
|                     if let Ok(transaction) = &mut transaction { | ||||
|                         transaction.gateway().change_mag_owner(&entity_id, &character).await?; | ||||
|                     } | ||||
|                     transaction | ||||
|                 }}).await?; | ||||
| 
 | ||||
|             let add_result = inventory.add_floor_item(floor_item)?; | ||||
|             transaction.gateway().set_character_inventory(&character.id, &inventory.inventory.as_inventory_entity(&character.id)).await?; | ||||
|             item_state.set_inventory(inventory); | ||||
| 
 | ||||
|             Ok(((item_state, transaction), | ||||
|                 match add_result { | ||||
|                     AddItemResult::NewItem => TriggerCreateItem::Yes, | ||||
|                     AddItemResult::AddToStack => TriggerCreateItem::No, | ||||
|                     AddItemResult::Meseta => TriggerCreateItem::No, | ||||
|                 })) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| fn add_floor_item_to_inventory(character: &CharacterEntity) | ||||
|                                -> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), FloorItem) | ||||
|                                                   -> Pin<Box<dyn Future<Output=Result<((ItemStateProxy, Box<dyn EntityGatewayTransaction + 'a>), TriggerCreateItem), ItemStateError>> + Send + 'a>> | ||||
| { | ||||
|     let character = character.clone(); | ||||
|     move |(mut item_state, transaction), floor_item| { | ||||
|         let character = character.clone(); | ||||
|         Box::pin(async move { | ||||
|             let mut inventory = item_state.inventory(&character.id)?; | ||||
| 
 | ||||
|             let character_id = character.id; | ||||
|             let transaction = floor_item.with_entity_id(Ok(transaction), |mut transaction: Result<_, ItemStateError>, entity_id| { | ||||
|                 async move { | ||||
|                     if let Ok(transaction) = &mut transaction { | ||||
|                         transaction.gateway().add_item_note(&entity_id, ItemNote::Pickup { | ||||
|                             character_id | ||||
|                         }).await?; | ||||
|                     } | ||||
|                     transaction | ||||
|                 }}).await?; | ||||
| 
 | ||||
|             let mut transaction = floor_item.with_mag(Ok(transaction), |mut transaction: Result<_, ItemStateError>, entity_id, _mag| { | ||||
|                 let character = character.clone(); | ||||
|                 async move { | ||||
|                     if let Ok(transaction) = &mut transaction { | ||||
|                         transaction.gateway().change_mag_owner(&entity_id, &character).await?; | ||||
|                     } | ||||
|                     transaction | ||||
|                 }}).await?; | ||||
| 
 | ||||
|             let add_result = inventory.add_floor_item(floor_item)?; | ||||
|             transaction.gateway().set_character_inventory(&character.id, &inventory.inventory.as_inventory_entity(&character.id)).await?; | ||||
|             item_state.set_inventory(inventory); | ||||
| 
 | ||||
|             Ok(((item_state, transaction), | ||||
|                 match add_result { | ||||
|                     AddItemResult::NewItem => TriggerCreateItem::Yes, | ||||
|                     AddItemResult::AddToStack => TriggerCreateItem::No, | ||||
|                     AddItemResult::Meseta => TriggerCreateItem::No, | ||||
|                 })) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| fn add_floor_item_to_inventory(character: &CharacterEntity) | ||||
|                                -> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), FloorItem) | ||||
|                                                   -> Pin<Box<dyn Future<Output=Result<((ItemStateProxy, Box<dyn EntityGatewayTransaction>), TriggerCreateItem), ItemStateError>> + Send + 'a>> | ||||
| { | ||||
|     let character = character.clone(); | ||||
|     move |(mut item_state, transaction), floor_item| { | ||||
|         let character = character.clone(); | ||||
|         Box::pin(async move { | ||||
|             let mut inventory = item_state.inventory(&character.id)?; | ||||
| 
 | ||||
|             let character_id = character.id; | ||||
|             let transaction = floor_item.with_entity_id(Ok(transaction), |mut transaction: Result<_, ItemStateError>, entity_id| { | ||||
|                 async move { | ||||
|                     if let Ok(transaction) = &mut transaction { | ||||
|                         transaction.gateway().add_item_note(&entity_id, ItemNote::Pickup { | ||||
|                             character_id | ||||
|                         }).await?; | ||||
|                     } | ||||
|                     transaction | ||||
|                 }}).await?; | ||||
| 
 | ||||
|             let mut transaction = floor_item.with_mag(Ok(transaction), |mut transaction: Result<_, ItemStateError>, entity_id, _mag| { | ||||
|                 let character = character.clone(); | ||||
|                 async move { | ||||
|                     if let Ok(transaction) = &mut transaction { | ||||
|                         transaction.gateway().change_mag_owner(&entity_id, &character).await?; | ||||
|                     } | ||||
|                     transaction | ||||
|                 }}).await?; | ||||
| 
 | ||||
|             let add_result = inventory.add_floor_item(floor_item)?; | ||||
|             transaction.gateway().set_character_inventory(&character.id, &inventory.inventory.as_inventory_entity(&character.id)).await?; | ||||
|             item_state.set_inventory(inventory); | ||||
| 
 | ||||
|             Ok(((item_state, transaction), | ||||
|                 match add_result { | ||||
|                     AddItemResult::NewItem => TriggerCreateItem::Yes, | ||||
|                     AddItemResult::AddToStack => TriggerCreateItem::No, | ||||
|                     AddItemResult::Meseta => TriggerCreateItem::No, | ||||
|                 })) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| fn take_item_from_inventory(character_id: CharacterEntityId, item_id: ClientItemId) | ||||
|                             -> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), ()) | ||||
|                                                -> Pin<Box<dyn Future<Output=Result<((ItemStateProxy, Box<dyn EntityGatewayTransaction>), InventoryItem), ItemStateError>> + Send + 'a>> | ||||
| { | ||||
|     move |(mut item_state, transaction), _| { | ||||
|         Box::pin(async move { | ||||
|             let mut inventory = item_state.inventory(&character_id)?; | ||||
|             let item = inventory.take_item(&item_id); | ||||
| 
 | ||||
|             transaction.gateway().set_character_inventory(&character_id, &inventory.inventory.as_inventory_entity(&character_id)).await?; | ||||
|             item_state.set_inventory(inventory); | ||||
|             Ok((item_state, transaction), item)    
 | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fn add_inventory_item_to_shared_floor(character: &CharacterEntity) | ||||
|                                       -> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction>), InventoryItem) | ||||
|                                                          -> Pin<Box<dyn Future<Output=Result<((ItemStateProxy, Box<dyn EntityGatewayTransaction>), ()), ItemStateError>> + Send + 'a>> | ||||
| { | ||||
|     let character = character.clone(); | ||||
|     move |(mut item_state, transaction), inventory_item| { | ||||
|         let character = character.clone(); | ||||
|         Box::pin(async move { | ||||
|             
 | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| pub async fn pick_up_item<'a, EG>( | ||||
|     item_state: &'a mut ItemState, | ||||
|     entity_gateway: &mut EG, | ||||
|     character: &CharacterEntity, | ||||
|     item_id: &ClientItemId) | ||||
|     -> Result<TriggerCreateItem, ItemStateError> | ||||
| where | ||||
|     //'a: 'static,
 | ||||
|     EG: EntityGateway, | ||||
| { | ||||
|     let result: Result<TriggerCreateItem, ItemStateError> = 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_item_from_floor(character.id, *item_id)) | ||||
|             .act(add_floor_item_to_inventory(character)) | ||||
|             .commit((item_state_proxy, transaction)) | ||||
|             .await?; | ||||
|         item_state_proxy.commit(); | ||||
|         Ok((transaction, result)) | ||||
|     }).await; | ||||
|     Ok(result?) | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| pub async fn pick_up_item<EG>( | ||||
|     item_state: &mut ItemState, | ||||
|     entity_gateway: &mut EG, | ||||
|     character: &CharacterEntity, | ||||
|     item_id: &ClientItemId) | ||||
|     -> Result<TriggerCreateItem, ItemStateError> | ||||
| where | ||||
|     EG: EntityGateway, | ||||
| { | ||||
|     let result: Result<TriggerCreateItem, ItemStateError> = 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_item_from_floor(character.id, *item_id)) | ||||
|             .act(add_floor_item_to_inventory(character)) | ||||
|             .commit((item_state_proxy, transaction)) | ||||
|             .await?; | ||||
|         item_state_proxy.commit(); | ||||
|         Ok((transaction, result)) | ||||
|     }).await; | ||||
|     Ok(result?) | ||||
| } | ||||
| 
 | ||||
| pub async fn drop_item<EG>( | ||||
|     item_state: &mut ItemState, | ||||
|     entity_gateway: &mut EG, | ||||
|     character: &CharacterEntity, | ||||
|     item_id: &ClientItemId) | ||||
|     -> Result<(), ItemStateError> | ||||
| where | ||||
|     //'a: 'static,
 | ||||
|     EG: EntityGateway, | ||||
| { | ||||
| /* | ||||
|     let result: Result<TriggerCreateItem, ItemStateError> = 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_item_from_inventory(character.id, *item_id)) | ||||
|             .act(add_inventory_item_to_shared_floor(&character)) | ||||
|             .commit((item_state_proxy, transaction)) | ||||
|             .await?; | ||||
|         item_state_proxy.commit(); | ||||
|         Ok((transaction, result)) | ||||
|     }).await; | ||||
|     Ok(result?) | ||||
|      */ | ||||
|     Ok(()) | ||||
| } | ||||
| @ -5,6 +5,7 @@ pub mod manager; | ||||
| pub mod transaction; | ||||
| pub mod use_tool; | ||||
| pub mod state; | ||||
| pub mod actions; | ||||
| use serde::{Serialize, Deserialize}; | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, derive_more::Display)] | ||||
|  | ||||
| @ -14,16 +14,12 @@ use crate::entity::character::{CharacterEntity, CharacterEntityId, TechLevel}; | ||||
| use crate::entity::gateway::{EntityGateway, GatewayError}; | ||||
| use crate::entity::gateway::entitygateway::EntityGatewayTransaction; | ||||
| use crate::entity::item::tool::{Tool, ToolType}; | ||||
| use crate::entity::item::mag::Mag; | ||||
| use crate::ship::drops::ItemDrop; | ||||
| 
 | ||||
| pub enum TriggerCreateItem { | ||||
|     Yes, | ||||
|     No | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[derive(thiserror::Error, Debug)] | ||||
| enum ItemStateError { | ||||
| pub enum ItemStateError { | ||||
|     #[error("character {0} not found")] | ||||
|     NoCharacter(CharacterEntityId), | ||||
|     #[error("room {0} not found")] | ||||
| @ -46,7 +42,7 @@ enum ItemStateError { | ||||
| 
 | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| trait ItemAction { | ||||
| pub trait ItemAction { | ||||
|     type Input; | ||||
|     type Output; | ||||
|     type Start; | ||||
| @ -57,7 +53,7 @@ trait ItemAction { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| struct ItemStateAction<T, S, E> { | ||||
| pub struct ItemStateAction<T, S, E> { | ||||
|     _t: std::marker::PhantomData<T>, | ||||
|     _s: std::marker::PhantomData<S>, | ||||
|     _e: std::marker::PhantomData<E>, | ||||
| @ -185,20 +181,20 @@ where | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| struct IndividualItemDetail { | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct IndividualItemDetail { | ||||
|     entity_id: ItemEntityId, | ||||
|     item: ItemDetail, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct StackedItemDetail { | ||||
|     pub entity_ids: Vec<ItemEntityId>, | ||||
|     pub tool: Tool, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| enum InventoryItemDetail { | ||||
| #[derive(Clone, Debug)] | ||||
| pub enum InventoryItemDetail { | ||||
|     Individual(IndividualItemDetail), | ||||
|     Stacked(StackedItemDetail), | ||||
| } | ||||
| @ -219,14 +215,35 @@ impl InventoryItemDetail { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| struct InventoryItem { | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct InventoryItem { | ||||
|     item_id: ClientItemId, | ||||
|     item: InventoryItemDetail, | ||||
| } | ||||
| 
 | ||||
| impl InventoryItem { | ||||
|     pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> T | ||||
|     where | ||||
|         F: FnMut(T, ItemEntityId) -> Fut, | ||||
|         Fut: Future<Output=T>, | ||||
|     { | ||||
|         match &self.item { | ||||
|             InventoryItemDetail::Individual(individual_item) => { | ||||
|                 param = func(param, individual_item.entity_id.clone()).await; | ||||
|             }, | ||||
|             InventoryItemDetail::Stacked(stacked_item) => { | ||||
|                 for entity_id in &stacked_item.entity_ids { | ||||
|                     param = func(param, entity_id.clone()).await; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         param | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| enum FloorItemDetail { | ||||
| pub enum FloorItemDetail { | ||||
|     Individual(IndividualItemDetail), | ||||
|     Stacked(StackedItemDetail), | ||||
|     Meseta(Meseta), | ||||
| @ -239,14 +256,70 @@ impl FloorItemDetail { | ||||
|             _ => None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|     fn mag<'a>(&'a self) -> Option<&'a IndividualItemDetail> { | ||||
|         match self { | ||||
|             FloorItemDetail::Individual(individual_item) => { | ||||
|                 match individual_item.item { | ||||
|                     ItemDetail::Mag(mag) => Some(mag), | ||||
|                     _ => None, | ||||
|                 } | ||||
|             }, | ||||
|             _ => None | ||||
|         } | ||||
|     } | ||||
| */ | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| struct FloorItem { | ||||
| pub struct FloorItem { | ||||
|     item_id: ClientItemId, | ||||
|     item: FloorItemDetail, | ||||
| } | ||||
| 
 | ||||
| impl FloorItem { | ||||
|     pub async fn with_entity_id<F, Fut, T>(&self, mut param: T, mut func: F) -> T | ||||
|     where | ||||
|         F: FnMut(T, ItemEntityId) -> Fut, | ||||
|         Fut: Future<Output=T>, | ||||
|     { | ||||
|         match &self.item { | ||||
|             FloorItemDetail::Individual(individual_item) => { | ||||
|                 param = func(param, individual_item.entity_id.clone()).await; | ||||
|             }, | ||||
|             FloorItemDetail::Stacked(stacked_item) => { | ||||
|                 for entity_id in &stacked_item.entity_ids { | ||||
|                     param = func(param, entity_id.clone()).await; | ||||
|                 } | ||||
|             }, | ||||
|             FloorItemDetail::Meseta(_meseta) => {}, | ||||
|         } | ||||
| 
 | ||||
|         param | ||||
|     } | ||||
| 
 | ||||
|     pub async fn with_mag<F, Fut, T>(&self, mut param: T, mut func: F) -> T | ||||
|     where | ||||
|         F: FnMut(T, ItemEntityId, Mag) -> Fut, | ||||
|         Fut: Future<Output=T>, | ||||
|     { | ||||
|         match &self.item { | ||||
|             FloorItemDetail::Individual(individual_item) => { | ||||
|                 match &individual_item.item { | ||||
|                     ItemDetail::Mag(mag) => { | ||||
|                         param = func(param, individual_item.entity_id.clone(), mag.clone()).await; | ||||
|                     } | ||||
|                     _ => {} | ||||
|                 } | ||||
|             }, | ||||
|             _ => {} | ||||
|         } | ||||
| 
 | ||||
|         param | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // meseta is a floor item
 | ||||
| /* | ||||
| impl Into<InventoryItem> for FloorItem { | ||||
| @ -259,12 +332,49 @@ impl Into<InventoryItem> for FloorItem { | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| struct Inventory(Vec<InventoryItem>); | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct Inventory(Vec<InventoryItem>); | ||||
| /* | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct Inventory { | ||||
|     item_id_counter: u32, | ||||
|     items: Vec<InventoryItem>, | ||||
|     equipped: EquippedEntity, | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| impl Inventory { | ||||
|     pub fn as_inventory_entity(&self, _character_id: &CharacterEntityId) -> InventoryEntity { | ||||
|         InventoryEntity { | ||||
|             items: self.0.iter() | ||||
|                 .map(|item| { | ||||
|                     match &item.item { | ||||
|                         InventoryItemDetail::Individual(item) => { | ||||
|                             InventoryItemEntity::Individual(ItemEntity { | ||||
|                                 id: item.entity_id, | ||||
|                                 item: item.item.clone(), | ||||
|                             }) | ||||
|                         }, | ||||
|                         InventoryItemDetail::Stacked(items) => { | ||||
|                             InventoryItemEntity::Stacked(items.entity_ids.iter() | ||||
|                                                          .map(|id| { | ||||
|                                                              ItemEntity { | ||||
|                                                                  id: *id, | ||||
|                                                                  item: ItemDetail::Tool(items.tool) | ||||
|                                                              } | ||||
|                                                          }) | ||||
|                                                          .collect()) | ||||
|                         }, | ||||
|                     } | ||||
|                 }) | ||||
|                 .collect() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[derive(thiserror::Error, Debug)] | ||||
| enum InventoryError { | ||||
| pub enum InventoryError { | ||||
|     #[error("inventory full")] | ||||
|     InventoryFull, | ||||
|     #[error("stack full")] | ||||
| @ -273,49 +383,27 @@ enum InventoryError { | ||||
|     MesetaFull, | ||||
| } | ||||
| 
 | ||||
| enum AddItemResult { | ||||
| pub enum AddItemResult { | ||||
|     NewItem, | ||||
|     AddToStack, | ||||
|     Meseta, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| struct LocalFloor(Vec<FloorItem>); | ||||
| pub struct LocalFloor(Vec<FloorItem>); | ||||
| #[derive(Clone)] | ||||
| struct SharedFloor(Vec<FloorItem>); | ||||
| pub struct SharedFloor(Vec<FloorItem>); | ||||
| #[derive(Clone)] | ||||
| struct RoomFloorItems(Vec<FloorItem>); | ||||
| pub struct RoomFloorItems(Vec<FloorItem>); | ||||
| 
 | ||||
| struct InventoryState { | ||||
| pub struct InventoryState { | ||||
|     character_id: CharacterEntityId, | ||||
|     inventory: Inventory, | ||||
|     pub inventory: Inventory, | ||||
|     meseta: Meseta, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
| impl Deref for InventoryState { | ||||
|     type Target = Inventory; | ||||
|     
 | ||||
|     fn deref(&self) -> &Self::Target { | ||||
|         &self.inventory | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| impl DerefMut for InventoryState { | ||||
|     fn deref_mut(&mut self) -> &mut Self::Target { | ||||
|         &mut self.inventory | ||||
|     } | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| impl InventoryState { | ||||
|     fn add_floor_item(&mut self, item: FloorItem) -> Result<AddItemResult, InventoryError> { | ||||
|     pub fn add_floor_item(&mut self, item: FloorItem) -> Result<AddItemResult, InventoryError> { | ||||
|         match item.item { | ||||
|             FloorItemDetail::Individual(iitem) => { | ||||
|                 if self.inventory.0.len() >= 30 { | ||||
| @ -374,14 +462,14 @@ impl InventoryState { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct FloorState { | ||||
| pub struct FloorState { | ||||
|     character_id: CharacterEntityId, | ||||
|     local: LocalFloor, | ||||
|     shared: SharedFloor, | ||||
| } | ||||
| 
 | ||||
| impl FloorState { | ||||
|     fn take_item(&mut self, item_id: &ClientItemId) -> Option<FloorItem> { | ||||
|     pub fn take_item(&mut self, item_id: &ClientItemId) -> Option<FloorItem> { | ||||
|         let item = self.local.0 | ||||
|             .drain_filter(|item| { | ||||
|                 item.item_id == *item_id | ||||
| @ -398,7 +486,7 @@ impl FloorState { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| struct ItemState { | ||||
| pub struct ItemState { | ||||
|     character_inventory: HashMap<CharacterEntityId, Inventory>, | ||||
|     //character_bank: HashMap<CharacterEntityId, Bank>,
 | ||||
|     character_meseta: HashMap<CharacterEntityId, Meseta>, | ||||
| @ -485,19 +573,31 @@ impl Default for ProxiedItemState { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct ItemStateProxy<'a> { | ||||
| pub struct ItemStateProxy<'a> { | ||||
|     item_state: &'a mut ItemState, | ||||
|     //entity_gateway: &'a mut dyn EntityGateway,
 | ||||
|     transaction: Box<dyn EntityGatewayTransaction>, | ||||
|     //transaction: Box<dyn EntityGatewayTransaction>,
 | ||||
|     //entity_gateway: &'a mut Box<dyn EntityGateway>,
 | ||||
|     //entity_gateway: &'a mut Box<dyn EntityGateway>,
 | ||||
|     proxied_state: ProxiedItemState, | ||||
| 
 | ||||
|     gateway_actions: Vec<GatewayActions>, | ||||
|     //gateway_actions: Vec<GatewayActions>,
 | ||||
| 
 | ||||
|     //_eg: std::marker::PhantomData<EG>,
 | ||||
| } | ||||
| 
 | ||||
| //impl<'a> Drop for ItemStateProxy<'a> {
 | ||||
| //    fn drop(&mut self) {
 | ||||
| impl<'a> ItemStateProxy<'a> { | ||||
|     pub fn commit(self) { | ||||
|         self.item_state.character_inventory.extend(self.proxied_state.character_inventory.clone()); | ||||
|         self.item_state.character_meseta.extend(self.proxied_state.character_meseta.clone()); | ||||
|         self.item_state.character_room.extend(self.proxied_state.character_room.clone()); | ||||
|         self.item_state.character_floor.extend(self.proxied_state.character_floor.clone()); | ||||
|         self.item_state.room_floor.extend(self.proxied_state.room_floor.clone()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| fn get_or_clone<'a,  K, V>(master: &HashMap<K, V>, proxy: &'a RefCell<HashMap<K, RefCell<V>>>, key: K, err: fn(K) -> ItemStateError) -> Result<impl Deref<Target = V> + 'a, ItemStateError> | ||||
| where | ||||
| @ -541,18 +641,18 @@ where | ||||
| impl<'a> ItemStateProxy<'a> { | ||||
|     //fn new(item_state: &'a mut ItemState, entity_gateway: &'a mut EG) -> Self {
 | ||||
|     //fn new(item_state: &'a mut ItemState, entity_gateway: &'a mut dyn EntityGateway) -> Self {
 | ||||
|     fn new(item_state: &'a mut ItemState, transaction: Box<dyn EntityGatewayTransaction>) -> Self { | ||||
|     pub fn new(item_state: &'a mut ItemState/*, transaction: Box<dyn EntityGatewayTransaction>*/) -> Self { | ||||
|         ItemStateProxy { | ||||
|             item_state, | ||||
|             //entity_gateway,
 | ||||
|             transaction, | ||||
|             //transaction,
 | ||||
|             proxied_state: Default::default(), | ||||
|             gateway_actions: Vec::new(), | ||||
|             //gateway_actions: Vec::new(),
 | ||||
|             //_eg: std::marker::PhantomData,
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn inventory(&mut self, character_id: &CharacterEntityId) -> Result<InventoryState, ItemStateError> { | ||||
|     pub fn inventory(&mut self, character_id: &CharacterEntityId) -> Result<InventoryState, ItemStateError> { | ||||
|         Ok(InventoryState { | ||||
|             character_id: *character_id, | ||||
|             inventory: get_or_clone(&self.item_state.character_inventory, &mut self.proxied_state.character_inventory, *character_id, |c| ItemStateError::NoCharacter(c))?, | ||||
| @ -560,12 +660,12 @@ impl<'a> ItemStateProxy<'a> { | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn set_inventory(&mut self, inventory: InventoryState) { | ||||
|     pub fn set_inventory(&mut self, inventory: InventoryState) { | ||||
|         self.proxied_state.character_inventory.insert(inventory.character_id, inventory.inventory); | ||||
|         self.proxied_state.character_meseta.insert(inventory.character_id, inventory.meseta); | ||||
|     } | ||||
| 
 | ||||
|     fn floor(&mut self, character_id: &CharacterEntityId) -> Result<FloorState, ItemStateError> { | ||||
|     pub fn floor(&mut self, character_id: &CharacterEntityId) -> Result<FloorState, ItemStateError> { | ||||
|         let room_id = get_or_clone(&self.item_state.character_room, &mut self.proxied_state.character_room, *character_id, |c| ItemStateError::NoCharacter(c))?; | ||||
|         Ok(FloorState { | ||||
|             character_id: *character_id, | ||||
| @ -574,13 +674,13 @@ impl<'a> ItemStateProxy<'a> { | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn set_floor(&mut self, floor: FloorState) { | ||||
|     pub fn set_floor(&mut self, floor: FloorState) { | ||||
|         let room_id = get_or_clone(&self.item_state.character_room, &mut self.proxied_state.character_room, floor.character_id, |c| ItemStateError::NoCharacter(c)).unwrap(); | ||||
|         self.proxied_state.character_floor.insert(floor.character_id, floor.local); | ||||
|         self.proxied_state.room_floor.insert(room_id, floor.shared); | ||||
|     } | ||||
| 
 | ||||
|     fn new_item_id(&mut self) -> Result<ClientItemId, ItemStateError> { | ||||
|     pub fn new_item_id(&mut self) -> Result<ClientItemId, ItemStateError> { | ||||
|         //let room_id = get_or_clone(&self.item_state.character_room, &mut self.proxied_state.character_room, *character_id, |c| ItemStateError::NoCharacter(c))?;
 | ||||
|         self.item_state.room_item_id_counter += 1; | ||||
|         Ok(ClientItemId(self.item_state.room_item_id_counter)) | ||||
| @ -595,59 +695,6 @@ impl<'a> ItemStateProxy<'a> { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fn take_item_from_floor(character_id: CharacterEntityId, item_id: ClientItemId) | ||||
|                         -> impl for<'a> Fn(ItemStateProxy<'a>, ()) | ||||
|                                            -> Pin<Box<dyn Future<Output=Result<(ItemStateProxy, FloorItem), ItemStateError>> + Send + 'a>> { | ||||
|     move |mut item_state, _| { | ||||
|         Box::pin(async move { | ||||
|             let mut floor = item_state.floor(&character_id)?; | ||||
|             let item = floor.take_item(&item_id).ok_or(ItemStateError::NoFloorItem(item_id))?; | ||||
|             item_state.set_floor(floor); | ||||
|             Ok((item_state, item)) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn add_floor_item_to_inventory(character_id: CharacterEntityId) | ||||
|                                -> impl for<'a> Fn(ItemStateProxy<'a>, FloorItem) | ||||
|                                                   -> Pin<Box<dyn Future<Output=Result<(ItemStateProxy, TriggerCreateItem), ItemStateError>> + Send + 'a>> { | ||||
|     move |mut item_state, floor_item| Box::pin(async move { | ||||
|         let mut inventory = item_state.inventory(&character_id)?; | ||||
|         let add_result = inventory.add_floor_item(floor_item)?; | ||||
|         item_state.set_inventory(inventory); | ||||
|         Ok((item_state, | ||||
|             match add_result { | ||||
|                 AddItemResult::NewItem => TriggerCreateItem::Yes, | ||||
|                 AddItemResult::AddToStack => TriggerCreateItem::No, | ||||
|                 AddItemResult::Meseta => TriggerCreateItem::No, | ||||
|             })) | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[fix_hidden_lifetime_bug] | ||||
| async fn pick_up_item<'a, EG>( | ||||
|     item_state: &'a mut ItemState, | ||||
|     entity_gateway: &'a mut EG, | ||||
|     character_id: &CharacterEntityId, | ||||
|     item_id: &ClientItemId) | ||||
|     -> Result<TriggerCreateItem, ItemStateError> | ||||
| where | ||||
|     'a: 'static, | ||||
|     EG: EntityGateway, | ||||
| { | ||||
|     let result: Result<TriggerCreateItem, ItemStateError> = 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_item_from_floor(*character_id, *item_id)) | ||||
|             .act(add_floor_item_to_inventory(*character_id)) | ||||
|             .commit((item_state_proxy, transaction)) | ||||
|             .await?; | ||||
|         Ok((transaction, result)) | ||||
|     }).await; | ||||
|     Ok(result?) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
| fn record_item_drop(character_id: CharacterEntityId, item_drop: ItemDrop) -> impl Fn(&mut ItemStateProxy, ()) -> Result<(), ItemStateError> { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user