use thiserror::Error; use std::convert::TryInto; use crate::entity::gateway::{EntityGateway, GatewayError}; use crate::entity::character::CharacterEntity; use crate::entity::item::mag::{MagCell, MagCellError}; use crate::entity::item::tool::ToolType; use crate::entity::item::{ItemDetail, ItemEntityId}; use crate::ship::items::state::{ItemStateProxy, ItemStateError}; use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail}; #[derive(Error, Debug)] pub enum ApplyItemError { #[error("no character")] NoCharacter, #[error("item not equipped")] ItemNotEquipped, #[error("invalid item")] InvalidItem, #[error("gateway error {0}")] GatewayError(#[from] GatewayError), #[error("itemstate error {0}")] ItemStateError(Box), #[error("magcell error {0}")] MagCellError(#[from] MagCellError), } impl From for ApplyItemError { fn from(other: ItemStateError) -> ApplyItemError { ApplyItemError::ItemStateError(Box::new(other)) } } // TODO: make all these functions not-pub pub async fn power_material(entity_gateway: &mut EG, character: &mut CharacterEntity) -> Result<(), ApplyItemError> { character.materials.power += 1; entity_gateway.save_character(character).await?; Ok(()) } pub async fn mind_material(entity_gateway: &mut EG, character: &mut CharacterEntity) -> Result<(), ApplyItemError> { character.materials.mind += 1; entity_gateway.save_character(character).await.unwrap(); Ok(()) } pub async fn evade_material(entity_gateway: &mut EG, character: &mut CharacterEntity) -> Result<(), ApplyItemError> { character.materials.evade += 1; entity_gateway.save_character(character).await.unwrap(); Ok(()) } pub async fn def_material(entity_gateway: &mut EG, character: &mut CharacterEntity) -> Result<(), ApplyItemError> { character.materials.def += 1; entity_gateway.save_character(character).await.unwrap(); Ok(()) } pub async fn luck_material(entity_gateway: &mut EG, character: &mut CharacterEntity) -> Result<(), ApplyItemError> { character.materials.luck += 1; entity_gateway.save_character(character).await.unwrap(); Ok(()) } pub async fn hp_material(entity_gateway: &mut EG, character: &mut CharacterEntity) -> Result<(), ApplyItemError> { character.materials.hp += 1; entity_gateway.save_character(character).await.unwrap(); Ok(()) } pub async fn tp_material(entity_gateway: &mut EG, character: &mut CharacterEntity) -> Result<(), ApplyItemError> { character.materials.tp += 1; entity_gateway.save_character(character).await.unwrap(); Ok(()) } /* async fn mag_cell(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory, mag_cell_type: MagCell) -> Result<(), ApplyItemError> { let mut mag_handle = inventory.get_equipped_mag_handle().ok_or(ApplyItemError::ItemNotEquipped)?; let mag_item = mag_handle.item_mut() .ok_or(ApplyItemError::InvalidItem)?; let actual_mag = mag_item .individual_mut() .ok_or(ApplyItemError::InvalidItem)? .mag_mut() .ok_or(ApplyItemError::InvalidItem)?; actual_mag.apply_mag_cell(mag_cell_type); for mag_entity_id in mag_item.entity_ids() { for cell_entity_id in used_cell.entity_ids() { entity_gateway.use_mag_cell(&mag_entity_id, &cell_entity_id).await.unwrap(); } } Ok(()) } */ async fn mag_cell<'a, EG>(item_state: &mut ItemStateProxy<'a>, entity_gateway: &mut EG, character: &CharacterEntity, cell_entity_id: ItemEntityId, mag_cell_type: MagCell) -> Result<(), ApplyItemError> where EG: EntityGateway + ?Sized, { let mut inventory = item_state.inventory(&character.id)?; let (mag_entity_id, mag) = inventory.equipped_mag_mut() .ok_or(ApplyItemError::ItemNotEquipped)?; mag.apply_mag_cell(mag_cell_type)?; entity_gateway.use_mag_cell(&mag_entity_id, &cell_entity_id).await?; entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?; item_state.set_inventory(inventory); Ok(()) } /* pub async fn cell_of_mag_502(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, inventory, MagCell::CellOfMag502).await } pub async fn cell_of_mag_213(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::CellOfMag213).await } pub async fn parts_of_robochao(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::PartsOfRobochao).await } pub async fn heart_of_opaopa(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfOpaOpa).await } pub async fn heart_of_pian(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfPian).await } pub async fn heart_of_chao(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfChao).await } pub async fn heart_of_angel(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfAngel).await } pub async fn kit_of_hamburger(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfHamburger).await } pub async fn panthers_spirit(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::PanthersSpirit).await } pub async fn kit_of_mark3(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfMark3).await } pub async fn kit_of_master_system(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfMasterSystem).await } pub async fn kit_of_genesis(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfGenesis).await } pub async fn kit_of_sega_saturn(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfSegaSaturn).await } pub async fn kit_of_dreamcast(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfDreamcast).await } pub async fn tablet(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::Tablet).await } pub async fn dragon_scale(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::DragonScale).await } pub async fn heaven_striker_coat(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::HeavenStrikerCoat).await } pub async fn pioneer_parts(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::PioneerParts).await } pub async fn amities_memo(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::AmitiesMemo).await } pub async fn heart_of_morolian(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfMorolian).await } pub async fn rappys_beak(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::RappysBeak).await } pub async fn yahoos_engine(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::YahoosEngine).await } pub async fn d_photon_core(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::DPhotonCore).await } pub async fn liberta_kit(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), ApplyItemError> { mag_cell(entity_gateway, used_cell, inventory, MagCell::LibertaKit).await } */ async fn apply_tool<'a, EG>(item_state: &mut ItemStateProxy<'a>, entity_gateway: &mut EG, character: &mut CharacterEntity, entity_id: ItemEntityId, tool: ToolType) -> Result<(), ApplyItemError> where EG: EntityGateway + ?Sized, { match tool { ToolType::PowerMaterial => power_material(entity_gateway, character).await, ToolType::MindMaterial => mind_material(entity_gateway, character).await, ToolType::EvadeMaterial => evade_material(entity_gateway, character).await, ToolType::DefMaterial => def_material(entity_gateway, character).await, ToolType::LuckMaterial => luck_material(entity_gateway, character).await, ToolType::HpMaterial => hp_material(entity_gateway, character).await, ToolType::TpMaterial => tp_material(entity_gateway, character).await, ToolType::Monomate => Ok(()), ToolType::Dimate => Ok(()), ToolType::Trimate => Ok(()), ToolType::Monofluid => Ok(()), ToolType::Difluid => Ok(()), ToolType::Trifluid => Ok(()), ToolType::HuntersReport => Ok(()), ToolType::CellOfMag502 | ToolType::CellOfMag213 | ToolType::PartsOfRobochao | ToolType::HeartOfOpaOpa | ToolType::HeartOfPian | ToolType::HeartOfChao | ToolType::HeartOfAngel | ToolType::KitOfHamburger | ToolType::PanthersSpirit | ToolType::KitOfMark3 | ToolType::KitOfMasterSystem | ToolType::KitOfGenesis | ToolType::KitOfSegaSaturn | ToolType::KitOfDreamcast | ToolType::Tablet | ToolType::DragonScale | ToolType::HeavenStrikerCoat | ToolType::PioneerParts | ToolType::AmitiesMemo | ToolType::HeartOfMorolian | ToolType::RappysBeak | ToolType::YahoosEngine | ToolType::DPhotonCore | ToolType::LibertaKit => { mag_cell(item_state, entity_gateway, character, entity_id, tool.try_into()?).await } // TODO: rest of these _ => Err(ApplyItemError::InvalidItem) } } pub async fn apply_item<'a, EG: EntityGateway + ?Sized>(item_state: &mut ItemStateProxy<'a>, entity_gateway: &mut EG, character: &mut CharacterEntity, item: InventoryItem) -> Result<(), ApplyItemError> { match item.item { InventoryItemDetail::Individual(individual_item) => { match individual_item.item { ItemDetail::Tool(tool) => apply_tool(item_state, entity_gateway, character, individual_item.entity_id, tool.tool).await, _ => Err(ApplyItemError::InvalidItem) } }, InventoryItemDetail::Stacked(stacked_item) => { for entity_id in stacked_item.entity_ids { apply_tool(item_state, entity_gateway, character, entity_id, stacked_item.tool.tool).await? } Ok(()) }, } }