- Selections are now properly separated by platform, fixing potential future issues related to two games on different platforms having the same id
- Saved pre-scan choices now have to be saved in JSON, and thus will be reset
- Selection nodes now display their platform and are now also sorted by their platform
This commit is contained in:
pointfeev 2022-08-17 18:48:05 -04:00
parent b22dddde48
commit 5f3329305c
14 changed files with 187 additions and 157 deletions

View file

@ -1,19 +0,0 @@
using System.Collections.Generic;
namespace CreamInstaller.Components;
internal class AppIdComparer : IComparer<string>
{
private static AppIdComparer comparer;
public static AppIdComparer Comparer => comparer ??= new AppIdComparer();
public int Compare(string a, string b) =>
a == "ParadoxLauncher" ? -1
: b == "ParadoxLauncher" ? 1
: !int.TryParse(a, out _) && !int.TryParse(b, out _) ? string.Compare(a, b, System.StringComparison.Ordinal)
: !int.TryParse(a, out int A) ? 1
: !int.TryParse(b, out int B) ? -1
: A > B ? 1
: A < B ? -1
: 0;
}

View file

@ -15,27 +15,11 @@ internal class CustomTreeView : TreeView
base.WndProc(ref m); base.WndProc(ref m);
} }
internal class TreeNodeSorter : IComparer
{
private readonly bool compareText;
internal TreeNodeSorter(bool compareText = false) : base() => this.compareText = compareText;
public int Compare(object a, object b)
{
if (a is not TreeNode NodeA) return 0;
if (b is not TreeNode NodeB) return 0;
string StringA = compareText ? NodeA.Text : NodeA.Name;
string StringB = compareText ? NodeB.Text : NodeB.Name;
return AppIdComparer.Comparer.Compare(StringA, StringB);
}
}
internal CustomTreeView() : base() internal CustomTreeView() : base()
{ {
DrawMode = TreeViewDrawMode.OwnerDrawAll; DrawMode = TreeViewDrawMode.OwnerDrawAll;
DrawNode += new DrawTreeNodeEventHandler(DrawTreeNode); DrawNode += new DrawTreeNodeEventHandler(DrawTreeNode);
TreeViewNodeSorter = new TreeNodeSorter(); TreeViewNodeSorter = PlatformIdComparer.TreeNodes;
} }
private void DrawTreeNode(object sender, DrawTreeNodeEventArgs e) private void DrawTreeNode(object sender, DrawTreeNodeEventArgs e)
@ -45,23 +29,28 @@ internal class CustomTreeView : TreeView
if (!node.IsVisible) if (!node.IsVisible)
return; return;
string subText = node.Name;
Platform? platform = node.Tag as Platform?;
string tagText = platform?.ToString();
if (string.IsNullOrWhiteSpace(subText) || string.IsNullOrWhiteSpace(tagText) || subText == "PL")
return;
Graphics graphics = e.Graphics; Graphics graphics = e.Graphics;
Color backColor = BackColor; Color backColor = BackColor;
using SolidBrush brush = new(backColor); using SolidBrush brush = new(backColor);
Font font = Font; Font font = Font;
using Font subFont = new(font.FontFamily, font.SizeInPoints, FontStyle.Regular, font.Unit, font.GdiCharSet, font.GdiVerticalFont);
string subText = node.Name;
if (string.IsNullOrWhiteSpace(subText) || subText == "ParadoxLauncher"
|| node.Tag is null && ProgramSelection.FromId(subText) is null && ProgramSelection.GetDlcFromId(subText) is null)
return;
Size subSize = TextRenderer.MeasureText(graphics, subText, subFont);
Rectangle bounds = node.Bounds; Rectangle bounds = node.Bounds;
Rectangle subBounds = new(bounds.X + bounds.Width, bounds.Y, subSize.Width, bounds.Height);
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);
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); graphics.FillRectangle(brush, subBounds);
Point location = subBounds.Location; Point subLocation = new(subBounds.Location.X - 1, subBounds.Location.Y + 1);
Point subLocation = new(location.X - 1, location.Y + 1); TextRenderer.DrawText(graphics, subText, font, subLocation, Color.LightSlateGray);
TextRenderer.DrawText(graphics, subText, subFont, subLocation, Color.Gray);
} }
} }

View file

@ -0,0 +1,33 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
namespace CreamInstaller.Components;
internal static class PlatformIdComparer
{
private static PlatformIdStringComparer stringComparer;
internal static PlatformIdStringComparer Strings => stringComparer ??= new();
private static PlatformIdNodeComparer nodeComparer;
internal static PlatformIdNodeComparer TreeNodes => nodeComparer ??= new();
}
internal class PlatformIdStringComparer : IComparer<string>
{
public int Compare(string a, string b) =>
!int.TryParse(a, out _) && !int.TryParse(b, out _) ? string.Compare(a, b, StringComparison.Ordinal)
: !int.TryParse(a, out int A) ? 1 : !int.TryParse(b, out int B) ? -1
: A > B ? 1 : A < B ? -1 : 0;
}
internal class PlatformIdNodeComparer : IComparer
{
public int Compare(object a, object b) =>
a is not TreeNode A ? 1 : b is not TreeNode B ? -1
: A.Tag is not Platform pA ? 1 : B.Tag is not Platform pB ? -1
: pA > pB ? 1 : pA < pB ? -1
: PlatformIdComparer.Strings.Compare(A.Name, B.Name);
}

View file

@ -5,7 +5,7 @@
<UseWindowsForms>True</UseWindowsForms> <UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon> <ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract> <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<Version>3.6.0.0</Version> <Version>3.6.1.0</Version>
<PackageIcon>Resources\ini.ico</PackageIcon> <PackageIcon>Resources\ini.ico</PackageIcon>
<PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageLicenseFile>LICENSE</PackageLicenseFile>
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright> <Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>

View file

