Please disclose if your mod was created primarily 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 Instance Method Injector v1.0.0
BepInEx/patchers/Daydream.InstanceMethodInjector.dll
Decompiled 2 years 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.InteropServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using Mono.Cecil; using Mono.Cecil.Cil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Daydream.InstanceMethodInjector")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Daydream.InstanceMethodInjector")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8D6B7A3E-C51F-4A44-8D6F-59A3565273B8")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace Daydream.InstanceMethodInjector; internal class ComparableMethod { internal readonly string TypeName; internal readonly string MethodName; internal readonly CustomAttributeArgument[] Arguments; internal string ArgumentsComp => ArgumentsCompiled(((IEnumerable<CustomAttributeArgument>)Arguments).Select((Func<CustomAttributeArgument, TypeReference>)((CustomAttributeArgument attr) => (TypeReference)((CustomAttributeArgument)(ref attr)).Value)).ToArray()); internal static string ArgumentsCompiled(TypeReference[] args) { return string.Join(", ", args?.Select((TypeReference argument) => ((MemberReference)argument).Name).ToArray() ?? new string[0]); } public override string ToString() { return TypeName + "." + MethodName + "(" + ArgumentsComp + ")"; } internal bool IsEqual(MethodDefinition methodDef) { if (MethodName == ((MemberReference)methodDef).Name && TypeName == ((MemberReference)methodDef.DeclaringType).FullName) { return ArgumentsComp == ArgumentsCompiled(((IEnumerable<ParameterDefinition>)((MethodReference)methodDef).Parameters).Select((ParameterDefinition par) => ((ParameterReference)par).ParameterType).ToArray()); } return false; } internal bool IsEqual(ComparableMethod other) { if (TypeName == other.TypeName && MethodName == other.MethodName) { return ArgumentsComp == other.ArgumentsComp; } return false; } private ComparableMethod(string typeName, string methodName, CustomAttributeArgument[] parameters) { TypeName = typeName; MethodName = methodName; Arguments = parameters; } internal static ComparableMethod FromCecilConstructor(CustomAttribute attribute) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (((MemberReference)attribute.AttributeType).FullName != typeof(RequiresMethodAttribute).FullName) { return null; } CustomAttributeArgument val = attribute.ConstructorArguments[0]; string fullName = ((MemberReference)(TypeReference)((CustomAttributeArgument)(ref val)).Value).FullName; val = attribute.ConstructorArguments[1]; string methodName = (string)((CustomAttributeArgument)(ref val)).Value; val = attribute.ConstructorArguments[2]; return new ComparableMethod(fullName, methodName, (CustomAttributeArgument[])((CustomAttributeArgument)(ref val)).Value); } } public static class Preloader { internal class CacheData : ICacheable { void ICacheable.Save(BinaryWriter bw) { } void ICacheable.Load(BinaryReader br) { } } private const string CacheName = "instance_injector"; internal static ManualLogSource Logger { get; set; } private static Dictionary<string, List<ComparableMethod>> RequiresMethods { get; set; } public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" }; public static void Initialize() { Logger = Logger.CreateLogSource("DayDream.InstanceMethodInjector"); RequiresMethods = FindRequiredMethods(Paths.PluginPath); } public static void Patch(AssemblyDefinition assemblyDefinition) { TypeDefinition[] array = assemblyDefinition.MainModule.GetTypes().ToArray(); foreach (TypeDefinition val in array) { if (!RequiresMethods.TryGetValue(((MemberReference)val).FullName, out var value)) { continue; } foreach (ComparableMethod item in value) { CreateDesiredMethod(val, item); } } assemblyDefinition.Write(Path.Combine(Paths.CachePath, "Assembly-CSharp.dll")); } private static Dictionary<string, List<ComparableMethod>> FindRequiredMethods(string directory) { Dictionary<string, List<ComparableMethod>> dictionary = new Dictionary<string, List<ComparableMethod>>(); Dictionary<string, CachedAssembly<CacheData>> dictionary2 = TypeLoader.LoadAssemblyCache<CacheData>("instance_injector") ?? new Dictionary<string, CachedAssembly<CacheData>>(); Logger.LogWarning((object)string.Format("Ignoring {0} disregarded plugin{1}.", dictionary2.Count, (dictionary2.Count == 1) ? "" : "s")); string[] files = Directory.GetFiles(Path.GetFullPath(directory), "*.dll", SearchOption.AllDirectories); foreach (string text in files) { try { if (dictionary2.TryGetValue(text, out var value) && value.Timestamp == File.GetLastWriteTimeUtc(text).Ticks) { continue; } if (dictionary2.ContainsKey(text)) { dictionary2.Remove(text); } AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text, TypeLoader.ReaderParameters); int num = 0; foreach (ComparableMethod comp in ((IEnumerable<CustomAttribute>)val.CustomAttributes).Select(ComparableMethod.FromCecilConstructor)) { if (comp != null) { if (!dictionary.ContainsKey(comp.TypeName)) { dictionary.Add(comp.TypeName, new List<ComparableMethod>()); } num++; if (dictionary[comp.TypeName].All((ComparableMethod compCheck) => !compCheck.IsEqual(comp))) { Logger.LogInfo((object)(((AssemblyNameReference)val.Name).Name + " queued method '" + comp?.ToString() + "' for creation!")); dictionary[comp.TypeName].Add(comp); } else { Logger.LogWarning((object)(((AssemblyNameReference)val.Name).Name + " skipped queuing method '" + comp?.ToString() + "' because it's already queued.")); } } } if (num == 0) { Logger.LogWarning((object)("Disregarding " + Path.GetFileName(text) + " for future loads due to requiring no additional methods.")); dictionary2.Add(text, new CachedAssembly<CacheData> { CacheItems = new List<CacheData> { new CacheData() }, Timestamp = 0L }); val.Dispose(); } else { val.Dispose(); } } catch (BadImageFormatException ex) { Logger.LogDebug((object)("Skipping loading " + text + " because it's not a valid .NET assembly. Full error: " + ex.Message)); } catch (Exception ex2) { Logger.LogError((object)ex2.ToString()); } } Dictionary<string, List<CacheData>> dictionary3 = dictionary2.ToDictionary((KeyValuePair<string, CachedAssembly<CacheData>> keyValuePair) => keyValuePair.Key, (KeyValuePair<string, CachedAssembly<CacheData>> keyValuePair) => keyValuePair.Value.CacheItems); TypeLoader.SaveAssemblyCache<CacheData>("instance_injector", dictionary3); return dictionary; } private static void CreateDesiredMethod(TypeDefinition typeDefinition, ComparableMethod requiredMethod) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Expected O, but got Unknown MethodDefinition val = new MethodDefinition(requiredMethod.MethodName, (MethodAttributes)198, ((MemberReference)typeDefinition).Module.TypeSystem.Void); if (((IEnumerable<MethodDefinition>)typeDefinition.Methods).Any(requiredMethod.IsEqual)) { Logger.LogError((object)("Skipping " + requiredMethod.TypeName + ":" + requiredMethod.MethodName + " because it already contains a definition.")); return; } Dictionary<string, int> dictionary = new Dictionary<string, int>(); Dictionary<string, int> dictionary2 = new Dictionary<string, int>(); CustomAttributeArgument[] arguments = requiredMethod.Arguments; for (int i = 0; i < arguments.Length; i++) { CustomAttributeArgument val2 = arguments[i]; TypeReference val3 = (TypeReference)((CustomAttributeArgument)(ref val2)).Value; string key = (val3.IsGenericInstance ? ((MemberReference)val3).Name.Substring(0, ((MemberReference)val3).Name.IndexOf('`')) : ((MemberReference)val3).Name); if (!dictionary2.ContainsKey(key)) { dictionary2.Add(key, 0); } if (!dictionary.ContainsKey(key)) { dictionary.Add(key, 0); } dictionary[key]++; } arguments = requiredMethod.Arguments; TypeReference val6 = default(TypeReference); for (int i = 0; i < arguments.Length; i++) { CustomAttributeArgument val4 = arguments[i]; TypeReference val5 = (TypeReference)((CustomAttributeArgument)(ref val4)).Value; string text = (val5.IsGenericInstance ? ((MemberReference)val5).Name.Substring(0, ((MemberReference)val5).Name.IndexOf('`')) : ((MemberReference)val5).Name); int num = dictionary[text]; int num2 = dictionary2[text]++; string text2 = "p" + text + ((num > 1) ? ("_" + num2) : ""); if (!((MemberReference)typeDefinition).Module.TryGetTypeReference(((MemberReference)val5).FullName, ref val6)) { val6 = ((MemberReference)typeDefinition).Module.ImportReference(val5); } ((MethodReference)val).Parameters.Add(new ParameterDefinition(text2, (ParameterAttributes)0, val6)); } typeDefinition.Methods.Add(val); val.Body.InitLocals = true; val.Body.GetILProcessor().Emit(OpCodes.Ret); } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public class RequiresMethodAttribute : Attribute { private readonly Type type; private readonly string methodName; private readonly Type[] parameterTypes; public RequiresMethodAttribute(Type type, string methodName, params Type[] parameterTypes) { this.type = type; this.methodName = methodName; this.parameterTypes = parameterTypes; } }