using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using HarmonyLib.Internal.Patching; using HarmonyLib.Internal.RuntimeFixes; using HarmonyLib.Internal.Util; using HarmonyLib.Public.Patching; using HarmonyLib.Tools; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Mdb; using Mono.Cecil.Pdb; using Mono.Cecil.Rocks; using Mono.Collections.Generic; using Mono.CompilerServices.SymbolWriter; using MonoMod.Cil; using MonoMod.Core.Platforms; using MonoMod.RuntimeDetour; using MonoMod.Utils; using MonoMod.Utils.Cil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: ComVisible(false)] [assembly: InternalsVisibleTo("HarmonyTests")] [assembly: InternalsVisibleTo("MonoMod.Utils.Cil.ILGeneratorProxy")] [assembly: Guid("69aee16a-b6e7-4642-8081-3928b32455df")] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("BepInEx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © BepInEx 2022")] [assembly: AssemblyDescription("A general non-destructive patch library for .NET and Mono modules")] [assembly: AssemblyFileVersion("2.16.1.0")] [assembly: AssemblyInformationalVersion("2.16.1+02a98f540fa12ac4656f189a3cf67b0c96cc68f7")] [assembly: AssemblyProduct("HarmonyX")] [assembly: AssemblyTitle("0Harmony")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/BepInEx/HarmonyX")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.16.1.0")] [assembly: TypeForwardedTo(typeof(AssemblyAttributes))] [assembly: TypeForwardedTo(typeof(AssemblyDefinition))] [assembly: TypeForwardedTo(typeof(AssemblyHashAlgorithm))] [assembly: TypeForwardedTo(typeof(AssemblyNameDefinition))] [assembly: TypeForwardedTo(typeof(AssemblyNameReference))] [assembly: TypeForwardedTo(typeof(AssemblyResolutionException))] [assembly: TypeForwardedTo(typeof(ByReferenceType))] [assembly: TypeForwardedTo(typeof(CallSite))] [assembly: TypeForwardedTo(typeof(Code))] [assembly: TypeForwardedTo(typeof(ConstantDebugInformation))] [assembly: TypeForwardedTo(typeof(CustomDebugInformation))] [assembly: TypeForwardedTo(typeof(CustomDebugInformationKind))] [assembly: TypeForwardedTo(typeof(DebugInformation))] [assembly: TypeForwardedTo(typeof(Document))] [assembly: TypeForwardedTo(typeof(DocumentHashAlgorithm))] [assembly: TypeForwardedTo(typeof(DocumentLanguage))] [assembly: TypeForwardedTo(typeof(DocumentLanguageVendor))] [assembly: TypeForwardedTo(typeof(DocumentType))] [assembly: TypeForwardedTo(typeof(ExceptionHandler))] [assembly: TypeForwardedTo(typeof(ExceptionHandlerType))] [assembly: TypeForwardedTo(typeof(FlowControl))] [assembly: TypeForwardedTo(typeof(ILProcessor))] [assembly: TypeForwardedTo(typeof(ImageDebugDirectory))] [assembly: TypeForwardedTo(typeof(ImageDebugHeader))] [assembly: TypeForwardedTo(typeof(ImageDebugHeaderEntry))] [assembly: TypeForwardedTo(typeof(ImageDebugType))] [assembly: TypeForwardedTo(typeof(ImportDebugInformation))] [assembly: TypeForwardedTo(typeof(ImportTarget))] [assembly: TypeForwardedTo(typeof(ImportTargetKind))] [assembly: TypeForwardedTo(typeof(Instruction))] [assembly: TypeForwardedTo(typeof(InstructionOffset))] [assembly: TypeForwardedTo(typeof(ISymbolReader))] [assembly: TypeForwardedTo(typeof(ISymbolReaderProvider))] [assembly: TypeForwardedTo(typeof(ISymbolWriter))] [assembly: TypeForwardedTo(typeof(ISymbolWriterProvider))] [assembly: TypeForwardedTo(typeof(MethodBody))] [assembly: TypeForwardedTo(typeof(MethodDebugInformation))] [assembly: TypeForwardedTo(typeof(OpCode))] [assembly: TypeForwardedTo(typeof(OpCodes))] [assembly: TypeForwardedTo(typeof(OpCodeType))] [assembly: TypeForwardedTo(typeof(OperandType))] [assembly: TypeForwardedTo(typeof(ScopeDebugInformation))] [assembly: TypeForwardedTo(typeof(SequencePoint))] [assembly: TypeForwardedTo(typeof(StackBehaviour))] [assembly: TypeForwardedTo(typeof(SymbolsNotFoundException))] [assembly: TypeForwardedTo(typeof(SymbolsNotMatchingException))] [assembly: TypeForwardedTo(typeof(VariableAttributes))] [assembly: TypeForwardedTo(typeof(VariableDebugInformation))] [assembly: TypeForwardedTo(typeof(VariableDefinition))] [assembly: TypeForwardedTo(typeof(VariableReference))] [assembly: TypeForwardedTo(typeof(CustomAttribute))] [assembly: TypeForwardedTo(typeof(CustomAttributeArgument))] [assembly: TypeForwardedTo(typeof(CustomAttributeNamedArgument))] [assembly: TypeForwardedTo(typeof(EventAttributes))] [assembly: TypeForwardedTo(typeof(EventDefinition))] [assembly: TypeForwardedTo(typeof(EventReference))] [assembly: TypeForwardedTo(typeof(ExportedType))] [assembly: TypeForwardedTo(typeof(FieldAttributes))] [assembly: TypeForwardedTo(typeof(FieldDefinition))] [assembly: TypeForwardedTo(typeof(FieldReference))] [assembly: TypeForwardedTo(typeof(GenericInstanceMethod))] [assembly: TypeForwardedTo(typeof(GenericInstanceType))] [assembly: TypeForwardedTo(typeof(GenericParameter))] [assembly: TypeForwardedTo(typeof(GenericParameterAttributes))] [assembly: TypeForwardedTo(typeof(GenericParameterConstraint))] [assembly: TypeForwardedTo(typeof(GenericParameterType))] [assembly: TypeForwardedTo(typeof(IAssemblyResolver))] [assembly: TypeForwardedTo(typeof(ICustomAttributeProvider))] [assembly: TypeForwardedTo(typeof(IGenericParameterProvider))] [assembly: TypeForwardedTo(typeof(IMemberDefinition))] [assembly: TypeForwardedTo(typeof(IMetadataImporter))] [assembly: TypeForwardedTo(typeof(IMetadataImporterProvider))] [assembly: TypeForwardedTo(typeof(IMetadataResolver))] [assembly: TypeForwardedTo(typeof(IMetadataScope))] [assembly: TypeForwardedTo(typeof(IMetadataTokenProvider))] [assembly: TypeForwardedTo(typeof(IMethodSignature))] [assembly: TypeForwardedTo(typeof(InterfaceImplementation))] [assembly: TypeForwardedTo(typeof(IReflectionImporter))] [assembly: TypeForwardedTo(typeof(IReflectionImporterProvider))] [assembly: TypeForwardedTo(typeof(ManifestResourceAttributes))] [assembly: TypeForwardedTo(typeof(MarshalInfo))] [assembly: TypeForwardedTo(typeof(MdbReader))] [assembly: TypeForwardedTo(typeof(MemberReference))] [assembly: TypeForwardedTo(typeof(MetadataKind))] [assembly: TypeForwardedTo(typeof(MetadataScopeType))] [assembly: TypeForwardedTo(typeof(MetadataToken))] [assembly: TypeForwardedTo(typeof(MetadataType))] [assembly: TypeForwardedTo(typeof(MethodAttributes))] [assembly: TypeForwardedTo(typeof(MethodCallingConvention))] [assembly: TypeForwardedTo(typeof(MethodDefinition))] [assembly: TypeForwardedTo(typeof(MethodImplAttributes))] [assembly: TypeForwardedTo(typeof(MethodReference))] [assembly: TypeForwardedTo(typeof(MethodReturnType))] [assembly: TypeForwardedTo(typeof(MethodSemanticsAttributes))] [assembly: TypeForwardedTo(typeof(ModuleAttributes))] [assembly: TypeForwardedTo(typeof(ModuleCharacteristics))] [assembly: TypeForwardedTo(typeof(ModuleDefinition))] [assembly: TypeForwardedTo(typeof(ModuleKind))] [assembly: TypeForwardedTo(typeof(ModuleParameters))] [assembly: TypeForwardedTo(typeof(ModuleReference))] [assembly: TypeForwardedTo(typeof(NativeType))] [assembly: TypeForwardedTo(typeof(ParameterAttributes))] [assembly: TypeForwardedTo(typeof(ParameterDefinition))] [assembly: TypeForwardedTo(typeof(ParameterReference))] [assembly: TypeForwardedTo(typeof(NativePdbReader))] [assembly: TypeForwardedTo(typeof(NativePdbWriter))] [assembly: TypeForwardedTo(typeof(PInvokeAttributes))] [assembly: TypeForwardedTo(typeof(PInvokeInfo))] [assembly: TypeForwardedTo(typeof(PropertyAttributes))] [assembly: TypeForwardedTo(typeof(PropertyDefinition))] [assembly: TypeForwardedTo(typeof(PropertyReference))] [assembly: TypeForwardedTo(typeof(ReaderParameters))] [assembly: TypeForwardedTo(typeof(ReadingMode))] [assembly: TypeForwardedTo(typeof(ResolutionException))] [assembly: TypeForwardedTo(typeof(Resource))] [assembly: TypeForwardedTo(typeof(ResourceType))] [assembly: TypeForwardedTo(typeof(IILVisitor))] [assembly: TypeForwardedTo(typeof(ILParser))] [assembly: TypeForwardedTo(typeof(ModuleDefinitionRocks))] [assembly: TypeForwardedTo(typeof(TypeDefinitionRocks))] [assembly: TypeForwardedTo(typeof(SecurityAction))] [assembly: TypeForwardedTo(typeof(SecurityAttribute))] [assembly: TypeForwardedTo(typeof(SecurityDeclaration))] [assembly: TypeForwardedTo(typeof(TargetArchitecture))] [assembly: TypeForwardedTo(typeof(TargetRuntime))] [assembly: TypeForwardedTo(typeof(TokenType))] [assembly: TypeForwardedTo(typeof(TypeAttributes))] [assembly: TypeForwardedTo(typeof(TypeDefinition))] [assembly: TypeForwardedTo(typeof(TypeReference))] [assembly: TypeForwardedTo(typeof(TypeSpecification))] [assembly: TypeForwardedTo(typeof(TypeSystem))] [assembly: TypeForwardedTo(typeof(WriterParameters))] [assembly: TypeForwardedTo(typeof(Collection<>))] [assembly: TypeForwardedTo(typeof(AnonymousScopeEntry))] [assembly: TypeForwardedTo(typeof(CapturedScope))] [assembly: TypeForwardedTo(typeof(CapturedVariable))] [assembly: TypeForwardedTo(typeof(CodeBlockEntry))] [assembly: TypeForwardedTo(typeof(CompileUnitEntry))] [assembly: TypeForwardedTo(typeof(LineNumberEntry))] [assembly: TypeForwardedTo(typeof(LineNumberTable))] [assembly: TypeForwardedTo(typeof(LocalVariableEntry))] [assembly: TypeForwardedTo(typeof(MethodEntry))] [assembly: TypeForwardedTo(typeof(MonoSymbolFile))] [assembly: TypeForwardedTo(typeof(NamespaceEntry))] [assembly: TypeForwardedTo(typeof(OffsetTable))] [assembly: TypeForwardedTo(typeof(ScopeVariable))] [assembly: TypeForwardedTo(typeof(SourceFileEntry))] [assembly: TypeForwardedTo(typeof(CecilILGenerator))] [assembly: TypeForwardedTo(typeof(ILGeneratorShim))] [assembly: TypeForwardedTo(typeof(DMDEmitDynamicMethodGenerator))] [assembly: TypeForwardedTo(typeof(DMDGenerator<>))] [assembly: TypeForwardedTo(typeof(DynamicMethodDefinition))] [assembly: TypeForwardedTo(typeof(Extensions))] [assembly: TypeForwardedTo(typeof(ICallSiteGenerator))] [assembly: TypeForwardedTo(typeof(ReflectionHelper))] [assembly: TypeForwardedTo(typeof(Relinker))] [module: UnverifiableCode] [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 JetBrains.Annotations { [AttributeUsage(AttributeTargets.All)] internal sealed class UsedImplicitlyAttribute : Attribute { public ImplicitUseKindFlags UseKindFlags { get; } public ImplicitUseTargetFlags TargetFlags { get; } public UsedImplicitlyAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) { } public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter | AttributeTargets.GenericParameter)] internal sealed class MeansImplicitUseAttribute : Attribute { [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; } [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; } public MeansImplicitUseAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) : this(useKindFlags, ImplicitUseTargetFlags.Default) { } public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) { UseKindFlags = useKindFlags; TargetFlags = targetFlags; } } [Flags] internal enum ImplicitUseKindFlags { Default = 7, Access = 1, Assign = 2, InstantiatedWithFixedConstructorSignature = 4, InstantiatedNoFixedConstructorSignature = 8 } [Flags] internal enum ImplicitUseTargetFlags { Default = 1, Itself = 1, Members = 2, WithInheritors = 4, WithMembers = 3 } } namespace HarmonyLib { public class DelegateTypeFactory { private class DelegateEntry { public CallingConvention? callingConvention; public Type delegateType; } private static int counter; private static readonly Dictionary> TypeCache = new Dictionary>(); private static readonly MethodBase CallingConvAttr = AccessTools.Constructor(typeof(UnmanagedFunctionPointerAttribute), new Type[1] { typeof(CallingConvention) }); public static readonly DelegateTypeFactory instance = new DelegateTypeFactory(); public Type CreateDelegateType(Type returnType, Type[] argTypes) { return CreateDelegateType(returnType, argTypes, null); } public Type CreateDelegateType(Type returnType, Type[] argTypes, CallingConvention? convention) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) counter++; AssemblyDefinition val = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition($"HarmonyDTFAssembly{counter}", new Version(1, 0)), $"HarmonyDTFModule{counter}", (ModuleKind)0); ModuleDefinition module = val.MainModule; TypeDefinition val2 = new TypeDefinition("", $"HarmonyDTFType{counter}", (TypeAttributes)257); val2.BaseType = module.ImportReference(typeof(MulticastDelegate)); TypeDefinition val3 = val2; module.Types.Add(val3); if (convention.HasValue) { CustomAttribute val4 = new CustomAttribute(module.ImportReference(CallingConvAttr)); val4.ConstructorArguments.Add(new CustomAttributeArgument(module.ImportReference(typeof(CallingConvention)), (object)convention.Value)); val3.CustomAttributes.Add(val4); } MethodDefinition val5 = new MethodDefinition(".ctor", (MethodAttributes)4230, module.ImportReference(typeof(void))) { ImplAttributes = (MethodImplAttributes)3 }; Extensions.AddRange(((MethodReference)val5).Parameters, (IEnumerable)(object)new ParameterDefinition[2] { new ParameterDefinition(module.ImportReference(typeof(object))), new ParameterDefinition(module.ImportReference(typeof(IntPtr))) }); val3.Methods.Add(val5); MethodDefinition val6 = new MethodDefinition("Invoke", (MethodAttributes)198, module.ImportReference(returnType)) { ImplAttributes = (MethodImplAttributes)3 }; Extensions.AddRange(((MethodReference)val6).Parameters, ((IEnumerable)argTypes).Select((Func)((Type t) => new ParameterDefinition(module.ImportReference(t))))); val3.Methods.Add(val6); Assembly assembly = ReflectionHelper.Load(val.MainModule); return assembly.GetType($"HarmonyDTFType{counter}"); } public Type CreateDelegateType(MethodInfo method) { return CreateDelegateType(method, null); } public Type CreateDelegateType(MethodInfo method, CallingConvention? convention) { DelegateEntry delegateEntry; if (TypeCache.TryGetValue(method, out var value) && (delegateEntry = value.FirstOrDefault((DelegateEntry e) => e.callingConvention == convention)) != null) { return delegateEntry.delegateType; } if (value == null) { value = (TypeCache[method] = new List()); } delegateEntry = new DelegateEntry { delegateType = CreateDelegateType(method.ReturnType, method.GetParameters().Types().ToArray(), convention), callingConvention = convention }; value.Add(delegateEntry); return delegateEntry.delegateType; } } [Obsolete("Use AccessTools.FieldRefAccess for fields and AccessTools.MethodDelegate> for property getters")] [EditorBrowsable(EditorBrowsableState.Never)] public delegate S GetterHandler(T source); [Obsolete("Use AccessTools.FieldRefAccess for fields and AccessTools.MethodDelegate> for property setters")] [EditorBrowsable(EditorBrowsableState.Never)] public delegate void SetterHandler(T source, S value); public delegate T InstantiationHandler(); public static class FastAccess { public static InstantiationHandler CreateInstantiationHandler() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown ConstructorInfo constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Array.Empty(), null); if ((object)constructor == null) { throw new ApplicationException($"The type {typeof(T)} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public)."); } DynamicMethodDefinition val = new DynamicMethodDefinition("InstantiateObject_" + typeof(T).Name, typeof(T), (Type[])null); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Newobj, constructor); iLGenerator.Emit(OpCodes.Ret); return Extensions.CreateDelegate>((MethodBase)val.Generate()); } [Obsolete("Use AccessTools.MethodDelegate>(PropertyInfo.GetGetMethod(true))")] [EditorBrowsable(EditorBrowsableState.Never)] public static GetterHandler CreateGetterHandler(PropertyInfo propertyInfo) { MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); DynamicMethodDefinition val = CreateGetDynamicMethod(propertyInfo.DeclaringType); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Call, getMethod); iLGenerator.Emit(OpCodes.Ret); return Extensions.CreateDelegate>((MethodBase)val.Generate()); } [Obsolete("Use AccessTools.FieldRefAccess(fieldInfo)")] [EditorBrowsable(EditorBrowsableState.Never)] public static GetterHandler CreateGetterHandler(FieldInfo fieldInfo) { DynamicMethodDefinition val = CreateGetDynamicMethod(fieldInfo.DeclaringType); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return Extensions.CreateDelegate>((MethodBase)val.Generate()); } [Obsolete("Use AccessTools.FieldRefAccess(name) for fields and AccessTools.MethodDelegate>(AccessTools.PropertyGetter(typeof(T), name)) for properties")] [EditorBrowsable(EditorBrowsableState.Never)] public static GetterHandler CreateFieldGetter(params string[] names) { foreach (string name in names) { FieldInfo field = typeof(T).GetField(name, AccessTools.all); if ((object)field != null) { return CreateGetterHandler(field); } PropertyInfo property = typeof(T).GetProperty(name, AccessTools.all); if ((object)property != null) { return CreateGetterHandler(property); } } return null; } [Obsolete("Use AccessTools.MethodDelegate>(PropertyInfo.GetSetMethod(true))")] [EditorBrowsable(EditorBrowsableState.Never)] public static SetterHandler CreateSetterHandler(PropertyInfo propertyInfo) { MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); DynamicMethodDefinition val = CreateSetDynamicMethod(propertyInfo.DeclaringType); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Call, setMethod); iLGenerator.Emit(OpCodes.Ret); return Extensions.CreateDelegate>((MethodBase)val.Generate()); } [Obsolete("Use AccessTools.FieldRefAccess(fieldInfo)")] [EditorBrowsable(EditorBrowsableState.Never)] public static SetterHandler CreateSetterHandler(FieldInfo fieldInfo) { DynamicMethodDefinition val = CreateSetDynamicMethod(fieldInfo.DeclaringType); ILGenerator iLGenerator = val.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Stfld, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return Extensions.CreateDelegate>((MethodBase)val.Generate()); } private static DynamicMethodDefinition CreateGetDynamicMethod(Type type) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown return new DynamicMethodDefinition("DynamicGet_" + type.Name, typeof(S), new Type[1] { typeof(T) }); } private static DynamicMethodDefinition CreateSetDynamicMethod(Type type) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown return new DynamicMethodDefinition("DynamicSet_" + type.Name, typeof(void), new Type[2] { typeof(T), typeof(S) }); } } public delegate object FastInvokeHandler(object target, params object[] parameters); public static class MethodInvoker { public static FastInvokeHandler GetHandler(MethodInfo methodInfo, bool directBoxValueAccess = false) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown DynamicMethodDefinition val = new DynamicMethodDefinition("FastInvoke_" + methodInfo.Name + "_" + (directBoxValueAccess ? "direct" : "indirect"), typeof(object), new Type[2] { typeof(object), typeof(object[]) }); ILGenerator iLGenerator = val.GetILGenerator(); if (!methodInfo.IsStatic) { Emit(iLGenerator, OpCodes.Ldarg_0); EmitUnboxIfNeeded(iLGenerator, methodInfo.DeclaringType); } bool flag = true; ParameterInfo[] parameters = methodInfo.GetParameters(); for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; bool isByRef = type.IsByRef; if (isByRef) { type = type.GetElementType(); } bool isValueType = type.IsValueType; if (isByRef && isValueType && !directBoxValueAccess) { Emit(iLGenerator, OpCodes.Ldarg_1); EmitFastInt(iLGenerator, i); } Emit(iLGenerator, OpCodes.Ldarg_1); EmitFastInt(iLGenerator, i); if (isByRef && !isValueType) { Emit(iLGenerator, OpCodes.Ldelema, typeof(object)); continue; } Emit(iLGenerator, OpCodes.Ldelem_Ref); if (!isValueType) { continue; } if (!isByRef || !directBoxValueAccess) { Emit(iLGenerator, OpCodes.Unbox_Any, type); if (isByRef) { Emit(iLGenerator, OpCodes.Box, type); Emit(iLGenerator, OpCodes.Dup); if (flag) { flag = false; iLGenerator.DeclareLocal(typeof(object), pinned: false); } Emit(iLGenerator, OpCodes.Stloc_0); Emit(iLGenerator, OpCodes.Stelem_Ref); Emit(iLGenerator, OpCodes.Ldloc_0); Emit(iLGenerator, OpCodes.Unbox, type); } } else { Emit(iLGenerator, OpCodes.Unbox, type); } } if (methodInfo.IsStatic) { EmitCall(iLGenerator, OpCodes.Call, methodInfo); } else { EmitCall(iLGenerator, OpCodes.Callvirt, methodInfo); } if (methodInfo.ReturnType == typeof(void)) { Emit(iLGenerator, OpCodes.Ldnull); } else { EmitBoxIfNeeded(iLGenerator, methodInfo.ReturnType); } Emit(iLGenerator, OpCodes.Ret); return Extensions.CreateDelegate((MethodBase)val.Generate()); } internal static void Emit(ILGenerator il, OpCode opcode) { il.Emit(opcode); } internal static void Emit(ILGenerator il, OpCode opcode, Type type) { il.Emit(opcode, type); } internal static void EmitCall(ILGenerator il, OpCode opcode, MethodInfo methodInfo) { il.EmitCall(opcode, methodInfo, null); } private static void EmitUnboxIfNeeded(ILGenerator il, Type type) { if (type.IsValueType) { Emit(il, OpCodes.Unbox_Any, type); } } private static void EmitBoxIfNeeded(ILGenerator il, Type type) { if (type.IsValueType) { Emit(il, OpCodes.Box, type); } } internal static void EmitFastInt(ILGenerator il, int value) { switch (value) { case -1: il.Emit(OpCodes.Ldc_I4_M1); return; case 0: il.Emit(OpCodes.Ldc_I4_0); return; case 1: il.Emit(OpCodes.Ldc_I4_1); return; case 2: il.Emit(OpCodes.Ldc_I4_2); return; case 3: il.Emit(OpCodes.Ldc_I4_3); return; case 4: il.Emit(OpCodes.Ldc_I4_4); return; case 5: il.Emit(OpCodes.Ldc_I4_5); return; case 6: il.Emit(OpCodes.Ldc_I4_6); return; case 7: il.Emit(OpCodes.Ldc_I4_7); return; case 8: il.Emit(OpCodes.Ldc_I4_8); return; } if (value > -129 && value < 128) { il.Emit(OpCodes.Ldc_I4_S, (sbyte)value); } else { il.Emit(OpCodes.Ldc_I4, value); } } } public delegate ref T RefResult(); internal class AccessCache { internal enum MemberType { Any, Static, Instance } private const BindingFlags BasicFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; private static readonly Dictionary declaredOnlyBindingFlags = new Dictionary { { MemberType.Any, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty }, { MemberType.Instance, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty }, { MemberType.Static, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty } }; private readonly Dictionary> declaredFields = new Dictionary>(); private readonly Dictionary> declaredProperties = new Dictionary>(); private readonly Dictionary>> declaredMethods = new Dictionary>>(); private readonly Dictionary> inheritedFields = new Dictionary>(); private readonly Dictionary> inheritedProperties = new Dictionary>(); private readonly Dictionary>> inheritedMethods = new Dictionary>>(); private static T Get(Dictionary> dict, Type type, string name, Func fetcher) { lock (dict) { if (!dict.TryGetValue(type, out var value)) { value = (dict[type] = new Dictionary()); } if (!value.TryGetValue(name, out var value2)) { value2 = (value[name] = fetcher()); } return value2; } } private static T Get(Dictionary>> dict, Type type, string name, Type[] arguments, Func fetcher) { lock (dict) { if (!dict.TryGetValue(type, out var value)) { value = (dict[type] = new Dictionary>()); } if (!value.TryGetValue(name, out var value2)) { value2 = (value[name] = new Dictionary()); } int key = AccessTools.CombinedHashCode(arguments); if (!value2.TryGetValue(key, out var value3)) { value3 = (value2[key] = fetcher()); } return value3; } } internal FieldInfo GetFieldInfo(Type type, string name, MemberType memberType = MemberType.Any, bool declaredOnly = false) { FieldInfo fieldInfo = Get(declaredFields, type, name, () => type.GetField(name, declaredOnlyBindingFlags[memberType])); if ((object)fieldInfo == null && !declaredOnly) { fieldInfo = Get(inheritedFields, type, name, () => AccessTools.FindIncludingBaseTypes(type, (Type t) => t.GetField(name, AccessTools.all))); } return fieldInfo; } internal PropertyInfo GetPropertyInfo(Type type, string name, MemberType memberType = MemberType.Any, bool declaredOnly = false) { PropertyInfo propertyInfo = Get(declaredProperties, type, name, () => type.GetProperty(name, declaredOnlyBindingFlags[memberType])); if ((object)propertyInfo == null && !declaredOnly) { propertyInfo = Get(inheritedProperties, type, name, () => AccessTools.FindIncludingBaseTypes(type, (Type t) => t.GetProperty(name, AccessTools.all))); } return propertyInfo; } internal MethodBase GetMethodInfo(Type type, string name, Type[] arguments, MemberType memberType = MemberType.Any, bool declaredOnly = false) { MethodBase methodBase = Get(declaredMethods, type, name, arguments, () => type.GetMethod(name, declaredOnlyBindingFlags[memberType], null, arguments, null)); if ((object)methodBase == null && !declaredOnly) { methodBase = Get(inheritedMethods, type, name, arguments, () => AccessTools.Method(type, name, arguments)); } return methodBase; } } internal static class PatchArgumentExtensions { private static IEnumerable AllHarmonyArguments(object[] attributes) { return attributes.Select((object attr) => (attr.GetType().Name != "HarmonyArgument") ? null : AccessTools.MakeDeepCopy(attr)).OfType(); } internal static HarmonyArgument GetArgumentAttribute(this ParameterInfo parameter) { object[] customAttributes = parameter.GetCustomAttributes(inherit: true); return AllHarmonyArguments(customAttributes).FirstOrDefault(); } internal static IEnumerable GetArgumentAttributes(this MethodInfo method) { object[] customAttributes = method.GetCustomAttributes(inherit: true); return AllHarmonyArguments(customAttributes); } internal static IEnumerable GetArgumentAttributes(this Type type) { object[] customAttributes = type.GetCustomAttributes(inherit: true); return AllHarmonyArguments(customAttributes); } internal static string GetRealName(this IEnumerable attributes, string name, string[] originalParameterNames) { HarmonyArgument harmonyArgument = attributes.FirstOrDefault((HarmonyArgument p) => p.OriginalName == name); if (harmonyArgument == null) { return null; } if (!string.IsNullOrEmpty(harmonyArgument.NewName)) { return harmonyArgument.NewName; } if (originalParameterNames != null && harmonyArgument.Index >= 0 && harmonyArgument.Index < originalParameterNames.Length) { return originalParameterNames[harmonyArgument.Index]; } return null; } private static string GetRealParameterName(this MethodInfo method, string[] originalParameterNames, string name) { if ((object)method == null || method is DynamicMethod) { return name; } string realName = method.GetArgumentAttributes().GetRealName(name, originalParameterNames); if (realName != null) { return realName; } Type declaringType = method.DeclaringType; if ((object)declaringType != null) { realName = declaringType.GetArgumentAttributes().GetRealName(name, originalParameterNames); if (realName != null) { return realName; } } return name; } private static string GetRealParameterName(this ParameterInfo parameter, string[] originalParameterNames) { HarmonyArgument argumentAttribute = parameter.GetArgumentAttribute(); if (argumentAttribute == null) { return null; } if (!string.IsNullOrEmpty(argumentAttribute.OriginalName)) { return argumentAttribute.OriginalName; } if (argumentAttribute.Index >= 0 && argumentAttribute.Index < originalParameterNames.Length) { return originalParameterNames[argumentAttribute.Index]; } return null; } internal static int GetArgumentIndex(this MethodInfo patch, string[] originalParameterNames, ParameterInfo patchParam) { if (patch is DynamicMethod) { return Array.IndexOf(originalParameterNames, patchParam.Name); } string realParameterName = patchParam.GetRealParameterName(originalParameterNames); if (realParameterName != null) { return Array.IndexOf(originalParameterNames, realParameterName); } realParameterName = patch.GetRealParameterName(originalParameterNames, patchParam.Name); if (realParameterName != null) { return Array.IndexOf(originalParameterNames, realParameterName); } return -1; } } internal static class PatchFunctions { internal static List GetSortedPatchMethods(MethodBase original, Patch[] patches, bool debug) { return new PatchSorter(patches, debug).Sort(original); } internal static Patch[] GetSortedPatchMethodsAsPatches(MethodBase original, Patch[] patches, bool debug) { return new PatchSorter(patches, debug).SortAsPatches(original); } internal static MethodInfo UpdateWrapper(MethodBase original, PatchInfo patchInfo) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown MethodPatcher methodPatcher = original.GetMethodPatcher(); DynamicMethodDefinition val = methodPatcher.PrepareOriginal(); if (val != null) { ILContext ctx = new ILContext(val.Definition); HarmonyManipulator.Manipulate(original, patchInfo, ctx); } try { return methodPatcher.DetourTo((val != null) ? val.Generate() : null) as MethodInfo; } catch (Exception ex) { object body; if (val == null) { body = null; } else { MethodDefinition definition = val.Definition; body = ((definition != null) ? definition.Body : null); } throw HarmonyException.Create(ex, (MethodBody)body); } } internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase original, MethodInfo postTranspiler, MethodInfo postManipulator) { //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown if (standin == null) { throw new ArgumentNullException("standin"); } if ((object)standin.method == null) { throw new ArgumentNullException("standin", "standin.method is NULL"); } if (!standin.method.IsStatic) { throw new ArgumentException("standin", "standin.method is not static"); } bool debug = standin.debug == true; List transpilers = new List(); List ilmanipulators = new List(); if (standin.reversePatchType == HarmonyReversePatchType.Snapshot) { Patches patchInfo = Harmony.GetPatchInfo(original); transpilers.AddRange(GetSortedPatchMethods(original, patchInfo.Transpilers.ToArray(), debug)); ilmanipulators.AddRange(GetSortedPatchMethods(original, patchInfo.ILManipulators.ToArray(), debug)); } if ((object)postTranspiler != null) { transpilers.Add(postTranspiler); } if ((object)postManipulator != null) { ilmanipulators.Add(postManipulator); } Logger.Log(Logger.LogChannel.Info, delegate { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Reverse patching " + standin.method.FullDescription() + " with " + original.FullDescription()); PrintInfo(stringBuilder, transpilers, "Transpiler"); PrintInfo(stringBuilder, ilmanipulators, "Manipulators"); return stringBuilder.ToString(); }, debug); MethodBody patchBody = null; ILHook val = new ILHook((MethodBase)standin.method, (Manipulator)delegate(ILContext ctx) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) if (original is MethodInfo methodInfo2) { patchBody = ctx.Body; MethodPatcher methodPatcher = methodInfo2.GetMethodPatcher(); DynamicMethodDefinition val2 = methodPatcher.CopyOriginal(); if (val2 == null) { throw new NullReferenceException($"Cannot reverse patch {methodInfo2.FullDescription()}: method patcher ({methodPatcher.GetType().FullDescription()}) can't copy original method body"); } ILManipulator iLManipulator = new ILManipulator(val2.Definition.Body, debug); ctx.Body.Variables.Clear(); Enumerator enumerator = iLManipulator.Body.Variables.GetEnumerator(); try { while (enumerator.MoveNext()) { VariableDefinition current = enumerator.Current; ctx.Body.Variables.Add(new VariableDefinition(ctx.Module.ImportReference(((VariableReference)current).VariableType))); } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } foreach (MethodInfo item in transpilers) { iLManipulator.AddTranspiler(item); } iLManipulator.WriteTo(ctx.Body, standin.method); HarmonyManipulator.ApplyManipulators(ctx, original, ilmanipulators, null); StackTraceFixes.FixStackTrace(ctx); Instruction val3 = null; foreach (Instruction item2 in ((IEnumerable)ctx.Instrs).Where((Instruction i) => i.OpCode == OpCodes.Ret)) { if (val3 == null) { val3 = ctx.IL.Create(OpCodes.Ret); } item2.OpCode = OpCodes.Br; item2.Operand = val3; } if (val3 != null) { ctx.IL.Append(val3); } Logger.Log(Logger.LogChannel.IL, () => "Generated reverse patcher (" + ((MemberReference)ctx.Method).FullName + "):\n" + ctx.Body.ToILDasmString(), debug); } }, false); try { val.Apply(); } catch (Exception ex) { throw HarmonyException.Create(ex, patchBody); } MethodInfo methodInfo = val.Method as MethodInfo; PatchTools.RememberObject(standin.method, (methodInfo, val)); return methodInfo; static void PrintInfo(StringBuilder sb, ICollection methods, string name) { if (methods.Count <= 0) { return; } sb.AppendLine(name + ":"); foreach (MethodInfo method in methods) { sb.AppendLine(" * " + method.FullDescription()); } } } internal static IEnumerable ApplyTranspilers(MethodBase methodBase, ILGenerator generator, int maxTranspilers = 0) { MethodPatcher methodPatcher = methodBase.GetMethodPatcher(); DynamicMethodDefinition val = methodPatcher.CopyOriginal(); if (val == null) { throw new NullReferenceException($"Cannot reverse patch {methodBase.FullDescription()}: method patcher ({methodPatcher.GetType().FullDescription()}) can't copy original method body"); } ILManipulator iLManipulator = new ILManipulator(val.Definition.Body, debug: false); PatchInfo patchInfo = methodBase.GetPatchInfo(); if (patchInfo != null) { List sortedPatchMethods = GetSortedPatchMethods(methodBase, patchInfo.transpilers, debug: false); for (int i = 0; i < maxTranspilers && i < sortedPatchMethods.Count; i++) { iLManipulator.AddTranspiler(sortedPatchMethods[i]); } } return iLManipulator.GetInstructions(generator, methodBase); } internal static void UnpatchConditional(Func executionCondition) { List list = PatchProcessor.GetAllPatchedMethods().ToList(); foreach (MethodBase item in list) { Patches patchInfo = PatchProcessor.GetPatchInfo(item); PatchProcessor patchProcessor = new PatchProcessor(null, item); patchInfo.Postfixes.DoIf(executionCondition, delegate(Patch patch) { patchProcessor.Unpatch(patch.PatchMethod); }); patchInfo.Prefixes.DoIf(executionCondition, delegate(Patch patch) { patchProcessor.Unpatch(patch.PatchMethod); }); patchInfo.ILManipulators.DoIf(executionCondition, delegate(Patch patch) { patchProcessor.Unpatch(patch.PatchMethod); }); patchInfo.Transpilers.DoIf(executionCondition, delegate(Patch patch) { patchProcessor.Unpatch(patch.PatchMethod); }); patchInfo.Finalizers.DoIf(executionCondition, delegate(Patch patch) { patchProcessor.Unpatch(patch.PatchMethod); }); } } } internal class PatchJobs { internal class Job { internal MethodBase original; internal T replacement; internal List prefixes = new List(); internal List postfixes = new List(); internal List transpilers = new List(); internal List finalizers = new List(); internal List ilmanipulators = new List(); internal void AddPatch(AttributePatch patch) { HarmonyPatchType? type = patch.type; if (type.HasValue) { switch (type.GetValueOrDefault()) { case HarmonyPatchType.Prefix: prefixes.Add(patch.info); break; case HarmonyPatchType.Postfix: postfixes.Add(patch.info); break; case HarmonyPatchType.Transpiler: transpilers.Add(patch.info); break; case HarmonyPatchType.Finalizer: finalizers.Add(patch.info); break; case HarmonyPatchType.ILManipulator: ilmanipulators.Add(patch.info); break; case HarmonyPatchType.ReversePatch: break; } } } } internal Dictionary state = new Dictionary(); internal Job GetJob(MethodBase method) { if ((object)method == null) { return null; } if (!state.TryGetValue(method, out var value)) { value = new Job { original = method }; state[method] = value; } return value; } internal List GetJobs() { return state.Values.Where((Job job) => job.prefixes.Count + job.postfixes.Count + job.transpilers.Count + job.finalizers.Count + job.ilmanipulators.Count > 0).ToList(); } internal List GetReplacements() { return state.Values.Select((Job job) => job.replacement).ToList(); } } internal class AttributePatch { private static readonly HarmonyPatchType[] allPatchTypes = new HarmonyPatchType[6] { HarmonyPatchType.Prefix, HarmonyPatchType.Postfix, HarmonyPatchType.Transpiler, HarmonyPatchType.Finalizer, HarmonyPatchType.ReversePatch, HarmonyPatchType.ILManipulator }; internal HarmonyMethod info; internal HarmonyPatchType? type; internal static IEnumerable Create(MethodInfo patch, bool collectIncomplete = false) { if ((object)patch == null) { throw new NullReferenceException("Patch method cannot be null"); } object[] customAttributes = patch.GetCustomAttributes(inherit: true); string name = patch.Name; HarmonyPatchType? type = GetPatchType(name, customAttributes); if (!type.HasValue) { return Enumerable.Empty(); } if (type != HarmonyPatchType.ReversePatch && !patch.IsStatic) { throw new ArgumentException("Patch method " + patch.FullDescription() + " must be static"); } List list = customAttributes.Where((object attr) => attr.GetType().BaseType.FullName == PatchTools.harmonyAttributeFullName).Select(delegate(object attr) { FieldInfo fieldInfo = AccessTools.Field(attr.GetType(), "info"); return fieldInfo.GetValue(attr); }).Select(AccessTools.MakeDeepCopy) .ToList(); List list2 = new List(); ILookup lookup = list.ToLookup((HarmonyMethod m) => IsComplete(m, collectIncomplete)); List incomplete = lookup[false].ToList(); HarmonyMethod info = HarmonyMethod.Merge(incomplete); List list3 = lookup[true].Where((HarmonyMethod m) => !Same(m, info)).ToList(); if (list3.Count > 1) { list2.AddRange(list3.Select((HarmonyMethod m) => HarmonyMethod.Merge(incomplete.AddItem(m)))); } else { list2.Add(HarmonyMethod.Merge(list)); } foreach (HarmonyMethod item in list2) { item.method = patch; } return list2.Select((HarmonyMethod i) => new AttributePatch { info = i, type = type }).ToList(); static bool IsComplete(HarmonyMethod m, bool flag) { if (flag || m.declaringType != null) { return m.methodName != null; } return false; } static bool Same(HarmonyMethod m1, HarmonyMethod m2) { if (m1.declaringType == m2.declaringType && m1.methodName == m2.methodName) { return m1.GetArgumentList().SequenceEqual(m2.GetArgumentList()); } return false; } } private static HarmonyPatchType? GetPatchType(string methodName, object[] allAttributes) { HashSet hashSet = new HashSet(from attr in allAttributes select attr.GetType().FullName into name where name.StartsWith("Harmony") select name); HarmonyPatchType? result = null; HarmonyPatchType[] array = allPatchTypes; for (int num = 0; num < array.Length; num++) { HarmonyPatchType value = array[num]; string text = value.ToString(); if (text == methodName || hashSet.Contains("HarmonyLib.Harmony" + text)) { result = value; break; } } return result; } } internal class PatchSorter { private class PatchSortingWrapper : IComparable { internal readonly HashSet after; internal readonly HashSet before; internal readonly Patch innerPatch; internal PatchSortingWrapper(Patch patch) { innerPatch = patch; before = new HashSet(); after = new HashSet(); } public int CompareTo(object obj) { return PatchInfoSerialization.PriorityComparer((obj is PatchSortingWrapper patchSortingWrapper) ? patchSortingWrapper.innerPatch : null, innerPatch.index, innerPatch.priority); } public override bool Equals(object obj) { if (obj is PatchSortingWrapper patchSortingWrapper) { return innerPatch.PatchMethod == patchSortingWrapper.innerPatch.PatchMethod; } return false; } public override int GetHashCode() { return innerPatch.PatchMethod.GetHashCode(); } internal void AddBeforeDependency(IEnumerable dependencies) { foreach (PatchSortingWrapper dependency in dependencies) { before.Add(dependency); dependency.after.Add(this); } } internal void AddAfterDependency(IEnumerable dependencies) { foreach (PatchSortingWrapper dependency in dependencies) { after.Add(dependency); dependency.before.Add(this); } } internal void RemoveAfterDependency(PatchSortingWrapper afterNode) { after.Remove(afterNode); afterNode.before.Remove(this); } internal void RemoveBeforeDependency(PatchSortingWrapper beforeNode) { before.Remove(beforeNode); beforeNode.after.Remove(this); } } internal class PatchDetailedComparer : IEqualityComparer { public bool Equals(Patch x, Patch y) { if (y != null && x != null && x.owner == y.owner && x.PatchMethod == y.PatchMethod && x.index == y.index && x.priority == y.priority && x.before.Length == y.before.Length && x.after.Length == y.after.Length && x.before.All(((IEnumerable)y.before).Contains)) { return x.after.All(((IEnumerable)y.after).Contains); } return false; } public int GetHashCode(Patch obj) { return obj.GetHashCode(); } } private List patches; private HashSet handledPatches; private List result; private List waitingList; internal Patch[] sortedPatchArray; private readonly bool debug; internal PatchSorter(Patch[] patches, bool debug = false) { this.patches = patches.Select((Patch x) => new PatchSortingWrapper(x)).ToList(); this.debug = debug; foreach (PatchSortingWrapper node in this.patches) { node.AddBeforeDependency(this.patches.Where((PatchSortingWrapper x) => node.innerPatch.before.Contains(x.innerPatch.owner))); node.AddAfterDependency(this.patches.Where((PatchSortingWrapper x) => node.innerPatch.after.Contains(x.innerPatch.owner))); } this.patches.Sort(); } internal List Sort(MethodBase original) { return (from x in SortAsPatches(original) select x.GetMethod(original)).ToList(); } internal Patch[] SortAsPatches(MethodBase original) { if (sortedPatchArray != null) { return sortedPatchArray; } handledPatches = new HashSet(); waitingList = new List(); result = new List(patches.Count); Queue queue = new Queue(patches); while (queue.Count != 0) { foreach (PatchSortingWrapper item in queue) { if (item.after.All((PatchSortingWrapper x) => handledPatches.Contains(x))) { AddNodeToResult(item); if (item.before.Count != 0) { ProcessWaitingList(); } } else { waitingList.Add(item); } } CullDependency(); queue = new Queue(waitingList); waitingList.Clear(); } sortedPatchArray = result.Select((PatchSortingWrapper x) => x.innerPatch).ToArray(); handledPatches = null; waitingList = null; patches = null; return sortedPatchArray; } internal bool ComparePatchLists(Patch[] patches) { if (sortedPatchArray == null) { Sort(null); } if (patches != null && sortedPatchArray.Length == patches.Length) { return sortedPatchArray.All((Patch x) => patches.Contains(x, new PatchDetailedComparer())); } return false; } private void CullDependency() { for (int i = waitingList.Count - 1; i >= 0; i--) { foreach (PatchSortingWrapper afterNode in waitingList[i].after) { if (!handledPatches.Contains(afterNode)) { waitingList[i].RemoveAfterDependency(afterNode); Logger.Log(Logger.LogChannel.Debug, delegate { string text = afterNode.innerPatch.PatchMethod.FullDescription(); string text2 = waitingList[i].innerPatch.PatchMethod.FullDescription(); return "Breaking dependence between " + text + " and " + text2; }, debug); return; } } } } private void ProcessWaitingList() { int num = waitingList.Count; int num2 = 0; while (num2 < num) { PatchSortingWrapper patchSortingWrapper = waitingList[num2]; if (patchSortingWrapper.after.All(handledPatches.Contains)) { waitingList.Remove(patchSortingWrapper); AddNodeToResult(patchSortingWrapper); num--; num2 = 0; } else { num2++; } } } private void AddNodeToResult(PatchSortingWrapper node) { result.Add(node); handledPatches.Add(node); } } internal static class PatchTools { internal static readonly string harmonyMethodFullName = typeof(HarmonyMethod).FullName; internal static readonly string harmonyAttributeFullName = typeof(HarmonyAttribute).FullName; internal static readonly string harmonyPatchAllFullName = typeof(HarmonyPatchAll).FullName; private static readonly Dictionary objectReferences = new Dictionary(); internal static void RememberObject(object key, object value) { lock (objectReferences) { objectReferences[key] = value; } } public static MethodInfo CreateMethod(string name, Type returnType, List> parameters, Action generator) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown Type[] array = parameters.Select((KeyValuePair p) => p.Value).ToArray(); if (AccessTools.IsMonoRuntime && !ReflectionTools.isWindows) { AssemblyName name2 = new AssemblyName("TempAssembly"); AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(name2, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("TempModule"); TypeBuilder typeBuilder = moduleBuilder.DefineType("TempType", TypeAttributes.Public); MethodBuilder methodBuilder = typeBuilder.DefineMethod(name, MethodAttributes.Public | MethodAttributes.Static, returnType, array); for (int num = 0; num < parameters.Count; num++) { methodBuilder.DefineParameter(num + 1, ParameterAttributes.None, parameters[num].Key); } generator(methodBuilder.GetILGenerator()); Type type = typeBuilder.CreateTypeInfo().AsType(); return type.GetMethod(name, BindingFlags.Static | BindingFlags.Public); } DynamicMethodDefinition val = new DynamicMethodDefinition(name, returnType, array); for (int num2 = 0; num2 < parameters.Count; num2++) { ((ParameterReference)((MethodReference)val.Definition).Parameters[num2]).Name = parameters[num2].Key; } generator(val.GetILGenerator()); return val.Generate(); } internal static MethodInfo GetPatchMethod(Type patchType, string attributeName) { MethodInfo methodInfo = patchType.GetMethods(AccessTools.all).FirstOrDefault((MethodInfo m) => m.GetCustomAttributes(inherit: true).Any((object a) => a.GetType().FullName == attributeName)); if ((object)methodInfo == null) { string name = attributeName.Replace("HarmonyLib.Harmony", ""); methodInfo = patchType.GetMethod(name, AccessTools.all); } return methodInfo; } internal static AssemblyBuilder DefineDynamicAssembly(string name) { AssemblyName name2 = new AssemblyName(name); return AssemblyBuilder.DefineDynamicAssembly(name2, AssemblyBuilderAccess.Run); } internal static List GetPatchMethods(Type type, bool collectIncomplete = false) { return (from attributePatch in AccessTools.GetDeclaredMethods(type).SelectMany((MethodInfo method) => AttributePatch.Create(method, collectIncomplete)) where attributePatch != null select attributePatch).ToList(); } internal static MethodBase GetOriginalMethod(this HarmonyMethod attr) { try { MethodType? methodType = attr.methodType; if (methodType.HasValue) { switch (methodType.GetValueOrDefault()) { case MethodType.Normal: if (string.IsNullOrEmpty(attr.methodName)) { return null; } return AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes); case MethodType.Getter: if (string.IsNullOrEmpty(attr.methodName)) { return AccessTools.DeclaredIndexerGetter(attr.declaringType, attr.argumentTypes); } return AccessTools.DeclaredPropertyGetter(attr.declaringType, attr.methodName); case MethodType.Setter: if (string.IsNullOrEmpty(attr.methodName)) { return AccessTools.DeclaredIndexerSetter(attr.declaringType, attr.argumentTypes); } return AccessTools.DeclaredPropertySetter(attr.declaringType, attr.methodName); case MethodType.Constructor: return AccessTools.DeclaredConstructor(attr.declaringType, attr.argumentTypes); case MethodType.StaticConstructor: return AccessTools.GetDeclaredConstructors(attr.declaringType).FirstOrDefault((ConstructorInfo c) => c.IsStatic); case MethodType.Enumerator: if (string.IsNullOrEmpty(attr.methodName)) { return null; } return AccessTools.EnumeratorMoveNext(AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes)); case MethodType.Async: if (string.IsNullOrEmpty(attr.methodName)) { return null; } return AccessTools.AsyncMoveNext(AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes)); } } } catch (AmbiguousMatchException ex) { throw new HarmonyException("Ambiguous match for HarmonyMethod[" + attr.Description() + "]", ex.InnerException ?? ex); } return null; } } public enum MethodType { Normal, Getter, Setter, Constructor, StaticConstructor, Enumerator, Async } public enum ArgumentType { Normal, Ref, Out, Pointer } public enum HarmonyPatchType { All, Prefix, Postfix, Transpiler, Finalizer, ReversePatch, ILManipulator } public enum HarmonyReversePatchType { Original, Snapshot } public enum MethodDispatchType { VirtualCall, Call } [MeansImplicitUse] public class HarmonyAttribute : Attribute { public HarmonyMethod info = new HarmonyMethod(); } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class HarmonyPatchCategory : HarmonyAttribute { public HarmonyPatchCategory(string category) { info.category = category; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Delegate, AllowMultiple = true)] public class HarmonyPatch : HarmonyAttribute { public HarmonyPatch() { } public HarmonyPatch(Type declaringType) { info.declaringType = declaringType; } public HarmonyPatch(Type declaringType, Type[] argumentTypes) { info.declaringType = declaringType; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, string methodName) { info.declaringType = declaringType; info.methodName = methodName; } public HarmonyPatch(Type declaringType, string methodName, params Type[] argumentTypes) { info.declaringType = declaringType; info.methodName = methodName; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.declaringType = declaringType; info.methodName = methodName; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(string typeName, string methodName) { info.declaringType = AccessTools.TypeByName(typeName); info.methodName = methodName; } public HarmonyPatch(string typeName, string methodName, MethodType methodType, Type[] argumentTypes = null, ArgumentType[] argumentVariations = null) { info.declaringType = AccessTools.TypeByName(typeName); info.methodName = methodName; info.methodType = methodType; if (argumentTypes != null) { ParseSpecialArguments(argumentTypes, argumentVariations); } } public HarmonyPatch(Type declaringType, MethodType methodType) { info.declaringType = declaringType; info.methodType = methodType; } public HarmonyPatch(Type declaringType, MethodType methodType, params Type[] argumentTypes) { info.declaringType = declaringType; info.methodType = methodType; info.argumentTypes = argumentTypes; } public HarmonyPatch(Type declaringType, MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.declaringType = declaringType; info.methodType = methodType; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(Type declaringType, string methodName, MethodType methodType) { info.declaringType = declaringType; info.methodName = methodName; info.methodType = methodType; } public HarmonyPatch(string methodName) { info.methodName = methodName; } public HarmonyPatch(string methodName, params Type[] argumentTypes) { info.methodName = methodName; info.argumentTypes = argumentTypes; } public HarmonyPatch(string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.methodName = methodName; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(string methodName, MethodType methodType) { info.methodName = methodName; info.methodType = methodType; } public HarmonyPatch(MethodType methodType) { info.methodType = methodType; } public HarmonyPatch(MethodType methodType, params Type[] argumentTypes) { info.methodType = methodType; info.argumentTypes = argumentTypes; } public HarmonyPatch(MethodType methodType, Type[] argumentTypes, ArgumentType[] argumentVariations) { info.methodType = methodType; ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(Type[] argumentTypes) { info.argumentTypes = argumentTypes; } public HarmonyPatch(Type[] argumentTypes, ArgumentType[] argumentVariations) { ParseSpecialArguments(argumentTypes, argumentVariations); } public HarmonyPatch(string typeName, string methodName, MethodType methodType = MethodType.Normal) { info.declaringType = AccessTools.TypeByName(typeName); info.methodName = methodName; info.methodType = methodType; } private void ParseSpecialArguments(Type[] argumentTypes, ArgumentType[] argumentVariations) { if (argumentVariations == null || argumentVariations.Length == 0) { info.argumentTypes = argumentTypes; return; } if (argumentTypes.Length < argumentVariations.Length) { throw new ArgumentException("argumentVariations contains more elements than argumentTypes", "argumentVariations"); } List list = new List(); for (int i = 0; i < argumentTypes.Length; i++) { Type type = argumentTypes[i]; switch (argumentVariations[i]) { case ArgumentType.Ref: case ArgumentType.Out: type = type.MakeByRefType(); break; case ArgumentType.Pointer: type = type.MakePointerType(); break; } list.Add(type); } info.argumentTypes = list.ToArray(); } } [AttributeUsage(AttributeTargets.Delegate, AllowMultiple = true)] public class HarmonyDelegate : HarmonyPatch { public HarmonyDelegate(Type declaringType) : base(declaringType) { } public HarmonyDelegate(Type declaringType, Type[] argumentTypes) : base(declaringType, argumentTypes) { } public HarmonyDelegate(Type declaringType, string methodName) : base(declaringType, methodName) { } public HarmonyDelegate(Type declaringType, string methodName, params Type[] argumentTypes) : base(declaringType, methodName, argumentTypes) { } public HarmonyDelegate(Type declaringType, string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(declaringType, methodName, argumentTypes, argumentVariations) { } public HarmonyDelegate(Type declaringType, MethodDispatchType methodDispatchType) : base(declaringType, MethodType.Normal) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type declaringType, MethodDispatchType methodDispatchType, params Type[] argumentTypes) : base(declaringType, MethodType.Normal, argumentTypes) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type declaringType, MethodDispatchType methodDispatchType, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(declaringType, MethodType.Normal, argumentTypes, argumentVariations) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type declaringType, string methodName, MethodDispatchType methodDispatchType) : base(declaringType, methodName, MethodType.Normal) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(string methodName) : base(methodName) { } public HarmonyDelegate(string methodName, params Type[] argumentTypes) : base(methodName, argumentTypes) { } public HarmonyDelegate(string methodName, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(methodName, argumentTypes, argumentVariations) { } public HarmonyDelegate(string methodName, MethodDispatchType methodDispatchType) : base(methodName, MethodType.Normal) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(MethodDispatchType methodDispatchType) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(MethodDispatchType methodDispatchType, params Type[] argumentTypes) : base(MethodType.Normal, argumentTypes) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(MethodDispatchType methodDispatchType, Type[] argumentTypes, ArgumentType[] argumentVariations) : base(MethodType.Normal, argumentTypes, argumentVariations) { info.nonVirtualDelegate = methodDispatchType == MethodDispatchType.Call; } public HarmonyDelegate(Type[] argumentTypes) : base(argumentTypes) { } public HarmonyDelegate(Type[] argumentTypes, ArgumentType[] argumentVariations) : base(argumentTypes, argumentVariations) { } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class HarmonyReversePatch : HarmonyAttribute { public HarmonyReversePatch(HarmonyReversePatchType type = HarmonyReversePatchType.Original) { info.reversePatchType = type; } } [AttributeUsage(AttributeTargets.Class)] public class HarmonyPatchAll : HarmonyAttribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyPriority : HarmonyAttribute { public HarmonyPriority(int priority) { info.priority = priority; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyBefore : HarmonyAttribute { public HarmonyBefore(params string[] before) { info.before = before; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyAfter : HarmonyAttribute { public HarmonyAfter(params string[] after) { info.after = after; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyDebug : HarmonyAttribute { public HarmonyDebug() { info.debug = true; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyEmitIL : HarmonyAttribute { public HarmonyEmitIL() { info.debugEmitPath = "./"; } public HarmonyEmitIL(string dir) { info.debugEmitPath = dir; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class HarmonyWrapSafe : HarmonyAttribute { public HarmonyWrapSafe() { info.wrapTryCatch = true; } } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPrepare : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyCleanup : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTargetMethod : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTargetMethods : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPrefix : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyPostfix : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyTranspiler : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyILManipulator : Attribute { } [AttributeUsage(AttributeTargets.Method)] public class HarmonyFinalizer : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = true)] public class HarmonyArgument : Attribute { public string OriginalName { get; private set; } public int Index { get; private set; } public string NewName { get; private set; } public HarmonyArgument(string originalName) : this(originalName, null) { } public HarmonyArgument(int index) : this(index, null) { } public HarmonyArgument(string originalName, string newName) { OriginalName = originalName; Index = -1; NewName = newName; } public HarmonyArgument(int index, string name) { OriginalName = null; Index = index; NewName = name; } } [AttributeUsage(AttributeTargets.Method)] public class HarmonyOptional : HarmonyAttribute { public HarmonyOptional() { info.optional = true; } } public class CodeInstruction { public OpCode opcode; public object operand; public List