public async Task <int> UninstallMultipleMods(List <InstalledMod> mods, bool skipPreventRemoveCheck = true, IProgress <ProgressReport> progress = null)
        {
            if (mods.Count == 0)
            {
                return(0);
            }

            int uninstalledCount = 0;

            mods = mods.OrderBy((e) => e.usedBy.Count).ToList();

            progress?.Report(new ProgressReport($"Uninstalling { mods.Count } mods...", 0f));

            for (int i = 0; i < mods.Count; i++)
            {
                InstalledMod m = mods[i];

                if (await UninstallMod(m, skipPreventRemoveCheck, ProgressReport.Partial(progress, i * (1f / mods.Count), 1f / mods.Count)))
                {
                    uninstalledCount++;
                }
            }

            progress?.Report(new ProgressReport($"{ mods.Count } of { uninstalledCount } mods were uninstalled successfully.", 0f));

            return(uninstalledCount);
        }
        public Task <bool> UninstallMod(InstalledMod mod, bool skipPreventRemoveCheck = false, IProgress <ProgressReport> progess = null)
        {
            return(Task.Run(() =>
            {
                progess?.Report(new ProgressReport($"Preparing to uninstall { mod } ...", 0.1f));

                if (!skipPreventRemoveCheck && mod.usedBy.Count > 0)
                {
                    progess?.Report(new ProgressReport($"Could not uninstall mod: other mods are depending on it.", 1f));
                    return false;
                }

                if (!skipPreventRemoveCheck && mod.preventRemoval)
                {
                    progess?.Report(new ProgressReport($"Could not uninstall mod: the removal of this mod was prevented.", 1f));
                    return false;
                }

                for (int f = 0; f < mod.affectedFiles.Count; f++)
                {
                    string file = Path.Combine(BeatSaberDirectory, mod.affectedFiles[f]);

                    progess?.Report(new ProgressReport($"Removing { mod.Name } ... { file }", (float)(f + 1) / mod.affectedFiles.Count * 0.9f));

                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }

                    DirectoryExtensions.DeleteEmptyParentDirectories(Path.GetDirectoryName(file));
                }

                foreach (string uses in mod.uses)
                {
                    InstalledMod usesMod = GetInstalledMod(uses);

                    usesMod?.usedBy.Remove(mod.Name);
                }

                progess?.Report(new ProgressReport($"Mod { mod.ToString() } was uninstalled successfully.", 1f));

                InstalledMods.Remove(mod);
                SaveConfig();

                return true;
            }));
        }
        public Task <InstalledMod> UpdateMod(InstalledMod currentModVersion, Mod newModVersion, IProgress <ProgressReport> progress = null)
        {
            return(Task.Run(async() =>
            {
                if (currentModVersion >= newModVersion)
                {
                    progress?.Report(new ProgressReport($"Update skipped: a newer or equal version was already installed.", 1f));

                    return currentModVersion;
                }

                progress?.Report(new ProgressReport($"Removing old version: { currentModVersion.Version } ...", 0.1f));

                if (await UninstallMod(currentModVersion, true, ProgressReport.Partial(progress, 0.1f, 0.4f)))
                {
                    InstalledMod newInstalledVersion = await InstallMod(newModVersion, ProgressReport.Partial(progress, 0.5f, 0.5f));

                    if (newInstalledVersion != null)
                    {
                        newInstalledVersion.usedBy = currentModVersion.usedBy;
                        newInstalledVersion.uses = currentModVersion.uses;
                        newInstalledVersion.preventRemoval = currentModVersion.preventRemoval;

                        progress?.Report(new ProgressReport($"Update succeeded: { currentModVersion } -> { newModVersion }", 1f));
                        return newInstalledVersion;
                    }
                    else
                    {
                        progress?.Report(new ProgressReport($"Update failed: Could not install new version.", 1f));
                        return null;
                    }
                }
                else
                {
                    progress?.Report(new ProgressReport($"Update failed: Could not remove old version.", 1f));
                    return null;
                }
            }));
        }
        public async Task UninstallAllMods(bool showIPAConsole = false, IProgress <ProgressReport> progress = null)
        {
            progress?.Report(new ProgressReport("Unpatching...", 0.1f));

            await RunIPA(revert : true, wait : showIPAConsole, shown : showIPAConsole);

            List <InstalledMod> toRemove = config.installedMods.OrderBy((e) => e.usedBy.Count).ToList();

            for (int m = 0; m < toRemove.Count; m++)
            {
                InstalledMod mod = toRemove[m];

                progress?.Report(new ProgressReport($"Removing { mod }...", 0.25f + (float)(m + 1) / toRemove.Count * 0.7f));

                await UninstallMod(mod, true);
            }

            config.installedMods.Clear();
            SaveConfig();

            progress?.Report(new ProgressReport($"Done removing { toRemove.Count } mods.", 1f));
        }
Example #5
0
 public Mod GetModFromLocal(InstalledMod mod)
 {
     return(AllMods.FirstOrDefault((e) => e.Version == mod.Version && string.Compare(e.Name, mod.Name, StringComparison.OrdinalIgnoreCase) == 0));
 }
        /*public Task<bool> DownloadMod(Mod mod, string archiveDestination, IProgress<ProgressReport> progress = null)
         * {
         * }*/

        public Task <InstalledMod> InstallMod(Mod mod, IProgress <ProgressReport> progress = null)
        {
            return(Task.Run(async() =>
            {
                progress?.Report(new ProgressReport($"Starting to install { mod } ...", 0.1f));

                if (!mod.IsInformationKnown)
                {
                    mod = beatMods.GetModFromId(mod.Id);
                    if (mod == null)
                    {
                        progress?.Report(new ProgressReport($"Install failed: mod with id { mod.Id } could not be found.", 1f));
                        return null;
                    }
                }

                if (IsInstalledAnyVersion(mod))
                {
                    progress?.Report(new ProgressReport($"Install skipped: another version of this mod was already installed.", 1f));
                    return GetInstalledModIgnoreVersion(mod);
                }

                // Every mod should require BSIPA
                if (string.Compare(mod.Name, Mod.BSIPA, StringComparison.OrdinalIgnoreCase) != 0 &&
                    !mod.dependencies.Any((e) => string.Compare(e.Name, Mod.BSIPA, StringComparison.OrdinalIgnoreCase) == 0))
                {
                    Mod bsipa = beatMods.GetMostRecentModWithName(Mod.BSIPA, BeatSaberVersion);

                    if (bsipa == null)
                    {
                        progress?.Report(new ProgressReport($"Install failed: BSIPA (required) could not be found as a dependency.", 1f));
                        return null;
                    }

                    mod.dependencies.Add(bsipa);
                }

                Mod.Download md = mod.GetBestDownloadFor(config.beatSaberType);

                if (string.IsNullOrEmpty(md.DownloadUrl))
                {
                    progress?.Report(new ProgressReport($"Install failed: there was no compatible plugin file available for { config.beatSaberType }", 1f));
                    return null;
                }

                string zipDownloadLocation = Path.Combine(ModArchivesDownloadLocation, mod.GetArchiveName());
                new FileInfo(zipDownloadLocation).Directory.Create();

                DownloadZip:
                if (!File.Exists(zipDownloadLocation))
                {
                    if (beatMods.IsOffline)
                    {
                        progress?.Report(new ProgressReport($"Install failed: mod { mod } is not offline available.", 1f));
                        return null;
                    }

                    using (WebClient wc = new WebClient())
                    {
                        wc.DownloadProgressChanged += (sender, e) =>
                                                      progress?.Report(new ProgressReport($"Downloading { mod } ...", 0.1f + e.ProgressPercentage / 100f * 0.3f));

                        await wc.DownloadFileTaskAsync(md.DownloadUrl, zipDownloadLocation);
                    }
                }

                InstalledMod localMod = new InstalledMod(mod, BeatSaberType);

                try
                {
                    using (FileStream fs = new FileStream(zipDownloadLocation, FileMode.Open))
                        using (ZipArchive archive = new ZipArchive(fs))
                        {
                            Progress <float> extractProgress = new Progress <float>((i) =>
                                                                                    progress?.Report(new ProgressReport($"Extracting { mod.ToString() } ...", 0.4f + i * 0.3f)));

                            localMod.affectedFiles = archive.ExtractToDirectory(BeatSaberDirectory, true, false, extractProgress);
                        }
                }
                catch (InvalidDataException)
                {
                    File.Delete(zipDownloadLocation);

                    goto DownloadZip;
                }

                for (int d = 0; d < mod.dependencies.Count; d++)
                {
                    Mod dependency = mod.dependencies[d];
                    if (dependency.IsInformationKnown) // Install the most recent that is compatible with the game's version
                    {
                        Mod mostRecentCompatible = beatMods.GetMostRecentModWithName(dependency.Name, BeatSaberVersion);

                        if (mostRecentCompatible != null)
                        {
                            dependency = mostRecentCompatible;
                        }
                    }

                    progress?.Report(new ProgressReport($"Installing dependencies: { dependency.ToString() } ...", 0.7f + (float)(d + 1) / mod.dependencies.Count * 0.3f));

                    InstalledMod installedDependency = await InstallMod(dependency);

                    if (!localMod.uses.Contains(installedDependency.Name))
                    {
                        localMod.uses.Add(installedDependency.Name);
                    }

                    if (installedDependency != null)
                    {
                        if (!installedDependency.usedBy.Contains(localMod.Name))
                        {
                            installedDependency.usedBy.Add(localMod.Name);
                        }
                    }
                    else
                    {
                        progress?.Report(new ProgressReport($"Could not install dependency: { dependency.ToString() }, skipped.", 0.7f + (float)(d + 1) / mod.dependencies.Count * 0.3f));
                    }
                }

                if (RemoveModArchivesAfterInstall)
                {
                    progress?.Report(new ProgressReport($"Removing archive...", 0.95f));

                    File.Delete(zipDownloadLocation);
                }
                else
                {
                    if (!beatMods.OfflineMods.Contains(mod))
                    {
                        beatMods.OfflineMods.Add(mod);
                    }
                }

                if (string.Compare(mod.Name, Mod.BSIPA, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    progress?.Report(new ProgressReport($"Patching Beat Saber...", 1f));

                    await RunIPA();
                }

                progress?.Report(new ProgressReport($"Mod { mod.ToString() } was installed successfully.", 1f));

                InstalledMods.Add(localMod);
                SaveConfig();

                return localMod;
            }));
        }