public async Task <bool> UpdateMods(List <BaseMod> mods, bool forceNoBackup = false) { this.Updating = true; UpdaterForm.SetStatus($"Starting SteamCMD..."); int statusCount = 0; double totalSize = 0; mods.ForEach(x => totalSize += x.Details?.file_size ?? 0); double totalSizeTemp = totalSize; UpdaterForm.SetProgress(0, ProgressBarStyle.Blocks); UpdaterForm.SetProgressBounds(mods.Count); var downloader = new Downloader(); downloader.ModDownloaded += delegate(object sender, BaseMod mod, string folder) { statusCount++; totalSizeTemp -= mod.Details.file_size; UpdaterForm.SetStatus($"Downloaded {statusCount}/{mods.Count} mods ({Math.Round(totalSizeTemp / 1024d / 1024d, 2)} MB)"); UpdaterForm.UpdateProgress(); }; downloader.SteamStarted += sender => { UpdaterForm.SetStatus($"Downloaded {statusCount}/{mods.Count} mods ({Math.Round(totalSizeTemp / 1024d / 1024d, 2)} MB)"); }; bool ok = await downloader.DownloadMods(mods); if (!ok) { this.Updating = false; MessageBox.Show("An error occurred while downloading workshop mods; Check the log file.", "Uh oh", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } Log.Information("Updating mod files..."); UpdaterForm.SetStatus("Updating mod files..."); string modsPath = Path.Combine(ModsPath); string toolPath = Path.GetFullPath("./"); string downloadContentPath = Path.Combine(toolPath, "steamcmd", "steamapps", "workshop", "content", "294100"); UpdaterForm.SetProgress(0, ProgressBarStyle.Blocks); UpdaterForm.SetProgressBounds(mods.Count); foreach (var obj in mods) { if (!UpdateMod(obj, downloadContentPath, forceNoBackup)) { UpdaterForm.UpdateProgress(); continue; } UpdaterForm.UpdateProgress(); obj.Updated = true; if (!forceNoBackup) { UpdaterForm.UpdateObject(obj); } } UpdaterForm.SetStatus($"Finished updating {mods.Count} mods! A total of {Math.Round(totalSize / 1024d / 1024d, 2)} MB was downloaded."); Log.Information($"Finished updating {mods.Count} mods."); this.Updating = false; return(true); }
private void UpdaterForm_Load(object s, EventArgs e) { _instance = this; this.Text = "Rimworld Mod Updater " + Utils.GetProgramVersion(); // It's times like this when I really question myself new ToolTip().SetToolTip(btnManualUpdate, "Select a mod in your mods folder to update manually.\nWill replace files regardless of whether it's outdated or not."); new ToolTip().SetToolTip(btnReset, "Reset the updater to it's inital state, allowing you to query for outdated mods again."); new ToolTip().SetToolTip(btnOpenFileDialog, "Opens a file dialog for you to choose your rimworld installation folder.\nIf you put the updater in your rimworld folder, it should be set for you."); new ToolTip().SetToolTip(textGamePath, "The rimworld game path. Shit wont work if this isn't set."); new ToolTip().SetToolTip(btnViewDownloadMod, "Start downloading this mod/collection.\nIf it's a collection, it may take a while to query the collection & all of the mods in it depending on the size."); // Fixes an issue where context menu isn't opened on first try. Not completely sure why this fixes it. listMenu.Items.Add(""); downloadedModMenu.Items.Add(""); if (Directory.Exists("./Mods")) { // Talk about a cluttered rimworld folder if you had this piece of shit in the main folder. textGamePath.Text = Path.GetFullPath("./"); } else if (Directory.Exists("../Mods")) { textGamePath.Text = Path.GetFullPath("../"); } listObjectsParsed.ItemsChanged += delegate(object sender, ItemsChangedEventArgs args) { lblObjectsParsed.Text = $"Mods with updates available: {listObjectsParsed.GetItemCount()}"; }; textViewUrlBar.Text = "Loading browser..."; textViewUrlBar.Enabled = false; var clicker = new WorkshopJSClicker(); clicker.Clicked += (id) => { if (id == null) { StartModDownload(null); } else { StartModDownload("https://steamcommunity.com/sharedfiles/filedetails/?id=" + id); } }; chromiumWebBrowser.JavascriptObjectRepository.Register("_____updater", clicker, false); if (File.Exists("steamHelper.js")) { chromiumWebBrowser.ExecuteScriptAsyncWhenPageLoaded(File.ReadAllText("steamHelper.js"), false); } chromiumWebBrowser.Load("https://steamcommunity.com/app/294100/workshop/"); chromiumWebBrowser.LifeSpanHandler = new LifeSpanHandler(); currentUpdater = new Updater(textGamePath.Text); downloadTabManager = new DownloadTabManager(downloaderTabProgressBar, downloaderTabStatus, currentUpdater); Utils.CheckForUpdates(); }
public async Task QueryFiles() { var folders = Directory.GetDirectories(ModsPath); int numFolders = folders.Length; int count = 0; if (folders.Length == 0) { Log.Error("Tried to query mod folders but found none."); MessageBox.Show("You have no mods installed!", "bruh", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } UpdaterForm.SetProgressBounds(numFolders); UpdaterForm.SetProgress(0); UpdaterForm.SetStatus($"Querying {numFolders} mod folders for outdated mods..."); Log.Information($"Querying {numFolders} mod folders for outdated mods..."); List <BaseMod> mods = new List <BaseMod>(); for (int i = 0; i < numFolders; i++) { string id = await QueryModId(folders[i]); if (!String.IsNullOrWhiteSpace(id)) { Log.Information("Got valid mod folder {0} ({1})", folders[i], id); mods.Add(new BaseMod { ModPath = folders[i], ModId = id }); count++; } UpdaterForm.UpdateProgress(); } UpdaterForm.SetStatus($"Found {count}/{numFolders} valid (steam) mod folders."); Log.Information("Found {0}/{1} valid mod folders.", count, numFolders); int batchCount = 50; int num = 0; int num2 = 0; int len = mods.Count; UpdaterForm.SetStatus($"Querying {len} mods in {(int)Math.Ceiling((double)len / batchCount)} batches of {batchCount}"); Log.Information("Querying {0} mods in {1} batches of {2}", len, (int)Math.Ceiling((double)len / batchCount), batchCount); UpdaterForm.ResetProgress(); UpdaterForm.SetProgressBounds((int)Math.Ceiling((double)len / batchCount)); bool retry = false; var tasks = new List <Task>(); for (int i = 0; i < len; i += batchCount) { var task = Task.Run(async() => { var batch = mods.GetRange(i, Math.Min(batchCount, len - i)); await QueryModBatch(batch); num2 += batchCount; Log.Information($"Queried {Math.Min(num2, len)}/{len} mods."); UpdaterForm.SetStatus($"Queried {Math.Min(num2, len)}/{len} mods."); UpdaterForm.UpdateProgress(); }); tasks.Add(task); await Task.Delay(250); } await Task.WhenAll(tasks); // Let's just send it all at once lol //var files = await SteamWorkshop.GetWorkshopFileDetails(fileIds.Keys.ToArray()); Log.Information($"Got workshop file details for {mods.Count(x => x.Details != null)} mods."); UpdaterForm.SetProgressBounds(mods.Count); UpdaterForm.ResetProgress(); int updateCount = 0; foreach (var mod in mods) { UpdaterForm.UpdateProgress(); var details = mod.Details; string folderName = mod.Folder; if (details == null) { Log.Error($"Couldn't get any file details for mod {mod.ModId} ({folderName})."); continue; } string id = details.publishedfileid; if (details.result == 9) { Log.Warning($"Tried to query workshop file {id} ({folderName}) but no file could be found. (Code 9). This could mean the mod has been removed/unlisted"); continue; } if (details.result != 1) { Log.Warning($"Tried to query workshop file {id} ({folderName}) but steam returned code {details.result}"); } if (details.visibility != 0) { Log.Warning($"Got workshop file {id} ({folderName}) but it's a private file."); continue; } if (details.banned == 1) { Log.Warning($"Got workshop file {id} ({folderName}) but it's a banned file."); continue; } if (details.creator_app_id != 294100) { Log.Warning($"Got workshop file {id} ({folderName}) but it's not a rimworld mod! (Huh?)"); continue; } var modPath = mod.ModPath; var remoteDate = details.TimeUpdated; var lastUpdatedDate = GetModLastUpdatedTime(modPath); //Log.Information("{0} < {1}: {2}", remoteDate.ToUnixTimeSeconds(), lastUpdatedDate.ToUnixTimeSeconds(), (remoteDate < lastUpdatedDate)); if (remoteDate > lastUpdatedDate) { updateCount++; Log.Information($"Mod folder {folderName} ({details.publishedfileid}) has an update available."); UpdaterForm.AddRow(mod); await Task.Delay(1); } } Log.Information("There are {0} mods with updates available.", updateCount); }