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)