using System; using System.Collections.Generic; using HG; using UnityEngine; namespace RoR2; [CreateAssetMenu(menuName = "RoR2/ItemDisplayRuleSet")] public class ItemDisplayRuleSet : ScriptableObject { [Serializable] [Obsolete] public struct NamedRuleGroup { public string name; public DisplayRuleGroup displayRuleGroup; } [Serializable] public struct KeyAssetRuleGroup { public UnityEngine.Object keyAsset; public DisplayRuleGroup displayRuleGroup; } [SerializeField] [Obsolete("Use .assetRuleGroups instead.")] private NamedRuleGroup[] namedItemRuleGroups = Array.Empty(); [Obsolete("Use .assetRuleGroups instead.")] [SerializeField] private NamedRuleGroup[] namedEquipmentRuleGroups = Array.Empty(); public KeyAssetRuleGroup[] keyAssetRuleGroups = Array.Empty(); private DisplayRuleGroup[] runtimeItemRuleGroups; private DisplayRuleGroup[] runtimeEquipmentRuleGroups; private static readonly List instancesList = new List(); private static bool runtimeDependenciesReady = false; private bool hasObsoleteNamedRuleGroups { get { if (namedItemRuleGroups.Length == 0) { return namedEquipmentRuleGroups.Length != 0; } return true; } } public bool isEmpty => keyAssetRuleGroups.Length == 0; [SystemInitializer(new Type[] { typeof(ItemCatalog), typeof(EquipmentCatalog) })] private static void Init() { runtimeDependenciesReady = true; for (int i = 0; i < instancesList.Count; i++) { instancesList[i].GenerateRuntimeValues(); } } private void OnEnable() { instancesList.Add(this); if (runtimeDependenciesReady) { GenerateRuntimeValues(); } } private void OnDisable() { instancesList.Remove(this); } private void OnValidate() { if (hasObsoleteNamedRuleGroups) { Debug.LogWarningFormat(this, "ItemDisplayRuleSet \"{0}\" still defines one or more entries in an obsolete format. Run the upgrade from the inspector context menu.", this); } } public void GenerateRuntimeValues() { runtimeItemRuleGroups = ItemCatalog.GetPerItemBuffer(); runtimeEquipmentRuleGroups = EquipmentCatalog.GetPerEquipmentBuffer(); ArrayUtils.SetAll(runtimeItemRuleGroups, in DisplayRuleGroup.empty); ArrayUtils.SetAll(runtimeEquipmentRuleGroups, in DisplayRuleGroup.empty); for (int i = 0; i < keyAssetRuleGroups.Length; i++) { ref KeyAssetRuleGroup reference = ref keyAssetRuleGroups[i]; UnityEngine.Object keyAsset = reference.keyAsset; if (!(keyAsset is ItemDef itemDef)) { if (keyAsset is EquipmentDef { equipmentIndex: not EquipmentIndex.None } equipmentDef) { runtimeEquipmentRuleGroups[(int)equipmentDef.equipmentIndex] = reference.displayRuleGroup; } } else if (itemDef.itemIndex != ItemIndex.None) { runtimeItemRuleGroups[(int)itemDef.itemIndex] = reference.displayRuleGroup; } } } public DisplayRuleGroup FindDisplayRuleGroup(UnityEngine.Object keyAsset) { if ((bool)keyAsset) { for (int i = 0; i < keyAssetRuleGroups.Length; i++) { ref KeyAssetRuleGroup reference = ref keyAssetRuleGroups[i]; if ((object)reference.keyAsset == keyAsset) { return reference.displayRuleGroup; } } } return DisplayRuleGroup.empty; } public void SetDisplayRuleGroup(UnityEngine.Object keyAsset, DisplayRuleGroup displayRuleGroup) { if (!keyAsset) { return; } for (int i = 0; i < keyAssetRuleGroups.Length; i++) { ref KeyAssetRuleGroup reference = ref keyAssetRuleGroups[i]; if ((object)reference.keyAsset == keyAsset) { reference.displayRuleGroup = displayRuleGroup; return; } } ref KeyAssetRuleGroup[] array = ref keyAssetRuleGroups; KeyAssetRuleGroup value = new KeyAssetRuleGroup { keyAsset = keyAsset, displayRuleGroup = displayRuleGroup }; ArrayUtils.ArrayAppend(ref array, in value); } public DisplayRuleGroup GetItemDisplayRuleGroup(ItemIndex itemIndex) { return ArrayUtils.GetSafe(runtimeItemRuleGroups, (int)itemIndex, in DisplayRuleGroup.empty); } public DisplayRuleGroup GetEquipmentDisplayRuleGroup(EquipmentIndex equipmentIndex) { return ArrayUtils.GetSafe(runtimeEquipmentRuleGroups, (int)equipmentIndex, in DisplayRuleGroup.empty); } public void Reset() { keyAssetRuleGroups = Array.Empty(); runtimeItemRuleGroups = Array.Empty(); runtimeEquipmentRuleGroups = Array.Empty(); } [ContextMenu("Upgrade to keying by asset")] public void UpdgradeToAssetKeying() { _ = Application.isPlaying; if (hasObsoleteNamedRuleGroups) { List list = new List(); UpgradeNamedRuleGroups(ref namedItemRuleGroups, "ItemDef", (string assetName) => ItemCatalog.GetItemDef(ItemCatalog.FindItemIndex(assetName)), list); UpgradeNamedRuleGroups(ref namedEquipmentRuleGroups, "EquipmentDef", (string assetName) => EquipmentCatalog.GetEquipmentDef(EquipmentCatalog.FindEquipmentIndex(assetName)), list); if (list.Count > 0) { Debug.LogWarningFormat("Encountered {0} errors attempting to upgrade ItemDisplayRuleSet \"{1}\":\n{2}", list.Count, base.name, string.Join("\n", list)); } EditorUtil.SetDirty(this); } } private void UpgradeNamedRuleGroups(ref NamedRuleGroup[] namedRuleGroups, string assetTypeName, Func assetLookupMethod, List failureMessagesList) { int arraySize = namedRuleGroups.Length; for (int i = 0; i < arraySize; i++) { NamedRuleGroup namedRuleGroup = namedRuleGroups[i]; UnityEngine.Object @object = assetLookupMethod(namedRuleGroup.name); string text = null; if (!namedRuleGroup.displayRuleGroup.isEmpty) { if ((bool)@object) { if (FindDisplayRuleGroup(@object).isEmpty) { SetDisplayRuleGroup(@object, namedRuleGroup.displayRuleGroup); } else { text = "Conflicts with existing rule group."; } } else { text = "Named asset not found."; } } if (text != null) { failureMessagesList.Add(assetTypeName + " \"" + namedRuleGroup.name + "\": " + text); } else { ArrayUtils.ArrayRemoveAt(namedRuleGroups, ref arraySize, i); i--; } } Array.Resize(ref namedRuleGroups, arraySize); } }