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 Loadstone v0.1.24
com.adibtw.loadstone.dll
Decompiled 2 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DunGen; using DunGen.Adapters; using DunGen.Graph; using DunGen.Tags; using HarmonyLib; using HarmonyLib.Public.Patching; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LethalExpansionCore.Patches; using Loadstone.Config; using Loadstone.Patches; using Loadstone.Patches.ExpansionCore; using Microsoft.CodeAnalysis; using Unity.AI.Navigation; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("BepInEx")] [assembly: AssemblyCompany("com.adibtw.loadstone")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Reduces stuttering during level loading")] [assembly: AssemblyFileVersion("0.1.23.0")] [assembly: AssemblyInformationalVersion("0.1.23+f51ce6fed97a84b69768623a481c0ee7c9c9ce84")] [assembly: AssemblyProduct("Loadstone")] [assembly: AssemblyTitle("com.adibtw.loadstone")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.23.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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; } } } namespace Loadstone { [BepInPlugin("com.adibtw.loadstone", "Loadstone", "0.1.23")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Loadstone : BaseUnityPlugin { private static ManualLogSource CurrentLog; private static ManualLogSource HarmonyLog; private static ManualLogSource TranspilerLog; private void Awake() { ((BaseUnityPlugin)this).Logger.LogDebug((object)"Loading Loadstone..."); HarmonyLog = Logger.CreateLogSource(" Loadstone(Harmony)"); TranspilerLog = Logger.CreateLogSource(" Loadstone(Transpiler)"); CurrentLog = TranspilerLog; ((BaseUnityPlugin)this).Logger.LogDebug((object)"Loading Configs..."); LoadstoneConfig.BindAllTo(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Logger.LogDebug((object)"Patching Methods..."); if (LoadstoneConfig.StatusChangeFix.Value) { ConflictResolver.TryPatch(typeof(StatusChangedFixer)); if (LoadstoneConfig.AsyncDungeon.Value) { ConflictResolver.TryPatch(typeof(AsyncDungeonPatches)); if (LoadstoneConfig.DungeonRealization.Value) { ConflictResolver.TryPatch(typeof(FromProxyPatches)); } } } if (LoadstoneConfig.AsyncNavmesh.Value) { ConflictResolver.TryPatch(typeof(NavmeshPatches)); } ConflictResolver.TryPatch(typeof(ScreenDarkenPatches)); ConflictResolver.TryPatch(typeof(ObjectFindPatches)); ConflictResolver.TryPatch(typeof(RoundManagerMusicPatches)); if (LoadstoneConfig.DunGenOptimizations.Value) { ConflictResolver.TryPatch(typeof(DungenOptimizationPatches)); } if (LoadstoneConfig.LocalPerformanceReports.Value) { ConflictResolver.TryPatch(typeof(PerformanceReportPatches)); } CheckModded(); CurrentLog = HarmonyLog; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Loadstone is loaded!"); } private void Start() { ConflictResolver.CheckUnknownPatches(); } private void CheckModded() { OptionalModPatcher(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loadstone modded compat is loaded!"); } private void OptionalModPatcher() { foreach (string key in Chainloader.PluginInfos.Keys) { if (!(key == "com.github.lethalmods.lethalexpansioncore")) { if (key == "ainavt.lc.lethalconfig") { LoadstoneDynamicConfig.RegisterDynamicConfig(); } } else { PatchExpansionCore(); } } } private void PatchExpansionCore() { ((BaseUnityPlugin)this).Logger.LogDebug((object)"Patching ExpansionCore"); ConflictResolver.TryPatch(typeof(DungeonGenerator_PatchPatches)); } public static bool IsNightly() { return false; } internal static void Log(LogLevel level, object data) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) CurrentLog.Log(level, data); } internal static void LogDebug(object data) { CurrentLog.LogDebug(data); } internal static void LogError(object data) { CurrentLog.LogError(data); } internal static void LogFatal(object data) { CurrentLog.LogFatal(data); } internal static void LogInfo(object data) { CurrentLog.LogInfo(data); } internal static void LogMessage(object data) { CurrentLog.LogMessage(data); } internal static void LogWarning(object data) { CurrentLog.LogWarning(data); } } public static class PluginInfo { public const string PLUGIN_GUID = "com.adibtw.loadstone"; public const string PLUGIN_NAME = "Loadstone"; public const string PLUGIN_VERSION = "0.1.23"; } } namespace Loadstone.Patches { public class AsyncDungeonPatches { [HarmonyPatch(typeof(DungeonGenerator), "ShouldSkipFrame")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ShouldSkipFrameTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown Loadstone.LogDebug("Attempting to inject modified frame skip transpiler into DungeonGenerator::ShouldSkipFrame"); IEnumerable<CodeInstruction> result = new CodeMatcher(instructions, (ILGenerator)null).Start().InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(DungeonGenerator), "yieldTimer")), new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.DeclaredMethod(typeof(Stopwatch), "Start", (Type[])null, (Type[])null)) }).MatchForward(false, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.DeclaredMethod(typeof(Stopwatch), "Restart", (Type[])null, (Type[])null), (string)null) }) .Advance(2) .SetOperandAndAdvance((object)AccessTools.DeclaredMethod(typeof(Stopwatch), "Reset", (Type[])null, (Type[])null)) .InstructionEnumeration(); Loadstone.LogDebug("Validating injected frame skip transpiler into DungeonGenerator::ShouldSkipFrame"); return result; } [HarmonyPatch(typeof(DungeonGenerator), "Generate")] [HarmonyPrefix] private static void GenerateNewFloorPatch(DungeonGenerator __instance) { if (LoadstoneConfig.AsyncDungeonBlacklist.Value.Split(",").ToList().Contains(((Object)__instance.DungeonFlow).name)) { Loadstone.LogInfo("This dungeon flow is blacklisted, not forcing Async Dungeon for this landing"); return; } __instance.GenerateAsynchronously = LoadstoneConfig.AsyncDungeon.Value; __instance.PauseBetweenRooms = 0f; __instance.MaxAsyncFrameMilliseconds = LoadstoneConfig.DungeonAsyncMaxTime.Value; } } public static class ConflictResolver { private static Harmony HarmonyInstance; private static bool HasOurs; static ConflictResolver() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown HarmonyInstance = new Harmony("com.adibtw.loadstone"); } public static void CheckUnknownPatches() { foreach (MethodBase method in PatchManager.GetPatchedMethods()) { PatchInfo patchInfo = PatchManager.GetPatchInfo(method); patchInfo.transpilers.Where((Patch patch) => !IsPatchOurs(patch, method)).ToList().ForEach(delegate(Patch patch) { WarnPatch(patch, method, "transpiler"); }); HasOurs = false; patchInfo.ilmanipulators.Where((Patch patch) => !IsPatchOurs(patch, method)).ToList().ForEach(delegate(Patch patch) { WarnPatch(patch, method, "IL manipulator"); }); HasOurs = false; patchInfo.prefixes.Where((Patch patch) => !IsPatchOurs(patch, method)).ToList().ForEach(delegate(Patch patch) { WarnPatch(patch, method, "prefix"); }); HasOurs = false; patchInfo.postfixes.Where((Patch patch) => !IsPatchOurs(patch, method)).ToList().ForEach(delegate(Patch patch) { WarnPatch(patch, method, "postfix"); }); HasOurs = false; patchInfo.finalizers.Where((Patch patch) => !IsPatchOurs(patch, method)).ToList().ForEach(delegate(Patch patch) { WarnPatch(patch, method, "finalizer"); }); HasOurs = false; } } public static bool IsPatchOurs(Patch patch, MethodBase method) { string name = patch.GetMethod(method).DeclaringType.Assembly.GetName().Name; HasOurs = HasOurs || name == "com.adibtw.loadstone"; return name == "com.adibtw.loadstone"; } public static void WarnPatch(Patch patch, MethodBase method, string patchType) { if (HasOurs) { Loadstone.LogWarning("The assembly \"" + patch.GetMethod(method).DeclaringType.Assembly.GetName().Name + "\" has patched the method \"" + method.ToString() + "\" with a " + patchType + " using \"" + patch.GetMethod(method).ToString() + "\", which we also modify. Unexpected behaviour may occur"); } } public static void TryPatch(Type type) { try { HarmonyInstance.CreateClassProcessor(type, true).Patch(); } catch (Exception ex) { Loadstone.LogFatal($"Loadstone failed to patch {type}. The following exception was received:\n{ex.ToString()}"); } } } public class DungenOptimizationPatches { internal static Dictionary<TagContainer, Dictionary<TagContainer, bool>> DungeonTagMatchTemp = null; internal static Dictionary<DungeonFlow, Dictionary<TagContainer, Dictionary<TagContainer, bool>>> TagMatchDictionary = new Dictionary<DungeonFlow, Dictionary<TagContainer, Dictionary<TagContainer, bool>>>(); public static List<Func<DungeonGenerator, bool>> cacheValidators = new List<Func<DungeonGenerator, bool>> { delegate(DungeonGenerator generator) { DungeonFlow dungeonFlow2 = generator.DungeonFlow; if (!TagMatchDictionary.ContainsKey(dungeonFlow2)) { return false; } if (!TagMatchDictionary[dungeonFlow2].Values.Any((Dictionary<TagContainer, bool> tag) => tag == null)) { return true; } Loadstone.LogWarning("At least one tag container in " + ((Object)dungeonFlow2).name + " has been deleted since the flow was last cached! The cache will be fully recalculated as a result"); return false; } }; public static List<Func<DungeonGenerator, HashSet<Tile>>> tileCollectors = new List<Func<DungeonGenerator, HashSet<Tile>>> { delegate(DungeonGenerator generator) { DungeonFlow dungeonFlow = generator.DungeonFlow; HashSet<Tile> tiles = new HashSet<Tile>(); foreach (GraphNode node in dungeonFlow.Nodes) { GenerateTileHashSet(ref tiles, node.TileSets); } foreach (GraphLine line in dungeonFlow.Lines) { foreach (DungeonArchetype dungeonArchetype in line.DungeonArchetypes) { GenerateTileHashSet(ref tiles, dungeonArchetype.TileSets); GenerateTileHashSet(ref tiles, dungeonArchetype.BranchCapTileSets); } } return tiles; } }; [HarmonyPatch(typeof(DungeonFlow), "HasMatchingTagPair")] [HarmonyPrefix] private static bool HasMatchingTagPairEarlyOut(DungeonFlow __instance, Tile tileA, Tile tileB, ref bool __result) { if (tileA.Tags.Tags.Count == 0 || tileB.Tags.Tags.Count == 0) { __result = false; return false; } try { __result = DungeonTagMatchTemp[tileA.Tags][tileB.Tags]; } catch (KeyNotFoundException) { Loadstone.LogWarning("Tag pair for \"" + ((Object)tileA).name + "\" and \"" + ((Object)tileB).name + "\" was not found in the tag cache! This pair is now being cached, which will cause a small performance penalty"); if (!TagMatchDictionary.ContainsKey(__instance)) { TagMatchDictionary[__instance] = new Dictionary<TagContainer, Dictionary<TagContainer, bool>>(); DungeonTagMatchTemp = TagMatchDictionary[__instance]; } if (!DungeonTagMatchTemp.ContainsKey(tileA.Tags)) { DungeonTagMatchTemp[tileA.Tags] = new Dictionary<TagContainer, bool>(); } if (!DungeonTagMatchTemp.ContainsKey(tileB.Tags)) { DungeonTagMatchTemp[tileB.Tags] = new Dictionary<TagContainer, bool>(); } __result = HasMatchingTagPairOriginal(__instance, tileA, tileB); DungeonTagMatchTemp[tileA.Tags][tileB.Tags] = __result; DungeonTagMatchTemp[tileB.Tags][tileA.Tags] = HasMatchingTagPairOriginal(__instance, tileB, tileA); } return false; } [HarmonyPatch(typeof(DungeonFlow), "HasMatchingTagPair")] [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] private static bool HasMatchingTagPairOriginal(DungeonFlow flow, Tile tileA, Tile tileB) { throw new NotImplementedException("Reverse Patch Stub"); } private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<TileSet> tileSets) { foreach (TileSet tileSet in tileSets) { foreach (GameObjectChance weight in tileSet.TileWeights.Weights) { Tile component = weight.Value.GetComponent<Tile>(); if (!((Object)(object)component == (Object)null)) { tiles.Add(component); } } } } private static Dictionary<TagContainer, Dictionary<TagContainer, bool>> TileConnectionTagOptimization(HashSet<Tile> tiles, DungeonFlow flow) { Dictionary<TagContainer, Dictionary<TagContainer, bool>> dictionary = new Dictionary<TagContainer, Dictionary<TagContainer, bool>>(); foreach (Tile tile in tiles) { Dictionary<TagContainer, bool> dictionary2 = new Dictionary<TagContainer, bool>(); foreach (Tile tile2 in tiles) { dictionary2.Add(tile2.Tags, HasMatchingTagPairOriginal(flow, tile, tile2)); } dictionary.Add(tile.Tags, dictionary2); } return dictionary; } [HarmonyPriority(100)] [HarmonyPatch(typeof(DungeonGenerator), "Generate")] [HarmonyPrefix] private static void TagPrecalcPatch(DungeonGenerator __instance) { DungeonFlow dungeonFlow = __instance.DungeonFlow; if (!Object.op_Implicit((Object)(object)dungeonFlow)) { Loadstone.LogWarning("The dungeon generator's flow is null or deleted!"); } else if (!cacheValidators.All((Func<DungeonGenerator, bool> v) => v(__instance))) { HashSet<Tile> tiles = new HashSet<Tile>(); tileCollectors.ForEach(delegate(Func<DungeonGenerator, HashSet<Tile>> collector) { tiles.UnionWith(collector(__instance)); }); TagMatchDictionary.Add(dungeonFlow, TileConnectionTagOptimization(tiles, dungeonFlow)); DungeonTagMatchTemp = TagMatchDictionary[dungeonFlow]; } } } public class FromProxyPatches { public static bool ConversionComplete; [HarmonyPatch(typeof(Dungeon), "FromProxy")] [HarmonyPrefix] private static bool FromProxyPre(Dungeon __instance, DungeonProxy proxyDungeon, DungeonGenerator generator) { Loadstone.LogInfo("Setting ConversionComplete false"); ConversionComplete = false; ((MonoBehaviour)__instance).StartCoroutine(FromProxyEnumerator(generator, proxyDungeon, __instance)); return false; } private static IEnumerator FromProxyEnumerator(DungeonGenerator generator, DungeonProxy proxyDungeon, Dungeon __instance) { __instance.Clear(); Dictionary<TileProxy, Tile> dictionary = new Dictionary<TileProxy, Tile>(); MethodInfo shouldSkip = typeof(DungeonGenerator).GetMethod("ShouldSkipFrame", BindingFlags.Instance | BindingFlags.NonPublic); foreach (TileProxy allTile in proxyDungeon.AllTiles) { FromProxyIteration(__instance, dictionary, generator, allTile); if ((bool)shouldSkip.Invoke(generator, new object[1] { false })) { yield return null; } } FromProxyEnd(__instance, proxyDungeon, generator, dictionary); Loadstone.LogInfo("Setting ConversionComplete true"); ConversionComplete = true; } [HarmonyPatch(typeof(Dungeon), "FromProxy")] [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] private static void FromProxyIteration(Dungeon __instance, Dictionary<TileProxy, Tile> dictionary, DungeonGenerator generator, TileProxy tile) { StartTranspiler(null, null); static IEnumerable<CodeInstruction> StartTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown Loadstone.LogDebug("Attempting to reverse-patch Dungeon::FromProxy's first inner for loop"); CodeMatcher val = new CodeMatcher(instructions, generator); int pos = val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Br, (object)null, (string)null) }).Advance(4).Pos; val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_3, (object)null), new CodeInstruction(OpCodes.Stloc_2, (object)null), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Stloc_0, (object)null) }); int pos2 = val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Endfinally, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldloca_S, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)null, (string)null) }).Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Ret, (object)null) }) .Pos; Label label = default(Label); val.CreateLabel(ref label); val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Leave, (object)null, (string)null) }).Advance(1).SetOperandAndAdvance((object)label); IEnumerable<CodeInstruction> result = val.InstructionsInRange(pos, pos2).AsEnumerable(); Loadstone.LogDebug("Validating reverse-patched Dungeon::FromProxy's first inner for loop"); return result; } } [HarmonyPatch(typeof(Dungeon), "FromProxy")] [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] private static void FromProxyEnd(Dungeon __instance, DungeonProxy proxyDungeon, DungeonGenerator generator, Dictionary<TileProxy, Tile> dictionary) { EndTranspiler(null); static IEnumerable<CodeInstruction> EndTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown Loadstone.LogDebug("Attempting to reverse-patch Dungeon::FromProxy's final code"); CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); int pos = val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Endfinally, (object)null, (string)null) }).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldarg_1, (object)null, (string)null) }).Pos; val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_3, (object)null), new CodeInstruction(OpCodes.Stloc_0, (object)null), new CodeInstruction(OpCodes.Ldtoken, (object)typeof(GameObject)), new CodeInstruction(OpCodes.Pop, (object)null) }); int pos2 = val.End().Pos; List<CodeInstruction> source = val.InstructionsInRange(pos, pos2); Loadstone.LogDebug("Validating reverse-patched Dungeon::FromProxy's final code"); return source.AsEnumerable(); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> PostProcessPatch(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Expected O, but got Unknown //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Expected O, but got Unknown //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Expected O, but got Unknown //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Expected O, but got Unknown Loadstone.LogDebug("Attempting to inject async check into DungeonGenerator::PostProcess"); Type[] array = new Type[1] { typeof(Func<bool>) }; Type[] array2 = new Type[2] { typeof(object), typeof(IntPtr) }; CodeMatcher val = new CodeMatcher(instructions, ilGenerator).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Switch, (object)null, (string)null) }); List<Label> list = (val.InstructionAt(0).operand as Label[]).ToList(); int count = list.Count; val.Advance(3); object operand = val.InstructionAt(0).operand; if (operand == null) { Loadstone.LogFatal("Leave instruction did not have an operand! Cannot inject a wait for FromProxy! The dungeon *will* be corrupt"); throw new ArgumentNullException("leaveObject is null. Cannot inject functioning code"); } Label label = (Label)operand; FieldInfo fieldInfo = (FieldInfo)val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldnull, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Stfld, (object)null, (string)null) }).InstructionAt(0).operand; FieldInfo fieldInfo2 = (FieldInfo)val.InstructionAt(3).operand; Label item = default(Label); val.Start().MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Switch, (object)null, (string)null) }).Advance(7) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[12] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldloc_2, (object)null), new CodeInstruction(OpCodes.Ldftn, (object)AccessTools.Method(typeof(FromProxyPatches), "ConversionCheck", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Newobj, (object)AccessTools.Constructor(typeof(Func<bool>), array2, false)), new CodeInstruction(OpCodes.Newobj, (object)AccessTools.Constructor(typeof(WaitUntil), array, false)), new CodeInstruction(OpCodes.Stfld, (object)fieldInfo), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldc_I4_S, (object)count), new CodeInstruction(OpCodes.Stfld, (object)fieldInfo2), new CodeInstruction(OpCodes.Ldc_I4_1, (object)null), new CodeInstruction(OpCodes.Stloc_0, (object)null), new CodeInstruction(OpCodes.Leave, (object)label) }) .CreateLabel(ref item); list.Add(item); val.Start().MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Switch, (object)null, (string)null) }).SetOperandAndAdvance((object)list.ToArray()); IEnumerable<CodeInstruction> result = val.InstructionEnumeration(); Loadstone.LogDebug("Validating injected async check into DungeonGenerator::PostProcess"); return result; } private static bool ConversionCheck() { Loadstone.LogInfo($"ConversionComplete checked, returning {ConversionComplete}"); return ConversionComplete; } } public class NavmeshPatches { [HarmonyPatch(typeof(RoundManager), "SpawnOutsideHazards")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> SpawnOutsideHazardsPatch(IEnumerable<CodeInstruction> instructions) { //IL_000c: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown Loadstone.LogDebug("Writing SpawnOutsideHazards Transpiler"); IEnumerable<CodeInstruction> result = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(GameObject), "GetComponent", (Type[])null, new Type[1] { typeof(NavMeshSurface) }), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Ldarg_0, (object)null) }) .Set(OpCodes.Call, (object)AccessTools.Method(typeof(NavmeshPatches), "GenerateNavMeshAsync", new Type[2] { typeof(NavMeshSurface), typeof(RoundManager) }, (Type[])null)) .InstructionEnumeration(); Loadstone.LogDebug("Verifying SpawnOutsideHazards Transpiler"); return result; } [HarmonyPatch(typeof(UnityNavMeshAdapter), "BakeFullDungeon")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> BakeFullDungeonPatch(IEnumerable<CodeInstruction> instructions) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown Loadstone.LogDebug("Writing UnityNavMeshAdapter Transpiler"); IEnumerable<CodeInstruction> result = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.DeclaredMethod(typeof(NavMeshSurface), "BuildNavMesh", (Type[])null, (Type[])null), (string)null) }).Repeat((Action<CodeMatcher>)delegate(CodeMatcher matcher) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown matcher.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Ldarg_0, (object)null) }).SetOperandAndAdvance((object)AccessTools.DeclaredMethod(typeof(NavmeshPatches), "GenerateNavMeshAsync", (Type[])null, (Type[])null)); }, (Action<string>)null).InstructionEnumeration(); Loadstone.LogDebug("Verifying UnityNavMeshAdapter Transpiler"); return result; } private static void GenerateNavMeshAsync(NavMeshSurface navMeshSurface, MonoBehaviour coroutineHijack) { //IL_002b: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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) List<NavMeshBuildSource> list = (List<NavMeshBuildSource>)typeof(NavMeshSurface).GetMethod("CollectSources", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(navMeshSurface, new object[0]); Bounds val = default(Bounds); ((Bounds)(ref val))..ctor(navMeshSurface.center, navMeshSurface.size); if ((int)navMeshSurface.collectObjects != 1) { val = (Bounds)typeof(NavMeshSurface).GetMethod("CalculateWorldBounds", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(navMeshSurface, new object[1] { list }); } Loadstone.LogDebug($"Updating navmesh with {list.Count} obstacles"); NavMeshBuildSettings buildSettings = navMeshSurface.GetBuildSettings(); if ((Object)(object)navMeshSurface.navMeshData != (Object)null) { navMeshSurface.navMeshData.position = ((Component)navMeshSurface).transform.position; navMeshSurface.navMeshData.rotation = ((Component)navMeshSurface).transform.rotation; } else { navMeshSurface.navMeshData = new NavMeshData(((NavMeshBuildSettings)(ref buildSettings)).agentTypeID) { position = ((Component)navMeshSurface).transform.position, rotation = ((Component)navMeshSurface).transform.rotation }; } coroutineHijack.StartCoroutine(NavMeshUpdateCheck(NavMeshBuilder.UpdateNavMeshDataAsync(navMeshSurface.navMeshData, buildSettings, list, val), navMeshSurface)); } private static IEnumerator NavMeshUpdateCheck(AsyncOperation asyncOperation, NavMeshSurface navMeshSurface) { while (!asyncOperation.isDone) { yield return null; } navMeshSurface.RemoveData(); navMeshSurface.AddData(); Loadstone.LogDebug("Updated navmesh"); } } public class ObjectFindPatches { [HarmonyPatch(typeof(InteractTrigger), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> InteractTriggerPatch(IEnumerable<CodeInstruction> instructions) { Loadstone.LogDebug("Attempting to replace InteractTrigger's StartOfRound finding function"); IEnumerable<CodeInstruction> result = StartOfRoundFixer(instructions); Loadstone.LogDebug("Verifying InteractTrigger's replaced StartOfRound finding function"); return result; } [HarmonyPatch(typeof(OutOfBoundsTrigger), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> OutOfBoundsTriggerPatch(IEnumerable<CodeInstruction> instructions) { Loadstone.LogDebug("Attempting to replace OutOfBoundsTrigger's StartOfRound finding function"); IEnumerable<CodeInstruction> result = StartOfRoundFixer(instructions); Loadstone.LogDebug("Verifying OutOfBoundsTrigger's replaced StartOfRound finding function"); return result; } [HarmonyPatch(typeof(FoliageDetailDistance), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> FoliageDetailDistancePatch(IEnumerable<CodeInstruction> instructions) { Loadstone.LogDebug("Attempting to replace FoliageDetailDistance's StartOfRound finding function"); IEnumerable<CodeInstruction> result = StartOfRoundFixer(instructions); Loadstone.LogDebug("Verifying FoliageDetailDistance's replaced StartOfRound finding function"); return result; } [HarmonyPatch(typeof(ItemDropship), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ItemDropshipPatch(IEnumerable<CodeInstruction> instructions) { Loadstone.LogDebug("Attempting to replace ItemDropship's StartOfRound finding function"); IEnumerable<CodeInstruction> result = StartOfRoundFixer(instructions); Loadstone.LogDebug("Verifying ItemDropship's replaced StartOfRound finding function"); return result; } [HarmonyPatch(typeof(animatedSun), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> animatedSunPatch(IEnumerable<CodeInstruction> instructions) { Loadstone.LogDebug("Attempting to replace animatedSun's TImeOfDay finding function"); IEnumerable<CodeInstruction> result = InstanceFixer(instructions, typeof(TimeOfDay)); Loadstone.LogDebug("Verifying animatedSun's replaced TImeOfDay finding function"); return result; } private static IEnumerable<CodeInstruction> StartOfRoundFixer(IEnumerable<CodeInstruction> instructions) { return InstanceFixer(instructions, typeof(StartOfRound)); } private static IEnumerable<CodeInstruction> InstanceFixer(IEnumerable<CodeInstruction> instructions, Type instanceType) { //IL_000f: 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_0057: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(Object), "FindObjectOfType", new Type[0], new Type[1] { instanceType }), (string)null) }).Repeat((Action<CodeMatcher>)delegate(CodeMatcher matcher) { matcher.SetOperandAndAdvance((object)AccessTools.DeclaredMethod(instanceType, "get_Instance", (Type[])null, (Type[])null)); }, (Action<string>)null).InstructionEnumeration(); } } public class PerformanceReportPatches { private static Stopwatch timer = new Stopwatch(); private static double DungeonWaitStartedAt = 0.0; private static double DungeonWaitEndedAt = 0.0; private static double FinishGeneratingLevelCalledAt = 0.0; private static DungeonGenerator CurrentGenerator = null; [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPrefix] private static void StartGameCalled() { timer.Reset(); timer.Start(); } [HarmonyPatch(typeof(RoundManager), "RefreshEnemiesList")] [HarmonyPrefix] private static void FinishGeneratingLevel() { FinishGeneratingLevelCalledAt = timer.Elapsed.TotalMilliseconds; timer.Stop(); GenerationStats val = null; if (CurrentGenerator != null) { val = CurrentGenerator.GenerationStats; } Loadstone.LogInfo("Level Loading Stats:"); if (val != null) { Loadstone.LogInfo("\t DunGen"); Loadstone.LogInfo($"\t\tMainPathRoomCount: {val.MainPathRoomCount}"); Loadstone.LogInfo($"\t\tBranchPathRoomCount: {val.BranchPathRoomCount}"); Loadstone.LogInfo($"\t\tMaxBranchDepth: {val.MaxBranchDepth}"); Loadstone.LogInfo($"\t\tTotalRetries: {val.TotalRetries}"); Loadstone.LogInfo($"\t\tPrunedBranchTileCount: {val.PrunedBranchTileCount}"); Loadstone.LogInfo($"\t\tPreProcessTime: {val.PreProcessTime / 1000f} seconds"); Loadstone.LogInfo($"\t\tMainPathGenerationTime: {val.MainPathGenerationTime / 1000f} seconds"); Loadstone.LogInfo($"\t\tBranchPathGenerationTime: {val.BranchPathGenerationTime / 1000f} seconds"); Loadstone.LogInfo($"\t\tPostProcessTime: {val.PostProcessTime / 1000f} seconds"); Loadstone.LogInfo($"\t\tTotalTime: {val.TotalTime / 1000f} seconds"); } else { Loadstone.LogInfo("\t No DunGen timing stats present"); } Loadstone.LogInfo($"\tStarted Waiting for Others' Dungeons to Finish after {DungeonWaitStartedAt / 1000.0} seconds"); Loadstone.LogInfo($"\tFinished Waiting for Others' Dungeons to Finish after {DungeonWaitEndedAt / 1000.0} seconds"); Loadstone.LogInfo($"\tTotal generation time took {FinishGeneratingLevelCalledAt / 1000.0} seconds"); } private static void DungeonWaitStarted() { DungeonWaitStartedAt = timer.Elapsed.TotalMilliseconds; } private static void DungeonWaitEnded() { DungeonWaitEndedAt = timer.Elapsed.TotalMilliseconds; } [HarmonyPatch(typeof(RoundManager), "GenerateNewFloor")] [HarmonyPostfix] private static void GetDungeonReference(RoundManager __instance) { CurrentGenerator = __instance.dungeonGenerator.Generator; } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] [HarmonyDebug] private static IEnumerable<CodeInstruction> DungeonWaitDetection(IEnumerable<CodeInstruction> instructions) { //IL_000c: 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_002c: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown Loadstone.LogDebug("Attempting to patch Dungeon Wait Detection into RoundManager::LoadNewLevelWait"); IEnumerable<CodeInstruction> result = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldftn, (object)null, (string)null) }).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldftn, (object)null, (string)null) }).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(PerformanceReportPatches), "DungeonWaitStarted", (Type[])null, (Type[])null)) }) .Advance(10) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(PerformanceReportPatches), "DungeonWaitEnded", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); Loadstone.LogDebug("Validating Dungeon Wait Detection patch in RoundManager::LoadNewLevelWait"); return result; } } [HarmonyPatch(typeof(RoundManager))] public class RoundManagerMusicPatches { internal static AudioSource loadingAudioSource; internal static AudioClip loadingAudioClip; [HarmonyPatch("Awake")] [HarmonyPrefix] private static void CreateAudioSource() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Invalid comparison between Unknown and I4 if ((Object)(object)loadingAudioSource != (Object)null) { Object.Destroy((Object)(object)loadingAudioSource); } if ((Object)(object)loadingAudioClip == (Object)null) { loadingAudioClip = Resources.FindObjectsOfTypeAll(typeof(AudioClip)).Cast<AudioClip>().FirstOrDefault((Func<AudioClip, bool>)((AudioClip a) => ((Object)a).name == "ElevatorJingle")); } if ((Object)(object)loadingAudioClip == (Object)null) { Loadstone.LogError("Unable to find ElevatorJingle"); } if ((int)loadingAudioClip.loadState != 2) { loadingAudioClip.LoadAudioData(); } loadingAudioSource = Object.Instantiate<AudioSource>(StartOfRound.Instance.speakerAudioSource); ((Object)loadingAudioSource).name = "LoadstoneLoading"; loadingAudioSource.clip = Object.Instantiate<AudioClip>(loadingAudioClip); ((Object)loadingAudioSource.clip).name = ((Object)loadingAudioSource).name; ((Component)loadingAudioSource).transform.parent = ((Component)StartOfRound.Instance.speakerAudioSource).transform; } [HarmonyPatch("GenerateNewLevelClientRpc")] [HarmonyPrefix] private static void PlayWaitingMusicPatch() { if (LoadstoneConfig.ShouldLoadingMusicPlay.Value) { loadingAudioSource.loop = LoadstoneConfig.ShouldLoadingMusicLoop.Value; loadingAudioSource.volume = LoadstoneConfig.LoadingMusicVolume.Value; loadingAudioSource.Play(); } } [HarmonyPatch("ResetEnemySpawningVariables")] [HarmonyPostfix] private static void StopWaitingMusicPatch() { ((MonoBehaviour)RoundManager.Instance).StartCoroutine(FadeOutMusic(loadingAudioSource)); } private static IEnumerator FadeOutMusic(AudioSource source) { float originalVolume = source.volume; float timeElapsed = 0f; while ((double)source.volume > 0.01) { source.volume = Mathf.Lerp(originalVolume, 0f, timeElapsed); timeElapsed += Time.deltaTime / LoadstoneConfig.LoadingMusicFadeTime.Value; yield return null; } source.Stop(); source.volume = originalVolume; Loadstone.LogDebug("Music fully faded and stopped"); } } public class ScreenDarkenPatches { [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GenerateNewLevelPatch(IEnumerable<CodeInstruction> instructions) { //IL_001b: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (LoadstoneConfig.SeedDisplayConfig.Value == LoadstoneConfig.SeedDisplayType.Darken) { return instructions; } Loadstone.LogDebug("Attempting to disable screen overlay on scene load in \"RoundManager::GenerateNewLevelClientRpc\""); IEnumerable<CodeInstruction> result = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null) }).SetOpcodeAndAdvance(OpCodes.Ldc_I4_0).InstructionEnumeration(); Loadstone.LogDebug("Validating disabled screen overlay on scene load in \"RoundManager::GenerateNewLevelClientRpc\""); return result; } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPostfix] private static void GenerateNewLevelClientRpcPrefixPath(int randomSeed) { Loadstone.LogInfo($"Random seed: {randomSeed}"); if (LoadstoneConfig.SeedDisplayConfig.Value == LoadstoneConfig.SeedDisplayType.Popup) { HUDManager.Instance.DisplayTip("Random Seed", $"{randomSeed}", false, false, "LC_Tip1"); } } [HarmonyPatch(typeof(StartOfRound), "SceneManager_OnLoadComplete1")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> OnLoadCompletePatch(IEnumerable<CodeInstruction> instructions) { //IL_001b: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown if (LoadstoneConfig.SeedDisplayConfig.Value == LoadstoneConfig.SeedDisplayType.Darken) { return instructions; } Loadstone.LogDebug("Attempting to disable screen overlay on scene load in \"StartOfRound::SceneManager_OnLoadComplete1\""); IEnumerable<CodeInstruction> result = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null) }).SetOpcodeAndAdvance(OpCodes.Ldc_I4_0).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null) }) .SetOpcodeAndAdvance(OpCodes.Ldc_I4_0) .InstructionEnumeration(); Loadstone.LogDebug("Validating disabled screen overlay on scene load in \"StartOfRound::SceneManager_OnLoadComplete1\""); return result; } [HarmonyPatch(typeof(StartOfRound), "SceneManager_OnLoad")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> OnLoadPatch(IEnumerable<CodeInstruction> instructions) { //IL_001b: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (LoadstoneConfig.SeedDisplayConfig.Value == LoadstoneConfig.SeedDisplayType.Darken) { return instructions; } Loadstone.LogDebug("Attempting to disable screen overlay on scene load in \"StartOfRound::SceneManager_OnLoad\""); IEnumerable<CodeInstruction> result = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null) }).SetOpcodeAndAdvance(OpCodes.Ldc_I4_0).InstructionEnumeration(); Loadstone.LogDebug("Validating disabled screen overlay on scene load in \"StartOfRound::SceneManager_OnLoad\""); return result; } } public class StatusChangedFixer { [HarmonyPatch(typeof(RoundManager), "Generator_OnGenerationStatusChanged")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StatusChangedPatch(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator) { //IL_000c: 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_002c: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown Loadstone.LogDebug("Attempting to fix Generator_OnGenerationStatusChanged"); Label label = default(Label); return new CodeMatcher(instructions, ilGenerator).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ret, (object)null, (string)null) }).CreateLabel(ref label).Start() .MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Bne_Un, (object)null, (string)null) }) .SetOperandAndAdvance((object)label) .InstructionEnumeration(); } } } namespace Loadstone.Patches.ExpansionCore { public class DungeonGenerator_PatchPatches { [HarmonyPatch(typeof(DungeonGenerator_Patch), "Generate_Postfix")] [HarmonyPrefix] private static bool Generate_PostfixPrefix() { return false; } } } namespace Loadstone.Config { public static class LoadstoneConfig { public enum SeedDisplayType { Popup, Darken, JustLog } public static int CurrentVersion = 1; public static ConfigFile LoadstoneFile; public static ConfigEntry<bool> AsyncDungeon; public static ConfigEntry<float> DungeonAsyncMaxTime; public static ConfigEntry<string> AsyncDungeonBlacklist; public static ConfigEntry<bool> AsyncNavmesh; public static ConfigEntry<bool> DungeonRealization; public static ConfigEntry<SeedDisplayType> SeedDisplayConfig; public static ConfigEntry<bool> StatusChangeFix; public static ConfigEntry<bool> DunGenOptimizations; public static ConfigEntry<bool> LocalPerformanceReports; public static ConfigEntry<bool> ShouldLoadingMusicPlay; public static ConfigEntry<bool> ShouldLoadingMusicLoop; public static ConfigEntry<float> LoadingMusicFadeTime; public static ConfigEntry<float> LoadingMusicVolume; public static ConfigEntry<int> LastConfigVersion; public static void BindAllTo(ConfigFile config) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Expected O, but got Unknown LoadstoneFile = config; AsyncDungeon = LoadstoneFile.Bind<bool>("AsyncDungeon", "Enabled", true, "Whether or not the dungeon should generate asynchronously. The vanilla value is false. This option requires StatusChangeFix to be enabled"); DungeonAsyncMaxTime = LoadstoneFile.Bind<float>("AsyncDungeon", "Dungeon Target Frametime", 20f, new ConfigDescription("How long to spend generating the dungeon each frame, in milliseconds. There is no vanilla value", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 1000f), Array.Empty<object>())); AsyncDungeonBlacklist = LoadstoneFile.Bind<string>("AsyncDungeon", "Async Dungeon Blacklist", "", "A comma-separated list of interiors which should not be processed asynchrounously"); AsyncNavmesh = LoadstoneFile.Bind<bool>("AsyncNavmesh", "Enabled", true, "Whether or not the navmesh should be generated asynchrounously. The vanilla value is false"); DungeonRealization = LoadstoneFile.Bind<bool>("DungeonRealization", "Spread Over Multiple Frames", true, "Whether or not to spread dungeon realization over multiple frames. The vanilla value is false"); SeedDisplayConfig = LoadstoneFile.Bind<SeedDisplayType>("ScreenDarkening", "Seed Display Type", SeedDisplayType.Popup, "Decides how the random seed should appear when loading into a level. The vanilla value is \"Darken\""); StatusChangeFix = LoadstoneFile.Bind<bool>("StatusChangeFix", "Enabled", true, "Enables a fix for the game's status change callback, which is non-functional in vanilla. The vanilla value is false"); DunGenOptimizations = LoadstoneFile.Bind<bool>("DunGenOptimizations", "Enabled", true, "Enables a number of optmizations for DunGen's dungeon generator"); LocalPerformanceReports = LoadstoneFile.Bind<bool>("LocalPerformanceReports", "Enabled", false, "Enables local performance reports, which will appear in the logs every time the ship lands"); ShouldLoadingMusicPlay = LoadstoneFile.Bind<bool>("LoadingMusic", "Should Loading Music Play", false, new ConfigDescription("Should we play loading music as the level loads in?", (AcceptableValueBase)null, Array.Empty<object>())); ShouldLoadingMusicLoop = LoadstoneFile.Bind<bool>("LoadingMusic", "Should Loading Music Loop", true, new ConfigDescription("Should the loading music loop?", (AcceptableValueBase)null, Array.Empty<object>())); LoadingMusicFadeTime = LoadstoneFile.Bind<float>("LoadingMusic", "Loading Music Fade Time", 15f, new ConfigDescription("How long should it take for the loading music to fade out", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); LoadingMusicVolume = LoadstoneFile.Bind<float>("LoadingMusic", "Loading Music Volume", 0.75f, new ConfigDescription("The volume of the loading music", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.5f), Array.Empty<object>())); LastConfigVersion = LoadstoneFile.Bind<int>("Debug", "Last Config Version", 0, new ConfigDescription("The version when this config was last saved. Used for config migrations", (AcceptableValueBase)null, Array.Empty<object>())); MigrateConfigs(); } private static void MigrateConfigs() { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown if (LoadstoneFile.OrphanedEntries == null) { Loadstone.LogError("Failed to migrate config, orphaned entries property was not found."); return; } foreach (ConfigDefinition key in LoadstoneFile.OrphanedEntries.Keys) { Loadstone.LogDebug($"{key}"); } if (LastConfigVersion.Value > CurrentVersion) { Loadstone.LogWarning("Previous config version is newer than current. Did you downgrade your mod?"); } else if (LastConfigVersion.Value != CurrentVersion) { MigrateVersion<bool>(0, new ConfigDefinition("LCSoundTool", "Should Loading Music Play"), ShouldLoadingMusicPlay); MigrateVersion<float>(0, new ConfigDefinition("LCSoundTool", "Loading Music Fade Time"), LoadingMusicFadeTime); MigrateVersion<float>(0, new ConfigDefinition("LCSoundTool", "Loading Music Volume"), LoadingMusicVolume); LastConfigVersion.Value = 1; } } private static void MigrateVersion<T>(int fromVersion, ConfigDefinition oldConfigDefinition, ConfigEntry<T> newConfig) { Dictionary<ConfigDefinition, string> orphanedEntries = LoadstoneFile.OrphanedEntries; if (LastConfigVersion.Value <= fromVersion && orphanedEntries.TryGetValue(oldConfigDefinition, out var value)) { Loadstone.LogInfo($"Migrating '{oldConfigDefinition}' to '{((ConfigEntryBase)newConfig).Definition}' from v{fromVersion}"); newConfig.Value = TomlTypeConverter.ConvertToValue<T>(value); orphanedEntries.Remove(oldConfigDefinition); } } } internal static class LoadstoneDynamicConfig { internal static void RegisterDynamicConfig() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0034: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0085: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0095: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00c4: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown BaseConfigItem[] array = new BaseConfigItem[5]; ConfigEntry<float> dungeonAsyncMaxTime = LoadstoneConfig.DungeonAsyncMaxTime; FloatSliderOptions val = new FloatSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<float>)val).Min = 0f; ((BaseRangeOptions<float>)val).Max = 1000f; array[0] = (BaseConfigItem)new FloatSliderConfigItem(dungeonAsyncMaxTime, val); array[1] = (BaseConfigItem)new BoolCheckBoxConfigItem(LoadstoneConfig.ShouldLoadingMusicPlay, new BoolCheckBoxOptions { RequiresRestart = false }); array[2] = (BaseConfigItem)new BoolCheckBoxConfigItem(LoadstoneConfig.ShouldLoadingMusicLoop, new BoolCheckBoxOptions { RequiresRestart = false }); ConfigEntry<float> loadingMusicFadeTime = LoadstoneConfig.LoadingMusicFadeTime; FloatSliderOptions val2 = new FloatSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<float>)val2).Min = 0f; ((BaseRangeOptions<float>)val2).Max = 30f; array[3] = (BaseConfigItem)new FloatSliderConfigItem(loadingMusicFadeTime, val2); ConfigEntry<float> loadingMusicVolume = LoadstoneConfig.LoadingMusicVolume; FloatSliderOptions val3 = new FloatSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<float>)val3).Min = 0f; ((BaseRangeOptions<float>)val3).Max = 1.5f; array[4] = (BaseConfigItem)new FloatSliderConfigItem(loadingMusicVolume, val3); AddConfigItems((IEnumerable<BaseConfigItem>)(object)array); } internal static void AddConfigItems(IEnumerable<BaseConfigItem> configItems) { foreach (BaseConfigItem configItem in configItems) { LethalConfigManager.AddConfigItem(configItem); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }