Example #1
0
            public void Fetch()
            {
                // 1. Download the mod updates database
                updateCatalog = ModUpdaterHelper.DownloadModUpdateList();

                // 2. Find out what actually has been updated
                if (updateCatalog != null)
                {
                    availableUpdatesCatalog = ModUpdaterHelper.ListAvailableUpdates(updateCatalog, excludeBlacklist: false);
                }
            }
Example #2
0
        public override IEnumerator Enter(Oui from)
        {
            Everest.Loader.AutoLoadNewMods = false;

            menu = new TextMenu();

            // display the title and a dummy "Fetching" button
            menu.Add(new TextMenu.Header(Dialog.Clean("MODUPDATECHECKER_MENU_TITLE")));

            menu.Add(subHeader = new TextMenuExt.SubHeaderExt(Dialog.Clean("MODUPDATECHECKER_MENU_HEADER")));

            fetchingButton          = new TextMenu.Button(Dialog.Clean("MODUPDATECHECKER_FETCHING"));
            fetchingButton.Disabled = true;
            menu.Add(fetchingButton);

            Scene.Add(menu);

            menu.Visible = Visible = true;
            menu.Focused = false;

            for (float p = 0f; p < 1f; p += Engine.DeltaTime * 4f)
            {
                menu.X = offScreenX + -1920f * Ease.CubeOut(p);
                alpha  = Ease.CubeOut(p);
                yield return(null);
            }

            menu.Focused = true;
            menuOnScreen = true;

            task = new Task(() => {
                // 1. Download the mod updates database
                updateCatalog = ModUpdaterHelper.DownloadModUpdateList();

                // 2. Find out what actually has been updated
                if (updateCatalog != null)
                {
                    availableUpdatesCatalog = ModUpdaterHelper.ListAvailableUpdates(updateCatalog);
                }
            });

            task.Start();
        }
