using Barotrauma.Items.Components; using Barotrauma.Networking; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; namespace Barotrauma { partial class ItemInventory : Inventory { private readonly ItemContainer container; public ItemContainer Container { get { return container; } } public ItemInventory(Item owner, ItemContainer container, int capacity, int slotsPerRow = 5) : base(owner, capacity, slotsPerRow) { this.container = container; } public override int FindAllowedSlot(Item item, bool ignoreCondition = false) { if (ItemOwnsSelf(item)) { return -1; } //item is already in the inventory! if (Contains(item)) { return -1; } if (!container.CanBeContained(item)) { return -1; } //try to stack first for (int i = 0; i < capacity; i++) { if (slots[i].Any() && CanBePutInSlot(item, i, ignoreCondition)) { return i; } } for (int i = 0; i < capacity; i++) { if (CanBePutInSlot(item, i, ignoreCondition)) { return i; } } return -1; } public override bool CanBePutInSlot(Item item, int i, bool ignoreCondition = false) { if (ItemOwnsSelf(item)) { return false; } if (i < 0 || i >= slots.Length) { return false; } if (!container.CanBeContained(item, i)) { return false; } return item != null && slots[i].CanBePut(item, ignoreCondition) && slots[i].Items.Count < container.GetMaxStackSize(i); } public override bool CanBePutInSlot(ItemPrefab itemPrefab, int i, float? condition, int? quality = null) { if (i < 0 || i >= slots.Length) { return false; } if (!container.CanBeContained(itemPrefab, i)) { return false; } return itemPrefab != null && slots[i].CanBePut(itemPrefab, condition, quality) && slots[i].Items.Count < container.GetMaxStackSize(i); } public override int HowManyCanBePut(ItemPrefab itemPrefab, int i, float? condition, bool ignoreItemsInSlot = false) { if (itemPrefab == null) { return 0; } if (i < 0 || i >= slots.Length) { return 0; } if (!container.CanBeContained(itemPrefab, i)) { return 0; } return slots[i].HowManyCanBePut(itemPrefab, maxStackSize: Math.Min(itemPrefab.GetMaxStackSize(this), container.GetMaxStackSize(i)), condition, ignoreItemsInSlot); } public override bool IsFull(bool takeStacksIntoAccount = false) { if (takeStacksIntoAccount) { for (int i = 0; i < capacity; i++) { if (!slots[i].Any()) { return false; } var item = slots[i].FirstOrDefault(); if (slots[i].Items.Count < Math.Min(item.Prefab.GetMaxStackSize(this), container.GetMaxStackSize(i))) { return false; } } } else { for (int i = 0; i < capacity; i++) { if (!slots[i].Any()) { return false; } } } return true; } public override bool TryPutItem(Item item, Character user, IEnumerable allowedSlots = null, bool createNetworkEvent = true, bool ignoreCondition = false) { bool wasPut = base.TryPutItem(item, user, allowedSlots, createNetworkEvent, ignoreCondition); if (wasPut) { foreach (Character c in Character.CharacterList) { if (!c.HeldItems.Contains(item)) { continue; } item.Unequip(c); break; } container.IsActive = true; container.OnItemContained(item); #if SERVER GameMain.Server?.KarmaManager?.OnItemContained(item, container.Item, user); #endif } return wasPut; } public override bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool ignoreCondition = false) { bool wasPut = base.TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent, ignoreCondition); if (wasPut && item.ParentInventory == this) { foreach (Character c in Character.CharacterList) { if (!c.HeldItems.Contains(item)) { continue; } item.Unequip(c); break; } container.IsActive = true; container.OnItemContained(item); #if SERVER GameMain.Server?.KarmaManager?.OnItemContained(item, container.Item, user); #endif } return wasPut; } protected override void CreateNetworkEvent(Range slotRange) { if (!Item.ItemList.Contains(container.Item)) { string errorMsg = "Attempted to create a network event for an item (" + container.Item.Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace(); DebugConsole.ThrowError(errorMsg); GameAnalyticsManager.AddErrorEventOnce( "ItemInventory.CreateServerEvent:EventForUninitializedItem" + container.Item.Name + container.Item.ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg); return; } if (!container.Item.Components.Contains(container)) { DebugConsole.Log("Creating a network event for the item \"" + container.Item + "\" failed, ItemContainer not found in components"); return; } if (slotRange.Start.Value < 0 || slotRange.End.Value > capacity) { DebugConsole.ThrowError($"Error when creating an inventory event: invalid slot range ({slotRange})\n" + Environment.StackTrace); return; } if (GameMain.NetworkMember != null) { if (GameMain.NetworkMember.IsClient) { syncItemsDelay = 1.0f; } GameMain.NetworkMember.CreateEntityEvent(Owner as INetSerializable, new Item.InventoryStateEventData(container, slotRange)); } } public override void RemoveItem(Item item) { base.RemoveItem(item); container.OnItemRemoved(item); } } }