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
|
let unloaded_items = from_equip
|
||||||
.map(|mut from_equip| {
|
.map(|mut from_equip| {
|
||||||
// Unload any items held inside the previously equipped item
|
// 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
|
// 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
|
// 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
|
// swapped for a smaller one) then we will attempt to push it to the inventory
|
||||||
// inventory slot instead.
|
// with the rest of the unloaded items.
|
||||||
if let Err(returned) = self.insert_at(inv_slot_id, from_equip) {
|
if let Err(returned) = self.insert_at(inv_slot_id, from_equip) {
|
||||||
self.push(returned)
|
items.insert(0, returned);
|
||||||
.expect("Unable to push to inventory, no slots (bug in can_swap()?)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
items
|
items
|
||||||
@ -778,17 +777,7 @@ impl Inventory {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're swapping an equipped item with an empty inventory slot, make
|
if self.slot(inv_slot_id).is_none() {
|
||||||
// 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 {
|
|
||||||
debug!(
|
debug!(
|
||||||
"can_swap = false, tried to swap into non-existent inventory slot: {:?}",
|
"can_swap = false, tried to swap into non-existent inventory slot: {:?}",
|
||||||
inv_slot_id
|
inv_slot_id
|
||||||
|
@ -207,7 +207,7 @@ fn can_swap_equipped_bag_into_empty_inv_slot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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();
|
let mut inv = Inventory::new_empty();
|
||||||
|
|
||||||
inv.replace_loadout_item(EquipSlot::Armor(ArmorSlot::Bag1), Some(get_test_bag(18)));
|
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));
|
let result = inv.can_swap(InvSlotId::new(15, 17), EquipSlot::Armor(ArmorSlot::Bag1));
|
||||||
|
|
||||||
assert!(!result);
|
assert!(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -320,7 +320,7 @@ fn equip_equipping_smaller_bag_from_last_slot_of_big_bag() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 mut inv = Inventory::new_empty();
|
||||||
let bag = get_test_bag(9);
|
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 =
|
let result =
|
||||||
inv.swap_inventory_loadout(InvSlotId::new(15, 0), EquipSlot::Armor(ArmorSlot::Bag1));
|
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]
|
#[test]
|
||||||
@ -458,6 +465,31 @@ fn free_after_swap_inv_item_without_slots_swapped_with_empty_equip_slot() {
|
|||||||
assert_eq!(13, result);
|
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) {
|
fn fill_inv_slots(inv: &mut Inventory, items: u16) {
|
||||||
let msm = &MaterialStatManifest::default();
|
let msm = &MaterialStatManifest::default();
|
||||||
let ability_map = &AbilityMap::default();
|
let ability_map = &AbilityMap::default();
|
||||||
|
Loading…
Reference in New Issue
Block a user