Player/Inventory/Container/InventoryContainer.cs
namespace Opium;
public partial class InventoryContainer : Component
{
/// <summary>
/// Which item type does this inventory container accept?
/// </summary>
[Property] public ItemType ItemType { get; set; }
[Property] public int MaxItems { get; set; } = 0;
[Property] public List<InventoryItem> Items { get; set; }
[Property] public List<InventoryItemResource> DefaultItems { get; set; }
protected override void OnEnabled()
{
Items ??= new();
Items?.Clear();
for ( int i = 0; i < MaxItems; i++ )
{
// Add empty items
Items.Add( null );
}
SetupDefaultItems();
}
/// <summary>
/// Sets up default items if we have any set. (Mainly for development)
/// </summary>
void SetupDefaultItems()
{
if ( DefaultItems is not null && DefaultItems.Count > 0 )
{
int index = 0;
foreach ( var resource in DefaultItems )
{
SetItem( index, resource );
index++;
}
}
}
/// <summary>
/// Sets an item from a resource
/// </summary>
/// <param name="index"></param>
/// <param name="resource"></param>
public void SetItem( int index, InventoryItemResource resource )
{
// TF?
if ( Items.Count < index ) return;
Items[index] = new InventoryItem( resource );
}
/// <summary>
/// Clear an item from the index
/// </summary>
/// <param name="index"></param>
public void RemoveItem( int index )
{
if ( MaxItems < 1 )
{
Items.RemoveAt( index );
}
else
{
Items[index] = null;
}
}
// Try to find an existing inventory item that can be stacked.
private InventoryItem FindExistingItem( InventoryItemResource resource, int quantity )
{
foreach ( var item in Items.Where( x => x is not null ) )
{
// If the item is the same, and it's stackable, let's use it!
if ( item.ItemResource == resource && item.CanStack( quantity ) )
{
return item;
}
}
return null;
}
/// <summary>
/// Tries to add an item to the player's inventory
/// </summary>
/// <param name="resource"></param>
/// <param name="quantity"></param>
public void AddItem( InventoryItemResource resource, int quantity = 1 )
{
// Look for an existing item instance that has enough stack quantity for our item.
var existingItem = FindExistingItem( resource, quantity );
if ( existingItem is not null )
{
// Up the item's quantity, and bail.
existingItem.Quantity += quantity;
return;
}
// If we don't have an item limit
if ( MaxItems < 1 )
{
Items.Add( new InventoryItem( resource ) );
}
else
{
// Find the index of the first available slot
var indexOf = Items.IndexOf( Items.FirstOrDefault( x => x is null ) );
if ( indexOf != -1 )
{
SetItem( indexOf, resource );
}
}
}
/// <summary>
/// Does the player have an item in this container?
/// </summary>
/// <param name="resource"></param>
/// <returns></returns>
public bool HasItem( InventoryItemResource resource )
{
var itemInstance = Items.FirstOrDefault( x => x.ItemResource == resource );
return itemInstance is not null;
}
/// <summary>
/// Gets an item from a container.
/// </summary>
/// <param name="resource"></param>
/// <returns></returns>
public (InventoryItem Item, int Index) GetItem( InventoryItemResource resource )
{
var itemInstance = Items.FirstOrDefault( x => x.ItemResource == resource );
var itemId = Items.IndexOf( itemInstance );
return (itemInstance, itemId);
}
public override int GetHashCode()
{
int hash = base.GetHashCode();
if ( Items is null ) return hash;
foreach ( var item in Items )
{
hash += item?.ItemResource?.GetHashCode() ?? 0;
}
return hash;
}
}