Decompiled source of ErrorAnalyzer v1.1.0

ErrorAnalyzer.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ErrorAnalyzer")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
namespace ErrorAnalyzer;

[BepInPlugin("aaa.dsp.plugin.ErrorAnalyzer", "ErrorAnalyzer", "1.1.0")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "aaa.dsp.plugin.ErrorAnalyzer";

	public const string NAME = "ErrorAnalyzer";

	public const string VERSION = "1.1.0";

	public static ManualLogSource Log;

	public static bool isRegisitered;

	public static string errorString;

	public static string errorStackTrace;

	private static Harmony harmony;

	public void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Expected O, but got Unknown
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		harmony = new Harmony("aaa.dsp.plugin.ErrorAnalyzer");
		if (!Chainloader.PluginInfos.TryGetValue("dsp.nebula-multiplayer", out var value))
		{
			try
			{
				harmony.PatchAll(typeof(UIFatalErrorTip_Patch));
				Application.logMessageReceived += new LogCallback(HandleLog);
				isRegisitered = true;
			}
			catch (Exception ex)
			{
				Log.LogError((object)"Error when patching UIFatalErrorTip_Patch");
				Log.LogError((object)ex);
			}
		}
		if (!Chainloader.PluginInfos.TryGetValue("NebulaCompatibilityAssist", out value))
		{
			try
			{
				harmony.PatchAll(typeof(StacktraceParser));
			}
			catch (Exception ex2)
			{
				Log.LogError((object)"Error when patching StacktraceParser");
				Log.LogError((object)ex2);
			}
		}
	}

	public void OnDestroy()
	{
		harmony.UnpatchSelf();
		harmony = null;
	}

	public static void HandleLog(string logString, string stackTrace, LogType type)
	{
		if (string.IsNullOrEmpty(errorString) && logString.IndexOf("Exception") > 0)
		{
			errorString = logString;
			errorStackTrace = stackTrace;
			Log.LogDebug((object)"Exception Record");
		}
	}
}
internal class StacktraceParser
{
	private static bool IsChecked;

	private static Dictionary<string, List<MethodBase>> patchMap;

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIFatalErrorTip), "_OnClose")]
	public static void OnClose_Postfix()
	{
		IsChecked = false;
		patchMap = null;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIFatalErrorTip), "_OnOpen")]
	public static void OnOpen_Postfix(UIFatalErrorTip __instance)
	{
		//IL_00fe: 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_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		if (IsChecked)
		{
			return;
		}
		if (patchMap == null)
		{
			patchMap = new Dictionary<string, List<MethodBase>>();
			foreach (MethodBase allPatchedMethod in PatchProcessor.GetAllPatchedMethods())
			{
				string fullName = allPatchedMethod.DeclaringType.FullName;
				if (!patchMap.TryGetValue(fullName, out var value))
				{
					value = new List<MethodBase>();
					patchMap[fullName] = value;
				}
				value.Add(allPatchedMethod);
			}
			Plugin.Log.LogDebug((object)("Patched type: " + patchMap.Count));
		}
		List<MethodBase> modifiedMethods = new List<MethodBase>();
		ParseStackTraceLines(__instance.errorLogText.text, delegate(string typeName, string methodName)
		{
			if (patchMap.TryGetValue(typeName, out var value2))
			{
				foreach (MethodBase item in value2)
				{
					if (item.Name == methodName)
					{
						modifiedMethods.Add(item);
					}
				}
			}
		});
		Text errorLogText = __instance.errorLogText;
		errorLogText.text += GetResultString(modifiedMethods);
		__instance.rectTrans.sizeDelta = new Vector2(__instance.rectTrans.sizeDelta.x, __instance.errorLogText.preferredHeight + 45f);
		((Graphic)__instance.errorLogText).rectTransform.sizeDelta = new Vector2(((Graphic)__instance.errorLogText).rectTransform.sizeDelta.x, __instance.errorLogText.preferredHeight + 2f);
		IsChecked = true;
	}

	private static void ParseStackTraceLines(string source, Action<string, string> validate)
	{
		string[] array = source.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			int num = text.IndexOf('(');
			if (num != -1)
			{
				int num2 = text.LastIndexOf('.', num);
				if (num2 != -1 && num - num2 - 2 > 0)
				{
					string arg = ((!text.StartsWith("  at ")) ? text.Substring(0, num2) : text.Substring(5, num2 - 5));
					string arg2 = text.Substring(num2 + 1, num - num2 - 2);
					validate(arg, arg2);
				}
			}
		}
	}

	private static string GetResultString(List<MethodBase> modifiedMethods)
	{
		StringBuilder stringBuilder = new StringBuilder();
		foreach (MethodBase modifiedMethod in modifiedMethods)
		{
			Patches patchInfo = PatchProcessor.GetPatchInfo(modifiedMethod);
			PatchesToString(stringBuilder, modifiedMethod.Name, "Prefix", patchInfo.Prefixes);
			PatchesToString(stringBuilder, modifiedMethod.Name, "Postfix", patchInfo.Postfixes);
			PatchesToString(stringBuilder, modifiedMethod.Name, "Transpiler", patchInfo.Transpilers);
			Plugin.Log.LogDebug((object)(modifiedMethod.Name + " owners:" + patchInfo.Owners.Count));
		}
		if (stringBuilder.Length > 0)
		{
			stringBuilder.Insert(0, "\n== Mod patches on the stack ==\n");
		}
		return stringBuilder.ToString();
	}

	private static void PatchesToString(StringBuilder sb, string name, string prefix, ReadOnlyCollection<Patch> patches)
	{
		foreach (Patch patch in patches)
		{
			if (!IsWhitelist(name, patch))
			{
				sb.Append(name).Append("(").Append(prefix)
					.Append("): ");
				if (prefix != "Transpiler")
				{
					sb.AppendLine(GeneralExtensions.FullDescription((MethodBase)patch.PatchMethod));
				}
				else
				{
					sb.AppendLine(GeneralExtensions.FullDescription((MethodBase)patch.PatchMethod).Replace("System.Collections.Generic.IEnumerable<HarmonyLib.CodeInstruction>", "var").Replace("System.Reflection.Emit.ILGenerator", "var"));
				}
			}
		}
	}

	private static bool IsWhitelist(string name, Patch patch)
	{
		return false;
	}
}
[HarmonyPatch(typeof(UIFatalErrorTip))]
internal class UIFatalErrorTip_Patch
{
	private static GameObject button1;

