254 lines
7.4 KiB
Rust
254 lines
7.4 KiB
Rust
use crate::ship::items::ClientItemId;
|
|
use crate::entity::item::{ItemEntityId, ItemDetail};
|
|
use crate::entity::item::Meseta;
|
|
use crate::entity::item::tool::Tool;
|
|
use crate::ship::map::MapArea;
|
|
use crate::ship::items::inventory::{IndividualInventoryItem, StackedInventoryItem, InventoryItemHandle};
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct IndividualFloorItem {
|
|
pub entity_id: ItemEntityId,
|
|
pub item_id: ClientItemId,
|
|
pub item: ItemDetail,
|
|
pub map_area: MapArea,
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub z: f32,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct StackedFloorItem {
|
|
pub entity_ids: Vec<ItemEntityId>,
|
|
pub item_id: ClientItemId,
|
|
pub tool: Tool,
|
|
pub map_area: MapArea,
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub z: f32,
|
|
}
|
|
|
|
impl StackedFloorItem {
|
|
pub fn count(&self) -> usize {
|
|
self.entity_ids.len()
|
|
}
|
|
|
|
pub fn as_client_bytes(&self) -> [u8; 16] {
|
|
self.tool.as_stacked_bytes(self.count())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct MesetaFloorItem {
|
|
pub item_id: ClientItemId,
|
|
pub meseta: Meseta,
|
|
pub map_area: MapArea,
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub z: f32,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum FloorItem {
|
|
Individual(IndividualFloorItem),
|
|
Stacked(StackedFloorItem),
|
|
Meseta(MesetaFloorItem),
|
|
}
|
|
|
|
impl FloorItem {
|
|
pub fn item_id(&self) -> ClientItemId {
|
|
match self {
|
|
FloorItem::Individual(individual_floor_item) => {
|
|
individual_floor_item.item_id
|
|
},
|
|
FloorItem::Stacked(stacked_floor_item) => {
|
|
stacked_floor_item.item_id
|
|
},
|
|
FloorItem::Meseta(meseta_floor_item) => {
|
|
meseta_floor_item.item_id
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn x(&self) -> f32 {
|
|
match self {
|
|
FloorItem::Individual(individual_floor_item) => {
|
|
individual_floor_item.x
|
|
},
|
|
FloorItem::Stacked(stacked_floor_item) => {
|
|
stacked_floor_item.x
|
|
},
|
|
FloorItem::Meseta(meseta_floor_item) => {
|
|
meseta_floor_item.x
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn y(&self) -> f32 {
|
|
match self {
|
|
FloorItem::Individual(individual_floor_item) => {
|
|
individual_floor_item.y
|
|
},
|
|
FloorItem::Stacked(stacked_floor_item) => {
|
|
stacked_floor_item.y
|
|
},
|
|
FloorItem::Meseta(meseta_floor_item) => {
|
|
meseta_floor_item.y
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn z(&self) -> f32 {
|
|
match self {
|
|
FloorItem::Individual(individual_floor_item) => {
|
|
individual_floor_item.z
|
|
},
|
|
FloorItem::Stacked(stacked_floor_item) => {
|
|
stacked_floor_item.z
|
|
},
|
|
FloorItem::Meseta(meseta_floor_item) => {
|
|
meseta_floor_item.z
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn map_area(&self) -> MapArea {
|
|
match self {
|
|
FloorItem::Individual(individual_floor_item) => {
|
|
individual_floor_item.map_area
|
|
},
|
|
FloorItem::Stacked(stacked_floor_item) => {
|
|
stacked_floor_item.map_area
|
|
},
|
|
FloorItem::Meseta(meseta_floor_item) => {
|
|
meseta_floor_item.map_area
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn as_client_bytes(&self) -> [u8; 16] {
|
|
match self {
|
|
FloorItem::Individual(individual_floor_item) => {
|
|
individual_floor_item.item.as_client_bytes()
|
|
},
|
|
FloorItem::Stacked(stacked_floor_item) => {
|
|
stacked_floor_item.as_client_bytes()
|
|
},
|
|
FloorItem::Meseta(meseta_floor_item) => {
|
|
meseta_floor_item.meseta.as_bytes()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub struct FloorItemHandle<'a> {
|
|
floor: &'a mut RoomFloorItems,
|
|
index: usize,
|
|
}
|
|
|
|
impl<'a> FloorItemHandle<'a> {
|
|
pub fn item(&'a self) -> Option<&'a FloorItem> {
|
|
self.floor.0.get(self.index)
|
|
}
|
|
|
|
pub fn remove_from_floor(self) {
|
|
self.floor.0.remove(self.index);
|
|
}
|
|
}
|
|
|
|
// TODO: floors should keep track of their own item_ids
|
|
#[derive(Debug, Default)]
|
|
pub struct RoomFloorItems(Vec<FloorItem>);
|
|
|
|
impl RoomFloorItems {
|
|
pub fn add_item(&mut self, item: FloorItem) {
|
|
self.0.push(item);
|
|
}
|
|
|
|
pub fn remove_item(&mut self, item_id: &ClientItemId) {
|
|
self.0.retain(|item| item.item_id() != *item_id);
|
|
}
|
|
|
|
// TODO: &ClientItemId
|
|
pub fn get_item_by_id(&self, item_id: ClientItemId) -> Option<&FloorItem> {
|
|
self.0.iter().find(|item| item.item_id() == item_id)
|
|
}
|
|
|
|
// TODO: &ClientItemId
|
|
pub fn get_item_handle_by_id(&mut self, item_id: ClientItemId) -> Option<FloorItemHandle> {
|
|
let index = self.0.iter().position(|item| item.item_id() == item_id)?;
|
|
Some(FloorItemHandle {
|
|
floor: self,
|
|
index,
|
|
})
|
|
}
|
|
|
|
pub fn take_item_by_id(&mut self, item_id: ClientItemId) -> Option<FloorItem> {
|
|
self.0
|
|
.drain_filter(|i| i.item_id() == item_id)
|
|
.next()
|
|
}
|
|
|
|
pub fn drop_individual_inventory_item(&mut self, individual_inventory_item: IndividualInventoryItem, item_drop_location: (MapArea, f32, f32, f32)) -> &IndividualFloorItem {
|
|
self.0.push(FloorItem::Individual(IndividualFloorItem {
|
|
entity_id: individual_inventory_item.entity_id,
|
|
item_id: individual_inventory_item.item_id,
|
|
item: individual_inventory_item.item,
|
|
map_area: item_drop_location.0,
|
|
x: item_drop_location.1,
|
|
y: item_drop_location.2,
|
|
z: item_drop_location.3,
|
|
}));
|
|
|
|
match self.0.last().unwrap() {
|
|
FloorItem::Individual(item) => item,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
pub fn drop_stacked_inventory_item(&mut self, stacked_inventory_item: StackedInventoryItem, item_drop_location: (MapArea, f32, f32, f32)) -> &StackedFloorItem {
|
|
self.0.push(FloorItem::Stacked(StackedFloorItem {
|
|
entity_ids: stacked_inventory_item.entity_ids,
|
|
item_id: stacked_inventory_item.item_id,
|
|
tool: stacked_inventory_item.tool,
|
|
map_area: item_drop_location.0,
|
|
x: item_drop_location.1,
|
|
y: item_drop_location.2,
|
|
z: item_drop_location.3,
|
|
}));
|
|
|
|
match self.0.last().unwrap() {
|
|
FloorItem::Stacked(item) => item,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
// TODO: Result
|
|
// TODO: if consumed_item is not a tool items do not get placed back into inventory (should I care?)
|
|
pub fn drop_partial_stacked_inventory_item(&mut self, inventory_item: InventoryItemHandle, amount: usize, new_item_id: ClientItemId, item_drop_location: (MapArea, f32, f32, f32)) -> Option<&StackedFloorItem> {
|
|
let consumed_item = inventory_item.consume(amount).ok()?;
|
|
|
|
if let ItemDetail::Tool(tool) = consumed_item.item() {
|
|
self.0.push(FloorItem::Stacked(StackedFloorItem {
|
|
entity_ids: consumed_item.entity_ids(),
|
|
item_id: new_item_id,
|
|
tool,
|
|
map_area: item_drop_location.0,
|
|
x: item_drop_location.1,
|
|
y: item_drop_location.2,
|
|
z: item_drop_location.3,
|
|
}))
|
|
}
|
|
else {
|
|
return None
|
|
}
|
|
|
|
match self.0.last().unwrap() {
|
|
FloorItem::Stacked(item) => Some(item),
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|