Ejemplo n.º 1
0
            /// <summary>
            /// Transpiles LoadDLLs to grab the exception information when a mod fails to load.
            /// </summary>
            private static IEnumerable <CodeInstruction> Transpiler(
                IEnumerable <CodeInstruction> method)
            {
                var instructions = new List <CodeInstruction>(method);
                // HarmonyInstance.Create and Assembly.LoadFrom will be wrapped
                var harmonyCreate = typeof(HarmonyInstance).GetMethodSafe(nameof(
                                                                              HarmonyInstance.Create), true, typeof(string));
                var loadFrom = typeof(Assembly).GetMethodSafe(nameof(Assembly.LoadFrom), true,
                                                              typeof(string));
                bool patchException = PUtil.GameVersion >= 397125u, patchAssembly = false,
                     patchCreate = false;

                // Add call to our handler in exception block, and wrap harmony instances to
                // have more information on each mod
                for (int i = instructions.Count - 1; i > 0; i--)
                {
                    var instr = instructions[i];
                    if (instr.opcode == OpCodes.Pop && !patchException)
                    {
                        instr.opcode = OpCodes.Call;
                        // Call our method instead
                        instr.operand = typeof(ModLoadHandler).GetMethodSafe(nameof(
                                                                                 ModLoadHandler.HandleModException), true, typeof(object));
                        patchException = true;
                    }
                    else if (instr.opcode == OpCodes.Call)
                    {
                        var target = instr.operand as MethodInfo;
                        if (target == harmonyCreate && harmonyCreate != null)
                        {
                            // Reroute HarmonyInstance.Create
                            instr.operand = typeof(ModLoadHandler).GetMethodSafe(nameof(
                                                                                     ModLoadHandler.CreateHarmonyInstance), true, typeof(string));
                            patchCreate = true;
                        }
                        else if (target == loadFrom && loadFrom != null)
                        {
                            // Reroute Assembly.LoadFrom
                            instr.operand = typeof(ModLoadHandler).GetMethodSafe(nameof(
                                                                                     ModLoadHandler.LoadAssembly), true, typeof(string));
                            patchAssembly = true;
                        }
                    }
                }
                if (!patchException)
                {
                    DebugLogger.LogError("Unable to transpile LoadDLLs: Could not find exception handler");
                }
                if (!patchAssembly)
                {
                    DebugLogger.LogWarning("Unable to transpile LoadDLLs: No calls to Assembly.LoadFrom found");
                }
                if (!patchCreate)
                {
                    DebugLogger.LogWarning("Unable to transpile LoadDLLs: No calls to HarmonyInstance.Create found");
                }
                return(instructions);
            }
Ejemplo n.º 2
0
            /// <summary>
            /// Applied before OnPrefabInit runs.
            /// </summary>
            internal static MethodBase TargetMethod()
            {
                MethodBase target = null;

#if DEBUG
                DebugLogger.LogDebug("Transpiling LoadDLLs()");
#endif
                try {
                    target = typeof(Mod).Assembly.GetType("KMod.DLLLoader", false)?.
                             GetMethodSafe("LoadDLLs", true, PPatchTools.AnyArguments);
                    if (target == null)
                    {
                        DebugLogger.LogError("Unable to transpile LoadDLLs: Method not found");
                    }
                } catch (IOException e) {
                    // This should theoretically be impossible since the type is loaded
                    DebugLogger.BaseLogException(e, null);
                }
                return(target);
            }
Ejemplo n.º 3
0
        /// <summary>
        /// Logs exceptions where some types in an assembly fail to load, and adds the types
        /// that did load to the list anyways.
        /// </summary>
        /// <param name="exception">The exception thrown.</param>
        /// <param name="assembly">The assembly that failed to fully load.</param>
        /// <param name="types">The location to store types that did load.</param>
        private static void HandleTypeLoadExceptions(ReflectionTypeLoadException exception,
                                                     Assembly assembly, ICollection <Type> types)
        {
            var failedTypes = exception?.Types;

            DebugLogger.LogError("Error when loading types from " + assembly.FullName);
            if (failedTypes != null)
            {
                int n = failedTypes.Length;
                for (int i = 0; i < n; i++)
                {
                    var type   = failedTypes[i];
                    var thrown = exception.LoaderExceptions[i];
                    if (type != null)
                    {
                        types.Add(type);
                    }
                    else if (thrown != null)
                    {
                        DebugLogger.LogException(thrown);
                    }
                }
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Applied before LogException runs.
 /// </summary>
 internal static bool Prefix(Exception e, string errorMessage)
 {
     DebugLogger.LogError(errorMessage);
     DebugLogger.LogException(e);
     return(false);
 }