@ -60,14 +60,14 @@ internal partial class InstallForm : CustomForm
UpdateProgress(0); UpdateProgress(0);
int count = selection.DllDirectories.Count; int count = selection.DllDirectories.Count;
int cur = 0; int cur = 0;
if (selection.Id == "ParadoxLauncher") if (selection.Id == "PL")
{ {
UpdateUser($"Repairing Paradox Launcher . . . ", InstallationLog.Operation); UpdateUser($"Repairing Paradox Launcher . . . ", InstallationLog.Operation);
_ = await Repair(this, selection); _ = await Repair(this, selection);
} }
foreach (string directory in selection.DllDirectories) foreach (string directory in selection.DllDirectories)
{ {
if (selection.IsSteam && selection.SelectedDlc.Any(d => d.Value.type is DlcType.Steam or DlcType.SteamHidden) if (selection.Platform is Platform.Steam && selection.SelectedDlc.Any(d => d.Value.type is DlcType.Steam or DlcType.SteamHidden)
|| selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.Steam or DlcType.SteamHidden))) || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.Steam or DlcType.SteamHidden)))
{ {
directory.GetSmokeApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config, out string cache); directory.GetSmokeApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config, out string cache);
@ -81,7 +81,7 @@ internal partial class InstallForm : CustomForm
await SmokeAPI.Install(directory, selection, this); await SmokeAPI.Install(directory, selection, this);
} }
} }
if (selection.IsEpic && selection.SelectedDlc.Any(d => d.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement) if (selection.Platform is Platform.Epic && selection.SelectedDlc.Any(d => d.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement)
|| selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement))) || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement)))
{ {
directory.GetScreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config); directory.GetScreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config);
@ -95,7 +95,7 @@ internal partial class InstallForm : CustomForm
await ScreamAPI.Install(directory, selection, this); await ScreamAPI.Install(directory, selection, this);
} }
} }
if (selection.IsUbisoft) if (selection.Platform is Platform.Ubisoft)
{ {
directory.GetUplayR1Components(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config); directory.GetUplayR1Components(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config);
if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config)) if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config))

View file

