v0.12.0.2
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
@@ -9,17 +10,209 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Inventory : IServerSerializable, IClientSerializable
|
||||
{
|
||||
public const int MaxStackSize = 32;
|
||||
|
||||
public class ItemSlot
|
||||
{
|
||||
private readonly List<Item> items = new List<Item>(MaxStackSize);
|
||||
|
||||
public bool HideIfEmpty;
|
||||
|
||||
public IEnumerable<Item> Items
|
||||
{
|
||||
get { return items; }
|
||||
}
|
||||
|
||||
public int ItemCount
|
||||
{
|
||||
get { return items.Count; }
|
||||
}
|
||||
|
||||
public bool CanBePut(Item item)
|
||||
{
|
||||
if (item == null) { return false; }
|
||||
if (items.Count > 0)
|
||||
{
|
||||
if (item.IsFullCondition)
|
||||
{
|
||||
if (items.Any(it => !it.IsFullCondition)) { return false; }
|
||||
}
|
||||
else if (MathUtils.NearlyEqual(item.Condition, 0.0f))
|
||||
{
|
||||
if (items.Any(it => !MathUtils.NearlyEqual(it.Condition, 0.0f))) { return false; }
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (items[0].Prefab.Identifier != item.Prefab.Identifier ||
|
||||
items.Count + 1 > item.Prefab.MaxStackSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanBePut(ItemPrefab itemPrefab)
|
||||
{
|
||||
if (itemPrefab == null) { return false; }
|
||||
if (items.Count > 0)
|
||||
{
|
||||
if (items.Any(it => !it.IsFullCondition)) { return false; }
|
||||
if (items[0].Prefab.Identifier != itemPrefab.Identifier ||
|
||||
items.Count + 1 > itemPrefab.MaxStackSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <param name="maxStackSize">Defaults to <see cref="ItemPrefab.MaxStackSize"/> if null</param>
|
||||
public int HowManyCanBePut(ItemPrefab itemPrefab, int? maxStackSize = null)
|
||||
{
|
||||
if (itemPrefab == null) { return 0; }
|
||||
maxStackSize ??= itemPrefab.MaxStackSize;
|
||||
if (items.Count > 0)
|
||||
{
|
||||
if (items.Any(it => !it.IsFullCondition)) { return 0; }
|
||||
if (items[0].Prefab.Identifier != itemPrefab.Identifier) { return 0; }
|
||||
return maxStackSize.Value - items.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
return maxStackSize.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(Item item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new InvalidOperationException("Tried to add a null item to an inventory slot.");
|
||||
}
|
||||
if (items.Count > 0)
|
||||
{
|
||||
if (items[0].Prefab.Identifier != item.Prefab.Identifier)
|
||||
{
|
||||
throw new InvalidOperationException("Tried to stack different types of items.");
|
||||
}
|
||||
else if (items.Count + 1 > item.Prefab.MaxStackSize)
|
||||
{
|
||||
throw new InvalidOperationException("Tried to add an item to a full inventory slot (stack already full).");
|
||||
}
|
||||
}
|
||||
if (items.Contains(item)) { return; }
|
||||
items.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes one item from the slot
|
||||
/// </summary>
|
||||
public Item RemoveItem()
|
||||
{
|
||||
if (items.Count == 0) { return null; }
|
||||
|
||||
var item = items[0];
|
||||
items.RemoveAt(0);
|
||||
return item;
|
||||
}
|
||||
|
||||
public void RemoveItem(Item item)
|
||||
{
|
||||
items.Remove(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all items from the slot
|
||||
/// </summary>
|
||||
public void RemoveAllItems()
|
||||
{
|
||||
items.Clear();
|
||||
}
|
||||
|
||||
public bool Any()
|
||||
{
|
||||
return items.Count > 0;
|
||||
}
|
||||
|
||||
public bool Empty()
|
||||
{
|
||||
return items.Count == 0;
|
||||
}
|
||||
|
||||
public Item First()
|
||||
{
|
||||
return items[0];
|
||||
}
|
||||
|
||||
public Item FirstOrDefault()
|
||||
{
|
||||
return items.FirstOrDefault();
|
||||
}
|
||||
|
||||
public Item LastOrDefault()
|
||||
{
|
||||
return items.LastOrDefault();
|
||||
}
|
||||
|
||||
public bool Contains(Item item)
|
||||
{
|
||||
return items.Contains(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public readonly Entity Owner;
|
||||
|
||||
protected readonly int capacity;
|
||||
|
||||
public Item[] Items;
|
||||
protected bool[] hideEmptySlot;
|
||||
protected readonly ItemSlot[] slots;
|
||||
|
||||
public bool Locked;
|
||||
|
||||
protected float syncItemsDelay;
|
||||
|
||||
/// <summary>
|
||||
/// All items contained in the inventory. Stacked items are returned as individual instances. DO NOT modify the contents of the inventory while enumerating this list.
|
||||
/// </summary>
|
||||
public IEnumerable<Item> AllItems
|
||||
{
|
||||
get
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
foreach (var item in slots[i].Items)
|
||||
{
|
||||
bool duplicateFound = false;
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
if (slots[j].Items.Contains(item))
|
||||
{
|
||||
duplicateFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!duplicateFound) { yield return item; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Item> allItemsList = new List<Item>();
|
||||
/// <summary>
|
||||
/// All items contained in the inventory. Allows modifying the contents of the inventory while being enumerated.
|
||||
/// </summary>
|
||||
public IEnumerable<Item> AllItemsMod
|
||||
{
|
||||
get
|
||||
{
|
||||
allItemsList.Clear();
|
||||
allItemsList.AddRange(AllItems);
|
||||
return allItemsList;
|
||||
}
|
||||
}
|
||||
|
||||
public int Capacity
|
||||
{
|
||||
get { return capacity; }
|
||||
@@ -31,8 +224,11 @@ namespace Barotrauma
|
||||
|
||||
this.Owner = owner;
|
||||
|
||||
Items = new Item[capacity];
|
||||
hideEmptySlot = new bool[capacity];
|
||||
slots = new ItemSlot[capacity];
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
slots[i] = new ItemSlot();
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
this.slotsPerRow = slotsPerRow;
|
||||
@@ -54,71 +250,117 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Item FindItemRecursive(Item item, Predicate<Item> condition)
|
||||
/// <summary>
|
||||
/// Is the item contained in this inventory. Does not recursively check items inside items.
|
||||
/// </summary>
|
||||
public bool Contains(Item item)
|
||||
{
|
||||
if (condition.Invoke(item))
|
||||
return slots.Any(i => i.Contains(item));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the first item in the inventory, or null if the inventory is empty.
|
||||
/// </summary>
|
||||
public Item FirstOrDefault()
|
||||
{
|
||||
foreach (var itemSlot in slots)
|
||||
{
|
||||
return item;
|
||||
var item = itemSlot.FirstOrDefault();
|
||||
if (item != null) { return item; }
|
||||
}
|
||||
|
||||
var containers = item.GetComponents<ItemContainer>();
|
||||
|
||||
if (containers != null)
|
||||
{
|
||||
foreach (var container in containers)
|
||||
{
|
||||
foreach (var inventoryItem in container.Inventory.Items)
|
||||
{
|
||||
var findItem = FindItemRecursive(inventoryItem, condition);
|
||||
if (findItem != null)
|
||||
{
|
||||
return findItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the last item in the inventory, or null if the inventory is empty.
|
||||
/// </summary>
|
||||
public Item LastOrDefault()
|
||||
{
|
||||
for (int i = slots.Length - 1; i >= 0; i--)
|
||||
{
|
||||
var item = slots[i].LastOrDefault();
|
||||
if (item != null) { return item; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the item stored in the specified inventory slot. If the slot contains a stack of items, returns the first item in the stack.
|
||||
/// </summary>
|
||||
public Item GetItemAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= slots.Length) { return null; }
|
||||
return slots[index].FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all the item stored in the specified inventory slot. Can return more than one item if the slot contains a stack of items.
|
||||
/// </summary>
|
||||
public IEnumerable<Item> GetItemsAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= slots.Length) { return Enumerable.Empty<Item>(); }
|
||||
return slots[index].Items;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the index of the first slot the item is contained in.
|
||||
/// </summary>
|
||||
public int FindIndex(Item item)
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (Items[i] == item) return i;
|
||||
if (slots[i].Contains(item)) { return i; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Returns true if the item owns any of the parent inventories
|
||||
|
||||
/// <summary>
|
||||
/// Find the indices of all the slots the item is contained in (two-hand items for example can be in multiple slots). Note that this method instantiates a new list.
|
||||
/// </summary>
|
||||
public List<int> FindIndices(Item item)
|
||||
{
|
||||
List<int> indices = new List<int>();
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (slots[i].Contains(item)) { indices.Add(i); }
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the item owns any of the parent inventories.
|
||||
/// </summary>
|
||||
public virtual bool ItemOwnsSelf(Item item)
|
||||
{
|
||||
if (Owner == null) return false;
|
||||
if (!(Owner is Item)) return false;
|
||||
if (Owner == null) { return false; }
|
||||
if (!(Owner is Item)) { return false; }
|
||||
Item ownerItem = Owner as Item;
|
||||
if (ownerItem == item) return true;
|
||||
if (ownerItem.ParentInventory == null) return false;
|
||||
if (ownerItem == item) { return true; }
|
||||
if (ownerItem.ParentInventory == null) { return false; }
|
||||
return ownerItem.ParentInventory.ItemOwnsSelf(item);
|
||||
}
|
||||
|
||||
public virtual int FindAllowedSlot(Item item)
|
||||
{
|
||||
if (ItemOwnsSelf(item)) return -1;
|
||||
if (ItemOwnsSelf(item)) { return -1; }
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
//item is already in the inventory!
|
||||
if (Items[i] == item) return -1;
|
||||
if (slots[i].Contains(item)) { return -1; }
|
||||
}
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (Items[i] == null) return i;
|
||||
if (slots[i].CanBePut(item)) { return i; }
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can the item be put in the inventory (i.e. is there a suitable free slot or a stack the item can be put in).
|
||||
/// </summary>
|
||||
public bool CanBePut(Item item)
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
@@ -128,20 +370,54 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can the item be put in the specified slot.
|
||||
/// </summary>
|
||||
public virtual bool CanBePut(Item item, int i)
|
||||
{
|
||||
if (ItemOwnsSelf(item)) return false;
|
||||
if (i < 0 || i >= Items.Length) return false;
|
||||
return (Items[i] == null);
|
||||
if (ItemOwnsSelf(item)) { return false; }
|
||||
if (i < 0 || i >= slots.Length) { return false; }
|
||||
return slots[i].CanBePut(item);
|
||||
}
|
||||
|
||||
|
||||
public bool CanBePut(ItemPrefab itemPrefab)
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (CanBePut(itemPrefab, i)) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool CanBePut(ItemPrefab itemPrefab, int i)
|
||||
{
|
||||
if (i < 0 || i >= slots.Length) { return false; }
|
||||
return slots[i].CanBePut(itemPrefab);
|
||||
}
|
||||
|
||||
public int HowManyCanBePut(ItemPrefab itemPrefab)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
count += HowManyCanBePut(itemPrefab, i);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public virtual int HowManyCanBePut(ItemPrefab itemPrefab, int i)
|
||||
{
|
||||
if (i < 0 || i >= slots.Length) { return 0; }
|
||||
return slots[i].HowManyCanBePut(itemPrefab);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If there is room, puts the item in the inventory and returns true, otherwise returns false
|
||||
/// </summary>
|
||||
public virtual bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
|
||||
public virtual bool TryPutItem(Item item, Character user, IEnumerable<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
|
||||
{
|
||||
int slot = FindAllowedSlot(item);
|
||||
if (slot < 0) return false;
|
||||
if (slot < 0) { return false; }
|
||||
|
||||
PutItem(item, slot, user, true, createNetworkEvent);
|
||||
return true;
|
||||
@@ -149,7 +425,7 @@ namespace Barotrauma
|
||||
|
||||
public virtual bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
|
||||
{
|
||||
if (i < 0 || i >= Items.Length)
|
||||
if (i < 0 || i >= slots.Length)
|
||||
{
|
||||
string errorMsg = "Inventory.TryPutItem failed: index was out of range(" + i + ").\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("Inventory.TryPutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
@@ -158,31 +434,41 @@ namespace Barotrauma
|
||||
|
||||
if (Owner == null) return false;
|
||||
//there's already an item in the slot
|
||||
if (Items[i] != null && allowCombine)
|
||||
if (slots[i].Any() && allowCombine)
|
||||
{
|
||||
if (Items[i].Combine(item, user))
|
||||
if (slots[i].First().Combine(item, user))
|
||||
{
|
||||
//item in the slot removed as a result of combining -> put this item in the now free slot
|
||||
if (Items[i] == null)
|
||||
if (!slots[i].Any())
|
||||
{
|
||||
return TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (Items[i] != null && item.ParentInventory != null && allowSwapping)
|
||||
{
|
||||
return TrySwapping(i, item, user, createNetworkEvent);
|
||||
}
|
||||
else if (CanBePut(item, i))
|
||||
if (CanBePut(item, i))
|
||||
{
|
||||
PutItem(item, i, user, true, createNetworkEvent);
|
||||
return true;
|
||||
}
|
||||
else if (slots[i].Any() && item.ParentInventory != null && allowSwapping)
|
||||
{
|
||||
var itemInSlot = slots[i].First();
|
||||
if (itemInSlot.OwnInventory != null &&
|
||||
!itemInSlot.OwnInventory.Contains(item) &&
|
||||
(itemInSlot.GetComponent<ItemContainer>()?.MaxStackSize ?? 0) == 1 &&
|
||||
itemInSlot.OwnInventory.TrySwapping(0, item, user, createNetworkEvent, swapWholeStack: false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return
|
||||
TrySwapping(i, item, user, createNetworkEvent, swapWholeStack: true) ||
|
||||
TrySwapping(i, item, user, createNetworkEvent, swapWholeStack: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if CLIENT
|
||||
if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
|
||||
if (visualSlots != null && createNetworkEvent) { visualSlots[i].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f); }
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -190,14 +476,14 @@ namespace Barotrauma
|
||||
|
||||
protected virtual void PutItem(Item item, int i, Character user, bool removeItem = true, bool createNetworkEvent = true)
|
||||
{
|
||||
if (i < 0 || i >= Items.Length)
|
||||
if (i < 0 || i >= slots.Length)
|
||||
{
|
||||
string errorMsg = "Inventory.PutItem failed: index was out of range(" + i + ").\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("Inventory.PutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Owner == null) return;
|
||||
if (Owner == null) { return; }
|
||||
|
||||
Inventory prevInventory = item.ParentInventory;
|
||||
Inventory prevOwnerInventory = item.FindParentInventory(inv => inv is CharacterInventory);
|
||||
@@ -206,20 +492,23 @@ namespace Barotrauma
|
||||
{
|
||||
CreateNetworkEvent();
|
||||
//also delay syncing the inventory the item was inside
|
||||
if (prevInventory != null && prevInventory != this) prevInventory.syncItemsDelay = 1.0f;
|
||||
if (prevInventory != null && prevInventory != this) { prevInventory.syncItemsDelay = 1.0f; }
|
||||
}
|
||||
|
||||
if (removeItem)
|
||||
{
|
||||
item.Drop(user);
|
||||
if (item.ParentInventory != null) item.ParentInventory.RemoveItem(item);
|
||||
if (item.ParentInventory != null) { item.ParentInventory.RemoveItem(item); }
|
||||
}
|
||||
|
||||
Items[i] = item;
|
||||
slots[i].Add(item);
|
||||
item.ParentInventory = this;
|
||||
|
||||
#if CLIENT
|
||||
if (slots != null) slots[i].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
|
||||
if (visualSlots != null)
|
||||
{
|
||||
visualSlots[i]?.ShowBorderHighlight(Color.White, 0.1f, 0.4f);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (item.body != null)
|
||||
@@ -258,33 +547,49 @@ namespace Barotrauma
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (Items[i] != null) return false;
|
||||
if (slots[i].Any()) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsFull()
|
||||
/// <summary>
|
||||
/// Is there room to put more items in the inventory. Doesn't take stacking into account by default.
|
||||
/// </summary>
|
||||
/// <param name="takeStacksIntoAccount">If true, the inventory is not considered full if all the stacks are not full.</param>
|
||||
public virtual bool IsFull(bool takeStacksIntoAccount = false)
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
if (takeStacksIntoAccount)
|
||||
{
|
||||
if (Items[i] == null) return false;
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (!slots[i].Any()) { return false; }
|
||||
var item = slots[i].FirstOrDefault();
|
||||
if (slots[i].ItemCount < item.Prefab.MaxStackSize) { return false; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (!slots[i].Any()) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool TrySwapping(int index, Item item, Character user, bool createNetworkEvent)
|
||||
protected bool TrySwapping(int index, Item item, Character user, bool createNetworkEvent, bool swapWholeStack)
|
||||
{
|
||||
if (item?.ParentInventory == null || Items[index] == null) return false;
|
||||
if (item?.ParentInventory == null || !slots[index].Any()) { return false; }
|
||||
|
||||
//swap to InvSlotType.Any if possible
|
||||
Inventory otherInventory = item.ParentInventory;
|
||||
bool otherIsEquipped = false;
|
||||
int otherIndex = -1;
|
||||
for (int i = 0; i < otherInventory.Items.Length; i++)
|
||||
for (int i = 0; i < otherInventory.slots.Length; i++)
|
||||
{
|
||||
if (otherInventory.Items[i] != item) continue;
|
||||
if (!otherInventory.slots[i].Contains(item)) { continue; }
|
||||
if (otherInventory is CharacterInventory characterInventory)
|
||||
{
|
||||
if (characterInventory.SlotTypes[i] == InvSlotType.Any)
|
||||
@@ -298,89 +603,138 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (otherIndex == -1) otherIndex = Array.IndexOf(otherInventory.Items, item);
|
||||
Item existingItem = Items[index];
|
||||
|
||||
for (int j = 0; j < otherInventory.capacity; j++)
|
||||
if (otherIndex == -1)
|
||||
{
|
||||
if (otherInventory.Items[j] == item) { otherInventory.Items[j] = null; }
|
||||
}
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (Items[j] == existingItem) { Items[j] = null; }
|
||||
otherIndex = otherInventory.FindIndex(item);
|
||||
if (otherIndex == -1)
|
||||
{
|
||||
DebugConsole.ThrowError("Something went wrong when trying to swap items between inventory slots: couldn't find the source item from it's inventory.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
List<Item> existingItems = new List<Item>();
|
||||
if (swapWholeStack)
|
||||
{
|
||||
existingItems.AddRange(slots[index].Items);
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (existingItems.Any(existingItem => slots[j].Contains(existingItem))) { slots[j].RemoveAllItems(); }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
existingItems.Add(slots[index].FirstOrDefault());
|
||||
slots[index].RemoveItem(existingItems.First());
|
||||
}
|
||||
|
||||
List<Item> stackedItems = new List<Item>();
|
||||
if (swapWholeStack)
|
||||
{
|
||||
for (int j = 0; j < otherInventory.capacity; j++)
|
||||
{
|
||||
if (otherInventory.slots[j].Contains(item))
|
||||
{
|
||||
stackedItems.AddRange(otherInventory.slots[j].Items);
|
||||
otherInventory.slots[j].RemoveAllItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stackedItems.Add(item);
|
||||
otherInventory.slots[otherIndex].RemoveItem(item);
|
||||
}
|
||||
|
||||
(otherInventory.Owner as Character)?.DeselectItem(item);
|
||||
(otherInventory.Owner as Character)?.DeselectItem(existingItem);
|
||||
|
||||
bool swapSuccessful = false;
|
||||
if (otherIsEquipped)
|
||||
{
|
||||
swapSuccessful =
|
||||
TryPutItem(item, index, false, false, user, createNetworkEvent) &&
|
||||
otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent);
|
||||
stackedItems.Distinct().All(stackedItem => TryPutItem(stackedItem, index, false, false, user, createNetworkEvent))
|
||||
&&
|
||||
(existingItems.All(existingItem => otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent)) ||
|
||||
existingItems.Count == 1 && otherInventory.TryPutItem(existingItems.First(), user, CharacterInventory.anySlot, createNetworkEvent));
|
||||
}
|
||||
else
|
||||
{
|
||||
swapSuccessful =
|
||||
otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent) &&
|
||||
TryPutItem(item, index, false, false, user, createNetworkEvent);
|
||||
swapSuccessful =
|
||||
(existingItems.All(existingItem => otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent)) ||
|
||||
existingItems.Count == 1 && otherInventory.TryPutItem(existingItems.First(),user, CharacterInventory.anySlot, createNetworkEvent))
|
||||
&&
|
||||
stackedItems.Distinct().All(stackedItem => TryPutItem(stackedItem, index, false, false, user, createNetworkEvent));
|
||||
}
|
||||
|
||||
//if the item in the slot can be moved to the slot of the moved item
|
||||
if (swapSuccessful)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(Items[index] == item, "Something when wrong when swapping items, item is not present in the inventory.");
|
||||
System.Diagnostics.Debug.Assert(otherInventory.Items[otherIndex] == existingItem, "Something when wrong when swapping items, item is not present in the other inventory.");
|
||||
System.Diagnostics.Debug.Assert(slots[index].Contains(item), "Something when wrong when swapping items, item is not present in the inventory.");
|
||||
System.Diagnostics.Debug.Assert(otherInventory.Contains(existingItems.FirstOrDefault()), "Something when wrong when swapping items, item is not present in the other inventory.");
|
||||
#if CLIENT
|
||||
if (slots != null)
|
||||
if (visualSlots != null)
|
||||
{
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (Items[j] == item) slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f);
|
||||
if (slots[j].Contains(item)) { visualSlots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f); }
|
||||
}
|
||||
for (int j = 0; j < otherInventory.capacity; j++)
|
||||
{
|
||||
if (otherInventory.Items[j] == existingItem) otherInventory.slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f);
|
||||
if (otherInventory.slots[j].Contains(existingItems.FirstOrDefault())) { otherInventory.visualSlots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f); }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
else //swapping the items failed -> move them back to where they were
|
||||
{
|
||||
for (int j = 0; j < capacity; j++)
|
||||
if (swapWholeStack)
|
||||
{
|
||||
if (Items[j] == item) Items[j] = null;
|
||||
foreach (Item stackedItem in stackedItems)
|
||||
{
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (slots[j].Contains(stackedItem)) { slots[j].RemoveItem(stackedItem); };
|
||||
}
|
||||
}
|
||||
foreach (Item existingItem in existingItems)
|
||||
{
|
||||
for (int j = 0; j < otherInventory.capacity; j++)
|
||||
{
|
||||
if (otherInventory.slots[j].Contains(existingItem)) { otherInventory.slots[j].RemoveItem(existingItem); }
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < otherInventory.capacity; j++)
|
||||
else
|
||||
{
|
||||
if (otherInventory.Items[j] == existingItem) otherInventory.Items[j] = null;
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (slots[j].Contains(item)) { slots[j].RemoveAllItems(); };
|
||||
}
|
||||
for (int j = 0; j < otherInventory.capacity; j++)
|
||||
{
|
||||
if (otherInventory.slots[j].Contains(existingItems.FirstOrDefault())) { otherInventory.slots[j].RemoveAllItems(); }
|
||||
}
|
||||
}
|
||||
|
||||
if (otherIsEquipped)
|
||||
{
|
||||
TryPutItem(existingItem, index, false, false, user, createNetworkEvent);
|
||||
otherInventory.TryPutItem(item, otherIndex, false, false, user, createNetworkEvent);
|
||||
existingItems.ForEach(existingItem => TryPutItem(existingItem, index, false, false, user, createNetworkEvent));
|
||||
stackedItems.ForEach(stackedItem => otherInventory.TryPutItem(stackedItem, otherIndex, false, false, user, createNetworkEvent));
|
||||
}
|
||||
else
|
||||
{
|
||||
otherInventory.TryPutItem(item, otherIndex, false, false, user, createNetworkEvent);
|
||||
TryPutItem(existingItem, index, false, false, user, createNetworkEvent);
|
||||
stackedItems.ForEach(stackedItem => otherInventory.TryPutItem(stackedItem, otherIndex, false, false, user, createNetworkEvent));
|
||||
existingItems.ForEach(existingItem => TryPutItem(existingItem, index, false, false, user, createNetworkEvent));
|
||||
}
|
||||
|
||||
//swapping the items failed -> move them back to where they were
|
||||
//otherInventory.TryPutItem(item, otherIndex, false, false, user, createNetworkEvent);
|
||||
//TryPutItem(existingItem, index, false, false, user, createNetworkEvent);
|
||||
#if CLIENT
|
||||
if (slots != null)
|
||||
if (visualSlots != null)
|
||||
{
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (Items[j] == existingItem)
|
||||
if (slots[j].Contains(existingItems.FirstOrDefault()))
|
||||
{
|
||||
slots[j].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
|
||||
visualSlots[j].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,10 +754,10 @@ namespace Barotrauma
|
||||
|
||||
public Item FindItem(Func<Item, bool> predicate, bool recursive)
|
||||
{
|
||||
Item match = Items.FirstOrDefault(i => i != null && predicate(i));
|
||||
Item match = AllItems.FirstOrDefault(i => predicate(i));
|
||||
if (match == null && recursive)
|
||||
{
|
||||
foreach (var item in Items)
|
||||
foreach (var item in AllItems)
|
||||
{
|
||||
if (item == null) { continue; }
|
||||
if (item.OwnInventory != null)
|
||||
@@ -422,9 +776,8 @@ namespace Barotrauma
|
||||
public List<Item> FindAllItems(Func<Item, bool> predicate, bool recursive = false, List<Item> list = null)
|
||||
{
|
||||
list ??= new List<Item>();
|
||||
foreach (var item in Items)
|
||||
foreach (var item in AllItems)
|
||||
{
|
||||
if (item == null) { continue; }
|
||||
if (predicate(item))
|
||||
{
|
||||
list.Add(item);
|
||||
@@ -448,30 +801,57 @@ namespace Barotrauma
|
||||
|
||||
public Item FindItemByIdentifier(string identifier, bool recursive = false)
|
||||
{
|
||||
if (identifier == null) return null;
|
||||
if (identifier == null) { return null; }
|
||||
return FindItem(i => i.Prefab.Identifier == identifier, recursive);
|
||||
}
|
||||
|
||||
public virtual void RemoveItem(Item item)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (item == null) { return; }
|
||||
|
||||
//go through the inventory and remove the item from all slots
|
||||
for (int n = 0; n < capacity; n++)
|
||||
{
|
||||
if (Items[n] != item) continue;
|
||||
|
||||
Items[n] = null;
|
||||
if (!slots[n].Contains(item)) { continue; }
|
||||
|
||||
slots[n].RemoveItem(item);
|
||||
item.ParentInventory = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces an item to a specific slot. Doesn't remove the item from existing slots/inventories or do any other sanity checks, use with caution!
|
||||
/// </summary>
|
||||
public void ForceToSlot(Item item, int index)
|
||||
{
|
||||
slots[index].Add(item);
|
||||
item.ParentInventory = this;
|
||||
if (item.body != null)
|
||||
{
|
||||
item.body.Enabled = false;
|
||||
item.body.BodyType = FarseerPhysics.BodyType.Dynamic;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from a specific slot. Doesn't do any sanity checks, use with caution!
|
||||
/// </summary>
|
||||
public void ForceRemoveFromSlot(Item item, int index)
|
||||
{
|
||||
slots[index].RemoveItem(item);
|
||||
}
|
||||
|
||||
|
||||
public void SharedWrite(IWriteMessage msg, object[] extraData = null)
|
||||
{
|
||||
msg.Write((byte)capacity);
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
msg.Write((ushort)(Items[i] == null ? 0 : Items[i].ID));
|
||||
msg.WriteRangedInteger(slots[i].ItemCount, 0, MaxStackSize);
|
||||
foreach (Item item in slots[i].Items)
|
||||
{
|
||||
msg.Write((ushort)(item == null ? 0 : item.ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,29 +862,17 @@ namespace Barotrauma
|
||||
{
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (Items[i] == null) continue;
|
||||
foreach (ItemContainer itemContainer in Items[i].GetComponents<ItemContainer>())
|
||||
if (!slots[i].Any()) { continue; }
|
||||
foreach (Item item in slots[i].Items)
|
||||
{
|
||||
itemContainer.Inventory.DeleteAllItems();
|
||||
foreach (ItemContainer itemContainer in item.GetComponents<ItemContainer>())
|
||||
{
|
||||
itemContainer.Inventory.DeleteAllItems();
|
||||
}
|
||||
}
|
||||
Items[i].Remove();
|
||||
slots[i].Items.ForEachMod(it => it.Remove());
|
||||
slots[i].RemoveAllItems();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Item> GetAllItems()
|
||||
{
|
||||
List<Item> deletedItems = new List<Item>();
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (Items[i] == null) continue;
|
||||
foreach (ItemContainer itemContainer in Items[i].GetComponents<ItemContainer>())
|
||||
{
|
||||
deletedItems.AddRange(itemContainer.Inventory.GetAllItems());
|
||||
}
|
||||
deletedItems.Add(Items[i]);
|
||||
}
|
||||
|
||||
return deletedItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user