예제 #1
0
        internal static void DoDetours()
        {
            // provide some info
            Verse.Log.Message("FluffyLib :: Detours :: Scanning mod assemblies for detour requests...");

            // loop over all methods and properties in all mod's assemblies
            foreach (ModContentPack mod in LoadedModManager.RunningMods)
            {
#if DEBUG_SPAMMY_DETOURS
                Verse.Log.Message(mod.Name);
#endif
                foreach (Assembly assembly in mod.assemblies.loadedAssemblies)
                {
#if DEBUG_SPAMMY_DETOURS
                    Verse.Log.Message("\t" + assembly.FullName);
#endif
                    foreach (Type type in assembly.GetTypes())
                    {
#if DEBUG_SPAMMY_DETOURS
                        Verse.Log.Message("\t\t" + type.FullName);
#endif
                        foreach (MethodInfo methodInfo in type.GetMethods(AllBindingFlags))
                        {
#if DEBUG_SPAMMY_DETOURS
                            Verse.Log.Message("\t\t\t" + methodInfo.Name);
#endif
                            if (methodInfo.HasAttribute <DetourMethodAttribute>())
                            {
#if DEBUG_SPAMMY_DETOURS
                                Verse.Log.Message("\t\t\t\t" + "DING!");
#endif
                                // if attribute is defined, do the detour
                                DetourMethodAttribute detourAttribute = methodInfo.GetCustomAttributes(typeof(DetourMethodAttribute), false).First() as DetourMethodAttribute;
                                HandleDetour(detourAttribute, methodInfo);
                            }
                        }
                        foreach (PropertyInfo propertyInfo in type.GetProperties((AllBindingFlags)))
                        {
#if DEBUG_SPAMMY_DETOURS
                            Verse.Log.Message("\t\t\t" + propertyInfo.Name);
#endif
                            if (propertyInfo.HasAttribute <DetourPropertyAttribute>())
                            {
#if DEBUG_SPAMMY_DETOURS
                                Verse.Log.Message("\t\t\t\t" + "DING!");
#endif
                                // if attribute is defined, do the detour
                                DetourPropertyAttribute detourAttribute = propertyInfo.GetCustomAttributes(typeof(DetourPropertyAttribute), false).First() as DetourPropertyAttribute;
                                HandleDetour(detourAttribute, propertyInfo);
                            }
                        }
                    }
                }
            }

#if DEBUG
            DetourTest.RunTests();
#endif
        }
예제 #2
0
        private static MethodInfo GetMatchingMethodInfo(DetourMethodAttribute sourceAttribute, MethodInfo targetInfo)
        {
            // we should only ever get here in case the attribute was not defined with a sourceMethodInfo, but let's check just in case.
            if (sourceAttribute.WasSetByMethodInfo)
            {
                return(sourceAttribute.sourceMethodInfo);
            }

            // aight, let's search by name
            MethodInfo[] candidates =
                sourceAttribute.sourceType.GetMethods(AllBindingFlags)
                .Where(mi => mi.Name == sourceAttribute.sourceMethodName).ToArray();

            // if we only get one result, we've got our method info - if the length is zero, the method doesn't exist.
            if (candidates.Length == 0)
            {
                return(null);
            }
            if (candidates.Length == 1)
            {
                return(candidates.First());
            }

            // this is where things get slightly complicated, we'll have to search by parameters.
            candidates = candidates.Where(mi =>
                                          mi.ReturnType == targetInfo.ReturnType &&
                                          mi.GetParameters()
                                          .Select(pi => pi.ParameterType)
                                          .SequenceEqual(targetInfo.GetParameters().Select(pi => pi.ParameterType)))
                         .ToArray();

            // if we only get one result, we've got our method info - if the length is zero, the method doesn't exist.
            if (candidates.Length == 0)
            {
                return(null);
            }
            if (candidates.Length == 1)
            {
                return(candidates.First());
            }

            // if we haven't returned anything by this point there were still multiple candidates. This is theoretically impossible,
            // unless I missed something.
            return(null);
        }
예제 #3
0
        private static void HandleDetour(DetourMethodAttribute sourceAttribute, MethodInfo targetInfo)
        {
            // we need to get the method info of the source (usually, vanilla) method.
            // if it was specified in the attribute, this is easy. Otherwise, we'll have to do some digging.
            MethodInfo sourceInfo = sourceAttribute.WasSetByMethodInfo
                                        ? sourceAttribute.sourceMethodInfo
                                        : GetMatchingMethodInfo(sourceAttribute, targetInfo);

            // make sure we've got what we wanted.
            if (sourceInfo == null)
            {
                throw new NullReferenceException("sourceMethodInfo could not be found based on attribute");
            }
            if (targetInfo == null)
            {
                throw new ArgumentNullException(nameof(targetInfo));
            }

            // call the actual detour
            TryDetourFromTo(sourceInfo, targetInfo);
        }