private async Task PatchKrabbyQuest(bool partial)
        {
            string path = null;

            Dispatcher.Invoke(delegate
            {
                path = Path.Combine(WorkspaceDir.Text);
            });
            if (path == null)
            {
                return;
            }
            GamePatcher patcher = new GamePatcher(path)
            {
                ProgressChanged = (object s, (string m, double p)e) =>
                                  InstallationInformationChanged(new InstallationCompletionInfo()
                {
                    StepName        = "Patching",
                    CurrentTask     = e.m,
                    PercentComplete = e.p
                }),
            };

            if (partial)
            {
                isPartialInstall = true;
                partialTitle     = "Game Update";
            }
            if (Installation == null)
            {
                if (!partial)
                {
                    partial = true;
                }
                Installation = new AutoInstall()
                {
                    DestinationDirectory = path,
                    OnProgressChanged    = (object s, InstallationCompletionInfo info) => InstallationInformationChanged(info)
                };
            }
            await Task.Run(() => patcher.Start(Installation)).ContinueWith((Task <bool> task) =>
            {
                if (task.IsFaulted)
                {
                    SafePushError(task.Exception.InnerException.Message);
                }
                if (partial)
                {
                    try
                    {
                        Installation.Start(AutoInstall.InstallationType.Finish, false);
                    }
                    catch (Exception e)
                    {
                        SafePushError(e.Message);
                    }
                    OnInstallationCompleted(task);
                }
                var settings = Properties.Settings.Default;
                lock (settings)
                {
                    if (!settings.IsSynchronized)
                    {
                        ;
                    }
                    settings.GameDir       = patcher.GameDir;
                    settings.GameExePath   = patcher.GameExePath;
                    settings.EditorDir     = patcher.EditorDir;
                    settings.EditorExePath = patcher.EditorExePath;
                    settings.Save();
                }
            });
        }
        void StartInstallation(StinkyFile.Installation.AutoInstall.InstallationType Type = default)
        {
            if (Installing)
            {
                MessageBox.Show("An installation is in progress. The current installation must be canceled or complete " +
                                "to start another one.", "Cannot Start Installation");
                return;
            }
            //Save user prefs
            SaveUserPrefs();
            //UI enable/disable
            PreferencesGrid.IsEnabled = false;
            //clear errors
            ErrorStack.Children.Clear();
            //started text
            var textBlock = new TextBlock()
            {
                Text = $"{(Type == default ? "Full" : AutoInstall.GetFriendlyStepName(Type))}" +
                       $" Installation starting...",
                Foreground   = Brushes.DarkCyan,
                FontWeight   = FontWeights.Bold,
                TextWrapping = TextWrapping.Wrap
            };

            ErrorStack.Children.Add(textBlock);
            //create installation context
            Installation = new StinkyFile.Installation.AutoInstall()
            {
                DestinationDirectory = WorkspaceDir.Text,
                BlenderPath          = BlenderPath.Text,
                SourceDirectory      = InstallPath.Text,
                OnTgaExtracting      = (object s, (string path, StinkyFile.ManifestChunk chunk, RefPrim <bool> success)tuple) =>
                                       ExtractTarGA(tuple.path, tuple.chunk, tuple.success),
                OnFontCreate = (object s, (string path, RefPrim <bool> success)tuple) =>
                               RunFontConverter(tuple.path, tuple.success),
                OnProgressChanged = (object s, InstallationCompletionInfo info) => InstallationInformationChanged(info),
                OnStepStarted     = StepStarted,
                OnErrorRaised     = (object s, string error) => SafePushError(error, Brushes.Red)
            };
            Installation.OnPausedStateChanged += Installation_OnPausedStateChanged;
            Installing = true;
            if (Type != default)
            {
                isPartialInstall = true;
                partialTitle     = AutoInstall.GetFriendlyStepName(Type);
                PartialType      = Type;
            }
            else
            {
                isPartialInstall = false;
            }
            //run async task
            Task.Run(() =>
            {
                if (Type == default)
                {
                    return(Installation.Start());
                }
                else
                {
                    return(Installation.Start(Type));
                }
            }).ContinueWith((Task <bool> task) => OnInstallationCompleted(task));
        }