redo active item stuff
This commit is contained in:
		
							parent
							
								
									a0e82c644c
								
							
						
					
					
						commit
						359120de07
					
				| @ -36,18 +36,17 @@ pub enum ItemLocation { | ||||
| */ | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| pub struct Tool { | ||||
|     pub tool: tool::ToolType, | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||||
| pub enum ItemType { | ||||
|     Weapon(weapon::WeaponType), | ||||
|     Armor(armor::ArmorType), | ||||
|     Shield(shield::ShieldType), | ||||
|     Unit(unit::UnitType), | ||||
|     Tool(tool::ToolType), | ||||
|     TechniqueDisk(tech::Technique) | ||||
| } | ||||
| 
 | ||||
| impl Tool { | ||||
|     pub fn as_bytes(&self) -> [u8; 16] { | ||||
|         let mut result = [0; 16]; | ||||
|         result[0..3].copy_from_slice(&self.tool.value()); | ||||
|         result | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| pub enum ItemDetail { | ||||
| @ -55,7 +54,7 @@ pub enum ItemDetail { | ||||
|     Armor(armor::Armor), | ||||
|     Shield(shield::Shield), | ||||
|     Unit(unit::Unit), | ||||
|     Tool(Tool), | ||||
|     Tool(tool::Tool), | ||||
|     TechniqueDisk(tech::TechniqueDisk) | ||||
| } | ||||
| 
 | ||||
| @ -67,14 +66,14 @@ impl ItemDetail { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn as_bytes(&self) -> [u8; 16] { | ||||
|     pub fn item_type(&self) -> ItemType { | ||||
|         match self { | ||||
|             ItemDetail::Weapon(weapon) => weapon.as_bytes(), | ||||
|             ItemDetail::Armor(armor) => armor.as_bytes(), | ||||
|             ItemDetail::Shield(shield) => shield.as_bytes(), | ||||
|             ItemDetail::Unit(unit) => unit.as_bytes(), | ||||
|             ItemDetail::Tool(tool) => tool.as_bytes(), | ||||
|             ItemDetail::TechniqueDisk(tech) => tech.as_bytes(), | ||||
|             ItemDetail::Weapon(w) => ItemType::Weapon(w.weapon), | ||||
|             ItemDetail::Armor(a) => ItemType::Armor(a.armor), | ||||
|             ItemDetail::Shield(s) => ItemType::Shield(s.shield), | ||||
|             ItemDetail::Unit(u) => ItemType::Unit(u.unit), | ||||
|             ItemDetail::Tool(t) => ItemType::Tool(t.tool), | ||||
|             ItemDetail::TechniqueDisk(d) => ItemType::TechniqueDisk(d.tech), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use serde::{Serialize, Deserialize}; | ||||
| 
 | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||||
| #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||||
| pub enum Technique { | ||||
|     Foie, | ||||
|     Gifoie, | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use serde::{Serialize, Deserialize}; | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] | ||||
| #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] | ||||
| pub enum ToolType { | ||||
|     Monomate, | ||||
|     Dimate, | ||||
| @ -394,25 +394,21 @@ impl ToolType { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone, PartialEq)] | ||||
| pub struct StackedTool { | ||||
| #[derive(Clone, Debug, PartialEq)] | ||||
| pub struct Tool { | ||||
|     pub tool: ToolType, | ||||
|     pub count: usize, | ||||
| } | ||||
| 
 | ||||
| impl StackedTool { | ||||
|     pub fn new(tool: ToolType, count: usize) -> StackedTool { | ||||
|         StackedTool { | ||||
|             tool: tool, | ||||
|             count: count, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn as_bytes(&self) -> [u8; 16] { | ||||
| impl Tool { | ||||
|     pub fn as_individual_bytes(&self) -> [u8; 16] { | ||||
|         let mut result = [0; 16]; | ||||
|         result[0..3].copy_from_slice(&self.tool.value()); | ||||
|         result[5] = self.count as u8; | ||||
| 
 | ||||
|         result | ||||
|     } | ||||
|     pub fn as_stacked_bytes(&self, len: usize) -> [u8; 16] { | ||||
|         let mut result = [0; 16]; | ||||
|         result[0..3].copy_from_slice(&self.tool.value()); | ||||
|         result[5] = len as u8; | ||||
|         result | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -61,7 +61,7 @@ pub enum WeaponSpecial { | ||||
|     Demons, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] | ||||
| pub enum WeaponType { | ||||
|     Saber, | ||||
|     Brand, | ||||
|  | ||||
| @ -17,10 +17,11 @@ use libpso::{utf8_to_array, utf8_to_utf16_array}; | ||||
| 
 | ||||
| use crate::entity::gateway::EntityGateway; | ||||
| use crate::entity::account::{UserAccount, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; | ||||
| use crate::entity::item::{ItemDetail, ItemLocation, Tool}; | ||||
| use crate::entity::item::{ItemDetail, ItemLocation}; | ||||
| use crate::entity::item::weapon::Weapon; | ||||
| use crate::entity::item::armor::Armor; | ||||
| use crate::entity::item::tech::Technique; | ||||
| use crate::entity::item::tool::Tool; | ||||
| use crate::entity::character::{Character, CharacterClass, TechLevel}; | ||||
| 
 | ||||
| use crate::login::login::get_login_status; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use libpso::character::character; | ||||
| use crate::common::leveltable::CharacterStats; | ||||
| use crate::entity::character::Character; | ||||
| use crate::ship::items::Inventory; | ||||
| use crate::ship::items::ActiveInventory; | ||||
| 
 | ||||
| // TODO: exp
 | ||||
| pub struct CharacterBytesBuilder<'a> { | ||||
| @ -79,7 +79,7 @@ pub struct FullCharacterBytesBuilder<'a> { | ||||
|     character: Option<&'a Character>, | ||||
|     stats: Option<&'a CharacterStats>, | ||||
|     level: Option<u32>, | ||||
|     inventory: Option<&'a Inventory>, | ||||
|     inventory: Option<&'a ActiveInventory>, | ||||
|     key_config: Option<&'a [u8; 0x16C]>, | ||||
|     joystick_config: Option<&'a [u8; 0x38]>, | ||||
| } | ||||
| @ -118,7 +118,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn inventory(self, inventory: &'a Inventory) -> FullCharacterBytesBuilder<'a> { | ||||
|     pub fn inventory(self, inventory: &'a ActiveInventory) -> FullCharacterBytesBuilder<'a> { | ||||
|         FullCharacterBytesBuilder { | ||||
|             inventory: Some(inventory), | ||||
|             ..self | ||||
|  | ||||
| @ -4,8 +4,8 @@ use serde::{Serialize, Deserialize}; | ||||
| use rand::{Rng, SeedableRng}; | ||||
| use rand::distributions::{WeightedIndex, Distribution}; | ||||
| 
 | ||||
| use crate::entity::item::{ItemDetail, Tool as ToolDetail}; | ||||
| use crate::entity::item::tool::{StackedTool, ToolType}; | ||||
| use crate::entity::item::ItemDetail; | ||||
| use crate::entity::item::tool::{Tool, ToolType}; | ||||
| use crate::ship::room::{Difficulty, Episode}; | ||||
| use crate::ship::map::MapVariantType; | ||||
| use crate::entity::character::SectionID; | ||||
| @ -132,7 +132,7 @@ impl ToolTable { | ||||
|     pub fn get_drop<R: Rng>(&self, map_area: &MapVariantType, rng: &mut R) -> Option<ItemDetail> { | ||||
|         let tool_type = self.tool_type(map_area, rng); | ||||
| 
 | ||||
|         Some(ItemDetail::Tool(ToolDetail { | ||||
|         Some(ItemDetail::Tool(Tool { | ||||
|             tool: tool_type | ||||
|         })) | ||||
|     } | ||||
|  | ||||
| @ -1,244 +1,186 @@ | ||||
| use std::collections::HashMap; | ||||
| use std::hash::{Hash, Hasher}; | ||||
| 
 | ||||
| use libpso::character::character::InventoryItem; | ||||
| 
 | ||||
| use crate::entity::item::{Item, ItemDetail, ItemLocation}; | ||||
| use crate::entity::gateway::EntityGateway; | ||||
| use crate::entity::character::Character; | ||||
| use crate::entity::item::{Item, ItemId, ItemDetail, ItemLocation}; | ||||
| use crate::entity::item::weapon::Weapon; | ||||
| use crate::entity::item::armor::Armor; | ||||
| use crate::entity::item::shield::Shield; | ||||
| use crate::entity::item::unit::Unit; | ||||
| use crate::entity::item::tool::StackedTool; | ||||
| use crate::entity::item::tool::Tool; | ||||
| 
 | ||||
| 
 | ||||
| fn are_items_same_type(itema: &Item, itemb: &Item) -> bool { | ||||
|     match (&itema.item, &itemb.item) { | ||||
|         (ItemDetail::Weapon(a), ItemDetail::Weapon(b)) => a.weapon == b.weapon, | ||||
|         (ItemDetail::Armor(a), ItemDetail::Armor(b)) => a.armor == b.armor, | ||||
|         (ItemDetail::Shield(a), ItemDetail::Shield(b)) => a.shield == b.shield, | ||||
|         (ItemDetail::Unit(a), ItemDetail::Unit(b)) => a.unit == b.unit, | ||||
|         (ItemDetail::Tool(a), ItemDetail::Tool(b)) => a.tool == b.tool, | ||||
|         _ => false | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct ActiveItemId(u32); | ||||
| 
 | ||||
| // TODO: Stacked(count, itemtype Vec<ItemId>)?
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum StackedItem { | ||||
|     Individual(Item), | ||||
|     Stacked(Vec<Item>), | ||||
| } | ||||
| 
 | ||||
| impl StackedItem { | ||||
|     fn is_same_item_type(&self, item: &Item) -> bool { | ||||
|         match self { | ||||
|             StackedItem::Individual(i) => are_items_same_type(i, item), | ||||
|             StackedItem::Stacked(i) => i.iter().all(|k| are_items_same_type(k, item)) | ||||
|         } | ||||
|     } | ||||
| #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] | ||||
| pub struct ActiveItemId(u32); | ||||
| 
 | ||||
|     fn index(&self) -> usize { | ||||
|         match self { | ||||
|             StackedItem::Individual(Item {location: ItemLocation::Inventory {index, ..}, ..}) => *index, | ||||
|             StackedItem::Stacked(items) => { | ||||
|                 match items[0].location { | ||||
|                     ItemLocation::Inventory {index, ..} => index, | ||||
|                     _ => panic!() | ||||
|                 } | ||||
|             } | ||||
|             _ => panic!() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn as_bytes(&self) -> [u8; 16] { | ||||
|         match self { | ||||
|             StackedItem::Individual(item) => { | ||||
|                 item.item.as_bytes() | ||||
| #[derive(Debug)] | ||||
| pub struct ActiveItem { | ||||
|     id: ActiveItemId, | ||||
|     item: StackedItem, | ||||
| } | ||||
| 
 | ||||
| impl ActiveItem { | ||||
|     pub fn as_client_bytes(&self) -> [u8; 16] { | ||||
|         match &self.item { | ||||
|             StackedItem::Individual(i) => { | ||||
|                 match &i.item { | ||||
|                     ItemDetail::Weapon(w) => w.as_bytes(), | ||||
|                     ItemDetail::Armor(a) => a.as_bytes(), | ||||
|                     ItemDetail::Shield(s) => s.as_bytes(), | ||||
|                     ItemDetail::Unit(u) => u.as_bytes(), | ||||
|                     ItemDetail::Tool(t) => t.as_individual_bytes(), | ||||
|                     ItemDetail::TechniqueDisk(d) => d.as_bytes(), | ||||
|                 } | ||||
|             StackedItem::Stacked(items) => { | ||||
|                 let count = items.len(); | ||||
|                 match &items[0].item { | ||||
|                     ItemDetail::Tool(tool) => { | ||||
|                         StackedTool { | ||||
|                             tool: tool.tool, | ||||
|                             count: count | ||||
|                         }.as_bytes() | ||||
|             }, | ||||
|             StackedItem::Stacked(i) => { | ||||
|                 let len = i.len(); | ||||
|                 match &i[0].item { | ||||
|                     ItemDetail::Tool(t) => t.as_stacked_bytes(len), | ||||
|                     _ => panic!(), | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct ActiveInventory(Vec<ActiveItem>); | ||||
| 
 | ||||
| impl ActiveInventory { | ||||
|     pub fn as_client_inventory_items(&self) -> [InventoryItem; 30] { | ||||
|         self.0.iter() | ||||
|             .enumerate() | ||||
|             .fold([InventoryItem::default(); 30], |mut inventory, (index, item)| { | ||||
|                 let bytes = item.as_client_bytes(); | ||||
|                 inventory[index].data1.copy_from_slice(&bytes[0..12]); | ||||
|                 inventory[index].item_id = item.id.0; | ||||
| 
 | ||||
|                 // does this do anything?
 | ||||
|                 inventory[index].equipped = match item.item { | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Weapon(Weapon {equipped: true, ..}), ..}) => 1, | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Armor(Armor {equipped: true, ..}), ..}) => 1, | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Shield(Shield {equipped: true, ..}), ..}) => 1, | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Unit(Unit{equipped: true, ..}), ..}) => 1, | ||||
|                     //StackedItem::Individual(Item {item: ItemDetail::Mag(Mag{equipped: true, ..}), ..}) => 1,
 | ||||
|                     _ => 0, | ||||
|                 }; | ||||
|                 // because this actually equips the item
 | ||||
|                 inventory[index].flags |= match item.item { | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Weapon(Weapon {equipped: true, ..}), ..}) => 8, | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Armor(Armor {equipped: true, ..}), ..}) => 8, | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Shield(Shield {equipped: true, ..}), ..}) => 8, | ||||
|                     StackedItem::Individual(Item {item: ItemDetail::Unit(Unit {equipped: true, ..}), ..}) => 8, | ||||
|                     //StackedItem::Individual(Item {item: ItemDetail::Mag(Mag{equipped: true, ..}), ..}) => 8,
 | ||||
|                     _ => 0, | ||||
|                 }; | ||||
|                 inventory | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn count(&self) -> usize { | ||||
|         self.0.len() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn inventory_item_index(item: &StackedItem) -> usize { | ||||
|     match item { | ||||
|         StackedItem::Individual(i) => { | ||||
|             match i.location { | ||||
|                 ItemLocation::Inventory{index: index, ..} => index, | ||||
|                 _ => panic!() | ||||
|             } | ||||
|         }, | ||||
|         StackedItem::Stacked(i) => { | ||||
|             match i[0].location { | ||||
|                 ItemLocation::Inventory{index: index, ..} => index, | ||||
|                 _ => panic!() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     } | ||||
|     
 | ||||
| } | ||||
| 
 | ||||
| fn stack_items(items: Vec<Item>) -> Vec<StackedItem> { | ||||
|     let mut stacks = HashMap::new(); | ||||
| 
 | ||||
| pub struct ItemActivator { | ||||
|     for item in items { | ||||
|         stacks.entry(item.item.item_type()).or_insert(Vec::new()).push(item); | ||||
|     } | ||||
| 
 | ||||
|     stacks.into_iter() | ||||
|         .map(|(itype, items)| { | ||||
|             match items[0].item.is_stackable() { | ||||
|                 true => { | ||||
|                     vec![StackedItem::Stacked(items)] | ||||
|                 }, | ||||
|                 false => { | ||||
|                     items.into_iter().map(|i| { | ||||
|                         StackedItem::Individual(i) | ||||
|                     }).collect() | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         .flatten() | ||||
|         .collect() | ||||
| } | ||||
| 
 | ||||
| struct ActiveBank([Option<ActiveItemId>; 200]); | ||||
| 
 | ||||
| pub struct ActiveItemDatabase { | ||||
|     id: u32, | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| impl ItemActivator { | ||||
|     pub fn new() -> ItemActivator { | ||||
|         ItemActivator { | ||||
|             id: 0 | ||||
| 
 | ||||
| 
 | ||||
| impl ActiveItemDatabase { | ||||
|     pub fn new() -> ActiveItemDatabase { | ||||
|         ActiveItemDatabase { | ||||
|             id: 0, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn activate_item(&mut self, item: StackedItem) -> ActiveItem { | ||||
|     fn activate_item(&mut self, item: StackedItem) -> ActiveItem { | ||||
|         self.id += 1; | ||||
|         ActiveItem { | ||||
|             id: ActiveItemId(self.id), | ||||
|             item: item, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     // deactivate item
 | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct ActiveItem { | ||||
|     pub id: ActiveItemId, | ||||
|     pub item: StackedItem, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| struct StackedItemKey(Item); | ||||
| 
 | ||||
| impl Hash for StackedItemKey { | ||||
|     fn hash<H: Hasher>(&self, hasher: &mut H) { | ||||
|         match &self.0.item { | ||||
|             ItemDetail::Weapon(w) => w.weapon.value().hash(hasher), | ||||
|             ItemDetail::Armor(a) => a.armor.value().hash(hasher), | ||||
|             ItemDetail::Shield(s) => s.shield.value().hash(hasher), | ||||
|             ItemDetail::Unit(u) => u.unit.value().hash(hasher), | ||||
|             ItemDetail::Tool(t) => t.tool.value().hash(hasher), | ||||
|             ItemDetail::TechniqueDisk(t) => t.tech.hash(hasher), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl std::cmp::PartialEq for StackedItemKey { | ||||
|     fn eq(&self, other: &StackedItemKey) -> bool { | ||||
|         are_items_same_type(&self.0, &other.0) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Eq for StackedItemKey {} | ||||
| 
 | ||||
| pub fn stack_items(items: Vec<Item>) -> Vec<StackedItem> { | ||||
|     items.into_iter() | ||||
|         .fold(HashMap::new(), |mut stacked: HashMap<StackedItemKey, Vec<Item>>, item| { | ||||
|             stacked.entry(StackedItemKey(item.clone())) | ||||
|                 .and_modify(|stack| stack.push(item.clone())) | ||||
|                 .or_insert_with(|| { | ||||
|                     vec![item] | ||||
|                 }); | ||||
| 
 | ||||
|             stacked | ||||
|         }) | ||||
|         .into_iter() | ||||
|         .map(|(_k, v)| { | ||||
|             v | ||||
|         }) | ||||
|         .fold(Vec::new(), |mut stacked, item| { | ||||
|             if item[0].item.is_stackable() { | ||||
|                 stacked.push(StackedItem::Stacked(item)) | ||||
|             } | ||||
|             else { | ||||
|                 stacked.append(&mut item.into_iter().map(|k| StackedItem::Individual(k)).collect()) | ||||
|             } | ||||
|             
 | ||||
|             stacked | ||||
|         }) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub enum InventoryAddError { | ||||
|     InventoryFull, | ||||
|     FullToolStack, | ||||
| } | ||||
| 
 | ||||
| pub enum InventoryRemoveError { | ||||
|     NoItemInInventory, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub struct Inventory([Option<ActiveItem>; 30]); | ||||
| 
 | ||||
| impl Inventory { | ||||
|     pub fn new(items: Vec<ActiveItem>) -> Inventory { | ||||
|         items.into_iter() | ||||
|             .fold(Inventory([None; 30]), |mut inventory, item| { | ||||
|                 let index = item.item.index(); | ||||
|                 inventory.0[index] = Some(item); | ||||
|                 inventory | ||||
|                     
 | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn count(&self) -> usize { | ||||
|         self.0.iter() | ||||
|             .filter(|k| k.is_some()) | ||||
|             .count() | ||||
|     } | ||||
| 
 | ||||
|     pub fn as_client_inventory_items(&self) -> [InventoryItem; 30] { | ||||
|         self.0.iter() | ||||
|             .enumerate() | ||||
|             .fold([InventoryItem::default(); 30], |mut inventory, (index, item)| { | ||||
|                 if let Some(i) = item { | ||||
|                     let bytes = i.item.as_bytes(); | ||||
|                     inventory[index].data1.copy_from_slice(&bytes[0..12]); | ||||
|                     inventory[index].item_id = i.id.0; | ||||
| 
 | ||||
|                     // does this do anything?
 | ||||
|                     inventory[index].equipped = match i.item { | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Weapon(Weapon {equipped: true, ..}), ..}) => 1, | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Armor(Armor {equipped: true, ..}), ..}) => 1, | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Shield(Shield {equipped: true, ..}), ..}) => 1, | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Unit(Unit{equipped: true, ..}), ..}) => 1, | ||||
|                         _ => 0, | ||||
|                     }; | ||||
|                     // because this actually equips the item
 | ||||
|                     inventory[index].flags |= match i.item { | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Weapon(Weapon {equipped: true, ..}), ..}) => 8, | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Armor(Armor {equipped: true, ..}), ..}) => 8, | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Shield(Shield {equipped: true, ..}), ..}) => 8, | ||||
|                         StackedItem::Individual(Item {item: ItemDetail::Unit(Unit {equipped: true, ..}), ..}) => 8, | ||||
|                         _ => 0, | ||||
|                     }; | ||||
|                 } | ||||
|                 inventory | ||||
|             }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub struct Bank {} | ||||
| 
 | ||||
| 
 | ||||
| pub fn split_items_into_inventory_and_bank(items: Vec<Item>) -> (Vec<Item>, Vec<Item>) { | ||||
|     items.into_iter().partition(|item| { | ||||
|     pub fn get_character_inventory<EG: EntityGateway>(&mut self, entity_gateway: &mut EG, character: &Character) -> ActiveInventory { | ||||
|         let items = entity_gateway.get_items_by_character(&character); | ||||
|         let inventory_items = items.into_iter() | ||||
|             .filter(|item| { | ||||
|                 match item.location { | ||||
|                     ItemLocation::Inventory{..} => true, | ||||
|             ItemLocation::Bank{..} => false, | ||||
|             ItemLocation::Floor{..} => panic!("oh god what happened"), | ||||
|                     _ => false, | ||||
|                 } | ||||
|             }).collect(); | ||||
|         let mut stacked = stack_items(inventory_items); | ||||
|         stacked.sort_by(|a, b| { | ||||
|             inventory_item_index(a).partial_cmp(&inventory_item_index(b)).unwrap() | ||||
|         }); | ||||
|         let activated = stacked.into_iter().map(|i| self.activate_item(i)); | ||||
|         ActiveInventory(activated.take(30).collect()) | ||||
|     } | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use super::*; | ||||
|     use crate::entity::item; | ||||
|     use crate::entity::item::{Item, ItemDetail, ItemEntityId, ItemLocation, Tool}; | ||||
|     
 | ||||
|     use crate::entity::item::{Item, ItemDetail, ItemEntityId, ItemLocation}; | ||||
|     #[test] | ||||
|     fn test_stacked_items() { | ||||
|     fn test_stack_items() { | ||||
|         let item1 = Item { | ||||
|             id: ItemEntityId(1), | ||||
|             location: ItemLocation::Inventory { | ||||
| @ -344,7 +286,6 @@ mod test { | ||||
|                 tool: item::tool::ToolType::Monomate, | ||||
|             }) | ||||
|         }; | ||||
| 
 | ||||
|         let item_vec = vec![item1.clone(), item2.clone(), item3.clone(), item4.clone(), item5.clone(), item6.clone(), item7.clone(), item8.clone(), item9.clone()]; | ||||
| 
 | ||||
|         let stacked = stack_items(item_vec); | ||||
|  | ||||
| @ -122,14 +122,14 @@ struct ClientState { | ||||
|     settings: UserSettings, | ||||
|     character: Character, | ||||
|     session: Session, | ||||
|     inventory: items::Inventory, | ||||
|     guildcard: GuildCard, | ||||
|     inventory: items::ActiveInventory, | ||||
|     //bank: Bank,
 | ||||
|     block: u32, | ||||
| } | ||||
| 
 | ||||
| impl ClientState { | ||||
|     fn new(user: UserAccount, settings: UserSettings, character: Character, inventory: items::Inventory, /*bank: Bank,*/ session: Session, guildcard: GuildCard) -> ClientState { | ||||
|     fn new(user: UserAccount, settings: UserSettings, character: Character, inventory: items::ActiveInventory, /*bank: Bank,*/ session: Session, guildcard: GuildCard) -> ClientState { | ||||
|         ClientState { | ||||
|             user: user, | ||||
|             settings: settings, | ||||
| @ -143,6 +143,7 @@ impl ClientState { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub struct ShipServerState<EG: EntityGateway> { | ||||
|     entity_gateway: EG, | ||||
|     clients: HashMap<ClientId, ClientState>, | ||||
| @ -150,7 +151,7 @@ pub struct ShipServerState<EG: EntityGateway> { | ||||
|     level_table: CharacterLevelTable, | ||||
|     name: String, | ||||
|     rooms: [Option<room::RoomState>; MAX_ROOMS], | ||||
|     item_activator: items::ItemActivator, | ||||
|     item_database: items::ActiveItemDatabase, | ||||
| } | ||||
| 
 | ||||
| impl<EG: EntityGateway> ShipServerState<EG> { | ||||
| @ -162,7 +163,7 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|             level_table: CharacterLevelTable::new(), | ||||
|             name: "Sona-Nyl".into(), | ||||
|             rooms: [None; MAX_ROOMS], | ||||
|             item_activator: items::ItemActivator::new(), | ||||
|             item_database: items::ActiveItemDatabase::new(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -180,14 +181,9 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|                     .clone(); | ||||
|                 let settings = self.entity_gateway.get_user_settings_by_user(&user) | ||||
|                     .ok_or(ShipError::ClientNotFound(id))?; | ||||
| 
 | ||||
|                 let items = self.entity_gateway.get_items_by_character(&character); | ||||
|                 let (inventory, bank) = items::split_items_into_inventory_and_bank(items); | ||||
|                 let stacked_items = items::stack_items(inventory); | ||||
|                 let activated_items = stacked_items.into_iter().map(|item| self.item_activator.activate_item(item)).collect(); | ||||
|                 let inventory = items::Inventory::new(activated_items); | ||||
|                 let guildcard = self.entity_gateway.get_guild_card_by_character(&character) | ||||
|                         .ok_or(ShipError::ClientNotFound(id))?; | ||||
|                 let inventory = self.item_database.get_character_inventory(&mut self.entity_gateway, &character); | ||||
| 
 | ||||
|                 self.clients.insert(id, ClientState::new(user, settings, character, inventory, pkt.session, guildcard)); | ||||
|                 vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&self.name, 3))] | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user