Inventory/InventorySlot.cs
using System;
using System.Text.Json.Serialization;
using Clover.Persistence;
using Sandbox.Diagnostics;
namespace Clover.Inventory;
public sealed partial class InventorySlot
{
[JsonInclude] public int Index { get; set; } = -1;
[JsonInclude, JsonPropertyName( "_item" )]
public PersistentItem PersistentItem;
/// <summary>
/// The amount of the item in the inventory slot. Not applicable for non-stackable items.
/// </summary>
[JsonInclude]
public int Amount { get; private set; } = 1;
[JsonIgnore] public bool IsStackable => PersistentItem.IsStackable;
[JsonIgnore] public bool MaxStackReached => PersistentItem.StackSize <= Amount;
public InventorySlot( InventoryContainer inventory )
{
InventoryContainer = inventory;
}
public InventorySlot()
{
}
[JsonIgnore] public InventoryContainer InventoryContainer { get; set; }
[JsonIgnore] public bool HasItem => PersistentItem != null;
public void SetItem( PersistentItem item )
{
PersistentItem = item;
InventoryContainer.OnChange();
}
public PersistentItem GetItem()
{
return PersistentItem;
}
public T GetItem<T>() where T : PersistentItem
{
if ( PersistentItem is T typedItem )
{
return typedItem;
}
Log.Error( $"InventorySlot.GetItem<{typeof(T).Name}>: Item in slot is not of type {typeof(T).Name}" );
return null;
}
public string GetName()
{
return PersistentItem.GetName();
}
public string GetIcon()
{
return PersistentItem.GetIcon();
}
public Texture GetIconTexture()
{
return PersistentItem.GetIconTexture();
}
public void Delete()
{
InventoryContainer.RemoveSlot( Index );
// _item = null;
// Inventory.OnChange();
// Inventory.Player.Save();
}
/// <summary>
/// Sets the amount of items in the inventory slot.
/// </summary>
/// <param name="amount">The new amount of items.</param>
public void SetAmount( int amount )
{
Amount = amount;
InventoryContainer.OnChange();
}
public bool CanMergeWith( InventorySlot other )
{
// abort if either item is null
if ( PersistentItem == null || other.PersistentItem == null )
{
Log.Info( "CanMerge: Item is null" );
return false;
}
// abort if item types are not the same
if ( PersistentItem.GetType() != other.PersistentItem.GetType() )
{
Log.Info( "CanMerge: Item types are not the same" );
return false;
}
// abort if either item is not stackable
if ( PersistentItem.IsStackable == false || other.PersistentItem.IsStackable == false )
{
Log.Info( "CanMerge: Item is not stackable" );
return false;
}
// abort if amount is zero. this should never happen
if ( Amount <= 0 )
{
Log.Info( "CanMerge: Amount is zero" );
return false;
}
// abort if stack can't hold the amount
if ( PersistentItem.StackSize < Amount + other.Amount )
{
Log.Info(
$"CanMerge: Stack cannot hold the amount ({PersistentItem.StackSize} < {Amount + other.Amount})" );
return false;
}
try
{
PersistentItem.CanMergeWith( other.PersistentItem );
}
catch ( Exception e )
{
// XLog.Error( "InventoryContainerSlot",
// $"CanMerge: Item cannot merge with other item in slot {Index} or other slot {other.Index}" );
Log.Warning( $"CanMerge: {e.Message}" );
return false;
}
return true;
}
/// <summary>
/// Merge this slot into another slot. It will delete this slot and sync the other slot.
/// </summary>
/// <param name="other"></param>
/// <exception cref="Exception"></exception>
public void MergeWith( InventorySlot other )
{
// sanity check!
if ( other == null )
{
throw new Exception( "Cannot merge with null slot" );
}
// sanity check!!
if ( other.InventoryContainer == null )
{
throw new Exception( "Cannot merge with slot with null inventory" );
}
// this is the same as the sanity check called in CanMergeWith
if ( !CanMergeWith( other ) )
{
throw new Exception( "Cannot merge with slot with incompatible item" );
}
// sanity check!!!
if ( !PersistentItem.CanMergeWith( other.PersistentItem ) )
{
throw new Exception( "Cannot merge with slot with incompatible item" );
}
/* if ( !InventoryContainer.AllowSlotInteract )
{
throw new Exception( "You cannot interact with this inventory" );
}
if ( !other.InventoryContainer.AllowSlotInteract )
{
throw new Exception( "You cannot interact with the receiving inventory" );
} */
// merge into other
// other.Amount += Amount;
other.SetAmount( other.Amount + Amount );
// other.InventoryContainer.FixEventRegistration();
// other.InventoryContainer.SyncToPlayerList();
// call merge on the item, by default it does nothing
PersistentItem.MergeWith( other.PersistentItem );
// delete and sync this one
Delete();
// FixEventRegistration();
// InventoryContainer.SyncToPlayerList();
// XLog.Info( "InventoryContainerSlot", $"Merged {other.Amount} items into slot {Index}" );
}
public void TakeOneOrDelete()
{
if ( !IsStackable )
{
Delete();
}
else if ( Amount > 1 )
{
// Amount--;
SetAmount( Amount - 1 );
}
else
{
Delete();
}
}
}