From 91880aa6987aa8644e756c1479de172b99f70244 Mon Sep 17 00:00:00 2001 From: pointfeev Date: Wed, 24 Aug 2022 22:56:26 -0400 Subject: [PATCH] fixes, color changes & game koaloader toggles - Improved tabbing in the selection forms - Improved main select form "All" check box logic - Swapped multiple main select form operations with their thread-safe alternatives (fixes game scanning lockups) - Extra text in the selection forms are now highlighted the same as nodes and can be left/right clicked --- CreamInstaller/Components/ContextMenuItem.cs | 4 +- CreamInstaller/Components/CustomTreeView.cs | 127 +++++- CreamInstaller/CreamInstaller.csproj | 1 + CreamInstaller/Forms/InstallForm.cs | 150 +++---- CreamInstaller/Forms/MainForm.cs | 4 +- .../Forms/SelectDialogForm.Designer.cs | 12 +- CreamInstaller/Forms/SelectForm.Designer.cs | 94 ++++- CreamInstaller/Forms/SelectForm.cs | 393 ++++++++++-------- CreamInstaller/Forms/SelectForm.resx | 3 + CreamInstaller/ProgramSelection.cs | 3 +- CreamInstaller/Resources/Koaloader.cs | 65 ++- CreamInstaller/Resources/ScreamAPI.cs | 58 +-- CreamInstaller/Resources/SmokeAPI.cs | 68 +-- CreamInstaller/Resources/UplayR1.cs | 46 +- CreamInstaller/Resources/UplayR2.cs | 46 +- 15 files changed, 650 insertions(+), 424 deletions(-) diff --git a/CreamInstaller/Components/ContextMenuItem.cs b/CreamInstaller/Components/ContextMenuItem.cs index 9149300..038722c 100644 --- a/CreamInstaller/Components/ContextMenuItem.cs +++ b/CreamInstaller/Components/ContextMenuItem.cs @@ -65,7 +65,7 @@ internal class ContextMenuItem : ToolStripMenuItem item.Image = image; } } - }).ConfigureAwait(false); + }); private static async Task TryImageIdentifierInfo(ContextMenuItem item, (string id, string iconUrl) imageIdentifierInfo, Action onFail = null) => await Task.Run(async () => { @@ -83,7 +83,7 @@ internal class ContextMenuItem : ToolStripMenuItem else if (onFail is not null) onFail(); } - }).ConfigureAwait(false); + }); private readonly EventHandler OnClickEvent; protected override void OnClick(EventArgs e) diff --git a/CreamInstaller/Components/CustomTreeView.cs b/CreamInstaller/Components/CustomTreeView.cs index f4d6423..b73bf5f 100644 --- a/CreamInstaller/Components/CustomTreeView.cs +++ b/CreamInstaller/Components/CustomTreeView.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; +using System.Windows.Forms.VisualStyles; namespace CreamInstaller.Components; @@ -21,35 +23,126 @@ internal class CustomTreeView : TreeView TreeViewNodeSorter = PlatformIdComparer.NodeName; } + private readonly Dictionary selectionBounds = new(); + private readonly Dictionary checkBoxBounds = new(); + private const string koaloaderToggleString = "Koaloader"; + private void DrawTreeNode(object sender, DrawTreeNodeEventArgs e) { e.DrawDefault = true; TreeNode node = e.Node; if (!node.IsVisible) return; + bool highlighted = node.IsSelected && SelectedNode == node && ContainsFocus; - string subText = node.Name; - Platform? platform = node.Tag as Platform?; - string tagText = platform?.ToString(); - if (string.IsNullOrWhiteSpace(subText) || string.IsNullOrWhiteSpace(tagText) || subText == "PL") + Form form = FindForm(); + if (form is not SelectForm and not SelectDialogForm) + return; + + string platformId = node.Name; + Platform platform = (node.Tag as Platform?).GetValueOrDefault(Platform.None); + if (string.IsNullOrWhiteSpace(platformId) || platform is Platform.None) return; Graphics graphics = e.Graphics; - Color backColor = BackColor; - using SolidBrush brush = new(backColor); + using SolidBrush backBrush = new(BackColor); + using SolidBrush highlightBrush = new(SystemColors.Highlight); Font font = Font; - Rectangle bounds = node.Bounds; + Size lastSize; + Rectangle lastBounds = node.Bounds; + Rectangle selectionBounds = lastBounds; + Point lastPoint; - Size tagSize = TextRenderer.MeasureText(graphics, tagText, font); - Rectangle tagBounds = new(bounds.X + bounds.Width, bounds.Y, tagSize.Width, bounds.Height); - graphics.FillRectangle(brush, tagBounds); - Point tagLocation = new(tagBounds.Location.X - 1, tagBounds.Location.Y + 1); - TextRenderer.DrawText(graphics, tagText, font, tagLocation, Color.Gray); + string tagText = platform.ToString(); + lastSize = TextRenderer.MeasureText(graphics, tagText, font); + lastBounds = new(lastBounds.X + lastBounds.Width, lastBounds.Y, lastSize.Width, lastBounds.Height); + selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(lastBounds.Size.Width, 0)); + graphics.FillRectangle(highlighted ? highlightBrush : backBrush, lastBounds); + lastPoint = new(lastBounds.Location.X - 1, lastBounds.Location.Y + 1); + TextRenderer.DrawText(graphics, tagText, font, lastPoint, highlighted ? ColorTranslator.FromHtml("#FFFF99") : Enabled ? ColorTranslator.FromHtml("#696900") : ColorTranslator.FromHtml("#AAAA69")); - Size subSize = TextRenderer.MeasureText(graphics, subText, font); - Rectangle subBounds = new(tagBounds.X + tagBounds.Width - 4, bounds.Y, subSize.Width, bounds.Height); - graphics.FillRectangle(brush, subBounds); - Point subLocation = new(subBounds.Location.X - 1, subBounds.Location.Y + 1); - TextRenderer.DrawText(graphics, subText, font, subLocation, Color.LightSlateGray); + if (platform is not Platform.Paradox) + { + string subText = platformId.ToString(); + lastSize = TextRenderer.MeasureText(graphics, subText, font); + lastBounds = new(lastBounds.X + lastBounds.Width - 4, lastBounds.Y, lastSize.Width, lastBounds.Height); + selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(lastBounds.Size.Width - 4, 0)); + graphics.FillRectangle(highlighted ? highlightBrush : backBrush, lastBounds); + lastPoint = new(lastBounds.Location.X - 1, lastBounds.Location.Y + 1); + TextRenderer.DrawText(graphics, subText, font, lastPoint, highlighted ? ColorTranslator.FromHtml("#99FFFF") : Enabled ? ColorTranslator.FromHtml("#006969") : ColorTranslator.FromHtml("#69AAAA")); + } + + if (form is SelectForm) + { + ProgramSelection selection = ProgramSelection.FromPlatformId(platform, platformId); + if (selection is not null) + { + if (lastBounds == node.Bounds) + { + lastSize = new(4, 0); + lastBounds = new(lastBounds.X + lastBounds.Width, lastBounds.Y, lastSize.Width, lastBounds.Height); + graphics.FillRectangle(highlighted ? highlightBrush : backBrush, lastBounds); + } + + CheckBoxState checkBoxState = selection.Koaloader ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal; + lastSize = CheckBoxRenderer.GetGlyphSize(graphics, checkBoxState); + lastBounds = new(lastBounds.X + lastBounds.Width, lastBounds.Y, lastSize.Width, lastBounds.Height); + selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(lastBounds.Size.Width, 0)); + Rectangle checkBoxBounds = lastBounds; + graphics.FillRectangle(backBrush, lastBounds); + lastPoint = new(lastBounds.Left, lastBounds.Top + lastBounds.Height / 2 - lastSize.Height / 2 - 1); + CheckBoxRenderer.DrawCheckBox(graphics, lastPoint, checkBoxState); + + lastSize = TextRenderer.MeasureText(graphics, koaloaderToggleString, font); + int left = 1; + lastBounds = new(lastBounds.X + lastBounds.Width, lastBounds.Y, lastSize.Width + left, lastBounds.Height); + selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(lastBounds.Size.Width + left, 0)); + checkBoxBounds = new(checkBoxBounds.Location, checkBoxBounds.Size + new Size(lastBounds.Size.Width + left, 0)); + graphics.FillRectangle(backBrush, lastBounds); + lastPoint = new(lastBounds.Location.X - 1 + left, lastBounds.Location.Y + 1); + TextRenderer.DrawText(graphics, koaloaderToggleString, font, lastPoint, Enabled ? ColorTranslator.FromHtml("#006900") : ColorTranslator.FromHtml("#69AA69")); + + this.checkBoxBounds[selection] = RectangleToClient(checkBoxBounds); + } + } + + this.selectionBounds[node] = RectangleToClient(selectionBounds); + } + + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + Refresh(); + Point clickPoint = PointToClient(e.Location); + foreach (KeyValuePair pair in selectionBounds) + if (pair.Key.IsVisible && pair.Value.Contains(clickPoint)) + { + SelectedNode = pair.Key; + if (e.Button is MouseButtons.Right && FindForm() is SelectForm selectForm) + selectForm.OnNodeRightClick(pair.Key, e.Location); + break; + } + if (e.Button is MouseButtons.Left) + { + bool invalidate = false; + foreach (KeyValuePair pair in checkBoxBounds) + if (pair.Value.Contains(clickPoint)) + { + pair.Key.Koaloader = !pair.Key.Koaloader; + invalidate = true; + break; + } + if (invalidate) + { + Invalidate(); + if (FindForm() is SelectForm selectForm) + { + CheckBox koaloaderAllCheckBox = selectForm.KoaloaderAllCheckBox(); + koaloaderAllCheckBox.CheckedChanged -= selectForm.OnKoaloaderAllCheckBoxChanged; + koaloaderAllCheckBox.Checked = ProgramSelection.AllSafe.TrueForAll(selection => selection.Koaloader); + koaloaderAllCheckBox.CheckedChanged += selectForm.OnKoaloaderAllCheckBoxChanged; + } + } + } } } \ No newline at end of file diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index 821a133..7cb57a4 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -151,6 +151,7 @@ + diff --git a/CreamInstaller/Forms/InstallForm.cs b/CreamInstaller/Forms/InstallForm.cs index 2429471..b9ce438 100644 --- a/CreamInstaller/Forms/InstallForm.cs +++ b/CreamInstaller/Forms/InstallForm.cs @@ -50,7 +50,7 @@ internal partial class InstallForm : CustomForm { if (logTextBox.Text.Length > 0) logTextBox.AppendText(Environment.NewLine, color); logTextBox.AppendText(text, color); - logTextBox.Refresh(); + logTextBox.Invalidate(); }); } } @@ -63,6 +63,81 @@ internal partial class InstallForm : CustomForm UpdateUser($"Repairing Paradox Launcher . . . ", InstallationLog.Operation); _ = await Repair(this, selection); } + if (Uninstalling || !selection.Koaloader) + { + foreach (string directory in selection.ExecutableDirectories) + { + directory.GetKoaloaderComponents(out List proxies, out string config); + if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(Resources.Resources.ResourceIdentifier.Koaloader)) + || Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) + || File.Exists(config)) + { + UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + await Koaloader.Uninstall(directory, this); + } + } + } + bool uninstallProxy = Uninstalling || selection.Koaloader; + int count = selection.DllDirectories.Count, cur = 0; + foreach (string directory in selection.DllDirectories) + { + if (selection.Platform is Platform.Steam || selection.SelectedDlc.Any(d => d.Value.type is DlcType.Steam or DlcType.SteamHidden) + || selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.Steam or DlcType.SteamHidden))) + { + directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string cache); + if (!uninstallProxy && (File.Exists(api32) || File.Exists(api64)) + || uninstallProxy && (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache))) + { + UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" + + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + if (uninstallProxy) + await SmokeAPI.Uninstall(directory, this); + else + await SmokeAPI.Install(directory, selection, this); + } + } + if (selection.Platform is Platform.Epic || selection.SelectedDlc.Any(d => d.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement) + || selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement))) + { + directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + if (!uninstallProxy && (File.Exists(api32) || File.Exists(api64)) + || uninstallProxy && (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config))) + { + UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" + + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + if (uninstallProxy) + await ScreamAPI.Uninstall(directory, this); + else + await ScreamAPI.Install(directory, selection, this); + } + } + if (selection.Platform is Platform.Ubisoft) + { + directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + if (!uninstallProxy && (File.Exists(api32) || File.Exists(api64)) + || uninstallProxy && (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config))) + { + UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + if (uninstallProxy) + await UplayR1.Uninstall(directory, this); + else + await UplayR1.Install(directory, selection, this); + } + directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config); + if (!uninstallProxy && (File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api64)) + || uninstallProxy && (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config))) + { + UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + if (uninstallProxy) + await UplayR2.Uninstall(directory, this); + else + await UplayR2.Install(directory, selection, this); + } + } + UpdateProgress(++cur / count * 100); + } if (selection.Koaloader && !Uninstalling) { foreach (string directory in selection.ExecutableDirectories) @@ -71,79 +146,6 @@ internal partial class InstallForm : CustomForm await Koaloader.Install(directory, selection, this); } } - else - { - if (Uninstalling) - { - foreach (string directory in selection.ExecutableDirectories) - { - directory.GetKoaloaderComponents(out List proxies, out string config); - if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(Resources.Resources.ResourceIdentifier.Koaloader)) - || Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) - || File.Exists(config)) - { - UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - await Koaloader.Uninstall(directory, this); - } - } - } - int count = selection.DllDirectories.Count, cur = 0; - foreach (string directory in selection.DllDirectories) - { - if (selection.Platform is Platform.Steam || selection.SelectedDlc.Any(d => d.Value.type is DlcType.Steam or DlcType.SteamHidden) - || selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.Steam or DlcType.SteamHidden))) - { - directory.GetSmokeApiComponents(out _, out string api32_o, out _, out string api64_o, out string config, out string cache); - if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)) - { - UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} SmokeAPI" + - $" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - if (Uninstalling) - await SmokeAPI.Uninstall(directory, this); - else - await SmokeAPI.Install(directory, selection, this); - } - } - if (selection.Platform is Platform.Epic || selection.SelectedDlc.Any(d => d.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement) - || selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement))) - { - directory.GetScreamApiComponents(out _, out string api32_o, out _, out string api64_o, out string config); - if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config)) - { - UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} ScreamAPI" + - $" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - if (Uninstalling) - await ScreamAPI.Uninstall(directory, this); - else - await ScreamAPI.Install(directory, selection, this); - } - } - if (selection.Platform is Platform.Ubisoft) - { - directory.GetUplayR1Components(out _, out string api32_o, out _, out string api64_o, out string config); - if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config)) - { - UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + - $" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - if (Uninstalling) - await UplayR1.Uninstall(directory, this); - else - await UplayR1.Install(directory, selection, this); - } - directory.GetUplayR2Components(out _, out _, out _, out api32_o, out _, out api64_o, out config); - if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config)) - { - UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + - $" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - if (Uninstalling) - await UplayR2.Uninstall(directory, this); - else - await UplayR2.Install(directory, selection, this); - } - } - UpdateProgress(++cur / count * 100); - } - } UpdateProgress(100); } diff --git a/CreamInstaller/Forms/MainForm.cs b/CreamInstaller/Forms/MainForm.cs index 405f3dc..29c419f 100644 --- a/CreamInstaller/Forms/MainForm.cs +++ b/CreamInstaller/Forms/MainForm.cs @@ -56,7 +56,7 @@ internal partial class MainForm : CustomForm progressLabel.Text = "Checking for updates . . ."; changelogTreeView.Visible = false; changelogTreeView.Location = new(progressLabel.Location.X, progressLabel.Location.Y + progressLabel.Size.Height + 13); - Refresh(); + Invalidate(); GithubPackageResolver resolver = new("pointfeev", "CreamInstaller", "CreamInstaller.zip"); ZipPackageExtractor extractor = new(); @@ -181,7 +181,7 @@ internal partial class MainForm : CustomForm updateButton.Click -= OnUpdate; updateButton.Click += new(OnUpdateCancel); changelogTreeView.Location = new(progressBar.Location.X, progressBar.Location.Y + progressBar.Size.Height + 6); - Refresh(); + Invalidate(); Progress progress = new(); progress.ProgressChanged += new(delegate (object sender, double _progress) diff --git a/CreamInstaller/Forms/SelectDialogForm.Designer.cs b/CreamInstaller/Forms/SelectDialogForm.Designer.cs index 06f245c..b93ae13 100644 --- a/CreamInstaller/Forms/SelectDialogForm.Designer.cs +++ b/CreamInstaller/Forms/SelectDialogForm.Designer.cs @@ -53,7 +53,7 @@ namespace CreamInstaller this.acceptButton.Name = "acceptButton"; this.acceptButton.Padding = new System.Windows.Forms.Padding(12, 0, 12, 0); this.acceptButton.Size = new System.Drawing.Size(61, 24); - this.acceptButton.TabIndex = 1; + this.acceptButton.TabIndex = 6; this.acceptButton.Text = "OK"; this.acceptButton.UseVisualStyleBackColor = true; // @@ -108,7 +108,7 @@ namespace CreamInstaller this.allCheckBox.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0); this.allCheckBox.Name = "allCheckBox"; this.allCheckBox.Size = new System.Drawing.Size(34, 19); - this.allCheckBox.TabIndex = 2; + this.allCheckBox.TabIndex = 1; this.allCheckBox.Text = "All"; this.allCheckBox.CheckedChanged += new System.EventHandler(this.OnAllCheckBoxChanged); // @@ -121,7 +121,7 @@ namespace CreamInstaller this.sortCheckBox.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0); this.sortCheckBox.Name = "sortCheckBox"; this.sortCheckBox.Size = new System.Drawing.Size(104, 20); - this.sortCheckBox.TabIndex = 2; + this.sortCheckBox.TabIndex = 3; this.sortCheckBox.Text = "Sort By Name"; this.sortCheckBox.CheckedChanged += new System.EventHandler(this.OnSortCheckBoxChanged); // @@ -136,7 +136,7 @@ namespace CreamInstaller this.cancelButton.Name = "cancelButton"; this.cancelButton.Padding = new System.Windows.Forms.Padding(12, 0, 12, 0); this.cancelButton.Size = new System.Drawing.Size(81, 24); - this.cancelButton.TabIndex = 0; + this.cancelButton.TabIndex = 2; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; // @@ -151,7 +151,7 @@ namespace CreamInstaller this.loadButton.Name = "loadButton"; this.loadButton.Padding = new System.Windows.Forms.Padding(12, 0, 12, 0); this.loadButton.Size = new System.Drawing.Size(71, 24); - this.loadButton.TabIndex = 4; + this.loadButton.TabIndex = 5; this.loadButton.Text = "Load"; this.loadButton.UseVisualStyleBackColor = true; this.loadButton.Click += new System.EventHandler(this.OnLoad); @@ -167,7 +167,7 @@ namespace CreamInstaller this.saveButton.Name = "saveButton"; this.saveButton.Padding = new System.Windows.Forms.Padding(12, 0, 12, 0); this.saveButton.Size = new System.Drawing.Size(69, 24); - this.saveButton.TabIndex = 5; + this.saveButton.TabIndex = 4; this.saveButton.Text = "Save"; this.saveButton.UseVisualStyleBackColor = true; this.saveButton.Click += new System.EventHandler(this.OnSave); diff --git a/CreamInstaller/Forms/SelectForm.Designer.cs b/CreamInstaller/Forms/SelectForm.Designer.cs index 3910b75..dbcb9b5 100644 --- a/CreamInstaller/Forms/SelectForm.Designer.cs +++ b/CreamInstaller/Forms/SelectForm.Designer.cs @@ -31,10 +31,14 @@ namespace CreamInstaller /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); this.installButton = new System.Windows.Forms.Button(); this.cancelButton = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel(); + this.koaloaderAllCheckBox = new System.Windows.Forms.CheckBox(); + this.flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel(); this.noneFoundLabel = new System.Windows.Forms.Label(); this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.blockedGamesCheckBox = new System.Windows.Forms.CheckBox(); @@ -49,7 +53,9 @@ namespace CreamInstaller this.progressLabelGames = new System.Windows.Forms.Label(); this.progressLabelDLCs = new System.Windows.Forms.Label(); this.sortCheckBox = new System.Windows.Forms.CheckBox(); + this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.groupBox1.SuspendLayout(); + this.flowLayoutPanel4.SuspendLayout(); this.flowLayoutPanel1.SuspendLayout(); this.flowLayoutPanel2.SuspendLayout(); this.SuspendLayout(); @@ -65,7 +71,7 @@ namespace CreamInstaller this.installButton.Name = "installButton"; this.installButton.Padding = new System.Windows.Forms.Padding(12, 0, 12, 0); this.installButton.Size = new System.Drawing.Size(149, 24); - this.installButton.TabIndex = 10003; + this.installButton.TabIndex = 10004; this.installButton.Text = "Generate and Install"; this.installButton.UseVisualStyleBackColor = true; this.installButton.Click += new System.EventHandler(this.OnInstall); @@ -97,6 +103,8 @@ namespace CreamInstaller this.groupBox1.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.groupBox1.Controls.Add(this.flowLayoutPanel4); + this.groupBox1.Controls.Add(this.flowLayoutPanel3); this.groupBox1.Controls.Add(this.noneFoundLabel); this.groupBox1.Controls.Add(this.flowLayoutPanel1); this.groupBox1.Controls.Add(this.selectionTreeView); @@ -109,6 +117,46 @@ namespace CreamInstaller this.groupBox1.TabStop = false; this.groupBox1.Text = "Programs / Games"; // + // flowLayoutPanel4 + // + this.flowLayoutPanel4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.flowLayoutPanel4.AutoSize = true; + this.flowLayoutPanel4.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.flowLayoutPanel4.Controls.Add(this.koaloaderAllCheckBox); + this.flowLayoutPanel4.Location = new System.Drawing.Point(420, -1); + this.flowLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel4.Name = "flowLayoutPanel4"; + this.flowLayoutPanel4.Size = new System.Drawing.Size(75, 19); + this.flowLayoutPanel4.TabIndex = 10005; + this.flowLayoutPanel4.WrapContents = false; + // + // koaloaderAllCheckBox + // + this.koaloaderAllCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.koaloaderAllCheckBox.Checked = true; + this.koaloaderAllCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.koaloaderAllCheckBox.Enabled = false; + this.koaloaderAllCheckBox.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.koaloaderAllCheckBox.Location = new System.Drawing.Point(3, 0); + this.koaloaderAllCheckBox.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0); + this.koaloaderAllCheckBox.Name = "koaloaderAllCheckBox"; + this.koaloaderAllCheckBox.Size = new System.Drawing.Size(72, 19); + this.koaloaderAllCheckBox.TabIndex = 4; + this.koaloaderAllCheckBox.Text = "Koaloader"; + this.koaloaderAllCheckBox.CheckedChanged += new System.EventHandler(this.OnKoaloaderAllCheckBoxChanged); + // + // flowLayoutPanel3 + // + this.flowLayoutPanel3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.flowLayoutPanel3.AutoSize = true; + this.flowLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.flowLayoutPanel3.Location = new System.Drawing.Point(500, -1); + this.flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel3.Name = "flowLayoutPanel3"; + this.flowLayoutPanel3.Size = new System.Drawing.Size(0, 0); + this.flowLayoutPanel3.TabIndex = 1007; + this.flowLayoutPanel3.WrapContents = false; + // // noneFoundLabel // this.noneFoundLabel.Dock = System.Windows.Forms.DockStyle.Fill; @@ -127,15 +175,15 @@ namespace CreamInstaller this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.flowLayoutPanel1.Controls.Add(this.blockedGamesCheckBox); this.flowLayoutPanel1.Controls.Add(this.blockProtectedHelpButton); - this.flowLayoutPanel1.Location = new System.Drawing.Point(224, -1); + this.flowLayoutPanel1.Location = new System.Drawing.Point(124, -1); this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.Size = new System.Drawing.Size(179, 20); + this.flowLayoutPanel1.Size = new System.Drawing.Size(165, 20); this.flowLayoutPanel1.TabIndex = 1005; + this.flowLayoutPanel1.WrapContents = false; // // blockedGamesCheckBox // - this.blockedGamesCheckBox.AutoSize = true; this.blockedGamesCheckBox.Checked = true; this.blockedGamesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; this.blockedGamesCheckBox.Enabled = false; @@ -143,8 +191,8 @@ namespace CreamInstaller this.blockedGamesCheckBox.Location = new System.Drawing.Point(3, 0); this.blockedGamesCheckBox.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0); this.blockedGamesCheckBox.Name = "blockedGamesCheckBox"; - this.blockedGamesCheckBox.Size = new System.Drawing.Size(154, 20); - this.blockedGamesCheckBox.TabIndex = 1003; + this.blockedGamesCheckBox.Size = new System.Drawing.Size(140, 20); + this.blockedGamesCheckBox.TabIndex = 1; this.blockedGamesCheckBox.Text = "Block Protected Games"; this.blockedGamesCheckBox.UseVisualStyleBackColor = true; this.blockedGamesCheckBox.CheckedChanged += new System.EventHandler(this.OnBlockProtectedGamesCheckBoxChanged); @@ -154,11 +202,11 @@ namespace CreamInstaller this.blockProtectedHelpButton.Enabled = false; this.blockProtectedHelpButton.FlatStyle = System.Windows.Forms.FlatStyle.System; this.blockProtectedHelpButton.Font = new System.Drawing.Font("Segoe UI", 7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.blockProtectedHelpButton.Location = new System.Drawing.Point(157, 0); + this.blockProtectedHelpButton.Location = new System.Drawing.Point(143, 0); this.blockProtectedHelpButton.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); this.blockProtectedHelpButton.Name = "blockProtectedHelpButton"; this.blockProtectedHelpButton.Size = new System.Drawing.Size(19, 19); - this.blockProtectedHelpButton.TabIndex = 1004; + this.blockProtectedHelpButton.TabIndex = 2; this.blockProtectedHelpButton.Text = "?"; this.blockProtectedHelpButton.UseVisualStyleBackColor = true; this.blockProtectedHelpButton.Click += new System.EventHandler(this.OnBlockProtectedGamesHelpButtonClicked); @@ -184,11 +232,12 @@ namespace CreamInstaller this.flowLayoutPanel2.AutoSize = true; this.flowLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.flowLayoutPanel2.Controls.Add(this.allCheckBox); - this.flowLayoutPanel2.Location = new System.Drawing.Point(517, -1); + this.flowLayoutPanel2.Location = new System.Drawing.Point(515, -1); this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); this.flowLayoutPanel2.Name = "flowLayoutPanel2"; this.flowLayoutPanel2.Size = new System.Drawing.Size(37, 19); this.flowLayoutPanel2.TabIndex = 1006; + this.flowLayoutPanel2.WrapContents = false; // // allCheckBox // @@ -201,7 +250,7 @@ namespace CreamInstaller this.allCheckBox.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0); this.allCheckBox.Name = "allCheckBox"; this.allCheckBox.Size = new System.Drawing.Size(34, 19); - this.allCheckBox.TabIndex = 1; + this.allCheckBox.TabIndex = 4; this.allCheckBox.Text = "All"; this.allCheckBox.CheckedChanged += new System.EventHandler(this.OnAllCheckBoxChanged); // @@ -235,7 +284,7 @@ namespace CreamInstaller this.scanButton.Name = "scanButton"; this.scanButton.Padding = new System.Windows.Forms.Padding(12, 0, 12, 0); this.scanButton.Size = new System.Drawing.Size(82, 24); - this.scanButton.TabIndex = 10001; + this.scanButton.TabIndex = 10002; this.scanButton.Text = "Rescan"; this.scanButton.UseVisualStyleBackColor = true; this.scanButton.Click += new System.EventHandler(this.OnScan); @@ -251,7 +300,7 @@ namespace CreamInstaller this.uninstallButton.Name = "uninstallButton"; this.uninstallButton.Padding = new System.Windows.Forms.Padding(12, 0, 12, 0); this.uninstallButton.Size = new System.Drawing.Size(91, 24); - this.uninstallButton.TabIndex = 10002; + this.uninstallButton.TabIndex = 10003; this.uninstallButton.Text = "Uninstall"; this.uninstallButton.UseVisualStyleBackColor = true; this.uninstallButton.Click += new System.EventHandler(this.OnUninstall); @@ -275,7 +324,7 @@ namespace CreamInstaller this.progressLabelDLCs.Location = new System.Drawing.Point(12, 281); this.progressLabelDLCs.Name = "progressLabelDLCs"; this.progressLabelDLCs.Size = new System.Drawing.Size(560, 12); - this.progressLabelDLCs.TabIndex = 10004; + this.progressLabelDLCs.TabIndex = 12; this.progressLabelDLCs.Text = "Remaining DLC (2): 123456, 654321"; // // sortCheckBox @@ -287,10 +336,19 @@ namespace CreamInstaller this.sortCheckBox.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0); this.sortCheckBox.Name = "sortCheckBox"; this.sortCheckBox.Size = new System.Drawing.Size(104, 20); - this.sortCheckBox.TabIndex = 1; + this.sortCheckBox.TabIndex = 10001; this.sortCheckBox.Text = "Sort By Name"; this.sortCheckBox.CheckedChanged += new System.EventHandler(this.OnSortCheckBoxChanged); // + // contextMenuStrip + // + this.contextMenuStrip.AllowMerge = false; + this.contextMenuStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow; + this.contextMenuStrip.Name = "contextMenuStrip"; + this.contextMenuStrip.ShowItemToolTips = false; + this.contextMenuStrip.Size = new System.Drawing.Size(181, 26); + this.contextMenuStrip.TabStop = true; + // // SelectForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); @@ -319,8 +377,8 @@ namespace CreamInstaller this.Load += new System.EventHandler(this.OnLoad); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); + this.flowLayoutPanel4.ResumeLayout(false); this.flowLayoutPanel1.ResumeLayout(false); - this.flowLayoutPanel1.PerformLayout(); this.flowLayoutPanel2.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -338,7 +396,7 @@ namespace CreamInstaller private System.Windows.Forms.CheckBox allCheckBox; private Button scanButton; private Label noneFoundLabel; - private CreamInstaller.Components.CustomTreeView selectionTreeView; + private Components.CustomTreeView selectionTreeView; private CheckBox blockedGamesCheckBox; private Button blockProtectedHelpButton; private FlowLayoutPanel flowLayoutPanel1; @@ -347,6 +405,10 @@ namespace CreamInstaller private Label progressLabelGames; private Label progressLabelDLCs; private CheckBox sortCheckBox; + private FlowLayoutPanel flowLayoutPanel3; + private ContextMenuStrip contextMenuStrip; + private FlowLayoutPanel flowLayoutPanel4; + private CheckBox koaloaderAllCheckBox; } } diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 1e1191e..cf0ee38 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -31,10 +31,10 @@ internal partial class SelectForm : CustomForm Text = Program.ApplicationName; } - private static void UpdateRemaining(Label label, List list, string descriptor) => + private static void UpdateRemaining(Label label, SynchronizedCollection list, string descriptor) => label.Text = list.Any() ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") : ""; - private readonly List RemainingGames = new(); + private readonly SynchronizedCollection RemainingGames = new(); private void UpdateRemainingGames() => UpdateRemaining(progressLabelGames, RemainingGames, "games"); private void AddToRemainingGames(string gameName) { @@ -53,13 +53,12 @@ internal partial class SelectForm : CustomForm Program.Invoke(progressLabelGames, delegate { if (Program.Canceled) return; - if (RemainingGames.Contains(gameName)) - _ = RemainingGames.Remove(gameName); + RemainingGames.Remove(gameName); UpdateRemainingGames(); }); } - private readonly List RemainingDLCs = new(); + private readonly SynchronizedCollection RemainingDLCs = new(); private void UpdateRemainingDLCs() => UpdateRemaining(progressLabelDLCs, RemainingDLCs, "DLCs"); private void AddToRemainingDLCs(string dlcId) { @@ -78,8 +77,7 @@ internal partial class SelectForm : CustomForm Program.Invoke(progressLabelDLCs, delegate { if (Program.Canceled) return; - if (RemainingDLCs.Contains(dlcId)) - _ = RemainingDLCs.Remove(dlcId); + RemainingDLCs.Remove(dlcId); UpdateRemainingDLCs(); }); } @@ -92,13 +90,13 @@ internal partial class SelectForm : CustomForm void AddToRemainingGames(string gameName) { this.AddToRemainingGames(gameName); - progress.Report(-++TotalGameCount); + progress.Report(-Interlocked.Increment(ref TotalGameCount)); progress.Report(CompleteGameCount); } void RemoveFromRemainingGames(string gameName) { this.RemoveFromRemainingGames(gameName); - progress.Report(++CompleteGameCount); + progress.Report(Interlocked.Increment(ref CompleteGameCount)); } if (Program.Canceled) return; List treeNodes = TreeNodes; @@ -119,6 +117,7 @@ internal partial class SelectForm : CustomForm ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL"); selection ??= new(); if (allCheckBox.Checked) selection.Enabled = true; + if (koaloaderAllCheckBox.Checked) selection.Koaloader = true; selection.Id = "PL"; selection.Name = "Paradox Launcher"; selection.RootDirectory = ParadoxLauncher.InstallPath; @@ -135,17 +134,17 @@ internal partial class SelectForm : CustomForm _ = selectionTreeView.Nodes.Add(programNode); } } - int totalGames = 0, gamesChecked = 0; + int steamGamesToCheck; if (ProgramsToScan.Any(c => c.platform is Platform.Steam)) { List<(string appId, string name, string branch, int buildId, string gameDirectory)> steamGames = await SteamLibrary.GetGames(); - totalGames = steamGames.Count; + steamGamesToCheck = steamGames.Count; foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in steamGames) { if (Program.Canceled) return; if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Steam && c.id == appId)) { - gamesChecked++; + Interlocked.Decrement(ref steamGamesToCheck); continue; } AddToRemainingGames(name); @@ -155,12 +154,12 @@ internal partial class SelectForm : CustomForm List dllDirectories = await SteamLibrary.GetDllDirectoriesFromGameDirectory(gameDirectory); if (dllDirectories is null) { - gamesChecked++; + Interlocked.Decrement(ref steamGamesToCheck); RemoveFromRemainingGames(name); return; } AppData appData = await SteamStore.QueryStoreAPI(appId); - gamesChecked++; + Interlocked.Decrement(ref steamGamesToCheck); VProperty appInfo = await SteamCMD.GetAppInfo(appId, branch, buildId); if (appData is null && appInfo is null) { @@ -183,8 +182,8 @@ internal partial class SelectForm : CustomForm { if (Program.Canceled) return; do // give games steam store api limit priority - Thread.Sleep(100); - while (!Program.Canceled && gamesChecked < totalGames); + Thread.Sleep(200); + while (!Program.Canceled && steamGamesToCheck > 0); if (Program.Canceled) return; string dlcName = null; string dlcIcon = null; @@ -228,9 +227,11 @@ internal partial class SelectForm : CustomForm if (Program.Canceled) return; await task; } + steamGamesToCheck = 0; ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Steam, appId) ?? new(); selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); + if (koaloaderAllCheckBox.Checked) selection.Koaloader = true; selection.Id = appId; selection.Name = appData?.name ?? name; selection.RootDirectory = gameDirectory; @@ -338,6 +339,7 @@ internal partial class SelectForm : CustomForm ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Epic, @namespace) ?? new(); selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); + if (koaloaderAllCheckBox.Checked) selection.Koaloader = true; selection.Id = @namespace; selection.Name = name; selection.RootDirectory = directory; @@ -424,6 +426,7 @@ internal partial class SelectForm : CustomForm ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Ubisoft, gameId) ?? new(); selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); + if (koaloaderAllCheckBox.Checked) selection.Koaloader = true; selection.Id = gameId; selection.Name = name; selection.RootDirectory = gameDirectory; @@ -454,7 +457,7 @@ internal partial class SelectForm : CustomForm if (Program.Canceled) return; await task; } - gamesChecked = totalGames; + steamGamesToCheck = 0; } private List<(Platform platform, string id, string name)> ProgramsToScan; @@ -467,6 +470,7 @@ internal partial class SelectForm : CustomForm scanButton.Enabled = false; noneFoundLabel.Visible = false; allCheckBox.Enabled = false; + koaloaderAllCheckBox.Enabled = false; installButton.Enabled = false; uninstallButton.Enabled = installButton.Enabled; selectionTreeView.Enabled = false; @@ -540,6 +544,7 @@ internal partial class SelectForm : CustomForm HideProgressBar(); selectionTreeView.Enabled = ProgramSelection.All.Any(); allCheckBox.Enabled = selectionTreeView.Enabled; + koaloaderAllCheckBox.Enabled = selectionTreeView.Enabled; noneFoundLabel.Visible = !selectionTreeView.Enabled; installButton.Enabled = ProgramSelection.AllEnabled.Any(); uninstallButton.Enabled = installButton.Enabled; @@ -644,6 +649,165 @@ internal partial class SelectForm : CustomForm + progressBar.Size.Height); } + internal void OnNodeRightClick(TreeNode node, Point location) + { + contextMenuStrip.Items.Clear(); + string id = node.Name; + Platform platform = (Platform)node.Tag; + ProgramSelection selection = ProgramSelection.FromPlatformId(platform, id); + (string gameAppId, (DlcType type, string name, string icon) app)? dlc = null; + if (selection is null) + dlc = ProgramSelection.GetDlcFromPlatformId(platform, id); + ProgramSelection dlcParentSelection = null; + if (dlc is not null) + dlcParentSelection = ProgramSelection.FromPlatformId(platform, dlc.Value.gameAppId); + if (selection is null && dlcParentSelection is null) + return; + ContextMenuItem header = null; + if (id == "PL") + header = new(node.Text, "Paradox Launcher"); + else if (selection is not null) + header = new(node.Text, (id, selection.IconUrl)); + else if (dlc is not null && dlcParentSelection is not null) + header = new(node.Text, (id, dlc.Value.app.icon), (id, dlcParentSelection.IconUrl)); + contextMenuStrip.Items.Add(header ?? new ContextMenuItem(node.Text)); + string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf"; + string appInfoJSON = $@"{SteamCMD.AppInfoPath}\{id}.json"; + string cooldown = $@"{ProgramData.CooldownPath}\{id}.txt"; + if ((File.Exists(appInfoVDF) || File.Exists(appInfoJSON)) && (selection is not null || dlc is not null)) + { + List queries = new(); + if (File.Exists(appInfoJSON)) + { + string platformString = (selection is null || selection.Platform is Platform.Steam) ? "Steam Store " + : selection.Platform is Platform.Epic ? "Epic GraphQL " : ""; + queries.Add(new ContextMenuItem($"Open {platformString}Query", "Notepad", + new EventHandler((sender, e) => Diagnostics.OpenFileInNotepad(appInfoJSON)))); + } + if (File.Exists(appInfoVDF)) + queries.Add(new ContextMenuItem("Open SteamCMD Query", "Notepad", + new EventHandler((sender, e) => Diagnostics.OpenFileInNotepad(appInfoVDF)))); + if (queries.Any()) + { + contextMenuStrip.Items.Add(new ToolStripSeparator()); + foreach (ContextMenuItem query in queries) + contextMenuStrip.Items.Add(query); + contextMenuStrip.Items.Add(new ContextMenuItem("Refresh Queries", "Command Prompt", + new EventHandler((sender, e) => + { + try + { + File.Delete(appInfoVDF); + } + catch { } + try + { + File.Delete(appInfoJSON); + } + catch { } + try + { + File.Delete(cooldown); + } + catch { } + OnLoad(forceScan: true); + }))); + } + } + if (selection is not null) + { + if (id == "PL") + { + contextMenuStrip.Items.Add(new ToolStripSeparator()); + contextMenuStrip.Items.Add(new ContextMenuItem("Repair", "Command Prompt", + new EventHandler(async (sender, e) => await ParadoxLauncher.Repair(this, selection)))); + } + contextMenuStrip.Items.Add(new ToolStripSeparator()); + contextMenuStrip.Items.Add(new ContextMenuItem("Open Root Directory", "File Explorer", + new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory)))); + List directories = selection.ExecutableDirectories.ToList(); + int executables = 0; + foreach (string directory in directories) + { + contextMenuStrip.Items.Add(new ContextMenuItem($"Open Executable Directory #{++executables}", "File Explorer", + new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + } + directories = selection.DllDirectories.ToList(); + int steam = 0, epic = 0, r1 = 0, r2 = 0; + if (selection.Platform is Platform.Steam or Platform.Paradox) + foreach (string directory in directories) + { + directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string cache); + if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)) + contextMenuStrip.Items.Add(new ContextMenuItem($"Open Steamworks Directory #{++steam}", "File Explorer", + new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + } + if (selection.Platform is Platform.Epic or Platform.Paradox) + foreach (string directory in directories) + { + directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) + contextMenuStrip.Items.Add(new ContextMenuItem($"Open Epic Online Services Directory #{++epic}", "File Explorer", + new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + } + if (selection.Platform is Platform.Ubisoft) + foreach (string directory in directories) + { + directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) + contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R1 Directory #{++r1}", "File Explorer", + new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config); + if (File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) + contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R2 Directory #{++r2}", "File Explorer", + new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + } + } + if (id != "PL") + { + if (selection is not null && selection.Platform is Platform.Steam + || dlcParentSelection is not null && dlcParentSelection.Platform is Platform.Steam) + { + contextMenuStrip.Items.Add(new ToolStripSeparator()); + contextMenuStrip.Items.Add(new ContextMenuItem("Open SteamDB", "SteamDB", + new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamdb.info/app/" + id)))); + } + if (selection is not null) + { + if (selection.Platform is Platform.Steam) + { + contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Store", "Steam Store", + new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); + contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), "Steam Community", + new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id)))); + } + if (selection.Platform is Platform.Epic) + { + contextMenuStrip.Items.Add(new ToolStripSeparator()); + contextMenuStrip.Items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB", + new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://scream-db.web.app/offers/" + id)))); + contextMenuStrip.Items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games", + new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); + } + if (selection.Platform is Platform.Ubisoft) + { + contextMenuStrip.Items.Add(new ToolStripSeparator()); +#pragma warning disable CA1308 // Normalize strings to uppercase + contextMenuStrip.Items.Add(new ContextMenuItem("Open Ubisoft Store", "Ubisoft Store", + new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://store.ubi.com/us/" + selection.Name.Replace(" ", "-").ToLowerInvariant())))); +#pragma warning restore CA1308 // Normalize strings to uppercase + } + } + } + if (selection is not null && selection.WebsiteUrl is not null) + { + contextMenuStrip.Items.Add(new ContextMenuItem("Open Official Website", ("Web_" + id, IconGrabber.GetDomainFaviconUrl(selection.WebsiteUrl)), + new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.WebsiteUrl)))); + } + contextMenuStrip.Show(selectionTreeView, location); + contextMenuStrip.Refresh(); + } + private void OnLoad(object sender, EventArgs _) { retry: @@ -651,161 +815,6 @@ internal partial class SelectForm : CustomForm { HideProgressBar(); selectionTreeView.AfterCheck += OnTreeViewNodeCheckedChanged; - selectionTreeView.NodeMouseClick += (sender, e) => - { - TreeNode node = e.Node; - if (node is null || !node.Bounds.Contains(e.Location) || e.Button != MouseButtons.Right || e.Clicks != 1) - return; - ContextMenuStrip contextMenuStrip = new(); - selectionTreeView.SelectedNode = node; - string id = node.Name; - Platform platform = (Platform)node.Tag; - ProgramSelection selection = ProgramSelection.FromPlatformId(platform, id); - (string gameAppId, (DlcType type, string name, string icon) app)? dlc = null; - if (selection is null) - dlc = ProgramSelection.GetDlcFromPlatformId(platform, id); - ProgramSelection dlcParentSelection = null; - if (dlc is not null) - dlcParentSelection = ProgramSelection.FromPlatformId(platform, dlc.Value.gameAppId); - if (selection is null && dlcParentSelection is null) - return; - ContextMenuItem header = null; - if (id == "PL") - header = new(node.Text, "Paradox Launcher"); - else if (selection is not null) - header = new(node.Text, (id, selection.IconUrl)); - else if (dlc is not null && dlcParentSelection is not null) - header = new(node.Text, (id, dlc.Value.app.icon), (id, dlcParentSelection.IconUrl)); - contextMenuStrip.Items.Add(header ?? new ContextMenuItem(node.Text)); - string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf"; - string appInfoJSON = $@"{SteamCMD.AppInfoPath}\{id}.json"; - string cooldown = $@"{ProgramData.CooldownPath}\{id}.txt"; - if ((File.Exists(appInfoVDF) || File.Exists(appInfoJSON)) && (selection is not null || dlc is not null)) - { - List queries = new(); - if (File.Exists(appInfoJSON)) - { - string platformString = (selection is null || selection.Platform is Platform.Steam) ? "Steam Store " - : selection.Platform is Platform.Epic ? "Epic GraphQL " : ""; - queries.Add(new ContextMenuItem($"Open {platformString}Query", "Notepad", - new EventHandler((sender, e) => Diagnostics.OpenFileInNotepad(appInfoJSON)))); - } - if (File.Exists(appInfoVDF)) - queries.Add(new ContextMenuItem("Open SteamCMD Query", "Notepad", - new EventHandler((sender, e) => Diagnostics.OpenFileInNotepad(appInfoVDF)))); - if (queries.Any()) - { - contextMenuStrip.Items.Add(new ToolStripSeparator()); - foreach (ContextMenuItem query in queries) - contextMenuStrip.Items.Add(query); - contextMenuStrip.Items.Add(new ContextMenuItem("Refresh Queries", "Command Prompt", - new EventHandler((sender, e) => - { - try - { - File.Delete(appInfoVDF); - } - catch { } - try - { - File.Delete(appInfoJSON); - } - catch { } - try - { - File.Delete(cooldown); - } - catch { } - OnLoad(forceScan: true); - }))); - } - } - if (selection is not null) - { - if (id == "PL") - { - contextMenuStrip.Items.Add(new ToolStripSeparator()); - contextMenuStrip.Items.Add(new ContextMenuItem("Repair", "Command Prompt", - new EventHandler(async (sender, e) => await ParadoxLauncher.Repair(this, selection)))); - } - contextMenuStrip.Items.Add(new ToolStripSeparator()); - contextMenuStrip.Items.Add(new ContextMenuItem("Open Root Directory", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory)))); - List directories = selection.DllDirectories.ToList(); - int steam = 0, epic = 0, r1 = 0, r2 = 0; - if (selection.Platform is Platform.Steam or Platform.Paradox) - foreach (string directory in directories) - { - directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string cache); - if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)) - contextMenuStrip.Items.Add(new ContextMenuItem($"Open Steamworks Directory #{++steam}", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); - } - if (selection.Platform is Platform.Epic or Platform.Paradox) - foreach (string directory in directories) - { - directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); - if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) - contextMenuStrip.Items.Add(new ContextMenuItem($"Open Epic Online Services Directory #{++epic}", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); - } - if (selection.Platform is Platform.Ubisoft) - foreach (string directory in directories) - { - directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config); - if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) - contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R1 Directory #{++r1}", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); - directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config); - if (File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) - contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R2 Directory #{++r2}", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); - } - } - if (id != "PL") - { - if (selection is not null && selection.Platform is Platform.Steam - || dlcParentSelection is not null && dlcParentSelection.Platform is Platform.Steam) - { - contextMenuStrip.Items.Add(new ToolStripSeparator()); - contextMenuStrip.Items.Add(new ContextMenuItem("Open SteamDB", "SteamDB", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamdb.info/app/" + id)))); - } - if (selection is not null) - { - if (selection.Platform is Platform.Steam) - { - contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Store", "Steam Store", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); - contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), "Steam Community", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id)))); - } - if (selection.Platform is Platform.Epic) - { - contextMenuStrip.Items.Add(new ToolStripSeparator()); - contextMenuStrip.Items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://scream-db.web.app/offers/" + id)))); - contextMenuStrip.Items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); - } - if (selection.Platform is Platform.Ubisoft) - { - contextMenuStrip.Items.Add(new ToolStripSeparator()); -#pragma warning disable CA1308 // Normalize strings to uppercase - contextMenuStrip.Items.Add(new ContextMenuItem("Open Ubisoft Store", "Ubisoft Store", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://store.ubi.com/us/" + selection.Name.Replace(" ", "-").ToLowerInvariant())))); -#pragma warning restore CA1308 // Normalize strings to uppercase - - } - } - } - if (selection is not null && selection.WebsiteUrl is not null) - { - contextMenuStrip.Items.Add(new ContextMenuItem("Open Official Website", ("Web_" + id, IconGrabber.GetDomainFaviconUrl(selection.WebsiteUrl)), - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.WebsiteUrl)))); - } - contextMenuStrip.Show(selectionTreeView, e.Location); - }; OnLoad(forceProvideChoices: true); } catch (Exception e) @@ -850,19 +859,39 @@ internal partial class SelectForm : CustomForm private void OnAllCheckBoxChanged(object sender, EventArgs e) { bool shouldCheck = false; - TreeNodes.ForEach(node => - { - if (node.Parent is null) + foreach (TreeNode node in TreeNodes) + if (node.Parent is null && !node.Checked) { - if (!node.Checked) shouldCheck = true; - if (node.Checked != shouldCheck) - { - node.Checked = shouldCheck; - OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse)); - } + shouldCheck = true; + break; } - }); + foreach (TreeNode node in TreeNodes) + if (node.Parent is null && node.Checked != shouldCheck) + { + node.Checked = shouldCheck; + OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse)); + } + allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; allCheckBox.Checked = shouldCheck; + allCheckBox.CheckedChanged += OnAllCheckBoxChanged; + } + + internal CheckBox KoaloaderAllCheckBox() => koaloaderAllCheckBox; + internal void OnKoaloaderAllCheckBoxChanged(object sender, EventArgs e) + { + bool shouldCheck = false; + foreach (ProgramSelection selection in ProgramSelection.AllSafe) + if (!selection.Koaloader) + { + shouldCheck = true; + break; + } + foreach (ProgramSelection selection in ProgramSelection.AllSafe) + selection.Koaloader = shouldCheck; + selectionTreeView.Invalidate(); + koaloaderAllCheckBox.CheckedChanged -= OnKoaloaderAllCheckBoxChanged; + koaloaderAllCheckBox.Checked = shouldCheck; + koaloaderAllCheckBox.CheckedChanged += OnKoaloaderAllCheckBoxChanged; } private void OnBlockProtectedGamesCheckBoxChanged(object sender, EventArgs e) diff --git a/CreamInstaller/Forms/SelectForm.resx b/CreamInstaller/Forms/SelectForm.resx index f298a7b..39d5bcf 100644 --- a/CreamInstaller/Forms/SelectForm.resx +++ b/CreamInstaller/Forms/SelectForm.resx @@ -57,4 +57,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 964f954..3ebde3e 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -27,7 +27,8 @@ public enum DlcType internal class ProgramSelection { internal bool Enabled; - internal bool Koaloader = true; + internal bool Koaloader; + internal string KoaloaderProxy = "Koaloader.version_64.version.dll"; internal Platform Platform; internal string Id = "0"; diff --git a/CreamInstaller/Resources/Koaloader.cs b/CreamInstaller/Resources/Koaloader.cs index a8f4687..3ba428c 100644 --- a/CreamInstaller/Resources/Koaloader.cs +++ b/CreamInstaller/Resources/Koaloader.cs @@ -34,6 +34,29 @@ internal static class Koaloader ("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll") }; + internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) + { + directory.GetKoaloaderComponents(out _, out string config); + SortedList targets = new(PlatformIdComparer.String); + SortedList modules = new(PlatformIdComparer.String); + if (targets.Any() || modules.Any()) + { + if (installForm is not null) + installForm.UpdateUser("Generating Koaloader configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + File.Create(config).Close(); + StreamWriter writer = new(config, true, Encoding.UTF8); + WriteConfig(writer, targets, modules, installForm); + writer.Flush(); + writer.Close(); + } + else if (File.Exists(config)) + { + File.Delete(config); + if (installForm is not null) + installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); + } + } + internal static void WriteConfig(StreamWriter writer, SortedList targets, SortedList modules, InstallForm installForm = null) { writer.WriteLine("{"); @@ -76,7 +99,7 @@ internal static class Koaloader writer.WriteLine("}"); } - internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(() => + internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(async () => { directory.GetKoaloaderComponents(out List proxies, out string config); foreach (string proxy in proxies.Where(proxy => File.Exists(proxy) && proxy.IsResourceFile(Resources.ResourceIdentifier.Koaloader))) @@ -99,13 +122,20 @@ internal static class Koaloader if (installForm is not null) installForm.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); } + await SmokeAPI.Uninstall(directory, installForm, deleteConfig); + await ScreamAPI.Uninstall(directory, installForm, deleteConfig); + await UplayR1.Uninstall(directory, installForm, deleteConfig); + await UplayR2.Uninstall(directory, installForm, deleteConfig); }); internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() => { directory.GetKoaloaderComponents(out List proxies, out string config); - string path = directory + @"\version.dll"; - "Koaloader.version_64.version.dll".Write(path); + string proxy = selection.KoaloaderProxy; + proxy = proxy[(proxy.IndexOf('.') + 1)..]; + proxy = proxy[(proxy.IndexOf('.') + 1)..]; + string path = directory + @"\" + proxy; + selection.KoaloaderProxy.Write(path); if (installForm is not null) installForm.UpdateUser($"Wrote Koaloader: {Path.GetFileName(path)}", InstallationLog.Action, info: false); if (selection.Platform is Platform.Steam or Platform.Paradox) @@ -133,6 +163,8 @@ internal static class Koaloader if (did32 && did64) break; } + if (did32 || did64) + SmokeAPI.CheckConfig(directory, selection, installForm); } if (selection.Platform is Platform.Epic or Platform.Paradox) { @@ -159,6 +191,8 @@ internal static class Koaloader if (did32 && did64) break; } + if (did32 || did64) + ScreamAPI.CheckConfig(directory, selection, installForm); } if (selection.Platform is Platform.Ubisoft) { @@ -202,27 +236,12 @@ internal static class Koaloader if (did32r1 && did64r1 && did32r2 && did64r2) break; } + if (did32r1 || did64r1) + UplayR1.CheckConfig(directory, selection, installForm); + if (did32r2 || did64r2) + UplayR2.CheckConfig(directory, selection, installForm); } if (generateConfig) - { - SortedList targets = new(PlatformIdComparer.String); - SortedList modules = new(PlatformIdComparer.String); - if (targets.Any() || modules.Any()) - { - if (installForm is not null) - installForm.UpdateUser("Generating Koaloader configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - File.Create(config).Close(); - StreamWriter writer = new(config, true, Encoding.UTF8); - WriteConfig(writer, targets, modules, installForm); - writer.Flush(); - writer.Close(); - } - else if (File.Exists(config)) - { - File.Delete(config); - if (installForm is not null) - installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); - } - } + CheckConfig(directory, selection, installForm); }); } diff --git a/CreamInstaller/Resources/ScreamAPI.cs b/CreamInstaller/Resources/ScreamAPI.cs index 7800545..886f82f 100644 --- a/CreamInstaller/Resources/ScreamAPI.cs +++ b/CreamInstaller/Resources/ScreamAPI.cs @@ -25,6 +25,36 @@ internal static class ScreamAPI config = directory + @"\ScreamAPI.json"; } + internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) + { + directory.GetScreamApiComponents(out _, out _, out _, out _, out string config); + IEnumerable> overrideCatalogItems = selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + overrideCatalogItems = overrideCatalogItems.Except(extraDlc); + IEnumerable> entitlements = selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement); + foreach ((string id, string name, SortedList _dlc) in selection.ExtraSelectedDlc) + entitlements = entitlements.Concat(_dlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement)); + if (overrideCatalogItems.Any() || entitlements.Any()) + { + if (installForm is not null) + installForm.UpdateUser("Generating ScreamAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + File.Create(config).Close(); + StreamWriter writer = new(config, true, Encoding.UTF8); + WriteConfig(writer, + new(overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + new(entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + installForm); + writer.Flush(); + writer.Close(); + } + else if (File.Exists(config)) + { + File.Delete(config); + if (installForm is not null) + installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); + } + } + internal static void WriteConfig(StreamWriter writer, SortedList overrideCatalogItems, SortedList entitlements, InstallForm installForm = null) { writer.WriteLine("{"); @@ -137,32 +167,6 @@ internal static class ScreamAPI installForm.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api64)}", InstallationLog.Action, info: false); } if (generateConfig) - { - IEnumerable> overrideCatalogItems = selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) - overrideCatalogItems = overrideCatalogItems.Except(extraDlc); - IEnumerable> entitlements = selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement); - foreach ((string id, string name, SortedList _dlc) in selection.ExtraSelectedDlc) - entitlements = entitlements.Concat(_dlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement)); - if (overrideCatalogItems.Any() || entitlements.Any()) - { - if (installForm is not null) - installForm.UpdateUser("Generating ScreamAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - File.Create(config).Close(); - StreamWriter writer = new(config, true, Encoding.UTF8); - WriteConfig(writer, - new(overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), - new(entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), - installForm); - writer.Flush(); - writer.Close(); - } - else if (File.Exists(config)) - { - File.Delete(config); - if (installForm is not null) - installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); - } - } + CheckConfig(directory, selection, installForm); }); } diff --git a/CreamInstaller/Resources/SmokeAPI.cs b/CreamInstaller/Resources/SmokeAPI.cs index e7a4206..eb58af7 100644 --- a/CreamInstaller/Resources/SmokeAPI.cs +++ b/CreamInstaller/Resources/SmokeAPI.cs @@ -26,6 +26,41 @@ internal static class SmokeAPI cache = directory + @"\SmokeAPI.cache.json"; } + internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) + { + directory.GetSmokeApiComponents(out _, out _, out _, out _, out string config, out _); + IEnumerable> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + overrideDlc = overrideDlc.Except(extraDlc); + IEnumerable> injectDlc = new List>(); + if (selection.AllDlc.Count > 64 || selection.ExtraDlc.Any(e => e.dlc.Count > 64)) + { + injectDlc = injectDlc.Concat(selection.SelectedDlc.Where(pair => pair.Value.type is DlcType.SteamHidden)); + foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + if (selection.ExtraDlc.Where(e => e.id == id).Single().dlc.Count > 64) + injectDlc = injectDlc.Concat(extraDlc.Where(pair => pair.Value.type is DlcType.SteamHidden)); + } + if (overrideDlc.Any() || injectDlc.Any()) + { + if (installForm is not null) + installForm.UpdateUser("Generating SmokeAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + File.Create(config).Close(); + StreamWriter writer = new(config, true, Encoding.UTF8); + WriteConfig(writer, + new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + installForm); + writer.Flush(); + writer.Close(); + } + else if (File.Exists(config)) + { + File.Delete(config); + if (installForm is not null) + installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); + } + } + internal static void WriteConfig(StreamWriter writer, SortedList overrideDlc, SortedList injectDlc, InstallForm installForm = null) { writer.WriteLine("{"); @@ -146,37 +181,6 @@ internal static class SmokeAPI installForm.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api64)}", InstallationLog.Action, info: false); } if (generateConfig) - { - IEnumerable> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) - overrideDlc = overrideDlc.Except(extraDlc); - IEnumerable> injectDlc = new List>(); - if (selection.AllDlc.Count > 64 || selection.ExtraDlc.Any(e => e.dlc.Count > 64)) - { - injectDlc = injectDlc.Concat(selection.SelectedDlc.Where(pair => pair.Value.type is DlcType.SteamHidden)); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) - if (selection.ExtraDlc.Where(e => e.id == id).Single().dlc.Count > 64) - injectDlc = injectDlc.Concat(extraDlc.Where(pair => pair.Value.type is DlcType.SteamHidden)); - } - if (overrideDlc.Any() || injectDlc.Any()) - { - if (installForm is not null) - installForm.UpdateUser("Generating SmokeAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - File.Create(config).Close(); - StreamWriter writer = new(config, true, Encoding.UTF8); - WriteConfig(writer, - new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), - new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), - installForm); - writer.Flush(); - writer.Close(); - } - else if (File.Exists(config)) - { - File.Delete(config); - if (installForm is not null) - installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); - } - } + CheckConfig(directory, selection, installForm); }); } diff --git a/CreamInstaller/Resources/UplayR1.cs b/CreamInstaller/Resources/UplayR1.cs index d817bff..35bbf8c 100644 --- a/CreamInstaller/Resources/UplayR1.cs +++ b/CreamInstaller/Resources/UplayR1.cs @@ -25,6 +25,30 @@ internal static class UplayR1 config = directory + @"\UplayR1Unlocker.jsonc"; } + internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) + { + directory.GetUplayR1Components(out _, out _, out _, out _, out string config); + IEnumerable> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + blacklistDlc = blacklistDlc.Except(extraDlc); + if (blacklistDlc.Any()) + { + if (installForm is not null) + installForm.UpdateUser("Generating Uplay R1 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + File.Create(config).Close(); + StreamWriter writer = new(config, true, Encoding.UTF8); + WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm); + writer.Flush(); + writer.Close(); + } + else if (File.Exists(config)) + { + File.Delete(config); + if (installForm is not null) + installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); + } + } + internal static void WriteConfig(StreamWriter writer, SortedList blacklistDlc, InstallForm installForm = null) { writer.WriteLine("{"); @@ -113,26 +137,6 @@ internal static class UplayR1 installForm.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api64)}", InstallationLog.Action, info: false); } if (generateConfig) - { - IEnumerable> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) - blacklistDlc = blacklistDlc.Except(extraDlc); - if (blacklistDlc.Any()) - { - if (installForm is not null) - installForm.UpdateUser("Generating Uplay R1 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - File.Create(config).Close(); - StreamWriter writer = new(config, true, Encoding.UTF8); - WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm); - writer.Flush(); - writer.Close(); - } - else if (File.Exists(config)) - { - File.Delete(config); - if (installForm is not null) - installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); - } - } + CheckConfig(directory, selection, installForm); }); } diff --git a/CreamInstaller/Resources/UplayR2.cs b/CreamInstaller/Resources/UplayR2.cs index f361f9c..f9028c4 100644 --- a/CreamInstaller/Resources/UplayR2.cs +++ b/CreamInstaller/Resources/UplayR2.cs @@ -27,6 +27,30 @@ internal static class UplayR2 config = directory + @"\UplayR2Unlocker.jsonc"; } + internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) + { + directory.GetUplayR2Components(out _, out _, out _, out _, out _, out _, out string config); + IEnumerable> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + blacklistDlc = blacklistDlc.Except(extraDlc); + if (blacklistDlc.Any()) + { + if (installForm is not null) + installForm.UpdateUser("Generating Uplay R2 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + File.Create(config).Close(); + StreamWriter writer = new(config, true, Encoding.UTF8); + WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm); + writer.Flush(); + writer.Close(); + } + else if (File.Exists(config)) + { + File.Delete(config); + if (installForm is not null) + installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); + } + } + internal static void WriteConfig(StreamWriter writer, SortedList blacklistDlc, InstallForm installForm = null) { writer.WriteLine("{"); @@ -121,26 +145,6 @@ internal static class UplayR2 installForm.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", InstallationLog.Action, info: false); } if (generateConfig) - { - IEnumerable> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) - blacklistDlc = blacklistDlc.Except(extraDlc); - if (blacklistDlc.Any()) - { - if (installForm is not null) - installForm.UpdateUser("Generating Uplay R2 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); - File.Create(config).Close(); - StreamWriter writer = new(config, true, Encoding.UTF8); - WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm); - writer.Flush(); - writer.Close(); - } - else if (File.Exists(config)) - { - File.Delete(config); - if (installForm is not null) - installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false); - } - } + CheckConfig(directory, selection, installForm); }); }