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 QuickStackStore Valheim1 Compat v1.0.0
patchers/QssValheim1Compat.Patcher.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Threading; using BepInEx; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("QssValheim1Compat.Patcher")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("QssValheim1Compat.Patcher")] [assembly: AssemblyTitle("QssValheim1Compat.Patcher")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace QssValheim1Compat { public static class Patcher { private const string StockSha256 = "0635F5871342E416A1BD2247A1F5785A280E11FF7A97D4C1FC880C85143785F1"; private const string TargetFileName = "QuickStackStore.dll"; private const string BackupSuffix = ".qsscompat-original-1.4.13.bak"; private const string MarkerSuffix = ".qsscompat.sha256"; private const string LockSuffix = ".qsscompat.lock"; private const string TempSuffix = ".qsscompat.tmp"; private const int LockTimeoutMs = 30000; private static readonly ManualLogSource Log = Logger.CreateLogSource("QSSValheim1Compat"); public static IEnumerable<string> TargetDLLs => new string[0]; public static void Patch(AssemblyDefinition assembly) { } public static void Initialize() { try { Run(); } catch (Exception arg) { Log.LogError((object)$"Patch aborted; QuickStackStore left untouched. {arg}"); } } private static void Run() { string text = Directory.GetFiles(Paths.PluginPath, "QuickStackStore.dll", SearchOption.AllDirectories).FirstOrDefault(); if (text == null) { Log.LogInfo((object)"QuickStackStore.dll not installed; nothing to do."); return; } string path = text + ".qsscompat.lock"; FileStream fileStream = null; int num = 0; while (fileStream == null) { try { fileStream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.None); } catch (IOException) { if (num >= 30000) { Log.LogWarning((object)($"Another instance held the patch lock for {30000}ms; skipping. " + "If this persists, delete " + Path.GetFileName(path) + ".")); return; } Thread.Sleep(200); num += 200; } } try { PatchUnderLock(text); } finally { fileStream.Dispose(); try { File.Delete(path); } catch { } } } private static void PatchUnderLock(string target) { string path = target + ".qsscompat.sha256"; string text = Sha256(File.ReadAllBytes(target)); if (File.Exists(path) && string.Equals(File.ReadAllText(path).Trim(), text, StringComparison.OrdinalIgnoreCase)) { Log.LogInfo((object)"QuickStackStore already patched; nothing to do."); return; } if (!string.Equals(text, "0635F5871342E416A1BD2247A1F5785A280E11FF7A97D4C1FC880C85143785F1", StringComparison.OrdinalIgnoreCase)) { Log.LogWarning((object)("QuickStackStore.dll is not the stock 1.4.13 build this patch was tested against (found " + text + "). Refusing to patch it. If QuickStackStore has been updated, this compatibility patch is probably no longer needed and should be removed.")); return; } byte[] array = File.ReadAllBytes(target); byte[] array2; using (MemoryStream memoryStream = new MemoryStream(array)) { ModuleDefinition val = ModuleDefinition.ReadModule((Stream)memoryStream); try { using MemoryStream memoryStream2 = new MemoryStream(); QssPatches.Apply(val, delegate(string m) { Log.LogInfo((object)m); }); val.Write((Stream)memoryStream2); array2 = memoryStream2.ToArray(); } finally { ((IDisposable)val)?.Dispose(); } } if (array2.Length == 0) { throw new InvalidOperationException("patched assembly came back empty"); } string text2 = Sha256(array2); string text3 = target + ".qsscompat-original-1.4.13.bak"; if (!File.Exists(text3)) { try { File.WriteAllBytes(text3, array); Log.LogInfo((object)("Saved a copy of the stock DLL to " + Path.GetFileName(text3))); } catch (IOException) { } } string text4 = string.Format("{0}.{1:N}{2}", target, Guid.NewGuid(), ".qsscompat.tmp"); try { File.WriteAllBytes(text4, array2); if (new FileInfo(text4).Length != array2.Length) { throw new IOException("staged file length does not match the patched assembly"); } using (MemoryStream memoryStream3 = new MemoryStream(File.ReadAllBytes(text4))) { ModuleDefinition.ReadModule((Stream)memoryStream3).Dispose(); } try { if (File.Exists(target)) { File.Delete(target); } File.Move(text4, target); } catch (Exception ex2) { if (!TargetMatches(target, text2)) { Restore(text3, target); throw new IOException("swap failed, restored the stock DLL: " + ex2.Message, ex2); } } if (!TargetMatches(target, text2)) { Restore(text3, target); throw new IOException("written file does not match the expected patched build; restored the stock DLL"); } File.WriteAllText(path, text2); Log.LogInfo((object)"QuickStackStore patched for Valheim 1.0."); } finally { try { if (File.Exists(text4)) { File.Delete(text4); } } catch { } } } private static bool TargetMatches(string target, string expectedHash) { try { return File.Exists(target) && Sha256(File.ReadAllBytes(target)) == expectedHash; } catch (IOException) { return false; } } private static void Restore(string backup, string target) { try { if (File.Exists(target)) { File.Delete(target); } File.Copy(backup, target); Log.LogWarning((object)"Restored the stock QuickStackStore.dll from backup."); } catch (Exception ex) { Log.LogError((object)("COULD NOT RESTORE " + Path.GetFileName(target) + ". Reinstall QuickStackStore. " + ex.Message)); } } private static string Sha256(byte[] bytes) { using SHA256 sHA = SHA256.Create(); return BitConverter.ToString(sHA.ComputeHash(bytes)).Replace("-", ""); } } public static class QssPatches { private static readonly string[][] MessageTargets = new string[7][] { new string[2] { "QuickStackStore.QuickStackModule", "DoQuickStack" }, new string[2] { "QuickStackStore.QuickStackModule", "ReportQuickStackResult" }, new string[2] { "QuickStackStore.StackAllPatch", "ContainerStackAllPatch" }, new string[2] { "QuickStackStore.RestockModule", "DoRestock" }, new string[2] { "QuickStackStore.RestockModule", "ReportRestockResult" }, new string[2] { "QuickStackStore.InventoryGridButtonHandlingPatches", "HandleClickInternal" }, new string[2] { "QuickStackStore.TrashModule/TrashItemsPatches", "UpdateItemDrag_Postfix" } }; private static readonly string[][] EverybodyTargets = new string[3][] { new string[2] { "ServerSync.ConfigSync", "sendZPackage" }, new string[2] { "ServerSync.ConfigSync/<>c__DisplayClass34_0`1", "<AddConfigEntry>b__0" }, new string[2] { "ServerSync.ConfigSync/<>c__DisplayClass36_0", "<AddCustomValue>b__1" } }; private static readonly string[][] ChangedTargets = new string[7][] { new string[2] { "QuickStackStore.QuickStackModule", "QuickStackIntoThisContainer" }, new string[2] { "QuickStackStore.QuickStackModule", "QuickStackIntoMultipleContainers" }, new string[2] { "QuickStackStore.RestockModule", "RestockFromThisContainer" }, new string[2] { "QuickStackStore.RestockModule", "RestockFromMultipleContainers" }, new string[2] { "QuickStackStore.StoreTakeAllModule", "MoveAllItemsInOrder" }, new string[2] { "QuickStackStore.SortModule", "SortInternal" }, new string[2] { "QuickStackStore.TrashModule", "QuickTrash" } }; public static void Apply(ModuleDefinition module, Action<string> log) { FixCharacterMessage(module, log); FixZRoutedRpcEverybody(module, log); FixInventoryChanged(module, log); FixSplitPanelField(module, log); FixClickHandlerTargets(module, log); FixInventoryGridElement(module, log); FixTooltipPatchSignature(module, log); FixHasRandyPlugin(module, log); FixTrashDialogSplitDialogClone(module, log); } private static IEnumerable<TypeDefinition> AllTypes(ModuleDefinition module) { return ((IEnumerable<TypeDefinition>)module.Types).SelectMany(Walk); static IEnumerable<TypeDefinition> Walk(TypeDefinition t) { yield return t; Enumerator<TypeDefinition> enumerator = t.NestedTypes.GetEnumerator(); try { while (enumerator.MoveNext()) { TypeDefinition current = enumerator.Current; foreach (TypeDefinition item in Walk(current)) { yield return item; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } } private static TypeDefinition FindType(ModuleDefinition module, string fullName) { return AllTypes(module).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition x) => ((MemberReference)x).FullName == fullName)) ?? throw new InvalidOperationException("type not found: " + fullName); } private static MethodDefinition FindMethod(TypeDefinition type, string name) { return ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition x) => ((MemberReference)x).Name == name)) ?? throw new InvalidOperationException("method not found: " + ((MemberReference)type).FullName + "." + name); } private static bool IsCall(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0018: Unknown result type (might be due to invalid IL or missing references) if (!(i.OpCode == OpCodes.Call)) { return i.OpCode == OpCodes.Callvirt; } return true; } private static void FixCharacterMessage(ModuleDefinition module, Action<string> log) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown MethodReference val = null; int num = 0; string[][] messageTargets = MessageTargets; foreach (string[] array in messageTargets) { MethodDefinition obj = FindMethod(FindType(module, array[0]), array[1]); ILProcessor iLProcessor = obj.Body.GetILProcessor(); List<Instruction> list = ((IEnumerable<Instruction>)obj.Body.Instructions).Where(delegate(Instruction val4) { if (IsCall(val4)) { object operand = val4.Operand; MethodReference val5 = (MethodReference)((operand is MethodReference) ? operand : null); if (val5 != null && ((MemberReference)val5).Name == "Message" && ((MemberReference)((MemberReference)val5).DeclaringType).FullName == "Character") { return val5.Parameters.Count == 4; } } return false; }).ToList(); if (list.Count == 0) { throw new InvalidOperationException("no stale Character.Message call in " + array[0] + "." + array[1]); } if (val == null) { MethodReference val2 = (MethodReference)list[0].Operand; MethodReference val3 = new MethodReference("Message", module.TypeSystem.Void, ((MemberReference)val2).DeclaringType) { HasThis = true }; Enumerator<ParameterDefinition> enumerator = val2.Parameters.GetEnumerator(); try { while (enumerator.MoveNext()) { ParameterDefinition current = enumerator.Current; val3.Parameters.Add(new ParameterDefinition(((ParameterReference)current).ParameterType)); } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } val3.Parameters.Add(new ParameterDefinition(module.TypeSystem.Boolean)); val = module.ImportReference(val3); } foreach (Instruction item in list) { iLProcessor.InsertBefore(item, Instruction.Create(OpCodes.Ldc_I4_0)); item.Operand = val; num++; } } log($"Character.Message: retargeted {num} call site(s) to the 5-arg overload"); } private static void FixZRoutedRpcEverybody(ModuleDefinition module, Action<string> log) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) int num = 0; string[][] everybodyTargets = EverybodyTargets; foreach (string[] array in everybodyTargets) { List<Instruction> list = ((IEnumerable<Instruction>)FindMethod(FindType(module, array[0]), array[1]).Body.Instructions).Where(delegate(Instruction val) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (val.OpCode == OpCodes.Ldsfld) { object operand = val.Operand; FieldReference val2 = (FieldReference)((operand is FieldReference) ? operand : null); if (val2 != null) { return ((MemberReference)val2).Name == "Everybody"; } } return false; }).ToList(); if (list.Count == 0) { throw new InvalidOperationException("no ldsfld Everybody in " + array[0] + "." + array[1]); } foreach (Instruction item in list) { item.OpCode = OpCodes.Ldc_I8; item.Operand = 0L; num++; } } log($"ZRoutedRpc.Everybody: replaced {num} field load(s) with the literal 0"); } private static void FixInventoryChanged(ModuleDefinition module, Action<string> log) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) MethodReference val = null; int num = 0; string[][] changedTargets = ChangedTargets; foreach (string[] array in changedTargets) { MethodDefinition obj = FindMethod(FindType(module, array[0]), array[1]); ILProcessor iLProcessor = obj.Body.GetILProcessor(); List<Instruction> list = ((IEnumerable<Instruction>)obj.Body.Instructions).Where(delegate(Instruction val4) { if (IsCall(val4)) { object operand = val4.Operand; MethodReference val5 = (MethodReference)((operand is MethodReference) ? operand : null); if (val5 != null && ((MemberReference)val5).Name == "Changed" && ((MemberReference)((MemberReference)val5).DeclaringType).FullName == "Inventory") { return val5.Parameters.Count == 0; } } return false; }).ToList(); if (list.Count == 0) { throw new InvalidOperationException("no stale Inventory.Changed() call in " + array[0] + "." + array[1]); } if (val == null) { MethodReference val2 = (MethodReference)list[0].Operand; MethodReference val3 = new MethodReference("Changed", module.TypeSystem.Void, ((MemberReference)val2).DeclaringType) { HasThis = true }; val3.Parameters.Add(new ParameterDefinition(module.TypeSystem.Boolean)); val3.Parameters.Add(new ParameterDefinition(module.TypeSystem.Boolean)); val = module.ImportReference(val3); } foreach (Instruction item in list) { iLProcessor.InsertBefore(item, Instruction.Create(OpCodes.Ldc_I4_0)); iLProcessor.InsertBefore(item, Instruction.Create(OpCodes.Ldc_I4_0)); item.Operand = val; num++; } } log($"Inventory.Changed: retargeted {num} call site(s) to the 2-arg overload"); } private static TypeReference SplitDialogRef(ModuleDefinition module) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown TypeReference val = module.GetTypeReferences().First((TypeReference r) => ((MemberReference)r).FullName == "InventoryGui"); return module.ImportReference(new TypeReference("", "SplitDialog", module, val.Scope)); } private static void FixSplitPanelField(ModuleDefinition module, Action<string> log) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown List<Instruction> list = ((IEnumerable<Instruction>)FindMethod(FindType(module, "QuickStackStore.TrashModule"), "ShowBaseConfirmDialog").Body.Instructions).Where(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Ldfld) { object operand = i.Operand; FieldReference val3 = (FieldReference)((operand is FieldReference) ? operand : null); if (val3 != null) { return ((MemberReference)val3).Name == "m_splitPanel"; } } return false; }).ToList(); if (list.Count == 0) { throw new InvalidOperationException("no ldfld m_splitPanel in TrashModule.ShowBaseConfirmDialog"); } TypeReference val = SplitDialogRef(module); foreach (Instruction item in list) { FieldReference val2 = (FieldReference)item.Operand; item.Operand = module.ImportReference(new FieldReference("m_splitDialog", val, ((MemberReference)val2).DeclaringType)); } log($"InventoryGui.m_splitPanel: retargeted {list.Count} field load(s) to m_splitDialog"); } private static void FixClickHandlerTargets(ModuleDefinition module, Action<string> log) { TypeDefinition type = FindType(module, "QuickStackStore.InventoryGridButtonHandlingPatches"); RetargetHarmonyPatch(type, "OnLeftClick", "OnLeftClick", "OnLeftDown", log); RetargetHarmonyPatch(type, "OnRightClick", "OnRightClick", "OnRightDown", log); } private static void RetargetHarmonyPatch(TypeDefinition type, string patchMethod, string oldTarget, string newTarget, Action<string> log) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) foreach (CustomAttribute item in ((IEnumerable<CustomAttribute>)FindMethod(type, patchMethod).CustomAttributes).Where((CustomAttribute a) => ((MemberReference)a.AttributeType).Name == "HarmonyPatch")) { for (int num = 0; num < item.ConstructorArguments.Count; num++) { CustomAttributeArgument val = item.ConstructorArguments[num]; if (!(((MemberReference)((CustomAttributeArgument)(ref val)).Type).FullName != "System.String") && !((string)((CustomAttributeArgument)(ref val)).Value != oldTarget)) { item.ConstructorArguments[num] = new CustomAttributeArgument(((CustomAttributeArgument)(ref val)).Type, (object)newTarget); log(patchMethod + ": [HarmonyPatch(\"" + oldTarget + "\")] -> [HarmonyPatch(\"" + newTarget + "\")]"); return; } } } throw new InvalidOperationException("no [HarmonyPatch(\"" + oldTarget + "\")] on " + patchMethod); } private static void FixInventoryGridElement(ModuleDefinition module, Action<string> log) { TypeReference? obj = module.GetTypeReferences().FirstOrDefault((Func<TypeReference, bool>)((TypeReference r) => ((MemberReference)r).FullName == "InventoryGrid/Element")) ?? throw new InvalidOperationException("no TypeReference to InventoryGrid/Element"); TypeReference val = module.GetTypeReferences().First((TypeReference r) => ((MemberReference)r).FullName == "InventoryGrid"); ((MemberReference)obj).DeclaringType = null; obj.Namespace = ""; ((MemberReference)obj).Name = "InventoryElement"; obj.Scope = val.Scope; log("InventoryGrid/Element: repointed to top-level InventoryElement"); } private static void FixTooltipPatchSignature(ModuleDefinition module, Action<string> log) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) MethodDefinition val = FindMethod(FindType(module, "QuickStackStore.TooltipRenderer"), "GetTooltip"); TypeReference val2 = module.GetTypeReferences().First((TypeReference r) => ((MemberReference)r).FullName == "ItemDrop/ItemData"); TypeReference[] source = (TypeReference[])(object)new TypeReference[6] { val2, module.TypeSystem.Int32, module.TypeSystem.Boolean, module.TypeSystem.Single, module.TypeSystem.Int32, module.TypeSystem.Boolean }; foreach (CustomAttribute item in ((IEnumerable<CustomAttribute>)val.CustomAttributes).Where((CustomAttribute a) => ((MemberReference)a.AttributeType).Name == "HarmonyPatch")) { for (int num = 0; num < item.ConstructorArguments.Count; num++) { CustomAttributeArgument val3 = item.ConstructorArguments[num]; if (!(((MemberReference)((CustomAttributeArgument)(ref val3)).Type).FullName != "System.Type[]")) { TypeReference elementType = ((CustomAttributeArgument)(ref val3)).Type.GetElementType(); CustomAttributeArgument[] array = ((IEnumerable<TypeReference>)source).Select((Func<TypeReference, CustomAttributeArgument>)((TypeReference t) => new CustomAttributeArgument(elementType, (object)t))).ToArray(); item.ConstructorArguments[num] = new CustomAttributeArgument(((CustomAttributeArgument)(ref val3)).Type, (object)array); log("TooltipRenderer.GetTooltip: declared argument types updated to the 6-parameter overload"); return; } } } throw new InvalidOperationException("no Type[] argument on TooltipRenderer.GetTooltip's [HarmonyPatch]"); } private static void FixHasRandyPlugin(ModuleDefinition module, Action<string> log) { //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown MethodDefinition obj = FindMethod(FindType(module, "QuickStackStore.CompatibilitySupport"), "HasRandyPlugin"); TypeReference catchType = (from h in ((IEnumerable<MethodDefinition>)FindType(module, "QuickStackStore.QSSConfig").Methods).Where((MethodDefinition m) => m.HasBody).SelectMany((MethodDefinition m) => (IEnumerable<ExceptionHandler>)m.Body.ExceptionHandlers) select h.CatchType).First((TypeReference c) => c != null && ((MemberReference)c).FullName == "System.Exception"); Instruction next = ((IEnumerable<Instruction>)obj.Body.Instructions).First(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Stsfld) { object operand = i.Operand; FieldReference val4 = (FieldReference)((operand is FieldReference) ? operand : null); if (val4 != null) { return ((MemberReference)val4).Name == "RandyQuickSlotsEnabled"; } } return false; }).Next; Instruction landing = next.Next; Instruction next2 = ((IEnumerable<Instruction>)obj.Body.Instructions).First((Instruction i) => (i.OpCode == OpCodes.Brfalse || i.OpCode == OpCodes.Brfalse_S) && i.Operand == landing).Next; ILProcessor iLProcessor = obj.Body.GetILProcessor(); Instruction val = Instruction.Create(OpCodes.Leave, landing); Instruction val2 = Instruction.Create(OpCodes.Pop); Instruction val3 = Instruction.Create(OpCodes.Leave, landing); iLProcessor.InsertAfter(next, val); iLProcessor.InsertAfter(val, val2); iLProcessor.InsertAfter(val2, val3); obj.Body.ExceptionHandlers.Add(new ExceptionHandler((ExceptionHandlerType)0) { TryStart = next2, TryEnd = val2, HandlerStart = val2, HandlerEnd = landing, CatchType = catchType }); log("HasRandyPlugin: reflection block wrapped in catch(Exception), falls through to EnabledWithQuickSlots"); } private static void FixTrashDialogSplitDialogClone(ModuleDefinition module, Action<string> log) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) MethodBody body = FindMethod(FindType(module, "QuickStackStore.TrashModule"), "ShowBaseConfirmDialog").Body; ILProcessor iLProcessor = body.GetILProcessor(); Instruction val = ((IEnumerable<Instruction>)body.Instructions).First(delegate(Instruction i) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (i.OpCode == OpCodes.Stsfld) { object operand = i.Operand; FieldReference val10 = (FieldReference)((operand is FieldReference) ? operand : null); if (val10 != null) { return ((MemberReference)val10).Name == "dialog"; } } return false; }); MethodReference val2 = (MethodReference)((IEnumerable<Instruction>)body.Instructions).First(delegate(Instruction i) { object operand = i.Operand; MethodReference val10 = (MethodReference)((operand is MethodReference) ? operand : null); return val10 != null && ((MemberReference)val10).Name == "get_transform" && ((MemberReference)((MemberReference)val10).DeclaringType).FullName == "UnityEngine.GameObject"; }).Operand; MethodReference val3 = (MethodReference)((IEnumerable<Instruction>)body.Instructions).First(delegate(Instruction i) { object operand = i.Operand; MethodReference val10 = (MethodReference)((operand is MethodReference) ? operand : null); return val10 != null && ((MemberReference)val10).Name == "GetComponent"; }).Operand; MethodReference val4 = (MethodReference)(from m in AllTypes(module).SelectMany((TypeDefinition t) => (IEnumerable<MethodDefinition>)t.Methods) where m.HasBody select m).SelectMany((MethodDefinition m) => (IEnumerable<Instruction>)m.Body.Instructions).First(delegate(Instruction i) { object operand = i.Operand; MethodReference val10 = (MethodReference)((operand is MethodReference) ? operand : null); return val10 != null && ((MemberReference)val10).Name == "set_enabled" && ((MemberReference)((MemberReference)val10).DeclaringType).FullName == "UnityEngine.Behaviour"; }).Operand; TypeReference val5 = SplitDialogRef(module); GenericInstanceMethod val6 = new GenericInstanceMethod(val3.GetElementMethod()); val6.GenericArguments.Add(val5); VariableDefinition val7 = new VariableDefinition(val5); body.Variables.Add(val7); Instruction next = val.Next; Instruction[] obj = new Instruction[9] { Instruction.Create(OpCodes.Ldsfld, (FieldReference)val.Operand), Instruction.Create(OpCodes.Callvirt, val2), Instruction.Create(OpCodes.Call, (MethodReference)(object)val6), Instruction.Create(OpCodes.Stloc, val7), Instruction.Create(OpCodes.Ldloc, val7), Instruction.Create(OpCodes.Brfalse, next), Instruction.Create(OpCodes.Ldloc, val7), Instruction.Create(OpCodes.Ldc_I4_0), Instruction.Create(OpCodes.Callvirt, val4) }; Instruction val8 = val; Instruction[] array = (Instruction[])(object)obj; foreach (Instruction val9 in array) { iLProcessor.InsertAfter(val8, val9); val8 = val9; } log("TrashModule.ShowBaseConfirmDialog: cloned SplitDialog component disabled before SetActive"); } } }