示例#1
0
        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();
                }
            }
        }