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 FasterStartup v1.0.0
plugins/FasterStartup.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using FasterStartup.Patcher; using HG; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using On.RoR2; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.ConVar; using RoR2.ContentManagement; using RoR2.UI.MainMenu; using UnityEngine; using UnityEngine.Rendering.PostProcessing; using UnityEngine.SceneManagement; [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("FasterStartup")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FasterStartup")] [assembly: AssemblyTitle("FasterStartup")] [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 FasterStartup { internal static class ContentPackTimer { internal sealed class Timing { public string identifier; public double loadDoneMs = -1.0; public double generateDoneMs = -1.0; public double finalizeDoneMs = -1.0; public double mainThreadMs; } private sealed class TimedProvider : IContentPackProvider { private readonly IContentPackProvider inner; private readonly Timing timing; public string identifier => inner.identifier; public TimedProvider(IContentPackProvider inner) { this.inner = inner; timing = new Timing { identifier = inner.identifier }; timings.Add(timing); } public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) { return new TimedCoroutine(inner.LoadStaticContentAsync(args), timing, delegate(double ms) { timing.loadDoneMs = ms; }); } public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) { return new TimedCoroutine(inner.GenerateContentPackAsync(args), timing, delegate(double ms) { timing.generateDoneMs = ms; }); } public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) { return new TimedCoroutine(inner.FinalizeAsync(args), timing, delegate(double ms) { timing.finalizeDoneMs = ms; }); } } private sealed class TimedCoroutine : IEnumerator { private readonly IEnumerator inner; private readonly Timing timing; private readonly Action<double> onDone; public object Current => inner?.Current; public TimedCoroutine(IEnumerator inner, Timing timing, Action<double> onDone) { this.inner = inner; this.timing = timing; this.onDone = onDone; } public bool MoveNext() { if (inner == null) { return false; } double totalMilliseconds = sinceStart.Elapsed.TotalMilliseconds; bool num = inner.MoveNext(); double totalMilliseconds2 = sinceStart.Elapsed.TotalMilliseconds; timing.mainThreadMs += totalMilliseconds2 - totalMilliseconds; if (!num) { onDone(totalMilliseconds2); } return num; } public void Reset() { inner?.Reset(); } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Manipulator <>9__5_0; internal void <Install>b__5_0(ILContext il) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown <>c__DisplayClass5_0 CS$<>8__locals2 = new <>c__DisplayClass5_0(); ILCursor val = new ILCursor(il); CS$<>8__locals2.loadContentPacks = typeof(ContentManager).GetMethod("LoadContentPacks"); if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)CS$<>8__locals2.loadContentPacks) })) { val.EmitDelegate<Action>((Action)WrapProviders); } else { FasterStartupPlugin.Log.LogDebug((object)"ContentManager.LoadContentPacks call not found; content packs won't be timed."); } } } [CompilerGenerated] private sealed class <>c__DisplayClass5_0 { public MethodInfo loadContentPacks; internal bool <Install>b__1(Instruction i) { return ILPatternMatchingExt.MatchCall(i, (MethodBase)loadContentPacks); } } internal static readonly List<Timing> timings = new List<Timing>(); private static readonly Stopwatch sinceStart = new Stopwatch(); private static FieldInfo collectField; private static ILHook hook; internal static void Install() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown collectField = typeof(ContentManager).GetField("collectContentPackProviders", BindingFlags.Static | BindingFlags.NonPublic); MethodBase methodBase = LoadPacer.FindMoveNext(typeof(RoR2Application), "<LoadGameContent>"); if (collectField == null || methodBase == null) { FasterStartupPlugin.Log.LogDebug((object)"Content loading code not found; content packs won't be timed."); return; } object obj = <>c.<>9__5_0; if (obj == null) { Manipulator val = delegate(ILContext il) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown ILCursor val2 = new ILCursor(il); MethodInfo loadContentPacks = typeof(ContentManager).GetMethod("LoadContentPacks"); if (val2.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)loadContentPacks) })) { val2.EmitDelegate<Action>((Action)WrapProviders); } else { FasterStartupPlugin.Log.LogDebug((object)"ContentManager.LoadContentPacks call not found; content packs won't be timed."); } }; <>c.<>9__5_0 = val; obj = (object)val; } hook = new ILHook(methodBase, (Manipulator)obj); } internal static void Uninstall() { ILHook obj = hook; if (obj != null) { obj.Dispose(); } hook = null; } private static void WrapProviders() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown try { CollectContentPackProvidersDelegate collect = default(CollectContentPackProvidersDelegate); ref CollectContentPackProvidersDelegate reference = ref collect; object? value = collectField.GetValue(null); reference = (CollectContentPackProvidersDelegate)((value is CollectContentPackProvidersDelegate) ? value : null); if (collect != null) { CollectContentPackProvidersDelegate value2 = (CollectContentPackProvidersDelegate)delegate(AddContentPackProviderDelegate addContentPackProvider) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown collect.Invoke((AddContentPackProviderDelegate)delegate(IContentPackProvider provider) { addContentPackProvider.Invoke((IContentPackProvider)(object)((provider == null) ? null : new TimedProvider(provider))); }); }; collectField.SetValue(null, value2); } sinceStart.Restart(); FasterStartupPlugin.Stage("starting content packs"); } catch (Exception arg) { FasterStartupPlugin.Log.LogDebug((object)$"Could not time content packs: {arg}"); } } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.elevated.FasterStartup", "FasterStartup", "1.0.0")] public class FasterStartupPlugin : BaseUnityPlugin { public const string PluginGUID = "com.elevated.FasterStartup"; public const string PluginName = "FasterStartup"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private static ConfigEntry<bool> unlockFrameRate; private static ConfigEntry<int> loadingFrameRateLimit; private static ConfigEntry<bool> changeLoadBudget; private static ConfigEntry<float> loadBudgetMs; private static ConfigEntry<bool> fastPostProcessingScan; private static ConfigEntry<bool> writeStartupReport; private bool timeline; private bool startupDone; private bool initializersDone; private int loadingFrames; public void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; unlockFrameRate = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "UnlockFrameRate", true, "Lift the frame rate limit and vsync while the game loads. Loading advances once per frame, and the game caps the loading screen at 60 FPS by default. Your own settings are restored at the main menu."); loadingFrameRateLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Loading", "LoadingFrameRateLimit", 0, new ConfigDescription("Frame rate limit while loading when UnlockFrameRate is on. 0 = unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>())); changeLoadBudget = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "ChangeLoadBudget", true, "Replace the game's per-frame loading budget (16 ms for content packs, 22 ms for catalogs) with LoadBudgetMs. The loader mostly waits on assets that only arrive between frames, so a short budget gets them in sooner."); loadBudgetMs = ((BaseUnityPlugin)this).Config.Bind<float>("Loading", "LoadBudgetMs", 2f, new ConfigDescription("How long the loader may run per frame, in milliseconds. Lower lets assets stream in faster; very low values slow down the CPU-heavy parts of loading.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); fastPostProcessingScan = ((BaseUnityPlugin)this).Config.Bind<bool>("Mod loading", "FastPostProcessingScan", true, "When the loading screen starts, the game looks for post-processing effects in every loaded assembly, including MMHOOK and every mod. With many mods that takes several seconds. Only scan the assemblies that can contain such effects; finds the same effects."); writeStartupReport = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "WriteStartupReport", true, "Write BepInEx/FasterStartup_Report.txt with how long each plugin and loading stage took. Needs the FasterStartup patcher (installed with this mod)."); if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { RiskOfOptionsCompat.Init(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), unlockFrameRate, loadingFrameRateLimit, changeLoadBudget, loadBudgetMs, fastPostProcessingScan, writeStartupReport); } if (unlockFrameRate.Value) { FramePacing.Begin(loadingFrameRateLimit.Value); } if (changeLoadBudget.Value) { LoadPacer.Install(loadBudgetMs.Value); } if (fastPostProcessingScan.Value) { PostProcessScan.Install(); } timeline = writeStartupReport.Value && StartupReport.TimelineAvailable; if (writeStartupReport.Value && !timeline) { Log.LogWarning((object)"The FasterStartup patcher isn't loaded, so no startup report will be written."); } if (timeline) { ContentPackTimer.Install(); StageMarks.Install(); } SceneManager.activeSceneChanged += OnActiveSceneChanged; ContentManager.onContentPacksAssigned += OnContentPacksAssigned; RoR2Application.onLoadFinished = (Action)Delegate.Combine(RoR2Application.onLoadFinished, new Action(OnLoadFinished)); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnLoad)); MainMenuController.OnMainMenuInitialised += OnMainMenuInitialised; Log.LogInfo((object)("Settings: " + SettingsSummary())); } public void OnDestroy() { SceneManager.activeSceneChanged -= OnActiveSceneChanged; ContentManager.onContentPacksAssigned -= OnContentPacksAssigned; RoR2Application.onLoadFinished = (Action)Delegate.Remove(RoR2Application.onLoadFinished, new Action(OnLoadFinished)); RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(OnLoad)); MainMenuController.OnMainMenuInitialised -= OnMainMenuInitialised; FramePacing.Restore(); LoadPacer.Uninstall(); ContentPackTimer.Uninstall(); PostProcessScan.Uninstall(); StageMarks.Uninstall(); } public void Update() { FramePacing.Tick(); if (!startupDone) { loadingFrames++; if (!initializersDone && SystemInitializerAttribute.hasExecuted) { initializersDone = true; Stage("system initializers (catalogs) finished"); } } } public void LateUpdate() { FramePacing.Tick(); } private static string SettingsSummary() { return $"UnlockFrameRate={unlockFrameRate.Value} (limit {loadingFrameRateLimit.Value}), " + $"ChangeLoadBudget={changeLoadBudget.Value} ({loadBudgetMs.Value} ms), FastPostProcessingScan={fastPostProcessingScan.Value}"; } internal static void Stage(string name) { Log.LogInfo((object)("Stage: " + name)); } private void OnActiveSceneChanged(Scene oldScene, Scene newScene) { if (!startupDone) { Stage("scene '" + ((Scene)(ref newScene)).name + "' active"); } } private static void OnContentPacksAssigned(ReadOnlyArray<ReadOnlyContentPack> contentPacks) { Stage($"content packs loaded ({contentPacks.Length} packs)"); } private static void OnLoadFinished() { Stage("game content, sound banks and assets loaded"); } private static void OnLoad() { Stage("startup finished (achievements, logbook, entity states, user profiles)"); } private void OnMainMenuInitialised() { if (startupDone) { return; } startupDone = true; Stage("main menu ready"); FramePacing.Restore(); if (!timeline) { return; } try { StartupReport.Write(loadingFrames, SettingsSummary()); } catch (Exception arg) { Log.LogError((object)$"Failed to write the startup report: {arg}"); } } } internal static class FramePacing { private const float RestoreTimeoutSeconds = 20f; private static bool active; private static int loadingFrameRate; private static int savedFrameRate; private static int savedVSyncCount; private static float loadFinishedTime = -1f; private static readonly List<Hook> convarHooks = new List<Hook>(); internal static bool IsActive => active; internal static void Begin(int frameRateDuringLoad) { loadingFrameRate = ((frameRateDuringLoad <= 0) ? (-1) : frameRateDuringLoad); savedFrameRate = Application.targetFrameRate; savedVSyncCount = QualitySettings.vSyncCount; active = true; HookConVar("FpsMaxConVar", "FpsMaxSetString"); HookConVar("VSyncCountConVar", "VSyncCountSetString"); Enforce(); } private static void HookConVar(string nestedTypeName, string handlerName) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown MethodInfo methodInfo = typeof(SettingsConVars).GetNestedType(nestedTypeName, BindingFlags.Public | BindingFlags.NonPublic)?.GetMethod("SetString", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (methodInfo == null) { FasterStartupPlugin.Log.LogWarning((object)("SettingsConVars." + nestedTypeName + " not found; relying on frame checks to remember the player's setting.")); } else { convarHooks.Add(new Hook((MethodBase)methodInfo, typeof(FramePacing).GetMethod(handlerName, BindingFlags.Static | BindingFlags.NonPublic))); } } private static void FpsMaxSetString(Action<BaseConVar, string> orig, BaseConVar self, string newValue) { orig(self, newValue); if (active) { savedFrameRate = Application.targetFrameRate; Application.targetFrameRate = loadingFrameRate; } } private static void VSyncCountSetString(Action<BaseConVar, string> orig, BaseConVar self, string newValue) { orig(self, newValue); if (active) { savedVSyncCount = QualitySettings.vSyncCount; QualitySettings.vSyncCount = 0; } } private static void UnhookConVars() { foreach (Hook convarHook in convarHooks) { convarHook.Dispose(); } convarHooks.Clear(); } internal static void Tick() { if (active) { if (ShouldRestore()) { Restore(); } else { Enforce(); } } } private static void Enforce() { if (Application.targetFrameRate != loadingFrameRate) { savedFrameRate = Application.targetFrameRate; Application.targetFrameRate = loadingFrameRate; } if (QualitySettings.vSyncCount != 0) { savedVSyncCount = QualitySettings.vSyncCount; QualitySettings.vSyncCount = 0; } } private static bool ShouldRestore() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (RoR2Application.IsMainMenuInitialized) { return true; } if (!RoR2Application.loadFinished) { return false; } if (loadFinishedTime < 0f) { loadFinishedTime = Time.unscaledTime; } Scene activeScene = SceneManager.GetActiveScene(); switch (((Scene)(ref activeScene)).name) { case "intro": case "lobby": case "logbook": return true; default: return Time.unscaledTime - loadFinishedTime > 20f; } } internal static void Restore() { if (active) { active = false; UnhookConVars(); Application.targetFrameRate = savedFrameRate; QualitySettings.vSyncCount = savedVSyncCount; FasterStartupPlugin.Log.LogInfo((object)$"Restored frame rate limit (fps_max {savedFrameRate}, vsync {savedVSyncCount})."); } } } internal static class LoadPacer { [CompilerGenerated] private static class <>O { public static Manipulator <0>__PatchContentBudget; public static Manipulator <1>__PatchInitializerBudget; } private static readonly List<ILHook> hooks = new List<ILHook>(); private static double budgetMs; private static int initializerSitesPatched; internal static void Install(double workBudgetMs) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown budgetMs = Math.Max(1.0, workBudgetMs); MethodBase methodBase = FindMoveNext(typeof(RoR2Application), "<LoadGameContent>"); if (methodBase != null) { List<ILHook> list = hooks; object obj = <>O.<0>__PatchContentBudget; if (obj == null) { Manipulator val = PatchContentBudget; <>O.<0>__PatchContentBudget = val; obj = (object)val; } list.Add(new ILHook(methodBase, (Manipulator)obj)); } else { FasterStartupPlugin.Log.LogWarning((object)"RoR2Application.LoadGameContent not found; content loading budget unchanged."); } List<MethodBase> list2 = new List<MethodBase>(); MethodBase methodBase2 = FindMoveNext(typeof(SystemInitializerAttribute), "<ExecuteCoroutine>"); if (methodBase2 != null) { list2.Add(methodBase2); } list2.AddRange(FindBepInExPackSystemInitializer()); foreach (MethodBase item in list2) { List<ILHook> list3 = hooks; object obj2 = <>O.<1>__PatchInitializerBudget; if (obj2 == null) { Manipulator val2 = PatchInitializerBudget; <>O.<1>__PatchInitializerBudget = val2; obj2 = (object)val2; } list3.Add(new ILHook(item, (Manipulator)obj2)); } if (initializerSitesPatched == 0) { FasterStartupPlugin.Log.LogWarning((object)"SystemInitializerAttribute frame budget not found; catalog initialization budget unchanged."); } } internal static void Uninstall() { foreach (ILHook hook in hooks) { hook.Dispose(); } hooks.Clear(); } internal static MethodBase FindMoveNext(Type declaringType, string iteratorNamePrefix) { return declaringType.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((Type t) => t.Name.StartsWith(iteratorNamePrefix, StringComparison.Ordinal))?.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } private static IEnumerable<MethodBase> FindBepInExPackSystemInitializer() { Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "RoR2BepInExPack")?.GetType("RoR2BepInExPack.VanillaFixes.FixSystemInitializer"); if (type == null) { yield break; } Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type2 in nestedTypes) { if (typeof(IEnumerator).IsAssignableFrom(type2)) { MethodInfo method = type2.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { yield return method; } } } } private static void PatchContentBudget(ILContext il) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown ILCursor val = new ILCursor(il); MethodInfo opLessThan = typeof(TimeSpan).GetMethod("op_LessThan", new Type[2] { typeof(TimeSpan), typeof(TimeSpan) }); int num = 0; while (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall(i, (MethodBase)opLessThan) })) { val.Remove(); val.EmitDelegate<Func<TimeSpan, TimeSpan, bool>>((Func<TimeSpan, TimeSpan, bool>)((TimeSpan elapsed, TimeSpan vanillaBudget) => elapsed.TotalMilliseconds < budgetMs)); num++; } LogPatch("content loading", il, num); } private static void PatchInitializerBudget(ILContext il) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown ILCursor val = new ILCursor(il); FieldInfo threshold = typeof(SystemInitializerAttribute).GetField("FRAME_TIME_THRESHOLD_MS", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); int num = 0; while (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchLdsfld(i, threshold) })) { val.Remove(); val.EmitDelegate<Func<long>>((Func<long>)(() => (long)budgetMs)); num++; } initializerSitesPatched += num; if (num > 0) { LogPatch("system initializers", il, num); } } private static void LogPatch(string what, ILContext il, int patched) { if (patched == 0) { FasterStartupPlugin.Log.LogWarning((object)("Could not find the frame budget check in " + ((MemberReference)il.Method).FullName + "; " + what + " budget unchanged.")); } else { FasterStartupPlugin.Log.LogDebug((object)$"Set {what} frame budget to {budgetMs} ms: {((MemberReference)il.Method).FullName} ({patched} site(s))."); } } } internal static class PostProcessScan { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<Instruction, bool> <>9__13_1; public static Manipulator <>9__13_0; internal void <Install>b__13_0(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ILCursor val = new ILCursor(il); MethodReference val2 = default(MethodReference); if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall(i, ref val2) && ((MemberReference)val2).Name == "GetAllTypesDerivedFrom" && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == typeof(RuntimeUtilities).FullName })) { val.Remove(); val.EmitDelegate<Func<IEnumerable<Type>>>((Func<IEnumerable<Type>>)FindEffectSettingsTypes); } else { FasterStartupPlugin.Log.LogWarning((object)"Post-processing type scan not found in PostProcessManager.ReloadBaseTypes; left unchanged."); } } internal bool <Install>b__13_1(Instruction i) { MethodReference val = default(MethodReference); if (ILPatternMatchingExt.MatchCall(i, ref val) && ((MemberReference)val).Name == "GetAllTypesDerivedFrom") { return ((MemberReference)((MemberReference)val).DeclaringType).FullName == typeof(RuntimeUtilities).FullName; } return false; } } private static ILHook hook; internal static int AssembliesScanned { get; private set; } internal static int AssembliesSkipped { get; private set; } internal static double ScanMs { get; private set; } internal static void Install() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown MethodInfo method = typeof(PostProcessManager).GetMethod("ReloadBaseTypes", BindingFlags.Instance | BindingFlags.NonPublic); if (method == null) { FasterStartupPlugin.Log.LogWarning((object)"PostProcessManager.ReloadBaseTypes not found; post-processing type scan unchanged."); return; } object obj = <>c.<>9__13_0; if (obj == null) { Manipulator val = delegate(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ILCursor val2 = new ILCursor(il); MethodReference val3 = default(MethodReference); if (val2.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall(i, ref val3) && ((MemberReference)val3).Name == "GetAllTypesDerivedFrom" && ((MemberReference)((MemberReference)val3).DeclaringType).FullName == typeof(RuntimeUtilities).FullName })) { val2.Remove(); val2.EmitDelegate<Func<IEnumerable<Type>>>((Func<IEnumerable<Type>>)FindEffectSettingsTypes); } else { FasterStartupPlugin.Log.LogWarning((object)"Post-processing type scan not found in PostProcessManager.ReloadBaseTypes; left unchanged."); } }; <>c.<>9__13_0 = val; obj = (object)val; } hook = new ILHook((MethodBase)method, (Manipulator)obj); } internal static void Uninstall() { ILHook obj = hook; if (obj != null) { obj.Dispose(); } hook = null; } private static IEnumerable<Type> FindEffectSettingsTypes() { Stopwatch stopwatch = Stopwatch.StartNew(); Type typeFromHandle = typeof(PostProcessEffectSettings); Assembly assembly = typeFromHandle.Assembly; string name = assembly.GetName().Name; List<Type> list = new List<Type>(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies) { if (assembly2 != assembly && (IsHookGenAssembly(assembly2) || !References(assembly2, name))) { AssembliesSkipped++; continue; } AssembliesScanned++; double totalMilliseconds = stopwatch.Elapsed.TotalMilliseconds; Type[] types = GetTypes(assembly2); double num = stopwatch.Elapsed.TotalMilliseconds - totalMilliseconds; if (num >= 50.0) { FasterStartupPlugin.Log.LogDebug((object)$"Post-processing scan: {assembly2.GetName().Name} took {num:0} ms ({types.Length} types)."); } Type[] array = types; foreach (Type type in array) { if (type != null && type.IsSubclassOf(typeFromHandle)) { list.Add(type); } } } ScanMs = stopwatch.Elapsed.TotalMilliseconds; FasterStartupPlugin.Log.LogDebug((object)($"Post-processing effects: found {list.Count} types in {AssembliesScanned} assemblies " + $"(skipped {AssembliesSkipped} that can't contain any) in {ScanMs:0} ms.")); return list; } private static bool IsHookGenAssembly(Assembly assembly) { return assembly.GetName().Name.StartsWith("MMHOOK_", StringComparison.Ordinal); } private static bool References(Assembly assembly, string assemblyName) { try { AssemblyName[] referencedAssemblies = assembly.GetReferencedAssemblies(); for (int i = 0; i < referencedAssemblies.Length; i++) { if (referencedAssemblies[i].Name == assemblyName) { return true; } } return false; } catch (Exception) { return true; } } private static Type[] GetTypes(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types ?? Array.Empty<Type>(); } catch (Exception) { return Array.Empty<Type>(); } } } internal static class RiskOfOptionsCompat { internal const string PluginGUID = "com.rune580.riskofoptions"; [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void Init(string pluginDirectory, ConfigEntry<bool> unlockFrameRate, ConfigEntry<int> loadingFrameRateLimit, ConfigEntry<bool> changeLoadBudget, ConfigEntry<float> loadBudgetMs, ConfigEntry<bool> fastPostProcessingScan, ConfigEntry<bool> writeStartupReport) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00ad: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00c2: 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_00d3: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0133: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Expected O, but got Unknown ModSettingsManager.SetModDescription("Makes the game (and your mods) load faster at startup. All settings only affect startup, so changes take effect the next time the game starts.", "com.elevated.FasterStartup", "Faster Startup"); Sprite val = LoadIcon(Path.Combine(pluginDirectory, "icon.png")); if (Object.op_Implicit((Object)(object)val)) { ModSettingsManager.SetModIcon(val, "com.elevated.FasterStartup", "Faster Startup"); } ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(unlockFrameRate, new CheckBoxConfig { restartRequired = true }), "com.elevated.FasterStartup", "Faster Startup"); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(loadingFrameRateLimit, new IntSliderConfig { min = 0, max = 1000, restartRequired = true, checkIfDisabled = (IsDisabledDelegate)(() => !unlockFrameRate.Value) }), "com.elevated.FasterStartup", "Faster Startup"); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(changeLoadBudget, new CheckBoxConfig { restartRequired = true }), "com.elevated.FasterStartup", "Faster Startup"); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(loadBudgetMs, new StepSliderConfig { min = 1f, max = 50f, increment = 1f, FormatString = "{0:0} ms", restartRequired = true, checkIfDisabled = (IsDisabledDelegate)(() => !changeLoadBudget.Value) }), "com.elevated.FasterStartup", "Faster Startup"); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(fastPostProcessingScan, new CheckBoxConfig { restartRequired = true }), "com.elevated.FasterStartup", "Faster Startup"); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(writeStartupReport, new CheckBoxConfig { restartRequired = true }), "com.elevated.FasterStartup", "Faster Startup"); } private static Sprite LoadIcon(string path) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(path)) { return null; } Texture2D val = new Texture2D(2, 2); if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path))) { return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } internal static class StageMarks { [CompilerGenerated] private static class <>O { public static hook_EnableBehaviours <0>__RoR2Application_EnableBehaviours; public static hook_Init <1>__WwiseIntegrationManager_Init; public static hook_Init <2>__PlatformSystems_Init; public static hook_Init <3>__RewiredIntegrationManager_Init; public static hook_Awake <4>__Console_Awake; public static hook_Init <5>__MusicController_Init; } internal static void Install() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0070: 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_007b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown object obj = <>O.<0>__RoR2Application_EnableBehaviours; if (obj == null) { hook_EnableBehaviours val = RoR2Application_EnableBehaviours; <>O.<0>__RoR2Application_EnableBehaviours = val; obj = (object)val; } RoR2Application.EnableBehaviours += (hook_EnableBehaviours)obj; object obj2 = <>O.<1>__WwiseIntegrationManager_Init; if (obj2 == null) { hook_Init val2 = WwiseIntegrationManager_Init; <>O.<1>__WwiseIntegrationManager_Init = val2; obj2 = (object)val2; } WwiseIntegrationManager.Init += (hook_Init)obj2; object obj3 = <>O.<2>__PlatformSystems_Init; if (obj3 == null) { hook_Init val3 = PlatformSystems_Init; <>O.<2>__PlatformSystems_Init = val3; obj3 = (object)val3; } PlatformSystems.Init += (hook_Init)obj3; object obj4 = <>O.<3>__RewiredIntegrationManager_Init; if (obj4 == null) { hook_Init val4 = RewiredIntegrationManager_Init; <>O.<3>__RewiredIntegrationManager_Init = val4; obj4 = (object)val4; } RewiredIntegrationManager.Init += (hook_Init)obj4; object obj5 = <>O.<4>__Console_Awake; if (obj5 == null) { hook_Awake val5 = Console_Awake; <>O.<4>__Console_Awake = val5; obj5 = (object)val5; } Console.Awake += (hook_Awake)obj5; object obj6 = <>O.<5>__MusicController_Init; if (obj6 == null) { hook_Init val6 = MusicController_Init; <>O.<5>__MusicController_Init = val6; obj6 = (object)val6; } MusicController.Init += (hook_Init)obj6; } internal static void Uninstall() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0070: 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_007b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown object obj = <>O.<0>__RoR2Application_EnableBehaviours; if (obj == null) { hook_EnableBehaviours val = RoR2Application_EnableBehaviours; <>O.<0>__RoR2Application_EnableBehaviours = val; obj = (object)val; } RoR2Application.EnableBehaviours -= (hook_EnableBehaviours)obj; object obj2 = <>O.<1>__WwiseIntegrationManager_Init; if (obj2 == null) { hook_Init val2 = WwiseIntegrationManager_Init; <>O.<1>__WwiseIntegrationManager_Init = val2; obj2 = (object)val2; } WwiseIntegrationManager.Init -= (hook_Init)obj2; object obj3 = <>O.<2>__PlatformSystems_Init; if (obj3 == null) { hook_Init val3 = PlatformSystems_Init; <>O.<2>__PlatformSystems_Init = val3; obj3 = (object)val3; } PlatformSystems.Init -= (hook_Init)obj3; object obj4 = <>O.<3>__RewiredIntegrationManager_Init; if (obj4 == null) { hook_Init val4 = RewiredIntegrationManager_Init; <>O.<3>__RewiredIntegrationManager_Init = val4; obj4 = (object)val4; } RewiredIntegrationManager.Init -= (hook_Init)obj4; object obj5 = <>O.<4>__Console_Awake; if (obj5 == null) { hook_Awake val5 = Console_Awake; <>O.<4>__Console_Awake = val5; obj5 = (object)val5; } Console.Awake -= (hook_Awake)obj5; object obj6 = <>O.<5>__MusicController_Init; if (obj6 == null) { hook_Init val6 = MusicController_Init; <>O.<5>__MusicController_Init = val6; obj6 = (object)val6; } MusicController.Init -= (hook_Init)obj6; } private static void Mark(string step, Action orig) { FasterStartupPlugin.Stage("starting " + step); orig(); } private static void RoR2Application_EnableBehaviours(orig_EnableBehaviours orig, RoR2Application self) { FasterStartupPlugin.Stage("starting startup behaviours"); Behaviour[] behavioursToEnableDuringStartup = self.BehavioursToEnableDuringStartup; if (behavioursToEnableDuringStartup == null) { orig.Invoke(self); return; } Stopwatch stopwatch = new Stopwatch(); for (int i = 0; i < behavioursToEnableDuringStartup.Length; i++) { stopwatch.Restart(); behavioursToEnableDuringStartup[i].enabled = true; double totalMilliseconds = stopwatch.Elapsed.TotalMilliseconds; if (totalMilliseconds >= 20.0) { FasterStartupPlugin.Log.LogInfo((object)$"Enabling {((object)behavioursToEnableDuringStartup[i]).GetType().FullName} on '{((Object)behavioursToEnableDuringStartup[i]).name}' took {totalMilliseconds:0} ms"); } } } private static void WwiseIntegrationManager_Init(orig_Init orig) { Mark("Wwise (audio)", delegate { orig.Invoke(); }); } private static void PlatformSystems_Init(orig_Init orig) { Mark("platform systems (Addressables ready)", delegate { orig.Invoke(); }); } private static void RewiredIntegrationManager_Init(orig_Init orig) { Mark("Rewired (input), after Steamworks", delegate { orig.Invoke(); }); } private static void Console_Awake(orig_Awake orig, Console self) { Mark("console (config, convars)", delegate { orig.Invoke(self); }); } private static void MusicController_Init(orig_Init orig) { Mark("music, shaders, splash (language loaded)", delegate { orig.Invoke(); }); } } internal static class StartupReport { private struct Span { public string name; public double startMs; public double durationMs; } internal const string StagePrefix = "Stage: "; internal static string ReportPath => Path.Combine(Paths.BepInExRootPath, "FasterStartup_Report.txt"); internal static bool TimelineAvailable { get { try { return IsTimelineRunning(); } catch (Exception) { return false; } } } [MethodImpl(MethodImplOptions.NoInlining)] private static bool IsTimelineRunning() { return StartupTimeline.IsRunning; } [MethodImpl(MethodImplOptions.NoInlining)] internal static double NowMs() { return StartupTimeline.NowMs; } [MethodImpl(MethodImplOptions.NoInlining)] internal static void Write(int loadingFrames, string settingsSummary) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) List<TimelineEntry> list = StartupTimeline.Stop(); if (list.Count == 0) { return; } double timeMs = list[list.Count - 1].timeMs; double timeMs2 = list[0].timeMs; double num = FindTime(list, "BepInEx", "Chainloader started") ?? timeMs2; double num2 = FindTime(list, "BepInEx", "Chainloader startup complete") ?? num; List<Span> source = PluginSpans(list, num2); List<Span> list2 = StageSpans(list, num2, timeMs); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"FasterStartup startup report ({DateTime.Now:yyyy-MM-dd HH:mm:ss})"); stringBuilder.AppendLine(settingsSummary); stringBuilder.AppendLine(); stringBuilder.AppendLine("Game start -> main menu: " + Seconds(timeMs)); stringBuilder.AppendLine(" Engine start: " + Seconds(timeMs2)); stringBuilder.AppendLine(" Preloader (patchers): " + Seconds(num - timeMs2)); stringBuilder.AppendLine(" Plugins (chainloader): " + Seconds(num2 - num)); stringBuilder.AppendLine(" Game loading: " + Seconds(timeMs - num2)); if (loadingFrames > 0) { stringBuilder.AppendLine($" Frames during game loading: {loadingFrames} (avg {(timeMs - num2) / (double)loadingFrames:0.0} ms)"); } stringBuilder.AppendLine(); stringBuilder.AppendLine("Game loading stages:"); foreach (Span item in list2) { stringBuilder.AppendLine($" {Seconds(item.startMs),9} {Seconds(item.durationMs),9} {item.name}"); } stringBuilder.AppendLine(); if (ContentPackTimer.timings.Count > 0) { stringBuilder.AppendLine("Content packs (when each step finished, counted from the start of content loading; and the main-thread"); stringBuilder.AppendLine("time spent in the pack's own code, not counting the assets it waits for). Slowest load first:"); stringBuilder.AppendLine(string.Format(" {0,9} {1,9} {2,9} {3,9} content pack", "loaded", "generated", "finalized", "own time")); foreach (ContentPackTimer.Timing item2 in ContentPackTimer.timings.OrderByDescending((ContentPackTimer.Timing t) => t.loadDoneMs)) { stringBuilder.AppendLine($" {Seconds(item2.loadDoneMs),9} {Seconds(item2.generateDoneMs),9} {Seconds(item2.finalizeDoneMs),9} {Seconds(item2.mainThreadMs),9} {item2.identifier}"); } stringBuilder.AppendLine(); } stringBuilder.AppendLine("Plugin load times (Awake), slowest first:"); foreach (Span item3 in source.OrderByDescending((Span p) => p.durationMs)) { stringBuilder.AppendLine($" {Seconds(item3.durationMs),9} {item3.name}"); } stringBuilder.AppendLine(); stringBuilder.AppendLine("Timeline (time since game start, time since previous line):"); double num3 = 0.0; foreach (TimelineEntry item4 in list) { string text = item4.message.Replace("\r", "").Replace("\n", "\n "); stringBuilder.AppendLine($"{item4.timeMs / 1000.0,9:0.000}s {item4.timeMs - num3,8:+0.0}ms [{item4.level,-7}:{item4.source,15}] {text}"); num3 = item4.timeMs; } File.WriteAllText(ReportPath, stringBuilder.ToString()); IEnumerable<string> values = from p in source.OrderByDescending((Span p) => p.durationMs).Take(3) select p.name + " " + Seconds(p.durationMs); FasterStartupPlugin.Log.LogMessage((object)("Startup took " + Seconds(timeMs) + ": engine " + Seconds(timeMs2) + ", preloader " + Seconds(num - timeMs2) + ", plugins " + Seconds(num2 - num) + ", game loading " + Seconds(timeMs - num2) + ". Slowest plugins: " + string.Join(", ", values) + ". Full report: " + ReportPath)); } private static string Seconds(double ms) { return $"{ms / 1000.0:0.00}s"; } private static double? FindTime(List<TimelineEntry> entries, string source, string messageStart) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) foreach (TimelineEntry entry in entries) { if (entry.source == source && entry.message.StartsWith(messageStart, StringComparison.Ordinal)) { return entry.timeMs; } } return null; } private static List<Span> PluginSpans(List<TimelineEntry> entries, double chainloaderEnd) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_0096: 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_0078: Unknown result type (might be due to invalid IL or missing references) List<Span> list = new List<Span>(); Span? span = null; foreach (TimelineEntry entry in entries) { if (entry.timeMs > chainloaderEnd) { break; } if (!(entry.source != "BepInEx")) { bool flag = entry.message.StartsWith("Loading [", StringComparison.Ordinal); if (span.HasValue && (flag || entry.message.StartsWith("TS Manifest", StringComparison.Ordinal) || entry.message.StartsWith("Chainloader startup complete", StringComparison.Ordinal))) { Span value = span.Value; value.durationMs = entry.timeMs - value.startMs; list.Add(value); span = null; } if (flag) { string name = entry.message.Substring("Loading [".Length).TrimEnd(']'); span = new Span { name = name, startMs = entry.timeMs }; } } } if (span.HasValue) { Span value2 = span.Value; value2.durationMs = chainloaderEnd - value2.startMs; list.Add(value2); } return list; } private static List<Span> StageSpans(List<TimelineEntry> entries, double chainloaderEnd, double endMs) { //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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) List<Span> list = new List<Span>(); double num = chainloaderEnd; foreach (TimelineEntry entry in entries) { if (entry.source == "FasterStartup" && entry.message.StartsWith("Stage: ", StringComparison.Ordinal)) { list.Add(new Span { name = "until " + entry.message.Substring("Stage: ".Length), startMs = num, durationMs = entry.timeMs - num }); num = entry.timeMs; } } return list; } } }
patchers/FasterStartup.Patcher.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; [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("FasterStartup.Patcher")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FasterStartup.Patcher")] [assembly: AssemblyTitle("FasterStartup.Patcher")] [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 FasterStartup.Patcher { public static class FasterStartupPatcher { public static IEnumerable<string> TargetDLLs { get; } = Array.Empty<string>(); public static void Initialize() { StartupTimeline.Start(); Logger.Listeners.Add((ILogListener)(object)new TimelineLogListener()); StartupTimeline.Mark("Preloader patchers initializing"); } public static void Patch(AssemblyDefinition assembly) { } public static void Finish() { StartupTimeline.Mark("Preloader patching finished"); } } public struct TimelineEntry { public double timeMs; public string source; public LogLevel level; public string message; } public static class StartupTimeline { private static double offsetMs; private static readonly Stopwatch stopwatch = new Stopwatch(); private static readonly object entriesLock = new object(); private static List<TimelineEntry> entries = new List<TimelineEntry>(8192); public static bool IsRunning => stopwatch.IsRunning; public static double NowMs => offsetMs + stopwatch.Elapsed.TotalMilliseconds; public static void Start() { if (stopwatch.IsRunning) { return; } try { offsetMs = (DateTime.Now - Process.GetCurrentProcess().StartTime).TotalMilliseconds; if (offsetMs < 0.0 || offsetMs > 600000.0) { offsetMs = 0.0; } } catch { offsetMs = 0.0; } stopwatch.Start(); } public static void Mark(string message) { Add("FasterStartup", (LogLevel)8, "== " + message); } internal static void Add(string source, LogLevel level, string message) { //IL_002b: 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) if (!stopwatch.IsRunning) { return; } TimelineEntry item = new TimelineEntry { timeMs = NowMs, source = source, level = level, message = message }; lock (entriesLock) { entries?.Add(item); } } public static List<TimelineEntry> Stop() { lock (entriesLock) { List<TimelineEntry> result = entries ?? new List<TimelineEntry>(); entries = null; return result; } } } internal sealed class TimelineLogListener : ILogListener, IDisposable { public void LogEvent(object sender, LogEventArgs eventArgs) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) ILogSource source = eventArgs.Source; StartupTimeline.Add(((source != null) ? source.SourceName : null) ?? "?", eventArgs.Level, eventArgs.Data?.ToString() ?? ""); } public void Dispose() { } } }