Beispiel #1
0
        protected override async Task <bool> _Begin(CancellationToken cancel)
        {
            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            await Metrics.Send(Metrics.BeginInstall, ModList.Name);

            Utils.Log("Configuring Processor");

            FileExtractor2.FavorPerfOverRAM = FavorPerfOverRam;

            if (GameFolder == null)
            {
                GameFolder = Game.TryGetGameLocation();
            }

            if (GameFolder == null)
            {
                var otherGame = Game.CommonlyConfusedWith.Where(g => g.MetaData().IsInstalled).Select(g => g.MetaData()).FirstOrDefault();
                if (otherGame != null)
                {
                    await Utils.Log(new CriticalFailureIntervention(
                                        $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed, we did however find a installed " +
                                        $"copy of {otherGame.HumanFriendlyGameName}, did you install the wrong game?",
                                        $"Could not locate {Game.HumanFriendlyGameName}"))
                    .Task;
                }
                else
                {
                    await Utils.Log(new CriticalFailureIntervention(
                                        $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed",
                                        $"Could not locate {Game.HumanFriendlyGameName}"))
                    .Task;
                }

                Utils.Log("Exiting because we couldn't find the game folder.");
                return(false);
            }

            Utils.Log($"Install Folder: {OutputFolder}");
            Utils.Log($"Downloads Folder: {DownloadFolder}");
            Utils.Log($"Game Folder: {GameFolder.Value}");
            Utils.Log($"Wabbajack Folder: {AbsolutePath.EntryPoint}");


            var watcher = new DiskSpaceWatcher(cancel, new[] { OutputFolder, DownloadFolder, GameFolder.Value, AbsolutePath.EntryPoint }, (long)2 << 31,
                                               drive =>
                    {
                    Utils.Log($"Aborting due to low space on {drive.Name}");
                    Abort();
                });
            var watcherTask = watcher.Start();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Validating Game ESMs");
            await ValidateGameESMs();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Creating Output Folders");

            OutputFolder.CreateDirectory();
            DownloadFolder.CreateDirectory();

            if (OutputFolder.Combine(Consts.MO2ModFolderName).IsDirectory&& WarnOnOverwrite)
            {
                if ((await Utils.Log(new ConfirmUpdateOfExistingInstall {
                    ModListName = ModList.Name, OutputFolder = OutputFolder
                }).Task) == ConfirmUpdateOfExistingInstall.Choice.Abort)
                {
                    Utils.Log("Exiting installation at the request of the user, existing mods folder found.");
                    return(false);
                }
            }

            // Reduce to one thread if downloads on HDD, else use specified. Hashing on HDD has no benefit with more threads.
            if (new PhysicalDisk(DownloadFolder.DriveInfo().Name).MediaType == PhysicalDisk.MediaTypes.HDD && ReduceHDDThreads)
            {
                DesiredThreads.OnNext(1);
            }
            else
            {
                DesiredThreads.OnNext(DiskThreads);
            }

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Optimizing ModList");
            await OptimizeModlist();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Hashing Archives");
            await HashArchives();

            // Set to download thread count.
            DesiredThreads.OnNext(DownloadThreads);

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Downloading Missing Archives");
            await DownloadArchives();

            // Reduce to one thread if downloads on HDD, else use specified. Hashing on HDD has no benefit with more threads.
            if (new PhysicalDisk(DownloadFolder.DriveInfo().Name).MediaType == PhysicalDisk.MediaTypes.HDD && ReduceHDDThreads)
            {
                DesiredThreads.OnNext(1);
            }
            else
            {
                DesiredThreads.OnNext(DiskThreads);
            }

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Hashing Remaining Archives");
            await HashArchives();

            var missing = ModList.Archives.Where(a => !HashedArchives.ContainsKey(a.Hash)).ToList();

            if (missing.Count > 0)
            {
                foreach (var a in missing)
                {
                    Info($"Unable to download {a.Name} ({a.State.PrimaryKeyString})");
                }
                if (IgnoreMissingFiles)
                {
                    Info("Missing some archives, but continuing anyways at the request of the user");
                }
                else
                {
                    Error("Cannot continue, was unable to download one or more archives");
                }
            }

            // Reduce to two threads if output on HDD, else use specified. Installing files seems to have a slight benefit with two threads.
            if (new PhysicalDisk(OutputFolder.DriveInfo().Name).MediaType == PhysicalDisk.MediaTypes.HDD && ReduceHDDThreads)
            {
                DesiredThreads.OnNext(2);
            }
            else
            {
                DesiredThreads.OnNext(DiskThreads);
            }

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Extracting Modlist contents");
            await ExtractModlist();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Priming VFS");
            await PrimeVFS();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Building Folder Structure");
            BuildFolderStructure();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Installing Archives");
            await InstallArchives();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Installing Included files");
            await InstallIncludedFiles();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Installing Archive Metas");
            await InstallIncludedDownloadMetas();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Building BSAs");
            await BuildBSAs();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Generating Merges");
            await zEditIntegration.GenerateMerges(this);

            UpdateTracker.NextStep("Set MO2 into portable");
            await ForcePortable();

            UpdateTracker.NextStep("Create Empty Output Mods");
            CreateOutputMods();

            UpdateTracker.NextStep("Updating System-specific ini settings");
            SetScreenSizeInPrefs();

            UpdateTracker.NextStep("Compacting files");
            await CompactFiles();

            UpdateTracker.NextStep("Installation complete! You may exit the program.");
            await ExtractedModlistFolder !.DisposeAsync();
            await Metrics.Send(Metrics.FinishInstall, ModList.Name);

            return(true);
        }