diff --git a/CreamInstaller/Classes/ExceptionHandler.cs b/CreamInstaller/Classes/ExceptionHandler.cs index 2384f99..ef8420f 100644 --- a/CreamInstaller/Classes/ExceptionHandler.cs +++ b/CreamInstaller/Classes/ExceptionHandler.cs @@ -7,27 +7,27 @@ namespace CreamInstaller { public static bool OutputException(Exception e) { - while (!(e.InnerException is null)) + while (e.InnerException is not null) { e = e.InnerException; } string output = ""; string[] stackTrace = e.StackTrace?.Split('\n'); - if (!(stackTrace is null) && stackTrace.Length > 0) + if (stackTrace is not null && stackTrace.Length > 0) { output += "STACK TRACE\n"; for (int i = 0; i < Math.Min(stackTrace.Length, 3); i++) { string line = stackTrace[i]; - if (!(line is null)) + if (line is not null) { output += "\n " + line[line.IndexOf("at")..]; } } } string[] messageLines = e.Message?.Split('\n'); - if (!(messageLines is null) && messageLines.Length > 0) + if (messageLines is not null && messageLines.Length > 0) { if (output.Length > 0) { @@ -38,7 +38,7 @@ namespace CreamInstaller for (int i = 0; i < messageLines.Length; i++) { string line = messageLines[i]; - if (!(line is null)) + if (line is not null) { output += "\n " + messageLines[i]; } diff --git a/CreamInstaller/Classes/ProgramSelection.cs b/CreamInstaller/Classes/ProgramSelection.cs index 7c36e52..e8d884b 100644 --- a/CreamInstaller/Classes/ProgramSelection.cs +++ b/CreamInstaller/Classes/ProgramSelection.cs @@ -1,6 +1,7 @@ using Gameloop.Vdf.Linq; using System; using System.Collections.Generic; +using System.IO; using System.Linq; namespace CreamInstaller @@ -8,6 +9,7 @@ namespace CreamInstaller public class ProgramSelection { public bool Enabled = false; + public bool Usable = true; public string Name; public string RootDirectory; @@ -84,9 +86,23 @@ namespace CreamInstaller All.Add(this); } + public void Validate() + { + SteamApiDllDirectories.RemoveAll(directory => !Directory.Exists(directory)); + if (!Directory.Exists(RootDirectory) || !SteamApiDllDirectories.Any()) + { + All.Remove(this); + } + } + + public static void ValidateAll() + { + All.ForEach(selection => selection.Validate()); + } + public static List All => Program.ProgramSelections; - public static List AllSafe => All.ToList(); + public static List AllSafe => All.FindAll(s => s.Usable); public static List AllSafeEnabled => AllSafe.FindAll(s => s.Enabled); diff --git a/CreamInstaller/Classes/SteamCMD.cs b/CreamInstaller/Classes/SteamCMD.cs index ef70625..fd36bca 100644 --- a/CreamInstaller/Classes/SteamCMD.cs +++ b/CreamInstaller/Classes/SteamCMD.cs @@ -136,7 +136,7 @@ namespace CreamInstaller goto restart; } - if (appInfo is null || (!(appInfo.Value is VValue) && appInfo.Value.Children().ToList().Count == 0)) + if (appInfo is null || (appInfo.Value is not VValue && appInfo.Value.Children().ToList().Count == 0)) { return true; } @@ -145,7 +145,7 @@ namespace CreamInstaller if (type is null || type.ToString() == "Game") { string buildid = appInfo.Value is VValue ? null : appInfo.Value["depots"]?["branches"]?[branch]?["buildid"]?.ToString(); - if (buildid is null && !(type is null)) + if (buildid is null && type is not null) { return true; } @@ -174,12 +174,12 @@ namespace CreamInstaller public static List ParseDlcAppIds(VProperty appInfo) { List dlcIds = new(); - if (!(appInfo is VProperty)) + if (appInfo is not VProperty) { return dlcIds; } - if (!(appInfo.Value["extended"] is null)) + if (appInfo.Value["extended"] is not null) { foreach (VProperty property in appInfo.Value["extended"]) { @@ -196,7 +196,7 @@ namespace CreamInstaller } } - if (!(appInfo.Value["depots"] is null)) + if (appInfo.Value["depots"] is not null) { foreach (VProperty _property in appInfo.Value["depots"]) { diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index 82c5fe1..6c27f1b 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -5,7 +5,7 @@ true Resources\ini.ico true - 2.1.0.1 + 2.1.1.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/InstallForm.cs b/CreamInstaller/Forms/InstallForm.cs index 90229b3..41b2d75 100644 --- a/CreamInstaller/Forms/InstallForm.cs +++ b/CreamInstaller/Forms/InstallForm.cs @@ -36,7 +36,6 @@ namespace CreamInstaller { return; } - userProgressBar.Value = value; } @@ -164,20 +163,15 @@ namespace CreamInstaller private async Task Operate() { - OperationsCount = ProgramSelection.AllSafeEnabled.Count; + List programSelections = ProgramSelection.AllSafeEnabled; + OperationsCount = programSelections.Count; CompleteOperationsCount = 0; - foreach (ProgramSelection selection in ProgramSelection.AllSafe) + foreach (ProgramSelection selection in programSelections) { - if (!selection.Enabled) - { - continue; - } - if (!Program.IsProgramRunningDialog(this, selection)) { throw new OperationCanceledException(); } - try { await OperateFor(selection); diff --git a/CreamInstaller/Forms/MainForm.cs b/CreamInstaller/Forms/MainForm.cs index 2e78b71..895a264 100644 --- a/CreamInstaller/Forms/MainForm.cs +++ b/CreamInstaller/Forms/MainForm.cs @@ -28,7 +28,7 @@ namespace CreamInstaller private void StartProgram() { - if (!(cancellationTokenSource is null)) + if (cancellationTokenSource is not null) { cancellationTokenSource.Cancel(); cancellationTokenSource.Dispose(); @@ -195,7 +195,7 @@ namespace CreamInstaller } catch { } - if (!(updateManager is null) && updateManager.IsUpdatePrepared(latestVersion)) + if (updateManager is not null && updateManager.IsUpdatePrepared(latestVersion)) { updateManager.LaunchUpdater(latestVersion); Application.Exit(); diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 2f851ab..b2cf21e 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -180,7 +180,18 @@ namespace CreamInstaller return true; } - private readonly List treeNodes = new(); + internal List TreeNodes => GatherTreeNodes(selectionTreeView.Nodes); + private List GatherTreeNodes(TreeNodeCollection nodeCollection) + { + List treeNodes = new(); + foreach (TreeNode rootNode in nodeCollection) + { + treeNodes.Add(rootNode); + treeNodes.AddRange(GatherTreeNodes(rootNode.Nodes)); + } + return treeNodes; + } + internal List RunningTasks = new(); private void GetCreamApiApplicablePrograms(IProgress progress) @@ -217,6 +228,7 @@ namespace CreamInstaller string branch = program.Item3; int buildId = program.Item4; string directory = program.Item5; + ProgramSelection selection = ProgramSelection.FromAppId(appId); if (Program.Canceled) { return; @@ -236,6 +248,11 @@ namespace CreamInstaller } if (blockedGame) { + if (selection is not null) + { + selection.Enabled = false; + selection.Usable = false; + } continue; } } @@ -315,7 +332,8 @@ namespace CreamInstaller return; } - ProgramSelection selection = ProgramSelection.FromAppId(appId) ?? new(); + selection ??= new(); + selection.Usable = true; selection.Name = name; selection.RootDirectory = directory; selection.SteamAppId = appId; @@ -347,14 +365,12 @@ namespace CreamInstaller return; } - TreeNode programNode = treeNodes.Find(s => s.Name == "" + appId) ?? new(); + TreeNode programNode = TreeNodes.Find(s => s.Name == "" + appId) ?? new(); programNode.Name = "" + appId; programNode.Text = /*(appId > 0 ? $"[{appId}] " : "") +*/ name; programNode.Checked = selection.Enabled; programNode.Remove(); selectionTreeView.Nodes.Add(programNode); - treeNodes.Remove(programNode); - treeNodes.Add(programNode); if (appId == 0) // paradox launcher { // maybe add game and/or dlc choice here? @@ -374,14 +390,12 @@ namespace CreamInstaller selection.SelectedSteamDlc[dlcApp.Key] = dlcApp.Value; } - TreeNode dlcNode = treeNodes.Find(s => s.Name == "" + dlcApp.Key) ?? new(); + TreeNode dlcNode = TreeNodes.Find(s => s.Name == "" + dlcApp.Key) ?? new(); dlcNode.Name = "" + dlcApp.Key; dlcNode.Text = dlcApp.Value; dlcNode.Checked = selection.SelectedSteamDlc.Contains(dlcApp); dlcNode.Remove(); programNode.Nodes.Add(dlcNode); - treeNodes.Remove(dlcNode); - treeNodes.Add(dlcNode); } } }); @@ -405,177 +419,162 @@ namespace CreamInstaller private async void OnLoad(bool validating = false) { - Program.Canceled = false; - blockedGamesCheckBox.Enabled = false; - blockProtectedHelpButton.Enabled = false; - cancelButton.Enabled = true; - scanButton.Enabled = false; - noneFoundLabel.Visible = false; - allCheckBox.Enabled = false; - installButton.Enabled = false; - uninstallButton.Enabled = installButton.Enabled; - selectionTreeView.Enabled = false; - - label2.Visible = true; - progressBar1.Visible = true; - progressBar1.Value = 0; - groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height - 44); - - bool setup = true; - int maxProgress = 0; - int curProgress = 0; - Progress progress = new(); - IProgress iProgress = progress; - progress.ProgressChanged += (sender, _progress) => + retry: + try { - if (_progress < 0) + Program.Canceled = false; + blockedGamesCheckBox.Enabled = false; + blockProtectedHelpButton.Enabled = false; + cancelButton.Enabled = true; + scanButton.Enabled = false; + noneFoundLabel.Visible = false; + allCheckBox.Enabled = false; + installButton.Enabled = false; + uninstallButton.Enabled = installButton.Enabled; + selectionTreeView.Enabled = false; + + label2.Visible = true; + progressBar1.Visible = true; + progressBar1.Value = 0; + groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height - 44); + + bool setup = true; + int maxProgress = 0; + int curProgress = 0; + Progress progress = new(); + IProgress iProgress = progress; + progress.ProgressChanged += (sender, _progress) => { - maxProgress = -_progress; - } - else + if (_progress < 0) + { + maxProgress = -_progress; + } + else + { + curProgress = _progress; + } + + int p = Math.Max(Math.Min((int)((float)(curProgress / (float)maxProgress) * 100), 100), 0); + if (validating) + { + label2.Text = $"Validating . . . {p}% ({curProgress}/{maxProgress})"; + } + else if (setup) + { + label2.Text = $"Setting up SteamCMD . . . {p}% ({curProgress}/{maxProgress})"; + } + else + { + label2.Text = $"Gathering and caching your applicable games and their DLCs . . . {p}% ({curProgress}/{maxProgress})"; + } + + progressBar1.Value = p; + }; + + iProgress.Report(-1660); // not exact, number varies + int cur = 0; + iProgress.Report(cur); + if (!validating) { - curProgress = _progress; + label2.Text = "Setting up SteamCMD . . . "; } - int p = Math.Max(Math.Min((int)((float)(curProgress / (float)maxProgress) * 100), 100), 0); - if (validating) + if (!Directory.Exists(SteamCMD.DirectoryPath)) { - label2.Text = $"Validating . . . {p}% ({curProgress}/{maxProgress})"; - } - else if (setup) - { - label2.Text = $"Setting up SteamCMD . . . {p}% ({curProgress}/{maxProgress})"; - } - else - { - label2.Text = $"Gathering and caching your applicable games and their DLCs . . . {p}% ({curProgress}/{maxProgress})"; + Directory.CreateDirectory(SteamCMD.DirectoryPath); } - progressBar1.Value = p; - }; + FileSystemWatcher watcher = new(SteamCMD.DirectoryPath); + watcher.Changed += (sender, e) => iProgress.Report(++cur); + watcher.Filter = "*"; + watcher.IncludeSubdirectories = true; + watcher.EnableRaisingEvents = true; + await Task.Run(() => SteamCMD.Setup()); + watcher.Dispose(); - iProgress.Report(-1660); // not exact, number varies - int cur = 0; - iProgress.Report(cur); - if (!validating) - { - label2.Text = "Setting up SteamCMD . . . "; - } - - if (!Directory.Exists(SteamCMD.DirectoryPath)) - { - Directory.CreateDirectory(SteamCMD.DirectoryPath); - } - - FileSystemWatcher watcher = new(SteamCMD.DirectoryPath); - watcher.Changed += (sender, e) => iProgress.Report(++cur); - watcher.Filter = "*"; - watcher.IncludeSubdirectories = true; - watcher.EnableRaisingEvents = true; - await Task.Run(() => SteamCMD.Setup()); - watcher.Dispose(); - - setup = false; - if (!validating) - { - selectionTreeView.Nodes.Clear(); - Program.ProgramSelections.Clear(); - label2.Text = "Gathering and caching your applicable games and their DLCs . . . "; - } - - await Task.Run(() => GetCreamApiApplicablePrograms(iProgress)); - ProgramSelection.All.ForEach(selection => selection.SteamApiDllDirectories.RemoveAll(directory => !Directory.Exists(directory))); - ProgramSelection.All.RemoveAll(selection => !Directory.Exists(selection.RootDirectory) || !selection.SteamApiDllDirectories.Any()); - foreach (TreeNode treeNode in treeNodes) - { - if (treeNode.Parent is null && ProgramSelection.FromAppId(int.Parse(treeNode.Name)) is null) + setup = false; + if (!validating) { - treeNode.Remove(); + label2.Text = "Gathering and caching your applicable games and their DLCs . . . "; + } + + await Task.Run(() => GetCreamApiApplicablePrograms(iProgress)); + ProgramSelection.ValidateAll(); + TreeNodes.ForEach(node => + { + if (node.Parent is null && ProgramSelection.FromAppId(int.Parse(node.Name)) is null) + { + node.Remove(); + } + }); + + progressBar1.Value = 100; + groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height + 44); + label2.Visible = false; + progressBar1.Visible = false; + + selectionTreeView.Enabled = ProgramSelection.All.Any(); + allCheckBox.Enabled = selectionTreeView.Enabled; + noneFoundLabel.Visible = !selectionTreeView.Enabled; + + installButton.Enabled = ProgramSelection.AllSafeEnabled.Any(); + uninstallButton.Enabled = installButton.Enabled; + cancelButton.Enabled = false; + scanButton.Enabled = true; + + blockedGamesCheckBox.Enabled = true; + blockProtectedHelpButton.Enabled = true; + + label2.Text = "Validating . . . "; + if (!validating && !Program.Canceled) + { + OnLoad(true); } } - //SetMinimumSizeFromTreeView(); - - progressBar1.Value = 100; - groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height + 44); - label2.Visible = false; - progressBar1.Visible = false; - - selectionTreeView.Enabled = ProgramSelection.All.Any(); - allCheckBox.Enabled = selectionTreeView.Enabled; - noneFoundLabel.Visible = !selectionTreeView.Enabled; - - installButton.Enabled = ProgramSelection.AllSafeEnabled.Any(); - uninstallButton.Enabled = installButton.Enabled; - cancelButton.Enabled = false; - scanButton.Enabled = true; - - blockedGamesCheckBox.Enabled = true; - blockProtectedHelpButton.Enabled = true; - - label2.Text = "Validating . . . "; - if (!validating && !Program.Canceled) + catch (Exception e) { - OnLoad(true); + if (ExceptionHandler.OutputException(e)) + { + goto retry; + } + Close(); } } - /*private const int GWL_STYLE = -16; - private const int WS_VSCROLL = 0x00200000; - private const int WS_HSCROLL = 0x00100000; - - [DllImport("user32.dll", ExactSpelling = false, CharSet = CharSet.Auto)] - private static extern int GetWindowLong(IntPtr hWnd, int nIndex); - - private const int MINIMUM_SIZE_INCREMENT = 8; - private void SetMinimumSizeFromTreeView() - { - Dictionary expansionState = new(); - foreach (TreeNode node in treeView1.Nodes) expansionState[node] = node.IsExpanded; - treeView1.ExpandAll(); - Size minimumSize = MinimumSize; - Point point; - int style = GetWindowLong(treeView1.Handle, GWL_STYLE); - while ((style & WS_HSCROLL) != 0) - { - minimumSize.Width += MINIMUM_SIZE_INCREMENT; - point = Location; - point.X -= MINIMUM_SIZE_INCREMENT / 2; - Location = point; - MinimumSize = minimumSize; - style = GetWindowLong(treeView1.Handle, GWL_STYLE); - Update(); - } - foreach (TreeNode node in treeView1.Nodes) if (!expansionState[node]) node.Collapse(); - }*/ - private void OnTreeViewNodeCheckedChanged(object sender, TreeViewEventArgs e) { if (e.Action == TreeViewAction.Unknown) { return; } - - ProgramSelection selection = ProgramSelection.FromAppId(int.Parse(e.Node.Name)); - if (selection is null) + TreeNode node = e.Node; + if (node is not null) { - ProgramSelection.FromAppId(int.Parse(e.Node.Parent.Name)).ToggleDlc(int.Parse(e.Node.Name), e.Node.Checked); - e.Node.Parent.Checked = e.Node.Parent.Nodes.Cast().ToList().Any(treeNode => treeNode.Checked); - } - else - { - if (selection.AllSteamDlc.Any()) + ProgramSelection selection = ProgramSelection.FromAppId(int.Parse(node.Name)); + if (selection is null) { - selection.ToggleAllDlc(e.Node.Checked); - e.Node.Nodes.Cast().ToList().ForEach(treeNode => treeNode.Checked = e.Node.Checked); + TreeNode parent = node.Parent; + if (parent is not null) + { + ProgramSelection.FromAppId(int.Parse(parent.Name)).ToggleDlc(int.Parse(node.Name), node.Checked); + parent.Checked = parent.Nodes.Cast().ToList().Any(treeNode => treeNode.Checked); + } } else { - selection.Enabled = e.Node.Checked; + if (selection.AllSteamDlc.Any()) + { + selection.ToggleAllDlc(node.Checked); + node.Nodes.Cast().ToList().ForEach(treeNode => treeNode.Checked = node.Checked); + } + else + { + selection.Enabled = node.Checked; + } + allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; + allCheckBox.Checked = TreeNodes.TrueForAll(treeNode => treeNode.Checked); + allCheckBox.CheckedChanged += OnAllCheckBoxChanged; } - - allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; - allCheckBox.Checked = treeNodes.TrueForAll(treeNode => treeNode.Checked); - allCheckBox.CheckedChanged += OnAllCheckBoxChanged; } installButton.Enabled = ProgramSelection.AllSafeEnabled.Any(); uninstallButton.Enabled = installButton.Enabled; @@ -612,26 +611,13 @@ namespace CreamInstaller } } }; - retry: - try - { - OnLoad(); - } - catch (Exception e) - { - if (ExceptionHandler.OutputException(e)) - { - goto retry; - } - - Close(); - } + OnLoad(); } private static void PopulateParadoxLauncherDlc(ProgramSelection paradoxLauncher = null) { paradoxLauncher ??= ProgramSelection.FromAppId(0); - if (!(paradoxLauncher is null)) + if (paradoxLauncher is not null) { paradoxLauncher.ExtraSteamAppIdDlc.Clear(); foreach (ProgramSelection selection in ProgramSelection.AllSafeEnabled) @@ -640,12 +626,10 @@ namespace CreamInstaller { continue; } - if (selection.AppInfo.Value["extended"]["publisher"].ToString() != "Paradox Interactive") { continue; } - paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.Name, selection.SelectedSteamDlc)); } if (!paradoxLauncher.ExtraSteamAppIdDlc.Any()) @@ -656,12 +640,10 @@ namespace CreamInstaller { continue; } - if (selection.AppInfo.Value["extended"]["publisher"].ToString() != "Paradox Interactive") { continue; } - paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.Name, selection.AllSteamDlc)); } } @@ -671,7 +653,7 @@ namespace CreamInstaller private static bool ParadoxLauncherDlcDialog(Form form) { ProgramSelection paradoxLauncher = ProgramSelection.FromAppId(0); - if (!(paradoxLauncher is null) && paradoxLauncher.Enabled) + if (paradoxLauncher is not null && paradoxLauncher.Enabled) { PopulateParadoxLauncherDlc(paradoxLauncher); if (!paradoxLauncher.ExtraSteamAppIdDlc.Any()) @@ -691,7 +673,7 @@ namespace CreamInstaller private void OnAccept(bool uninstall = false) { - if (ProgramSelection.All.Count > 0) + if (ProgramSelection.All.Any()) { foreach (ProgramSelection selection in ProgramSelection.AllSafeEnabled) { @@ -700,12 +682,10 @@ namespace CreamInstaller return; } } - if (ParadoxLauncherDlcDialog(this)) { return; } - Hide(); InstallForm installForm = new(this, uninstall); installForm.ShowDialog(); @@ -745,19 +725,21 @@ namespace CreamInstaller private void OnAllCheckBoxChanged(object sender, EventArgs e) { bool shouldCheck = false; - foreach (TreeNode treeNode in treeNodes) + TreeNodes.ForEach(node => { - if (treeNode.Parent is null) + if (node.Parent is null) { - if (!treeNode.Checked) + if (!node.Checked) { shouldCheck = true; } - - treeNode.Checked = shouldCheck; - OnTreeViewNodeCheckedChanged(null, new(treeNode, TreeViewAction.ByMouse)); + if (node.Checked != shouldCheck) + { + node.Checked = shouldCheck; + OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse)); + } } - } + }); allCheckBox.Checked = shouldCheck; }