veloren_common/comp/inventory/
slot.rs

1use serde::{Deserialize, Serialize};
2use std::{cmp::Ordering, convert::TryFrom};
3
4use crate::comp::inventory::{
5    item::{ItemKind, armor, armor::ArmorKind, tool},
6    loadout::LoadoutSlotId,
7};
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum SlotError {
11    InventoryFull,
12}
13
14#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
15pub enum Slot {
16    Inventory(InvSlotId),
17    Equip(EquipSlot),
18    Overflow(usize),
19}
20
21#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
22pub struct InvSlotId {
23    // The index of the loadout item that provides this inventory slot. 0 represents
24    // built-in inventory slots
25    loadout_idx: u16,
26    // The index of the slot within its container
27    slot_idx: u16,
28}
29
30impl InvSlotId {
31    pub const fn new(loadout_idx: u16, slot_idx: u16) -> Self {
32        Self {
33            loadout_idx,
34            slot_idx,
35        }
36    }
37
38    pub fn idx(&self) -> u32 { (u32::from(self.loadout_idx) << 16) | u32::from(self.slot_idx) }
39
40    pub fn loadout_idx(&self) -> usize { usize::from(self.loadout_idx) }
41
42    pub fn slot_idx(&self) -> usize { usize::from(self.slot_idx) }
43}
44
45impl From<LoadoutSlotId> for InvSlotId {
46    fn from(loadout_slot_id: LoadoutSlotId) -> Self {
47        Self {
48            loadout_idx: u16::try_from(loadout_slot_id.loadout_idx + 1).unwrap(),
49            slot_idx: u16::try_from(loadout_slot_id.slot_idx).unwrap(),
50        }
51    }
52}
53
54impl PartialOrd for InvSlotId {
55    fn partial_cmp(&self, other: &InvSlotId) -> Option<Ordering> { Some(self.cmp(other)) }
56}
57
58impl Ord for InvSlotId {
59    fn cmp(&self, other: &InvSlotId) -> Ordering { self.idx().cmp(&other.idx()) }
60}
61
62pub(super) enum SlotId {
63    Inventory(usize),
64    Loadout(LoadoutSlotId),
65}
66
67impl From<InvSlotId> for SlotId {
68    fn from(inv_slot_id: InvSlotId) -> Self {
69        match inv_slot_id.loadout_idx {
70            0 => SlotId::Inventory(inv_slot_id.slot_idx()),
71            _ => SlotId::Loadout(LoadoutSlotId {
72                loadout_idx: inv_slot_id.loadout_idx() - 1,
73                slot_idx: inv_slot_id.slot_idx(),
74            }),
75        }
76    }
77}
78
79#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
80pub enum EquipSlot {
81    Armor(ArmorSlot),
82    ActiveMainhand,
83    ActiveOffhand,
84    InactiveMainhand,
85    InactiveOffhand,
86    Lantern,
87    Glider,
88}
89
90#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
91pub enum ArmorSlot {
92    Head,
93    Neck,
94    Shoulders,
95    Chest,
96    Hands,
97    Ring1,
98    Ring2,
99    Back,
100    Belt,
101    Legs,
102    Feet,
103    Tabard,
104    Bag1,
105    Bag2,
106    Bag3,
107    Bag4,
108}
109
110impl EquipSlot {
111    pub fn can_hold(self, item_kind: &ItemKind) -> bool {
112        match (self, item_kind) {
113            (Self::Armor(slot), ItemKind::Armor(armor::Armor { kind, .. })) => slot.can_hold(kind),
114            (Self::ActiveMainhand, ItemKind::Tool(_)) => true,
115            (Self::ActiveOffhand, ItemKind::Tool(tool)) => matches!(tool.hands, tool::Hands::One),
116            (Self::InactiveMainhand, ItemKind::Tool(_)) => true,
117            (Self::InactiveOffhand, ItemKind::Tool(tool)) => matches!(tool.hands, tool::Hands::One),
118            (Self::Lantern, ItemKind::Lantern(_)) => true,
119            (Self::Glider, ItemKind::Glider) => true,
120            _ => false,
121        }
122    }
123}
124
125impl ArmorSlot {
126    fn can_hold(self, armor: &ArmorKind) -> bool {
127        matches!(
128            (self, armor),
129            (Self::Head, ArmorKind::Head)
130                | (Self::Neck, ArmorKind::Neck)
131                | (Self::Shoulders, ArmorKind::Shoulder)
132                | (Self::Chest, ArmorKind::Chest)
133                | (Self::Hands, ArmorKind::Hand)
134                | (Self::Ring1, ArmorKind::Ring)
135                | (Self::Ring2, ArmorKind::Ring)
136                | (Self::Back, ArmorKind::Back)
137                | (Self::Back, ArmorKind::Backpack)
138                | (Self::Belt, ArmorKind::Belt)
139                | (Self::Legs, ArmorKind::Pants)
140                | (Self::Feet, ArmorKind::Foot)
141                | (Self::Tabard, ArmorKind::Tabard)
142                | (Self::Bag1, ArmorKind::Bag)
143                | (Self::Bag2, ArmorKind::Bag)
144                | (Self::Bag3, ArmorKind::Bag)
145                | (Self::Bag4, ArmorKind::Bag)
146        )
147    }
148}