I keep forgetting to add files to git
This commit is contained in:
		
							parent
							
								
									2010222c9b
								
							
						
					
					
						commit
						eb3d86a20a
					
				
							
								
								
									
										370
									
								
								src/ship/items.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								src/ship/items.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,370 @@ | ||||
| use std::collections::HashMap; | ||||
| use std::hash::{Hash, Hasher}; | ||||
| 
 | ||||
| use libpso::character::character::InventoryItem; | ||||
| use libpso::item; | ||||
| 
 | ||||
| use crate::entity::item::{Item, ItemDetail, ItemLocation, Weapon, Armor, Shield}; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| fn are_items_same_type(itema: &Item, itemb: &Item) -> bool { | ||||
|     match (&itema.item, &itemb.item) { | ||||
|         (ItemDetail::Weapon(a), ItemDetail::Weapon(b)) => a.weapon.weapon == b.weapon.weapon, | ||||
|         (ItemDetail::Armor(a), ItemDetail::Armor(b)) => a.armor.armor == b.armor.armor, | ||||
|         (ItemDetail::Shield(a), ItemDetail::Shield(b)) => a.shield.shield == b.shield.shield, | ||||
|         (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)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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() | ||||
|             } | ||||
|             StackedItem::Stacked(items) => { | ||||
|                 let count = items.len(); | ||||
|                 match &items[0].item { | ||||
|                     ItemDetail::Tool(tool) => { | ||||
|                         item::tool::Tool { | ||||
|                             tool: tool.tool, | ||||
|                             count: count | ||||
|                         }.as_bytes() | ||||
|                     }, | ||||
|                     _ => panic!() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub struct ItemActivator { | ||||
|     id: u32, | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| impl ItemActivator { | ||||
|     pub fn new() -> ItemActivator { | ||||
|         ItemActivator { | ||||
|             id: 0 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn activate_item(&mut self, item: StackedItem) -> ActiveItem { | ||||
|         self.id += 1; | ||||
|         ActiveItem { | ||||
|             id: ActiveItemId(self.id), | ||||
|             item: 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.weapon.value().hash(hasher), | ||||
|             ItemDetail::Armor(a) => a.armor.armor.value().hash(hasher), | ||||
|             ItemDetail::Shield(s) => s.shield.shield.value().hash(hasher), | ||||
|             ItemDetail::Tool(t) => t.tool.value().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)| { | ||||
|                 log::warn!("inv item: {:?}", item); | ||||
|                 if let Some(i) = item { | ||||
|                     let bytes = i.item.as_bytes(); | ||||
|                     log::warn!("inv item bytes:{:?} ", 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, | ||||
|                         _ => 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, | ||||
|                         _ => 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| { | ||||
|         match item.location { | ||||
|             ItemLocation::Inventory{..} => true, | ||||
|             ItemLocation::Bank{..} => false, | ||||
|             ItemLocation::Floor{..} => panic!("oh god what happened"), | ||||
|         } | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| mod test { | ||||
|     use super::*; | ||||
|     use crate::entity::item::{Item, ItemDetail, ItemEntityId, ItemLocation, Weapon, Tool}; | ||||
|     use libpso::item; | ||||
|     
 | ||||
|     #[test] | ||||
|     fn test_stacked_items() { | ||||
|         let item1 = Item { | ||||
|             id: ItemEntityId(1), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 0, | ||||
|             }, | ||||
|             item: ItemDetail::Weapon(Weapon { | ||||
|                 equipped: false, | ||||
|                 weapon: item::weapon::Weapon { | ||||
|                     weapon: item::weapon::WeaponType::Saber, | ||||
|                     grind: 0, | ||||
|                     special: None, | ||||
|                     attrs: [None; 3] | ||||
|                 } | ||||
|             }) | ||||
|         }; | ||||
|         let item2 = Item { | ||||
|             id: ItemEntityId(2), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 1 | ||||
|             }, | ||||
|             item: ItemDetail::Tool(Tool { | ||||
|                 tool: item::tool::ToolType::Monofluid, | ||||
|             }) | ||||
|         }; | ||||
|         let item3 = Item { | ||||
|             id: ItemEntityId(3), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 2, | ||||
|             }, | ||||
|             item: ItemDetail::Weapon(Weapon { | ||||
|                 equipped: false, | ||||
|                 weapon: item::weapon::Weapon { | ||||
|                     weapon: item::weapon::WeaponType::Handgun, | ||||
|                     grind: 12, | ||||
|                     special: None, | ||||
|                     attrs: [None; 3] | ||||
|                 } | ||||
|             }) | ||||
|         }; | ||||
|         let item4  = Item { | ||||
|             id: ItemEntityId(4), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 1 | ||||
|             }, | ||||
|             item: ItemDetail::Tool(Tool { | ||||
|                 tool: item::tool::ToolType::Monofluid, | ||||
|             }) | ||||
|         }; | ||||
|         let item5 = Item { | ||||
|             id: ItemEntityId(5), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 1 | ||||
|             }, | ||||
|             item: ItemDetail::Tool(Tool { | ||||
|                 tool: item::tool::ToolType::Monofluid, | ||||
|             }) | ||||
|         }; | ||||
|         let item6 = Item { | ||||
|             id: ItemEntityId(6), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 3, | ||||
|             }, | ||||
|             item: ItemDetail::Weapon(Weapon { | ||||
|                 equipped: false, | ||||
|                 weapon: item::weapon::Weapon { | ||||
|                     weapon: item::weapon::WeaponType::Handgun, | ||||
|                     grind: 12, | ||||
|                     special: None, | ||||
|                     attrs: [None; 3] | ||||
|                 } | ||||
|             }) | ||||
|         }; | ||||
|         let item7 = Item { | ||||
|             id: ItemEntityId(7), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 4 | ||||
|             }, | ||||
|             item: ItemDetail::Tool(Tool { | ||||
|                 tool: item::tool::ToolType::Monomate, | ||||
|             }) | ||||
|         }; | ||||
|         let item8 = Item { | ||||
|             id: ItemEntityId(8), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 4 | ||||
|             }, | ||||
|             item: ItemDetail::Tool(Tool { | ||||
|                 tool: item::tool::ToolType::Monomate, | ||||
|             }) | ||||
|         }; | ||||
|         let item9 = Item { | ||||
|             id: ItemEntityId(9), | ||||
|             location: ItemLocation::Inventory { | ||||
|                 character_id: 0, | ||||
|                 index: 4 | ||||
|             }, | ||||
|             item: ItemDetail::Tool(Tool { | ||||
|                 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); | ||||
| 
 | ||||
|         assert!(stacked.len() == 5); | ||||
|         assert!(stacked.iter().filter(|k| { | ||||
|             **k == StackedItem::Individual(item6.clone()) | ||||
|         }).count() == 1); | ||||
| 
 | ||||
|         assert!(stacked.iter().filter(|k| { | ||||
|             **k == StackedItem::Individual(item3.clone()) | ||||
|         }).count() == 1); | ||||
| 
 | ||||
|         assert!(stacked.iter().filter(|k| { | ||||
|             **k == StackedItem::Individual(item1.clone()) | ||||
|         }).count() == 1); | ||||
| 
 | ||||
|         assert!(stacked.iter().filter(|k| { | ||||
|             **k == StackedItem::Stacked(vec![item2.clone(), item4.clone(), item5.clone()]) | ||||
|         }).count() == 1); | ||||
| 
 | ||||
|         assert!(stacked.iter().filter(|k| { | ||||
|             **k == StackedItem::Stacked(vec![item7.clone(), item8.clone(), item9.clone()]) | ||||
|         }).count() == 1); | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user