Decompiled source of CommandQueueExtendedIconFix v1.0.0

CommandQueueIconFix.dll

Decompiled 17 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("CommandQueueIconFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CommandQueueIconFix")]
[assembly: AssemblyTitle("CommandQueueIconFix")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CommandQueueIconFix
{
	[BepInPlugin("local.commandqueue.iconfix", "CommandQueueExtended Icon Fix", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class CommandQueueIconFixPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "local.commandqueue.iconfix";

		public const string PluginName = "CommandQueueExtended Icon Fix";

		public const string PluginVersion = "1.0.0";

		private const string OverlayName = "CommandQueueIconFix_ItemIcon";

		private const BindingFlags DeclaredMethods = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static CommandQueueIconFixPlugin instance;

		private static GameObject vanillaItemIconPrefab;

		private static bool failedToFindPrefab;

		private static int overlaysCreated;

		private static int diagnosticCount;

		private static int exceptionCount;

		[ThreadStatic]
		private static PickupDef currentPickup;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			instance = this;
			Type type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
				select assembly.GetType("CommandQueue.UIManager", throwOnError: false)).FirstOrDefault((Type type2) => type2 != null);
			if (type == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Cannot find CommandQueue.UIManager. Check that CommandQueueExtended 2.0.0 is installed and enabled.");
				return;
			}
			harmony = new Harmony("local.commandqueue.iconfix");
			int num = 0;
			foreach (Type item in FindNestedTypes(type))
			{
				MethodInfo[] methods = item.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name.Contains("<CreateQueueContainer>") && methodInfo.GetMethodBody() != null)
					{
						try
						{
							harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CommandQueueIconFixPlugin), "ReplaceLegacyGridSprites", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
							num++;
						}
						catch (Exception ex)
						{
							((BaseUnityPlugin)this).Logger.LogError((object)("Cannot patch " + methodInfo.Name + ": " + ex));
						}
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("v1.0.0 installed Harmony patches on " + num + " CreateQueueContainer callback(s)."));
			if (num == 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"No matching callbacks found: this mod version may have changed.");
			}
		}

		private static IEnumerable<Type> FindNestedTypes(Type type)
		{
			yield return type;
			Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
			foreach (Type type2 in nestedTypes)
			{
				foreach (Type item in FindNestedTypes(type2))
				{
					yield return item;
				}
			}
		}

		public static IEnumerable<CodeInstruction> ReplaceLegacyGridSprites(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			MethodInfo capture = AccessTools.Method(typeof(CommandQueueIconFixPlugin), "CapturePickup", (Type[])null, (Type[])null);
			MethodInfo assign = AccessTools.Method(typeof(CommandQueueIconFixPlugin), "AssignItemIcon", (Type[])null, (Type[])null);
			int captures = 0;
			int assignments = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo fieldInfo && fieldInfo.DeclaringType == typeof(PickupDef) && fieldInfo.Name == "iconSprite")
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = capture;
					captures++;
				}
				else if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && instruction.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Image) && methodInfo.Name == "set_sprite")
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = assign;
					assignments++;
				}
				yield return instruction;
			}
			if (captures <= 0 && assignments <= 0)
			{
				yield break;
			}
			CommandQueueIconFixPlugin commandQueueIconFixPlugin = instance;
			if (commandQueueIconFixPlugin != null)
			{
				((BaseUnityPlugin)commandQueueIconFixPlugin).Logger.LogInfo((object)("Replaced icon calls in " + __originalMethod.DeclaringType?.FullName + "." + __originalMethod.Name + ": " + captures + " pickup capture(s), " + assignments + " Image.sprite setter(s)."));
			}
			if (captures != 1 || assignments < 1)
			{
				CommandQueueIconFixPlugin commandQueueIconFixPlugin2 = instance;
				if (commandQueueIconFixPlugin2 != null)
				{
					((BaseUnityPlugin)commandQueueIconFixPlugin2).Logger.LogWarning((object)"Unexpected icon IL pattern. This patch is intended for CommandQueueExtended 2.0.0.");
				}
			}
		}

		public static Sprite CapturePickup(PickupDef definition)
		{
			currentPickup = definition;
			return definition?.iconSprite;
		}

		public static void AssignItemIcon(Image target, Sprite originalSprite)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			PickupDef val = currentPickup;
			currentPickup = null;
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			if (val == null || (int)val.itemIndex == -1 || (Object)(object)instance == (Object)null)
			{
				target.sprite = originalSprite;
				return;
			}
			try
			{
				if (!instance.TryInstallItemIcon(target, val.itemIndex))
				{
					target.sprite = originalSprite;
				}
			}
			catch (Exception ex)
			{
				target.sprite = originalSprite;
				if (exceptionCount++ < 5)
				{
					((BaseUnityPlugin)instance).Logger.LogError((object)("Failed ItemIcon for " + ((object)Unsafe.As<ItemIndex, ItemIndex>(ref val.itemIndex)/*cast due to .constrained prefix*/).ToString() + ": " + ex));
				}
			}
		}

		private static GameObject FindItemIconPrefab()
		{
			if ((Object)(object)vanillaItemIconPrefab != (Object)null)
			{
				return vanillaItemIconPrefab;
			}
			if (failedToFindPrefab)
			{
				return null;
			}
			try
			{
				GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/HUDSimple");
				HUD val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<HUD>() : null);
				ItemInventoryDisplay val3 = (((Object)(object)val2 != (Object)null) ? val2.itemInventoryDisplay : null);
				vanillaItemIconPrefab = (((Object)(object)val3 != (Object)null) ? val3.itemIconPrefab : null);
				if ((Object)(object)vanillaItemIconPrefab == (Object)null || (Object)(object)vanillaItemIconPrefab.GetComponent<ItemIcon>() == (Object)null)
				{
					CommandQueueIconFixPlugin commandQueueIconFixPlugin = instance;
					if (commandQueueIconFixPlugin != null)
					{
						((BaseUnityPlugin)commandQueueIconFixPlugin).Logger.LogError((object)"HUDSimple itemIconPrefab is missing or does not have RoR2.UI.ItemIcon.");
					}
					failedToFindPrefab = true;
					return null;
				}
				CommandQueueIconFixPlugin commandQueueIconFixPlugin2 = instance;
				if (commandQueueIconFixPlugin2 != null)
				{
					((BaseUnityPlugin)commandQueueIconFixPlugin2).Logger.LogInfo((object)("Reusing HUDSimple ItemIcon prefab: " + ((Object)vanillaItemIconPrefab).name));
				}
				return vanillaItemIconPrefab;
			}
			catch (Exception ex)
			{
				failedToFindPrefab = true;
				CommandQueueIconFixPlugin commandQueueIconFixPlugin3 = instance;
				if (commandQueueIconFixPlugin3 != null)
				{
					((BaseUnityPlugin)commandQueueIconFixPlugin3).Logger.LogError((object)("Cannot load HUDSimple ItemIcon prefab: " + ex));
				}
				return null;
			}
		}

		private unsafe bool TryInstallItemIcon(Image legacyImage, ItemIndex itemIndex)
		{
			//IL_018f: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindItemIconPrefab();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Transform val2 = ((Component)legacyImage).transform.Find("CommandQueueIconFix_ItemIcon");
			bool flag = false;
			ItemIcon component;
			if ((Object)(object)val2 != (Object)null)
			{
				GameObject gameObject = ((Component)val2).gameObject;
				component = gameObject.GetComponent<ItemIcon>();
				if ((Object)(object)component == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Existing icon overlay has no ItemIcon: " + ((object)(*(ItemIndex*)(&itemIndex))/*cast due to .constrained prefix*/).ToString()));
					return false;
				}
			}
			else
			{
				GameObject gameObject = Object.Instantiate<GameObject>(val, ((Component)legacyImage).transform, false);
				((Object)gameObject).name = "CommandQueueIconFix_ItemIcon";
				component = gameObject.GetComponent<ItemIcon>();
				RectTransform component2 = gameObject.GetComponent<RectTransform>();
				if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
				{
					Object.Destroy((Object)(object)gameObject);
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Cannot create an ItemIcon and RectTransform for " + ((object)(*(ItemIndex*)(&itemIndex))/*cast due to .constrained prefix*/).ToString()));
					return false;
				}
				component2.anchorMin = Vector2.zero;
				component2.anchorMax = Vector2.one;
				component2.pivot = new Vector2(0.5f, 0.5f);
				component2.offsetMin = Vector2.zero;
				component2.offsetMax = Vector2.zero;
				((Transform)component2).localScale = Vector3.one;
				((Transform)component2).localRotation = Quaternion.identity;
				gameObject.transform.SetAsLastSibling();
				Graphic[] componentsInChildren = gameObject.GetComponentsInChildren<Graphic>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].raycastTarget = false;
				}
				CanvasGroup val3 = gameObject.GetComponent<CanvasGroup>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = gameObject.AddComponent<CanvasGroup>();
				}
				val3.blocksRaycasts = false;
				val3.interactable = false;
				flag = true;
			}
			component.SetItemIndex(itemIndex, 1);
			legacyImage.sprite = null;
			legacyImage.overrideSprite = null;
			((Behaviour)legacyImage).enabled = false;
			if (flag)
			{
				overlaysCreated++;
				bool flag2 = overlaysCreated <= 8;
				if (flag2)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Attached vanilla ItemIcon for " + ((object)(*(ItemIndex*)(&itemIndex))/*cast due to .constrained prefix*/).ToString() + " to " + ((Object)((Component)legacyImage).gameObject).name));
				}
				((MonoBehaviour)this).StartCoroutine(RebindAndInspect(component, itemIndex, flag2));
			}
			return true;
		}

		private unsafe IEnumerator RebindAndInspect(ItemIcon icon, ItemIndex itemIndex, bool inspect)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			yield return null;
			if ((Object)(object)icon == (Object)null)
			{
				yield break;
			}
			try
			{
				icon.SetItemIndex(itemIndex, 1);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("ItemIcon.SetItemIndex failed for " + ((object)(*(ItemIndex*)(&itemIndex))/*cast due to .constrained prefix*/).ToString() + ": " + ex));
				yield break;
			}
			if (!inspect)
			{
				yield break;
			}
			yield return (object)new WaitForSecondsRealtime(0.5f);
			if (!((Object)(object)icon == (Object)null) && diagnosticCount++ < 8)
			{
				Image[] componentsInChildren = ((Component)icon).GetComponentsInChildren<Image>(true);
				RawImage[] componentsInChildren2 = ((Component)icon).GetComponentsInChildren<RawImage>(true);
				int num = componentsInChildren.Count((Image image) => (Object)(object)image != (Object)null && (Object)(object)image.sprite != (Object)null);
				int num2 = componentsInChildren2.Count((RawImage image) => (Object)(object)image != (Object)null && (Object)(object)image.texture != (Object)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ItemIcon inspection " + ((object)(*(ItemIndex*)(&itemIndex))/*cast due to .constrained prefix*/).ToString() + ": Image components=" + componentsInChildren.Length + ", populated sprites=" + num + ", RawImage textures=" + num2 + ". This is diagnostic only; the game's icon pipeline may be asynchronous."));
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			instance = null;
			vanillaItemIconPrefab = null;
		}
	}
}