using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using UnityDebuggerAssistant.Components;
using UnityDebuggerAssistant.Filtering;
using UnityDebuggerAssistant.Patches;
using UnityDebuggerAssistant.Processing;
using UnityDebuggerAssistant.Utils;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("LethalCompanyModding")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A BepinEx plugin that captures Harmony and Monomod (wip) hook information at\r\n runtime to ease debugging")]
[assembly: AssemblyFileVersion("1.4.2.0")]
[assembly: AssemblyInformationalVersion("1.4.2+79a459d07838d68bc658c4def630236d2d21cdcd")]
[assembly: AssemblyProduct("UnityDebuggerAssistant")]
[assembly: AssemblyTitle("dev.mamallama.lcm.dbgasst")]
[assembly: AssemblyMetadata("RepositoryUrl", "gitgithub.com:RobynLlama/UnityDebuggerAssistant.git")]
[assembly: AssemblyVersion("1.4.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class IsReadOnlyAttribute : Attribute
{
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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;
}
}
}
[BepInPlugin("dev.mamallama.lcm.dbgasst", "UnityDebuggerAssistant", "1.4.2")]
public class UDAPlugin : BaseUnityPlugin
{
internal static ManualLogSource? Log;
internal static PluginConfiguration UDASettings;
private void Awake()
{
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Expected O, but got Unknown
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
UDASettings = new PluginConfiguration(((BaseUnityPlugin)this).Config);
UDABlacklist.UpdateLists_Internal();
StringBuilder stringBuilder = new StringBuilder("\r\n\r\n>------------------------------------------------------------------------<\r\n Unity Debugger assistant is loaded and receiving exceptions!\r\n\r\n Note: That UDA will catch ALL exceptions, even harmless ones\r\n Please ONLY report logs to modders if you have an issue with their mod\r\n\r\n Config:\r\n");
stringBuilder.Append(" Using Per-Exception Whitelist: ");
stringBuilder.AppendLine(UDASettings.EnableWhitelistPerException.Value.ToString());
stringBuilder.Append(" Using Per-Exception Blacklist: ");
stringBuilder.AppendLine(UDASettings.EnableBlacklistPerException.Value.ToString());
stringBuilder.Append(" Using Per-Frame Whitelist: ");
stringBuilder.AppendLine(UDASettings.EnableWhitelistPerFrame.Value.ToString());
stringBuilder.Append(" Using Per-Frame Blacklist: ");
stringBuilder.AppendLine(UDASettings.EnableBlacklistPerFrame.Value.ToString());
stringBuilder.Append(" Total Filters: ");
stringBuilder.AppendLine((UDABlacklist.ExceptionBlackList.Count() + UDABlacklist.FrameBlackList.Count()).ToString());
stringBuilder.AppendLine(">------------------------------------------------------------------------<");
Log.LogMessage((object)stringBuilder);
ILHook.OnDetour = (Func<ILHook, MethodBase, Manipulator, bool>)Delegate.Combine(ILHook.OnDetour, new Func<ILHook, MethodBase, Manipulator, bool>(UDAPatchListener.ListenForPatch));
Harmony val = new Harmony("dev.mamallama.lcm.dbgasst");
val.PatchAll(typeof(ExceptionConstructorPatch));
GameObject val2 = new GameObject("UDAMain", new Type[2]
{
typeof(UDAExceptionBroker),
typeof(UDAPostChainloadRunner)
})
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)(object)val2);
}
}
internal class PluginConfiguration
{
public readonly ConfigEntry<bool> EnableWhitelistPerException = Config.Bind<bool>(new ConfigDefinition("ExceptionFilter", "WhitelistEnabled"), true, new ConfigDescription("The per-exception whitelist filters out exceptions that do not originate from common game assemblies or BepinEx plugins.\nDisable this to catch everything. Will increase the log file size.", (AcceptableValueBase)null, Array.Empty<object>()));
public readonly ConfigEntry<bool> EnableWhitelistPerFrame = Config.Bind<bool>(new ConfigDefinition("FrameFilter", "WhitelistEnabled"), false, new ConfigDescription("The per-frame whitelist will remove frames inside of exceptions that do not originate from common game assemblies.\nEnable this to reduce log file size by cutting out less relevant frames", (AcceptableValueBase)null, Array.Empty<object>()));
public readonly ConfigEntry<bool> EnableBlacklistPerException = Config.Bind<bool>(new ConfigDefinition("ExceptionFilter", "BlacklistEnabled"), false, new ConfigDescription("The per-exception blacklist filters out exceptions that match the given patterns.\nThis is useful if you know a specific assembly throws errors you can ignore", (AcceptableValueBase)null, Array.Empty<object>()));
public readonly ConfigEntry<bool> EnableBlacklistPerFrame = Config.Bind<bool>(new ConfigDefinition("FrameFilter", "BlacklistEnabled"), false, new ConfigDescription("The per-frame blacklist filters out exceptions that match the given patterns.\nThis is useful if you know a specific assembly throws errors you can ignore", (AcceptableValueBase)null, Array.Empty<object>()));
public readonly ConfigEntry<string> ExceptionBlacklist = Config.Bind<string>(new ConfigDefinition("ExceptionFilter", "Blacklist"), "UniverseLib.Mono, UnityExplorer.", new ConfigDescription("A comma-separated list of assembly names to ignore in exception processing\nThis will be matched against the beginning of each assembly name so e.g. `UnityEngine.` will match all UnityEngine assemblies", (AcceptableValueBase)null, Array.Empty<object>()));
public readonly ConfigEntry<string> FrameBlacklist = Config.Bind<string>(new ConfigDefinition("FrameFilter", "Blacklist"), "mscorlib", new ConfigDescription("A comma-separated list of assembly names to ignore in individual frame processing\nThis will be matched against the beginning of each assembly name so e.g. `UnityEngine.` will match all UnityEngine assemblies", (AcceptableValueBase)null, Array.Empty<object>()));
public PluginConfiguration(ConfigFile Config)
{
}//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_0027: Expected O, but got Unknown
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_0053: Expected O, but got Unknown
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Expected O, but got Unknown
//IL_007f: Expected O, but got Unknown
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Expected O, but got Unknown
//IL_00ab: Expected O, but got Unknown
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Expected O, but got Unknown
//IL_00db: Expected O, but got Unknown
//IL_00ec: 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_010b: Expected O, but got Unknown
//IL_010b: Expected O, but got Unknown
}
internal static class LCMPluginInfo
{
public const string PLUGIN_GUID = "dev.mamallama.lcm.dbgasst";
public const string PLUGIN_NAME = "UnityDebuggerAssistant";
public const string PLUGIN_VERSION = "1.4.2";
}
namespace UnityDebuggerAssistant.Utils
{
internal static class Helpers
{
internal static Assembly GetAssemblyByName(string name)
{
string name2 = name;
return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => assembly.GetName().Name.Equals(name2, StringComparison.InvariantCultureIgnoreCase));
}
}
public static class UDAPatchListener
{
internal static bool ListenForPatch(ILHook hook, MethodBase @base, Manipulator manipulator)
{
if ((object)@base == null || manipulator == null || hook == null || ((Delegate)(object)manipulator).Target == null)
{
ManualLogSource? log = UDAPlugin.Log;
if (log != null)
{
log.LogInfo((object)"Skipping a null/empty patch");
}
return true;
}
UDAPatchStorage.AddPatchInformation(@base, ((Delegate)(object)manipulator).Target.GetType().Assembly);
return true;
}
}
internal static class UDAPatchStorage
{
private static readonly Dictionary<MethodBase, List<Assembly>> Patches = new Dictionary<MethodBase, List<Assembly>>();
private static readonly Assembly HarmonyAssembly = typeof(Harmony).Assembly;
internal static bool AddPatchInformation(MethodBase method, Assembly assembly)
{
if ((object)assembly == null || assembly == HarmonyAssembly)
{
return false;
}
if (!Patches.TryGetValue(method, out List<Assembly> value))
{
value = (Patches[method] = new List<Assembly>());
}
if (value.Contains(assembly))
{
return false;
}
value.Add(assembly);
ManualLogSource? log = UDAPlugin.Log;
if (log != null)
{
log.LogInfo((object)("blame " + assembly.GetName().Name + " for " + GeneralExtensions.FullDescription(method)));
}
return true;
}
internal static List<Assembly> GetPatchInformation(MethodBase method)
{
if (!Patches.TryGetValue(method, out List<Assembly> value))
{
return new List<Assembly>();
}
return value;
}
}
public static class UDAPluginMarshal
{
internal static readonly Dictionary<Assembly, PluginInfo> InfoCache = new Dictionary<Assembly, PluginInfo>();
public static void Run()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Dictionary<string, PluginInfo>.KeyCollection keys = Chainloader.PluginInfos.Keys;
foreach (string item in keys)
{
Assembly assembly = ((object)Chainloader.PluginInfos[item].Instance).GetType().Assembly;
PluginInfo val = Chainloader.PluginInfos[item];
if (val != null)
{
AddToInfoCache(assembly, val);
}
}
stopwatch.Stop();
ManualLogSource? log = UDAPlugin.Log;
if (log != null)
{
log.LogInfo((object)$"BepinEx Plugins Marshaled in {stopwatch.ElapsedMilliseconds}ms");
}
}
internal static bool AddToInfoCache(Assembly assembly, PluginInfo info)
{
if (InfoCache.ContainsKey(assembly))
{
return false;
}
InfoCache.Add(assembly, info);
return true;
}
}
}
namespace UnityDebuggerAssistant.Processing
{
public static class UDAExceptionHandler
{
public static void Handle(Exception ex)
{
int num = 0;
MethodBase targetSite = ex.TargetSite;
StackTrace stackTrace = new StackTrace(ex, fNeedFileInfo: true);
Assembly assembly2 = targetSite?.DeclaringType.Assembly;
bool flag = false;
if ((object)assembly2 == null)
{
flag = true;
_ = stackTrace.FrameCount;
StackFrame[] frames = stackTrace.GetFrames();
foreach (StackFrame stackFrame in frames)
{
if (stackFrame.HasMethod())
{
assembly2 = stackFrame.GetMethod().DeclaringType.Assembly;
break;
}
}
if ((object)assembly2 == null)
{
return;
}
}
if (!UDAWhitelist.IsOnExceptionWhitelist(assembly2) || UDABlacklist.IsOnExceptionBlacklist(assembly2))
{
return;
}
StringBuilder stringBuilder = new StringBuilder("\n\n--- Exception Handler ---\n\n");
stringBuilder.Append("Exception Caught: ");
stringBuilder.AppendLine(ex.GetType().ToString());
stringBuilder.Append("Assembly: ");
stringBuilder.Append(assembly2.GetName().Name);
if (flag)
{
stringBuilder.Append(" (Guess)");
}
stringBuilder.AppendLine();
if (UDAPluginMarshal.InfoCache.TryGetValue(assembly2, out PluginInfo value))
{
WritePluginInfo(stringBuilder, value, 1);
}
stringBuilder.Append("Message: ");
stringBuilder.AppendLine(ex.Message);
if (ex.Source != null)
{
stringBuilder.Append("Source: ");
stringBuilder.AppendLine(ex.Source);
}
stringBuilder.AppendLine();
stringBuilder.Append(Tabs(1));
stringBuilder.AppendLine("--- Begin Frames ---");
stringBuilder.AppendLine();
StackFrame[] frames2 = stackTrace.GetFrames();
foreach (StackFrame frame2 in frames2)
{
StringBuilder stringBuilder2 = new StringBuilder();
if (DumpFrame(stringBuilder2, frame2, 2))
{
stringBuilder.Append(Tabs(1));
stringBuilder.Append("--FRAME ");
num++;
stringBuilder.Append(num);
stringBuilder.AppendLine(":");
stringBuilder.Append(stringBuilder2.ToString());
}
}
stringBuilder.Append(Tabs(1));
stringBuilder.AppendLine("--- End Frames ---");
stringBuilder.AppendLine("\n--- End Exception Handler ---");
if (num > 0)
{
ManualLogSource? log = UDAPlugin.Log;
if (log != null)
{
log.LogError((object)stringBuilder);
}
}
static void DoHarmonyBlames(StringBuilder sb, ReadOnlyCollection<Patch>? Patches, int Indent)
{
if (Patches == null)
{
return;
}
foreach (Patch Patch in Patches)
{
DumpPatch(sb, Patch.PatchMethod.DeclaringType.Assembly, Indent);
}
}
static bool DumpFrame(StringBuilder sb, StackFrame frame, int Indent)
{
MethodBase method = frame.GetMethod();
int iLOffset = frame.GetILOffset();
bool result = false;
if ((object)method != null)
{
Assembly assembly3 = method.DeclaringType.Assembly;
if (UDAWhitelist.IsOnFrameWhitelist(assembly3) && !UDABlacklist.IsOnFrameBlacklist(assembly3))
{
result = true;
sb.Append(Tabs(Indent));
sb.Append("In Assembly: ");
sb.AppendLine(assembly3.GetName().Name);
if (frame.GetFileName() != null)
{
sb.Append(Tabs(Indent));
sb.Append("Source: ");
sb.Append(frame.GetFileName());
sb.Append(':');
sb.Append(frame.GetFileLineNumber());
sb.Append(',');
sb.AppendLine(frame.GetFileColumnNumber().ToString());
}
sb.Append(Tabs(Indent));
sb.Append("Target Method: ");
sb.Append(method.DeclaringType.Name);
sb.Append('.');
sb.AppendLine(method.Name);
sb.AppendLine();
List<Assembly> patchInformation = UDAPatchStorage.GetPatchInformation(method);
Patches patchInfo = Harmony.GetPatchInfo(method);
if (patchInformation.Count > 0 || patchInfo != null)
{
sb.Append(Tabs(Indent));
sb.AppendLine("Patched By:");
}
foreach (Assembly item in patchInformation)
{
DumpPatch(sb, item, Indent + 1);
}
if (patchInfo != null)
{
DoHarmonyBlames(sb, patchInfo.Prefixes, Indent + 1);
DoHarmonyBlames(sb, patchInfo.Postfixes, Indent + 1);
DoHarmonyBlames(sb, patchInfo.Finalizers, Indent + 1);
}
}
}
return result;
}
static void DumpPatch(StringBuilder sb, Assembly assembly, int Indent)
{
sb.Append(Tabs(Indent));
sb.AppendLine(assembly.GetName().Name);
if (UDAPluginMarshal.InfoCache.TryGetValue(assembly, out PluginInfo value2))
{
WritePluginInfo(sb, value2, Indent);
}
}
static string GetPluginDirSandboxed(PluginInfo info)
{
int num2 = info.Location.IndexOf($"{Path.DirectorySeparatorChar}plugins{Path.DirectorySeparatorChar}");
if (num2 < 0)
{
return "Unknown";
}
int length = info.Location.Length - num2;
return new string(info.Location.ToCharArray(), num2, length);
}
static string Tabs(int n)
{
return new string(' ', n * 2);
}
static void WritePluginInfo(StringBuilder sb, PluginInfo info, int Indent)
{
sb.AppendLine();
sb.Append(Tabs(Indent));
sb.AppendLine("Plugin Info");
sb.Append(Tabs(Indent + 1));
sb.Append("GUID: ");
sb.AppendLine(info.Metadata.GUID);
sb.Append(Tabs(Indent + 1));
sb.Append("NAME/VER: ");
sb.Append(info.Metadata.Name);
sb.Append("@");
sb.AppendLine(info.Metadata.Version.ToString());
sb.Append(Tabs(Indent + 1));
sb.Append("LOCATION: ");
sb.AppendLine(GetPluginDirSandboxed(info));
sb.AppendLine();
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void DebugThrow()
{
throw new Exception("Debug throw");
}
}
internal static class UDAExceptionProcessor
{
internal static readonly ConcurrentStack<Exception> Storage = new ConcurrentStack<Exception>();
internal static readonly int[] LastInExceptions = new int[10];
internal static int LastInPosition = 0;
private static bool OperationUnderway = false;
internal static void PushException(Exception ex)
{
int hashCode = ex.GetHashCode();
int[] lastInExceptions = LastInExceptions;
foreach (int num in lastInExceptions)
{
if (hashCode == num)
{
return;
}
}
LastInExceptions[LastInPosition] = hashCode;
LastInPosition++;
LastInPosition %= LastInExceptions.Length;
Storage.Push(ex);
}
internal static void Run(Exception __instance)
{
if (OperationUnderway)
{
ManualLogSource? log = UDAPlugin.Log;
if (log != null)
{
log.LogWarning((object)"Exception processor is busy");
}
return;
}
OperationUnderway = true;
try
{
UDAExceptionHandler.Handle(__instance);
}
catch (Exception ex)
{
ManualLogSource? log2 = UDAPlugin.Log;
if (log2 != null)
{
log2.LogError((object)"The exception handler failed while running. Please report the next line to Robyn:");
}
ManualLogSource? log3 = UDAPlugin.Log;
if (log3 != null)
{
log3.LogError((object)ex);
}
}
finally
{
OperationUnderway = false;
}
}
}
}
namespace UnityDebuggerAssistant.Patches
{
public static class ExceptionStackGetterPatch
{
private static bool LockRoot;
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPostfix]
internal static void ExceptionStackGot(Exception __instance)
{
if (!LockRoot)
{
LockRoot = true;
UDAExceptionProcessor.Run(__instance);
LockRoot = false;
}
}
}
[HarmonyPatch]
public static class ExceptionConstructorPatch
{
private static IEnumerable<MethodBase> TargetMethods()
{
return typeof(Exception).GetConstructors(BindingFlags.Instance | BindingFlags.Public);
}
private static void Postfix(Exception __instance)
{
UDAExceptionProcessor.PushException(__instance);
}
}
}
namespace UnityDebuggerAssistant.Filtering
{
internal static class UDABlacklist
{
internal static string[] ExceptionBlackList = Array.Empty<string>();
internal static string[] FrameBlackList = Array.Empty<string>();
internal static bool IsOnExceptionBlacklist(Assembly assembly)
{
if (!UDAPlugin.UDASettings.EnableBlacklistPerException.Value)
{
return false;
}
return IsOnList_Internal(assembly.GetName().Name, in ExceptionBlackList);
}
internal static bool IsOnFrameBlacklist(Assembly assembly)
{
if (!UDAPlugin.UDASettings.EnableBlacklistPerException.Value)
{
return false;
}
return IsOnList_Internal(assembly.GetName().Name, in FrameBlackList);
}
internal static bool IsOnList_Internal(string name, in string[] blacklist)
{
string[] array = blacklist;
foreach (string value in array)
{
if (name.StartsWith(value))
{
return true;
}
}
return false;
}
internal static void UpdateLists_Internal()
{
ExceptionBlackList = UDAPlugin.UDASettings.ExceptionBlacklist.Value.Split(new char[1] { ',' });
FrameBlackList = UDAPlugin.UDASettings.FrameBlacklist.Value.Split(new char[1] { ',' });
for (int i = 0; i < ExceptionBlackList.Length; i++)
{
ExceptionBlackList[i] = ExceptionBlackList[i].Trim();
}
for (int j = 0; j < FrameBlackList.Length; j++)
{
FrameBlackList[j] = FrameBlackList[j].Trim();
}
}
}
internal static class UDAWhitelist
{
internal static readonly List<Assembly> AssemblyWhiteList = new List<Assembly>(2)
{
Helpers.GetAssemblyByName("Assembly-CSharp"),
Helpers.GetAssemblyByName("MMHOOK_Assembly-CSharp")
};
internal static bool IsOnExceptionWhitelist(Assembly assembly)
{
return Whitelist(UDAPlugin.UDASettings.EnableWhitelistPerException.Value, assembly);
}
internal static bool IsOnFrameWhitelist(Assembly assembly)
{
return Whitelist(UDAPlugin.UDASettings.EnableWhitelistPerFrame.Value, assembly);
}
private static bool Whitelist(bool Setting, Assembly assembly)
{
if (UDAPluginMarshal.InfoCache.ContainsKey(assembly))
{
return true;
}
if (Setting)
{
if (Setting)
{
return AssemblyWhiteList.Contains(assembly);
}
return false;
}
return true;
}
}
}
namespace UnityDebuggerAssistant.Components
{
public class UDAExceptionBroker : MonoBehaviour
{
private readonly Exception[] popped = new Exception[3];
private void Awake()
{
ManualLogSource? log = UDAPlugin.Log;
if (log != null)
{
log.LogInfo((object)"UDAExceptionBroker active");
}
}
private void Update()
{
ConcurrentStack<Exception> storage = UDAExceptionProcessor.Storage;
int num = storage.TryPopRange(popped);
if (num > 0)
{
for (int i = 0; i < num; i++)
{
UDAExceptionProcessor.Run(popped[i]);
}
}
}
}
public class UDAPostChainloadRunner : MonoBehaviour
{
private void Start()
{
ManualLogSource? log = UDAPlugin.Log;
if (log != null)
{
log.LogInfo((object)"UDAPostChainloadRunner Starting");
}
UDAPluginMarshal.Run();
}
}
}