Example #1
0
        static void Main(string[] args)
        {
            var arguments = new Arguments(args);
            Log.AddChannel("debug", "dedicated-debug.log");
            Log.AddChannel("perf", "dedicated-perf.log");
            Log.AddChannel("server", "dedicated-server.log");
            Log.AddChannel("nat", "dedicated-nat.log");

            // Special case handling of Game.Mod argument: if it matches a real filesystem path
            // then we use this to override the mod search path, and replace it with the mod id
            var modArgument = arguments.GetValue("Game.Mod", null);
            string customModPath = null;
            if (modArgument != null && (File.Exists(modArgument) || Directory.Exists(modArgument)))
            {
                customModPath = modArgument;
                arguments.ReplaceValue("Game.Mod", Path.GetFileNameWithoutExtension(modArgument));
            }

            // HACK: The engine code assumes that Game.Settings is set.
            // This isn't nearly as bad as ModData, but is still not very nice.
            Game.InitializeSettings(arguments);
            var settings = Game.Settings.Server;

            var mod = Game.Settings.Game.Mod;
            var mods = new InstalledMods(customModPath);

            // HACK: The engine code *still* assumes that Game.ModData is set
            var modData = Game.ModData = new ModData(mods[mod], mods);
            modData.MapCache.LoadMaps();

            settings.Map = modData.MapCache.ChooseInitialMap(settings.Map, new MersenneTwister());

            Console.WriteLine("[{0}] Starting dedicated server for mod: {1}", DateTime.Now.ToString(settings.TimestampFormat), mod);
            while (true)
            {
                var server = new Server(new IPEndPoint(IPAddress.Any, settings.ListenPort), settings, modData, true);

                while (true)
                {
                    Thread.Sleep(1000);
                    if (server.State == ServerState.GameStarted && server.Conns.Count < 1)
                    {
                        Console.WriteLine("[{0}] No one is playing, shutting down...", DateTime.Now.ToString(settings.TimestampFormat));
                        server.Shutdown();
                        break;
                    }
                }

                Console.WriteLine("[{0}] Starting a new server instance...", DateTime.Now.ToString(settings.TimestampFormat));
            }
        }
