289 lines
8.5 KiB
C#
289 lines
8.5 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using System.Text;
|
||
|
using System.Xml.Linq;
|
||
|
using HG;
|
||
|
using RoR2.ContentManagement;
|
||
|
using RoR2.Modding;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace RoR2;
|
||
|
|
||
|
public static class ItemCatalog
|
||
|
{
|
||
|
public struct AllItemsEnumerator : IEnumerator<ItemIndex>, IEnumerator, IDisposable
|
||
|
{
|
||
|
private ItemIndex position;
|
||
|
|
||
|
public ItemIndex Current => position;
|
||
|
|
||
|
object IEnumerator.Current => Current;
|
||
|
|
||
|
public bool MoveNext()
|
||
|
{
|
||
|
position++;
|
||
|
return (int)position < itemCount;
|
||
|
}
|
||
|
|
||
|
public void Reset()
|
||
|
{
|
||
|
position = ItemIndex.None;
|
||
|
}
|
||
|
|
||
|
void IDisposable.Dispose()
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static List<ItemIndex> tier1ItemList = new List<ItemIndex>();
|
||
|
|
||
|
public static List<ItemIndex> tier2ItemList = new List<ItemIndex>();
|
||
|
|
||
|
public static List<ItemIndex> tier3ItemList = new List<ItemIndex>();
|
||
|
|
||
|
public static List<ItemIndex> lunarItemList = new List<ItemIndex>();
|
||
|
|
||
|
public static ResourceAvailability availability = default(ResourceAvailability);
|
||
|
|
||
|
public static string[] itemNames = Array.Empty<string>();
|
||
|
|
||
|
private static readonly Dictionary<string, ItemIndex> itemNameToIndex = new Dictionary<string, ItemIndex>();
|
||
|
|
||
|
private static ItemIndex[][] itemIndicesByTag = Array.Empty<ItemIndex[]>();
|
||
|
|
||
|
private static Dictionary<ItemRelationshipType, ItemDef.Pair[]> itemRelationships = new Dictionary<ItemRelationshipType, ItemDef.Pair[]>();
|
||
|
|
||
|
private static readonly Stack<ItemIndex[]> itemOrderBuffers = new Stack<ItemIndex[]>();
|
||
|
|
||
|
private static readonly Stack<int[]> itemStackArrays = new Stack<int[]>();
|
||
|
|
||
|
public static readonly GenericStaticEnumerable<ItemIndex, AllItemsEnumerator> allItems;
|
||
|
|
||
|
public static int itemCount
|
||
|
{
|
||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
|
get
|
||
|
{
|
||
|
if (ContentManager._itemDefs == null)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
return ContentManager._itemDefs.Length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static ReadOnlyArray<ItemDef> allItemDefs => ContentManager._itemDefs;
|
||
|
|
||
|
[Obsolete("Use IContentPackProvider instead.")]
|
||
|
public static event Action<List<ItemDef>> getAdditionalEntries
|
||
|
{
|
||
|
add
|
||
|
{
|
||
|
LegacyModContentPackProvider.instance.HandleLegacyGetAdditionalEntries("RoR2.ItemCatalog.getAdditionalEntries", value, LegacyModContentPackProvider.instance.registrationContentPack.itemDefs);
|
||
|
}
|
||
|
remove
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[SystemInitializer(new Type[] { typeof(ItemTierCatalog) })]
|
||
|
private static void Init()
|
||
|
{
|
||
|
HGXml.Register(delegate(XElement element, ItemIndex[] obj)
|
||
|
{
|
||
|
element.Value = string.Join(" ", obj.Select((ItemIndex v) => GetItemDef(v)?.name));
|
||
|
}, delegate(XElement element, ref ItemIndex[] output)
|
||
|
{
|
||
|
output = (from v in element.Value.Split(' ')
|
||
|
select GetItemDef(FindItemIndex(v))?.itemIndex ?? ItemIndex.None).ToArray();
|
||
|
return true;
|
||
|
});
|
||
|
SetItemDefs(ContentManager.itemDefs);
|
||
|
SetItemRelationships(ContentManager.itemRelationshipProviders);
|
||
|
availability.MakeAvailable();
|
||
|
}
|
||
|
|
||
|
private static void SetItemDefs(ItemDef[] newItemDefs)
|
||
|
{
|
||
|
ItemDef[] itemDefs = ContentManager._itemDefs;
|
||
|
for (int i = 0; i < itemDefs.Length; i++)
|
||
|
{
|
||
|
itemDefs[i].itemIndex = ItemIndex.None;
|
||
|
}
|
||
|
ArrayUtils.CloneTo(newItemDefs, ref ContentManager._itemDefs);
|
||
|
itemNameToIndex.Clear();
|
||
|
itemOrderBuffers.Clear();
|
||
|
itemStackArrays.Clear();
|
||
|
Array.Resize(ref itemNames, newItemDefs.Length);
|
||
|
for (int j = 0; j < newItemDefs.Length; j++)
|
||
|
{
|
||
|
itemNames[j] = newItemDefs[j].name;
|
||
|
}
|
||
|
Array.Sort(itemNames, ContentManager._itemDefs, StringComparer.Ordinal);
|
||
|
for (ItemIndex itemIndex = ItemIndex.Count; (int)itemIndex < ContentManager._itemDefs.Length; itemIndex++)
|
||
|
{
|
||
|
ItemDef obj = ContentManager._itemDefs[(int)itemIndex];
|
||
|
string key = itemNames[(int)itemIndex];
|
||
|
obj.itemIndex = itemIndex;
|
||
|
switch (obj.tier)
|
||
|
{
|
||
|
case ItemTier.Tier1:
|
||
|
tier1ItemList.Add(itemIndex);
|
||
|
break;
|
||
|
case ItemTier.Tier2:
|
||
|
tier2ItemList.Add(itemIndex);
|
||
|
break;
|
||
|
case ItemTier.Tier3:
|
||
|
tier3ItemList.Add(itemIndex);
|
||
|
break;
|
||
|
case ItemTier.Lunar:
|
||
|
lunarItemList.Add(itemIndex);
|
||
|
break;
|
||
|
}
|
||
|
itemNameToIndex[key] = itemIndex;
|
||
|
}
|
||
|
int num = 23;
|
||
|
Array.Resize(ref itemIndicesByTag, num);
|
||
|
ItemIndex[][] array = itemIndicesByTag;
|
||
|
ItemIndex[] value = Array.Empty<ItemIndex>();
|
||
|
ArrayUtils.SetAll(array, in value);
|
||
|
List<ItemIndex>[] array2 = new List<ItemIndex>[num];
|
||
|
for (ItemTag itemTag = ItemTag.Any; (int)itemTag < num; itemTag++)
|
||
|
{
|
||
|
array2[(int)itemTag] = CollectionPool<ItemIndex, List<ItemIndex>>.RentCollection();
|
||
|
}
|
||
|
for (ItemIndex itemIndex2 = ItemIndex.Count; (int)itemIndex2 < ContentManager._itemDefs.Length; itemIndex2++)
|
||
|
{
|
||
|
ItemTag[] tags = ContentManager._itemDefs[(int)itemIndex2].tags;
|
||
|
foreach (ItemTag itemTag2 in tags)
|
||
|
{
|
||
|
array2[(int)itemTag2].Add(itemIndex2);
|
||
|
}
|
||
|
}
|
||
|
for (ItemTag itemTag3 = ItemTag.Any; (int)itemTag3 < num; itemTag3++)
|
||
|
{
|
||
|
ref List<ItemIndex> reference = ref array2[(int)itemTag3];
|
||
|
itemIndicesByTag[(int)itemTag3] = reference.ToArray();
|
||
|
reference = CollectionPool<ItemIndex, List<ItemIndex>>.ReturnCollection(reference);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void SetItemRelationships(ItemRelationshipProvider[] newProviders)
|
||
|
{
|
||
|
Dictionary<ItemRelationshipType, HashSet<ItemDef.Pair>> dictionary = new Dictionary<ItemRelationshipType, HashSet<ItemDef.Pair>>();
|
||
|
foreach (ItemRelationshipProvider itemRelationshipProvider in newProviders)
|
||
|
{
|
||
|
if (!dictionary.ContainsKey(itemRelationshipProvider.relationshipType))
|
||
|
{
|
||
|
dictionary.Add(itemRelationshipProvider.relationshipType, new HashSet<ItemDef.Pair>());
|
||
|
}
|
||
|
dictionary[itemRelationshipProvider.relationshipType].UnionWith(itemRelationshipProvider.relationships);
|
||
|
}
|
||
|
itemRelationships.Clear();
|
||
|
foreach (KeyValuePair<ItemRelationshipType, HashSet<ItemDef.Pair>> item in dictionary)
|
||
|
{
|
||
|
IEnumerable<ItemDef.Pair> enumerable = item.Value.Where((ItemDef.Pair pair) => !pair.itemDef1 || !pair.itemDef2);
|
||
|
foreach (ItemDef.Pair item2 in enumerable)
|
||
|
{
|
||
|
Debug.LogError("Trying to define a " + item.Key.name + " relationship between " + item2.itemDef1?.name + " and " + item2.itemDef2?.name + ".");
|
||
|
}
|
||
|
item.Value.ExceptWith(enumerable);
|
||
|
itemRelationships.Add(item.Key, item.Value.ToArray());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static ItemIndex[] RequestItemOrderBuffer()
|
||
|
{
|
||
|
if (itemOrderBuffers.Count > 0)
|
||
|
{
|
||
|
return itemOrderBuffers.Pop();
|
||
|
}
|
||
|
return new ItemIndex[itemCount];
|
||
|
}
|
||
|
|
||
|
public static void ReturnItemOrderBuffer(ItemIndex[] buffer)
|
||
|
{
|
||
|
itemOrderBuffers.Push(buffer);
|
||
|
}
|
||
|
|
||
|
public static int[] RequestItemStackArray()
|
||
|
{
|
||
|
if (itemStackArrays.Count > 0)
|
||
|
{
|
||
|
return itemStackArrays.Pop();
|
||
|
}
|
||
|
return new int[itemCount];
|
||
|
}
|
||
|
|
||
|
public static void ReturnItemStackArray(int[] itemStackArray)
|
||
|
{
|
||
|
if (itemStackArray.Length == itemCount)
|
||
|
{
|
||
|
Array.Clear(itemStackArray, 0, itemStackArray.Length);
|
||
|
itemStackArrays.Push(itemStackArray);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static ItemDef GetItemDef(ItemIndex itemIndex)
|
||
|
{
|
||
|
return ArrayUtils.GetSafe(ContentManager._itemDefs, (int)itemIndex);
|
||
|
}
|
||
|
|
||
|
public static ItemIndex FindItemIndex(string itemName)
|
||
|
{
|
||
|
if (itemNameToIndex.TryGetValue(itemName, out var value))
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
return ItemIndex.None;
|
||
|
}
|
||
|
|
||
|
public static T[] GetPerItemBuffer<T>()
|
||
|
{
|
||
|
return new T[itemCount];
|
||
|
}
|
||
|
|
||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
|
public static bool IsIndexValid(in ItemIndex itemIndex)
|
||
|
{
|
||
|
return (uint)itemIndex < (uint)itemCount;
|
||
|
}
|
||
|
|
||
|
public static ReadOnlyArray<ItemIndex> GetItemsWithTag(ItemTag itemTag)
|
||
|
{
|
||
|
ItemIndex[][] array = itemIndicesByTag;
|
||
|
ItemIndex[] defaultValue = Array.Empty<ItemIndex>();
|
||
|
return ArrayUtils.GetSafe(array, (int)itemTag, in defaultValue);
|
||
|
}
|
||
|
|
||
|
public static ReadOnlyArray<ItemDef.Pair> GetItemPairsForRelationship(ItemRelationshipType relationshipType)
|
||
|
{
|
||
|
if (itemRelationships.ContainsKey(relationshipType))
|
||
|
{
|
||
|
return itemRelationships[relationshipType];
|
||
|
}
|
||
|
return Array.Empty<ItemDef.Pair>();
|
||
|
}
|
||
|
|
||
|
[ConCommand(commandName = "item_list", flags = ConVarFlags.None, helpText = "Lists internal names of all items registered to the item catalog.")]
|
||
|
private static void CCEquipmentList(ConCommandArgs args)
|
||
|
{
|
||
|
StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder();
|
||
|
ItemDef[] itemDefs = ContentManager._itemDefs;
|
||
|
foreach (ItemDef itemDef in itemDefs)
|
||
|
{
|
||
|
string colorHexString = ColorCatalog.GetColorHexString(itemDef.colorIndex);
|
||
|
stringBuilder.AppendLine("<color=#" + colorHexString + ">" + itemDef.name + " (" + Language.GetString(itemDef.nameToken) + ")</color>");
|
||
|
}
|
||
|
args.Log(stringBuilder.ToString());
|
||
|
HG.StringBuilderPool.ReturnStringBuilder(stringBuilder);
|
||
|
}
|
||
|
|
||
|
private static void DefineItems()
|
||
|
{
|
||
|
}
|
||
|
}
|