elseware/src/ship/items/manager.rs
2020-09-07 08:02:12 -06:00

686 lines
33 KiB
Rust

use crate::ship::items::ClientItemId;
use std::collections::{HashMap, BTreeMap};
use thiserror::Error;
use crate::entity::gateway::EntityGateway;
use crate::entity::character::{CharacterEntity, CharacterEntityId};
use crate::entity::item::{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::bank::*;
use crate::ship::items::floor::*;
use crate::ship::items::inventory::*;
use crate::ship::items::use_tool;
pub enum TriggerCreateItem {
Yes,
No
}
#[derive(Error, Debug)]
#[error("")]
pub enum ItemManagerError {
EntityGatewayError,
NoSuchItemId(ClientItemId),
NoCharacter(CharacterEntityId),
CouldNotAddToInventory(ClientItemId),
//ItemBelongsToOtherPlayer,
Idunnoman,
CouldNotSplitItem(ClientItemId),
CouldNotDropMeseta,
InvalidBankName(BankName),
NotEnoughTools(Tool, usize, usize), // have, expected
InventoryItemConsumeError(#[from] InventoryItemConsumeError),
BankFull,
WrongItemType(ClientItemId),
}
pub struct ItemManager {
id_counter: u32,
character_inventory: HashMap<CharacterEntityId, CharacterInventory>,
//character_bank: HashMap<CharacterEntityId, BTreeMap<BankName, CharacterBank>>,
character_bank: HashMap<CharacterEntityId, CharacterBank>,
character_floor: HashMap<CharacterEntityId, RoomFloorItems>,
character_room: HashMap<CharacterEntityId, RoomId>,
room_floor: HashMap<RoomId, RoomFloorItems>,
room_item_id_counter: HashMap<RoomId, Box<dyn FnMut() -> ClientItemId + Send>>,
}
impl ItemManager {
pub fn new() -> ItemManager {
ItemManager {
id_counter: 0,
character_inventory: HashMap::new(),
character_bank: HashMap::new(),
character_floor: HashMap::new(),
character_room: HashMap::new(),
room_floor: HashMap::new(),
room_item_id_counter: HashMap::new(),
}
}
pub fn next_global_item_id(&mut self) -> ClientItemId {
self.id_counter += 1;
ClientItemId(self.id_counter)
}
// TODO: Result
pub async fn load_character<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) {
let items = entity_gateway.get_items_by_character(&character).await;
let inventory_items = items.clone().into_iter()
.filter_map(|item| {
match item.location {
ItemLocation::Inventory{slot, equipped, ..} => Some((item.id, item.item, slot, equipped)),
_ => None,
}
})
.fold(BTreeMap::new(), |mut acc, (id, item, slot, equipped)| {
if item.is_stackable() {
if let ItemDetail::Tool(tool) = item {
let inventory_item = acc.entry(slot).or_insert(InventoryItem::Stacked(StackedInventoryItem {
entity_ids: Vec::new(),
item_id: self.next_global_item_id(),
tool: tool,
}));
if let InventoryItem::Stacked(ref mut stacked_inventory_item) = inventory_item {
stacked_inventory_item.entity_ids.push(id);
}
}
}
else {
acc.insert(slot, InventoryItem::Individual(IndividualInventoryItem {
entity_id: id,
item_id: self.next_global_item_id(),
item: item,
equipped: equipped,
}));
}
acc
});
// TODO: not using BankName anymore, clean this up
let mut bank_items = items.into_iter()
.filter_map(|item| {
match item.location {
ItemLocation::Bank{name, ..} => Some((item.id, item.item, name)),
_ => None,
}
})
.fold(BTreeMap::new(), |mut acc, (id, item, name)| {
acc.entry(name).or_insert(Vec::new()).push((id, item));
acc
})
.into_iter()
.map(|(bank_name, bank_items)| {
let stacked_bank_items = bank_items.into_iter()
.fold(Vec::new(), |mut acc, (id, bank_item)| {
if bank_item.is_stackable() {
let existing_item = acc.iter_mut()
.find(|item| {
if let (BankItem::Stacked(stacked_bank_item), &ItemDetail::Tool(ref tool)) = (item, &bank_item) {
stacked_bank_item.tool == *tool
}
else {
false
}
});
match existing_item {
Some(item) => {
if let BankItem::Stacked(ref mut stacked_bank_item) = item {
stacked_bank_item.entity_ids.push(id);
}
}
None => {
if let ItemDetail::Tool(tool) = bank_item {
acc.push(BankItem::Stacked(StackedBankItem {
entity_ids: vec![id],
item_id: self.next_global_item_id(),
tool: tool,
}));
}
},
}
}
else {
acc.push(BankItem::Individual(IndividualBankItem {
entity_id: id,
item_id: self.next_global_item_id(),
item: bank_item,
}));
}
acc
});
(bank_name, CharacterBank::new(stacked_bank_items))
})
.collect::<BTreeMap<_, _>>();
let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect());
self.character_inventory.insert(character.id, inventory);
self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new())));
}
pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) {
let base_inventory_id = ((area_client.local_client.id() as u32) << 21) | 0x10000;
let inventory = self.character_inventory.get_mut(&character.id).unwrap();
inventory.initialize_item_ids(base_inventory_id);
let base_bank_id = ((area_client.local_client.id() as u32) << 21) | 0x20000;
let default_bank = self.character_bank.get_mut(&character.id);//.unwrap().get_mut(&BankName("".to_string()));
match default_bank {
Some(default_bank) => {
default_bank.initialize_item_ids(base_bank_id);
},
None => {},
}
self.character_room.insert(character.id, room_id);
self.character_floor.insert(character.id, RoomFloorItems::new());
self.room_floor.entry(room_id).or_insert(RoomFloorItems::new());
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> {
Ok(self.character_inventory.get(&character.id)
.ok_or(ItemManagerError::NoCharacter(character.id))?)
}
pub fn get_character_bank(&self, character: &CharacterEntity) -> Result<&CharacterBank, ItemManagerError> {
Ok(self.character_bank
.get(&character.id)
.ok_or(ItemManagerError::NoCharacter(character.id))?)
//.get(&BankName("".to_string()))
//.ok_or(ItemManagerError::InvalidBankName(BankName("".to_string())))?)
}
/*pub fn get_character_bank_mut(&mut self, character: &CharacterEntity) -> Result<&CharacterBank, ItemManagerError> {
Ok(self.character_bank
.get_mut(&character.id)
.ok_or(ItemManagerError::NoCharacter(character.id))?
.entry(BankName("".to_string()))
.or_insert(CharacterBank::new(Vec::new())))
//.ok_or(ItemManagerError::InvalidBankName(BankName("".to_string())))?)
}*/
pub fn remove_character_from_room(&mut self, character: &CharacterEntity) {
self.character_inventory.remove(&character.id);
self.character_floor.remove(&character.id);
self.character_room.remove(&character.id)
.as_ref()
.map(|room| {
if self.character_room.iter().find(|(_, r)| *r == room).is_none() {
self.room_floor.remove(room);
}
});
}
pub fn get_floor_item_by_id(&self, character: &CharacterEntity, item_id: ClientItemId) -> Result<&FloorItem, ItemManagerError> {
let local_floor = self.character_floor.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let room = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let shared_floor = self.room_floor.get(room).ok_or(ItemManagerError::NoCharacter(character.id))?;
local_floor.get_item_by_id(item_id)
.or_else(|| {
shared_floor.get_item_by_id(item_id)
})
.ok_or(ItemManagerError::NoSuchItemId(item_id))
}
pub async fn character_picks_up_item<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &mut CharacterEntity, item_id: ClientItemId)
-> Result<TriggerCreateItem, ItemManagerError> {
let local_floor = self.character_floor.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
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 floor_item = local_floor.get_item_handle_by_id(item_id)
.or_else(|| {
shared_floor.get_item_handle_by_id(item_id)
})
.ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let trigger_create_item = match floor_item.item() {
Some(FloorItem::Individual(individual_floor_item)) => {
let new_inventory_item = inventory.pick_up_individual_floor_item(&individual_floor_item);
match new_inventory_item {
Some((new_inventory_item, slot)) => {
entity_gateway.change_item_location(
&new_inventory_item.entity_id,
ItemLocation::Inventory {
character_id: character.id,
slot: slot.0,
equipped: false,
}
).await;
if let Some(_) = new_inventory_item.mag() {
entity_gateway.change_mag_owner(&new_inventory_item.entity_id, character).await;
}
},
None => {
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
},
}
TriggerCreateItem::Yes
},
Some(FloorItem::Stacked(stacked_floor_item)) => {
let new_inventory_item = inventory.pick_up_stacked_floor_item(&stacked_floor_item);
match new_inventory_item {
Some((new_inventory_item, slot)) => {
for entity_id in &new_inventory_item.entity_ids {
entity_gateway.change_item_location(
&entity_id,
ItemLocation::Inventory {
character_id: character.id,
slot: slot.0,
equipped: false,
}
).await;
}
if stacked_floor_item.count() != new_inventory_item.count() {
TriggerCreateItem::No
}
else {
TriggerCreateItem::Yes
}
},
None => {
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
}
}
},
Some(FloorItem::Meseta(meseta_floor_item)) => {
if character.meseta >= 999999 {
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
}
character.meseta = std::cmp::min(character.meseta + meseta_floor_item.meseta.0, 999999);
entity_gateway.save_character(&character).await;
TriggerCreateItem::No
},
None => {
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
}
};
floor_item.remove_from_floor();
Ok(trigger_create_item)
}
pub async fn enemy_drop_item_on_local_floor<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &CharacterEntity, item_drop: ItemDrop) -> Result<&FloorItem, ItemManagerError> {
let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
enum ItemOrMeseta {
Individual(ItemDetail),
Stacked(Tool),
Meseta(Meseta)
}
let item = match item_drop.item {
ItemDropType::Weapon(w) => ItemOrMeseta::Individual(ItemDetail::Weapon(w)),
ItemDropType::Armor(w) => ItemOrMeseta::Individual(ItemDetail::Armor(w)),
ItemDropType::Shield(w) => ItemOrMeseta::Individual(ItemDetail::Shield(w)),
ItemDropType::Unit(w) => ItemOrMeseta::Individual(ItemDetail::Unit(w)),
ItemDropType::TechniqueDisk(w) => ItemOrMeseta::Individual(ItemDetail::TechniqueDisk(w)),
ItemDropType::Mag(w) => ItemOrMeseta::Individual(ItemDetail::Mag(w)),
//ItemDropType::IndividualTool(t) => ItemOrMeseta::Individual(ItemDetail::Tool(t)),
//ItemDropType::StackedTool(t, _) => ItemOrMeseta::Stacked(t),
ItemDropType::Tool(t) if t.tool.is_stackable() => ItemOrMeseta::Stacked(t),
ItemDropType::Tool(t) if !t.tool.is_stackable() => ItemOrMeseta::Individual(ItemDetail::Tool(t)),
ItemDropType::Meseta(m) => ItemOrMeseta::Meseta(Meseta(m)),
_ => unreachable!() // rust isnt smart enough to see that the conditional on tool catches everything
};
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
let floor_item = match item {
ItemOrMeseta::Individual(item_detail) => {
let entity = entity_gateway.create_item(NewItemEntity {
item: item_detail.clone(),
location: ItemLocation::LocalFloor {
character_id: character.id,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
FloorItem::Individual(IndividualFloorItem {
entity_id: entity.id,
item_id: item_id,
item: item_detail,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
})
},
ItemOrMeseta::Stacked(tool) => {
let entity = entity_gateway.create_item(NewItemEntity {
item: ItemDetail::Tool(tool),
location: ItemLocation::LocalFloor {
character_id: character.id,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}
}).await.ok_or(ItemManagerError::EntityGatewayError)?;
FloorItem::Stacked(StackedFloorItem {
entity_ids: vec![entity.id],
item_id: item_id,
tool: tool,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
})
},
ItemOrMeseta::Meseta(meseta) => {
FloorItem::Meseta(MesetaFloorItem {
item_id: item_id,
meseta: meseta,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
})
},
};
self.character_floor.entry(character.id).or_insert(RoomFloorItems::new()).add_item(floor_item);
// TODO: make these real errors
self.character_floor.get(&character.id).ok_or(ItemManagerError::Idunnoman)?.get_item_by_id(item_id).ok_or(ItemManagerError::Idunnoman)
}
pub async fn player_drop_item_on_shared_floor<EG: EntityGateway>(&mut self,
entity_gateway: &mut EG,
character: &CharacterEntity,
//inventory_item: InventoryItem,
item_id: ClientItemId,
item_drop_location: (MapArea, f32, f32, f32))
-> Result<(), 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 dropped_inventory_item = inventory.take_item_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
match dropped_inventory_item {
InventoryItem::Individual(individual_inventory_item) => {
let individual_floor_item = shared_floor.drop_individual_inventory_item(individual_inventory_item, item_drop_location);
entity_gateway.change_item_location(
&individual_floor_item.entity_id,
ItemLocation::SharedFloor {
map_area: item_drop_location.0,
x: item_drop_location.1,
y: item_drop_location.2,
z: item_drop_location.3,
}
).await;
},
InventoryItem::Stacked(stacked_inventory_item) => {
let stacked_floor_item = shared_floor.drop_stacked_inventory_item(stacked_inventory_item, item_drop_location);
for entity_id in &stacked_floor_item.entity_ids {
entity_gateway.change_item_location(
entity_id,
ItemLocation::SharedFloor {
map_area: item_drop_location.0,
x: item_drop_location.1,
y: item_drop_location.2,
z: item_drop_location.3,
}
).await;
}
},
}
Ok(())
}
pub async 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).await;
let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
let floor_item = FloorItem::Meseta(MesetaFloorItem {
item_id: item_id,
meseta: Meseta(amount),
map_area: drop_location.map_area,
x: drop_location.x,
y: 0.0,
z: drop_location.z,
});
shared_floor.add_item(floor_item.clone());
Ok(floor_item)
}
pub async fn player_drops_partial_stack_on_shared_floor<EG: EntityGateway>(&mut self,
entity_gateway: &mut EG,
character: &CharacterEntity,
//inventory_item: InventoryItem,
item_id: ClientItemId,
drop_location: ItemDropLocation,
amount: usize)
-> Result<&StackedFloorItem, 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.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let new_item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?();
let stacked_floor_item = shared_floor.drop_partial_stacked_inventory_item(item_to_split, amount, new_item_id, (drop_location.map_area, drop_location.x, 0.0, drop_location.z))
.ok_or(ItemManagerError::CouldNotSplitItem(item_id))?;
for entity_id in &stacked_floor_item.entity_ids {
entity_gateway.change_item_location(
entity_id,
ItemLocation::SharedFloor {
map_area: drop_location.map_area,
x: drop_location.x,
y: 0.0,
z: drop_location.z,
}
).await;
}
Ok(stacked_floor_item)
}
pub async fn player_consumes_tool<EG: EntityGateway>(&mut self,
entity_gateway: &mut EG,
character: &CharacterEntity,
item_id: ClientItemId,
amount: usize)
-> Result<ConsumedItem, ItemManagerError> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let used_item = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let consumed_item = used_item.consume(amount)?;
for entity_id in consumed_item.entity_ids() {
entity_gateway.change_item_location(&entity_id,
ItemLocation::Consumed).await;
}
Ok(consumed_item)
}
pub async fn player_deposits_item<EG: EntityGateway>(&mut self,
entity_gateway: &mut EG,
character: &CharacterEntity,
item_id: ClientItemId,
amount: usize)
-> Result<(), ItemManagerError> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let bank = self.character_bank
.get_mut(&character.id)
.ok_or(ItemManagerError::NoCharacter(character.id))?;
let item_to_deposit = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let bank_item = bank.deposit_item(item_to_deposit, amount).ok_or(ItemManagerError::Idunnoman)?;
match bank_item {
BankItem::Individual(individual_bank_item) => {
entity_gateway.change_item_location(&individual_bank_item.entity_id,
ItemLocation::Bank {
character_id: character.id,
name: BankName("".to_string())
}).await;
},
BankItem::Stacked(stacked_bank_item) => {
for entity_id in &stacked_bank_item.entity_ids {
entity_gateway.change_item_location(entity_id,
ItemLocation::Bank {
character_id: character.id,
name: BankName("".to_string())
}).await;
}
}
}
Ok(())
}
pub async fn player_withdraws_item<EG: EntityGateway>(&mut self,
entity_gateway: &mut EG,
character: &CharacterEntity,
item_id: ClientItemId,
amount: usize)
-> Result<&InventoryItem, ItemManagerError> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let bank = self.character_bank
.get_mut(&character.id)
.ok_or(ItemManagerError::NoCharacter(character.id))?;
let item_to_withdraw = bank.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
let inventory_item = inventory.withdraw_item(item_to_withdraw, amount).ok_or(ItemManagerError::Idunnoman)?;
match inventory_item {
(InventoryItem::Individual(individual_inventory_item), slot) => {
entity_gateway.change_item_location(&individual_inventory_item.entity_id,
ItemLocation::Inventory {
character_id: character.id,
slot: slot,
equipped: false,
}).await;
},
(InventoryItem::Stacked(stacked_inventory_item), slot) => {
for entity_id in &stacked_inventory_item.entity_ids {
entity_gateway.change_item_location(entity_id,
ItemLocation::Inventory {
character_id: character.id,
slot: slot,
equipped: false,
}).await;
}
}
}
Ok(inventory_item.0)
}
pub async fn player_feeds_mag_item<EG: EntityGateway>(&mut self,
entity_gateway: &mut EG,
character: &CharacterEntity,
mag_id: ClientItemId,
tool_id: ClientItemId)
-> Result<(), ItemManagerError> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let consumed_tool = {
let item_to_feed = inventory.get_item_handle_by_id(tool_id).ok_or(ItemManagerError::NoSuchItemId(tool_id))?;
item_to_feed.consume(1)?
};
let mut mag_handle = inventory.get_item_handle_by_id(mag_id).ok_or(ItemManagerError::NoSuchItemId(mag_id))?;
let individual_item = mag_handle.item_mut()
.ok_or(ItemManagerError::NoSuchItemId(mag_id))?
.individual()
.ok_or(ItemManagerError::WrongItemType(mag_id))?;
let mag = individual_item
.mag_mut()
.ok_or(ItemManagerError::WrongItemType(mag_id))?;
let consumed_tool_type = match &consumed_tool {
ConsumedItem::Stacked(stacked_consumed_item) => stacked_consumed_item.tool.tool,
_ => return Err(ItemManagerError::WrongItemType(tool_id))
};
mag.feed(consumed_tool_type);
for entity_id in consumed_tool.entity_ids() {
entity_gateway.feed_mag(&individual_item.entity_id, &entity_id).await;
entity_gateway.change_item_location(&entity_id, ItemLocation::FedToMag {
mag: individual_item.entity_id,
}).await;
}
Ok(())
}
pub async fn use_item<EG: EntityGateway>(&mut self,
used_item: ConsumedItem,
entity_gateway: &mut EG,
character: &mut CharacterEntity) -> Result<(), ItemManagerError> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
match &used_item.item() {
ItemDetail::Weapon(_w) => {
// something like when items are used to combine/transform them?
//_ => {}
},
ItemDetail::Tool(t) => {
match t.tool {
ToolType::PowerMaterial => {
use_tool::power_material(entity_gateway, character).await;
},
ToolType::MindMaterial => {
use_tool::mind_material(entity_gateway, character).await;
},
ToolType::EvadeMaterial => {
use_tool::evade_material(entity_gateway, character).await;
},
ToolType::DefMaterial => {
use_tool::def_material(entity_gateway, character).await;
},
ToolType::LuckMaterial => {
use_tool::luck_material(entity_gateway, character).await;
},
ToolType::HpMaterial => {
use_tool::hp_material(entity_gateway, character).await;
},
ToolType::TpMaterial => {
use_tool::tp_material(entity_gateway, character).await;
},
ToolType::CellOfMag502 => {
use_tool::cell_of_mag_502(entity_gateway, &used_item, inventory).await;
},
_ => {}
}
}
_ => {}
}
Ok(())
}
}