init
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using VOID.Generic.Dict;
|
||||
using System.Linq;
|
||||
using Sirenix.Utilities;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Item;
|
||||
|
||||
namespace VOID.Generic.Util
|
||||
{
|
||||
public static class ItemObjectSortUtil
|
||||
{
|
||||
public static void Sort(ref ItemObject[] items, Func<ItemObject, IComparable> valueGetter, SortDirectionType sortDirection)
|
||||
{
|
||||
if (items.IsNullOrEmpty()) return;
|
||||
|
||||
// Find items that can be stacked and then merge them (empty leftovers will be destroyed and removed)
|
||||
StackGroups(GetStackGroups(items));
|
||||
|
||||
Array.Sort(items, (item1, item2) =>
|
||||
{
|
||||
// Empty item slots always to the end
|
||||
if (!item1 && !item2) return 0;
|
||||
if (!item1) return 1;
|
||||
if (!item2) return -1;
|
||||
|
||||
// Existing items sort by given value getter with given sort direction
|
||||
var result = valueGetter(item1).CompareTo(valueGetter(item2));
|
||||
if (sortDirection is SortDirectionType.Descending) result *= - 1;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Returns list of item groups that can be stacked together</summary>
|
||||
private static List<List<ItemObject>> GetStackGroups(ItemObject[] items)
|
||||
{
|
||||
var groups = new List<List<ItemObject>>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
// Ignore: empty, non-stackable, those with max stack size already
|
||||
if (!item) continue;
|
||||
if (!item.itemData.stackable) continue;
|
||||
if (item.itemData.stackSize >= item.itemData.stackSizeMax) continue;
|
||||
|
||||
// Each group has items that can be stacked together
|
||||
var group = groups.FirstOrDefault(group => group.First().CanStackWith(item));
|
||||
if (group == null)
|
||||
{
|
||||
group = new List<ItemObject>();
|
||||
groups.Add(group);
|
||||
}
|
||||
group.Add(item);
|
||||
}
|
||||
|
||||
// Ignore groups with only 1 item
|
||||
return groups.Where(group => group.Count > 1).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 1. Stacks items together as tight as possible
|
||||
/// 2. Destroys and removes items that have no more stacks inside (by invoking event with Remove())
|
||||
/// </summary>
|
||||
private static void StackGroups(List<List<ItemObject>> groups)
|
||||
{
|
||||
foreach (var group in groups)
|
||||
{
|
||||
var stackSize = group.Sum(item => item.itemData.stackSize);
|
||||
var maxStackSize = group.First().itemData.stackSizeMax;
|
||||
|
||||
var maxStackSizeItems = Mathf.FloorToInt((float)stackSize / maxStackSize);
|
||||
var remainingStackSize = stackSize % maxStackSize;
|
||||
|
||||
// Items that will have 100% of its stack size
|
||||
group.Take(maxStackSizeItems).ForEach(item => item.itemData.stackSize = maxStackSize);
|
||||
|
||||
// Remaining of stack will go to next item
|
||||
if (remainingStackSize > 0) group.Skip(maxStackSizeItems).First().itemData.stackSizeMax = maxStackSize;
|
||||
|
||||
// IMPORTANT! Because we got ref to items here, event caused by Remove() should remove items from list itself
|
||||
// All other items are left without stacks, so they're "empty" - destroy and remove from list
|
||||
group.Skip(maxStackSizeItems).Skip(remainingStackSize > 0 ? 1 : 0).ForEach(item => item.Remove());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user