コード例 #1
0
 internal static List <AttributePatch> GetPatchMethods(Type type, bool collectIncomplete = false)
 {
     return(AccessTools.GetDeclaredMethods(type)
            .SelectMany(m => AttributePatch.Create(m, collectIncomplete))
            .Where(attributePatch => attributePatch is object)
            .ToList());
 }
コード例 #2
0
 internal static List <AttributePatch> GetPatchMethods(Type type)
 {
     return(AccessTools.GetDeclaredMethods(type)
            .Select(method => AttributePatch.Create(method))
            .Where(attributePatch => attributePatch != null)
            .ToList());
 }
コード例 #3
0
 internal static List <AttributePatch> GetPatchMethods(Type type)
 {
     return(AccessTools.GetDeclaredMethods(type)
            .SelectMany(AttributePatch.Create)
            .Where(attributePatch => attributePatch is object)
            .ToList());
 }
コード例 #4
0
        private MethodInfo GetTranspiler(MethodInfo method)
        {
            var methodName = method.Name;
            var type       = method.DeclaringType;
            var methods    = AccessTools.GetDeclaredMethods(type);
            var ici        = typeof(IEnumerable <CodeInstruction>);

            return(methods.FirstOrDefault(m => m.ReturnType == ici && m.Name.StartsWith($"<{methodName}>")));
        }
コード例 #5
0
        internal static List <AttributePatch> GetPatchMethods(Type type)
        {
            var harmonyPatchName = typeof(HarmonyPatch).FullName;

            return(AccessTools.GetDeclaredMethods(type)
                   .Select(method => AttributePatch.Create(method))
                   .Where(attributePatch => attributePatch != null)
                   .ToList());
        }
コード例 #6
0
        List <MethodBase> GetBulkMethods()
        {
            var isPatchAll = containerType.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName);

            if (isPatchAll)
            {
                var type = containerAttributes.declaringType;
                if (type == null)
                {
                    throw new ArgumentException($"Using {typeof(HarmonyPatchAll).FullName} requires an additional attribute for specifying the Class/Type");
                }

                var list = new List <MethodBase>();
                list.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>());
                list.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>());
                var props = AccessTools.GetDeclaredProperties(type);
                list.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method != null).Cast <MethodBase>());
                list.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method != null).Cast <MethodBase>());
                return(list);
            }

            string FailOnResult(IEnumerable <MethodBase> res)
            {
                if (res == null)
                {
                    return("null");
                }
                if (res.Any(m => m == null))
                {
                    return("some element was null");
                }
                return(null);
            }

            var targetMethods = RunMethod <HarmonyTargetMethods, IEnumerable <MethodBase> >(null, null, FailOnResult);

            if (targetMethods != null)
            {
                return(targetMethods.ToList());
            }

            var result       = new List <MethodBase>();
            var targetMethod = RunMethod <HarmonyTargetMethod, MethodBase>(null, null, method => method == null ? "null" : null);

            if (targetMethod != null)
            {
                result.Add(targetMethod);
            }
            return(result);
        }
コード例 #7
0
        internal static MethodInfo GetManipulator(MethodInfo method)
        {
            var methodName = method.Name;
            var type       = method.DeclaringType;
            var methods    = AccessTools.GetDeclaredMethods(type);
            var ctxType    = typeof(ILContext);

            return(methods.FirstOrDefault(m =>
            {
                if (!m.GetParameters().Select(p => p.ParameterType).Contains(ctxType))
                {
                    return false;
                }
                return m.Name.StartsWith($"<{methodName }>");
            }));
        }
コード例 #8
0
        internal static MethodInfo GetTranspiler(MethodInfo method)
        {
            var methodName = method.Name;
            var type       = method.DeclaringType;
            var methods    = AccessTools.GetDeclaredMethods(type);
            var ici        = typeof(IEnumerable <CodeInstruction>);

            return(methods.FirstOrDefault(m =>
            {
                if (m.ReturnType != ici)
                {
                    return false;
                }
                return m.Name.StartsWith($"<{methodName }>");
            }));
        }
