using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LethalPerformance.Patcher.Helpers; using LethalPerformance.Patcher.TomlConverters; using LethalPerformance.Patcher.Utilities; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.RuntimeDetour; using MonoMod.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("BepInEx")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LethalPerformance.Patcher")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.5.0")] [assembly: AssemblyInformationalVersion("1.2.5+76a8596824241c3ab2931e3ae57f62e5eb8f97e7")] [assembly: AssemblyProduct("LethalPerformance.Patcher")] [assembly: AssemblyTitle("LethalPerformance.Patcher")] [assembly: InternalsVisibleTo("LethalPerformance")] [assembly: InternalsVisibleTo("LethalPerformance.Dev")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.5.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlyArray : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => _items.Length; T IReadOnlyList.this[int index] => _items[index]; int ICollection.Count => _items.Length; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return ((ICollection)_items).Contains(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { ((ICollection)_items).CopyTo(array, arrayIndex); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { return ((IList)_items).IndexOf(item); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LethalPerformance.Patcher { public class LethalPerformancePatcher { internal static Harmony? Harmony { get; set; } internal static ManualLogSource Logger { get; } = Logger.CreateLogSource("LethalPerformance.Patcher"); public static ConfigSaverTask ConfigSaverTask { get; } = new ConfigSaverTask(); public static IEnumerable TargetDLLs { get; } = new <>z__ReadOnlyArray(new string[2] { "Assembly-CSharp.dll", "Assembly-CSharp-firstpass.dll" }); public static void Finish() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown Harmony = new Harmony("LethalPerformance.Patcher"); Harmony.PatchAll(typeof(LethalPerformancePatcher).Assembly); Harmony.UnpatchID("org.bepinex.fixes.harmonyinterop"); TomlTypeConverter.TypeConverters[typeof(string)] = (TypeConverter)(object)new StringTomlConverter(); TomlTypeConverter.TypeConverters[typeof(bool)] = (TypeConverter)(object)new BoolTomlConverter(); WarnIfTerbiumInstalled(); } private static void WarnIfTerbiumInstalled() { IList list = (IList)Type.GetType("BepInEx.Preloader.Patching.AssemblyPatcher,BepInEx.Preloader").GetProperty("PatcherPlugins", AccessTools.all).GetGetMethod() .Invoke(null, null); PropertyInfo property = list[0].GetType().GetProperty("TypeName", AccessTools.all); foreach (object item in list) { string text = (string)property.GetGetMethod().Invoke(item, null); if (text == "Terbium.TerbiumPreloader") { Logger.LogWarning((object)"Terbium mod installed, for better compatibility remove it."); break; } } } public static void Patch(AssemblyDefinition assembly) { if (((AssemblyNameReference)assembly.Name).Name == "Assembly-CSharp-firstpass") { PatchES3(assembly); return; } Dictionary> dictionary = new Dictionary> { { "AudioReverbPresets", delegate(AssemblyDefinition a, TypeDefinition t) { AssemblyPatcherUtilities.AddMethod(a, t, "Awake"); } } }; foreach (KeyValuePair> item in dictionary) { item.Deconstruct(out var key, out var value); string text = key; Action action = value; TypeDefinition type = assembly.MainModule.GetType(text); if (type == null) { Logger.LogWarning((object)("Failed to patch " + text)); } else { action(assembly, type); } } } private static void PatchES3(AssemblyDefinition assembly) { TypeDefinition type = assembly.MainModule.GetType("ES3"); TypeDefinition type2 = assembly.MainModule.GetType("ES3Settings"); PatchSave(assembly, type, (TypeReference)(object)type2); PatchLoad(assembly, type, (TypeReference)(object)type2); PatchSerialize(assembly, type); TypeDefinition type3 = assembly.MainModule.GetType("ES3File"); PatchFileSave(assembly, type3, type2); } private static void PatchFileSave(AssemblyDefinition assembly, TypeDefinition es3FileType, TypeDefinition es3SettingsType) { //IL_004e: 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) MethodDefinition val = ((IEnumerable)es3FileType.Methods).FirstOrDefault((Func)((MethodDefinition m) => ((MemberReference)m).Name == "Save")); MethodDefinition val2 = AddNonGenericMethod(assembly, es3FileType, null, "LethalPerformance_Save", (MethodAttributes)6); Extensions.InsertRange(val.Body.Instructions, 0, (IEnumerable)new <>z__ReadOnlyArray((Instruction[])(object)new Instruction[2] { Instruction.Create(OpCodes.Ldarg_0), Instruction.Create(OpCodes.Call, (MethodReference)(object)val2) })); } private static void PatchSave(AssemblyDefinition assembly, TypeDefinition es3Type, TypeReference es3SettingsType) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_006f: 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) MethodDefinition val = ((IEnumerable)es3Type.Methods).FirstOrDefault((Func)((MethodDefinition m) => ((MemberReference)m).Name == "Save" && ((MethodReference)m).Parameters.Count == 3 && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[2]).ParameterType).Name == "ES3Settings" && ((MethodReference)m).HasGenericParameters)); if (val == null) { Logger.LogWarning((object)"ES3.Save doesn't exists. Removed by other mod?"); return; } ParameterDefinition parameter = new ParameterDefinition("settings", (ParameterAttributes)0, es3SettingsType); MethodDefinition val2 = AddNonGenericMethod(assembly, es3Type, parameter, "LethalPerformance_Save", (MethodAttributes)22); Collection instructions = val.Body.Instructions; Instruction[] array = new Instruction[2]; OpCode ldarg = OpCodes.Ldarg; Collection parameters = ((MethodReference)val).Parameters; array[0] = Instruction.Create(ldarg, parameters[parameters.Count - 1]); array[1] = Instruction.Create(OpCodes.Call, (MethodReference)(object)val2); Extensions.InsertRange(instructions, 0, (IEnumerable)new <>z__ReadOnlyArray((Instruction[])(object)array)); } private static void PatchLoad(AssemblyDefinition assembly, TypeDefinition es3Type, TypeReference es3SettingsType) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) List list = ((IEnumerable)es3Type.Methods).Where(delegate(MethodDefinition m) { if (((MemberReference)m).Name != "Load" || !((MethodReference)m).ReturnType.IsGenericParameter) { return false; } if (((MethodReference)m).Parameters.Count == 2 && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).Name == "String" && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[1]).ParameterType).Name == "ES3Settings") { return true; } return (((MethodReference)m).Parameters.Count == 3 && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType).Name == "String" && ((ParameterReference)((MethodReference)m).Parameters[1]).ParameterType.IsGenericParameter && ((MemberReference)((ParameterReference)((MethodReference)m).Parameters[2]).ParameterType).Name == "ES3Settings") ? true : false; }).ToList(); if (list.Count != 2) { Logger.LogWarning((object)"Detected ES3.Load mismatch of count"); return; } ParameterDefinition parameter = new ParameterDefinition("settings", (ParameterAttributes)0, es3SettingsType); MethodDefinition val = AddNonGenericMethod(assembly, es3Type, parameter, "LethalPerformance_Load", (MethodAttributes)22); foreach (MethodDefinition item in list) { Collection instructions = item.Body.Instructions; Instruction[] array = new Instruction[2]; OpCode ldarg = OpCodes.Ldarg; Collection parameters = ((MethodReference)item).Parameters; array[0] = Instruction.Create(ldarg, parameters[parameters.Count - 1]); array[1] = Instruction.Create(OpCodes.Call, (MethodReference)(object)val); Extensions.InsertRange(instructions, 0, (IEnumerable)new <>z__ReadOnlyArray((Instruction[])(object)array)); } } private static void PatchSerialize(AssemblyDefinition assembly, TypeDefinition es3Type) { //IL_00b4: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) MethodDefinition val = ((IEnumerable)es3Type.Methods).FirstOrDefault((Func)((MethodDefinition m) => ((MemberReference)m).Name == "Serialize" && ((MethodReference)m).Parameters.Count == 2)); MethodDefinition val2 = ((IEnumerable)es3Type.Methods).FirstOrDefault((Func)((MethodDefinition m) => ((MemberReference)m).Name == "Serialize" && ((MethodReference)m).Parameters.Count == 3)); MethodDefinition val3 = ((IEnumerable)assembly.MainModule.GetType("ES3Internal.ES3TypeMgr").Methods).FirstOrDefault((Func)((MethodDefinition m) => ((MemberReference)m).Name == "GetOrCreateES3Type")); val.Body.Instructions.Clear(); Extensions.AddRange(val.Body.Instructions, (IEnumerable)new <>z__ReadOnlyArray((Instruction[])(object)new Instruction[10] { Instruction.Create(OpCodes.Ldarg_0), Instruction.Create(OpCodes.Box, ((ParameterReference)((MethodReference)val).Parameters[0]).ParameterType), Instruction.Create(OpCodes.Ldarga, ((MethodReference)val).Parameters[0]), Instruction.Create(OpCodes.Constrained, ((ParameterReference)((MethodReference)val).Parameters[0]).ParameterType), Instruction.Create(OpCodes.Callvirt, assembly.MainModule.ImportReference((MethodBase)typeof(object).GetMethod("GetType"))), Instruction.Create(OpCodes.Ldc_I4_1), Instruction.Create(OpCodes.Call, (MethodReference)(object)val3), Instruction.Create(OpCodes.Ldarg_1), Instruction.Create(OpCodes.Call, (MethodReference)(object)val2), Instruction.Create(OpCodes.Ret) })); } private static MethodDefinition AddNonGenericMethod(AssemblyDefinition assembly, TypeDefinition es3Type, ParameterDefinition? parameter, string name, MethodAttributes attributes = 22) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown MethodDefinition val = new MethodDefinition(name, attributes, assembly.MainModule.TypeSystem.Void); if (parameter != null) { ((MethodReference)val).Parameters.Add(parameter); } AssemblyPatcherUtilities.StubMethod(val.Body.GetILProcessor()); es3Type.Methods.Add(val); return val; } } } namespace LethalPerformance.Patcher.Utilities { internal static class AssemblyPatcherUtilities { public static void RemoveMethod(AssemblyDefinition assembly, TypeDefinition type, string methodName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Enumerator enumerator = type.Methods.GetEnumerator(); try { while (enumerator.MoveNext()) { MethodDefinition current = enumerator.Current; if (((MemberReference)current).Name == methodName) { type.Methods.Remove(current); break; } } } finally { ((IDisposable)enumerator).Dispose(); } } public static void AddMethod(AssemblyDefinition assembly, TypeDefinition type, string methodName) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown string methodName2 = methodName; if (!((IEnumerable)type.Methods).Any((MethodDefinition m) => ((MemberReference)m).Name == methodName2)) { MethodDefinition val = new MethodDefinition(methodName2, (MethodAttributes)1, assembly.MainModule.TypeSystem.Void); ILProcessor iLProcessor = val.Body.GetILProcessor(); StubMethod(iLProcessor); type.Methods.Add(val); } } public static void StubMethod(ILProcessor processor) { //IL_0005: 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) for (int i = 0; i < 32; i++) { processor.Emit(OpCodes.Nop); } processor.Emit(OpCodes.Ret); } } public class ConfigSaverTask { private readonly HashSet m_ConfigFilesToSave = new HashSet(); private readonly HashSet m_IgnoredConfigFiles = new HashSet(); public void ScheduleSaveFor(ConfigFile configFile) { if (configFile == null) { LethalPerformancePatcher.Logger.LogWarning((object)("Null config file passed for save\n" + Environment.StackTrace)); } else if (!m_IgnoredConfigFiles.Contains(configFile)) { m_ConfigFilesToSave.Add(configFile); } } public void AddIgnoredConfigFile(ConfigFile configFile) { if (!m_IgnoredConfigFiles.Add(configFile)) { return; } foreach (ConfigFile ignoredConfigFile in m_IgnoredConfigFiles) { m_ConfigFilesToSave.Remove(ignoredConfigFile); } } public void ScheduleSave() { if (m_ConfigFilesToSave.Count != 0) { Queue param = new Queue(m_ConfigFilesToSave); m_ConfigFilesToSave.Clear(); AsyncHelper.Schedule(SaveAsync, param); } } public void Save() { if (m_ConfigFilesToSave.Count != 0) { Queue queue = new Queue(m_ConfigFilesToSave); m_ConfigFilesToSave.Clear(); SaveAsync(queue); } } private Task SaveAsync(Queue queue) { int count = queue.Count; ConfigFile result; while (queue.TryDequeue(out result)) { result.Save(); } LethalPerformancePatcher.Logger.LogInfo((object)$"Saved {count} config(s)"); return Task.CompletedTask; } } } namespace LethalPerformance.Patcher.TomlConverters { internal class BoolTomlConverter : TypeConverter { public override bool ConvertToObject(string value) { return bool.Parse(value); } public override string ConvertToString(bool value) { if (!value) { return "false"; } return "true"; } } internal class StringTomlConverter : TypeConverter { private static readonly Regex s_WindowsPathRegex = new Regex("^\"?\\w:\\\\(?!\\\\)(?!.+\\\\\\\\)", RegexOptions.Compiled); public override string ConvertToObject(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } if (s_WindowsPathRegex.IsMatch(value)) { return value; } return Unescape(value); } public override string ConvertToString(string value) { return Escape(value); } private static string Escape(string txt) { if (string.IsNullOrEmpty(txt)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(txt.Length + 2); foreach (char c in txt) { switch (c) { case '\0': stringBuilder.Append("\\0"); break; case '\a': stringBuilder.Append("\\a"); break; case '\b': stringBuilder.Append("\\b"); break; case '\t': stringBuilder.Append("\\t"); break; case '\n': stringBuilder.Append("\\n"); break; case '\v': stringBuilder.Append("\\v"); break; case '\f': stringBuilder.Append("\\f"); break; case '\r': stringBuilder.Append("\\r"); break; case '\'': stringBuilder.Append("\\'"); break; case '"': stringBuilder.Append("\\\""); break; default: stringBuilder.Append(c); break; } } if (stringBuilder.Length == txt.Length) { return txt; } return stringBuilder.ToString(); } private static string Unescape(string txt) { if (string.IsNullOrEmpty(txt)) { return txt; } int num = txt.IndexOf('\\'); if (num == -1) { return txt; } StringBuilder stringBuilder = new StringBuilder(txt.Length); stringBuilder.Append(txt, 0, num); int num2 = num; while (num2 < txt.Length) { int num3 = txt.IndexOf('\\', num2); if (num3 < 0 || num3 == txt.Length - 1) { num3 = txt.Length; } stringBuilder.Append(txt, num2, num3 - num2); if (num3 >= txt.Length) { break; } char c = txt[num3 + 1]; switch (c) { case '0': stringBuilder.Append('\0'); break; case 'a': stringBuilder.Append('\a'); break; case 'b': stringBuilder.Append('\b'); break; case 't': stringBuilder.Append('\t'); break; case 'n': stringBuilder.Append('\n'); break; case 'v': stringBuilder.Append('\v'); break; case 'f': stringBuilder.Append('\f'); break; case 'r': stringBuilder.Append('\r'); break; case '\'': stringBuilder.Append('\''); break; case '"': stringBuilder.Append('"'); break; case '\\': stringBuilder.Append('\\'); break; default: stringBuilder.Append('\\').Append(c); break; } num2 = num3 + 2; } return stringBuilder.ToString(); } } internal abstract class TypeConverter : TypeConverter where T : IEquatable { protected TypeConverter() { ((TypeConverter)this).ConvertToObject = (string value, Type _) => ConvertToObject(value); ((TypeConverter)this).ConvertToString = (object value, Type _) => ConvertToString((T)value); } public abstract T ConvertToObject(string value); public abstract string ConvertToString(T value); } } namespace LethalPerformance.Patcher.Patches { [HarmonyPatch(typeof(Chainloader))] internal static class Patch_Chainloader { private static Dictionary? s_PluginsToLoad; internal static bool IsModWillBeLoaded(string guid) { return s_PluginsToLoad?.ContainsKey(guid) ?? false; } [HarmonyPatch("Initialize")] [HarmonyPostfix] private static void Initialize() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown try { LethalPerformancePatcher.Harmony.Patch((MethodBase)MethodOf(new Action(Chainloader.Start)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(MethodOf(new Func, IEnumerable>(SaveListOfPluginsTranspiler))), (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { LethalPerformancePatcher.Logger.LogWarning((object)ex); } DebugRemoveThreadSafetyCheck(); } private static void DebugRemoveThreadSafetyCheck() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (Debug.isDebugBuild) { IntPtr? intPtr = Process.GetCurrentProcess().Modules.Cast().FirstOrDefault((ProcessModule p) => p.ModuleName.Contains("UnityPlayer"))?.BaseAddress; if (intPtr.HasValue) { NativeDetour val = new NativeDetour(intPtr.Value + 16905760, (MethodBase)MethodOf(new Action(StubMethod))); } } } private static void StubMethod() { } private static MethodInfo MethodOf(Delegate @delegate) { return @delegate.Method; } private static IEnumerable SaveListOfPluginsTranspiler(IEnumerable codeInstructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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 //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(codeInstructions, (ILGenerator)null); object operand = val.SearchForward((Func)((CodeInstruction c) => c.operand is FieldInfo fieldInfo && fieldInfo.FieldType == typeof(Dictionary))).Operand; val.Start().MatchForward(true, (CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldloc_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_I4_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Newarr, (object)typeof(string), (string)null), new CodeMatch((OpCode?)OpCodes.Stfld, (object)null, (string)null) }).ThrowIfInvalid("Failed to get injection point") .Insert((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldloc_0, (object)null), new CodeInstruction(OpCodes.Ldfld, operand), new CodeInstruction(OpCodes.Stsfld, (object)typeof(Patch_Chainloader).GetField("s_PluginsToLoad", AccessTools.all)) }); return val.InstructionEnumeration(); } } [HarmonyPatch(typeof(ConfigDefinition))] internal static class Patch_ConfigDefinition { private static readonly MethodInfo s_TargetMethod = typeof(Patch_ConfigDefinition).GetMethod("CheckInvalidConfigCharsOptimized", AccessTools.all); [HarmonyPatch("CheckInvalidConfigChars")] [HarmonyTranspiler] public static IEnumerable CallCheckInvalidConfigCharsOptimized() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown return new <>z__ReadOnlyArray((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)s_TargetMethod), new CodeInstruction(OpCodes.Ret, (object)null) }); } private static void CheckInvalidConfigCharsOptimized(string value, string name) { if (value == null) { throw new ArgumentNullException(name); } ReadOnlySpan span = value.AsSpan().Trim(); if (!span.SequenceEqual(value)) { throw new ArgumentException("Cannot use whitespace characters at start or end of section and key names", name); } if (span.IndexOfAny(ConfigDefinition._invalidConfigChars) >= 0) { throw new ArgumentException("Cannot use any of the following characters in section and key names: = \\n \\t \\ \" ' [ ]", name); } } } [HarmonyPatch(typeof(ConfigEntryBase))] internal static class Patch_ConfigEntryBase { [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] public static void ScheduleSave(ConfigFile configFile) { LethalPerformancePatcher.ConfigSaverTask.ScheduleSaveFor(configFile); } [HarmonyPatch("WriteDescription")] [HarmonyTranspiler] public static IEnumerable CallWriteDescriptionOptimized() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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 return new <>z__ReadOnlyArray((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression)(() => WriteDescriptionOptimized(null, null)))), new CodeInstruction(OpCodes.Ret, (object)null) }); } public static void WriteDescriptionOptimized(ConfigEntryBase instance, StreamWriter writer) { if (!string.IsNullOrEmpty(instance.Description.Description)) { writer.Write("## "); string description = instance.Description.Description; foreach (char c in description) { writer.Write(c); if (c == '\n') { writer.Write("## "); } } writer.WriteLine(); } writer.Write("# Setting type: "); writer.WriteLine(instance.SettingType.Name); writer.Write("# Default value: "); writer.WriteLine(TomlTypeConverter.ConvertToString(instance.DefaultValue, instance.SettingType)); if (instance.Description.AcceptableValues != null) { writer.WriteLine(instance.Description.AcceptableValues.ToDescriptionString()); } else { if (!instance.SettingType.IsEnum) { return; } writer.Write("# Acceptable values: "); string[] orCreate = EnumCacheHelper.GetOrCreate(instance.SettingType); for (int j = 0; j < orCreate.Length; j++) { string value = orCreate[j]; writer.Write(value); if (j != orCreate.Length - 1) { writer.Write(", "); } } writer.WriteLine(); if (instance.SettingType.IsDefined(typeof(FlagsAttribute), inherit: false)) { writer.WriteLine("# Multiple values can be set at the same time by separating them with , (e.g. Debug, Warning)"); } } } } [HarmonyPatch(typeof(ConfigFile))] internal static class Patch_ConfigFile { private static bool s_IgnoreConfigSet; [HarmonyPatch("Reload")] [HarmonyTranspiler] public static IEnumerable CallOptimizedReload() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown return new <>z__ReadOnlyArray((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression)(() => OptimizedReload(null)))), new CodeInstruction(OpCodes.Ret, (object)null) }); } [HarmonyPatch("Save")] [HarmonyTranspiler] public static IEnumerable CallOptimizedSave() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown return new <>z__ReadOnlyArray((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression)(() => SaveOptimized(null)))), new CodeInstruction(OpCodes.Ret, (object)null) }); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] public static void SetFalseForSaveOnConfigSet(ConfigFile __instance, bool saveOnInit) { s_IgnoreConfigSet = true; __instance.SaveOnConfigSet = false; s_IgnoreConfigSet = false; if (saveOnInit) { LethalPerformancePatcher.ConfigSaverTask.ScheduleSaveFor(__instance); } __instance.SettingChanged += delegate(object _, SettingChangedEventArgs arg) { LethalPerformancePatcher.ConfigSaverTask.ScheduleSaveFor(arg.ChangedSetting.ConfigFile); }; } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] public static void AddIgnoreIfSetToFalse(ConfigFile __instance, bool value) { if (!s_IgnoreConfigSet && !value) { LethalPerformancePatcher.ConfigSaverTask.AddIgnoredConfigFile(__instance); } } private static void OptimizedReload(ConfigFile instance) { //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Expected O, but got Unknown lock (instance._ioLock) { instance.OrphanedEntries.Clear(); using StreamReader streamReader = new StreamReader(instance.ConfigFilePath, Encoding.UTF8); string text = string.Empty; Span ranges = stackalloc Range[2]; string text2; while ((text2 = streamReader.ReadLine()) != null) { ReadOnlySpan readOnlySpan = text2.AsSpan().Trim(); if (readOnlySpan.IsEmpty || readOnlySpan.StartsWith("#")) { continue; } if (readOnlySpan.StartsWith("[") && readOnlySpan.EndsWith("]")) { text = readOnlySpan.Slice(1, readOnlySpan.Length - 2).ToString(); } else if (SpanExtensions.Split(readOnlySpan, ranges, '=')) { Range range = ranges[0]; ReadOnlySpan readOnlySpan2 = readOnlySpan[range.Start..range.End].Trim(); range = ranges[1]; ReadOnlySpan readOnlySpan3 = readOnlySpan[range.Start..range.End].Trim(); ConfigDefinition key = new ConfigDefinition(text, readOnlySpan2.ToString()); if (instance.Entries.TryGetValue(key, out var value)) { value.SetSerializedValue(readOnlySpan3.ToString()); } else { instance.OrphanedEntries[key] = readOnlySpan3.ToString(); } } } } instance.OnConfigReloaded(); } private static void SaveOptimized(ConfigFile instance) { lock (instance._ioLock) { string directoryName = Path.GetDirectoryName(instance.ConfigFilePath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } Span destination = stackalloc char[128]; using StreamWriter streamWriter = new StreamWriter(instance.ConfigFilePath, append: false, Utility.UTF8NoBom); if (instance._ownerMetadata != null) { streamWriter.Write("## Settings file was created by plugin "); streamWriter.Write(instance._ownerMetadata.Name); streamWriter.Write(" v"); if (instance._ownerMetadata.Version != null) { instance._ownerMetadata.Version.TryFormat(destination, out var charsWritten); streamWriter.WriteLine(destination.Slice(0, charsWritten)); } streamWriter.Write("## Plugin GUID: "); streamWriter.WriteLine(instance._ownerMetadata.GUID); streamWriter.WriteLine(); } var second = instance.OrphanedEntries.Select((KeyValuePair x) => new { Key = x.Key, entry = (ConfigEntryBase)null, value = x.Value }); var first = instance.Entries.Select((KeyValuePair x) => new { Key = x.Key, entry = x.Value, value = (string)null }); var orderedEnumerable = from x in first.Concat(second) group x by x.Key.Section into x orderby x.Key select x; foreach (var item in orderedEnumerable) { streamWriter.Write('['); streamWriter.Write(item.Key); streamWriter.WriteLine(']'); foreach (var item2 in item) { streamWriter.WriteLine(); ConfigEntryBase entry = item2.entry; if (entry != null) { entry.WriteDescription(streamWriter); } object obj = item2.value; if (obj == null) { ConfigEntryBase entry2 = item2.entry; obj = ((entry2 != null) ? entry2.GetSerializedValue() : null) ?? string.Empty; } string value = (string)obj; streamWriter.Write(item2.Key.Key); streamWriter.Write(" = "); streamWriter.WriteLine(value); } streamWriter.WriteLine(); } } } } [HarmonyPatch] internal class Patch_FileSystemWatcher { private static readonly MethodInfo? s_StartDispatching; private static readonly FieldInfo? s_Watches; static Patch_FileSystemWatcher() { Type type = typeof(FileSystemWatcher).Assembly.GetType("System.IO.DefaultWatcher", throwOnError: false); if (!(type == null)) { s_StartDispatching = type.GetMethod("StartDispatching", AccessTools.all); s_Watches = type.GetField("watches", AccessTools.all); s_Watches?.SetValue(null, new Hashtable()); } } [HarmonyPrepare] private static bool ShouldPatch() { return s_StartDispatching != null; } [HarmonyTargetMethod] private static MethodInfo? GetTargetPatch() { return s_StartDispatching; } [HarmonyPrefix] private static bool DisableDefaultWatcher() { return false; } } } namespace LethalPerformance.Patcher.Helpers { internal static class AsyncHelper { public static void Schedule(Func func) { Func func2 = func; Task.Run(async delegate { try { await func2(); } catch (Exception ex) { LethalPerformancePatcher.Logger.LogError((object)ex); } }); } public static void Schedule(Func func, T param1) { Func func2 = func; T param2 = param1; Task.Run(async delegate { try { await func2(param2); } catch (Exception ex) { LethalPerformancePatcher.Logger.LogError((object)ex); } }); } } internal static class EnumCacheHelper { private static readonly Dictionary s_EnumNamesCache = new Dictionary(); public static string[] GetOrCreate(Type enumType) { if (s_EnumNamesCache.Count >= 255) { s_EnumNamesCache.Clear(); } if (s_EnumNamesCache.TryGetValue(enumType, out string[] value)) { return value; } string[] names = Enum.GetNames(enumType); s_EnumNamesCache[enumType] = names; return names; } } internal static class SpanExtensions { public static bool Split(ReadOnlySpan input, Span ranges, char separator) { if (ranges.IsEmpty && ranges.Length != 2) { return false; } for (int i = 0; i < input.Length; i++) { char c = input[i]; if (c == separator) { ranges[0] = 0..i; ranges[1] = (i + 1)..input.Length; return true; } } return false; } } } namespace LethalPerformance.Patcher.API { internal static class HarmonyExceptionHandler { public static Exception? ReportException(Exception? exception) { if (exception != null) { LethalPerformancePatcher.Logger.LogWarning((object)exception); LethalPerformancePatcher.Logger.LogWarning((object)Environment.StackTrace); } return null; } } [AttributeUsage(AttributeTargets.Method)] internal sealed class InitializeOnAwakeAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }