Decompiled source of ErrorAnalyzer v1.2.3

ErrorAnalyzer.dll

Decompiled a month 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.2.3.0")]
[module: UnverifiableCode]
namespace ErrorAnalyzer;

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

	public const string NAME = "ErrorAnalyzer";

	public const string VERSION = "1.2.3";

	public static ManualLogSource Log;

	public static bool isRegisitered;

	public static string errorString;

	public static string errorStackTrace;

	private static Harmony harmony;

	private static bool init;

	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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		harmony = new Harmony("aaa.dsp.plugin.ErrorAnalyzer");
		bool value = ((BaseUnityPlugin)this).Config.Bind<bool>("DEBUG Mode", "Enable", false, "Enable DEBUG mode to track the entity when starting up the game").Value;
		_ = ((BaseUnityPlugin)this).Config.Bind<bool>("Message", "Show All Patches", false, "Show all mod patches on the stacktrace (By default it will not list GameData.Gametick() and below methods)").Value;
		bool value2 = ((BaseUnityPlugin)this).Config.Bind<bool>("Message", "Dump All Patches", false, "Dump Harmony patches of all mods when the game load in BepInEx\\LogOutput.log").Value;
		if (Chainloader.PluginInfos.ContainsKey("dsp.nebula-multiplayer"))
		{
			Log.LogInfo((object)"Skip patching UIFatalErrorTip_Patch for Nebula is enabled");
		}
		else
		{
			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);
			}
		}
		try
		{
			harmony.PatchAll(typeof(StacktraceParser));
		}
		catch (Exception ex2)
		{
			Log.LogError((object)"Error when patching StacktraceParser");
			Log.LogError((object)ex2);
		}
		if (value)
		{
			TrackEntity_Patch.Enable(on: true);
		}
		if (value2)
		{
			harmony.PatchAll(typeof(Plugin));
		}
	}

	[HarmonyPostfix]
	[HarmonyPriority(0)]
	[HarmonyPatch(typeof(GameMain), "Begin")]
	private static void OnBegin()
	{
		if (!init)
		{
			init = true;
			StacktraceParser.GeneratePatchMap();
			StacktraceParser.DumpPatchMap();
		}
	}

	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");
		}
	}
}
public static class StacktraceParser
{
	private static bool IsChecked;

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

	public static bool ShowAllPatches { get; set; }

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

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIFatalErrorTip), "_OnOpen")]
	public static void OnOpen_Postfix(UIFatalErrorTip __instance)
	{
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		if (!IsChecked)
		{
			if (patchMap == null)
			{
				GeneratePatchMap();
			}
			List<string> callStackTypeNames = new List<string>();
			List<string> callStackMethodNames = new List<string>();
			ParseStackTraceLines(__instance.errorLogText.text, delegate(string typeName, string methodName)
			{
				callStackTypeNames.Add(typeName);
				callStackMethodNames.Add(methodName);
			});
			string resultString = GetResultString(callStackTypeNames, callStackMethodNames);
			Plugin.Log.LogInfo((object)resultString);
			Text errorLogText = __instance.errorLogText;
			errorLogText.text += resultString;
			__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;
		}
	}

	public static void DumpPatchMap()
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("DumpPatchMap type count: ").Append(patchMap.Keys.Count).AppendLine();
		foreach (KeyValuePair<string, List<MethodBase>> item in patchMap)
		{
			stringBuilder.Append("\n[Type: ").Append(item.Key).AppendLine("]");
			foreach (MethodBase item2 in item.Value)
			{
				stringBuilder.Append("-- ").Append(item.Key).Append(".")
					.Append(item2.Name)
					.AppendLine(" --");
				Patches patchInfo = PatchProcessor.GetPatchInfo(item2);
				PatchesToString(stringBuilder, "", "Prefix", patchInfo.Prefixes);
				PatchesToString(stringBuilder, "", "Postfix", patchInfo.Postfixes);
				PatchesToString(stringBuilder, "", "Transpiler", patchInfo.Transpilers);
				PatchesToString(stringBuilder, "", "Finalizer", patchInfo.Finalizers);
			}
		}
		Plugin.Log.LogInfo((object)stringBuilder.ToString());
	}

	public static void GeneratePatchMap()
	{
		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 count: " + patchMap.Count));
	}

	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(5, num2 - 5) : text.Substring(0, num2));
					string arg2 = text.Substring(num2 + 1, num - num2 - 2);
					validate(arg, arg2);
				}
			}
		}
	}

	private static string GetResultString(List<string> stackTypeNames, List<string> stackMethodNames)
	{
		if (stackTypeNames.Count == 0)
		{
			return "";
		}
		List<MethodBase> list = new List<MethodBase>();
		List<MethodBase> list2 = null;
		for (int i = 0; i < stackTypeNames.Count && (i == 0 || !(stackTypeNames[i] == "GameData") || !(stackMethodNames[i] == "GameTick") || ShowAllPatches); i++)
		{
			if (!patchMap.TryGetValue(stackTypeNames[i], out var value))
			{
				continue;
			}
			foreach (MethodBase item in value)
			{
				if (item.Name == stackMethodNames[i])
				{
					list.Add(item);
				}
			}
			if (i == 0)
			{
				list2 = value;
				Plugin.Log.LogInfo((object)(stackTypeNames[i] + " modified methods count = " + value.Count));
			}
		}
		StringBuilder stringBuilder = new StringBuilder();
		foreach (MethodBase item2 in list)
		{
			Patches patchInfo = PatchProcessor.GetPatchInfo(item2);
			PatchesToString(stringBuilder, item2.Name, "Prefix", patchInfo.Prefixes);
			PatchesToString(stringBuilder, item2.Name, "Postfix", patchInfo.Postfixes);
			PatchesToString(stringBuilder, item2.Name, "Transpiler", patchInfo.Transpilers);
			Plugin.Log.LogDebug((object)(item2.Name + " owners:" + patchInfo.Owners.Count));
		}
		string bepInexNamesFromTypeNames = GetBepInexNamesFromTypeNames(stackTypeNames);
		if (stringBuilder.Length > 0 || !string.IsNullOrEmpty(bepInexNamesFromTypeNames))
		{
			stringBuilder.Insert(0, "\n[== Mod patches on the stack ==]" + bepInexNamesFromTypeNames + "\n");
		}
		if (list2 != null && list2.Count > 0 && stackTypeNames[0] != "VFPreload" && stackTypeNames[0] != "GameData")
		{
			HashSet<string> hashSet = new HashSet<string>();
			stringBuilder.AppendLine("\n[== Mod patches to " + stackTypeNames[0] + " ==]");
			foreach (MethodBase item3 in list2)
			{
				Patches patchInfo2 = PatchProcessor.GetPatchInfo(item3);
				GetNames(hashSet, patchInfo2.Prefixes);
				GetNames(hashSet, patchInfo2.Postfixes);
				GetNames(hashSet, patchInfo2.Transpilers);
			}
			foreach (string item4 in hashSet)
			{
				stringBuilder.AppendLine(item4);
			}
		}
		return stringBuilder.ToString();
	}

	private static string GetBepInexNamesFromTypeNames(List<string> stackTypeNames)
	{
		HashSet<string> hashSet = new HashSet<string>();
		foreach (PluginInfo value in Chainloader.PluginInfos.Values)
		{
			hashSet.Add(value.Metadata.Name);
		}
		string text = "";
		foreach (string stackTypeName in stackTypeNames)
		{
			int num = stackTypeName.IndexOf('.');
			string text2 = ((num != -1) ? stackTypeName.Substring(0, num) : stackTypeName);
			if (hashSet.Contains(text2))
			{
				text = text + " " + text2;
				hashSet.Remove(text2);
			}
		}
		return text;
	}

	private static void GetNames(HashSet<string> modNameSpaces, ReadOnlyCollection<Patch> patches)
	{
		foreach (Patch patch in patches)
		{
			string fullName = patch.PatchMethod.DeclaringType.FullName;
			if (!string.IsNullOrEmpty(fullName))
			{
				modNameSpaces.Add(fullName);
			}
		}
	}

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

	private static bool IsWhitelist(string name, Patch patch)
	{
		return false;
	}
}
internal class TrackEntity_Patch
{
	private static Harmony _patch;

	public static bool Active => _patch != null;

	public static int AstroId { get; private set; }

	public static int EntityId { get; private set; }

	public static Vector3 LocalPos { get; private set; }

