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
|
// TODO: item specific abilities
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_amount() -> u32 { 1 }
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum ItemKind {
|
pub enum ItemKind {
|
||||||
/// Something wieldable
|
/// Something wieldable
|
||||||
@ -205,11 +207,19 @@ pub enum ItemKind {
|
|||||||
Consumable {
|
Consumable {
|
||||||
kind: Consumable,
|
kind: Consumable,
|
||||||
effect: Effect,
|
effect: Effect,
|
||||||
|
#[serde(skip, default = "default_amount")]
|
||||||
|
amount: u32,
|
||||||
},
|
},
|
||||||
Utility {
|
Utility {
|
||||||
kind: 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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
@ -29,9 +29,105 @@ impl Inventory {
|
|||||||
|
|
||||||
pub fn len(&self) -> usize { self.slots.len() }
|
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
|
/// Adds a new item to the first empty slot of the inventory. Returns the
|
||||||
/// item again if no free slot was found.
|
/// 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()) {
|
match self.slots.iter_mut().find(|slot| slot.is_none()) {
|
||||||
Some(slot) => {
|
Some(slot) => {
|
||||||
*slot = Some(item);
|
*slot = Some(item);
|
||||||
@ -123,6 +219,59 @@ impl Inventory {
|
|||||||
pub fn remove(&mut self, cell: usize) -> Option<Item> {
|
pub fn remove(&mut self, cell: usize) -> Option<Item> {
|
||||||
self.slots.get_mut(cell).and_then(|item| item.take())
|
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 {
|
impl Default for Inventory {
|
||||||
|
@ -88,7 +88,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
|||||||
.ecs()
|
.ecs()
|
||||||
.write_storage::<comp::Inventory>()
|
.write_storage::<comp::Inventory>()
|
||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.and_then(|inv| inv.remove(slot_idx));
|
.and_then(|inv| inv.take(slot_idx));
|
||||||
|
|
||||||
let mut event = comp::InventoryUpdateEvent::Used;
|
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);
|
event = comp::InventoryUpdateEvent::Consumed(*kind);
|
||||||
state.apply_effect(entity, *effect);
|
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 => {
|
comp::item::Utility::Collar => {
|
||||||
let reinsert = if let Some(pos) =
|
let reinsert = if let Some(pos) =
|
||||||
state.read_storage::<comp::Pos>().get(entity)
|
state.read_storage::<comp::Pos>().get(entity)
|
||||||
|
@ -26,9 +26,9 @@ impl From<&Item> for ItemKey {
|
|||||||
match &item.kind {
|
match &item.kind {
|
||||||
ItemKind::Tool(ToolData { kind, .. }) => ItemKey::Tool(kind.clone()),
|
ItemKind::Tool(ToolData { kind, .. }) => ItemKey::Tool(kind.clone()),
|
||||||
ItemKind::Armor { kind, .. } => ItemKey::Armor(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::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