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 SCP3166Fix v1.0.1
BepInEx\patchers\SCP3166Fix\SCP3166Fix.dll
Decompiled 10 hours 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 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.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("v0id")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Preloader compatibility patch for ProjectSCP's SCP3166 in modern Lethal Company versions.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("SCP3166Fix")] [assembly: AssemblyTitle("SCP3166Fix")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 SCP3166Fix { public static class Patcher { private static readonly ManualLogSource Logger = Logger.CreateLogSource("SCP3166Fix"); public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "ProjectSCP.SCP3166.dll" }; public static void Initialize() { Logger.LogInfo((object)"Preloader initialized. Scanning for ProjectSCP.SCP3166.dll..."); try { string pluginPath = Paths.PluginPath; if (Directory.Exists(pluginPath)) { string[] files = Directory.GetFiles(pluginPath, "ProjectSCP.SCP3166.dll", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { TryPatchFile(files[i]); } } } catch (Exception arg) { Logger.LogError((object)$"Error during scan/patch: {arg}"); } } public static void Patch(AssemblyDefinition assembly) { if (((AssemblyNameReference)assembly.Name).Name == "ProjectSCP.SCP3166") { PatchAssembly(assembly, null); } } public static void Finish() { } public static bool TryPatchFile(string filePath) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown try { DefaultAssemblyResolver val = new DefaultAssemblyResolver(); ((BaseAssemblyResolver)val).AddSearchDirectory(Paths.ManagedPath); ((BaseAssemblyResolver)val).AddSearchDirectory(Paths.BepInExAssemblyDirectory); string directoryName = Path.GetDirectoryName(filePath); if (!string.IsNullOrEmpty(directoryName)) { ((BaseAssemblyResolver)val).AddSearchDirectory(directoryName); } using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(filePath)); ReaderParameters val2 = new ReaderParameters { AssemblyResolver = (IAssemblyResolver)(object)val }; AssemblyDefinition val3 = AssemblyDefinition.ReadAssembly((Stream)memoryStream, val2); try { if (PatchAssembly(val3, (IAssemblyResolver?)(object)val)) { string text = filePath + ".orig"; if (!File.Exists(text)) { File.Copy(filePath, text, overwrite: false); } using MemoryStream memoryStream2 = new MemoryStream(); val3.Write((Stream)memoryStream2); File.WriteAllBytes(filePath, memoryStream2.ToArray()); Logger.LogInfo((object)("Successfully patched and updated: " + filePath)); return true; } Logger.LogInfo((object)(filePath + " is already compatible / patched.")); } finally { ((IDisposable)val3)?.Dispose(); } } catch (Exception arg) { Logger.LogError((object)$"Failed to patch {filePath}: {arg}"); } return false; } private static bool PatchAssembly(AssemblyDefinition asm, IAssemblyResolver? resolver) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) string text = Path.Combine(Paths.ManagedPath, "Assembly-CSharp.dll"); if (!File.Exists(text)) { Logger.LogWarning((object)("Assembly-CSharp.dll not found at " + text)); return false; } ReaderParameters val = new ReaderParameters { AssemblyResolver = resolver }; AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(text, val); try { ModuleDefinition mainModule = val2.MainModule; TypeDefinition type = mainModule.GetType("EnemyAI"); MethodDefinition val3 = ((type != null) ? ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == "PlayerIsTargetable" && ((MethodReference)m).Parameters.Count == 4)) : null); TypeDefinition type2 = mainModule.GetType("EntranceTeleport"); FieldDefinition val4 = ((type2 != null) ? ((IEnumerable<FieldDefinition>)type2.Fields).FirstOrDefault((Func<FieldDefinition, bool>)((FieldDefinition f) => ((MemberReference)f).Name == "entrancePoint")) : null); if (val3 == null || val4 == null) { Logger.LogWarning((object)"Failed to resolve required modern target symbols from Assembly-CSharp.dll"); return false; } ModuleDefinition mainModule2 = asm.MainModule; MethodReference operand = mainModule2.ImportReference((MethodReference)(object)val3); FieldReference operand2 = mainModule2.ImportReference((FieldReference)(object)val4); int num = 0; Enumerator<TypeDefinition> enumerator = mainModule2.Types.GetEnumerator(); try { while (enumerator.MoveNext()) { Enumerator<MethodDefinition> enumerator2 = enumerator.Current.Methods.GetEnumerator(); try { while (enumerator2.MoveNext()) { MethodDefinition current = enumerator2.Current; if (!current.HasBody) { continue; } ILProcessor iLProcessor = current.Body.GetILProcessor(); Instruction[] array = current.Body.Instructions.ToArray(); foreach (Instruction val5 in array) { if (val5.Operand == null) { continue; } string? text2 = val5.Operand.ToString(); if (text2.Contains("PlayerIsTargetable")) { object operand3 = val5.Operand; MethodReference val6 = (MethodReference)((operand3 is MethodReference) ? operand3 : null); if (val6 != null && val6.Parameters.Count == 3) { Instruction val7 = Instruction.Create(OpCodes.Ldc_I4_0); iLProcessor.InsertBefore(val5, val7); val5.Operand = operand; num++; } } if (text2.Contains("EntranceTeleport::exitPoint")) { val5.Operand = operand2; num++; } } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } return num > 0; } finally { ((IDisposable)val2)?.Dispose(); } } } }