Exemple #1
0
        private static void ApplyHarmonyPatches([NotNull] List <Assembly> modAssemblies)
        {
            ModLogger.WriteLine("Applying Harmony patches");
            List <string> failedMods = new List <string>();

            foreach (Assembly modAssembly in modAssemblies)
            {
                if (modAssembly == null)
                {
                    continue;
                }

                try
                {
                    {
                        HarmonyInstance.Create(modAssembly.FullName)?.PatchAll(modAssembly);
                    }
                }
                catch (Exception e)
                {
                    failedMods.Add(modAssembly.GetName() + ExceptionToString(e));
                    ModLogger.Error.WriteLine("Patching mod " + modAssembly.GetName() + " failed!");
                    ModLogger.Error.WriteLine(e);
                }
            }

            if (failedMods.Count > 0)
            {
                throw new ModLoadingException("The following mods could not be patched:", failedMods);
            }
        }
Exemple #2
0
        public static DirectoryInfo GetModsDirectory()
        {
            DirectoryInfo dataDir = new DirectoryInfo(Application.dataPath);

            ModLogger.WriteLine("Data dir: " + dataDir.FullName);
            ModLogger.WriteLine("RuntimePlatform: " + Application.platform);

            DirectoryInfo oniBaseDirectory;

            if (Application.platform == RuntimePlatform.OSXPlayer)
            {
                oniBaseDirectory = new DirectoryInfo(Path.Combine(dataDir.FullName, "Resources"));
            }
            else if (Application.platform == RuntimePlatform.LinuxPlayer)
            {
                oniBaseDirectory = dataDir.Parent;
            }
            else
            {
                oniBaseDirectory = dataDir.Parent;
            }

            ModLogger.WriteLine("Path to mods is: " + Path.Combine(oniBaseDirectory?.FullName, "Mods"));
            return(new DirectoryInfo(Path.Combine(oniBaseDirectory?.FullName, "Mods")));
        }
Exemple #3
0
        private static DependencyGraph PreloadModAssemblies(List <FileInfo> assemblyFiles)
        {
            ModLogger.WriteLine("Loading mod assemblies");
            List <Assembly> loadedAssemblies = new List <Assembly>();
            List <string>   failedAssemblies = new List <string>();

            if (assemblyFiles != null)
            {
                foreach (FileInfo file in assemblyFiles)
                {
                    if (file?.Extension != ".dll")
                    {
                        // GetFiles filter is too inclusive
                        continue;
                    }

                    if (file.Name.ToLower() == "0harmony" || file.Name.ToLower() == "modloader"
                        )
                    {
                        // GetFiles filter is too inclusive
                        continue;
                    }

                    try
                    {
                        //Assembly modAssembly = Assembly.LoadFrom(file.FullName);
                        Assembly modAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
                        if (loadedAssemblies.Contains(modAssembly))
                        {
                            ModLogger.WriteLine("Skipping duplicate mod " + modAssembly.FullName);
                        }
                        else
                        {
                            ModLogger.WriteLine("Preloading " + modAssembly.FullName);
                            loadedAssemblies.Add(modAssembly);
                        }
                    }
                    catch (Exception e)
                    {
                        failedAssemblies.Add(file.Name + ExceptionToString(e));
                        ModLogger.Error.WriteLine("Preloading mod " + file.Name + " failed!");
                        ModLogger.Error.WriteLine(e);
                    }
                }
            }

            if (failedAssemblies.Count > 0)
            {
                throw new ModLoadingException("The following mods could not be preloaded:", failedAssemblies);
            }

            return(new DependencyGraph(loadedAssemblies));
        }
Exemple #4
0
 private static bool CheckForEmbeddedDependence(string name, Assembly modAssembly)
 {
     // Load embedded resources to check inner dependences
     string[] resources = modAssembly.GetManifestResourceNames();
     foreach (string resource in resources)
     {
         ModLogger.WriteLine("\t\t\t" + resource);
         if (resource.Contains(name))
         {
             return(true);
         }
     }
     return(false);
 }
