|
|
@ -7,6 +7,7 @@ use crate::entity::item::{ItemEntityId, ItemEntity, ItemDetail, ItemLocation}; |
|
|
|
use crate::entity::item::{Meseta, NewItemEntity};
|
|
|
|
use crate::entity::item::tool::Tool;
|
|
|
|
use crate::ship::map::MapArea;
|
|
|
|
use crate::ship::ship::ItemDropLocation;
|
|
|
|
use crate::ship::drops::{ItemDrop, ItemDropType};
|
|
|
|
use crate::ship::location::{AreaClient, RoomId};
|
|
|
|
|
|
|
@ -145,6 +146,8 @@ pub enum ItemManagerError { |
|
|
|
CouldNotAddToInventory(FloorItem),
|
|
|
|
//ItemBelongsToOtherPlayer,
|
|
|
|
Idunnoman,
|
|
|
|
CouldNotSplitItem(InventoryItem),
|
|
|
|
CouldNotDropMeseta,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ItemManager {
|
|
|
@ -152,11 +155,10 @@ pub struct ItemManager { |
|
|
|
|
|
|
|
character_inventory: HashMap<CharacterEntityId, Vec<InventoryItem>>,
|
|
|
|
character_floor: HashMap<CharacterEntityId, Vec<FloorItem>>,
|
|
|
|
character_item_id_counter: HashMap<CharacterEntityId, u32>,
|
|
|
|
|
|
|
|
character_room: HashMap<CharacterEntityId, RoomId>,
|
|
|
|
room_floor: HashMap<RoomId, Vec<FloorItem>>,
|
|
|
|
room_item_id_counter: HashMap<RoomId, u32>,
|
|
|
|
room_item_id_counter: HashMap<RoomId, Box<dyn FnMut() -> ClientItemId + Send>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ItemManager {
|
|
|
@ -165,7 +167,6 @@ impl ItemManager { |
|
|
|
id_counter: 0,
|
|
|
|
character_inventory: HashMap::new(),
|
|
|
|
character_floor: HashMap::new(),
|
|
|
|
character_item_id_counter: HashMap::new(),
|
|
|
|
character_room: HashMap::new(),
|
|
|
|
room_floor: HashMap::new(),
|
|
|
|
room_item_id_counter: HashMap::new(),
|
|
|
@ -177,12 +178,6 @@ impl ItemManager { |
|
|
|
ClientItemId(self.id_counter)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_drop_item_id(&mut self, room_id: RoomId) -> ClientItemId {
|
|
|
|
let next_id = self.room_item_id_counter.entry(room_id).or_insert(0xF0000000);
|
|
|
|
*next_id += 1;
|
|
|
|
ClientItemId(*next_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Result
|
|
|
|
pub fn load_character<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) {
|
|
|
|
let items = entity_gateway.get_items_by_character(&character);
|
|
|
@ -234,7 +229,12 @@ impl ItemManager { |
|
|
|
self.character_room.insert(character.id, room_id);
|
|
|
|
self.character_floor.insert(character.id, Vec::new());
|
|
|
|
self.room_floor.entry(room_id).or_insert(Vec::new());
|
|
|
|
self.character_item_id_counter.insert(character.id, base_id + inventory.len() as u32);
|
|
|
|
|
|
|
|
let mut inc = 0xF0000000;
|
|
|
|
self.room_item_id_counter.entry(room_id).or_insert(Box::new(move || {
|
|
|
|
inc += 1;
|
|
|
|
ClientItemId(inc)
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_character_inventory(&self, character: &CharacterEntity) -> Result<CharacterInventory, ItemManagerError> {
|
|
|
@ -406,8 +406,8 @@ impl ItemManager { |
|
|
|
FloorItemType::Meseta(m) => ActiveItemEntityId::Meseta(m.clone()),
|
|
|
|
};
|
|
|
|
|
|
|
|
let room_id = *self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
|
|
|
let item_id = self.next_drop_item_id(room_id);
|
|
|
|
let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
|
|
|
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
|
|
|
|
|
|
|
let floor_item = FloorItem {
|
|
|
|
entity_id: entity_id,
|
|
|
@ -488,4 +488,88 @@ impl ItemManager { |
|
|
|
shared_floor.push(room_floor_item);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn player_drops_meseta_on_shared_floor<EG: EntityGateway>(&mut self,
|
|
|
|
entity_gateway: &mut EG,
|
|
|
|
character: &mut CharacterEntity,
|
|
|
|
drop_location: ItemDropLocation,
|
|
|
|
amount: u32)
|
|
|
|
-> Result<FloorItem, ItemManagerError> {
|
|
|
|
let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
|
|
|
let shared_floor = self.room_floor.get_mut(&room_id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
|
|
|
if character.meseta <= amount {
|
|
|
|
return Err(ItemManagerError::CouldNotDropMeseta)
|
|
|
|
}
|
|
|
|
character.meseta -= amount;
|
|
|
|
entity_gateway.save_character(&character);
|
|
|
|
|
|
|
|
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
|
|
|
let floor_item = FloorItem {
|
|
|
|
entity_id: ActiveItemEntityId::Meseta(Meseta(amount)),
|
|
|
|
item_id: item_id,
|
|
|
|
item: FloorItemType::Meseta(Meseta(amount)),
|
|
|
|
map_area: drop_location.map_area,
|
|
|
|
x: drop_location.x,
|
|
|
|
y: 0.0,
|
|
|
|
z: drop_location.z,
|
|
|
|
};
|
|
|
|
|
|
|
|
shared_floor.push(floor_item.clone());
|
|
|
|
Ok(floor_item)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn player_drops_partial_stack_on_shared_floor<EG: EntityGateway>(&mut self,
|
|
|
|
entity_gateway: &mut EG,
|
|
|
|
character: &CharacterEntity,
|
|
|
|
inventory_item: InventoryItem,
|
|
|
|
drop_location: ItemDropLocation,
|
|
|
|
amount: usize)
|
|
|
|
-> Result<FloorItem, ItemManagerError> {
|
|
|
|
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
|
|
|
let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
|
|
|
let shared_floor = self.room_floor.get_mut(&room_id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
|
|
|
|
|
|
|
let item_to_split = inventory.iter_mut()
|
|
|
|
.find(|i| i.item_id == inventory_item.item_id)
|
|
|
|
.ok_or(ItemManagerError::NoSuchItemId(inventory_item.item_id))?;
|
|
|
|
|
|
|
|
if let (ActiveItemEntityId::Stacked(ref mut entity_ids), HeldItemType::Stacked(tool, ref mut tool_amount)) = (&mut item_to_split.entity_id, &mut item_to_split.item) {
|
|
|
|
if entity_ids.len() <= amount || *tool_amount <= amount {
|
|
|
|
return Err(ItemManagerError::CouldNotSplitItem(inventory_item));
|
|
|
|
}
|
|
|
|
|
|
|
|
*tool_amount -= amount;
|
|
|
|
|
|
|
|
let dropped_entities = entity_ids.drain(..amount).collect::<Vec<_>>();
|
|
|
|
|
|
|
|
dropped_entities.iter().for_each(|entity_id| {
|
|
|
|
entity_gateway.save_item(&ItemEntity {
|
|
|
|
id: *entity_id,
|
|
|
|
item: ItemDetail::Tool(*tool),
|
|
|
|
location: ItemLocation::SharedFloor {
|
|
|
|
map_area: drop_location.map_area,
|
|
|
|
x: drop_location.x,
|
|
|
|
y: 0.0,
|
|
|
|
z: drop_location.z,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
|
|
|
|
let floor_item = FloorItem {
|
|
|
|
entity_id: ActiveItemEntityId::Stacked(dropped_entities),
|
|
|
|
item_id: item_id,
|
|
|
|
item: FloorItemType::Stacked(*tool, amount),
|
|
|
|
map_area: drop_location.map_area,
|
|
|
|
x: drop_location.x,
|
|
|
|
y: 0.0,
|
|
|
|
z: drop_location.z,
|
|
|
|
};
|
|
|
|
shared_floor.push(floor_item.clone());
|
|
|
|
Ok(floor_item)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Err(ItemManagerError::CouldNotSplitItem(inventory_item))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|