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 OldModCompat v1.0.0
patchers/OldModCompat.dll
Decompiled 3 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(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("LegacyCompat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LegacyCompat")] [assembly: AssemblyTitle("LegacyCompat")] [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; } } } public static class LegacyCompat { private static readonly ManualLogSource Log = Logger.CreateLogSource("LegacyCompat"); private static readonly (string Type, string Old, int Params, string New)[] Calls = new(string, string, int, string)[5] { ("MenuManager", "DisplayMenuNotification", 2, "DisplayMenuNotification"), ("GameNetcodeStuff.PlayerControllerB", "KillPlayer", 5, "KillPlayer"), ("GameNetcodeStuff.PlayerControllerB", "HasLineOfSightToPosition", 4, "HasLineOfSightToPosition"), ("GameNetcodeStuff.PlayerControllerB", "DropAllHeldItemsServerRpc", 0, "DropAllHeldItemsAndSyncNonexact"), ("SpawnableEnemyWithRarity", ".ctor", 0, ".ctor") }; public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" }; public static void Initialize() { FixPlugins(Paths.PluginPath, Paths.ManagedPath); } public static void Patch(AssemblyDefinition assembly) { ForwardDunGen(assembly.MainModule); } public static void ForwardDunGen(ModuleDefinition module) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown int num = 0; foreach (AssemblyNameReference item in ((IEnumerable<AssemblyNameReference>)module.AssemblyReferences).Where((AssemblyNameReference r) => r.Name.StartsWith("DunGen")).ToList()) { Enumerator<TypeDefinition> enumerator2 = module.AssemblyResolver.Resolve(item).MainModule.Types.GetEnumerator(); try { while (enumerator2.MoveNext()) { TypeDefinition type = enumerator2.Current; if (!(((MemberReference)type).Name == "<Module>") && module.GetType(((MemberReference)type).FullName) == null && !((IEnumerable<ExportedType>)module.ExportedTypes).Any((ExportedType e) => e.FullName == ((MemberReference)type).FullName)) { module.ExportedTypes.Add(new ExportedType(((TypeReference)type).Namespace, ((MemberReference)type).Name, module, (IMetadataScope)(object)item) { IsForwarder = true }); num++; } } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } } Log.LogInfo((object)$"Forwarded {num} DunGen types"); } public static void FixPlugins(string pluginPath, string managedPath) { ModuleDefinition val = ModuleDefinition.ReadModule(Path.Combine(managedPath, "Assembly-CSharp.dll")); try { Dictionary<(string, string, int), MethodDefinition> dictionary = new Dictionary<(string, string, int), MethodDefinition>(); (string, string, int, string)[] calls = Calls; for (int i = 0; i < calls.Length; i++) { (string Type, string Old, int Params, string New) c = calls[i]; TypeDefinition type = val.GetType(c.Type); MethodDefinition val2 = ((type != null) ? ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => (((MemberReference)m).Name == c.New && ((MethodReference)m).Parameters.Count > c.Params) || (((MemberReference)m).Name == c.New && c.Old != c.New && ((MethodReference)m).Parameters.Count == c.Params))) : null); if (val2 != null && ((IEnumerable<ParameterDefinition>)((MethodReference)val2).Parameters).Skip(c.Params).All(CanFill)) { dictionary[(c.Type, c.Old, c.Params)] = val2; continue; } Log.LogWarning((object)(c.Type + "." + c.New + ": v80 target not found, not rewriting " + c.Old)); } string[] files = Directory.GetFiles(pluginPath, "*.dll", SearchOption.AllDirectories); foreach (string text in files) { char directorySeparatorChar = Path.DirectorySeparatorChar; string text2 = directorySeparatorChar.ToString(); directorySeparatorChar = Path.DirectorySeparatorChar; if (!text.Contains(text2 + "MMHOOK" + directorySeparatorChar)) { try { FixPlugin(text, dictionary); } catch (Exception ex) { Log.LogError((object)("Could not fix " + Path.GetFileName(text) + ": " + ex.Message)); } } } } finally { ((IDisposable)val)?.Dispose(); } } private static void FixPlugin(string path, Dictionary<(string, string, int), MethodDefinition> targets) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown byte[] buffer = File.ReadAllBytes(path); ModuleDefinition val; try { val = ModuleDefinition.ReadModule((Stream)new MemoryStream(buffer), new ReaderParameters { ReadingMode = (ReadingMode)2 }); } catch { return; } ModuleDefinition val2 = val; try { if (!val.GetMemberReferences().Any(delegate(MemberReference r) { MethodReference val3 = (MethodReference)(object)((r is MethodReference) ? r : null); return val3 != null && targets.ContainsKey((((MemberReference)((MemberReference)val3).DeclaringType).FullName, ((MemberReference)val3).Name, val3.Parameters.Count)); }) && !val.GetMemberReferences().Any(IsDarkenField)) { return; } int num = 0; int num2 = 0; foreach (MethodDefinition item in from m in val.GetTypes().SelectMany((TypeDefinition t) => (IEnumerable<MethodDefinition>)t.Methods) where m.HasBody select m) { num += RewriteCalls(val, item, targets); num2 += RemoveDarkenScreen(item); } if (num + num2 != 0) { val.Write(path); Log.LogInfo((object)$"Rewrote {num} old call(s), {num2} removed-field use(s) in {Path.GetFileName(path)}"); } } finally { ((IDisposable)val2)?.Dispose(); } } private static bool IsIntLike(TypeReference t) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((int)t.MetadataType != 2) { return (int)t.MetadataType == 8; } return true; } private static bool CanFill(ParameterDefinition p) { if (!p.HasConstant && ((ParameterReference)p).ParameterType.IsValueType) { return IsIntLike(((ParameterReference)p).ParameterType); } return true; } private static TypeReference Import(ModuleDefinition module, TypeReference t) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((int)t.MetadataType != 2) { if ((int)t.MetadataType != 8) { return module.ImportReference(t); } return module.TypeSystem.Int32; } return module.TypeSystem.Boolean; } private static int RewriteCalls(ModuleDefinition module, MethodDefinition method, Dictionary<(string, string, int), MethodDefinition> targets) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) int num = 0; ILProcessor iLProcessor = method.Body.GetILProcessor(); foreach (Instruction item in ((IEnumerable<Instruction>)method.Body.Instructions).ToList()) { object operand = item.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val == null || (item.OpCode != OpCodes.Call && item.OpCode != OpCodes.Callvirt && item.OpCode != OpCodes.Newobj) || !targets.TryGetValue((((MemberReference)((MemberReference)val).DeclaringType).FullName, ((MemberReference)val).Name, val.Parameters.Count), out var value)) { continue; } MethodReference val2 = new MethodReference(((MemberReference)value).Name, val.ReturnType, ((MemberReference)val).DeclaringType) { HasThis = val.HasThis, ExplicitThis = val.ExplicitThis, CallingConvention = val.CallingConvention }; Enumerator<ParameterDefinition> enumerator2 = val.Parameters.GetEnumerator(); try { while (enumerator2.MoveNext()) { ParameterDefinition current2 = enumerator2.Current; val2.Parameters.Add(new ParameterDefinition(((ParameterReference)current2).ParameterType)); } } finally { ((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose(); } List<ParameterDefinition> list = ((IEnumerable<ParameterDefinition>)((MethodReference)value).Parameters).Skip(val.Parameters.Count).ToList(); foreach (ParameterDefinition item2 in list) { val2.Parameters.Add(new ParameterDefinition(Import(module, ((ParameterReference)item2).ParameterType))); } Instruction val3 = iLProcessor.Create(item.OpCode, val2); if (list.Count == 0) { item.Operand = val2; num++; continue; } Instruction val4 = Fill(iLProcessor, list[0]); item.OpCode = val4.OpCode; item.Operand = val4.Operand; Instruction val5 = item; foreach (ParameterDefinition item3 in list.Skip(1)) { Instruction val6 = Fill(iLProcessor, item3); iLProcessor.InsertAfter(val5, val6); val5 = val6; } iLProcessor.InsertAfter(val5, val3); num++; } return num; } private static Instruction Fill(ILProcessor il, ParameterDefinition p) { //IL_001f: 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_0067: 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) if (p.HasConstant && p.Constant is bool flag) { return il.Create(OpCodes.Ldc_I4, flag ? 1 : 0); } if (p.HasConstant && p.Constant is int num) { return il.Create(OpCodes.Ldc_I4, num); } if (IsIntLike(((ParameterReference)p).ParameterType)) { return il.Create(OpCodes.Ldc_I4_0); } return il.Create(OpCodes.Ldnull); } private static bool IsDarkenField(MemberReference r) { FieldReference val = (FieldReference)(object)((r is FieldReference) ? r : null); if (val != null && ((MemberReference)val).Name == "loadingDarkenScreen") { return ((MemberReference)((MemberReference)val).DeclaringType).FullName == "HUDManager"; } return false; } private static int RemoveDarkenScreen(MethodDefinition method) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //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_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_00cc: 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) int num = 0; Collection<Instruction> instructions = method.Body.Instructions; for (int i = 0; i + 2 < instructions.Count; i++) { if (instructions[i].OpCode == OpCodes.Ldfld && IsDarkenField((MemberReference)/*isinst with value type is only supported in some contexts*/) && (instructions[i + 1].OpCode == OpCodes.Ldc_I4_0 || instructions[i + 1].OpCode == OpCodes.Ldc_I4_1) && instructions[i + 2].OpCode == OpCodes.Callvirt) { object operand = instructions[i + 2].Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); if (val != null && ((MemberReference)val).Name == "set_enabled") { instructions[i].OpCode = OpCodes.Pop; instructions[i].Operand = null; instructions[i + 2].OpCode = OpCodes.Pop; instructions[i + 2].Operand = null; num++; } } } return num; } }