示例#1
0
        /// <summary>Create a patch processor from an annotated class</summary>
        /// <param name="type">The class</param>
        ///
        public PatchProcessor ProcessorForAnnotatedClass(Type type)
        {
            var parentMethodInfos = HarmonyMethodExtensions.GetFromType(type);

            if (parentMethodInfos != null && parentMethodInfos.Count() > 0)
            {
                var info = HarmonyMethod.Merge(parentMethodInfos);
                return(new PatchProcessor(this, type, info));
            }
            return(null);
        }
示例#2
0
 void ImportMethod(MethodInfo theMethod)
 {
     method = theMethod;
     if (method != null)
     {
         var infos = HarmonyMethodExtensions.GetFromMethod(method);
         if (infos != null)
         {
             Merge(infos).CopyTo(this);
         }
     }
 }
示例#3
0
        public static HarmonyMethod Merge(List <HarmonyMethod> attributes)
        {
            var result = new HarmonyMethod();

            if (attributes == null)
            {
                return(result);
            }
            var resultTrv = Traverse.Create(result);

            attributes.ForEach(attribute =>
            {
                var trv = Traverse.Create(attribute);
                HarmonyFields().ForEach(f =>
                {
                    var val = trv.Field(f).GetValue();
                    if (val != null)
                    {
                        HarmonyMethodExtensions.SetValue(resultTrv, f, val);
                    }
                });
            });
            return(result);
        }
示例#4
0
        void PrepareType()
        {
            var mainPrepareResult = RunMethod <HarmonyPrepare, bool>(true);

            if (mainPrepareResult == false)
            {
                return;
            }

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

            if (customOriginals != null)
            {
                originals = customOriginals.ToList();
            }
            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);
            if (prefix != null)
            {
                prefix.method = prefixMethod;
            }
            if (postfix != null)
            {
                postfix.method = postfixMethod;
            }
            if (transpiler != null)
            {
                transpiler.method = transpilerMethod;
            }

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

                var prefixAttributes = HarmonyMethodExtensions.GetFromMethod(prefix.method);
                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 infixAttributes = HarmonyMethodExtensions.GetFromMethod(transpilerMethod);
                containerAttributes.Merge(HarmonyMethod.Merge(infixAttributes)).CopyTo(transpiler);
            }
        }