Example #2
0
        /// <summary>
        /// Installs a mod into the game.
        /// </summary>
        public async Task <bool> Install(Mod m)
        {
            string mPath       = Mod.InstallPath + m.Slug;
            string mBackupPath = Mod.BackupPath + m.Slug;

            if (!Directory.Exists(mBackupPath))
            {
                Directory.CreateDirectory(mBackupPath);
            }
            Console.WriteLine("Install Mod");
            // Before installing get the list of affected ice files and make sure no installed
            // mod uses the same files
            if (!ModCollision(m))
            {
                m.ContentsMD5 = new Dictionary <string, string>();
                foreach (var f in Directory.GetFiles(mPath))
                {
                    var    fileName = Path.GetFileName(f);
                    string from     = mPath + "\\" + fileName;
                    string destin   = settings.PSO2Dir + "\\" + fileName;
                    string backup   = mBackupPath + "\\" + fileName;

                    if (!File.Exists(from))
                    {
                        MessageBox.Show("Mod file(s) are not found. please reinstall mod.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        return(false);
                    }
                    if (!File.Exists(destin))
                    {
                        // backup target no match
                        continue;
                    }
                    //Console.WriteLine ("Backup FROM: " + settings.PSO2Dir + "\\" + fileName + "  TO: " + mBackupPath + "\\" + fileName);
                    //Console.WriteLine ("Replace FROM: " + mPath + "\\" + fileName + "  TO: " + settings.PSO2Dir + "\\" + fileName);

                    if (!Mod.modSettingsFiles.Contains(fileName))
                    {
                        var BackupTask   = new Helpers.FileCopy(destin, backup);
                        var ApplyModTask = new Helpers.FileCopy(from, destin);

                        // This is done here because some mods will have dynamic/setup content so we create
                        // the md5 hash over the file we copy on the pso2 dir
                        m.ContentsMD5.Add(fileName, Helpers.CheckMD5(destin));

                        Console.WriteLine("Backup Task");
                        await Task.Run(() => BackupTask.StartCopy());

                        Console.WriteLine("Apply Mod Task");
                        await Task.Run(() => ApplyModTask.StartCopy());
                    }
                }
                InstalledMods.Add(m);
                AvailableMods.Remove(m);
                UpdateSettings();
            }
            else
            {
                MessageBox.Show("Another installed mod is using the same files this mod will try to overwrite. Installation cancelled",
                                "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return(false);
            }
            return(true);
        }
Example #3
0
 /// <summary>
 /// Saves the settings file.
 /// </summary>
 private void UpdateSettings()
 {
     settings.AvailableMods = AvailableMods.ToList();
     settings.InstalledMods = InstalledMods.ToList();
     File.WriteAllText(Settings.SettingsPath, JsonSerializer.SerializeToString(settings));
 }
Example #4
0
 /// <summary>
 /// Returns true if the mod is installed
 /// </summary>
 public bool IsInstalled(Mod m)
 {
     return(InstalledMods.Contains(m));
 }
Example #5
0
        private async Task DownloadSelectedModRelease()
        {
            string token;

            if (GlobalCredentials.Instance.LogIn(Window, out token))
            {
                var progressWindow = new ProgressWindow {
                    Owner = Window
                };
                var progressViewModel = (ProgressViewModel)progressWindow.ViewModel;
                progressViewModel.ActionName          = App.Instance.GetLocalizedResourceString("DownloadingAction");
                progressViewModel.ProgressDescription = string.Format(App.Instance.GetLocalizedResourceString("DownloadingDescription"), selectedRelease.FileName);

                progressViewModel.CanCancel = true;
                var cancellationSource = new CancellationTokenSource();
                progressViewModel.CancelRequested += (sender, e) => cancellationSource.Cancel();

                var progress = new Progress <double>(p => progressViewModel.Progress = p);

                Mod newMod;
                try
                {
                    Task closeWindowTask = null;
                    try
                    {
                        Task <Mod> downloadTask = ModWebsite.DownloadReleaseAsync(selectedRelease,
                                                                                  GlobalCredentials.Instance.Username, token,
                                                                                  progress, cancellationSource.Token, InstalledMods, MainViewModel.Instance.Modpacks);

                        closeWindowTask = downloadTask.ContinueWith(t => progressWindow.Dispatcher.Invoke(progressWindow.Close));
                        progressWindow.ShowDialog();

                        newMod = await downloadTask;
                    }
                    finally
                    {
                        if (closeWindowTask != null)
                        {
                            await closeWindowTask;
                        }
                    }
                }
                catch (HttpRequestException)
                {
                    MessageBox.Show(Window,
                                    App.Instance.GetLocalizedMessage("InternetConnection", MessageType.Error),
                                    App.Instance.GetLocalizedMessageTitle("InternetConnection", MessageType.Error),
                                    MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                if (!cancellationSource.IsCancellationRequested)
                {
                    if (newMod != null)
                    {
                        InstalledMods.Add(newMod);
                    }
                    UpdateSelectedReleases();
                }
            }
        }
Example #6
0
 public Utility(ModData modData, InstalledMods mods)
 {
     ModData = modData;
     Mods = mods;
 }
        /// <summary>
        ///     Backend input
        /// </summary>
        /// <param name="inputargs">Input</param>
        public static void doCommand(string[] inputargs)
        {
            switch (inputargs[0])
            {
            case "reload":
                JsonModList.GetModLists(true);
                break;

            case "wipe":
                File.Delete(Directory.GetCurrentDirectory() + @"\installedmods.json");
                Console.WriteLine("Wiped!");
                break;

            case "modlists":
                listmodlists();
                break;

            case "check":

                var ml = JsonModList.GetModLists();

                for (var i = 0; i < ml.Length; i++)
                {
                    for (var x = 0; x < ml[i].Modlist.Length; x++)
                    {
                        if (ml[i].Modlist[x].ModId == inputargs[1])
                        {
                            var link = ml[i].Modlist[x].Website;
                            var psi  = new ProcessStartInfo
                            {
                                FileName        = link,
                                UseShellExecute = true
                            };
                            Process.Start(psi);
                        }
                    }
                }

                break;

            case "dl":
                Downloader.DownloadModDirector(inputargs[1]);
                break;

            case "install":
                Downloader.DownloadModDirector(inputargs[1], true);
                break;

            case "list":
                if (inputargs[1] == "installedmods")
                {
                    var mf = InstalledMods.GetInstalledMods();
                    for (var i = 0; i < mf.Length; i++)
                    {
                        Console.WriteLine(mf[i].Name);
                    }
                }
                else
                {
                    list(inputargs[1]);
                }

                break;

            case "exit":
                return;

            case "help":
                Console.WriteLine("wipe - Wipes the installed registry (DOES NOT DELETE MODS)");
                Console.WriteLine("modlists - Lists all modlists, which are lists of mods.");
                Console.WriteLine("dl [modname] - Downloads mod listed.");
                Console.WriteLine("check [modname] - Opens browser to modpage.");
                Console.WriteLine("list [modlist] - Lists all mods contained in a modlist.");
                Console.WriteLine("list installedmods - Lists all mods registered as installed.");
                Console.WriteLine("exit - Close H3VRModInstaller.");
                break;

            case "toggledebugging":
                ModInstallerCommon.enableDebugging = !ModInstallerCommon.enableDebugging;
                Console.WriteLine("Debugging is now " + ModInstallerCommon.enableDebugging);
                break;

            //deletion
            case "rm":
                Console.WriteLine($"Deleting {inputargs[1]}");
                Uninstaller.DeleteMod(inputargs[1]);
                break;

            default:
                Console.WriteLine("Invalid command!");
                break;
            }
        }
Example #8
0
        static void Main(string[] args)
        {
            var arguments = new Arguments(args);

            var engineDirArg = arguments.GetValue("Engine.EngineDir", null);

            if (!string.IsNullOrEmpty(engineDirArg))
            {
                Platform.OverrideEngineDir(engineDirArg);
            }

            var supportDirArg = arguments.GetValue("Engine.SupportDir", null);

            if (!string.IsNullOrEmpty(supportDirArg))
            {
                Platform.OverrideSupportDir(supportDirArg);
            }

            Log.AddChannel("debug", "dedicated-debug.log", true);
            Log.AddChannel("perf", "dedicated-perf.log", true);
            Log.AddChannel("server", "dedicated-server.log", true);
            Log.AddChannel("nat", "dedicated-nat.log", true);
            Log.AddChannel("geoip", "dedicated-geoip.log", true);

            // Special case handling of Game.Mod argument: if it matches a real filesystem path
            // then we use this to override the mod search path, and replace it with the mod id
            var modID            = arguments.GetValue("Game.Mod", null);
            var explicitModPaths = new string[0];

            if (modID != null && (File.Exists(modID) || Directory.Exists(modID)))
            {
                explicitModPaths = new[] { modID };
                modID            = Path.GetFileNameWithoutExtension(modID);
            }

            if (modID == null)
            {
                throw new InvalidOperationException("Game.Mod argument missing or mod could not be found.");
            }

            // HACK: The engine code assumes that Game.Settings is set.
            // This isn't nearly as bad as ModData, but is still not very nice.
            Game.InitializeSettings(arguments);
            var settings = Game.Settings.Server;

            var envModSearchPaths = Environment.GetEnvironmentVariable("MOD_SEARCH_PATHS");
            var modSearchPaths    = !string.IsNullOrWhiteSpace(envModSearchPaths) ?
                                    FieldLoader.GetValue <string[]>("MOD_SEARCH_PATHS", envModSearchPaths) :
                                    new[] { Path.Combine(Platform.EngineDir, "mods") };

            var mods = new InstalledMods(modSearchPaths, explicitModPaths);

            Console.WriteLine("[{0}] Starting dedicated server for mod: {1}", DateTime.Now.ToString(settings.TimestampFormat), modID);
            while (true)
            {
                // HACK: The engine code *still* assumes that Game.ModData is set
                var modData = Game.ModData = new ModData(mods[modID], mods);
                modData.MapCache.LoadMaps();

                settings.Map = modData.MapCache.ChooseInitialMap(settings.Map, new MersenneTwister());

                var endpoints = new List <IPEndPoint> {
                    new IPEndPoint(IPAddress.IPv6Any, settings.ListenPort), new IPEndPoint(IPAddress.Any, settings.ListenPort)
                };
                var server = new Server(endpoints, settings, modData, ServerType.Dedicated);

                GC.Collect();
                while (true)
                {
                    Thread.Sleep(1000);
                    if (server.State == ServerState.GameStarted && server.Conns.Count < 1)
                    {
                        Console.WriteLine("[{0}] No one is playing, shutting down...", DateTime.Now.ToString(settings.TimestampFormat));
                        server.Shutdown();
                        break;
                    }
                }

                modData.Dispose();
                Console.WriteLine("[{0}] Starting a new server instance...", DateTime.Now.ToString(settings.TimestampFormat));
            }
        }
Example #9
0
        /// <summary>
        /// Called when [activated].
        /// </summary>
        /// <param name="disposables">The disposables.</param>
        protected override void OnActivated(CompositeDisposable disposables)
        {
            Task.Run(() => EvalResumeAvailabilityLoopAsync().ConfigureAwait(false));

            ShowAdvancedFeatures = (gameService.GetSelected()?.AdvancedFeaturesSupported).GetValueOrDefault();
            AnalyzeClass         = string.Empty;

            var allowModSelectionEnabled = this.WhenAnyValue(v => v.AllowModSelection);
            var applyEnabled             = Observable.Merge(this.WhenAnyValue(v => v.ApplyingCollection, v => !v), allowModSelectionEnabled);

            this.WhenAnyValue(v => v.CollectionMods.SelectedModCollection).Subscribe(s =>
            {
                if (s != null)
                {
                    AllowModSelection = true;
                    InstalledMods.AllowModSelection  = true;
                    CollectionMods.AllowModSelection = true;
                }
                else
                {
                    AllowModSelection = false;
                    InstalledMods.AllowModSelection  = false;
                    CollectionMods.AllowModSelection = false;
                }
                InstallModsAsync().ConfigureAwait(true);
            }).DisposeWith(disposables);

            this.WhenAnyValue(v => v.InstalledMods.Mods).Subscribe(v =>
            {
                CollectionMods.SetMods(v, InstalledMods.ActiveGame);
            });

            this.WhenAnyValue(v => v.InstalledMods.RefreshingMods).Subscribe(s =>
            {
                CollectionMods.HandleModRefresh(s, InstalledMods.Mods, InstalledMods.ActiveGame);
            }).DisposeWith(disposables);

            this.WhenAnyValue(v => v.CollectionMods.NeedsModListRefresh).Where(x => x).Subscribe(s =>
            {
                InstalledMods.RefreshMods();
            }).DisposeWith(disposables);

            this.WhenAnyValue(p => p.InstalledMods.PerformingEnableAll).Subscribe(s =>
            {
                CollectionMods.HandleEnableAllToggled(s, InstalledMods.AllModsEnabled, InstalledMods.FilteredMods);
            }).DisposeWith(disposables);

            ApplyCommand = ReactiveCommand.Create(() =>
            {
                ApplyCollectionAsync(idGenerator.GetNextId()).ConfigureAwait(true);
            }, applyEnabled).DisposeWith(disposables);

            AnalyzeCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                var game = gameService.GetSelected();
                if (game != null && CollectionMods.SelectedMods?.Count > 0 && CollectionMods.SelectedModCollection != null)
                {
                    var id = idGenerator.GetNextId();
                    await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.App.WaitBackgroundOperationMessage));
                    await shutDownState.WaitUntilFreeAsync();
                    modPatchCollectionService.ResetPatchStateCache();
                    var mode = await modPatchCollectionService.GetPatchStateModeAsync(CollectionMods.SelectedModCollection.Name);
                    if (mode == PatchStateMode.None)
                    {
                        await TriggerOverlayAsync(id, false);
                        await Task.Delay(50);
                        IsModeOpen = true;
                    }
                    else
                    {
                        await AnalyzeModsAsync(id, mode);
                    }
                }
            }, allowModSelectionEnabled).DisposeWith(disposables);

            async Task <bool> ensureSteamIsRunning(IGameSettings args)
            {
                if (gameService.IsSteamGame(args))
                {
                    // Check if process is running
                    var processes = Process.GetProcesses();
                    if (!processes.Any(p => p.ProcessName.Equals(SteamProcess, StringComparison.OrdinalIgnoreCase)))
                    {
                        await appAction.OpenAsync(SteamLaunch);

                        var attempts = 0;
                        while (!processes.Any(p => p.ProcessName.Equals(SteamProcess, StringComparison.OrdinalIgnoreCase)))
                        {
                            if (attempts > 3)
                            {
                                break;
                            }
                            await Task.Delay(3000);

                            processes = Process.GetProcesses();
                            attempts++;
                        }
                    }
                }
                return(true);
            }

            async Task launchGame(bool continueGame)
            {
                var game = gameService.GetSelected();

                if (game != null)
                {
                    var args = gameService.GetLaunchSettings(game, continueGame);
                    if (!string.IsNullOrWhiteSpace(args.ExecutableLocation))
                    {
                        var id = idGenerator.GetNextId();
                        await TriggerOverlayAsync(id, true, localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.Overlay));

                        if (game.RefreshDescriptors)
                        {
                            await modService.DeleteDescriptorsAsync(InstalledMods.Mods);

                            await modService.InstallModsAsync(InstalledMods.Mods);
                        }
                        await ApplyCollectionAsync(id, false);

                        await MessageBus.PublishAsync(new LaunchingGameEvent(game.Type));

                        if (gameService.IsSteamLaunchPath(args))
                        {
                            if (await appAction.OpenAsync(args.ExecutableLocation))
                            {
                                if (game.CloseAppAfterGameLaunch)
                                {
                                    await appAction.ExitAppAsync();
                                }
                            }
                            else
                            {
                                notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Title),
                                                                    localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Message), NotificationType.Error, 10);
                                await TriggerOverlayAsync(id, false);
                            }
                        }
                        else
                        {
                            await ensureSteamIsRunning(args);

                            if (await appAction.RunAsync(args.ExecutableLocation, args.LaunchArguments))
                            {
                                if (game.CloseAppAfterGameLaunch)
                                {
                                    await appAction.ExitAppAsync();
                                }
                                else
                                {
                                    await TriggerOverlayAsync(id, false);
                                }
                            }
                            else
                            {
                                notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Title),
                                                                    localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.LaunchError.Message), NotificationType.Error, 10);
                                await TriggerOverlayAsync(id, false);
                            }
                        }
                    }
                    else
                    {
                        notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.NotSet.Title),
                                                            localizationManager.GetResource(LocalizationResources.Mod_Actions.LaunchGame.NotSet.Message), NotificationType.Warning, 10);
                    }
                }
            }

            LaunchGameCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await launchGame(false);
            }, allowModSelectionEnabled).DisposeWith(disposables);

            ResumeGameCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await launchGame(true);
            }, allowModSelectionEnabled).DisposeWith(disposables);

            AdvancedModeCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await AnalyzeModsAsync(idGenerator.GetNextId(), PatchStateMode.Advanced);
            }).DisposeWith(disposables);

            DefaultModeCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                await AnalyzeModsAsync(idGenerator.GetNextId(), PatchStateMode.Default);
            }).DisposeWith(disposables);

            CloseModeCommand = ReactiveCommand.Create(() =>
            {
                ForceClosePopups();
            }).DisposeWith(disposables);

            var previousCollectionNotification = string.Empty;

            CollectionMods.ConflictSolverStateChanged += (collectionName, state) =>
            {
                AnalyzeClass = !state ? InvalidConflictSolverClass : string.Empty;
                if (!state && previousCollectionNotification != collectionName)
                {
                    notificationAction.ShowNotification(localizationManager.GetResource(LocalizationResources.Notifications.ConflictSolverUpdate.Title),
                                                        localizationManager.GetResource(LocalizationResources.Notifications.ConflictSolverUpdate.Message), NotificationType.Warning, 30);
                    previousCollectionNotification = collectionName;
                }
            };

            gameDirectoryChangedHandler.Message.Subscribe(s =>
            {
                InstalledMods.RefreshMods();
                EvalResumeAvailability(s.Game);
            }).DisposeWith(disposables);

            this.WhenAnyValue(v => v.InstalledMods.ModFilePopulationInCompleted).Subscribe(s =>
            {
                CollectionMods.CanExportModHashReport = s;
            }).DisposeWith(disposables);

            base.OnActivated(disposables);
        }
