private void Steam_DataReceived(object sender, string e)
        {
            if (string.IsNullOrEmpty(e))
            {
                return;
            }
            string line = e;

            Console.WriteLine(e);

            SteamOutput?.Invoke(this, line);

            if (line.Equals("Loading Steam API...OK."))
            {
                waitStartAsync.Set();
                //SteamExited?.Invoke(this, SteamExitReason.NonEnglishCharachers);
            }
            else if (line.Contains("cannot run from a folder path that includes non-English characters"))
            {
                close(SteamExitReason.NonEnglishCharachers);
            }
            else if (line.Equals("FAILED with result code 5") | line.Equals("Login with cached credentials FAILED with result code 5"))
            {
                LoginCallback?.Invoke(this, LoginResult.WrongInformation);
            }
            else if (line.Equals("FAILED with result code 88"))
            {
                LoginCallback?.Invoke(this, LoginResult.SteamGuardCodeWrong);
            }
            else if (line.Equals("FAILED with result code 65"))
            {
                LoginCallback?.Invoke(this, LoginResult.SteamGuardCodeWrong);
            }
            else if (line.Equals("FAILED with result code 71"))
            {
                LoginCallback?.Invoke(this, LoginResult.ExpiredCode);
            }
            else if (line.Equals("FAILED with result code 84"))
            {
                LoginCallback?.Invoke(this, LoginResult.RateLimitedExceeded);
            }
            else if (line.Contains("using 'set_steam_guard_code'"))
            {
                LoginCallback?.Invoke(this, LoginResult.SteamGuardNotSupported);
            }
            else if (line.Contains("Enter the current code from your Steam Guard Mobile Authenticator app"))
            {
                LoginCallback?.Invoke(this, LoginResult.WaitingForSteamGuard);
            }
            else if (line.Contains("FAILED with result code 50"))
            {
                LoginCallback?.Invoke(this, LoginResult.AlreadyLoggedIn);
            }
            else if (LoginState == false & (line.Contains("Waiting for license info...OK") | line.Contains("Logged in OK")))
            {
                LoginState = true;
                LoginCallback?.Invoke(this, LoginResult.OK);
            }
            else if (Regex.IsMatch(line, "ERROR! Download item [0-9]+ failed (Access Denied)."))
            {
                ModDownloaded?.Invoke(this, null);
            }
            else if (Regex.IsMatch(line, "Error! App '[0-9]+' state is 0x[0-9]+ after update job."))
            {
                AppUpdated?.Invoke(true);
            }
            else if (Regex.IsMatch(line, @"Update state \(0x5\) validating, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)"))
            {
                Regex pattern = new Regex(@"Update state \(0x5\) validating, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)");
                Match match   = pattern.Match(line);


                SteamAppUpdateState state = new SteamAppUpdateState();
                state.percentage    = Convert.ToInt32(match.Groups[1].Value);
                state.receivedBytes = Convert.ToInt64(match.Groups[3].Value);
                state.totalBytes    = Convert.ToInt64(match.Groups[4].Value);
                state.stage         = UpdateStateStage.Validating;

                AppUpdateStateChanged?.Invoke(this, state);
            }
            else if (Regex.IsMatch(line, @"Update state \(0x61\) downloading, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)"))
            {
                Regex pattern = new Regex(@"Update state \(0x61\) downloading, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)");
                Match match   = pattern.Match(line);


                SteamAppUpdateState state = new SteamAppUpdateState();
                state.percentage    = Convert.ToInt32(match.Groups[1].Value);
                state.receivedBytes = Convert.ToInt64(match.Groups[3].Value);
                state.totalBytes    = Convert.ToInt64(match.Groups[4].Value);
                state.stage         = UpdateStateStage.Downloading;

                AppUpdateStateChanged?.Invoke(this, state);
            }
            else if (Regex.IsMatch(line, @"Update state \(0x81\) commiting, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)"))
            {
                Regex pattern = new Regex(@"Update state \(0x81\) commiting, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)");
                Match match   = pattern.Match(line);


                SteamAppUpdateState state = new SteamAppUpdateState();
                state.percentage    = Convert.ToInt32(match.Groups[1].Value);
                state.receivedBytes = Convert.ToInt64(match.Groups[3].Value);
                state.totalBytes    = Convert.ToInt64(match.Groups[4].Value);
                state.stage         = UpdateStateStage.Commiting;

                AppUpdateStateChanged?.Invoke(this, state);
            }
            else if (Regex.IsMatch(line, @"Update state \(0x11\) preallocating, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)"))
            {
                Regex pattern = new Regex(@"Update state \(0x11\) preallocating, progress: ([0-9]+)\.([0-9]+) \(([0-9]+) / ([0-9]+)\)");
                Match match   = pattern.Match(line);


                SteamAppUpdateState state = new SteamAppUpdateState();
                state.percentage    = Convert.ToInt32(match.Groups[1].Value);
                state.receivedBytes = Convert.ToInt64(match.Groups[3].Value);
                state.totalBytes    = Convert.ToInt64(match.Groups[4].Value);
                state.stage         = UpdateStateStage.Preallocating;
                AppUpdateStateChanged?.Invoke(this, state);
            }
            else if (line.Contains("Success! App '") & line.Contains("' fully installed."))
            {
                AppUpdated?.Invoke(this);
            }
            else if (line.Contains("Success! App '") & line.Contains("' already up to date."))
            {
                AppUpdated?.Invoke(this);
            }
            else if (line.Contains("Success. Downloaded item") & line.Contains("bytes"))
            {
                ModDownloaded?.Invoke(this, line.Split('"')[1]);
            }
        }
        public async Task <bool> DownloadMods(List <BaseMod> mods)
        {
            try
            {
                // I'm not 100% sure this causes issues but... pretty sure so that's good enough. We don't need it anyway.
                File.Delete(Path.Combine(SteamCmdPath, "steamapps", "workshop", "appworkshop_294100.acf"));
            }
            catch (Exception ex) { }

            try
            {
                string downloadPath = Path.Combine(SteamCmdPath, "steamapps", "workshop", "content", "294100");

                Log.Information("Downloading {0} workshop mods with SteamCMD", mods.Count);

                StringBuilder script = new StringBuilder();

                // Create steamcmd script
                script.AppendLine("login anonymous");
                foreach (var listObject in mods)
                {
                    script.AppendLine($"workshop_download_item 294100 {listObject.ModId}");
                }
                script.AppendLine("quit");

                File.WriteAllText(Path.Combine(SteamCmdPath, "run.txt"), script.ToString());

                var startInfo = new ProcessStartInfo
                {
                    Arguments       = "+runscript run.txt",
                    CreateNoWindow  = !showWindows,
                    UseShellExecute = false,
                    FileName        = Path.Combine(SteamCmdPath, "steamcmd.exe"),
                    WindowStyle     = showWindows ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden
                };

                // Just make sure it's there
                Directory.CreateDirectory(downloadPath);

                Log.Information("Watching folder {0}", downloadPath);

                FileSystemWatcher watcher = new FileSystemWatcher(downloadPath);

                watcher.Created += delegate(object sender, FileSystemEventArgs args)
                {
                    // Check that this path is a directory and not a file just to be sure.
                    if (Directory.Exists(args.FullPath))
                    {
                        string id  = args.Name;
                        var    mod = mods.FirstOrDefault(x => x.ModId == id);

                        // Make sure this is actually a mod being downloaded by this instance of steamcmd and not another one.
                        // (probably, anyway)
                        if (mod?.Details != null)
                        {
                            mod.Downloaded = true;

                            ModDownloaded?.Invoke(this, mod, args.FullPath);

                            Log.Information("Downloaded mod folder created @ {0}", args.FullPath);
                        }
                    }
                };

                // Start watching folder
                watcher.EnableRaisingEvents = true;

                // Start SteamCMD
                var steamCMD = new Process {
                    StartInfo = startInfo
                };

                Log.Information("Starting SteamCMD instance for download of {0} mods", mods.Count);
                steamCMD.Start();

                // Wait for SteamCMD to start and login.
                await Task.Delay(3000);

                // Today on unreliable and arbitrary events
                SteamStarted?.Invoke(this);

                // wait for steamcmd to exit
                while (!steamCMD.HasExited)
                {
                    await Task.Delay(100);
                }

                // Stop watching the download folder & get rid of watcher
                watcher.EnableRaisingEvents = false;
                watcher.Dispose();

                await Task.Delay(500);

                SteamExited?.Invoke(this);

                Log.Information($"Finished downloading {mods.Count} mods from workshop. SteamCMD instance closed.");

                return(true);
            }
            catch (Exception ex)
            {
                StringBuilder str = new StringBuilder();
                mods.ForEach(x => str.AppendLine(x.ModId + " - " + x.Details.title));
                Log.Error(ex, "Error occurred while downloading {0} mods with SteamCMD. Mods:\n{1}", mods.Count, str);
            }

            return(false);
        }