185 lines
6.4 KiB
C#
185 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Cielonos.MainGame.Inventory;
|
|
using SLSUtilities.General;
|
|
|
|
namespace Cielonos.MainGame.Items
|
|
{
|
|
/// <summary>
|
|
/// 物品排序模式。
|
|
/// </summary>
|
|
public enum ItemSortMode
|
|
{
|
|
/// <summary>
|
|
/// 默认:按类型(主武器→支援→被动→消耗品)→ 稀有度(高→低)→ 名称。
|
|
/// Extender 插队到其宿主物品之后。
|
|
/// </summary>
|
|
Default,
|
|
|
|
/// <summary>按稀有度(高→低)→ 名称。</summary>
|
|
ByRarity,
|
|
|
|
/// <summary>完全按显示名称排序。</summary>
|
|
ByName
|
|
}
|
|
|
|
/// <summary>
|
|
/// 物品排序工具类,与 <see cref="ItemFilter"/> 配合使用。
|
|
/// <para>
|
|
/// 通过 <see cref="NameResolver"/> 可替换名称解析策略以适配不同的本地化方案。
|
|
/// 默认使用 <c>ContentData.displayNameKey.Localize()</c>。
|
|
/// </para>
|
|
/// </summary>
|
|
public static class ItemSorter
|
|
{
|
|
/// <summary>
|
|
/// 名称解析委托。排序时通过此方法获取物品的显示名称。
|
|
/// 替换此委托即可切换本地化或自定义命名策略。
|
|
/// </summary>
|
|
public static Func<ItemBase, string> NameResolver { get; set; } = DefaultNameResolver;
|
|
|
|
private static string DefaultNameResolver(ItemBase item)
|
|
{
|
|
if (item?.contentData == null) return string.Empty;
|
|
return item.contentData.displayNameKey.Localize("Items");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 对物品列表就地排序。
|
|
/// </summary>
|
|
public static void Sort(List<ItemBase> items, ItemSortMode mode)
|
|
{
|
|
if (items == null || items.Count <= 1) return;
|
|
|
|
switch (mode)
|
|
{
|
|
case ItemSortMode.Default:
|
|
SortDefault(items);
|
|
break;
|
|
case ItemSortMode.ByRarity:
|
|
SortByRarity(items);
|
|
break;
|
|
case ItemSortMode.ByName:
|
|
SortByName(items);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ─────────────────── Default ───────────────────
|
|
|
|
private static void SortDefault(List<ItemBase> items)
|
|
{
|
|
// 1. 分离已绑定宿主的 Extender
|
|
List<ExtenderBase> attachedExtenders = new List<ExtenderBase>();
|
|
List<ItemBase> regularItems = new List<ItemBase>();
|
|
|
|
foreach (ItemBase item in items)
|
|
{
|
|
if (item is ExtenderBase ext && ext.IsAttached)
|
|
{
|
|
attachedExtenders.Add(ext);
|
|
}
|
|
else
|
|
{
|
|
regularItems.Add(item);
|
|
}
|
|
}
|
|
|
|
// 2. 对常规物品排序:类型 → 稀有度(降序)→ 名称
|
|
regularItems.Sort(CompareByTypeRarityName);
|
|
|
|
// 3. Extender 之间按稀有度(降序)→ 名称排序,保证同宿主下多个 Extender 顺序稳定
|
|
attachedExtenders.Sort((a, b) =>
|
|
{
|
|
int cmp = CompareRarityDescending(a, b);
|
|
return cmp != 0 ? cmp : CompareName(a, b);
|
|
});
|
|
|
|
// 4. 将 Extender 插入到宿主之后
|
|
items.Clear();
|
|
items.AddRange(regularItems);
|
|
|
|
foreach (ExtenderBase ext in attachedExtenders)
|
|
{
|
|
int hostIndex = items.IndexOf(ext.Host);
|
|
if (hostIndex >= 0)
|
|
{
|
|
int insertPos = hostIndex + 1;
|
|
while (insertPos < items.Count
|
|
&& items[insertPos] is ExtenderBase sibling
|
|
&& sibling.IsAttached
|
|
&& sibling.Host == ext.Host)
|
|
{
|
|
insertPos++;
|
|
}
|
|
|
|
items.Insert(insertPos, ext);
|
|
}
|
|
else
|
|
{
|
|
// 宿主不在列表中(被筛选等情况),追加到末尾
|
|
items.Add(ext);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ─────────────────── ByRarity ───────────────────
|
|
|
|
private static void SortByRarity(List<ItemBase> items)
|
|
{
|
|
items.Sort((a, b) =>
|
|
{
|
|
int cmp = CompareRarityDescending(a, b);
|
|
return cmp != 0 ? cmp : CompareName(a, b);
|
|
});
|
|
}
|
|
|
|
// ─────────────────── ByName ───────────────────
|
|
|
|
private static void SortByName(List<ItemBase> items)
|
|
{
|
|
items.Sort(CompareName);
|
|
}
|
|
|
|
// ─────────────────── Comparison Helpers ───────────────────
|
|
|
|
private static int CompareByTypeRarityName(ItemBase a, ItemBase b)
|
|
{
|
|
int typeA = GetTypePriority(a);
|
|
int typeB = GetTypePriority(b);
|
|
if (typeA != typeB) return typeA.CompareTo(typeB);
|
|
|
|
int cmp = CompareRarityDescending(a, b);
|
|
return cmp != 0 ? cmp : CompareName(a, b);
|
|
}
|
|
|
|
/// <summary>稀有度降序比较(高稀有度在前)。</summary>
|
|
private static int CompareRarityDescending(ItemBase a, ItemBase b)
|
|
{
|
|
int ra = a?.contentData != null ? (int)a.contentData.itemRarity : -1;
|
|
int rb = b?.contentData != null ? (int)b.contentData.itemRarity : -1;
|
|
return rb.CompareTo(ra);
|
|
}
|
|
|
|
/// <summary>按本地化显示名称比较,使用当前文化区域排序规则。</summary>
|
|
private static int CompareName(ItemBase a, ItemBase b)
|
|
{
|
|
return string.Compare(NameResolver(a), NameResolver(b), StringComparison.CurrentCulture);
|
|
}
|
|
|
|
private static int GetTypePriority(ItemBase item)
|
|
{
|
|
if (item?.contentData == null) return int.MaxValue;
|
|
|
|
return item.contentData.itemType switch
|
|
{
|
|
ItemType.MainWeapon => 0,
|
|
ItemType.Support => 1,
|
|
ItemType.Passive => 2,
|
|
ItemType.Consumable => 3,
|
|
_ => int.MaxValue
|
|
};
|
|
}
|
|
}
|
|
}
|