private async Task <bool> CheckGameFiles(UpdateMethod method) { _gameTabController.ChangeTab(FileCheckTabItem); await PullManagementData(); _checkCancelSource = new CancellationTokenSource(); _isCheckPaused = false; CompletedCheckDownloadActionsLabel.Content = string.Empty; CompletedCheckActionsLabel.Content = string.Empty; CurrentCheckActionLabel.Content = string.Empty; CurrentCheckDownloadActionLabel.Content = string.Empty; CurrentCheckSizeActionLabel.Content = string.Empty; PauseCheckButton.Content = Text.Pause; CheckDownloadProgressbar.Value = 0; CheckProgressbar.Value = 0; var numberDownloaded = 0; var numberToDownload = 0; var fileOperations = new List <Task>(); long totalBytesToDownload = 0; long totalBytesDownloaded = 0; long lastBytesDownloaded = 0; using (var manager = new DownloadManager()) { async Task pause() { var taskSource = new TaskCompletionSource <object>(); void unpause(object s, RoutedEventArgs e) => taskSource.TrySetResult(null); void cancel(object s, RoutedEventArgs e) => taskSource.TrySetCanceled(); try { PauseCheckButton.Click += unpause; CancelCheckButton.Click += cancel; manager.PauseDownloads(taskSource.Task); await taskSource.Task; } finally { PauseCheckButton.Click -= unpause; CancelCheckButton.Click -= cancel; } } try { await Task.Run(() => { CreateDirectoryIfNoneExists(GameConfigFolder); CreateDirectoryIfNoneExists(DataFolder); }); string precedePath = Path.Combine(PrecedeFolder, "data", "win32"); if (File.Exists(PrecedeTxtPath) && Directory.Exists(precedePath)) { if (!ManagementData.ContainsKey("PrecedeVersion") || !ManagementData.ContainsKey("PrecedeCurrent")) { MessageDialogResult result = await this.ShowMessageAsync(Text.ApplyPrecede, Text.ApplyPrecedeNow, AffirmNeg, YesNo); if (result == MessageDialogResult.Affirmative) { // TODO: not this CancelCheckButton.IsEnabled = false; PauseCheckButton.IsEnabled = false; string[] files = await Task.Run(() => Directory.GetFiles(precedePath)); CheckProgressbar.Maximum = files.Length; foreach (string file in files) { CurrentCheckActionLabel.Content = Path.GetFileName(file); try { await Task.Run(() => MoveAndOverwriteFile(file, Path.Combine(DataFolder, Path.GetFileName(file ?? string.Empty)))); } catch (Exception) { // ignored } CompletedCheckActionsLabel.Content = Text.ApplyingPrecede.Format(++CheckProgressbar.Value, CheckProgressbar.Maximum); } try { await Task.Run(() => Directory.Delete(PrecedeFolder, true)); } catch (Exception) { await this.ShowMessageAsync(Text.Error, Text.PrecedeDeleteFailed); } // TODO: not this CancelCheckButton.IsEnabled = true; PauseCheckButton.IsEnabled = true; method = UpdateMethod.FileCheck; } } } var masterUrl = new Uri(ManagementData["MasterURL"]); var patchUrl = new Uri(ManagementData["PatchURL"]); string launcherList = await manager.DownloadStringTaskAsync(new Uri(patchUrl, "launcherlist.txt")); string patchList = await manager.DownloadStringTaskAsync(new Uri(patchUrl, "patchlist.txt")); string listAlways = await manager.DownloadStringTaskAsync(new Uri(patchUrl, "patchlist_always.txt")); PatchListEntry[] launcherListData = ParsePatchList(launcherList).ToArray(); PatchListEntry[] patchListData = ParsePatchList(patchList).ToArray(); PatchListEntry[] patchListAlways = ParsePatchList(listAlways).ToArray(); await RestoreAllPatchBackups(); if (method == UpdateMethod.Update && Directory.Exists(GameConfigFolder)) { var entryComparer = new PatchListEntryComparer(); if (File.Exists(LauncherListPath)) { IEnumerable <PatchListEntry> storedLauncherlist = await Task.Run(() => ParsePatchList(File.ReadAllText(LauncherListPath))); launcherListData = launcherListData.Except(storedLauncherlist, entryComparer).ToArray(); } if (File.Exists(PatchListPath)) { IEnumerable <PatchListEntry> storedNewlist = await Task.Run(() => ParsePatchList(File.ReadAllText(PatchListPath))); patchListData = patchListData.Except(storedNewlist, entryComparer).ToArray(); } if (File.Exists(PatchListAlwaysPath)) { IEnumerable <PatchListEntry> storedAlwaysList = await Task.Run(() => ParsePatchList(File.ReadAllText(PatchListAlwaysPath))); patchListAlways = patchListAlways.Except(storedAlwaysList, entryComparer).ToArray(); } } PatchListEntry[] lists = launcherListData.Concat(patchListData.Concat(patchListAlways)).ToArray(); PatchListEntry[] groups = (from v in lists group v by v.Name into d select d.First()).ToArray(); CheckProgressbar.Maximum = groups.Length; void setTopLabel() { CompletedCheckDownloadActionsLabel.Content = Text.DownloadedOf .Format(numberDownloaded, numberToDownload, SizeSuffix(totalBytesDownloaded), SizeSuffix(totalBytesToDownload)); } manager.DownloadStarted += (s, e) => { CurrentCheckDownloadActionLabel.Dispatcher.InvokeAsync(() => { lastBytesDownloaded = 0; CheckDownloadProgressbar.Maximum = 100; CurrentCheckDownloadActionLabel.Content = Path.GetFileNameWithoutExtension(e); }); }; manager.DownloadProgressChanged += (s, e) => { CheckDownloadProgressbar.Dispatcher.InvokeAsync(() => { CheckDownloadProgressbar.Value = e.ProgressPercentage; totalBytesDownloaded += e.BytesReceived - lastBytesDownloaded; lastBytesDownloaded = e.BytesReceived; setTopLabel(); CurrentCheckSizeActionLabel.Content = $"{SizeSuffix(e.BytesReceived)}/{SizeSuffix(e.TotalBytesToReceive)}"; }); }; manager.DownloadCompleted += (s, e) => { CheckDownloadProgressbar.Dispatcher.InvokeAsync(() => { numberDownloaded++; setTopLabel(); }); }; for (var index = 0; index < groups.Length;) { _checkCancelSource.Token.ThrowIfCancellationRequested(); if (_isCheckPaused) { PauseCheckButton.Content = Text.Resume; await pause(); PauseCheckButton.Content = Text.Pause; } else { PatchListEntry data = groups[index]; CurrentCheckActionLabel.Content = Path.GetFileNameWithoutExtension(data.Name); string filePath = MakeLocalToGame(Path.ChangeExtension(data.Name, null)); bool upToDate = await Task.Run(() => IsFileUpToDate(filePath, data.Size, data.Hash)); CheckProgressbar.Value = ++index; CompletedCheckActionsLabel.Content = Text.CheckedOf.Format(index, groups.Length); if (upToDate) { continue; } string patPath = MakeLocalToGame(data.Name); Directory.CreateDirectory(Path.GetDirectoryName(patPath)); void pat(Task t) => MoveAndOverwriteFile(patPath, filePath); Uri uri; switch (data.Source) { case PatchListSource.None: if (patchListData.Contains(data) || launcherListData.Contains(data)) { goto case PatchListSource.Patch; } goto case PatchListSource.Master; case PatchListSource.Master: uri = masterUrl; break; case PatchListSource.Patch: uri = patchUrl; break; default: throw new ArgumentOutOfRangeException(); } fileOperations.Add(manager.DownloadFileTaskAsync(new Uri(uri, data.Name), patPath).ContinueWith(pat)); numberToDownload++; totalBytesToDownload += data.Size; setTopLabel(); } } numberToDownload++; fileOperations.Add(manager.DownloadFileTaskAsync(new Uri(patchUrl, "version.ver"), VersionPath)); var downloads = Task.WhenAll(fileOperations); while (!downloads.IsCompleted && !downloads.IsCanceled && !downloads.IsFaulted) { _checkCancelSource.Token.ThrowIfCancellationRequested(); if (_isCheckPaused) { await pause(); } else { await Task.Delay(16); } } await downloads; await Task.Run(() => { File.WriteAllText(LauncherListPath, launcherList); File.WriteAllText(PatchListPath, patchList); File.WriteAllText(PatchListAlwaysPath, listAlways); if (File.Exists(VersionPath)) { SetTweakerRemoteVersion(File.ReadAllText(VersionPath)); } }); } catch when(_checkCancelSource.IsCancellationRequested) { manager.CancelDownloads(); _gameTabController.PreviousTab(); return(false); } } if (GameTabItem.IsSelected) { FlashWindow(this, true); if (numberDownloaded > 4) { await this.ShowMessageAsync(Text.Updated, Text.FilesDownloaded.Format(numberDownloaded - 4)); } else { await this.ShowMessageAsync(Text.Complete, Text.AllFilesValid); } } _gameTabController.PreviousTab(); return(true); }
private async Task DownloadPrecede() { using (var manager = new DownloadManager()) { try { var fileOperations = new List <Task>(); if (ManagementData.ContainsKey("PrecedeVersion") && ManagementData.ContainsKey("PrecedeCurrent")) { CreateDirectoryIfNoneExists(Path.Combine(PrecedeFolder, "data", "win32")); var listdatas = new PatchListEntry[int.Parse(ManagementData["PrecedeCurrent"]) + 1][]; for (var index = 0; index < listdatas.Length; index++) { var filename = $"patchlist{index}.txt"; var data = await manager.DownloadStringTaskAsync(new Uri(BasePrecede, filename)); listdatas[index] = ParsePatchList(data).ToArray(); await Task.Run(() => File.WriteAllText(Path.Combine(PrecedeFolder, filename), data)); } manager.DownloadProgressChanged += DownloadProgressChanged; manager.DownloadCompleted += DownloadCompleted; var groups = (from v in listdatas.SelectMany(x => x) group v by v.Name into d select d.First()).ToArray(); var precedePath = PrecedeFolder; _totalBytes = groups.Select(x => x.Size).Sum(); DownloadProgress.Maximum = _totalBytes; ScanProgress.Maximum = groups.Length; Func <Task> pause = async() => { var taskSource = new TaskCompletionSource <object>(); RoutedEventHandler unpause = (s, e) => taskSource.TrySetResult(null); RoutedEventHandler cancel = (s, e) => taskSource.TrySetCanceled(); try { ButtonPause.Click += unpause; ButtonCancel.Click += cancel; manager.PauseDownloads(taskSource.Task); await taskSource.Task; } finally { ButtonPause.Click -= unpause; ButtonCancel.Click -= cancel; } }; for (var index = 0; index < groups.Length;) { _checkCancelSource.Token.ThrowIfCancellationRequested(); if (_isPaused) { await pause(); } else { var data = groups[index]; var name = Path.ChangeExtension(data.Name, null); var filePath = Path.Combine(precedePath, name); ScanProgressLabel.Content = name; var upToDate = await Task.Run(() => IsFileUpToDate(File.Exists(filePath) ? filePath : MakeLocalToGame(name), data.Size, data.Hash)); ScanProgress.Value = ++index; ScanLabel.Content = string.Format(Text.CheckedOf, index, groups.Length); if (upToDate) { _totalBytes -= data.Size; DownloadProgress.Maximum = _totalBytes; } else { _numberToDownload++; var patPath = Path.Combine(precedePath, data.Name); fileOperations.Add(manager.DownloadFileTaskAsync(new Uri(BasePrecede, data.Name), patPath).ContinueWith(x => { lock (this) { _doneBytes += data.Size; } MoveAndOverwriteFile(patPath, filePath); })); DownloadLabel.Content = string.Format(Text.DownloadedOf, _numberDownloaded, _numberToDownload); } } } var downloads = Task.WhenAll(fileOperations); while (!downloads.IsCompleted && !downloads.IsCanceled && !downloads.IsFaulted) { _checkCancelSource.Token.ThrowIfCancellationRequested(); if (_isPaused) { await pause(); } else { await Task.Delay(16); } } await downloads; } await Task.Run(() => File.WriteAllText(PrecedeTxtPath, $"{ManagementData["PrecedeVersion"]}\t{ManagementData["PrecedeCurrent"]}")); } catch when(_checkCancelSource.IsCancellationRequested) { manager.CancelDownloads(); } } }