Merge branch 'angel/add-testing' into 'master'

Add slots tests and documentation

See merge request veloren/veloren!1058
This commit is contained in:
Marcel
2020-06-14 21:53:30 +00:00
4 changed files with 220 additions and 5 deletions

View File

@ -0,0 +1,8 @@
Item(
name: "Testing Boots",
description: "Hopefully this test doesn't break!",
kind: Armor(
kind: Foot(Dark),
stats: (20),
),
)

View File

@ -80,6 +80,8 @@ impl ArmorSlot {
// TODO: There are plans to save the selected abilities for each tool even // TODO: There are plans to save the selected abilities for each tool even
// when they are not equipped, when that is implemented this helper function // when they are not equipped, when that is implemented this helper function
// should no longer be needed // should no longer be needed
/// Create an ItemConfig for an item. Apply abilties to item.
fn item_config(item: item::Item) -> comp::ItemConfig { fn item_config(item: item::Item) -> comp::ItemConfig {
let mut abilities = if let item::ItemKind::Tool(tool) = &item.kind { let mut abilities = if let item::ItemKind::Tool(tool) = &item.kind {
tool.get_abilities() tool.get_abilities()
@ -98,6 +100,8 @@ fn item_config(item: item::Item) -> comp::ItemConfig {
} }
} }
/// Replace an equiptment slot with an item. Return the item that was in the
/// slot, if any. Doesn't update the inventory.
fn loadout_replace( fn loadout_replace(
equip_slot: EquipSlot, equip_slot: EquipSlot,
item: Option<item::Item>, item: Option<item::Item>,
@ -126,6 +130,7 @@ fn loadout_replace(
} }
} }
/// Insert an item into a loadout
#[must_use] #[must_use]
fn loadout_insert( fn loadout_insert(
equip_slot: EquipSlot, equip_slot: EquipSlot,
@ -135,10 +140,39 @@ fn loadout_insert(
loadout_replace(equip_slot, Some(item), loadout) loadout_replace(equip_slot, Some(item), loadout)
} }
/// Remove an item from a loadout.
///
/// ```
/// use veloren_common::{
/// comp::{
/// slot::{loadout_remove, EquipSlot},
/// Inventory,
/// },
/// LoadoutBuilder,
/// };
///
/// let mut inv = Inventory {
/// slots: vec![None],
/// amount: 0,
/// };
///
/// let mut loadout = LoadoutBuilder::new()
/// .defaults()
/// .active_item(LoadoutBuilder::default_item_config_from_str(Some(
/// "common.items.weapons.sword.zweihander_sword_0",
/// )))
/// .build();
///
/// let slot = EquipSlot::Mainhand;
///
/// loadout_remove(slot, &mut loadout);
/// assert_eq!(None, loadout.active_item);
/// ```
pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout) -> Option<item::Item> { pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout) -> Option<item::Item> {
loadout_replace(equip_slot, None, loadout) loadout_replace(equip_slot, None, loadout)
} }
/// Swap item in an inventory slot with one in a loadout slot.
fn swap_inventory_loadout( fn swap_inventory_loadout(
inventory_slot: usize, inventory_slot: usize,
equip_slot: EquipSlot, equip_slot: EquipSlot,
@ -167,6 +201,7 @@ fn swap_inventory_loadout(
} }
} }
/// Swap items in loadout.
fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) { fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) {
// Ensure that the slots are not the same // Ensure that the slots are not the same
if slot_a == slot_b { if slot_a == slot_b {
@ -191,8 +226,10 @@ fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) {
} }
} }
// Should this report if a change actually occurred? (might be useful when // TODO: Should this report if a change actually occurred? (might be useful when
// minimizing network use) // minimizing network use)
/// Swap items from two slots, regardless of if either is inventory or loadout.
pub fn swap( pub fn swap(
slot_a: Slot, slot_a: Slot,
slot_b: Slot, slot_b: Slot,
@ -216,6 +253,34 @@ pub fn swap(
} }
} }
/// Equip an item from a slot in inventory. The currently equipped item will go
/// into inventory. If the item is going to mainhand, put mainhand in
/// offhand and place offhand into inventory.
///
/// ```
/// use veloren_common::{
/// assets,
/// comp::{
/// slot::{equip, EquipSlot},
/// Inventory, Item,
/// },
/// LoadoutBuilder,
/// };
///
/// let boots: Option<Item> = Some(assets::load_expect_cloned(
/// "common.items.testing.test_boots",
/// ));
///
/// let mut inv = Inventory {
/// slots: vec![boots.clone()],
/// amount: 1,
/// };
///
/// let mut loadout = LoadoutBuilder::new().defaults().build();
///
/// equip(0, &mut inv, &mut loadout);
/// assert_eq!(boots, loadout.foot);
/// ```
pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) { pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) {
use item::{armor::Armor, ItemKind}; use item::{armor::Armor, ItemKind};
@ -249,9 +314,154 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) {
} }
} }
/// Unequip an item from slot and place into inventory. Will leave the item
/// equipped if inventory has no slots available.
///
/// ```
/// use veloren_common::{
/// comp::{
/// slot::{unequip, EquipSlot},
/// Inventory,
/// },
/// LoadoutBuilder,
/// };
///
/// let mut inv = Inventory {
/// slots: vec![None],
/// amount: 0,
/// };
///
/// let mut loadout = LoadoutBuilder::new()
/// .defaults()
/// .active_item(LoadoutBuilder::default_item_config_from_str(Some(
/// "common.items.weapons.sword.zweihander_sword_0",
/// )))
/// .build();
///
/// let slot = EquipSlot::Mainhand;
///
/// unequip(slot, &mut inv, &mut loadout);
/// assert_eq!(None, loadout.active_item);
/// ```
pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout) { pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout) {
loadout_remove(slot, loadout) // Remove item from loadout loadout_remove(slot, loadout) // Remove item from loadout
.and_then(|i| inventory.push(i)) // Insert into inventory .and_then(|i| inventory.push(i)) // Insert into inventory
.and_then(|i| loadout_insert(slot, i, loadout)) // If that fails put back in loadout .and_then(|i| loadout_insert(slot, i, loadout)) // If that fails put back in loadout
.unwrap_none(); // Never fails .unwrap_none(); // Never fails
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::{assets, LoadoutBuilder};
#[test]
fn test_unequip_items_both_hands() {
let mut inv = Inventory {
slots: vec![None],
amount: 0,
};
let sword = LoadoutBuilder::default_item_config_from_str(Some(
"common.items.weapons.sword.zweihander_sword_0",
));
let mut loadout = LoadoutBuilder::new()
.defaults()
.active_item(sword.clone())
.second_item(sword.clone())
.build();
assert_eq!(sword, loadout.active_item);
unequip(EquipSlot::Mainhand, &mut inv, &mut loadout);
// We have space in the inventory, so this should have unequipped
assert_eq!(None, loadout.active_item);
unequip(EquipSlot::Offhand, &mut inv, &mut loadout);
// There is no more space in the inventory, so this should still be equipped
assert_eq!(sword, loadout.second_item);
// Verify inventory
assert_eq!(inv.slots[0], Some(sword.clone().unwrap().item));
assert_eq!(inv.slots.len(), 1);
}
#[test]
fn test_equip_item() {
let boots: Option<comp::Item> = Some(assets::load_expect_cloned(
"common.items.testing.test_boots",
));
let starting_sandles: Option<comp::Item> = Some(assets::load_expect_cloned(
"common.items.armor.starter.sandals_0",
));
let mut inv = Inventory {
slots: vec![boots.clone()],
amount: 1,
};
let mut loadout = LoadoutBuilder::new().defaults().build();
// We should start with the starting sandles
assert_eq!(starting_sandles, loadout.foot);
equip(0, &mut inv, &mut loadout);
// We should now have the testing boots equiped
assert_eq!(boots, loadout.foot);
// Verify inventory
assert_eq!(inv.slots[0], starting_sandles);
assert_eq!(inv.slots.len(), 1);
}
#[test]
fn test_loadout_replace() {
let boots: Option<comp::Item> = Some(assets::load_expect_cloned(
"common.items.testing.test_boots",
));
let starting_sandles: Option<comp::Item> = Some(assets::load_expect_cloned(
"common.items.armor.starter.sandals_0",
));
let mut loadout = LoadoutBuilder::new().defaults().build();
// We should start with the starting sandles
assert_eq!(starting_sandles, loadout.foot);
// The swap should return the sandles
assert_eq!(
starting_sandles,
loadout_replace(
EquipSlot::Armor(ArmorSlot::Feet),
boots.clone(),
&mut loadout,
)
);
// We should now have the testing boots equiped
assert_eq!(boots, loadout.foot);
}
#[test]
fn test_loadout_remove() {
let sword = LoadoutBuilder::default_item_config_from_str(Some(
"common.items.weapons.sword.zweihander_sword_0",
));
let mut loadout = LoadoutBuilder::new()
.defaults()
.active_item(sword.clone())
.build();
// The swap should return the sword
assert_eq!(
Some(sword.clone().unwrap().item),
loadout_remove(EquipSlot::Mainhand, &mut loadout,)
);
// We should now have nothing equiped
assert_eq!(None, loadout.active_item);
}
}

View File

@ -6,9 +6,6 @@ lazy_static! {
assets::load_expect_cloned("common.items.debug.possess") assets::load_expect_cloned("common.items.debug.possess")
]; ];
} }
/// The `Default` inventory should contain 3 items: cheese, apple, lantern
#[test]
fn create_default_count() { assert_eq!(Inventory::default().count(), 2) }
/// Attempting to push into a full inventory should return the same item. /// Attempting to push into a full inventory should return the same item.
#[test] #[test]

View File

@ -110,7 +110,7 @@ impl LoadoutBuilder {
} }
pub fn second_item(mut self, item: Option<ItemConfig>) -> Self { pub fn second_item(mut self, item: Option<ItemConfig>) -> Self {
self.0.active_item = item; self.0.second_item = item;
self self
} }