Example #10
0
        public void UpdateModList(string dispcat = "n/a")
        {
            DownloadableModsList.Items.Clear();
            InstalledModsList.Items.Clear();

            if (dispcat == "n/a")
            {
                dispcat = publicdispcat;
            }
            publicdispcat = dispcat;

            var totalmods = JsonCommon.GetAllMods();

            if (dispcat == "n/a")
            {
                dispcat = "dependencies";
            }

            Console.WriteLine(dispcat);

            var dispmods = JsonModList.GetDeserializedModListFormatOnline(dispcat).Modlist;

            var installedMods = InstalledMods.GetInstalledMods(); //f**k you

            ModFile[] list = null;

            var relevantint = 0;

            for (var i = 0; i < totalmods.Length; i++)
            {
                //this just checks if the mod we're working with is an installedmod, or a dl mod in isinstldmod
                var isinstldmod = false;
                var x           = 0;
                for (x = 0; x < installedMods.Length; x++)
                {
                    if (totalmods[i].ModId == installedMods[x].ModId)
                    {
                        isinstldmod = true;
                        break;
                    }
                }

                var isdispmod = false;
                for (var y = 0; y < dispmods.Length; y++)
                {
                    if (totalmods[i].ModId == dispmods[y].ModId)
                    {
                        isdispmod = true;
                        break;
                    }
                }

                //sets vars to installedmods or input
                if (isinstldmod)
                {
                    list        = installedMods;
                    relevantint = x;
                }
                else
                {
                    if (publicdispcat == "n/a")
                    {
                        goto Finish;
                    }
                    list        = totalmods;
                    relevantint = i;
                }


                var mod = new ListViewItem(list[relevantint].Name, 0);         //0
                mod.SubItems.Add(list[relevantint].Version);                   //1
                mod.SubItems.Add(string.Join(", ", list[relevantint].Author)); //2
                mod.SubItems.Add(list[relevantint].Description);               //3
                mod.SubItems.Add(list[relevantint].ModId);                     //4


                if (!isinstldmod && isdispmod)
                {
                    DownloadableModsList.Items.Add(mod);
                }
                if (isinstldmod)
                {
                    InstalledModsList.Items.Add(mod);
                }
                Finish :;
            }

            for (var i = 0; i < InstalledModsList.Items.Count; i++)
            {
                //if cached installed mod is a older version than the database
                if (new Version(InstalledModsList.Items[i].SubItems[1].Text).CompareTo(
                        new Version(ModParsing.GetSpecificMod(InstalledModsList.Items[i].SubItems[4].Text).Version)) < 0)
                {
                    InstalledModsList.Items[i].BackColor = Color.Yellow;
                }
            }
        }
