262 lines
7.8 KiB
Rust
262 lines
7.8 KiB
Rust
|
use crate::ship::items::ClientItemId;
|
||
|
use std::collections::{HashMap, BTreeMap, BinaryHeap};
|
||
|
use std::cmp::{Ordering, PartialOrd, PartialEq};
|
||
|
use thiserror::Error;
|
||
|
use futures::future::join_all;
|
||
|
use libpso::character::character;//::InventoryItem;
|
||
|
use crate::entity::gateway::EntityGateway;
|
||
|
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
||
|
use crate::entity::item::{ItemEntityId, ItemEntity, ItemDetail, ItemLocation, BankName};
|
||
|
use crate::entity::item::{Meseta, NewItemEntity};
|
||
|
use crate::entity::item::tool::{Tool, ToolType};
|
||
|
use crate::ship::map::MapArea;
|
||
|
use crate::ship::ship::ItemDropLocation;
|
||
|
use crate::ship::drops::{ItemDrop, ItemDropType};
|
||
|
use crate::ship::location::{AreaClient, RoomId};
|
||
|
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)]
|
||
|
pub struct RoomFloorItems(Vec<FloorItem>);
|
||
|
|
||
|
impl RoomFloorItems {
|
||
|
pub fn new() -> RoomFloorItems {
|
||
|
RoomFloorItems(Vec::new())
|
||
|
}
|
||
|
|
||
|
pub fn add_item(&mut self, item: FloorItem) {
|
||
|
self.0.push(item);
|
||
|
}
|
||
|
|
||
|
pub fn get_item_by_id(&self, item_id: ClientItemId) -> Option<&FloorItem> {
|
||
|
self.0.iter().find(|item| item.item_id() == item_id)
|
||
|
}
|
||
|
|
||
|
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: index,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
pub fn take_item_by_id(&mut self, item_id: ClientItemId) -> Option<FloorItem> {
|
||
|
self.0
|
||
|
.drain_filter(|i| i.item_id() == item_id)
|
||
|
.nth(0)
|
||
|
}
|
||
|
|
||
|
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: 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!(),
|
||
|
}
|
||
|
}
|
||
|
}
|