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); }