Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CommandQueueIconFix v1.0.3
BepInEx/plugins/CommandQueue.IconFix/CommandQueue.IconFix.dll
Decompiled 11 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using RoR2; using RoR2.UI; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("CommandQueue.NewGameFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CommandQueue.NewGameFix")] [assembly: AssemblyTitle("CommandQueue.NewGameFix")] [assembly: AssemblyVersion("1.0.0.0")] namespace CommandQueueNewGameFix; [BepInPlugin("com.ror2modding.commandqueue-newgamefix", "CommandQueue.NewGameFix", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class NewGameFixPlugin : BaseUnityPlugin { public const string VERSION = "1.0.3"; private static NewGameFixPlugin instance; private static ManualLogSource s_logger; private static MethodInfo s_getIconAODR; private static bool s_newIconPipeline; private static bool s_backfillStarted; private static int s_backfilledCount; private static bool s_backfillDone; private static HUD s_hud; private static Transform s_container; private static Sprite s_lockIcon; private static bool s_repairActive; private static readonly HashSet<GameObject> s_asyncAssigned = new HashSet<GameObject>(); public static NewGameFixPlugin Instance => instance; public void Awake() { instance = this; s_logger = ((BaseUnityPlugin)this).Logger; DetectFeatures(); LogInfo(string.Format("Loaded v{0} (async icon pipeline: {1})", "1.0.3", s_newIconPipeline)); } private void DetectFeatures() { s_getIconAODR = typeof(PickupDef).GetMethod("GetIconAODR", BindingFlags.Instance | BindingFlags.Public, null, new Type[3] { typeof(bool), typeof(Action<Sprite>), typeof(Action<Sprite>) }, null); s_newIconPipeline = s_getIconAODR != null; } public void OnEnable() { if (!s_newIconPipeline) { LogInfo("This game build does not use the async icon pipeline — nothing to fix. Staying idle."); return; } Run.onRunStartGlobal += OnRunStart; ((MonoBehaviour)this).StartCoroutine(WatchForCommandQueueUI()); } public void OnDisable() { Run.onRunStartGlobal -= OnRunStart; } private void OnRunStart(Run run) { s_backfillStarted = false; s_backfillDone = false; s_backfilledCount = 0; s_asyncAssigned.Clear(); ((MonoBehaviour)this).StartCoroutine(EnsureBackfill()); ((MonoBehaviour)this).StartCoroutine(WatchForCommandQueueUI()); } private IEnumerator EnsureBackfill() { if (s_backfillStarted) { yield break; } s_backfillStarted = true; Queue<PickupDef> todo = new Queue<PickupDef>(); foreach (PickupDef allPickup in PickupCatalog.allPickups) { if (allPickup != null && !Object.op_Implicit((Object)(object)allPickup.iconSprite)) { todo.Enqueue(allPickup); } } LogInfo($"Backfill: {todo.Count} pickup(s) without a direct icon sprite"); int perFrame = 32; while (todo.Count > 0) { for (int i = 0; i < perFrame; i++) { if (todo.Count <= 0) { break; } if (TryResolveIcon(todo.Dequeue())) { s_backfilledCount++; } } yield return null; } s_backfillDone = true; LogInfo($"Backfill done: resolved {s_backfilledCount} icon(s)"); if (FindContainer()) { ((MonoBehaviour)this).StartCoroutine(RepairPass()); } } private static bool TryResolveIcon(PickupDef def) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown try { object obj = s_getIconAODR.Invoke(def, new object[3] { true, null, null }); if (obj == null) { return false; } object obj2 = (object)(Object)obj.GetType().GetMethod("WaitForCompletion").Invoke(obj, null); Sprite val = (Sprite)((obj2 is Sprite) ? obj2 : null); if (val != null && (Object)(object)val != (Object)null) { def.iconSprite = val; return true; } return false; } catch (Exception ex) { LogWarn("Failed to resolve icon for '" + def?.internalName + "': " + ex.Message); return false; } } private IEnumerator WatchForCommandQueueUI() { int attempts = 0; while (!Object.op_Implicit((Object)(object)s_hud) && attempts++ < 120) { HUD val = Object.FindObjectOfType<HUD>(); if ((Object)(object)val != (Object)null) { s_hud = val; } else { yield return (object)new WaitForSeconds(1f); } } if (!Object.op_Implicit((Object)(object)s_hud)) { LogInfo("No HUD found — CommandQueue UI is not active, repair pass disabled."); yield break; } attempts = 0; while (!FindContainer() && attempts++ < 240) { yield return (object)new WaitForSeconds(0.5f); } if (FindContainer()) { LogInfo("CommandQueue container found, starting icon repair."); ((MonoBehaviour)this).StartCoroutine(RepairPass()); } } private bool FindContainer() { if ((Object)(object)s_container != (Object)null) { return true; } GameObject val = GameObject.Find("CommandQueueContainer"); if ((Object)(object)val != (Object)null) { s_container = val.transform; return true; } if ((Object)(object)s_hud != (Object)null && FindChildByName(((Component)s_hud).transform, "CommandQueueContainer", out var result)) { s_container = result; return true; } return false; } private IEnumerator RepairPass() { if (s_repairActive) { yield break; } s_repairActive = true; int totalFixed = 0; try { int idleFrames = 0; for (int i = 0; i < 14400; i++) { if (!FindContainer()) { s_container = null; yield return (object)new WaitForSeconds(1f); continue; } int num = RepairAllIcons(); totalFixed += num; if (num == 0) { int num2 = idleFrames + 1; idleFrames = num2; if (num2 > 30) { break; } yield return null; } else { idleFrames = 0; yield return null; } } } finally { s_repairActive = false; } LogInfo($"IconFix repair finished: {totalFixed} button icon(s) assigned"); } private int RepairAllIcons() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown int num = 0; foreach (Transform item in s_container) { Transform val = item; if (!((Object)val).name.EndsWith("QueueContainer") || !Enum.TryParse<ItemTier>(((Object)val).name.Substring(0, ((Object)val).name.Length - "QueueContainer".Length), out ItemTier result)) { continue; } Transform val2 = val; int num2 = 0; foreach (Transform item2 in val) { Transform val3 = item2; if (!((Object)(object)((Component)val3).GetComponent<GridLayoutGroup>() == (Object)null)) { int num3 = ((Component)val3).GetComponentsInChildren<MPButton>(true).Length; if (num3 > num2) { num2 = num3; val2 = val3; } } } List<Image> list = null; try { MPButton[] componentsInChildren = ((Component)val2).GetComponentsInChildren<MPButton>(true); if (componentsInChildren.Length != 0) { list = new List<Image>(); MPButton[] array = componentsInChildren; foreach (MPButton val4 in array) { if (!((Object)(object)((Component)val4).transform.parent == (Object)(object)val)) { Image buttonIconImage = GetButtonIconImage(val4); if ((Object)(object)buttonIconImage != (Object)null) { list.Add(buttonIconImage); } } } } } catch { list = null; } if (list == null || list.Count == 0) { list = new List<Image>(); CollectIconImages(val, list); } if (list.Count == 0) { continue; } PickupIndex[] itemOptionsForTier = GetItemOptionsForTier(result); if (itemOptionsForTier == null || itemOptionsForTier.Length == 0) { continue; } try { int num4 = itemOptionsForTier.Length - itemOptionsForTier.Distinct().Count(); PickupDef pickupDef = PickupCatalog.GetPickupDef(itemOptionsForTier[0]); PickupDef pickupDef2 = PickupCatalog.GetPickupDef(itemOptionsForTier[^1]); LogInfo($"Tier {result}: grid images={list.Count}, items={itemOptionsForTier.Length}" + ((num4 > 0) ? $" *** {num4} duplicate(s) in the item list ***" : "") + ", first='" + pickupDef?.internalName + "', last='" + pickupDef2?.internalName + "'"); } catch { } for (int j = 0; j < list.Count && j < itemOptionsForTier.Length; j++) { Image val5 = list[j]; if (!((Object)(object)val5 == (Object)null) && !((Object)(object)val5.sprite != (Object)null)) { PickupDef pickupDef3 = PickupCatalog.GetPickupDef(itemOptionsForTier[j]); if (RepairOneButton(val5, pickupDef3)) { num++; } } } } return num; } private static Image GetButtonIconImage(MPButton button) { try { ChildLocator component = ((Component)button).GetComponent<ChildLocator>(); if ((Object)(object)component == (Object)null) { return null; } Transform obj = component.FindChild("Icon"); return (obj != null) ? ((Component)obj).GetComponent<Image>() : null; } catch { return null; } } private static bool RepairOneButton(Image img, PickupDef pickupDef) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (pickupDef == null) { return false; } if (!(((Graphic)img).color.g < 0.6f) && (!(Mathf.Abs(((Graphic)img).color.r - ((Graphic)img).color.b) < 0.01f) || !(((Graphic)img).color.r < 0.7f))) { GameObject gameObject = ((Component)img).gameObject; AsyncImage val = default(AsyncImage); if (gameObject.TryGetComponent<AsyncImage>(ref val)) { if (s_asyncAssigned.Contains(gameObject)) { return false; } ((AsyncViewable<Sprite, Image>)(object)val).SetAssetOrDirectReference(pickupDef.iconSpriteReference, pickupDef.iconSprite); s_asyncAssigned.Add(gameObject); return true; } if (s_backfillDone || ResolveIconNow(pickupDef)) { Sprite iconSprite = pickupDef.iconSprite; if ((Object)(object)iconSprite != (Object)null) { img.sprite = iconSprite; return true; } } return false; } Sprite lockIcon = GetLockIcon(); if ((Object)(object)lockIcon != (Object)null) { img.sprite = lockIcon; return true; } return false; } private static bool ResolveIconNow(PickupDef def) { if (!s_newIconPipeline) { return false; } return TryResolveIcon(def); } private static Sprite GetLockIcon() { if ((Object)(object)s_lockIcon != (Object)null) { return s_lockIcon; } try { s_lockIcon = LegacyResourcesAPI.Load<Sprite>("Textures/MiscIcons/texUnlockIcon"); } catch (Exception ex) { LogWarn("Could not load lock icon: " + ex.Message); } return s_lockIcon; } private static PickupIndex[] GetItemOptionsForTier(ItemTier tier) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) try { PickupIndex[] groupFromPickupIndex = PickupTransmutationManager.GetGroupFromPickupIndex(PickupCatalog.FindPickupIndex(tier)); if (groupFromPickupIndex != null && groupFromPickupIndex.Length != 0) { return groupFromPickupIndex; } return (from itemDef in ((IEnumerable<ItemIndex>)(object)ItemCatalog.allItems).Select((Func<ItemIndex, ItemDef>)ItemCatalog.GetItemDef) where (Object)(object)itemDef != (Object)null && itemDef.tier == tier let pickupIndex = PickupCatalog.FindPickupIndex(itemDef.itemIndex) where pickupIndex != PickupIndex.none select pickupIndex).ToArray(); } catch (Exception ex) { LogWarn($"GetItemOptionsForTier({tier}) failed: {ex.Message}"); return null; } } private static void CollectIconImages(Transform root, List<Image> result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown foreach (Transform item in root) { Transform val = item; if (((Object)val).name == "Icon") { Image component = ((Component)val).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { result.Add(component); } } CollectIconImages(val, result); } } private static bool FindChildByName(Transform root, string name, out Transform result) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown result = null; foreach (Transform item in root) { Transform val = item; if (((Object)val).name == name) { result = val; return true; } if (FindChildByName(val, name, out result)) { return true; } } return false; } private static void LogInfo(string msg) { ManualLogSource obj = s_logger; if (obj != null) { obj.LogInfo((object)msg); } } private static void LogWarn(string msg) { ManualLogSource obj = s_logger; if (obj != null) { obj.LogWarning((object)msg); } } }