use crate::ship::items::ClientItemId; use crate::entity::item::{Meseta, ItemEntityId, ItemDetail}; use std::future::Future; use crate::ship::map::MapArea; use crate::entity::character::CharacterEntityId; use crate::entity::item::mag::Mag; use crate::ship::items::state::ItemStateError; use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail}; use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail}; pub enum FloorType { Local, Shared, } #[derive(Debug, Clone)] pub enum FloorItemDetail { Individual(IndividualItemDetail), Stacked(StackedItemDetail), Meseta(Meseta), } #[derive(Debug, Clone)] pub struct FloorItem { pub item_id: ClientItemId, pub item: FloorItemDetail, pub map_area: MapArea, pub x: f32, pub y: f32, pub z: f32, } impl FloorItem { pub async fn with_entity_id(&self, mut param: T, mut func: F) -> Result where F: FnMut(T, ItemEntityId) -> Fut, Fut: Future>, { match &self.item { FloorItemDetail::Individual(individual_item) => { param = func(param, individual_item.entity_id).await?; }, FloorItemDetail::Stacked(stacked_item) => { for entity_id in &stacked_item.entity_ids { param = func(param, *entity_id).await?; } }, FloorItemDetail::Meseta(_meseta) => {}, } Ok(param) } pub async fn with_mag(&self, mut param: T, mut func: F) -> Result where F: FnMut(T, ItemEntityId, Mag) -> Fut, Fut: Future>, { if let FloorItemDetail::Individual(individual_item) = &self.item { if let ItemDetail::Mag(mag) = &individual_item.item { param = func(param, individual_item.entity_id, mag.clone()).await?; } } Ok(param) } pub fn as_client_bytes(&self) -> [u8; 16] { match &self.item { FloorItemDetail::Individual(individual_floor_item) => { individual_floor_item.item.as_client_bytes() }, FloorItemDetail::Stacked(stacked_floor_item) => { stacked_floor_item.tool.as_stacked_bytes(stacked_floor_item.entity_ids.len()) }, FloorItemDetail::Meseta(meseta_floor_item) => { meseta_floor_item.as_bytes() } } } } #[derive(Debug, Clone, Default)] pub struct LocalFloor(pub Vec); #[derive(Debug, Clone, Default)] pub struct SharedFloor(pub Vec); #[derive(Debug)] pub struct FloorState { pub character_id: CharacterEntityId, pub local: LocalFloor, pub shared: SharedFloor, } impl FloorState { pub fn take_item(&mut self, item_id: &ClientItemId) -> Option { let item = self.local.0 .drain_filter(|item| { item.item_id == *item_id }) .next(); item.or_else(|| { self.shared.0 .drain_filter(|item| { item.item_id == *item_id }) .next() }) } pub fn add_inventory_item(&mut self, inventory_item: InventoryItem, map_area: MapArea, position: (f32, f32, f32)) -> &FloorItem { let floor_item = FloorItem { item_id: inventory_item.item_id, item: match inventory_item.item { InventoryItemDetail::Individual(individual_item) => FloorItemDetail::Individual(individual_item), InventoryItemDetail::Stacked(stacked_item) => FloorItemDetail::Stacked(stacked_item), }, map_area, x: position.0, y: position.1, z: position.2, }; self.shared.0.push(floor_item); &self.shared.0[self.shared.0.len()-1] } pub fn add_shared_item(&mut self, floor_item: FloorItem) -> &FloorItem { self.shared.0.push(floor_item); &self.shared.0[self.shared.0.len()-1] } pub fn add_local_item(&mut self, floor_item: FloorItem) -> &FloorItem { self.local.0.push(floor_item); &self.local.0[self.local.0.len()-1] } }