	[HarmonyPostfix]
	[HarmonyPatch("_OnRegEvent")]
	private static void _OnRegEvent_Postfix()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		if (!Plugin.isRegisitered)
		{
			return;
		}
		Plugin.isRegisitered = false;
		try
		{
			Application.logMessageReceived -= new LogCallback(Plugin.HandleLog);
			if (!string.IsNullOrEmpty(Plugin.errorString))
			{
				UIFatalErrorTip.instance.ShowError(Plugin.errorString, Plugin.errorStackTrace);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch("_OnOpen")]
	private static void _OnOpen_Postfix()
	{
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)button1 == (Object)null)
			{
				GameObject val = GameObject.Find("UI Root/Overlay Canvas/Fatal Error/errored-panel/");
				((Component)val.transform.Find("tip-text-0")).GetComponent<Text>().text = Title();
				Object.Destroy((Object)(object)((Component)val.transform.Find("tip-text-0")).GetComponent<Localizer>());
				((Component)val.transform.Find("tip-text-1")).GetComponent<Text>().text = Title();
				Object.Destroy((Object)(object)((Component)val.transform.Find("tip-text-1")).GetComponent<Localizer>());
				button1 = GameObject.Find("UI Root/Overlay Canvas/In Game/Windows/Dyson Sphere Editor/Dyson Editor Control Panel/hierarchy/layers/blueprint-group/blueprint-2/copy-button");
				button1 = Object.Instantiate<GameObject>(button1, val.transform);
				((Object)button1).name = "Copy button";
				button1.transform.localPosition = val.transform.Find("icon").localPosition + new Vector3(30f, -35f, 0f);
				((Graphic)button1.GetComponent<Image>()).color = new Color(0.6f, 0.1f, 0.1f, 0.6f);
				button1.GetComponent<UIButton>().BindOnClickSafe((Action<int>)OnClick1);
				ref TipSettings tips = ref button1.GetComponent<UIButton>().tips;
				tips.tipTitle = "Copy Error";
				tips.tipText = "Copy the message to clipboard and close error.";
				tips.corner = 1;
			}
		}
		catch (Exception arg)
		{
			Plugin.Log.LogWarning((object)$"UIFatalErrorTip button did not patch! {arg}");
		}
	}

	private static string Title()
	{
		//IL_0013: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("An error has occurred! Game version ");
		Version gameVersion = GameConfig.gameVersion;
		stringBuilder.Append(((object)(Version)(ref gameVersion)).ToString());
		stringBuilder.Append('.');
		stringBuilder.Append(GameConfig.gameVersion.Build);
		stringBuilder.AppendLine();
		stringBuilder.Append(Chainloader.PluginInfos.Values.Count + " Mods used: ");
		foreach (PluginInfo value in Chainloader.PluginInfos.Values)
		{
			stringBuilder.Append('[');
			stringBuilder.Append(value.Metadata.Name);
			stringBuilder.Append(value.Metadata.Version);
			stringBuilder.Append("] ");
		}
		return stringBuilder.ToString();
	}

	private static void OnClick1(int id)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine("```ini");
		stringBuilder.AppendLine(Title());
		string[] array = UIFatalErrorTip.instance.errorLogText.text.Split('\n', '\r');
		foreach (string text in array)
		{
			if (!string.IsNullOrEmpty(text))
			{
				int num = text.LastIndexOf(" <", StringComparison.Ordinal);
				int num2 = text.LastIndexOf(">:", StringComparison.Ordinal);
				if (num != -1 && num2 > num)
				{
					stringBuilder.AppendLine(text.Remove(num, num2 - num + 2));
				}
				else
				{
					stringBuilder.AppendLine(text);
				}
			}
		}
		stringBuilder.Replace(" (at", ";(");
		stringBuilder.Replace(" inIL_", " ;IL_");
		stringBuilder.AppendLine("```");
		GUIUtility.systemCopyBuffer = stringBuilder.ToString();
		UIFatalErrorTip.ClearError();
		Object.Destroy((Object)(object)button1);
		button1 = null;
	}
}