veloren_common/comp/inventory/
slot.rs1use 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 loadout_idx: u16,
26 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}