From 0d4c1630d6ffe42a14ab1e553e89b03ef468f4ba Mon Sep 17 00:00:00 2001 From: pointfeev Date: Sat, 5 Feb 2022 02:04:22 -0500 Subject: [PATCH] v2.3.0.0 - Added extra labels to the selection form progress section that display remaining games and DLCs, replacing the "(#/#)" text - Fixed a harmless control invoke exception that happens when the program is closed - Fixed a harmless bug with duplicates being included in the games to be gathered --- CreamInstaller/Classes/ProgramSelection.cs | 2 +- CreamInstaller/Classes/SteamCMD.cs | 4 +- CreamInstaller/CreamInstaller.csproj | 2 +- CreamInstaller/Forms/MainForm.cs | 2 +- CreamInstaller/Forms/SelectForm.Designer.cs | 80 ++++++++--- CreamInstaller/Forms/SelectForm.cs | 149 +++++++++++++++++--- CreamInstaller/Program.cs | 10 ++ 7 files changed, 207 insertions(+), 42 deletions(-) diff --git a/CreamInstaller/Classes/ProgramSelection.cs b/CreamInstaller/Classes/ProgramSelection.cs index 2092a3a..0967de1 100644 --- a/CreamInstaller/Classes/ProgramSelection.cs +++ b/CreamInstaller/Classes/ProgramSelection.cs @@ -100,7 +100,7 @@ internal class ProgramSelection internal void Validate() { - if (Program.BlockProtectedGames && Program.IsGameBlocked(Name, RootDirectory)) + if (Program.IsGameBlocked(Name, RootDirectory)) { All.Remove(this); return; diff --git a/CreamInstaller/Classes/SteamCMD.cs b/CreamInstaller/Classes/SteamCMD.cs index f48aafe..8d64a5d 100644 --- a/CreamInstaller/Classes/SteamCMD.cs +++ b/CreamInstaller/Classes/SteamCMD.cs @@ -131,12 +131,12 @@ internal static class SteamCMD VToken extended = appInfo.Value.GetChild("extended"); if (extended is not null) foreach (VProperty property in extended) - if (property.Key.ToString() == "listofdlc") + if (property.Key == "listofdlc") foreach (string id in property.Value.ToString().Split(",")) if (int.TryParse(id, out int appId) && !dlcIds.Contains(appId)) dlcIds.Add(appId); VToken depots = appInfo.Value.GetChild("depots"); if (depots is not null) foreach (VProperty property in depots) - if (int.TryParse(property.Key.ToString(), out int _) + if (int.TryParse(property.Key, out int _) && int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appid) && !dlcIds.Contains(appid)) dlcIds.Add(appid); diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index f58ed82..3d376bb 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -5,7 +5,7 @@ true Resources\ini.ico true - 2.2.4.4 + 2.3.0.0 Resources\ini.ico Automatically generates and installs CreamAPI files for Steam games on the user's computer. It can also generate and install CreamAPI for the Paradox Launcher should the user select a Paradox Interactive game. diff --git a/CreamInstaller/Forms/MainForm.cs b/CreamInstaller/Forms/MainForm.cs index 7908828..7117644 100644 --- a/CreamInstaller/Forms/MainForm.cs +++ b/CreamInstaller/Forms/MainForm.cs @@ -113,7 +113,7 @@ internal partial class MainForm : CustomForm document.LoadHtml(reader.ReadToEnd()); foreach (HtmlNode node in document.DocumentNode.SelectNodes("//div[@data-test-selector='body-content']/ul/li")) { - changelogTreeView.Invoke((MethodInvoker)delegate + changelogTreeView.TryMethodInvoke(delegate { TreeNode change = new(); change.Text = $"{HttpUtility.HtmlDecode(node.InnerText)}"; diff --git a/CreamInstaller/Forms/SelectForm.Designer.cs b/CreamInstaller/Forms/SelectForm.Designer.cs index e655751..a128c7b 100644 --- a/CreamInstaller/Forms/SelectForm.Designer.cs +++ b/CreamInstaller/Forms/SelectForm.Designer.cs @@ -43,11 +43,13 @@ namespace CreamInstaller this.selectionTreeView = new CreamInstaller.CustomTreeView(); this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); this.allCheckBox = new System.Windows.Forms.CheckBox(); - this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.progressBar = new System.Windows.Forms.ProgressBar(); this.progressLabel = new System.Windows.Forms.Label(); this.scanButton = new System.Windows.Forms.Button(); this.uninstallButton = new System.Windows.Forms.Button(); this.nodeContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.progressLabelGames = new System.Windows.Forms.Label(); + this.progressLabelDLCs = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); this.flowLayoutPanel1.SuspendLayout(); this.flowLayoutPanel2.SuspendLayout(); @@ -97,19 +99,17 @@ namespace CreamInstaller this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System; this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(560, 308); + this.groupBox1.Size = new System.Drawing.Size(560, 240); this.groupBox1.TabIndex = 8; this.groupBox1.TabStop = false; this.groupBox1.Text = "Programs / Games"; // // noneFoundLabel // - this.noneFoundLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.noneFoundLabel.Location = new System.Drawing.Point(6, 22); + this.noneFoundLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.noneFoundLabel.Location = new System.Drawing.Point(3, 19); this.noneFoundLabel.Name = "noneFoundLabel"; - this.noneFoundLabel.Size = new System.Drawing.Size(548, 280); + this.noneFoundLabel.Size = new System.Drawing.Size(554, 218); this.noneFoundLabel.TabIndex = 1002; this.noneFoundLabel.Text = "No CreamAPI-applicable programs were found on your computer!"; this.noneFoundLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -160,8 +160,8 @@ namespace CreamInstaller // // selectionTreeView // - this.selectionTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) + this.selectionTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.selectionTreeView.BackColor = System.Drawing.SystemColors.Control; this.selectionTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None; @@ -198,24 +198,40 @@ namespace CreamInstaller this.allCheckBox.Text = "All"; this.allCheckBox.CheckedChanged += new System.EventHandler(this.OnAllCheckBoxChanged); // + // selectionTreeView + // + this.selectionTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.selectionTreeView.Location = new System.Drawing.Point(3, 19); + this.selectionTreeView.Size = new System.Drawing.Size(554, 218); + this.selectionTreeView.BackColor = System.Drawing.SystemColors.Control; + this.selectionTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.selectionTreeView.CheckBoxes = true; + this.selectionTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.selectionTreeView.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawAll; + this.selectionTreeView.Enabled = false; + this.selectionTreeView.FullRowSelect = true; + this.selectionTreeView.LineColor = System.Drawing.Color.Empty; + this.selectionTreeView.Name = "selectionTreeView"; + this.selectionTreeView.TabIndex = 1001; + // // progressBar1 // - this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.progressBar1.Location = new System.Drawing.Point(12, 297); - this.progressBar1.Name = "progressBar1"; - this.progressBar1.Size = new System.Drawing.Size(560, 23); - this.progressBar1.TabIndex = 9; + this.progressBar.Location = new System.Drawing.Point(12, 297); + this.progressBar.Name = "progressBar1"; + this.progressBar.Size = new System.Drawing.Size(560, 23); + this.progressBar.TabIndex = 9; // // progressLabel // this.progressLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.progressLabel.Location = new System.Drawing.Point(12, 279); + this.progressLabel.Location = new System.Drawing.Point(12, 255); this.progressLabel.Name = "progressLabel"; - this.progressLabel.Size = new System.Drawing.Size(760, 15); + this.progressLabel.Size = new System.Drawing.Size(560, 15); this.progressLabel.TabIndex = 10; - this.progressLabel.Text = "Loading . . ."; + this.progressLabel.Text = "Gathering and caching your applicable games and their DLCs . . . 0%"; // // scanButton // @@ -248,15 +264,39 @@ namespace CreamInstaller this.nodeContextMenu.Name = "nodeContextMenu"; this.nodeContextMenu.Size = new System.Drawing.Size(61, 4); // + // progressLabelGames + // + this.progressLabelGames.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.progressLabelGames.Font = new System.Drawing.Font("Segoe UI", 7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.progressLabelGames.Location = new System.Drawing.Point(12, 270); + this.progressLabelGames.Name = "progressLabelGames"; + this.progressLabelGames.Size = new System.Drawing.Size(560, 12); + this.progressLabelGames.TabIndex = 11; + this.progressLabelGames.Text = "Remaining games (2): Game 1, Game 2"; + // + // progressLabelDLC + // + this.progressLabelDLCs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.progressLabelDLCs.Font = new System.Drawing.Font("Segoe UI", 7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.progressLabelDLCs.Location = new System.Drawing.Point(12, 282); + this.progressLabelDLCs.Name = "progressLabelDLC"; + this.progressLabelDLCs.Size = new System.Drawing.Size(560, 12); + this.progressLabelDLCs.TabIndex = 10004; + this.progressLabelDLCs.Text = "Remaining DLC (2): 123456, 654321"; + // // SelectForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(584, 361); + this.Controls.Add(this.progressLabelDLCs); + this.Controls.Add(this.progressLabelGames); this.Controls.Add(this.uninstallButton); this.Controls.Add(this.scanButton); this.Controls.Add(this.groupBox1); - this.Controls.Add(this.progressBar1); + this.Controls.Add(this.progressBar); this.Controls.Add(this.label1); this.Controls.Add(this.cancelButton); this.Controls.Add(this.installButton); @@ -285,7 +325,7 @@ namespace CreamInstaller private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Label label1; private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.ProgressBar progressBar; private System.Windows.Forms.Label progressLabel; private System.Windows.Forms.CheckBox allCheckBox; private Button scanButton; @@ -297,6 +337,8 @@ namespace CreamInstaller private FlowLayoutPanel flowLayoutPanel2; private Button uninstallButton; private ContextMenuStrip nodeContextMenu; + private Label progressLabelGames; + private Label progressLabelDLCs; } } diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 07e9d3d..49747c5 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -119,6 +119,66 @@ internal partial class SelectForm : CustomForm internal List RunningTasks = new(); + private List RemainingGames = new(); + private void UpdateRemainingGames() + { + if (Program.Canceled) return; + progressLabelGames.Text = $"Remaining games ({RemainingGames.Count}): " + + (RemainingGames.Any() ? string.Join(", ", RemainingGames).Replace("&", "&&") : "None"); + } + private void AddToRemainingGames(string gameName) + { + if (Program.Canceled) return; + progressLabelGames.TryMethodInvoke(delegate + { + if (Program.Canceled) return; + if (!RemainingGames.Contains(gameName)) + RemainingGames.Add(gameName); + UpdateRemainingGames(); + }); + } + private void RemoveFromRemainingGames(string gameName) + { + if (Program.Canceled) return; + progressLabelGames.TryMethodInvoke(delegate + { + if (Program.Canceled) return; + if (RemainingGames.Contains(gameName)) + RemainingGames.Remove(gameName); + UpdateRemainingGames(); + }); + } + + private List RemainingDLCs = new(); + private void UpdateRemainingDLCs() + { + if (Program.Canceled) return; + progressLabelDLCs.Text = $"Remaining DLCs ({RemainingDLCs.Count}): " + + (RemainingDLCs.Any() ? string.Join(", ", RemainingDLCs).Replace("&", "&&") : "None"); + } + private void AddToRemainingDLCs(string dlcId) + { + if (Program.Canceled) return; + progressLabelDLCs.TryMethodInvoke(delegate + { + if (Program.Canceled) return; + if (!RemainingDLCs.Contains(dlcId)) + RemainingDLCs.Add(dlcId); + UpdateRemainingDLCs(); + }); + } + private void RemoveFromRemainingDLCs(string dlcId) + { + if (Program.Canceled) return; + progressLabelDLCs.TryMethodInvoke(delegate + { + if (Program.Canceled) return; + if (RemainingDLCs.Contains(dlcId)) + RemainingDLCs.Remove(dlcId); + UpdateRemainingDLCs(); + }); + } + private async Task GetCreamApiApplicablePrograms(IProgress progress) { if (Program.Canceled) return; @@ -132,11 +192,14 @@ internal partial class SelectForm : CustomForm List> games = await GetGamesFromLibraryDirectory(libraryDirectory); if (games is not null) foreach (Tuple game in games) - applicablePrograms.Add(game); + if (!applicablePrograms.Any(_game => _game.Item1 == game.Item1)) + applicablePrograms.Add(game); } int CompleteTasks = 0; RunningTasks.Clear(); + RemainingGames.Clear(); + RemainingDLCs.Clear(); foreach (Tuple program in applicablePrograms) { int appId = program.Item1; @@ -146,15 +209,24 @@ internal partial class SelectForm : CustomForm string directory = program.Item5; ProgramSelection selection = ProgramSelection.FromAppId(appId); if (Program.Canceled) return; - if (Program.BlockProtectedGames && Program.IsGameBlocked(name, directory)) continue; + if (Program.IsGameBlocked(name, directory)) continue; RunningTasks.Add(Task.Run(async () => { if (Program.Canceled) return; + AddToRemainingGames(name); List dllDirectories = await GetDllDirectoriesFromGameDirectory(directory); - if (dllDirectories is null) return; + if (dllDirectories is null) + { + RemoveFromRemainingGames(name); + return; + } VProperty appInfo = null; if (appId > 0) appInfo = await SteamCMD.GetAppInfo(appId, branch, buildId); - if (appId > 0 && appInfo is null) return; + if (appId > 0 && appInfo is null) + { + RemoveFromRemainingGames(name); + return; + } if (Program.Canceled) return; ConcurrentDictionary dlc = new(); List dlcTasks = new(); @@ -167,12 +239,18 @@ internal partial class SelectForm : CustomForm Task task = Task.Run(async () => { if (Program.Canceled) return; + AddToRemainingDLCs(id.ToString()); string dlcName = null; VProperty dlcAppInfo = await SteamCMD.GetAppInfo(id); if (dlcAppInfo is not null) dlcName = dlcAppInfo.Value?.GetChild("common")?.GetChild("name")?.ToString(); if (Program.Canceled) return; - if (string.IsNullOrWhiteSpace(dlcName)) return; //dlcName = "Unknown DLC"; + if (string.IsNullOrWhiteSpace(dlcName)) + { + RemoveFromRemainingDLCs(id.ToString()); + return; + } dlc[id] = /*$"[{id}] " +*/ dlcName; + RemoveFromRemainingDLCs(id.ToString()); progress.Report(++CompleteTasks); }); dlcTasks.Add(task); @@ -181,9 +259,17 @@ internal partial class SelectForm : CustomForm Thread.Sleep(10); // to reduce control & window freezing } } - else if (appId > 0) return; + else if (appId > 0) + { + RemoveFromRemainingGames(name); + return; + } if (Program.Canceled) return; - if (string.IsNullOrWhiteSpace(name)) return; + if (string.IsNullOrWhiteSpace(name)) + { + RemoveFromRemainingGames(name); + return; + } selection ??= new(); selection.Usable = true; @@ -209,7 +295,7 @@ internal partial class SelectForm : CustomForm await task; } if (Program.Canceled) return; - selectionTreeView.Invoke((MethodInvoker)delegate + selectionTreeView.TryMethodInvoke(delegate { if (Program.Canceled) return; TreeNode programNode = TreeNodes.Find(s => s.Name == "" + appId) ?? new(); @@ -238,6 +324,8 @@ internal partial class SelectForm : CustomForm } } }); + if (Program.Canceled) return; + RemoveFromRemainingGames(name); progress.Report(++CompleteTasks); })); progress.Report(-RunningTasks.Count); @@ -265,10 +353,7 @@ internal partial class SelectForm : CustomForm installButton.Enabled = false; uninstallButton.Enabled = installButton.Enabled; selectionTreeView.Enabled = false; - progressLabel.Visible = true; - progressBar1.Visible = true; - progressBar1.Value = 0; - groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height - 44); + ShowProgressBar(); bool setup = true; int maxProgress = 0; @@ -282,8 +367,8 @@ internal partial class SelectForm : CustomForm else curProgress = _progress; int p = Math.Max(Math.Min((int)((float)(curProgress / (float)maxProgress) * 100), 100), 0); progressLabel.Text = setup ? $"Setting up SteamCMD . . . {p}% ({curProgress}/{maxProgress})" - : $"Gathering and caching your applicable games and their DLCs . . . {p}% ({curProgress}/{maxProgress})"; - progressBar1.Value = p; + : $"Gathering and caching your applicable games and their DLCs . . . {p}%"; + progressBar.Value = p; }; iProgress.Report(-1660); // not exact, number varies @@ -309,10 +394,7 @@ internal partial class SelectForm : CustomForm }); await GetCreamApiApplicablePrograms(iProgress); - progressBar1.Value = 100; - groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height + 44); - progressLabel.Visible = false; - progressBar1.Visible = false; + HideProgressBar(); selectionTreeView.Enabled = ProgramSelection.All.Any(); allCheckBox.Enabled = selectionTreeView.Enabled; noneFoundLabel.Visible = !selectionTreeView.Enabled; @@ -373,8 +455,39 @@ internal partial class SelectForm : CustomForm } } + private void ShowProgressBar() + { + progressBar.Value = 0; + progressLabelGames.Text = "Loading . . . "; + progressLabel.Visible = true; + progressLabelGames.Text = ""; + progressLabelGames.Visible = true; + progressLabelDLCs.Text = ""; + progressLabelDLCs.Visible = true; + progressBar.Visible = true; + groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height - 3 + - progressLabel.Size.Height + - progressLabelGames.Size.Height + - progressLabelDLCs.Size.Height + - progressBar.Size.Height); + } + private void HideProgressBar() + { + progressBar.Value = 100; + progressLabel.Visible = false; + progressLabelGames.Visible = false; + progressLabelDLCs.Visible = false; + progressBar.Visible = false; + groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height + 3 + + progressLabel.Size.Height + + progressLabelGames.Size.Height + + progressLabelDLCs.Size.Height + + progressBar.Size.Height); + } + private void OnLoad(object sender, EventArgs _) { + HideProgressBar(); selectionTreeView.TreeViewNodeSorter = new TreeNodeSorter(); selectionTreeView.AfterCheck += OnTreeViewNodeCheckedChanged; Dictionary images = new(); diff --git a/CreamInstaller/Program.cs b/CreamInstaller/Program.cs index 1fbe404..894bd51 100644 --- a/CreamInstaller/Program.cs +++ b/CreamInstaller/Program.cs @@ -28,6 +28,7 @@ internal static class Program internal static bool IsGameBlocked(string name, string directory) { + if (!BlockProtectedGames) return false; if (ProtectedGameNames.Contains(name)) return true; if (!ProtectedGameDirectoryExceptions.Contains(name)) foreach (string path in ProtectedGameDirectories) @@ -122,6 +123,15 @@ internal static class Program await SteamCMD.Kill(); } + internal static void TryMethodInvoke(this Control control, MethodInvoker methodInvoker) + { + try + { + control.Invoke(methodInvoker); + } + catch { } + } + private static void OnApplicationExit(object s, EventArgs e) => Cleanup(); internal static void InheritLocation(this Form form, Form fromForm)