	public static void Enable(bool on)
	{
		AstroId = 0;
		EntityId = 0;
		if (on)
		{
			if (_patch == null)
			{
				_patch = Harmony.CreateAndPatchAll(typeof(TrackEntity_Patch), (string)null);
			}
			Plugin.Log.LogInfo((object)"TrackEntity_Patch enable");
			return;
		}
		Harmony patch = _patch;
		if (patch != null)
		{
			patch.UnpatchSelf();
		}
		_patch = null;
		Plugin.Log.LogInfo((object)"TrackEntity_Patch disable");
	}

	public static void ResetId()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		AstroId = 0;
		EntityId = 0;
		LocalPos = Vector3.zero;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(UIEntityBriefInfo), "_OnOpen")]
	private static void UIEntityBriefInfo_OnOpen(UIEntityBriefInfo __instance)
	{
		__instance.entityIdText.text = __instance.entityId.ToString();
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(FactorySystem), "GameTick", new Type[]
	{
		typeof(long),
		typeof(bool),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	[HarmonyPatch(typeof(FactorySystem), "GameTickLabProduceMode", new Type[]
	{
		typeof(long),
		typeof(bool),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	[HarmonyPatch(typeof(FactorySystem), "GameTickLabResearchMode", new Type[]
	{
		typeof(long),
		typeof(bool)
	})]
	[HarmonyPatch(typeof(FactorySystem), "GameTickInserters", new Type[]
	{
		typeof(long),
		typeof(bool),
		typeof(int),
		typeof(int)
	})]
	[HarmonyPatch(typeof(PowerSystem), "GameTick")]
	[HarmonyPatch(typeof(CargoTraffic), "SpraycoaterGameTick")]
	[HarmonyPatch(typeof(CargoTraffic), "PresentCargoPathsAsync")]
	[HarmonyPatch(typeof(DefenseSystem), "GameTick")]
	[HarmonyPatch(typeof(ConstructionSystem), "GameTick")]
	private static Exception GetFactoryId(Exception __exception, PlanetFactory ___factory)
	{
		if (__exception != null && AstroId == 0)
		{
			AstroId = ___factory.planet.astroId;
		}
		return __exception;
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(MinerComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(AssemblerComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(FractionatorComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(FractionatorComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(EjectorComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(SiloComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(LabComponent), "InternalUpdateAssemble")]
	[HarmonyPatch(typeof(LabComponent), "InternalUpdateResearch")]
	[HarmonyPatch(typeof(InserterComponent), "InternalOffsetCorrection")]
	[HarmonyPatch(typeof(SpraycoaterComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(TurretComponent), "InternalUpdate")]
	private static Exception GetEntityId(Exception __exception, int ___entityId)
	{
		if (__exception != null && EntityId == 0)
		{
			EntityId = ___entityId;
		}
		return __exception;
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(InserterComponent), "InternalUpdate_Bidirectional")]
	[HarmonyPatch(typeof(InserterComponent), "InternalUpdate")]
	[HarmonyPatch(typeof(InserterComponent), "InternalUpdateNoAnim")]
	[HarmonyPatch(typeof(DispenserComponent), "InternalTick")]
	private static Exception GetInserterId(Exception __exception, int ___entityId, PlanetFactory factory)
	{
		if (__exception != null)
		{
			if (AstroId == 0)
			{
				AstroId = factory.planet.astroId;
			}
			if (EntityId == 0)
			{
				EntityId = ___entityId;
			}
		}
		return __exception;
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(StationComponent), "DetermineDispatch")]
	[HarmonyPatch(typeof(StationComponent), "InternalTickLocal")]
	[HarmonyPatch(typeof(StationComponent), "InternalTickRemote")]
	private static Exception GetStationId(Exception __exception, int ___entityId, int ___planetId)
	{
		if (__exception != null)
		{
			if (AstroId == 0)
			{
				AstroId = ___planetId;
			}
			if (EntityId == 0)
			{
				EntityId = ___entityId;
			}
		}
		return __exception;
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(CargoPath), "PresentCargos")]
	private static Exception GetCargoPathPos(Exception __exception, Vector3[] ___pointPos)
	{
		//IL_0003: 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_0016: Unknown result type (might be due to invalid IL or missing references)
		if (__exception != null && LocalPos == Vector3.zero)
		{
			LocalPos = ___pointPos[0];
		}
		return __exception;
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(CargoTraffic), "SetBeltState")]
	private static Exception SetBeltState()
	{
		return null;
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(CargoContainer), "RemoveCargo")]
	private static Exception RemoveCargo()
	{
		return null;
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(CargoTraffic), "PickupBeltItems")]
	private static Exception PickupBeltItems()
	{
		return null;
	}
}
[HarmonyPatch(typeof(UIFatalErrorTip))]
internal class UIFatalErrorTip_Patch
{
	private static UIButton btnClose;

	private static UIButton btnCopy;

	private static UIButton btnInspect;

	private static bool waitingToRefresh;

	private static int astroId;

	private static int entityId;

	private static Vector3 localPos;

	[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);
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch("ShowError")]
	private static void ShowError_Prefix(UIFatalErrorTip __instance)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(__instance.errorLogText.text) || waitingToRefresh)
		{
			astroId = TrackEntity_Patch.AstroId;
			entityId = TrackEntity_Patch.EntityId;
			localPos = TrackEntity_Patch.LocalPos;
		}
		if (waitingToRefresh)
		{
			waitingToRefresh = false;
			UIFatalErrorTip.ClearError();
			TryNavigate();
		}
	}

	[HarmonyPostfix]
	[HarmonyPriority(200)]
	[HarmonyPatch("_OnOpen")]
	private static void OnOpen_Postfix(UIFatalErrorTip __instance)
	{
		if (!((Object)(object)btnClose != (Object)null) && !((Object)(object)btnCopy != (Object)null) && !((Object)(object)btnInspect != (Object)null))
		{
			TryCreateButton(delegate
			{
				CreateCloseBtn(__instance);
			}, "Close Button");
			TryCreateButton(delegate
			{
				CreateCopyBtn(__instance);
			}, "Copy Button");
			TryCreateButton(delegate
			{
				CreateInspectBtn(__instance);
			}, "Inspect Button");
			((Component)((Component)__instance).transform.Find("tip-text-0")).GetComponent<Text>().text = Title();
			((Component)((Component)__instance).transform.Find("tip-text-1")).GetComponent<Text>().text = Title();
			Object.Destroy((Object)(object)((Component)((Component)__instance).transform.Find("tip-text-0")).GetComponent<Localizer>());
			Object.Destroy((Object)(object)((Component)((Component)__instance).transform.Find("tip-text-1")).GetComponent<Localizer>());
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch("_OnClose")]
	private static void OnClose_Postfix()
	{
		if ((Object)(object)btnClose != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)btnClose).gameObject);
			btnClose = null;
		}
		if ((Object)(object)btnCopy != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)btnCopy).gameObject);
			btnCopy = null;
		}
		if ((Object)(object)btnInspect != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)btnInspect).gameObject);
			btnInspect = null;
		}
		TrackEntity_Patch.ResetId();
	}

	private static void TryCreateButton(Action createAction, string buttonName)
	{
		try
		{
			createAction();
		}
		catch (Exception arg)
		{
			Plugin.Log.LogWarning((object)$"{buttonName} did not patch!\n{arg}");
		}
	}

	private static UIButton CreateButton(string path, Transform parent, Vector3 positionOffset, Action<int> onClickAction)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		return CreateButton(GameObject.Find(path), parent, positionOffset, onClickAction);
	}

	private static UIButton CreateButton(GameObject originalGo, Transform parent, Vector3 positionOffset, Action<int> onClickAction)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)originalGo != (Object)null)
		{
			GameObject obj = Object.Instantiate<GameObject>(originalGo, parent);
			RectTransform val = (RectTransform)obj.transform;
			val.anchorMin = Vector2.up;
			val.anchorMax = Vector2.up;
			val.pivot = Vector2.up;
			val.anchoredPosition = Vector2.op_Implicit(positionOffset);
			obj.SetActive(true);
			UIButton component = obj.GetComponent<UIButton>();
			component.onClick += onClickAction;
			component.tips.corner = 1;
			return component;
		}
		return null;
	}

	private static void CreateCloseBtn(UIFatalErrorTip __instance)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)btnClose != (Object)null))
		{
			btnClose = CreateButton("UI Root/Overlay Canvas/In Game/Windows/Window Template/panel-bg/btn-box/close-btn", ((Component)__instance).transform, new Vector3(-5f, 0f, 0f), OnCloseClick);
		}
	}

	private static void CreateCopyBtn(UIFatalErrorTip __instance)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)btnCopy != (Object)null))
		{
			btnCopy = CreateButton("UI Root/Overlay Canvas/In Game/Windows/Dyson Sphere Editor/Dyson Editor Control Panel/hierarchy/layers/blueprint-group/blueprint-2/copy-button", ((Component)__instance).transform, new Vector3(5f, -55f, 0f), OnCopyClick);
			btnCopy.tips.tipTitle = "Copy Error";
			btnCopy.tips.tipText = "Copy the message to clipboard";
		}
	}

	private static void CreateInspectBtn(UIFatalErrorTip __instance)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)btnInspect != (Object)null) && GameMain.mainPlayer != null)
		{
			btnInspect = CreateButton(((Component)UIRoot.instance.uiGame.researchQueue.pauseButton).gameObject, ((Component)__instance).transform, new Vector3(20f, -80f, 0f), OnInspectClick);
			((Component)((Component)btnInspect).transform.Find("icon")).GetComponent<Image>().sprite = ((Component)((Component)UIRoot.instance.uiGame.starmap.cursorFunctionButton2).transform.Find("icon")).GetComponent<Image>().sprite;
			((Component)btnInspect).transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
			btnInspect.onRightClick += ToggleTrackMode;
			btnInspect.tips.tipTitle = "Find The Error Entity";
			btnInspect.tips.tipText = "Left click to navigate\nRight click to toggle tracking mode";
			if (astroId > 0 && astroId % 100 != 0)
			{
				string arg = GameMain.galaxy.PlanetById(astroId).displayName ?? "";
				btnInspect.tips.tipText += $"\nentity: {entityId} at [{astroId}] {arg}";
			}
			SetInsepctButton();
		}
	}

	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 OnCopyClick(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();
		UIRealtimeTip.Popup("Error message copied!", false, 0);
	}

	public static void OnCloseClick(int _)
	{
		waitingToRefresh = false;
		UIFatalErrorTip.ClearError();
	}

	private static void OnInspectClick(int _)
	{
		if (astroId <= 0)
		{
			if (!TrackEntity_Patch.Active)
			{
				waitingToRefresh = true;
				ToggleTrackMode(0);
			}
		}
		else
		{
			TryNavigate();
		}
	}

	internal static void TryNavigate()
	{
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: 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)
		if (astroId <= 0 || GameMain.mainPlayer == null)
		{
			return;
		}
		if (astroId % 100 != 0 && GameMain.data.localPlanet?.id == astroId)
		{
			PlanetFactory factory = GameMain.data.localPlanet.factory;
			if (entityId >= factory.entityPool.Length)
			{
				UIRealtimeTip.Popup($"EntityId {entityId} exceed Pool length {factory.entityPool.Length}!", true, 0);
				return;
			}
			localPos = ((entityId > 0) ? factory.entityPool[entityId].pos : localPos);
			UIRoot.instance.uiGame.globemap.MoveToViewTargetTwoStep(localPos, ((Vector3)(ref localPos)).magnitude - GameMain.data.localPlanet.realRadius);
			GameMain.data.mainPlayer.Order(OrderNode.MoveTo(localPos), false);
		}
		else
		{
			GameMain.mainPlayer.navigation.indicatorAstroId = astroId;
		}
	}

	private static void ToggleTrackMode(int _)
	{
		try
		{
			TrackEntity_Patch.Enable(!TrackEntity_Patch.Active);
			SetInsepctButton();
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Can't enable tracking!\n" + ex));
		}
	}

	private static void SetInsepctButton()
	{
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)btnInspect == (Object)null) && btnInspect.transitions.Length != 0)
		{
			btnInspect.CloseTip();
			if (TrackEntity_Patch.Active)
			{
				btnInspect.tips.tipTitle = "Find The Error Entity (ON)";
				btnInspect.transitions[0].normalColor = new Color(0.7f, 0.7f, 0.3f, 0.4f);
				btnInspect.transitions[0].mouseoverColor = new Color(0.7f, 0.7f, 0.3f, 0.5f);
			}
			else
			{
				btnInspect.tips.tipTitle = "Find The Error Entity (OFF)";
				btnInspect.transitions[0].normalColor = new Color(0.2392f, 0.6f, 0.9f, 0.078f);
				btnInspect.transitions[0].mouseoverColor = new Color(0.2392f, 0.6f, 0.9f, 0.178f);
			}
		}
	}
}