Example #3
0
        private void downloadAllDependencies()
        {
            // 1. Compute the list of dependencies we must download.
            LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_DOWNLOADING_DATABASE"));
            Dictionary <string, ModUpdateInfo> availableDownloads = ModUpdaterHelper.DownloadModUpdateList();

            if (availableDownloads == null)
            {
                shouldAutoRestart = false;
                shouldRestart     = false;

                LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_DOWNLOAD_DATABASE_FAILED"));
            }
            else
            {
                Logger.Log("OuiDependencyDownloader", "Computing dependencies to download...");

                // these mods are not installed currently, we will install them
                Dictionary <string, ModUpdateInfo> modsToInstall = new Dictionary <string, ModUpdateInfo>();

                // these mods are already installed, but need an update to satisfy the dependency
                Dictionary <string, ModUpdateInfo>         modsToUpdate = new Dictionary <string, ModUpdateInfo>();
                Dictionary <string, EverestModuleMetadata> modsToUpdateCurrentVersions = new Dictionary <string, EverestModuleMetadata>();

                // Everest should be updated to satisfy a dependency on Everest
                bool shouldUpdateEverest = false;

                // these mods are absent from the database
                HashSet <string> modsNotFound = new HashSet <string>();

                // these mods have multiple downloads, and as such, should be installed manually
                HashSet <string> modsNotInstallableAutomatically = new HashSet <string>();

                // these mods are blacklisted, and should be removed from the blacklist instead of being re-installed
                HashSet <string> modsBlacklisted = new HashSet <string>();

                // these mods are in the database, but the version found in there won't satisfy the dependency
                Dictionary <string, HashSet <Version> > modsWithIncompatibleVersionInDatabase = new Dictionary <string, HashSet <Version> >();
                Dictionary <string, string>             modsDatabaseVersions = new Dictionary <string, string>();

                foreach (EverestModuleMetadata dependency in MissingDependencies)
                {
                    if (Everest.Loader.Delayed.Any(delayedMod => dependency.Name == delayedMod.Item1.Name))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} is installed but failed to load, skipping");
                    }
                    else if (dependency.Name == "Everest")
                    {
                        Logger.Log("OuiDependencyDownloader", $"Everest should be updated");
                        shouldUpdateEverest = true;
                        shouldAutoRestart   = false;

                        // TODO: maybe check more precisely for blacklisted mods? We're only basing ourselves on the name here.
                    }
                    else if (Everest.Loader.Blacklist.Contains($"{dependency.Name}.zip"))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} is blacklisted, and should be unblacklisted instead");
                        modsBlacklisted.Add(dependency.Name);
                        shouldAutoRestart = false;
                    }
                    else if (!availableDownloads.ContainsKey(dependency.Name))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} was not found in the database");
                        modsNotFound.Add(dependency.Name);
                        shouldAutoRestart = false;
                    }
                    else if (availableDownloads[dependency.Name].xxHash.Count > 1)
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} has multiple versions and cannot be installed automatically");
                        modsNotInstallableAutomatically.Add(dependency.Name);
                        shouldAutoRestart = false;
                    }
                    else if (!isVersionCompatible(dependency.Version, availableDownloads[dependency.Name].Version))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} has a version in database ({availableDownloads[dependency.Name].Version}) that would not satisfy dependency ({dependency.Version})");

                        // add the required version to the list of versions for this mod
                        HashSet <Version> requiredVersions = modsWithIncompatibleVersionInDatabase.TryGetValue(dependency.Name, out HashSet <Version> result) ? result : new HashSet <Version>();
                        requiredVersions.Add(dependency.Version);
                        modsWithIncompatibleVersionInDatabase[dependency.Name] = requiredVersions;
                        modsDatabaseVersions[dependency.Name] = availableDownloads[dependency.Name].Version;
                        shouldAutoRestart = false;
                    }
                    else
                    {
                        EverestModuleMetadata installedVersion = null;
                        foreach (EverestModule module in Everest.Modules)
                        {
                            // note: if the mod is installed, but not as a zip, this will be treated as a fresh install rather than an update.
                            // this is fine since zips take the priority over directories, and we cannot update directory mods anyway.
                            if (module.Metadata.PathArchive != null && module.Metadata.Name == dependency.Name)
                            {
                                installedVersion = module.Metadata;
                                break;
                            }
                        }

                        if (installedVersion != null)
                        {
                            Logger.Log("OuiDependencyDownloader", $"{dependency.Name} is already installed and will be updated");
                            modsToUpdate[dependency.Name] = availableDownloads[dependency.Name];
                            modsToUpdateCurrentVersions[dependency.Name] = installedVersion;
                        }
                        else
                        {
                            Logger.Log("OuiDependencyDownloader", $"{dependency.Name} will be installed");
                            modsToInstall[dependency.Name] = availableDownloads[dependency.Name];
                        }
                    }
                }

                // actually install the mods now
                foreach (ModUpdateInfo modToInstall in modsToInstall.Values)
                {
                    downloadDependency(modToInstall, null);
                }

                foreach (ModUpdateInfo modToUpdate in modsToUpdate.Values)
                {
                    downloadDependency(modToUpdate, modsToUpdateCurrentVersions[modToUpdate.Name]);
                }

                // display all mods that couldn't be accounted for
                if (shouldUpdateEverest)
                {
                    LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_MUST_UPDATE_EVEREST"));
                }

                foreach (string mod in modsNotFound)
                {
                    LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_NOT_FOUND"), mod));
                }

                foreach (string mod in modsNotInstallableAutomatically)
                {
                    LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_NOT_AUTO_INSTALLABLE"), mod));
                }

                foreach (string mod in modsBlacklisted)
                {
                    LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_BLACKLISTED"), mod));
                }

                foreach (string mod in modsWithIncompatibleVersionInDatabase.Keys)
                {
                    LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_WRONG_VERSION"), mod,
                                          string.Join(", ", modsWithIncompatibleVersionInDatabase[mod]), modsDatabaseVersions[mod]));
                }
            }

            Progress    = 1;
            ProgressMax = 1;

            if (shouldAutoRestart)
            {
                // there are no errors to display: restart automatically
                LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_RESTARTING"));
                for (int i = 3; i > 0; --i)
                {
                    Lines[Lines.Count - 1] = string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_RESTARTING_IN"), i);
                    Thread.Sleep(1000);
                }
                Lines[Lines.Count - 1] = Dialog.Clean("DEPENDENCYDOWNLOADER_RESTARTING");

                Everest.QuickFullRestart();
            }
            else if (shouldRestart)
            {
                LogLine("\n" + Dialog.Clean("DEPENDENCYDOWNLOADER_PRESS_BACK_TO_RESTART"));
            }
            else
            {
                LogLine("\n" + Dialog.Clean("DEPENDENCYDOWNLOADER_PRESS_BACK_TO_GO_BACK"));
            }
        }
        private void downloadAllDependencies()
        {
            // 1. Compute the list of dependencies we must download.
            LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_DOWNLOADING_DATABASE"));

            Everest.Updater.Entry everestVersionToInstall = null;

            Dictionary <string, ModUpdateInfo> availableDownloads = ModUpdaterHelper.DownloadModUpdateList();

            if (availableDownloads == null)
            {
                shouldAutoExit = false;
                shouldRestart  = false;

                LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_DOWNLOAD_DATABASE_FAILED"));
            }
            else
            {
                // load information on all installed mods, so that we can spot blacklisted ones easily.
                LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_LOADING_INSTALLED_MODS"));

                Progress    = 0;
                ProgressMax = 100;
                Dictionary <string, EverestModuleMetadata[]> allModsInformationFlipped =
                    OuiModToggler.LoadAllModYamls(progress => {
                    Lines[Lines.Count - 1] = $"{Dialog.Clean("DEPENDENCYDOWNLOADER_LOADING_INSTALLED_MODS")} ({(int) (progress * 100)}%)";
                    Progress = (int)(progress * 100);
                });
                ProgressMax = 0;

                // but flip around the mapping for convenience.
                Dictionary <EverestModuleMetadata, string> allModsInformation = new Dictionary <EverestModuleMetadata, string>();
                foreach (KeyValuePair <string, EverestModuleMetadata[]> mods in allModsInformationFlipped)
                {
                    foreach (EverestModuleMetadata mod in mods.Value)
                    {
                        allModsInformation[mod] = mods.Key;
                    }
                }
                Lines[Lines.Count - 1] = $"{Dialog.Clean("DEPENDENCYDOWNLOADER_LOADING_INSTALLED_MODS")} {Dialog.Clean("DEPENDENCYDOWNLOADER_DONE")}";

                Logger.Log("OuiDependencyDownloader", "Computing dependencies to download...");

                // these mods are not installed currently, we will install them
                Dictionary <string, ModUpdateInfo> modsToInstall = new Dictionary <string, ModUpdateInfo>();

                // these mods are already installed, but need an update to satisfy the dependency
                Dictionary <string, ModUpdateInfo>         modsToUpdate = new Dictionary <string, ModUpdateInfo>();
                Dictionary <string, EverestModuleMetadata> modsToUpdateCurrentVersions = new Dictionary <string, EverestModuleMetadata>();

                // Everest should be updated to satisfy a dependency on Everest
                bool shouldUpdateEverestManually = false;

                // these mods are absent from the database
                HashSet <string> modsNotFound = new HashSet <string>();

                // these mods have multiple downloads, and as such, should be installed manually
                HashSet <string> modsNotInstallableAutomatically = new HashSet <string>();

                // these mods should be unblacklisted.
                HashSet <string> modFilenamesToUnblacklist = new HashSet <string>();

                // these mods are in the database, but the version found in there won't satisfy the dependency
                Dictionary <string, HashSet <Version> > modsWithIncompatibleVersionInDatabase = new Dictionary <string, HashSet <Version> >();
                Dictionary <string, string>             modsDatabaseVersions = new Dictionary <string, string>();

                foreach (EverestModuleMetadata dependency in MissingDependencies)
                {
                    if (Everest.Loader.Delayed.Any(delayedMod => dependency.Name == delayedMod.Item1.Name))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} is installed but failed to load, skipping");
                    }
                    else if (dependency.Name == "Everest")
                    {
                        Logger.Log("OuiDependencyDownloader", $"Everest should be updated");
                        shouldAutoExit = false;

                        if (dependency.Version.Major != 1 || dependency.Version.Build > 0 || dependency.Version.Revision > 0)
                        {
                            // the Everest version is not 1.XXX.0.0: Everest should be updated manually because this shouldn't happen.
                            shouldUpdateEverestManually = true;
                        }
                        else if (!shouldUpdateEverestManually && (everestVersionToInstall == null || everestVersionToInstall.Build < dependency.Version.Minor))
                        {
                            everestVersionToInstall = findEverestVersionToInstall(dependency.Version.Minor);
                            if (everestVersionToInstall == null)
                            {
                                // a suitable version was not found! so, it should be installed manually.
                                shouldUpdateEverestManually = true;
                            }
                        }
                    }
                    else if (tryUnblacklist(dependency, allModsInformation, modFilenamesToUnblacklist))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} is blacklisted, and should be unblacklisted instead");
                    }
                    else if (!availableDownloads.ContainsKey(dependency.Name))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} was not found in the database");
                        modsNotFound.Add(dependency.Name);
                        shouldAutoExit = false;
                    }
                    else if (availableDownloads[dependency.Name].xxHash.Count > 1)
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} has multiple versions and cannot be installed automatically");
                        modsNotInstallableAutomatically.Add(dependency.Name);
                        shouldAutoExit = false;
                    }
                    else if (!isVersionCompatible(dependency.Version, availableDownloads[dependency.Name].Version))
                    {
                        Logger.Log("OuiDependencyDownloader", $"{dependency.Name} has a version in database ({availableDownloads[dependency.Name].Version}) that would not satisfy dependency ({dependency.Version})");

                        // add the required version to the list of versions for this mod
                        HashSet <Version> requiredVersions = modsWithIncompatibleVersionInDatabase.TryGetValue(dependency.Name, out HashSet <Version> result) ? result : new HashSet <Version>();
                        requiredVersions.Add(dependency.Version);
                        modsWithIncompatibleVersionInDatabase[dependency.Name] = requiredVersions;
                        modsDatabaseVersions[dependency.Name] = availableDownloads[dependency.Name].Version;
                        shouldAutoExit = false;
                    }
                    else
                    {
                        EverestModuleMetadata installedVersion = null;
                        foreach (EverestModule module in Everest.Modules)
                        {
                            // note: if the mod is installed, but not as a zip, this will be treated as a fresh install rather than an update.
                            // this is fine since zips take the priority over directories, and we cannot update directory mods anyway.
                            if (module.Metadata.PathArchive != null && module.Metadata.Name == dependency.Name)
                            {
                                installedVersion = module.Metadata;
                                break;
                            }
                        }

                        if (installedVersion != null)
                        {
                            Logger.Log("OuiDependencyDownloader", $"{dependency.Name} is already installed and will be updated");
                            modsToUpdate[dependency.Name] = availableDownloads[dependency.Name];
                            modsToUpdateCurrentVersions[dependency.Name] = installedVersion;
                        }
                        else
                        {
                            Logger.Log("OuiDependencyDownloader", $"{dependency.Name} will be installed");
                            modsToInstall[dependency.Name] = availableDownloads[dependency.Name];
                        }
                    }
                }

                // actually install the mods now
                foreach (ModUpdateInfo modToInstall in modsToInstall.Values)
                {
                    downloadDependency(modToInstall, null);
                }

                foreach (ModUpdateInfo modToUpdate in modsToUpdate.Values)
                {
                    downloadDependency(modToUpdate, modsToUpdateCurrentVersions[modToUpdate.Name]);
                }

                // unblacklist mods if this is needed
                if (modFilenamesToUnblacklist.Count > 0)
                {
                    // remove the mods from blacklist.txt
                    if (!unblacklistMods(modFilenamesToUnblacklist))
                    {
                        // something bad happened
                        shouldAutoExit = false;
                        shouldRestart  = true;
                    }

                    foreach (string modFilename in modFilenamesToUnblacklist)
                    {
                        try {
                            LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_UNBLACKLIST"), modFilename));

                            // remove the mod from the loaded blacklist
                            while (Everest.Loader._Blacklist.Contains(modFilename))
                            {
                                Everest.Loader._Blacklist.Remove(modFilename);
                            }

                            // hot load the mod
                            if (modFilename.EndsWith(".zip"))
                            {
                                Everest.Loader.LoadZip(Path.Combine(Everest.Loader.PathMods, modFilename));
                            }
                            else
                            {
                                Everest.Loader.LoadDir(Path.Combine(Everest.Loader.PathMods, modFilename));
                            }
                        } catch (Exception e) {
                            // something bad happened during the mod hot loading, log it and prompt to restart the game to load the mod.
                            LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_UNBLACKLIST_FAILED"));
                            Logger.LogDetailed(e);
                            shouldAutoExit = false;
                            shouldRestart  = true;
                            break;
                        }
                    }
                }

                // display all mods that couldn't be accounted for
                if (shouldUpdateEverestManually)
                {
                    LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_MUST_UPDATE_EVEREST"));
                }

                foreach (string mod in modsNotFound)
                {
                    LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_NOT_FOUND"), mod));
                }

                foreach (string mod in modsNotInstallableAutomatically)
                {
                    LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_NOT_AUTO_INSTALLABLE"), mod));
                }

                foreach (string mod in modsWithIncompatibleVersionInDatabase.Keys)
                {
                    LogLine(string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_MOD_WRONG_VERSION"), mod,
                                          string.Join(", ", modsWithIncompatibleVersionInDatabase[mod]), modsDatabaseVersions[mod]));
                }
            }

            Progress    = 1;
            ProgressMax = 1;

            if (shouldAutoExit)
            {
                // there are no errors to display: restart automatically
                if (shouldRestart)
                {
                    LogLine(Dialog.Clean("DEPENDENCYDOWNLOADER_RESTARTING"));
                    for (int i = 3; i > 0; --i)
                    {
                        Lines[Lines.Count - 1] = string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_RESTARTING_IN"), i);
                        Thread.Sleep(1000);
                    }
                    Lines[Lines.Count - 1] = Dialog.Clean("DEPENDENCYDOWNLOADER_RESTARTING");

                    Everest.QuickFullRestart();
                }
                else
                {
                    Exit();
                }
            }
            else if (everestVersionToInstall != null)
            {
                LogLine("\n" + string.Format(Dialog.Get("DEPENDENCYDOWNLOADER_EVEREST_UPDATE"), everestVersionToInstall.Build));
                this.everestVersionToInstall = everestVersionToInstall;
            }
            else if (shouldRestart)
            {
                LogLine("\n" + Dialog.Clean("DEPENDENCYDOWNLOADER_PRESS_BACK_TO_RESTART"));
            }
            else
            {
                LogLine("\n" + Dialog.Clean("DEPENDENCYDOWNLOADER_PRESS_BACK_TO_GO_BACK"));
            }
        }