Example #11
0
        private async Task UpdateSelectedModRelease()
        {
            string token;

            if (GlobalCredentials.Instance.LogIn(Window, out token))
            {
                ModRelease newestRelease = GetNewestRelease(ExtendedInfo, SelectedRelease);
                Mod        mod           = InstalledMods.FindByFactorioVersion(SelectedMod.Name, newestRelease.FactorioVersion);
                var        zippedMod     = mod as ZippedMod;
                var        extractedMod  = mod as ExtractedMod;

                var cancellationSource = new CancellationTokenSource();
                var progressWindow     = new ProgressWindow {
                    Owner = Window
                };
                var progressViewModel = (ProgressViewModel)progressWindow.ViewModel;
                progressViewModel.ActionName          = App.Instance.GetLocalizedResourceString("UpdatingAction");
                progressViewModel.ProgressDescription = string.Format(App.Instance.GetLocalizedResourceString("DownloadingDescription"), newestRelease.FileName);
                progressViewModel.CanCancel           = true;
                progressViewModel.CancelRequested    += (sender, e) => cancellationSource.Cancel();

                IProgress <double> progress = new Progress <double>(p =>
                {
                    if (p > 1)
                    {
                        progressViewModel.ProgressDescription = App.Instance.GetLocalizedResourceString("ExtractingDescription");
                        progressViewModel.IsIndeterminate     = true;
                        progressViewModel.CanCancel           = false;
                    }
                    else
                    {
                        progressViewModel.Progress = p;
                    }
                });

                try
                {
                    Task closeWindowTask = null;
                    try
                    {
                        Task downloadTask = ModWebsite.UpdateReleaseAsync(newestRelease, GlobalCredentials.Instance.Username, token, progress, cancellationSource.Token);

                        if (extractedMod != null)
                        {
                            downloadTask = downloadTask.ContinueWith(t =>
                            {
                                progress.Report(2);

                                FileInfo modFile           = ((Task <FileInfo>)t).Result;
                                DirectoryInfo modDirectory = App.Instance.Settings.GetModDirectory(newestRelease.FactorioVersion);
                                ZipFile.ExtractToDirectory(modFile.FullName, modDirectory.FullName);
                                modFile.Delete();

                                return(new DirectoryInfo(Path.Combine(modDirectory.FullName, modFile.NameWithoutExtension())));
                            }, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.NotOnCanceled);
                        }

                        closeWindowTask = downloadTask.ContinueWith(t => progressWindow.Dispatcher.Invoke(progressWindow.Close));
                        progressWindow.ShowDialog();

                        if (zippedMod != null)
                        {
                            FileInfo newModFile = await(Task <FileInfo>) downloadTask;
                            if (zippedMod.FactorioVersion == newestRelease.FactorioVersion)
                            {
                                zippedMod.Update(newModFile, newestRelease.Version);
                            }
                            else
                            {
                                var newMod = new ZippedMod(zippedMod.Name, newestRelease.Version, newestRelease.FactorioVersion, newModFile,
                                                           InstalledMods, MainViewModel.Instance.Modpacks);
                                InstalledMods.Add(newMod);
                                foreach (var modpack in MainViewModel.Instance.Modpacks)
                                {
                                    ModReference reference;
                                    if (modpack.Contains(zippedMod, out reference))
                                    {
                                        modpack.Mods.Remove(reference);
                                        modpack.Mods.Add(new ModReference(newMod, modpack));
                                    }
                                }
                                zippedMod.File.Delete();
                                InstalledMods.Remove(extractedMod);
                            }
                        }
                        if (extractedMod != null)
                        {
                            DirectoryInfo newModDirectory = await(Task <DirectoryInfo>) downloadTask;
                            if (extractedMod.FactorioVersion == newestRelease.FactorioVersion)
                            {
                                extractedMod.Update(newModDirectory, newestRelease.Version);
                            }
                            else
                            {
                                var newMod = new ExtractedMod(extractedMod.Name, newestRelease.Version, newestRelease.FactorioVersion, newModDirectory,
                                                              InstalledMods, MainViewModel.Instance.Modpacks);
                                InstalledMods.Add(newMod);
                                foreach (var modpack in MainViewModel.Instance.Modpacks)
                                {
                                    ModReference reference;
                                    if (modpack.Contains(extractedMod, out reference))
                                    {
                                        modpack.Mods.Remove(reference);
                                        modpack.Mods.Add(new ModReference(newMod, modpack));
                                    }
                                }
                                extractedMod.Directory.Delete(true);
                                InstalledMods.Remove(extractedMod);

                                ModpackTemplateList.Instance.Update(MainViewModel.Instance.Modpacks);
                                ModpackTemplateList.Instance.Save();
                            }
                        }
                    }
                    finally
                    {
                        if (closeWindowTask != null)
                        {
                            await closeWindowTask;
                        }
                    }
                }
                catch (HttpRequestException)
                {
                    MessageBox.Show(Window,
                                    App.Instance.GetLocalizedMessage("InternetConnection", MessageType.Error),
                                    App.Instance.GetLocalizedMessageTitle("InternetConnection", MessageType.Error),
                                    MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                SelectedRelease = null;
                foreach (var release in SelectedReleases)
                {
                    release.IsInstalled        = InstalledMods.Contains(selectedMod.Name, release.Version);
                    release.IsVersionInstalled = !release.IsInstalled && InstalledMods.ContainsByFactorioVersion(selectedMod.Name, release.FactorioVersion);
                }
            }
        }