@ -2,12 +2,15 @@
using CreamInstaller.Utility; using CreamInstaller.Utility;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using Windows.Foundation.Metadata;
using static CreamInstaller.Components.CustomTreeView; using static CreamInstaller.Components.CustomTreeView;
namespace CreamInstaller; namespace CreamInstaller;
@ -16,15 +19,15 @@ internal partial class SelectDialogForm : CustomForm
{ {
internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent(); internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
private readonly List<(string platform, string id, string name)> selected = new(); private readonly List<(Platform platform, string id, string name)> selected = new();
internal List<(string platform, string id, string name)> QueryUser(string groupBoxText, List<(string platform, string id, string name, bool alreadySelected)> choices) internal List<(Platform platform, string id, string name)> QueryUser(string groupBoxText, List<(Platform platform, string id, string name, bool alreadySelected)> choices)
{ {
if (!choices.Any()) return null; if (!choices.Any()) return null;
groupBox.Text = groupBoxText; groupBox.Text = groupBoxText;
allCheckBox.Enabled = false; allCheckBox.Enabled = false;
acceptButton.Enabled = false; acceptButton.Enabled = false;
selectionTreeView.AfterCheck += OnTreeNodeChecked; selectionTreeView.AfterCheck += OnTreeNodeChecked;
foreach ((string platform, string id, string name, bool alreadySelected) in choices) foreach ((Platform platform, string id, string name, bool alreadySelected) in choices)
{ {
TreeNode node = new() TreeNode node = new()
{ {
@ -43,7 +46,7 @@ internal partial class SelectDialogForm : CustomForm
allCheckBox.Enabled = true; allCheckBox.Enabled = true;
acceptButton.Enabled = selected.Any(); acceptButton.Enabled = selected.Any();
saveButton.Enabled = acceptButton.Enabled; saveButton.Enabled = acceptButton.Enabled;
loadButton.Enabled = File.Exists(ProgramData.ChoicesPath); loadButton.Enabled = ProgramData.ReadChoices() is not null;
OnResize(null, null); OnResize(null, null);
Resize += OnResize; Resize += OnResize;
return ShowDialog() == DialogResult.OK ? selected : null; return ShowDialog() == DialogResult.OK ? selected : null;
@ -59,10 +62,11 @@ internal partial class SelectDialogForm : CustomForm
private void OnTreeNodeChecked(TreeNode node) private void OnTreeNodeChecked(TreeNode node)
{ {
string id = node.Name; string id = node.Name;
Platform platform = (Platform)node.Tag;
if (node.Checked) if (node.Checked)
selected.Add((node.Tag as string, id, node.Text)); selected.Add((platform, id, node.Text));
else else
_ = selected.RemoveAll(s => s.id == id); _ = selected.RemoveAll(s => s.platform == platform && s.id == id);
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
allCheckBox.Checked = selectionTreeView.Nodes.Cast<TreeNode>().All(n => n.Checked); allCheckBox.Checked = selectionTreeView.Nodes.Cast<TreeNode>().All(n => n.Checked);
allCheckBox.CheckedChanged += OnAllCheckBoxChanged; allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
@ -73,7 +77,7 @@ internal partial class SelectDialogForm : CustomForm
? Program.ApplicationNameShort ? Program.ApplicationNameShort
: Program.ApplicationName; : Program.ApplicationName;
private void OnSortCheckBoxChanged(object sender, EventArgs e) => selectionTreeView.TreeViewNodeSorter = new TreeNodeSorter(sortCheckBox.Checked); private void OnSortCheckBoxChanged(object sender, EventArgs e) => selectionTreeView.TreeViewNodeSorter = PlatformIdComparer.TreeNodes;
private void OnAllCheckBoxChanged(object sender, EventArgs e) private void OnAllCheckBoxChanged(object sender, EventArgs e)
{ {
@ -92,19 +96,20 @@ internal partial class SelectDialogForm : CustomForm
private void OnLoad(object sender, EventArgs e) private void OnLoad(object sender, EventArgs e)
{ {
List<string> choices = ProgramData.ReadChoices(); List<(Platform platform, string id)> choices = ProgramData.ReadChoices();
if (choices is null) return;
foreach (TreeNode node in selectionTreeView.Nodes) foreach (TreeNode node in selectionTreeView.Nodes)
{ {
node.Checked = choices.Contains(node.Name); node.Checked = choices.Any(n => n.platform == (Platform)node.Tag && n.id == node.Name);
OnTreeNodeChecked(node); OnTreeNodeChecked(node);
} }
} }
private void OnSave(object sender, EventArgs e) private void OnSave(object sender, EventArgs e)
{ {
List<string> choices = new(); List<(Platform platform, string id)> choices = new();
foreach (TreeNode node in selectionTreeView.Nodes.Cast<TreeNode>().Where(n => n.Checked)) foreach (TreeNode node in selectionTreeView.Nodes.Cast<TreeNode>().Where(n => n.Checked))
choices.Add(node.Name); choices.Add(((Platform)node.Tag, node.Name));
ProgramData.WriteChoices(choices); ProgramData.WriteChoices(choices);
loadButton.Enabled = File.Exists(ProgramData.ChoicesPath); loadButton.Enabled = File.Exists(ProgramData.ChoicesPath);
} }

View file

@ -21,6 +21,8 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Windows.Foundation.Metadata;
namespace CreamInstaller; namespace CreamInstaller;
internal partial class SelectForm : CustomForm internal partial class SelectForm : CustomForm
@ -105,23 +107,28 @@ internal partial class SelectForm : CustomForm
RemainingGames.Clear(); // for display purposes only, otherwise ignorable RemainingGames.Clear(); // for display purposes only, otherwise ignorable
RemainingDLCs.Clear(); // for display purposes only, otherwise ignorable RemainingDLCs.Clear(); // for display purposes only, otherwise ignorable
List<Task> appTasks = new(); List<Task> appTasks = new();
if (ProgramsToScan.Any(c => c.platform == "Paradox")) if (ProgramsToScan.Any(c => c.platform is Platform.Paradox))
{ {
List<string> steamDllDirectories = await SteamLibrary.GetDllDirectoriesFromGameDirectory(ParadoxLauncher.InstallPath); List<string> steamDllDirectories = await SteamLibrary.GetDllDirectoriesFromGameDirectory(ParadoxLauncher.InstallPath);
List<string> epicDllDirectories = await EpicLibrary.GetDllDirectoriesFromGameDirectory(ParadoxLauncher.InstallPath); List<string> epicDllDirectories = await EpicLibrary.GetDllDirectoriesFromGameDirectory(ParadoxLauncher.InstallPath);
List<string> dllDirectories = new();
if (steamDllDirectories is not null)
dllDirectories = dllDirectories.Union(steamDllDirectories).ToList();
if (epicDllDirectories is not null)
dllDirectories = dllDirectories.Union(epicDllDirectories).ToList();
if (steamDllDirectories is not null || epicDllDirectories is not null) if (steamDllDirectories is not null || epicDllDirectories is not null)
{ {
ProgramSelection selection = ProgramSelection.FromId("ParadoxLauncher"); ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL");
selection ??= new(); selection ??= new();
if (allCheckBox.Checked) selection.Enabled = true; if (allCheckBox.Checked) selection.Enabled = true;
selection.Id = "ParadoxLauncher"; selection.Id = "PL";
selection.Name = "Paradox Launcher"; selection.Name = "Paradox Launcher";
selection.RootDirectory = ParadoxLauncher.InstallPath; selection.RootDirectory = ParadoxLauncher.InstallPath;
selection.DllDirectories = steamDllDirectories ?? epicDllDirectories; selection.DllDirectories = dllDirectories;
selection.IsSteam = steamDllDirectories is not null; selection.Platform = Platform.Paradox;
selection.IsEpic = epicDllDirectories is not null;
TreeNode programNode = treeNodes.Find(s => s.Name == selection.Id) ?? new(); TreeNode programNode = treeNodes.Find(s => s.Name == selection.Id) ?? new();
programNode.Tag = selection.Platform;
programNode.Name = selection.Id; programNode.Name = selection.Id;
programNode.Text = selection.Name; programNode.Text = selection.Name;
programNode.Checked = selection.Enabled; programNode.Checked = selection.Enabled;
@ -129,7 +136,7 @@ internal partial class SelectForm : CustomForm
_ = selectionTreeView.Nodes.Add(programNode); _ = selectionTreeView.Nodes.Add(programNode);
} }
} }
if (ProgramsToScan.Any(c => c.platform == "Steam")) if (ProgramsToScan.Any(c => c.platform is Platform.Steam))
{ {
List<(string appId, string name, string branch, int buildId, string gameDirectory)> steamGames = await SteamLibrary.GetGames(); List<(string appId, string name, string branch, int buildId, string gameDirectory)> steamGames = await SteamLibrary.GetGames();
int totalGames = steamGames.Count; int totalGames = steamGames.Count;
@ -137,7 +144,7 @@ internal partial class SelectForm : CustomForm
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in steamGames) foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in steamGames)
{ {
if (Program.Canceled) return; if (Program.Canceled) return;
if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.id == appId)) if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Steam && c.id == appId))
{ {
gamesChecked++; gamesChecked++;
continue; continue;
@ -223,13 +230,13 @@ internal partial class SelectForm : CustomForm
await task; await task;
} }
ProgramSelection selection = ProgramSelection.FromId(appId) ?? new(); ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Steam, appId) ?? new();
selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any();
selection.Id = appId; selection.Id = appId;
selection.Name = appData?.name ?? name; selection.Name = appData?.name ?? name;
selection.RootDirectory = gameDirectory; selection.RootDirectory = gameDirectory;
selection.DllDirectories = dllDirectories; selection.DllDirectories = dllDirectories;
selection.IsSteam = true; selection.Platform = Platform.Steam;
selection.ProductUrl = "https://store.steampowered.com/app/" + appId; selection.ProductUrl = "https://store.steampowered.com/app/" + appId;
selection.IconUrl = IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("icon")}.jpg"; selection.IconUrl = IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("icon")}.jpg";
selection.SubIconUrl = appData?.header_image ?? IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("clienticon")}.ico"; selection.SubIconUrl = appData?.header_image ?? IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("clienticon")}.ico";
@ -241,6 +248,7 @@ internal partial class SelectForm : CustomForm
{ {
if (Program.Canceled) return; if (Program.Canceled) return;
TreeNode programNode = treeNodes.Find(s => s.Name == appId) ?? new(); TreeNode programNode = treeNodes.Find(s => s.Name == appId) ?? new();
programNode.Tag = selection.Platform;
programNode.Name = appId; programNode.Name = appId;
programNode.Text = appData?.name ?? name; programNode.Text = appData?.name ?? name;
programNode.Checked = selection.Enabled; programNode.Checked = selection.Enabled;
@ -254,6 +262,7 @@ internal partial class SelectForm : CustomForm
selection.AllDlc[appId] = dlcApp; selection.AllDlc[appId] = dlcApp;
if (allCheckBox.Checked) selection.SelectedDlc[appId] = dlcApp; if (allCheckBox.Checked) selection.SelectedDlc[appId] = dlcApp;
TreeNode dlcNode = treeNodes.Find(s => s.Name == appId) ?? new(); TreeNode dlcNode = treeNodes.Find(s => s.Name == appId) ?? new();
dlcNode.Tag = selection.Platform;
dlcNode.Name = appId; dlcNode.Name = appId;
dlcNode.Text = dlcApp.name; dlcNode.Text = dlcApp.name;
dlcNode.Checked = selection.SelectedDlc.ContainsKey(appId); dlcNode.Checked = selection.SelectedDlc.ContainsKey(appId);
@ -267,7 +276,7 @@ internal partial class SelectForm : CustomForm
appTasks.Add(task); appTasks.Add(task);
} }
} }
if (ProgramsToScan.Any(c => c.platform == "Epic")) if (ProgramsToScan.Any(c => c.platform is Platform.Epic))
{ {
List<Manifest> epicGames = await EpicLibrary.GetGames(); List<Manifest> epicGames = await EpicLibrary.GetGames();
foreach (Manifest manifest in epicGames) foreach (Manifest manifest in epicGames)
@ -276,7 +285,7 @@ internal partial class SelectForm : CustomForm
string name = manifest.DisplayName; string name = manifest.DisplayName;
string directory = manifest.InstallLocation; string directory = manifest.InstallLocation;
if (Program.Canceled) return; if (Program.Canceled) return;
if (Program.IsGameBlocked(name, directory) || !ProgramsToScan.Any(c => c.id == @namespace)) continue; if (Program.IsGameBlocked(name, directory) || !ProgramsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace)) continue;
AddToRemainingGames(name); AddToRemainingGames(name);
Task task = Task.Run(async () => Task task = Task.Run(async () =>
{ {
@ -318,13 +327,13 @@ internal partial class SelectForm : CustomForm
await task; await task;
} }
ProgramSelection selection = ProgramSelection.FromId(@namespace) ?? new(); ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Epic, @namespace) ?? new();
selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any();
selection.Id = @namespace; selection.Id = @namespace;
selection.Name = name; selection.Name = name;
selection.RootDirectory = directory; selection.RootDirectory = directory;
selection.DllDirectories = dllDirectories; selection.DllDirectories = dllDirectories;
selection.IsEpic = true; selection.Platform = Platform.Epic;
foreach (KeyValuePair<string, (string name, string product, string icon, string developer)> pair in entitlements.Where(p => p.Value.name == selection.Name)) foreach (KeyValuePair<string, (string name, string product, string icon, string developer)> pair in entitlements.Where(p => p.Value.name == selection.Name))
{ {
selection.ProductUrl = "https://www.epicgames.com/store/product/" + pair.Value.product; selection.ProductUrl = "https://www.epicgames.com/store/product/" + pair.Value.product;
@ -337,6 +346,7 @@ internal partial class SelectForm : CustomForm
{ {
if (Program.Canceled) return; if (Program.Canceled) return;
TreeNode programNode = treeNodes.Find(s => s.Name == @namespace) ?? new(); TreeNode programNode = treeNodes.Find(s => s.Name == @namespace) ?? new();
programNode.Tag = selection.Platform;
programNode.Name = @namespace; programNode.Name = @namespace;
programNode.Text = name; programNode.Text = name;
programNode.Checked = selection.Enabled; programNode.Checked = selection.Enabled;
@ -364,6 +374,7 @@ internal partial class SelectForm : CustomForm
selection.AllDlc[dlcId] = dlcApp; selection.AllDlc[dlcId] = dlcApp;
if (allCheckBox.Checked) selection.SelectedDlc[dlcId] = dlcApp; if (allCheckBox.Checked) selection.SelectedDlc[dlcId] = dlcApp;
TreeNode dlcNode = treeNodes.Find(s => s.Name == dlcId) ?? new(); TreeNode dlcNode = treeNodes.Find(s => s.Name == dlcId) ?? new();
dlcNode.Tag = selection.Platform;
dlcNode.Name = dlcId; dlcNode.Name = dlcId;
dlcNode.Text = dlcApp.name; dlcNode.Text = dlcApp.name;
dlcNode.Checked = selection.SelectedDlc.ContainsKey(dlcId); dlcNode.Checked = selection.SelectedDlc.ContainsKey(dlcId);
@ -378,13 +389,13 @@ internal partial class SelectForm : CustomForm
appTasks.Add(task); appTasks.Add(task);
} }
} }
if (ProgramsToScan.Any(c => c.platform == "Ubisoft")) if (ProgramsToScan.Any(c => c.platform is Platform.Ubisoft))
{ {
List<(string gameId, string name, string gameDirectory)> ubisoftGames = await UbisoftLibrary.GetGames(); List<(string gameId, string name, string gameDirectory)> ubisoftGames = await UbisoftLibrary.GetGames();
foreach ((string gameId, string name, string gameDirectory) in ubisoftGames) foreach ((string gameId, string name, string gameDirectory) in ubisoftGames)
{ {
if (Program.Canceled) return; if (Program.Canceled) return;
if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.id == gameId)) continue; if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Ubisoft && c.id == gameId)) continue;
AddToRemainingGames(name); AddToRemainingGames(name);
Task task = Task.Run(async () => Task task = Task.Run(async () =>
{ {
@ -397,19 +408,20 @@ internal partial class SelectForm : CustomForm
} }
if (Program.Canceled) return; if (Program.Canceled) return;
ProgramSelection selection = ProgramSelection.FromId(gameId) ?? new(); ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Ubisoft, gameId) ?? new();
selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any();
selection.Id = gameId; selection.Id = gameId;
selection.Name = name; selection.Name = name;
selection.RootDirectory = gameDirectory; selection.RootDirectory = gameDirectory;
selection.DllDirectories = dllDirectories; selection.DllDirectories = dllDirectories;
selection.IsUbisoft = true; selection.Platform = Platform.Ubisoft;
selection.IconUrl = IconGrabber.GetDomainFaviconUrl("store.ubi.com"); selection.IconUrl = IconGrabber.GetDomainFaviconUrl("store.ubi.com");
Program.Invoke(selectionTreeView, delegate Program.Invoke(selectionTreeView, delegate
{ {
if (Program.Canceled) return; if (Program.Canceled) return;
TreeNode programNode = treeNodes.Find(s => s.Name == gameId) ?? new(); TreeNode programNode = treeNodes.Find(s => s.Name == gameId) ?? new();
programNode.Tag = selection.Platform;
programNode.Name = gameId; programNode.Name = gameId;
programNode.Text = name; programNode.Text = name;
programNode.Checked = selection.Enabled; programNode.Checked = selection.Enabled;
@ -429,7 +441,7 @@ internal partial class SelectForm : CustomForm
} }
} }
private List<(string platform, string id, string name)> ProgramsToScan; private List<(Platform platform, string id, string name)> ProgramsToScan;
private async void OnLoad(bool forceScan = false, bool forceProvideChoices = false) private async void OnLoad(bool forceScan = false, bool forceProvideChoices = false)
{ {
Program.Canceled = false; Program.Canceled = false;
@ -450,22 +462,21 @@ internal partial class SelectForm : CustomForm
bool scan = forceScan; bool scan = forceScan;
if (!scan && (ProgramsToScan is null || !ProgramsToScan.Any() || forceProvideChoices)) if (!scan && (ProgramsToScan is null || !ProgramsToScan.Any() || forceProvideChoices))
{ {
List<(string platform, string id, string name, bool alreadySelected)> gameChoices = new(); List<(Platform platform, string id, string name, bool alreadySelected)> gameChoices = new();
if (Directory.Exists(ParadoxLauncher.InstallPath)) if (Directory.Exists(ParadoxLauncher.InstallPath))
gameChoices.Add(("Paradox", "ParadoxLauncher", "Paradox Launcher", ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == "ParadoxLauncher"))); gameChoices.Add((Platform.Paradox, "PL", "Paradox Launcher", ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL")));
if (Directory.Exists(SteamLibrary.InstallPath)) if (Directory.Exists(SteamLibrary.InstallPath))
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in await SteamLibrary.GetGames()) foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in (await SteamLibrary.GetGames()).Where(g => !Program.IsGameBlocked(g.name, g.gameDirectory)))
if (!Program.IsGameBlocked(name, gameDirectory)) gameChoices.Add((Platform.Steam, appId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Steam && p.id == appId)));
gameChoices.Add(("Steam", appId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == appId)));
if (Directory.Exists(EpicLibrary.EpicManifestsPath)) if (Directory.Exists(EpicLibrary.EpicManifestsPath))
foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation))) foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation)))
gameChoices.Add(("Epic", manifest.CatalogNamespace, manifest.DisplayName, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == manifest.CatalogNamespace))); gameChoices.Add((Platform.Epic, manifest.CatalogNamespace, manifest.DisplayName, ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Epic && p.id == manifest.CatalogNamespace)));
foreach ((string gameId, string name, string gameDirectory) in await UbisoftLibrary.GetGames()) foreach ((string gameId, string name, string gameDirectory) in (await UbisoftLibrary.GetGames()).Where(g => !Program.IsGameBlocked(g.name, g.gameDirectory)))
gameChoices.Add(("Ubisoft", gameId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == gameId))); gameChoices.Add((Platform.Ubisoft, gameId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Ubisoft && p.id == gameId)));
if (gameChoices.Any()) if (gameChoices.Any())
{ {
using SelectDialogForm form = new(this); using SelectDialogForm form = new(this);
List<(string platform, string id, string name)> choices = form.QueryUser("Choose which programs and/or games to scan for DLC:", gameChoices); List<(Platform platform, string id, string name)> choices = form.QueryUser("Choose which programs and/or games to scan for DLC:", gameChoices);
scan = choices is not null && choices.Any(); scan = choices is not null && choices.Any();
string retry = "\n\nPress the \"Rescan Programs / Games\" button to re-choose."; string retry = "\n\nPress the \"Rescan Programs / Games\" button to re-choose.";
if (scan) if (scan)
@ -497,7 +508,7 @@ internal partial class SelectForm : CustomForm
: $"Gathering and caching your applicable games and their DLCs . . . {p}%"; : $"Gathering and caching your applicable games and their DLCs . . . {p}%";
progressBar.Value = p; progressBar.Value = p;
}; };
if (Directory.Exists(SteamLibrary.InstallPath) && ProgramsToScan is not null && ProgramsToScan.Any(c => c.platform == "Steam")) if (Directory.Exists(SteamLibrary.InstallPath) && ProgramsToScan is not null && ProgramsToScan.Any(c => c.platform is Platform.Steam))
{ {
progressLabel.Text = $"Setting up SteamCMD . . . "; progressLabel.Text = $"Setting up SteamCMD . . . ";
await SteamCMD.Setup(iProgress); await SteamCMD.Setup(iProgress);
@ -557,17 +568,19 @@ internal partial class SelectForm : CustomForm
private static void SyncNode(TreeNode node) private static void SyncNode(TreeNode node)
{ {
(string gameId, (DlcType type, string name, string icon) app)? dlc = ProgramSelection.GetDlcFromId(node.Name); string id = node.Name;
Platform platform = (Platform)node.Tag;
(string gameId, (DlcType type, string name, string icon) app)? dlc = ProgramSelection.GetDlcFromPlatformId(platform, id);
if (dlc.HasValue) if (dlc.HasValue)
{ {
(string gameId, _) = dlc.Value; (string gameId, _) = dlc.Value;
ProgramSelection selection = ProgramSelection.FromId(gameId); ProgramSelection selection = ProgramSelection.FromPlatformId(platform, gameId);
if (selection is not null) if (selection is not null)
selection.ToggleDlc(node.Name, node.Checked); selection.ToggleDlc(node.Name, node.Checked);
} }
else else
{ {
ProgramSelection selection = ProgramSelection.FromId(node.Name); ProgramSelection selection = ProgramSelection.FromPlatformId(platform, id);
if (selection is not null) if (selection is not null)
selection.Enabled = node.Checked; selection.Enabled = node.Checked;
} }
@ -630,16 +643,18 @@ internal partial class SelectForm : CustomForm
ContextMenuStrip contextMenuStrip = new(); ContextMenuStrip contextMenuStrip = new();
selectionTreeView.SelectedNode = node; selectionTreeView.SelectedNode = node;
string id = node.Name; string id = node.Name;
ProgramSelection selection = ProgramSelection.FromId(id); Platform platform = (Platform)node.Tag;
ProgramSelection selection = ProgramSelection.FromPlatformId(platform, id);
(string gameAppId, (DlcType type, string name, string icon) app)? dlc = null; (string gameAppId, (DlcType type, string name, string icon) app)? dlc = null;
if (selection is null) dlc = ProgramSelection.GetDlcFromId(id); if (selection is null)
dlc = ProgramSelection.GetDlcFromPlatformId(platform, id);
ProgramSelection dlcParentSelection = null; ProgramSelection dlcParentSelection = null;
if (dlc is not null) if (dlc is not null)
dlcParentSelection = ProgramSelection.FromId(dlc.Value.gameAppId); dlcParentSelection = ProgramSelection.FromPlatformId(platform, dlc.Value.gameAppId);
if (selection is null && dlcParentSelection is null) if (selection is null && dlcParentSelection is null)
return; return;
ContextMenuItem header = null; ContextMenuItem header = null;
if (id == "ParadoxLauncher") if (id == "PL")
header = new(node.Text, "Paradox Launcher"); header = new(node.Text, "Paradox Launcher");
else if (selection is not null) else if (selection is not null)
header = new(node.Text, (id, selection.IconUrl)); header = new(node.Text, (id, selection.IconUrl));
@ -654,8 +669,9 @@ internal partial class SelectForm : CustomForm
List<ContextMenuItem> queries = new(); List<ContextMenuItem> queries = new();
if (File.Exists(appInfoJSON)) if (File.Exists(appInfoJSON))
{ {
string platform = (selection is null || selection.IsSteam) ? "Steam Store " : selection.IsEpic ? "Epic GraphQL " : ""; string platformString = (selection is null || selection.Platform is Platform.Steam) ? "Steam Store "
queries.Add(new ContextMenuItem($"Open {platform}Query", "Notepad", : selection.Platform is Platform.Epic ? "Epic GraphQL " : "";
queries.Add(new ContextMenuItem($"Open {platformString}Query", "Notepad",
new EventHandler((sender, e) => Diagnostics.OpenFileInNotepad(appInfoJSON)))); new EventHandler((sender, e) => Diagnostics.OpenFileInNotepad(appInfoJSON))));
} }
if (File.Exists(appInfoVDF)) if (File.Exists(appInfoVDF))
@ -690,7 +706,7 @@ internal partial class SelectForm : CustomForm
} }
if (selection is not null) if (selection is not null)
{ {
if (id == "ParadoxLauncher") if (id == "PL")
{ {
contextMenuStrip.Items.Add(new ToolStripSeparator()); contextMenuStrip.Items.Add(new ToolStripSeparator());
contextMenuStrip.Items.Add(new ContextMenuItem("Repair", "Command Prompt", contextMenuStrip.Items.Add(new ContextMenuItem("Repair", "Command Prompt",
@ -700,49 +716,40 @@ internal partial class SelectForm : CustomForm
contextMenuStrip.Items.Add(new ContextMenuItem("Open Root Directory", "File Explorer", contextMenuStrip.Items.Add(new ContextMenuItem("Open Root Directory", "File Explorer",
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory)))); new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory))));
List<string> directories = selection.DllDirectories.ToList(); List<string> directories = selection.DllDirectories.ToList();
if (selection.IsSteam) int steam = 0, epic = 0, r1 = 0, r2 = 0;
for (int i = 0; i < directories.Count; i++) if (selection.Platform is Platform.Steam or Platform.Paradox)
foreach (string directory in directories)
{ {
string directory = directories[i];
directory.GetSmokeApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config, out string cache); directory.GetSmokeApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config, out string cache);
if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config) || File.Exists(cache)) if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config) || File.Exists(cache))
{ contextMenuStrip.Items.Add(new ContextMenuItem($"Open Steamworks Directory #{++steam}", "File Explorer",
contextMenuStrip.Items.Add(new ContextMenuItem($"Open Steamworks SDK Directory #{i + 1}", "File Explorer",
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory))));
}
} }
if (selection.IsEpic) if (selection.Platform is Platform.Epic or Platform.Paradox)
for (int i = 0; i < directories.Count; i++) foreach (string directory in directories)
{ {
string directory = directories[i];
directory.GetScreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config); directory.GetScreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config);
if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config)) if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config))
{ contextMenuStrip.Items.Add(new ContextMenuItem($"Open Epic Online Services Directory #{++epic}", "File Explorer",
contextMenuStrip.Items.Add(new ContextMenuItem($"Open Epic Online Services SDK Directory #{i + 1}", "File Explorer",
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory))));
}
} }
if (selection.IsUbisoft) if (selection.Platform is Platform.Ubisoft)
for (int i = 0, r1 = 0, r2 = 0; i < directories.Count; i++) foreach (string directory in directories)
{ {
string directory = directories[i];
directory.GetUplayR1Components(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config); directory.GetUplayR1Components(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config);
if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config)) if (File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config))
{
contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R1 SDK Directory #{++r1}", "File Explorer", contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R1 SDK Directory #{++r1}", "File Explorer",
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory))));
}
directory.GetUplayR2Components(out string old_sdk32, out string old_sdk64, out sdk32, out sdk32_o, out sdk64, out sdk64_o, out config); directory.GetUplayR2Components(out string old_sdk32, out string old_sdk64, out sdk32, out sdk32_o, out sdk64, out sdk64_o, out config);
if (File.Exists(old_sdk32) || File.Exists(old_sdk64) || File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config)) if (File.Exists(old_sdk32) || File.Exists(old_sdk64) || File.Exists(sdk32) || File.Exists(sdk32_o) || File.Exists(sdk64) || File.Exists(sdk64_o) || File.Exists(config))
{
contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R2 SDK Directory #{++r2}", "File Explorer", contextMenuStrip.Items.Add(new ContextMenuItem($"Open Uplay R2 SDK Directory #{++r2}", "File Explorer",
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory))));
}
} }
} }
if (id != "ParadoxLauncher") if (id != "PL")
{ {
if (selection is not null && selection.IsSteam || dlcParentSelection is not null && dlcParentSelection.IsSteam) 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 ToolStripSeparator());
contextMenuStrip.Items.Add(new ContextMenuItem("Open SteamDB", "SteamDB", contextMenuStrip.Items.Add(new ContextMenuItem("Open SteamDB", "SteamDB",
@ -750,14 +757,14 @@ internal partial class SelectForm : CustomForm
} }
if (selection is not null) if (selection is not null)
{ {
if (selection.IsSteam) if (selection.Platform is Platform.Steam)
{ {
contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Store", "Steam Store", contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Store", "Steam Store",
new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl))));
contextMenuStrip.Items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), "Steam Community", 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)))); new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id))));
} }
else if (selection.IsEpic) if (selection.Platform is Platform.Epic)
{ {
contextMenuStrip.Items.Add(new ToolStripSeparator()); contextMenuStrip.Items.Add(new ToolStripSeparator());
contextMenuStrip.Items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB", contextMenuStrip.Items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB",
@ -765,7 +772,7 @@ internal partial class SelectForm : CustomForm
contextMenuStrip.Items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games", contextMenuStrip.Items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games",
new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl))));
} }
else if (selection.IsUbisoft) if (selection.Platform is Platform.Ubisoft)
{ {
contextMenuStrip.Items.Add(new ToolStripSeparator()); contextMenuStrip.Items.Add(new ToolStripSeparator());
#pragma warning disable CA1308 // Normalize strings to uppercase #pragma warning disable CA1308 // Normalize strings to uppercase

View file

@ -28,7 +28,7 @@ internal static class ParadoxLauncher
private static void PopulateDlc(ProgramSelection paradoxLauncher = null) private static void PopulateDlc(ProgramSelection paradoxLauncher = null)
{ {
paradoxLauncher ??= ProgramSelection.FromId("ParadoxLauncher"); paradoxLauncher ??= ProgramSelection.FromPlatformId(Platform.Paradox, "PL");
if (paradoxLauncher is not null) if (paradoxLauncher is not null)
{ {
paradoxLauncher.ExtraDlc.Clear(); paradoxLauncher.ExtraDlc.Clear();
@ -51,7 +51,7 @@ internal static class ParadoxLauncher
internal static bool DlcDialog(Form form) internal static bool DlcDialog(Form form)
{ {
ProgramSelection paradoxLauncher = ProgramSelection.FromId("ParadoxLauncher"); ProgramSelection paradoxLauncher = ProgramSelection.FromPlatformId(Platform.Paradox, "PL");
if (paradoxLauncher is not null && paradoxLauncher.Enabled) if (paradoxLauncher is not null && paradoxLauncher.Enabled)
{ {
PopulateDlc(paradoxLauncher); PopulateDlc(paradoxLauncher);

View file

@ -1,12 +1,22 @@
using CreamInstaller.Components; using CreamInstaller.Components;
using CreamInstaller.Resources; using CreamInstaller.Resources;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace CreamInstaller; namespace CreamInstaller;
public enum Platform
{
None = 0,
Paradox,
Steam,
Epic,
Ubisoft
}
public enum DlcType public enum DlcType
{ {
Steam, Steam,
@ -19,6 +29,7 @@ internal class ProgramSelection
{ {
internal bool Enabled; internal bool Enabled;
internal Platform Platform;
internal string Id = "0"; internal string Id = "0";
internal string Name = "Program"; internal string Name = "Program";
@ -33,12 +44,8 @@ internal class ProgramSelection
internal string RootDirectory; internal string RootDirectory;
internal List<string> DllDirectories; internal List<string> DllDirectories;
internal bool IsSteam; internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc = new(PlatformIdComparer.Strings);
internal bool IsEpic; internal readonly SortedList<string, (DlcType type, string name, string icon)> SelectedDlc = new(PlatformIdComparer.Strings);
internal bool IsUbisoft;
internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc = new(AppIdComparer.Comparer);
internal readonly SortedList<string, (DlcType type, string name, string icon)> SelectedDlc = new(AppIdComparer.Comparer);
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)> ExtraDlc = new(); // for Paradox Launcher internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)> ExtraDlc = new(); // for Paradox Launcher
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)> ExtraSelectedDlc = new(); // for Paradox Launcher internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)> ExtraSelectedDlc = new(); // for Paradox Launcher
@ -49,7 +56,7 @@ internal class ProgramSelection
{ {
foreach (string directory in DllDirectories) foreach (string directory in DllDirectories)
{ {
if (IsSteam) if (Platform is Platform.Steam or Platform.Paradox)
{ {
directory.GetCreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config); directory.GetCreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config);
if (sdk32.IsFilePathLocked() if (sdk32.IsFilePathLocked()
@ -67,7 +74,7 @@ internal class ProgramSelection
|| cache.IsFilePathLocked()) || cache.IsFilePathLocked())
return true; return true;
} }
else if (IsEpic) if (Platform is Platform.Epic or Platform.Paradox)
{ {
directory.GetScreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config); directory.GetScreamApiComponents(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config);
if (sdk32.IsFilePathLocked() if (sdk32.IsFilePathLocked()
@ -77,7 +84,7 @@ internal class ProgramSelection
|| config.IsFilePathLocked()) || config.IsFilePathLocked())
return true; return true;
} }
else if (IsUbisoft) if (Platform is Platform.Ubisoft)
{ {
directory.GetUplayR1Components(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config); directory.GetUplayR1Components(out string sdk32, out string sdk32_o, out string sdk64, out string sdk64_o, out string config);
if (sdk32.IsFilePathLocked() if (sdk32.IsFilePathLocked()
@ -140,9 +147,9 @@ internal class ProgramSelection
if (!DllDirectories.Any()) _ = All.Remove(this); if (!DllDirectories.Any()) _ = All.Remove(this);
} }
internal void Validate(List<(string platform, string id, string name)> programsToScan) internal void Validate(List<(Platform platform, string id, string name)> programsToScan)
{ {
if (programsToScan is null || !programsToScan.Any(p => p.id == Id)) if (programsToScan is null || !programsToScan.Any(p => p.platform == Platform && p.id == Id))
{ {
_ = All.Remove(this); _ = All.Remove(this);
return; return;
@ -152,7 +159,7 @@ internal class ProgramSelection
internal static void ValidateAll() => AllSafe.ForEach(selection => selection.Validate()); internal static void ValidateAll() => AllSafe.ForEach(selection => selection.Validate());
internal static void ValidateAll(List<(string platform, string id, string name)> programsToScan) => AllSafe.ForEach(selection => selection.Validate(programsToScan)); internal static void ValidateAll(List<(Platform platform, string id, string name)> programsToScan) => AllSafe.ForEach(selection => selection.Validate(programsToScan));
internal static readonly List<ProgramSelection> All = new(); internal static readonly List<ProgramSelection> All = new();
@ -160,11 +167,11 @@ internal class ProgramSelection
internal static List<ProgramSelection> AllEnabled => AllSafe.FindAll(s => s.Enabled); internal static List<ProgramSelection> AllEnabled => AllSafe.FindAll(s => s.Enabled);
internal static ProgramSelection FromId(string gameId) => AllSafe.Find(s => s.Id == gameId); internal static ProgramSelection FromPlatformId(Platform platform, string gameId) => AllSafe.Find(s => s.Platform == platform && s.Id == gameId);
internal static (string gameId, (DlcType type, string name, string icon) app)? GetDlcFromId(string dlcId) internal static (string gameId, (DlcType type, string name, string icon) app)? GetDlcFromPlatformId(Platform platform, string dlcId)
{ {
foreach (ProgramSelection selection in AllSafe) foreach (ProgramSelection selection in AllSafe.Where(s => s.Platform == platform))
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(p => p.Key == dlcId)) foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(p => p.Key == dlcId))
return (selection.Id, pair.Value); return (selection.Id, pair.Value);
return null; return null;

View file

@ -151,8 +151,8 @@ internal static class ScreamAPI
File.Create(config).Close(); File.Create(config).Close();
StreamWriter writer = new(config, true, Encoding.UTF8); StreamWriter writer = new(config, true, Encoding.UTF8);
WriteConfig(writer, WriteConfig(writer,
new(overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value), AppIdComparer.Comparer), new(overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.Strings),
new(entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), AppIdComparer.Comparer), new(entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.Strings),
installForm); installForm);
writer.Flush(); writer.Flush();
writer.Close(); writer.Close();

View file

@ -165,8 +165,8 @@ internal static class SmokeAPI
File.Create(config).Close(); File.Create(config).Close();
StreamWriter writer = new(config, true, Encoding.UTF8); StreamWriter writer = new(config, true, Encoding.UTF8);
WriteConfig(writer, WriteConfig(writer,
new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), AppIdComparer.Comparer), new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.Strings),
new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), AppIdComparer.Comparer), new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.Strings),
installForm); installForm);
writer.Flush(); writer.Flush();
writer.Close(); writer.Close();

View file

@ -123,7 +123,7 @@ internal static class UplayR1
installForm.UpdateUser("Generating Uplay R1 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); installForm.UpdateUser("Generating Uplay R1 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
File.Create(config).Close(); File.Create(config).Close();
StreamWriter writer = new(config, true, Encoding.UTF8); StreamWriter writer = new(config, true, Encoding.UTF8);
WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), AppIdComparer.Comparer), installForm); WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.Strings), installForm);
writer.Flush(); writer.Flush();
writer.Close(); writer.Close();
} }

View file

@ -131,7 +131,7 @@ internal static class UplayR2
installForm.UpdateUser("Generating Uplay R2 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); installForm.UpdateUser("Generating Uplay R2 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
File.Create(config).Close(); File.Create(config).Close();
StreamWriter writer = new(config, true, Encoding.UTF8); StreamWriter writer = new(config, true, Encoding.UTF8);
WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), AppIdComparer.Comparer), installForm); WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.Strings), installForm);
writer.Flush(); writer.Flush();
writer.Close(); writer.Close();
} }

