mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'xvar/fix-backpack-swap' into 'master'
Fixed crash when swapping an equipped item with slots for an item with no slots See merge request veloren/veloren!2430
This commit is contained in:
commit
e987f9ae10
@ -710,15 +710,14 @@ impl Inventory {
|
||||
let unloaded_items = from_equip
|
||||
.map(|mut from_equip| {
|
||||
// Unload any items held inside the previously equipped item
|
||||
let items: Vec<Item> = from_equip.drain().collect();
|
||||
let mut items: Vec<Item> = from_equip.drain().collect();
|
||||
|
||||
// Attempt to put the unequipped item in the same slot that the inventory item
|
||||
// was in - if that slot no longer exists (because a large container was
|
||||
// swapped for a smaller one) then push the item to the first free
|
||||
// inventory slot instead.
|
||||
// swapped for a smaller one) then we will attempt to push it to the inventory
|
||||
// with the rest of the unloaded items.
|
||||
if let Err(returned) = self.insert_at(inv_slot_id, from_equip) {
|
||||
self.push(returned)
|
||||
.expect("Unable to push to inventory, no slots (bug in can_swap()?)");
|
||||
items.insert(0, returned);
|
||||
}
|
||||
|
||||
items
|
||||
@ -778,17 +777,7 @@ impl Inventory {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we're swapping an equipped item with an empty inventory slot, make
|
||||
// sure that there will be enough space in the inventory after any
|
||||
// slots granted by the item being unequipped have been removed.
|
||||
if let Some(inv_slot) = self.slot(inv_slot_id) {
|
||||
if inv_slot.is_none() && self.free_slots_minus_equipped_item(equip_slot) == 0 {
|
||||
// No free inventory slots after slots provided by the equipped
|
||||
//item are discounted
|
||||
trace!("can_swap = false, no free slots minus item");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if self.slot(inv_slot_id).is_none() {
|
||||
debug!(
|
||||
"can_swap = false, tried to swap into non-existent inventory slot: {:?}",
|
||||
inv_slot_id
|
||||
|
@ -207,7 +207,7 @@ fn can_swap_equipped_bag_into_empty_inv_slot(
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_swap_equipped_bag_into_only_empty_slot_provided_by_itself_should_return_false() {
|
||||
fn can_swap_equipped_bag_into_only_empty_slot_provided_by_itself_should_return_true() {
|
||||
let mut inv = Inventory::new_empty();
|
||||
|
||||
inv.replace_loadout_item(EquipSlot::Armor(ArmorSlot::Bag1), Some(get_test_bag(18)));
|
||||
@ -216,7 +216,7 @@ fn can_swap_equipped_bag_into_only_empty_slot_provided_by_itself_should_return_f
|
||||
|
||||
let result = inv.can_swap(InvSlotId::new(15, 17), EquipSlot::Armor(ArmorSlot::Bag1));
|
||||
|
||||
assert!(!result);
|
||||
assert!(result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -320,7 +320,7 @@ fn equip_equipping_smaller_bag_from_last_slot_of_big_bag() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unequip_unequipping_bag_into_its_own_slot_with_no_other_free_slots() {
|
||||
fn unequip_unequipping_bag_into_its_own_slot_with_no_other_free_slots_returns_one_item() {
|
||||
let mut inv = Inventory::new_empty();
|
||||
let bag = get_test_bag(9);
|
||||
|
||||
@ -335,7 +335,14 @@ fn unequip_unequipping_bag_into_its_own_slot_with_no_other_free_slots() {
|
||||
|
||||
let result =
|
||||
inv.swap_inventory_loadout(InvSlotId::new(15, 0), EquipSlot::Armor(ArmorSlot::Bag1));
|
||||
assert!(result.is_empty())
|
||||
|
||||
assert_eq!(result.len(), 1);
|
||||
// Because the slot the bag was swapped with no longer exists as it was provided
|
||||
// by itself, the bag is returned to the caller
|
||||
assert_eq!(
|
||||
result[0].item_definition_id(),
|
||||
"common.items.testing.test_bag"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -458,6 +465,31 @@ fn free_after_swap_inv_item_without_slots_swapped_with_empty_equip_slot() {
|
||||
assert_eq!(13, result);
|
||||
}
|
||||
|
||||
// This test is a regression test for a bug that crashed the server when
|
||||
// swapping an equipped item providing slots with an item that does not
|
||||
// provide slots.
|
||||
#[test]
|
||||
fn backpack_crash() {
|
||||
let mut inv = Inventory::new_empty();
|
||||
|
||||
let backpack = Item::new_from_asset_expect("common.items.armor.misc.back.backpack");
|
||||
inv.loadout
|
||||
.swap(EquipSlot::Armor(ArmorSlot::Back), Some(backpack));
|
||||
|
||||
fill_inv_slots(&mut inv, 35);
|
||||
|
||||
let cape = Item::new_from_asset_expect("common.items.armor.misc.back.admin");
|
||||
assert!(inv.push(cape).is_ok());
|
||||
|
||||
let returned_items =
|
||||
inv.swap_inventory_loadout(InvSlotId::new(9, 17), EquipSlot::Armor(ArmorSlot::Back));
|
||||
assert_eq!(18, returned_items.len());
|
||||
assert_eq!(
|
||||
"common.items.armor.misc.back.backpack",
|
||||
returned_items[0].item_definition_id()
|
||||
);
|
||||
}
|
||||
|
||||
fn fill_inv_slots(inv: &mut Inventory, items: u16) {
|
||||
let msm = &MaterialStatManifest::default();
|
||||
let ability_map = &AbilityMap::default();
|
||||
|
Loading…
Reference in New Issue
Block a user