Exemple #5
0
        public static void Start()
        {
            ModLogger.WriteLine("Initializing Modloader " + ModLoaderVersion);

            // Patch in Mod Loader helpers
            HarmonyInstance.Create("ONI-ModLoader")?.PatchAll(Assembly.GetExecutingAssembly());

            // Load mods
            DirectoryInfo modsDir = GetModsDirectory();

            /*
             * List<FileInfo> files = modsDir.GetFiles("*.dll").ToList();
             * foreach (DirectoryInfo modDirectory in modsDir.GetDirectories())
             * {
             *  DirectoryInfo[] sub = modDirectory?.GetDirectories();
             *  DirectoryInfo assmeblies = sub?.FirstOrDefault(x => x != null && x.Name.Contains(AssemblyDir));
             *  if (assmeblies != null)
             *  {
             *      foreach (FileInfo file in assmeblies.GetFiles("*.dll"))
             *      {
             *          files.Add(file);
             *      }
             *  }
             * }
             */
            string[] pathFiles = Directory.GetFiles(modsDir.FullName, "*.dll", SearchOption.AllDirectories);

            List <FileInfo> files = new List <FileInfo>();

            foreach (var file in pathFiles)
            {
                files.Add(new FileInfo(file));
            }

            try
            {
                DependencyGraph dependencyGraph  = PreloadModAssemblies(files);
                List <Assembly> sortedAssemblies = dependencyGraph?.TopologicalSort();
                List <Assembly> loadableMods     = CheckForDependences(sortedAssemblies);
                List <Assembly> loadedMods       = ApplyHarmonyPatches(loadableMods);
                CallOnLoadMethods(loadedMods);

                ModLogger.WriteLine("All mods successfully loaded!");
            }
            catch (ModLoadingException mle)
            {
                failureMessage = mle.Message;
            }
        }
Exemple #6
0
        private static DirectoryInfo GetModsDirectory()
        {
            DirectoryInfo dataDir = new DirectoryInfo(Application.dataPath);

            DirectoryInfo oniBaseDirectory;

            if (Application.platform == RuntimePlatform.OSXPlayer)
            {
                oniBaseDirectory = dataDir.Parent?.Parent;
            }
            else
            {
                oniBaseDirectory = dataDir.Parent;
            }

            ModLogger.WriteLine("Path to mods is: " + Path.Combine(oniBaseDirectory?.FullName, "Mods"));
            return(new DirectoryInfo(Path.Combine(oniBaseDirectory?.FullName, "Mods")));
        }
Exemple #7
0
        private static List <Assembly> ApplyHarmonyPatches([NotNull] List <Assembly> modAssemblies)
        {
            ModLogger.WriteLine("Applying Harmony patches");
            List <string>   failedMods = new List <string>();
            List <Assembly> loadedMods = new List <Assembly>();

            foreach (Assembly modAssembly in modAssemblies)
            {
                if (modAssembly == null)
                {
                    continue;
                }

                try
                {
                    ModLogger.WriteLine("Loading: " + modAssembly.FullName);
                    Assembly loaded = Assembly.LoadFrom(modAssembly.Location);
                    HarmonyInstance.Create(loaded.FullName)?.PatchAll(loaded);
                    loadedMods.Add(loaded);
                }
                catch (Exception e)
                {
                    failedMods.Add(modAssembly.GetName() + ExceptionToString(e));
                    ModLogger.Error.WriteLine("Patching mod " + modAssembly.GetName() + " failed!");
                    ModLogger.Error.WriteLine(e);
                }
            }

            if (failedMods.Count > 0)
            {
                //throw new ModLoadingException("The following mods could not be patched:", failedMods);
                string message = "\nThe following mods could not be patched:\n" + String.Join("\n\t", failedMods.ToArray());
                ModLogger.Error.WriteLine(message);

                /*
                 * MainMenu mainMenus = (MainMenu)UnityEngine.Object.FindObjectOfType(typeof(MainMenu));
                 *
                 *
                 * ConfirmDialogScreen confirmDialogScreen = Util.KInstantiateUI<ConfirmDialogScreen>(ScreenPrefabs.Instance.ConfirmDialogScreen.gameObject, mainMenus.gameObject, force_active: true);
                 * confirmDialogScreen.PopupConfirmDialog(message, null, null);
                 */
            }
            return(loadedMods);
        }
        public DependencyGraph(List <Assembly> modAssemblies)
        {
            int size = modAssemblies.Count;

            this.vertices   = new Vertex[size];
            this.nameLookup = new Dictionary <string, Vertex>(size);

            // Create vertices
            for (int i = 0; i < size; ++i)
            {
                Assembly modAssembly = modAssemblies[i];
                string   modName     = Path.GetFileNameWithoutExtension(modAssembly.Location);

                Vertex modVertex = new Vertex(i, modAssembly, modName);
                this.vertices[i] = modVertex;
                this.nameLookup[modAssembly.FullName] = modVertex;
            }

            // Add edges
            foreach (Vertex modVertex in this.vertices)
            {
                Assembly modAssembly = modVertex.assembly;

                foreach (AssemblyName referenced in modAssembly.GetReferencedAssemblies())
                {
                    //if (this.nameLookup.TryGetValue(referenced.FullName, out Vertex dependencyVertex))
                    Vertex dependencyVertex;
                    if (this.nameLookup.TryGetValue(referenced.FullName, out dependencyVertex))
                    {
                        modVertex.dependencies.Add(dependencyVertex);
                        dependencyVertex.dependents.Add(modVertex);
                    }
                    else if (referenced.CodeBase != null)
                    {
                        ModLogger.WriteLine(
                            "Dependency " + referenced.FullName + " at " + referenced.CodeBase
                            + " was not a mod");
                    }
                }
            }
        }
