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
This commit is contained in:
pointfeev 2022-08-24 22:56:26 -04:00
parent 600e6e71f9
commit 91880aa698
15 changed files with 650 additions and 424 deletions

View file

@ -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)

View file

@ -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<TreeNode, Rectangle> selectionBounds = new();
private readonly Dictionary<ProgramSelection, Rectangle> 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<TreeNode, Rectangle> 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<ProgramSelection, Rectangle> 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;
}
}
}
}
}

View file

@ -151,6 +151,7 @@
<PackageReference Include="HtmlAgilityPack" Version="1.11.45" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Onova" Version="2.6.2" />
<PackageReference Include="System.ServiceModel.Primitives" Version="4.10.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="Forms\SelectDialogForm.cs">

View file

@ -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<string> 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<string> 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);
}

View file

@ -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<double> progress = new();
progress.ProgressChanged += new(delegate (object sender, double _progress)

View file

@ -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);

View file

@ -31,10 +31,14 @@ namespace CreamInstaller
/// </summary>
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;
}
}

View file

@ -31,10 +31,10 @@ internal partial class SelectForm : CustomForm
Text = Program.ApplicationName;
}
private static void UpdateRemaining(Label label, List<string> list, string descriptor) =>
private static void UpdateRemaining(Label label, SynchronizedCollection<string> list, string descriptor) =>
label.Text = list.Any() ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") : "";
private readonly List<string> RemainingGames = new();
private readonly SynchronizedCollection<string> 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<string> RemainingDLCs = new();
private readonly SynchronizedCollection<string> 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<TreeNode> 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<string> 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<ContextMenuItem> 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<string> 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<ContextMenuItem> 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<string> 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)

View file

@ -57,4 +57,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="contextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -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";

View file

@ -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<string, string> targets = new(PlatformIdComparer.String);
SortedList<string, string> 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<string, string> targets, SortedList<string, string> 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<string> 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<string> 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<string, string> targets = new(PlatformIdComparer.String);
SortedList<string, string> 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);
});
}

View file

@ -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<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideCatalogItems = selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
overrideCatalogItems = overrideCatalogItems.Except(extraDlc);
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> entitlements = selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> _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<string, (DlcType type, string name, string icon)> overrideCatalogItems, SortedList<string, (DlcType type, string name, string icon)> 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<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideCatalogItems = selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
overrideCatalogItems = overrideCatalogItems.Except(extraDlc);
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> entitlements = selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> _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);
});
}

View file

@ -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<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
overrideDlc = overrideDlc.Except(extraDlc);
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> injectDlc = new List<KeyValuePair<string, (DlcType type, string name, string icon)>>();
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<string, (DlcType type, string name, string icon)> 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<string, (DlcType type, string name, string icon)> overrideDlc, SortedList<string, (DlcType type, string name, string icon)> 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<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
overrideDlc = overrideDlc.Except(extraDlc);
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> injectDlc = new List<KeyValuePair<string, (DlcType type, string name, string icon)>>();
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<string, (DlcType type, string name, string icon)> 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);
});
}

View file

@ -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<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> 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<string, (DlcType type, string name, string icon)> 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<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> 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);
});
}

View file

@ -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<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> 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<string, (DlcType type, string name, string icon)> 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<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> 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);
});
}