View file

@ -1,8 +1,12 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@ -20,7 +24,8 @@ internal static class ProgramData
internal static readonly string CooldownPath = DirectoryPath + @"\cooldown"; internal static readonly string CooldownPath = DirectoryPath + @"\cooldown";
internal static readonly string ChoicesPath = DirectoryPath + @"\choices.txt"; internal static readonly string OldChoicesPath = DirectoryPath + @"\choices.txt";
internal static readonly string ChoicesPath = DirectoryPath + @"\choices.json";
internal static async Task Setup() => await Task.Run(() => internal static async Task Setup() => await Task.Run(() =>
{ {
@ -38,6 +43,8 @@ internal static class ProgramData
} }
if (!Directory.Exists(CooldownPath)) if (!Directory.Exists(CooldownPath))
_ = Directory.CreateDirectory(CooldownPath); _ = Directory.CreateDirectory(CooldownPath);
if (File.Exists(OldChoicesPath))
File.Delete(OldChoicesPath);
}); });
internal static bool CheckCooldown(string identifier, int cooldown) internal static bool CheckCooldown(string identifier, int cooldown)
@ -78,23 +85,24 @@ internal static class ProgramData
catch { } catch { }
} }
internal static List<string> ReadChoices() internal static List<(Platform platform, string id)> ReadChoices()
{ {
if (!File.Exists(ChoicesPath)) return new(); if (!File.Exists(ChoicesPath)) return null;
try try
{ {
return File.ReadAllLines(ChoicesPath).ToList(); return JsonConvert.DeserializeObject(File.ReadAllText(ChoicesPath),
typeof(List<(Platform platform, string id)>)) as List<(Platform platform, string id)>;
} }
catch catch
{ {
return new(); return new();
} }
} }
internal static void WriteChoices(List<string> choices) internal static void WriteChoices(List<(Platform platform, string id)> choices)
{ {
try try
{ {
File.WriteAllLines(ChoicesPath, choices.ToArray()); File.WriteAllText(ChoicesPath, JsonConvert.SerializeObject(choices));
} }
catch { } catch { }
} }