mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add inventory stacking
This commit is contained in:
parent
d863e12235
commit
449ae22730
@ -194,6 +194,8 @@ pub struct ToolData {
|
||||
// TODO: item specific abilities
|
||||
}
|
||||
|
||||
fn default_amount() -> u32 { 1 }
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum ItemKind {
|
||||
/// Something wieldable
|
||||
@ -205,11 +207,19 @@ pub enum ItemKind {
|
||||
Consumable {
|
||||
kind: Consumable,
|
||||
effect: Effect,
|
||||
#[serde(skip, default = "default_amount")]
|
||||
amount: u32,
|
||||
},
|
||||
Utility {
|
||||
kind: Utility,
|
||||
#[serde(skip, default = "default_amount")]
|
||||
amount: u32,
|
||||
},
|
||||
Ingredient {
|
||||
kind: Ingredient,
|
||||
#[serde(skip, default = "default_amount")]
|
||||
amount: u32,
|
||||
},
|
||||
Ingredient(Ingredient),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
|
@ -29,9 +29,105 @@ impl Inventory {
|
||||
|
||||
pub fn len(&self) -> usize { self.slots.len() }
|
||||
|
||||
/// Adds a new item to the first fitting group of the inventory or starts a
|
||||
/// new group. Returns the item again if no space was found.
|
||||
pub fn push(&mut self, item: Item) -> Option<Item> {
|
||||
match item.kind {
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } => self.add_to_first_empty(item),
|
||||
ItemKind::Utility {
|
||||
kind: item_kind,
|
||||
amount: new_amount,
|
||||
} => {
|
||||
for slot in &mut self.slots {
|
||||
if slot
|
||||
.as_ref()
|
||||
.map(|s| s.name() == item.name())
|
||||
.unwrap_or(false)
|
||||
&& slot
|
||||
.as_ref()
|
||||
.map(|s| s.description() == item.description())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if let Some(Item {
|
||||
kind: ItemKind::Utility { kind, amount },
|
||||
..
|
||||
}) = slot
|
||||
{
|
||||
if item_kind == *kind {
|
||||
*amount += new_amount;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// It didn't work
|
||||
self.add_to_first_empty(item)
|
||||
},
|
||||
ItemKind::Consumable {
|
||||
kind: item_kind,
|
||||
amount: new_amount,
|
||||
..
|
||||
} => {
|
||||
for slot in &mut self.slots {
|
||||
if slot
|
||||
.as_ref()
|
||||
.map(|s| s.name() == item.name())
|
||||
.unwrap_or(false)
|
||||
&& slot
|
||||
.as_ref()
|
||||
.map(|s| s.description() == item.description())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if let Some(Item {
|
||||
kind: ItemKind::Consumable { kind, amount, .. },
|
||||
..
|
||||
}) = slot
|
||||
{
|
||||
if item_kind == *kind {
|
||||
*amount += new_amount;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// It didn't work
|
||||
self.add_to_first_empty(item)
|
||||
},
|
||||
ItemKind::Ingredient {
|
||||
kind: item_kind,
|
||||
amount: new_amount,
|
||||
} => {
|
||||
for slot in &mut self.slots {
|
||||
if slot
|
||||
.as_ref()
|
||||
.map(|s| s.name() == item.name())
|
||||
.unwrap_or(false)
|
||||
&& slot
|
||||
.as_ref()
|
||||
.map(|s| s.description() == item.description())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if let Some(Item {
|
||||
kind: ItemKind::Ingredient { kind, amount },
|
||||
..
|
||||
}) = slot
|
||||
{
|
||||
if item_kind == *kind {
|
||||
*amount += new_amount;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// It didn't work
|
||||
self.add_to_first_empty(item)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a new item to the first empty slot of the inventory. Returns the
|
||||
/// item again if no free slot was found.
|
||||
pub fn push(&mut self, item: Item) -> Option<Item> {
|
||||
fn add_to_first_empty(&mut self, item: Item) -> Option<Item> {
|
||||
match self.slots.iter_mut().find(|slot| slot.is_none()) {
|
||||
Some(slot) => {
|
||||
*slot = Some(item);
|
||||
@ -123,6 +219,59 @@ impl Inventory {
|
||||
pub fn remove(&mut self, cell: usize) -> Option<Item> {
|
||||
self.slots.get_mut(cell).and_then(|item| item.take())
|
||||
}
|
||||
|
||||
/// Remove just one item from the slot
|
||||
pub fn take(&mut self, cell: usize) -> Option<Item> {
|
||||
if let Some(Some(item)) = self.slots.get_mut(cell) {
|
||||
let mut return_item = item.clone();
|
||||
match &mut item.kind {
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } => self.remove(cell),
|
||||
ItemKind::Utility { kind, amount } => {
|
||||
if *amount <= 1 {
|
||||
self.remove(cell)
|
||||
} else {
|
||||
*amount -= 1;
|
||||
return_item.kind = ItemKind::Utility {
|
||||
kind: *kind,
|
||||
amount: 1,
|
||||
};
|
||||
Some(return_item)
|
||||
}
|
||||
},
|
||||
ItemKind::Consumable {
|
||||
kind,
|
||||
amount,
|
||||
effect,
|
||||
} => {
|
||||
if *amount <= 1 {
|
||||
self.remove(cell)
|
||||
} else {
|
||||
*amount -= 1;
|
||||
return_item.kind = ItemKind::Consumable {
|
||||
kind: *kind,
|
||||
effect: *effect,
|
||||
amount: 1,
|
||||
};
|
||||
Some(return_item)
|
||||
}
|
||||
},
|
||||
ItemKind::Ingredient { kind, amount } => {
|
||||
if *amount <= 1 {
|
||||
self.remove(cell)
|
||||
} else {
|
||||
*amount -= 1;
|
||||
return_item.kind = ItemKind::Ingredient {
|
||||
kind: *kind,
|
||||
amount: 1,
|
||||
};
|
||||
Some(return_item)
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Inventory {
|
||||
|
@ -88,7 +88,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
.ecs()
|
||||
.write_storage::<comp::Inventory>()
|
||||
.get_mut(entity)
|
||||
.and_then(|inv| inv.remove(slot_idx));
|
||||
.and_then(|inv| inv.take(slot_idx));
|
||||
|
||||
let mut event = comp::InventoryUpdateEvent::Used;
|
||||
|
||||
@ -120,7 +120,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
}
|
||||
},
|
||||
|
||||
comp::ItemKind::Consumable { kind, effect } => {
|
||||
comp::ItemKind::Consumable { kind, effect, .. } => {
|
||||
event = comp::InventoryUpdateEvent::Consumed(*kind);
|
||||
state.apply_effect(entity, *effect);
|
||||
},
|
||||
@ -152,7 +152,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
}
|
||||
},
|
||||
|
||||
comp::ItemKind::Utility { kind } => match kind {
|
||||
comp::ItemKind::Utility { kind, .. } => match kind {
|
||||
comp::item::Utility::Collar => {
|
||||
let reinsert = if let Some(pos) =
|
||||
state.read_storage::<comp::Pos>().get(entity)
|
||||
|
@ -26,9 +26,9 @@ impl From<&Item> for ItemKey {
|
||||
match &item.kind {
|
||||
ItemKind::Tool(ToolData { kind, .. }) => ItemKey::Tool(kind.clone()),
|
||||
ItemKind::Armor { kind, .. } => ItemKey::Armor(kind.clone()),
|
||||
ItemKind::Utility { kind } => ItemKey::Utility(kind.clone()),
|
||||
ItemKind::Utility { kind, .. } => ItemKey::Utility(kind.clone()),
|
||||
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(kind.clone()),
|
||||
ItemKind::Ingredient(kind) => ItemKey::Ingredient(kind.clone()),
|
||||
ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(kind.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user