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, 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 tier1ItemList = new List(); public static List tier2ItemList = new List(); public static List tier3ItemList = new List(); public static List lunarItemList = new List(); public static ResourceAvailability availability = default(ResourceAvailability); public static string[] itemNames = Array.Empty(); private static readonly Dictionary itemNameToIndex = new Dictionary(); private static ItemIndex[][] itemIndicesByTag = Array.Empty(); private static Dictionary itemRelationships = new Dictionary(); private static readonly Stack itemOrderBuffers = new Stack(); private static readonly Stack itemStackArrays = new Stack(); public static readonly GenericStaticEnumerable allItems; public static int itemCount { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (ContentManager._itemDefs == null) { return 0; } return ContentManager._itemDefs.Length; } } public static ReadOnlyArray allItemDefs => ContentManager._itemDefs; [Obsolete("Use IContentPackProvider instead.")] public static event Action> 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(); ArrayUtils.SetAll(array, in value); List[] array2 = new List[num]; for (ItemTag itemTag = ItemTag.Any; (int)itemTag < num; itemTag++) { array2[(int)itemTag] = CollectionPool>.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 reference = ref array2[(int)itemTag3]; itemIndicesByTag[(int)itemTag3] = reference.ToArray(); reference = CollectionPool>.ReturnCollection(reference); } } private static void SetItemRelationships(ItemRelationshipProvider[] newProviders) { Dictionary> dictionary = new Dictionary>(); foreach (ItemRelationshipProvider itemRelationshipProvider in newProviders) { if (!dictionary.ContainsKey(itemRelationshipProvider.relationshipType)) { dictionary.Add(itemRelationshipProvider.relationshipType, new HashSet()); } dictionary[itemRelationshipProvider.relationshipType].UnionWith(itemRelationshipProvider.relationships); } itemRelationships.Clear(); foreach (KeyValuePair> item in dictionary) { IEnumerable 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() { return new T[itemCount]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsIndexValid(in ItemIndex itemIndex) { return (uint)itemIndex < (uint)itemCount; } public static ReadOnlyArray GetItemsWithTag(ItemTag itemTag) { ItemIndex[][] array = itemIndicesByTag; ItemIndex[] defaultValue = Array.Empty(); return ArrayUtils.GetSafe(array, (int)itemTag, in defaultValue); } public static ReadOnlyArray GetItemPairsForRelationship(ItemRelationshipType relationshipType) { if (itemRelationships.ContainsKey(relationshipType)) { return itemRelationships[relationshipType]; } return Array.Empty(); } [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("" + itemDef.name + " (" + Language.GetString(itemDef.nameToken) + ")"); } args.Log(stringBuilder.ToString()); HG.StringBuilderPool.ReturnStringBuilder(stringBuilder); } private static void DefineItems() { } }