Exemple #9
0
        public static void Start()
        {
            ModLogger.WriteLine("Initializing Modloader " + ModLoaderVersion);

            // Patch in Mod Loader helpers
            HarmonyInstance.Create("ONI-ModLoader")?.PatchAll(Assembly.GetExecutingAssembly());

            // Load mods
            DirectoryInfo modsDir = GetModsDirectory();

            List <FileInfo> files = modsDir.GetFiles("*.dll").ToList();

            foreach (DirectoryInfo modDirectory in modsDir.GetDirectories())
            {
                DirectoryInfo[] sub        = modDirectory?.GetDirectories();
                DirectoryInfo   assmeblies = sub?.FirstOrDefault(x => x != null && x.Name.Contains(AssemblyDir));
                if (assmeblies != null)
                {
                    foreach (FileInfo file in assmeblies.GetFiles("*.dll"))
                    {
                        files.Add(file);
                    }
                }
            }

            try
            {
                DependencyGraph dependencyGraph  = LoadModAssemblies(files);
                List <Assembly> sortedAssemblies = dependencyGraph?.TopologicalSort();

                ApplyHarmonyPatches(sortedAssemblies);
                CallOnLoadMethods(sortedAssemblies);

                ModLogger.WriteLine("All mods successfully loaded!");
            }
            catch (ModLoadingException mle)
            {
                failureMessage = mle.Message;
            }
        }
Exemple #10
0
        private static void CallOnLoadMethods([NotNull] List <Assembly> modAssemblies)
        {
            ModLogger.WriteLine("Calling OnLoad methods");

            foreach (Assembly modAssembly in modAssemblies)
            {
                if (modAssembly == null)
                {
                    continue;
                }

                foreach (Type type in modAssembly.GetTypes())
                {
                    if (type == null)
                    {
                        continue;
                    }

                    try
                    {
                        MethodInfo onLoad = type.GetMethod("OnLoad", new Type[0]);
                        onLoad?.Invoke(null, new object[0]);
                    }
                    catch (Exception e)
                    {
                        if (e is TargetInvocationException && e.InnerException != null)
                        {
                            e = e.InnerException;
                        }

                        string message = "OnLoad method failed for type " + type.FullName + " of mod "
                                         + modAssembly.GetName().Name;
                        ModLogger.Error.WriteLine(message);
                        ModLogger.Error.WriteLine(e);
                        throw new ModLoadingException(message + ExceptionToString(e));
                    }
                }
            }
        }
Exemple #11
0
        private static List <Assembly> CheckForDependences(List <Assembly> modAssemblies)
        {
            ModLogger.WriteLine("CheckForDependences");
            List <string>   failedMods   = new List <string>();
            List <Assembly> loadableMods = new List <Assembly>();

            foreach (Assembly modAssembly in modAssemblies)
            {
                if (modAssembly == null)
                {
                    continue;
                }

                try
                {
                    ModLogger.WriteLine("\tChecking " + modAssembly.FullName);

                    bool correct = true;
                    foreach (AssemblyName referenced in modAssembly.GetReferencedAssemblies())
                    {
                        ModLogger.WriteLine("\t\t" + referenced.FullName);
                        try
                        {
                            Assembly dependence = Assembly.ReflectionOnlyLoad(referenced.FullName);
                            if (dependence == null)
                            {
                                correct = false;
                                ModLogger.Error.WriteLine("\tCannot find dependence: " + referenced.FullName);

                                continue;
                            }
                        }
                        catch (Exception ex)
                        {
                            ModLogger.WriteLine("\t\t\tChecking embedded dependences:");
                            correct = CheckForEmbeddedDependence(referenced.Name, modAssembly);
                            if (!correct)
                            {
                                ModLogger.Error.WriteLine("\tCannot find dependence: " + referenced.FullName);
                                ModLogger.Error.WriteLine(ex);
                                continue;
                            }
                        }
                    }

                    if (correct)
                    {
                        loadableMods.Add(modAssembly);
                    }
                    else
                    {
                        failedMods.Add(modAssembly.GetName().ToString());
                    }
                }
                catch (Exception e)
                {
                    failedMods.Add(modAssembly.GetName() + ExceptionToString(e));
                    ModLogger.Error.WriteLine("Patching mod " + modAssembly.GetName() + " failed!");
                    ModLogger.Error.WriteLine(e);
                }
            }
            return(loadableMods);
        }