コード例 #9
0
        List <MethodBase> GetBulkMethods()
        {
            var isPatchAll = containerType.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName);

            if (isPatchAll)
            {
                var type = containerAttributes.declaringType;
                if (type is null)
                {
                    throw new ArgumentException($"Using {typeof(HarmonyPatchAll).FullName} requires an additional attribute for specifying the Class/Type");
                }

                var list = new List <MethodBase>();
                list.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>());
                list.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>());
                var props = AccessTools.GetDeclaredProperties(type);
                list.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method is object).Cast <MethodBase>());
                list.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method is object).Cast <MethodBase>());
                return(list);
            }
コード例 #10
0
        void PrepareType()
        {
            var mainPrepareResult = RunMethod <HarmonyPrepare, bool>(true);

            if (mainPrepareResult == false)
            {
                return;
            }

            var customOriginals = RunMethod <HarmonyTargetMethods, IEnumerable <MethodBase> >(null);

            if (customOriginals != null)
            {
                originals.Clear();
                originals.AddRange(customOriginals);
            }
            else
            {
                var originalMethodType = containerAttributes.methodType;

                // MethodType default is Normal
                if (containerAttributes.methodType == null)
                {
                    containerAttributes.methodType = MethodType.Normal;
                }

                var isPatchAll = container.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName);
                if (isPatchAll)
                {
                    var type = containerAttributes.declaringType;
                    originals.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>());
                    originals.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>());
                    var props = AccessTools.GetDeclaredProperties(type);
                    originals.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method != null).Cast <MethodBase>());
                    originals.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method != null).Cast <MethodBase>());
                }
                else
                {
                    var original = RunMethod <HarmonyTargetMethod, MethodBase>(null);

                    if (original == null)
                    {
                        original = GetOriginalMethod();
                    }

                    if (original == null)
                    {
                        var info = "(";
                        info += "declaringType=" + containerAttributes.declaringType + ", ";
                        info += "methodName =" + containerAttributes.methodName + ", ";
                        info += "methodType=" + originalMethodType + ", ";
                        info += "argumentTypes=" + containerAttributes.argumentTypes.Description();
                        info += ")";
                        throw new ArgumentException("No target method specified for class " + container.FullName + " " + info);
                    }

                    originals.Add(original);
                }
            }

            PatchTools.GetPatches(container, out var prefixMethod, out var postfixMethod, out var transpilerMethod, out var finalizerMethod);
            if (prefix != null)
            {
                prefix.method = prefixMethod;
            }
            if (postfix != null)
            {
                postfix.method = postfixMethod;
            }
            if (transpiler != null)
            {
                transpiler.method = transpilerMethod;
            }
            if (finalizer != null)
            {
                finalizer.method = finalizerMethod;
            }

            if (prefixMethod != null)
            {
                if (prefixMethod.IsStatic == false)
                {
                    throw new ArgumentException("Patch method " + prefixMethod.FullDescription() + " must be static");
                }

                var prefixAttributes = HarmonyMethodExtensions.GetFromMethod(prefixMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(prefixAttributes)).CopyTo(prefix);
            }

            if (postfixMethod != null)
            {
                if (postfixMethod.IsStatic == false)
                {
                    throw new ArgumentException("Patch method " + postfixMethod.FullDescription() + " must be static");
                }

                var postfixAttributes = HarmonyMethodExtensions.GetFromMethod(postfixMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(postfixAttributes)).CopyTo(postfix);
            }

            if (transpilerMethod != null)
            {
                if (transpilerMethod.IsStatic == false)
                {
                    throw new ArgumentException("Patch method " + transpilerMethod.FullDescription() + " must be static");
                }

                var transpilerAttributes = HarmonyMethodExtensions.GetFromMethod(transpilerMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(transpilerAttributes)).CopyTo(transpiler);
            }

            if (finalizerMethod != null)
            {
                if (finalizerMethod.IsStatic == false)
                {
                    throw new ArgumentException("Patch method " + finalizerMethod.FullDescription() + " must be static");
                }

                var finalizerAttributes = HarmonyMethodExtensions.GetFromMethod(finalizerMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(finalizerAttributes)).CopyTo(finalizer);
            }
        }
コード例 #11
0
        private void PrepareType()
        {
            var mainPrepareResult = RunMethod <HarmonyPrepare, bool>(true);

            if (mainPrepareResult == false)
            {
                return;
            }

            var originalMethodType = containerAttributes.methodType;

            // MethodType default is Normal
            if (containerAttributes.methodType == null)
            {
                containerAttributes.methodType = MethodType.Normal;
            }

            var reversePatchAttr    = typeof(HarmonyReversePatch).FullName;
            var reversePatchMethods = container.GetMethods(AccessTools.all).Where(m => m.GetCustomAttributes(true).Any(a => a.GetType().FullName == reversePatchAttr)).ToList();

            foreach (var reversePatchMethod in reversePatchMethods)
            {
                var attr           = containerAttributes.Merge(new HarmonyMethod(reversePatchMethod));
                var originalMethod = GetOriginalMethod(attr);
                var reversePatcher = instance.CreateReversePatcher(originalMethod, reversePatchMethod);
                reversePatcher.Patch();
            }

            var customOriginals = RunMethod <HarmonyTargetMethods, IEnumerable <MethodBase> >(null);

            if (customOriginals != null)
            {
                originals.Clear();
                originals.AddRange(customOriginals);
            }
            else
            {
                var isPatchAll = container.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName);
                if (isPatchAll)
                {
                    var type = containerAttributes.declaringType;
                    originals.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>());
                    originals.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>());
                    var props = AccessTools.GetDeclaredProperties(type);
                    originals.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method != null)
                                       .Cast <MethodBase>());
                    originals.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method != null)
                                       .Cast <MethodBase>());
                }
                else
                {
                    var original = RunMethod <HarmonyTargetMethod, MethodBase>(null) ?? GetOriginalMethod(containerAttributes);

                    if (original == null)
                    {
                        var info = "(";
                        info += $"declaringType={containerAttributes.declaringType}, ";
                        info += $"methodName ={containerAttributes.methodName}, ";
                        info += $"methodType={originalMethodType}, ";
                        info += $"argumentTypes={containerAttributes.argumentTypes.Description()}";
                        info += ")";
                        throw new ArgumentException(
                                  $"No target method specified for class {container.FullName} {info}");
                    }

                    originals.Add(original);
                }
            }

            GetPatches(container, out var prefixMethod, out var postfixMethod, out var transpilerMethod,
                       out var finalizerMethod);
            if (prefix != null)
            {
                prefix.method = prefixMethod;
            }
            if (postfix != null)
            {
                postfix.method = postfixMethod;
            }
            if (transpiler != null)
            {
                transpiler.method = transpilerMethod;
            }
            if (finalizer != null)
            {
                finalizer.method = finalizerMethod;
            }

            if (prefixMethod != null)
            {
                if (prefixMethod.IsStatic == false)
                {
                    throw new ArgumentException($"Patch method {prefixMethod.GetID()} must be static");
                }

                var prefixAttributes = HarmonyMethodExtensions.GetFromMethod(prefixMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(prefixAttributes)).CopyTo(prefix);
            }

            if (postfixMethod != null)
            {
                if (postfixMethod.IsStatic == false)
                {
                    throw new ArgumentException($"Patch method {postfixMethod.GetID()} must be static");
                }

                var postfixAttributes = HarmonyMethodExtensions.GetFromMethod(postfixMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(postfixAttributes)).CopyTo(postfix);
            }

            if (transpilerMethod != null)
            {
                if (transpilerMethod.IsStatic == false)
                {
                    throw new ArgumentException($"Patch method {transpilerMethod.GetID()} must be static");
                }

                var transpilerAttributes = HarmonyMethodExtensions.GetFromMethod(transpilerMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(transpilerAttributes)).CopyTo(transpiler);
            }

            if (finalizerMethod != null)
            {
                if (finalizerMethod.IsStatic == false)
                {
                    throw new ArgumentException($"Patch method {finalizerMethod.GetID()} must be static");
                }

                var finalizerAttributes = HarmonyMethodExtensions.GetFromMethod(finalizerMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(finalizerAttributes)).CopyTo(finalizer);
            }
        }