diff --git a/CreamInstaller/Components/ContextMenuItem.cs b/CreamInstaller/Components/ContextMenuItem.cs index a791d87..4247867 100644 --- a/CreamInstaller/Components/ContextMenuItem.cs +++ b/CreamInstaller/Components/ContextMenuItem.cs @@ -1,12 +1,11 @@ -using CreamInstaller.Platforms.Paradox; -using CreamInstaller.Utility; - -using System; +using System; using System.Collections.Concurrent; using System.Drawing; using System.IO; using System.Threading.Tasks; using System.Windows.Forms; +using CreamInstaller.Platforms.Paradox; +using CreamInstaller.Utility; namespace CreamInstaller.Components; @@ -14,64 +13,79 @@ internal class ContextMenuItem : ToolStripMenuItem { private static readonly ConcurrentDictionary images = new(); - private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier) => await Task.Run(async () => - { - if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) item.Image = image; - else + private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier) => await Task.Run( + async () => { - switch (imageIdentifier) + if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) { - case "Paradox Launcher": - if (Directory.Exists(ParadoxLauncher.InstallPath)) - foreach (string file in Directory.EnumerateFiles(ParadoxLauncher.InstallPath, "*.exe")) - { - image = IconGrabber.GetFileIconImage(file); - break; - } - break; - case "Notepad": - image = IconGrabber.GetNotepadImage(); - break; - case "Command Prompt": - image = IconGrabber.GetCommandPromptImage(); - break; - case "File Explorer": - image = IconGrabber.GetFileExplorerImage(); - break; - case "SteamDB": - image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("steamdb.info")); - break; - case "Steam Store": - image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("store.steampowered.com")); - break; - case "Steam Community": - image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("steamcommunity.com")); - break; - case "ScreamDB": - image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("scream-db.web.app")); - break; - case "Epic Games": - image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("epicgames.com")); - break; - case "Ubisoft Store": - image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("store.ubi.com")); - break; - default: - return; - } - if (image is not null) - { - images[imageIdentifier] = image; item.Image = image; } - } - }); + else + { + switch (imageIdentifier) + { + case "Paradox Launcher": + if (Directory.Exists(ParadoxLauncher.InstallPath)) + foreach (string file in Directory.EnumerateFiles(ParadoxLauncher.InstallPath, "*.exe")) + { + image = file.GetFileIconImage(); + break; + } + break; + case "Notepad": + image = IconGrabber.GetNotepadImage(); + break; + case "Command Prompt": + image = IconGrabber.GetCommandPromptImage(); + break; + case "File Explorer": + image = IconGrabber.GetFileExplorerImage(); + break; + case "SteamDB": + image = await HttpClientManager.GetImageFromUrl( + IconGrabber.GetDomainFaviconUrl("steamdb.info")); + break; + case "Steam Store": + image = await HttpClientManager.GetImageFromUrl( + IconGrabber.GetDomainFaviconUrl("store.steampowered.com")); + break; + case "Steam Community": + image = await HttpClientManager.GetImageFromUrl( + IconGrabber.GetDomainFaviconUrl("steamcommunity.com")); + break; + case "ScreamDB": + image = await HttpClientManager.GetImageFromUrl( + IconGrabber.GetDomainFaviconUrl("scream-db.web.app")); + break; + case "Epic Games": + image = await HttpClientManager.GetImageFromUrl( + IconGrabber.GetDomainFaviconUrl("epicgames.com")); + break; + case "Ubisoft Store": + image = await HttpClientManager.GetImageFromUrl( + IconGrabber.GetDomainFaviconUrl("store.ubi.com")); + break; + default: + return; + } + if (image is not null) + { + images[imageIdentifier] = image; + item.Image = image; + } + } + }); - private static async Task TryImageIdentifierInfo(ContextMenuItem item, (string id, string iconUrl) imageIdentifierInfo, Action onFail = null) => await Task.Run(async () => + private static async Task TryImageIdentifierInfo(ContextMenuItem item, + (string id, string iconUrl) imageIdentifierInfo, + Action onFail = null) => await Task.Run(async () => { (string id, string iconUrl) = imageIdentifierInfo; string imageIdentifier = "Icon_" + id; - if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) item.Image = image; + if (images.TryGetValue(imageIdentifier, out Image image) && image is not null) + { + item.Image = image; + } else { image = await HttpClientManager.GetImageFromUrl(iconUrl); @@ -81,11 +95,14 @@ internal class ContextMenuItem : ToolStripMenuItem item.Image = image; } else if (onFail is not null) + { onFail(); + } } }); private readonly EventHandler OnClickEvent; + protected override void OnClick(EventArgs e) { base.OnClick(e); @@ -105,9 +122,15 @@ internal class ContextMenuItem : ToolStripMenuItem internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, EventHandler onClick = null) : this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo); - internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, string imageIdentifierFallback, EventHandler onClick = null) - : this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifier(this, imageIdentifierFallback)); + internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, + string imageIdentifierFallback, EventHandler onClick = null) + : this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, + async () => await TryImageIdentifier( + this, imageIdentifierFallback)); - internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, (string id, string iconUrl) imageIdentifierInfoFallback, EventHandler onClick = null) - : this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifierInfo(this, imageIdentifierInfoFallback)); + internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, + (string id, string iconUrl) imageIdentifierInfoFallback, EventHandler onClick = null) + : this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo, + async () => await TryImageIdentifierInfo( + this, imageIdentifierInfoFallback)); } \ No newline at end of file diff --git a/CreamInstaller/Components/CustomForm.cs b/CreamInstaller/Components/CustomForm.cs index ed4e1c3..549b7db 100644 --- a/CreamInstaller/Components/CustomForm.cs +++ b/CreamInstaller/Components/CustomForm.cs @@ -4,12 +4,21 @@ using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Windows.Forms; +using CreamInstaller.Forms; namespace CreamInstaller.Components; internal class CustomForm : Form { - internal CustomForm() : base() + internal const short SWP_NOACTIVATE = 0x0010; + internal const short SWP_SHOWWINDOW = 0x0040; + internal const short SWP_NOMOVE = 0x0002; + internal const short SWP_NOSIZE = 0x0001; + + internal static readonly IntPtr HWND_NOTOPMOST = new(-2); + internal static readonly IntPtr HWND_TOPMOST = new(-1); + + internal CustomForm() { Icon = Properties.Resources.Icon; KeyPreview = true; @@ -19,47 +28,6 @@ internal class CustomForm : Form HelpButtonClicked += OnHelpButtonClicked; } - internal void OnHelpButtonClicked(object sender, EventArgs args) - { - using DialogForm helpDialog = new(this); - helpDialog.HelpButton = false; - string acidicoala = "https://github.com/acidicoala"; - string repository = $"https://github.com/{Program.RepositoryOwner}/{Program.RepositoryName}"; - _ = helpDialog.Show(SystemIcons.Information, - "Automatically finds all installed Steam, Epic and Ubisoft games with their respective DLC-related DLL locations on the user's computer,\n" - + "parses SteamCMD, Steam Store and Epic Games Store for user-selected games' DLCs, then provides a very simple graphical interface\n" - + "utilizing the gathered information for the maintenance of DLC unlockers.\n" - + "\n" - + $"The program utilizes the latest versions of [Koaloader]({acidicoala}/Koaloader), [SmokeAPI]({acidicoala}/SmokeAPI), [ScreamAPI]({acidicoala}/ScreamAPI), [Uplay R1 Unlocker]({acidicoala}/UplayR1Unlocker) and [Uplay R2 Unlocker]({acidicoala}/UplayR2Unlocker), all by\n" - + $"the wonderful [acidicoala]({acidicoala}), and all downloaded and embedded into the program itself; no further downloads necessary on your part!\n" - + "\n" - + "NOTE: This program does not automatically download nor install actual DLC files for you. As the title of the program says, it's\n" - + "only a DLC Unlocker installer. Should the game you wish to unlock DLC for not already come with the DLCs installed (very many\n" - + "do not), you have to find, download, and install those yourself. Preferably, you should be referring to the proper cs.rin.ru post for\n" - + "the game(s) you're tinkering with; you'll usually find any answer to your problems there.\n" - + "\n" - + "USAGE:\n" - + " 1. Choose which programs and/or games the program should scan for DLC.\n" - + " The program automatically gathers all installed games from Steam, Epic and Ubisoft directories.\n" - + " 2. Wait for the program to download and install SteamCMD (if you chose a Steam game).\n" - + " 3. Wait for the program to gather and cache the chosen games' information && DLCs.\n" - + " May take some time on the first run; depends on how many DLCs the games you chose have.\n" - + " 4. CAREFULLY select which games' DLCs you wish to unlock.\n" - + " Obviously none of the DLC unlockers are tested for every single game!\n" - + " 5. Choose whether or not to install with Koaloader, and if so then also pick the proxy DLL to use.\n" - + " If the default \'version.dll\' doesn't work, then see [here](https://cs.rin.ru/forum/viewtopic.php?p=2552172#p2552172) to find one that does.\n" - + " 6. Click the \"Generate and Install\" button.\n" - + " 7. Click the \"OK\" button to close the program.\n" - + " 8. If any of the DLC unlockers cause problems with any of the games you installed them on, simply go back\n" - + " to step 5 and select what games you wish you revert changes to, and instead click the \"Uninstall\" button this time.\n" - + "\n" - + $"For reliable and quick assistance, all bugs, crashes and other issues should be referred to the [GitHub Issues]({repository}/issues) page!\n" - + "\n" - + "SteamCMD installation and appinfo cache can be found at [C:\\ProgramData\\CreamInstaller]().\n" - + $"The program automatically and very quickly updates from [GitHub]({repository}) using [Onova](https://github.com/Tyrrrz/Onova). (updates can be ignored)\n" - + $"The program source and other information can be found on [GitHub]({repository})."); - } - internal CustomForm(IWin32Window owner) : this() { if (owner is Form form) @@ -73,27 +41,6 @@ internal class CustomForm : Form } } - internal void OnActivation(object sender, EventArgs args) => Activate(); - - internal static readonly IntPtr HWND_NOTOPMOST = new(-2); - internal static readonly IntPtr HWND_TOPMOST = new(-1); - internal const short SWP_NOACTIVATE = 0x0010; - internal const short SWP_SHOWWINDOW = 0x0040; - internal const short SWP_NOMOVE = 0x0002; - internal const short SWP_NOSIZE = 0x0001; - - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - internal static extern void SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); - - internal void BringToFrontWithoutActivation() - { - bool topMost = TopMost; - SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); - if (!topMost) - SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); - } - protected override CreateParams CreateParams // Double buffering for all controls { get @@ -104,13 +51,69 @@ internal class CustomForm : Form } } + internal void OnHelpButtonClicked(object sender, EventArgs args) + { + using DialogForm helpDialog = new(this); + helpDialog.HelpButton = false; + string acidicoala = "https://github.com/acidicoala"; + string repository = $"https://github.com/{Program.RepositoryOwner}/{Program.RepositoryName}"; + _ = helpDialog.Show(SystemIcons.Information, + "Automatically finds all installed Steam, Epic and Ubisoft games with their respective DLC-related DLL locations on the user's computer,\n" + + "parses SteamCMD, Steam Store and Epic Games Store for user-selected games' DLCs, then provides a very simple graphical interface\n" + + "utilizing the gathered information for the maintenance of DLC unlockers.\n" + + "\n" + + $"The program utilizes the latest versions of [Koaloader]({acidicoala}/Koaloader), [SmokeAPI]({acidicoala}/SmokeAPI), [ScreamAPI]({acidicoala}/ScreamAPI), [Uplay R1 Unlocker]({acidicoala}/UplayR1Unlocker) and [Uplay R2 Unlocker]({acidicoala}/UplayR2Unlocker), all by\n" + + $"the wonderful [acidicoala]({acidicoala}), and all downloaded and embedded into the program itself; no further downloads necessary on your part!\n" + + "\n" + + "NOTE: This program does not automatically download nor install actual DLC files for you. As the title of the program says, it's\n" + + "only a DLC Unlocker installer. Should the game you wish to unlock DLC for not already come with the DLCs installed (very many\n" + + "do not), you have to find, download, and install those yourself. Preferably, you should be referring to the proper cs.rin.ru post for\n" + + "the game(s) you're tinkering with; you'll usually find any answer to your problems there.\n" + + "\n" + + "USAGE:\n" + + " 1. Choose which programs and/or games the program should scan for DLC.\n" + + " The program automatically gathers all installed games from Steam, Epic and Ubisoft directories.\n" + + " 2. Wait for the program to download and install SteamCMD (if you chose a Steam game).\n" + + " 3. Wait for the program to gather and cache the chosen games' information && DLCs.\n" + + " May take some time on the first run; depends on how many DLCs the games you chose have.\n" + + " 4. CAREFULLY select which games' DLCs you wish to unlock.\n" + + " Obviously none of the DLC unlockers are tested for every single game!\n" + + " 5. Choose whether or not to install with Koaloader, and if so then also pick the proxy DLL to use.\n" + + " If the default \'version.dll\' doesn't work, then see [here](https://cs.rin.ru/forum/viewtopic.php?p=2552172#p2552172) to find one that does.\n" + + " 6. Click the \"Generate and Install\" button.\n" + + " 7. Click the \"OK\" button to close the program.\n" + + " 8. If any of the DLC unlockers cause problems with any of the games you installed them on, simply go back\n" + + " to step 5 and select what games you wish you revert changes to, and instead click the \"Uninstall\" button this time.\n" + + "\n" + + $"For reliable and quick assistance, all bugs, crashes and other issues should be referred to the [GitHub Issues]({repository}/issues) page!\n" + + "\n" + + "SteamCMD installation and appinfo cache can be found at [C:\\ProgramData\\CreamInstaller]().\n" + + $"The program automatically and very quickly updates from [GitHub]({repository}) using [Onova](https://github.com/Tyrrrz/Onova). (updates can be ignored)\n" + + $"The program source and other information can be found on [GitHub]({repository})."); + } + + internal void OnActivation(object sender, EventArgs args) => Activate(); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern void SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, + uint uFlags); + + internal void BringToFrontWithoutActivation() + { + bool topMost = TopMost; + SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + if (!topMost) + SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + } + internal void InheritLocation(Form fromForm) { if (fromForm is null) return; int X = fromForm.Location.X + fromForm.Size.Width / 2 - Size.Width / 2; int Y = fromForm.Location.Y + fromForm.Size.Height / 2 - Size.Height / 2; - Location = new(X, Y); + Location = new Point(X, Y); } private void OnKeyPress(object s, KeyPressEventArgs e) @@ -124,7 +127,8 @@ internal class CustomForm : Form using EncoderParameters encoding = new(1); using EncoderParameter encoderParam = new(Encoder.Quality, 100L); encoding.Param[0] = encoderParam; - graphics.CopyFromScreen(new(bounds.Left + 7, bounds.Top), Point.Empty, new(Size.Width - 14, Size.Height - 7)); + graphics.CopyFromScreen(new Point(bounds.Left + 7, bounds.Top), Point.Empty, + new Size(Size.Width - 14, Size.Height - 7)); Clipboard.SetImage(bitmap); e.Handled = true; } diff --git a/CreamInstaller/Components/CustomTreeView.cs b/CreamInstaller/Components/CustomTreeView.cs index ffe9471..4bb415e 100644 --- a/CreamInstaller/Components/CustomTreeView.cs +++ b/CreamInstaller/Components/CustomTreeView.cs @@ -1,25 +1,35 @@ -using CreamInstaller.Resources; - -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; - +using CreamInstaller.Forms; +using CreamInstaller.Resources; using static CreamInstaller.Resources.Resources; -using TreeView = System.Windows.Forms.TreeView; - namespace CreamInstaller.Components; internal class CustomTreeView : TreeView { - private Form form; + private const string koaloaderToggleString = "Koaloader"; + private readonly Dictionary checkBoxBounds = new(); + private readonly Dictionary comboBoxBounds = new(); + + private readonly Dictionary selectionBounds = new(); private SolidBrush backBrush; - private Font comboBoxFont; private ToolStripDropDown comboBoxDropDown; + private Font comboBoxFont; + private Form form; + + internal CustomTreeView() + { + DrawMode = TreeViewDrawMode.OwnerDrawText; + DrawNode += DrawTreeNode; + TreeViewNodeSorter = PlatformIdComparer.NodeName; + Disposed += OnDisposed; + } protected override void WndProc(ref Message m) { @@ -30,14 +40,6 @@ internal class CustomTreeView : TreeView form = FindForm(); } - internal CustomTreeView() : base() - { - DrawMode = TreeViewDrawMode.OwnerDrawText; - DrawNode += new DrawTreeNodeEventHandler(DrawTreeNode); - TreeViewNodeSorter = PlatformIdComparer.NodeName; - Disposed += OnDisposed; - } - private void OnDisposed(object sender, EventArgs e) { backBrush?.Dispose(); @@ -48,72 +50,68 @@ internal class CustomTreeView : TreeView comboBoxDropDown = null; } - private readonly Dictionary selectionBounds = new(); - private readonly Dictionary checkBoxBounds = new(); - private readonly Dictionary comboBoxBounds = 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 = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected && Focused; - Graphics graphics = e.Graphics; - backBrush ??= new(BackColor); + backBrush ??= new SolidBrush(BackColor); Font font = node.NodeFont ?? Font; - Brush brush = highlighted ? SystemBrushes.Highlight : backBrush; - string text;// = e.Node.Text; + string text; // = e.Node.Text; Size size; Rectangle bounds = node.Bounds; Rectangle selectionBounds = bounds; - Color color;// = highlighted ? SystemColors.HighlightText : (node.ForeColor != Color.Empty) ? node.ForeColor : node.TreeView.ForeColor; + Color + color; // = highlighted ? SystemColors.HighlightText : (node.ForeColor != Color.Empty) ? node.ForeColor : node.TreeView.ForeColor; Point point; - /*Size textSize = TextRenderer.MeasureText(text, font); Point textLoc = new(bounds.X - 1, bounds.Y); bounds = new Rectangle(textLoc, new Size(textSize.Width, bounds.Height)); graphics.FillRectangle(brush, bounds); TextRenderer.DrawText(graphics, text, font, bounds, color, TextFormatFlags.Default);*/ - 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; - - color = highlighted ? ColorTranslator.FromHtml("#FFFF99") : Enabled ? ColorTranslator.FromHtml("#696900") : ColorTranslator.FromHtml("#AAAA69"); + color = highlighted + ? ColorTranslator.FromHtml("#FFFF99") + : Enabled + ? ColorTranslator.FromHtml("#696900") + : ColorTranslator.FromHtml("#AAAA69"); text = platform.ToString(); size = TextRenderer.MeasureText(graphics, text, font); - bounds = new(bounds.X + bounds.Width, bounds.Y, size.Width, bounds.Height); - selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width, 0)); + bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y, size.Width, bounds.Height); + selectionBounds + = new Rectangle(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width, 0)); graphics.FillRectangle(brush, bounds); - point = new(bounds.Location.X - 1, bounds.Location.Y + 1); + point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1); TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default); - if (platform is not Platform.Paradox) { - color = highlighted ? ColorTranslator.FromHtml("#99FFFF") : Enabled ? ColorTranslator.FromHtml("#006969") : ColorTranslator.FromHtml("#69AAAA"); - text = platformId.ToString(); + color = highlighted + ? ColorTranslator.FromHtml("#99FFFF") + : Enabled + ? ColorTranslator.FromHtml("#006969") + : ColorTranslator.FromHtml("#69AAAA"); + text = platformId; size = TextRenderer.MeasureText(graphics, text, font); int left = -4; - bounds = new(bounds.X + bounds.Width + left, bounds.Y, size.Width, bounds.Height); - selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0)); + bounds = new Rectangle(bounds.X + bounds.Width + left, bounds.Y, size.Width, bounds.Height); + selectionBounds = new Rectangle(selectionBounds.Location, + selectionBounds.Size + new Size(bounds.Size.Width + left, 0)); graphics.FillRectangle(brush, bounds); - point = new(bounds.Location.X - 1, bounds.Location.Y + 1); + point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1); TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default); } - /*if (highlighted) ControlPaint.DrawFocusRectangle(graphics, selectionBounds, color, SystemColors.Highlight);*/ - if (form is SelectForm) { ProgramSelection selection = ProgramSelection.FromPlatformId(platform, platformId); @@ -121,64 +119,71 @@ internal class CustomTreeView : TreeView { if (bounds == node.Bounds) { - size = new(4, 0); - bounds = new(bounds.X + bounds.Width, bounds.Y, size.Width, bounds.Height); + size = new Size(4, 0); + bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y, size.Width, bounds.Height); graphics.FillRectangle(brush, bounds); } - CheckBoxState checkBoxState = selection.Koaloader ? Enabled ? CheckBoxState.CheckedPressed : CheckBoxState.CheckedDisabled - : Enabled ? CheckBoxState.UncheckedPressed : CheckBoxState.UncheckedDisabled; + : Enabled + ? CheckBoxState.UncheckedPressed + : CheckBoxState.UncheckedDisabled; size = CheckBoxRenderer.GetGlyphSize(graphics, checkBoxState); - bounds = new(bounds.X + bounds.Width, bounds.Y, size.Width, bounds.Height); - selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width, 0)); + bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y, size.Width, bounds.Height); + selectionBounds = new Rectangle(selectionBounds.Location, + selectionBounds.Size + new Size(bounds.Size.Width, 0)); Rectangle checkBoxBounds = bounds; graphics.FillRectangle(backBrush, bounds); - point = new(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1); + point = new Point(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1); CheckBoxRenderer.DrawCheckBox(graphics, point, checkBoxState); - text = koaloaderToggleString; size = TextRenderer.MeasureText(graphics, text, font); int left = 1; - bounds = new(bounds.X + bounds.Width, bounds.Y, size.Width + left, bounds.Height); - selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width, 0)); - checkBoxBounds = new(checkBoxBounds.Location, checkBoxBounds.Size + new Size(bounds.Size.Width, 0)); + bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y, size.Width + left, bounds.Height); + selectionBounds = new Rectangle(selectionBounds.Location, + selectionBounds.Size + new Size(bounds.Size.Width, 0)); + checkBoxBounds = new Rectangle(checkBoxBounds.Location, + checkBoxBounds.Size + new Size(bounds.Size.Width, 0)); graphics.FillRectangle(backBrush, bounds); - point = new(bounds.Location.X - 1 + left, bounds.Location.Y + 1); + point = new Point(bounds.Location.X - 1 + left, bounds.Location.Y + 1); TextRenderer.DrawText(graphics, text, font, point, - Enabled ? ColorTranslator.FromHtml("#006900") : ColorTranslator.FromHtml("#69AA69"), - TextFormatFlags.Default); - + Enabled + ? ColorTranslator.FromHtml("#006900") + : ColorTranslator.FromHtml("#69AA69"), + TextFormatFlags.Default); this.checkBoxBounds[selection] = RectangleToClient(checkBoxBounds); - string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy; if (selection.Koaloader && proxy is not null) { - comboBoxFont ??= new(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, font.GdiVerticalFont); + comboBoxFont ??= new Font(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, + font.GdiVerticalFont); ComboBoxState comboBoxState = Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled; - text = proxy + ".dll"; size = TextRenderer.MeasureText(graphics, text, comboBoxFont) + new Size(6, 0); int padding = 2; - bounds = new(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding); - selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width, 0)); + bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, + bounds.Height - padding); + selectionBounds = new Rectangle(selectionBounds.Location, + selectionBounds.Size + new Size(bounds.Size.Width, 0)); Rectangle comboBoxBounds = bounds; graphics.FillRectangle(backBrush, bounds); ComboBoxRenderer.DrawTextBox(graphics, bounds, text, comboBoxFont, comboBoxState); - - size = new(14, 0); + size = new Size(14, 0); left = -1; - bounds = new(bounds.X + bounds.Width + left, bounds.Y, size.Width, bounds.Height); - selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0)); - comboBoxBounds = new(comboBoxBounds.Location, comboBoxBounds.Size + new Size(bounds.Size.Width + left, 0)); + bounds = new Rectangle(bounds.X + bounds.Width + left, bounds.Y, size.Width, bounds.Height); + selectionBounds = new Rectangle(selectionBounds.Location, + selectionBounds.Size + new Size(bounds.Size.Width + left, 0)); + comboBoxBounds = new Rectangle(comboBoxBounds.Location, + comboBoxBounds.Size + new Size(bounds.Size.Width + left, 0)); ComboBoxRenderer.DrawDropDownButton(graphics, bounds, comboBoxState); - this.comboBoxBounds[selection] = RectangleToClient(comboBoxBounds); } - else _ = comboBoxBounds.Remove(selection); + else + { + _ = comboBoxBounds.Remove(selection); + } } } - this.selectionBounds[node] = RectangleToClient(selectionBounds); } @@ -189,9 +194,10 @@ internal class CustomTreeView : TreeView Point clickPoint = PointToClient(e.Location); SelectForm selectForm = (form ??= FindForm()) as SelectForm; foreach (KeyValuePair pair in selectionBounds.ToList()) - { if (pair.Key.TreeView is null) + { _ = selectionBounds.Remove(pair.Key); + } else if (pair.Key.IsVisible && pair.Value.Contains(clickPoint)) { SelectedNode = pair.Key; @@ -199,23 +205,24 @@ internal class CustomTreeView : TreeView selectForm.OnNodeRightClick(pair.Key, e.Location); break; } - } if (e.Button is MouseButtons.Left) { if (comboBoxBounds.Any() && selectForm is not null) foreach (KeyValuePair pair in comboBoxBounds.ToList()) - { if (!ProgramSelection.All.Contains(pair.Key)) + { _ = comboBoxBounds.Remove(pair.Key); + } else if (pair.Value.Contains(clickPoint)) { List proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")) - .Select(p => - { - p.GetProxyInfoFromIdentifier(out string proxyName, out _); - return proxyName; - }).Distinct().ToList(); - comboBoxDropDown ??= new(); + .Select(p => + { + p.GetProxyInfoFromIdentifier( + out string proxyName, out _); + return proxyName; + }).Distinct().ToList(); + comboBoxDropDown ??= new ToolStripDropDown(); comboBoxDropDown.ShowItemToolTips = false; comboBoxDropDown.Items.Clear(); foreach (string proxy in proxies) @@ -233,26 +240,25 @@ internal class CustomTreeView : TreeView if (canUse) _ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (s, e) => { - pair.Key.KoaloaderProxy = proxy == ProgramSelection.DefaultKoaloaderProxy ? null : proxy; + pair.Key.KoaloaderProxy + = proxy == ProgramSelection.DefaultKoaloaderProxy ? null : proxy; selectForm.OnKoaloaderChanged(); - }) - { Font = comboBoxFont }); + }) { Font = comboBoxFont }); } - comboBoxDropDown.Show(this, PointToScreen(new(pair.Value.Left, pair.Value.Bottom - 1))); + comboBoxDropDown.Show(this, PointToScreen(new Point(pair.Value.Left, pair.Value.Bottom - 1))); break; } - } foreach (KeyValuePair pair in checkBoxBounds.ToList()) - { if (!ProgramSelection.All.Contains(pair.Key)) + { _ = checkBoxBounds.Remove(pair.Key); + } else if (pair.Value.Contains(clickPoint)) { pair.Key.Koaloader = !pair.Key.Koaloader; selectForm.OnKoaloaderChanged(); break; } - } } } } \ No newline at end of file diff --git a/CreamInstaller/Components/PlatformIdComparer.cs b/CreamInstaller/Components/PlatformIdComparer.cs index d27e955..f2b15cd 100644 --- a/CreamInstaller/Components/PlatformIdComparer.cs +++ b/CreamInstaller/Components/PlatformIdComparer.cs @@ -8,45 +8,68 @@ namespace CreamInstaller.Components; internal static class PlatformIdComparer { private static StringComparer stringComparer; - internal static StringComparer String => stringComparer ??= new(); + internal static StringComparer String => stringComparer ??= new StringComparer(); private static NodeComparer nodeComparer; - internal static NodeComparer Node => nodeComparer ??= new(); + internal static NodeComparer Node => nodeComparer ??= new NodeComparer(); private static NodeNameComparer nodeNameComparer; - internal static NodeNameComparer NodeName => nodeNameComparer ??= new(); + internal static NodeNameComparer NodeName => nodeNameComparer ??= new NodeNameComparer(); private static NodeTextComparer nodeTextComparer; - internal static NodeTextComparer NodeText => nodeTextComparer ??= new(); + internal static NodeTextComparer NodeText => nodeTextComparer ??= new NodeTextComparer(); } internal class StringComparer : IComparer { 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; + !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 NodeComparer : IComparer { public int Compare(TreeNode a, TreeNode b) => - a.Tag is not Platform A ? 1 : b.Tag is not Platform B ? -1 - : A > B ? 1 : A < B ? -1 : 0; + a.Tag is not Platform A + ? 1 + : b.Tag is not Platform B + ? -1 + : A > B + ? 1 + : A < B + ? -1 + : 0; } internal class NodeNameComparer : IComparer { public int Compare(object a, object b) => - a is not TreeNode A ? 1 : b is not TreeNode B ? -1 - : PlatformIdComparer.Node.Compare(A, B) is int c && c != 0 ? c - : PlatformIdComparer.String.Compare(A.Name, B.Name); + a is not TreeNode A + ? 1 + : b is not TreeNode B + ? -1 + : PlatformIdComparer.Node.Compare(A, B) is int c && c != 0 + ? c + : PlatformIdComparer.String.Compare(A.Name, B.Name); } internal class NodeTextComparer : IComparer { public int Compare(object a, object b) => - a is not TreeNode A ? 1 : b is not TreeNode B ? -1 - : PlatformIdComparer.Node.Compare(A, B) is int c && c != 0 ? c - : PlatformIdComparer.String.Compare(A.Text, B.Text); + a is not TreeNode A + ? 1 + : b is not TreeNode B + ? -1 + : PlatformIdComparer.Node.Compare(A, B) is int c && c != 0 + ? c + : PlatformIdComparer.String.Compare(A.Text, B.Text); } \ No newline at end of file diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index c50cf6b..1e75f35 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -1,17 +1,16 @@  WinExe - net6.0-windows10.0.22621.0 + net7.0-windows True Resources\ini.ico - 4.2.3.1 + 4.3.0.0 2021, pointfeev (https://github.com/pointfeev) CreamInstaller Automatic DLC Unlocker Installer & Configuration Generator CreamInstaller.Program True - latest-all - 7.0 + latest-recommended AnyCPU true true @@ -27,6 +26,12 @@ $(Company)-debug + + False + + + False + @@ -137,10 +142,10 @@ - - - - + + + + diff --git a/CreamInstaller/Forms/DebugForm.Designer.cs b/CreamInstaller/Forms/DebugForm.Designer.cs index 0830960..3e54019 100644 --- a/CreamInstaller/Forms/DebugForm.Designer.cs +++ b/CreamInstaller/Forms/DebugForm.Designer.cs @@ -1,11 +1,14 @@ -namespace CreamInstaller; +using System.ComponentModel; +using System.Windows.Forms; + +namespace CreamInstaller.Forms; partial class DebugForm { /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private IContainer components = null; /// /// Clean up any resources being used. @@ -65,5 +68,5 @@ partial class DebugForm #endregion - private System.Windows.Forms.RichTextBox debugTextBox; + private RichTextBox debugTextBox; } \ No newline at end of file diff --git a/CreamInstaller/Forms/DebugForm.cs b/CreamInstaller/Forms/DebugForm.cs index 27429de..6d8c389 100644 --- a/CreamInstaller/Forms/DebugForm.cs +++ b/CreamInstaller/Forms/DebugForm.cs @@ -1,32 +1,34 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using System; +using System; using System.Drawing; using System.Windows.Forms; +using CreamInstaller.Components; +using CreamInstaller.Utility; -namespace CreamInstaller; +namespace CreamInstaller.Forms; internal partial class DebugForm : CustomForm { internal static DebugForm current; + + private Form attachedForm; + + internal DebugForm() + { + InitializeComponent(); + debugTextBox.BackColor = LogTextBox.Background; + } + internal static DebugForm Current { get { if (current is not null && (current.Disposing || current.IsDisposed)) current = null; - return current ??= new(); + return current ??= new DebugForm(); } set => current = value; } - internal DebugForm() : base() - { - InitializeComponent(); - debugTextBox.BackColor = LogTextBox.Background; - } - protected override void WndProc(ref Message message) // make form immovable by user { if (message.Msg == 0x0112) // WM_SYSCOMMAND @@ -38,8 +40,6 @@ internal partial class DebugForm : CustomForm base.WndProc(ref message); } - private Form attachedForm; - internal void Attach(Form form) { if (attachedForm is not null) @@ -64,7 +64,7 @@ internal partial class DebugForm : CustomForm if (attachedForm is not null && attachedForm.Visible) { //Size = new(Size.Width, attachedForm.Size.Height); - Location = new(attachedForm.Right, attachedForm.Top); + Location = new Point(attachedForm.Right, attachedForm.Top); BringToFrontWithoutActivation(); } } @@ -74,13 +74,11 @@ internal partial class DebugForm : CustomForm internal void Log(string text, Color color) { if (!debugTextBox.Disposing && !debugTextBox.IsDisposed) - { debugTextBox.Invoke(() => { if (debugTextBox.Text.Length > 0) - debugTextBox.AppendText(Environment.NewLine, color, scroll: true); - debugTextBox.AppendText(text, color, scroll: true); + debugTextBox.AppendText(Environment.NewLine, color, true); + debugTextBox.AppendText(text, color, true); }); - } } } diff --git a/CreamInstaller/Forms/DialogForm.Designer.cs b/CreamInstaller/Forms/DialogForm.Designer.cs index d051fd3..e37a8db 100644 --- a/CreamInstaller/Forms/DialogForm.Designer.cs +++ b/CreamInstaller/Forms/DialogForm.Designer.cs @@ -1,8 +1,7 @@ - -using System.ComponentModel; +using System.ComponentModel; using System.Windows.Forms; -namespace CreamInstaller +namespace CreamInstaller.Forms { partial class DialogForm { diff --git a/CreamInstaller/Forms/DialogForm.cs b/CreamInstaller/Forms/DialogForm.cs index 13f9c44..b28e247 100644 --- a/CreamInstaller/Forms/DialogForm.cs +++ b/CreamInstaller/Forms/DialogForm.cs @@ -1,31 +1,30 @@ -using CreamInstaller.Components; - -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Windows.Forms; +using CreamInstaller.Components; -namespace CreamInstaller; +namespace CreamInstaller.Forms; internal partial class DialogForm : CustomForm { internal DialogForm(IWin32Window owner) : base(owner) => InitializeComponent(); - internal DialogResult Show(Icon descriptionIcon, string descriptionText, string acceptButtonText = "OK", string cancelButtonText = null, string customFormText = null, Icon customFormIcon = null) + internal DialogResult Show(Icon descriptionIcon, string descriptionText, string acceptButtonText = "OK", + string cancelButtonText = null, string customFormText = null, Icon customFormIcon = null) { descriptionIcon ??= Icon; icon.Image = descriptionIcon.ToBitmap(); List links = new(); for (int i = 0; i < descriptionText.Length; i++) - { if (descriptionText[i] == '[') { - int textLeft = descriptionText.IndexOf("[", i); - int textRight = descriptionText.IndexOf("]", textLeft == -1 ? i : textLeft); - int linkLeft = descriptionText.IndexOf("(", textRight == -1 ? i : textRight); - int linkRight = descriptionText.IndexOf(")", linkLeft == -1 ? i : linkLeft); + int textLeft = descriptionText.IndexOf("[", i, StringComparison.Ordinal); + int textRight = descriptionText.IndexOf("]", textLeft == -1 ? i : textLeft, StringComparison.Ordinal); + int linkLeft = descriptionText.IndexOf("(", textRight == -1 ? i : textRight, StringComparison.Ordinal); + int linkRight = descriptionText.IndexOf(")", linkLeft == -1 ? i : linkLeft, StringComparison.Ordinal); if (textLeft != -1 && textRight == linkLeft - 1 && linkRight != -1) { string text = descriptionText[(textLeft + 1)..textRight]; @@ -36,7 +35,6 @@ internal partial class DialogForm : CustomForm links.Add(new LinkLabel.Link(i, text.Length, link)); } } - } descriptionLabel.Text = descriptionText; acceptButton.Text = acceptButtonText; if (cancelButtonText is null) @@ -44,9 +42,14 @@ internal partial class DialogForm : CustomForm cancelButton.Enabled = false; cancelButton.Visible = false; } - else cancelButton.Text = cancelButtonText; + else + { + cancelButton.Text = cancelButtonText; + } if (customFormText is not null) + { Text = customFormText; + } else { OnResize(null, null); @@ -58,7 +61,8 @@ internal partial class DialogForm : CustomForm { foreach (LinkLabel.Link link in links) _ = descriptionLabel.Links.Add(link); - descriptionLabel.LinkClicked += (s, e) => Process.Start(new ProcessStartInfo((string)e.Link.LinkData) { UseShellExecute = true }); + descriptionLabel.LinkClicked += (s, e) + => Process.Start(new ProcessStartInfo((string)e.Link.LinkData) { UseShellExecute = true }); } return ShowDialog(); } @@ -66,7 +70,7 @@ internal partial class DialogForm : CustomForm private void OnResize(object s, EventArgs e) => Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100 ? TextRenderer.MeasureText(Program.ApplicationNameShort, Font).Width > Size.Width - 100 - ? Program.Name - : Program.ApplicationNameShort + ? Program.Name + : Program.ApplicationNameShort : Program.ApplicationName; } diff --git a/CreamInstaller/Forms/InstallForm.Designer.cs b/CreamInstaller/Forms/InstallForm.Designer.cs index 79b43ca..c9f3e36 100644 --- a/CreamInstaller/Forms/InstallForm.Designer.cs +++ b/CreamInstaller/Forms/InstallForm.Designer.cs @@ -1,8 +1,7 @@ - -using System.ComponentModel; +using System.ComponentModel; using System.Windows.Forms; -namespace CreamInstaller +namespace CreamInstaller.Forms { partial class InstallForm { diff --git a/CreamInstaller/Forms/InstallForm.cs b/CreamInstaller/Forms/InstallForm.cs index 0587f17..8d1adf5 100644 --- a/CreamInstaller/Forms/InstallForm.cs +++ b/CreamInstaller/Forms/InstallForm.cs @@ -1,26 +1,30 @@ -using CreamInstaller.Components; -using CreamInstaller.Resources; -using CreamInstaller.Utility; - -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; - +using CreamInstaller.Components; +using CreamInstaller.Resources; +using CreamInstaller.Utility; using static CreamInstaller.Platforms.Paradox.ParadoxLauncher; using static CreamInstaller.Resources.Resources; -namespace CreamInstaller; +namespace CreamInstaller.Forms; internal partial class InstallForm : CustomForm { - internal bool Reselecting; - internal readonly bool Uninstalling; + private readonly List DisabledSelections = new(); - internal InstallForm(bool uninstall = false) : base() + private readonly int ProgramCount = ProgramSelection.AllEnabled.Count; + internal readonly bool Uninstalling; + private int CompleteOperationsCount; + + private int OperationsCount; + internal bool Reselecting; + + internal InstallForm(bool uninstall = false) { InitializeComponent(); Text = Program.ApplicationName; @@ -28,9 +32,6 @@ internal partial class InstallForm : CustomForm Uninstalling = uninstall; } - private int OperationsCount; - private int CompleteOperationsCount; - internal void UpdateProgress(int progress) { if (!userProgressBar.Disposing && !userProgressBar.IsDisposed) @@ -46,14 +47,12 @@ internal partial class InstallForm : CustomForm { if (info) _ = userInfoLabel.Invoke(() => userInfoLabel.Text = text); if (log && !logTextBox.Disposing && !logTextBox.IsDisposed) - { logTextBox.Invoke(() => { if (logTextBox.Text.Length > 0) logTextBox.AppendText(Environment.NewLine, color); logTextBox.AppendText(text, color); logTextBox.Invalidate(); }); - } } private async Task OperateFor(ProgramSelection selection) @@ -61,14 +60,16 @@ internal partial class InstallForm : CustomForm UpdateProgress(0); if (selection.Id == "PL") { - UpdateUser($"Repairing Paradox Launcher . . . ", LogTextBox.Operation); + UpdateUser("Repairing Paradox Launcher . . . ", LogTextBox.Operation); _ = await Repair(this, selection); } UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")}" + - $" {(Uninstalling ? "from" : "for")} " + selection.Name + $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation); + $" {(Uninstalling ? "from" : "for")} " + selection.Name + + $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation); IEnumerable invalidDirectories = (await selection.RootDirectory.GetExecutables()) - ?.Where(d => !selection.ExecutableDirectories.Any(s => s.directory == Path.GetDirectoryName(d.path))) - ?.Select(d => Path.GetDirectoryName(d.path)); + ?.Where(d => !selection.ExecutableDirectories.Any( + s => s.directory == Path.GetDirectoryName(d.path))) + ?.Select(d => Path.GetDirectoryName(d.path)); if (!selection.ExecutableDirectories.Any(s => s.directory == selection.RootDirectory)) invalidDirectories = invalidDirectories?.Append(selection.RootDirectory); invalidDirectories = invalidDirectories?.Distinct(); @@ -78,30 +79,33 @@ internal partial class InstallForm : CustomForm if (Program.Canceled) throw new CustomMessageException("The operation was canceled."); directory.GetKoaloaderComponents(out List proxies, out string config); if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader)) - || directory != selection.RootDirectory && Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) - || File.Exists(config)) + || (directory != selection.RootDirectory + && Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll))) + || File.Exists(config)) { - UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation); - await Koaloader.Uninstall(directory, rootDirectory: selection.RootDirectory, this); + UpdateUser("Uninstalling Koaloader from " + selection.Name + + $" in incorrect directory \"{directory}\" . . . ", + LogTextBox.Operation); + await Koaloader.Uninstall(directory, selection.RootDirectory, this); } Thread.Sleep(1); } if (Uninstalling || !selection.Koaloader) - { foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories) { if (Program.Canceled) throw new CustomMessageException("The operation was canceled."); directory.GetKoaloaderComponents(out List proxies, out string config); if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader)) - || Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) - || File.Exists(config)) + || Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) + || File.Exists(config)) { - UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); - await Koaloader.Uninstall(directory, rootDirectory: selection.RootDirectory, this); + UpdateUser( + "Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", + LogTextBox.Operation); + await Koaloader.Uninstall(directory, selection.RootDirectory, this); } Thread.Sleep(1); } - } bool uninstallProxy = Uninstalling || selection.Koaloader; int count = selection.DllDirectories.Count, cur = 0; foreach (string directory in selection.DllDirectories) @@ -109,11 +113,15 @@ internal partial class InstallForm : CustomForm if (Program.Canceled) throw new CustomMessageException("The operation was canceled."); if (selection.Platform is Platform.Steam or Platform.Paradox) { - 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_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache) : File.Exists(api32) || File.Exists(api64)) + 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_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache) + : File.Exists(api32) || File.Exists(api64)) { UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" + - $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); if (uninstallProxy) await SmokeAPI.Uninstall(directory, this); else @@ -122,11 +130,15 @@ internal partial class InstallForm : CustomForm } if (selection.Platform is Platform.Epic or Platform.Paradox) { - directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); - if (uninstallProxy ? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) : File.Exists(api32) || File.Exists(api64)) + directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, + out string api64_o, out string config); + if (uninstallProxy + ? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) + : File.Exists(api32) || File.Exists(api64)) { UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" + - $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); if (uninstallProxy) await ScreamAPI.Uninstall(directory, this); else @@ -135,21 +147,29 @@ internal partial class InstallForm : CustomForm } 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_o) || File.Exists(api64_o) || File.Exists(config) : File.Exists(api32) || File.Exists(api64)) + directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, + out string api64_o, out string config); + if (uninstallProxy + ? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) + : File.Exists(api32) || File.Exists(api64)) { UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + - $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + + $" in directory \"{directory}\" . . . ", LogTextBox.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(api32_o) || File.Exists(api64_o) || File.Exists(config) : File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api64)) + 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(api32_o) || File.Exists(api64_o) || File.Exists(config) + : File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api64)) { UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + - $" {(uninstallProxy ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); + $" {(uninstallProxy ? "from" : "for")} " + selection.Name + + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); if (uninstallProxy) await UplayR2.Uninstall(directory, this); else @@ -160,20 +180,17 @@ internal partial class InstallForm : CustomForm Thread.Sleep(1); } if (selection.Koaloader && !Uninstalling) - { foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories) { if (Program.Canceled) throw new CustomMessageException("The operation was canceled."); - UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); - await Koaloader.Install(directory, binaryType, selection, rootDirectory: selection.RootDirectory, this); + UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", + LogTextBox.Operation); + await Koaloader.Install(directory, binaryType, selection, selection.RootDirectory, this); Thread.Sleep(1); } - } UpdateProgress(100); } - private readonly List DisabledSelections = new(); - private async Task Operate() { List programSelections = ProgramSelection.AllEnabled; @@ -181,7 +198,8 @@ internal partial class InstallForm : CustomForm CompleteOperationsCount = 0; foreach (ProgramSelection selection in programSelections) { - if (Program.Canceled || !Program.IsProgramRunningDialog(this, selection)) throw new CustomMessageException("The operation was canceled."); + if (Program.Canceled || !Program.IsProgramRunningDialog(this, selection)) + throw new CustomMessageException("The operation was canceled."); try { await OperateFor(selection); @@ -207,8 +225,6 @@ internal partial class InstallForm : CustomForm DisabledSelections.Clear(); } - private readonly int ProgramCount = ProgramSelection.AllEnabled.Count; - private async void Start() { Program.Canceled = false; @@ -220,11 +236,13 @@ internal partial class InstallForm : CustomForm try { await Operate(); - UpdateUser($"DLC unlocker(s) successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + ProgramCount + " program(s).", LogTextBox.Success); + UpdateUser($"DLC unlocker(s) successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + + ProgramCount + " program(s).", LogTextBox.Success); } catch (Exception exception) { - UpdateUser($"DLC unlocker {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception, LogTextBox.Error); + UpdateUser($"DLC unlocker {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + + exception, LogTextBox.Error); retryButton.Enabled = true; } userProgressBar.Value = userProgressBar.Maximum; @@ -235,7 +253,7 @@ internal partial class InstallForm : CustomForm private void OnLoad(object sender, EventArgs _) { - retry: + retry: try { userInfoLabel.Text = "Loading . . . "; @@ -244,7 +262,7 @@ internal partial class InstallForm : CustomForm } catch (Exception e) { - if (e.HandleException(form: this)) goto retry; + if (e.HandleException(this)) goto retry; Close(); } } diff --git a/CreamInstaller/Forms/MainForm.Designer.cs b/CreamInstaller/Forms/MainForm.Designer.cs index 14a84b4..946069b 100644 --- a/CreamInstaller/Forms/MainForm.Designer.cs +++ b/CreamInstaller/Forms/MainForm.Designer.cs @@ -1,11 +1,8 @@ - -using System; -using System.ComponentModel; +using System.ComponentModel; using System.Windows.Forms; - using CreamInstaller.Components; -namespace CreamInstaller +namespace CreamInstaller.Forms { partial class MainForm { diff --git a/CreamInstaller/Forms/MainForm.cs b/CreamInstaller/Forms/MainForm.cs index 4b6d6db..0d5b8ee 100644 --- a/CreamInstaller/Forms/MainForm.cs +++ b/CreamInstaller/Forms/MainForm.cs @@ -1,13 +1,4 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using HtmlAgilityPack; - -using Onova; -using Onova.Models; -using Onova.Services; - -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -16,19 +7,29 @@ using System.Threading; using System.Threading.Tasks; using System.Web; using System.Windows.Forms; +using CreamInstaller.Components; +using CreamInstaller.Utility; +using HtmlAgilityPack; +using Onova; +using Onova.Models; +using Onova.Services; -namespace CreamInstaller; +namespace CreamInstaller.Forms; internal partial class MainForm : CustomForm { - internal MainForm() : base() + private CancellationTokenSource cancellationTokenSource; + private Version latestVersion; + + private UpdateManager updateManager; + private IReadOnlyList versions; + + internal MainForm() { InitializeComponent(); Text = Program.ApplicationNameShort; } - private CancellationTokenSource cancellationTokenSource; - private void StartProgram() { if (cancellationTokenSource is not null) @@ -49,10 +50,6 @@ internal partial class MainForm : CustomForm #endif } - private UpdateManager updateManager; - private Version latestVersion; - private IReadOnlyList versions; - private async void OnLoad() { progressBar.Visible = false; @@ -61,18 +58,22 @@ internal partial class MainForm : CustomForm updateButton.Click -= OnUpdateCancel; progressLabel.Text = "Checking for updates . . ."; changelogTreeView.Visible = false; - changelogTreeView.Location = new(progressLabel.Location.X, progressLabel.Location.Y + progressLabel.Size.Height + 13); + changelogTreeView.Location = new Point(progressLabel.Location.X, + progressLabel.Location.Y + progressLabel.Size.Height + 13); Refresh(); #if DEBUG DebugForm.Current.Attach(this); #endif - GithubPackageResolver resolver = new(Program.RepositoryOwner, Program.RepositoryName, Program.RepositoryPackage); + GithubPackageResolver resolver = new(Program.RepositoryOwner, Program.RepositoryName, + Program.RepositoryPackage); ZipPackageExtractor extractor = new(); - updateManager = new(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath), resolver, extractor); + updateManager + = new UpdateManager(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath), + resolver, extractor); if (latestVersion is null) { CheckForUpdatesResult checkForUpdatesResult = null; - cancellationTokenSource = new(); + cancellationTokenSource = new CancellationTokenSource(); try { checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token); @@ -80,8 +81,8 @@ internal partial class MainForm : CustomForm if (checkForUpdatesResult.CanUpdate) { #endif - latestVersion = checkForUpdatesResult.LastVersion; - versions = checkForUpdatesResult.Versions; + latestVersion = checkForUpdatesResult.LastVersion; + versions = checkForUpdatesResult.Versions; #if !DEBUG } #endif @@ -90,7 +91,8 @@ internal partial class MainForm : CustomForm catch (TaskCanceledException) { } catch (Exception e) { - DebugForm.Current.Log($"Exception while checking for updates: {e.GetType()} ({e.Message})", LogTextBox.Warning); + DebugForm.Current.Log($"Exception while checking for updates: {e.GetType()} ({e.Message})", + LogTextBox.Warning); } #else catch { } @@ -112,19 +114,17 @@ internal partial class MainForm : CustomForm progressLabel.Text = $"An update is available: v{latestVersion}"; ignoreButton.Enabled = true; updateButton.Enabled = true; - updateButton.Click += new(OnUpdate); + updateButton.Click += OnUpdate; changelogTreeView.Visible = true; Version currentVersion = new(Program.Version); #if DEBUG - foreach (Version version in versions.Where(v => (v > currentVersion || v == latestVersion) && !changelogTreeView.Nodes.ContainsKey(v.ToString()))) + foreach (Version version in versions.Where(v => (v > currentVersion || v == latestVersion) + && !changelogTreeView.Nodes.ContainsKey(v.ToString()))) #else foreach (Version version in versions.Where(v => v > currentVersion && !changelogTreeView.Nodes.ContainsKey(v.ToString()))) #endif { - TreeNode root = new($"v{version}") - { - Name = version.ToString() - }; + TreeNode root = new($"v{version}") { Name = version.ToString() }; changelogTreeView.Nodes.Add(root); if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible(); @@ -137,19 +137,14 @@ internal partial class MainForm : CustomForm changelogTreeView.Nodes.Remove(root); else foreach (HtmlNode node in nodes) - { changelogTreeView.Invoke(delegate { - TreeNode change = new() - { - Text = HttpUtility.HtmlDecode(node.InnerText) - }; + TreeNode change = new() { Text = HttpUtility.HtmlDecode(node.InnerText) }; root.Nodes.Add(change); root.Expand(); if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible(); }); - } }); } } @@ -157,7 +152,7 @@ internal partial class MainForm : CustomForm private void OnLoad(object sender, EventArgs _) { - retry: + retry: try { string FileName = Path.GetFileName(Program.CurrentProcessFilePath); @@ -165,9 +160,9 @@ internal partial class MainForm : CustomForm { using DialogForm form = new(this); if (form.Show(SystemIcons.Warning, - "WARNING: " + Program.ApplicationExecutable + " was renamed!" + - "\n\nThis will cause undesirable behavior when updating the program!", - "Ignore", "Abort") == DialogResult.Cancel) + "WARNING: " + Program.ApplicationExecutable + " was renamed!" + + "\n\nThis will cause undesirable behavior when updating the program!", + "Ignore", "Abort") == DialogResult.Cancel) { Application.Exit(); return; @@ -177,7 +172,7 @@ internal partial class MainForm : CustomForm } catch (Exception e) { - if (e.HandleException(form: this)) goto retry; + if (e.HandleException(this)) goto retry; Close(); } } @@ -190,19 +185,18 @@ internal partial class MainForm : CustomForm ignoreButton.Visible = false; updateButton.Text = "Cancel"; updateButton.Click -= OnUpdate; - updateButton.Click += new(OnUpdateCancel); - changelogTreeView.Location = new(progressBar.Location.X, progressBar.Location.Y + progressBar.Size.Height + 6); + updateButton.Click += OnUpdateCancel; + changelogTreeView.Location + = new Point(progressBar.Location.X, progressBar.Location.Y + progressBar.Size.Height + 6); Refresh(); - Progress progress = new(); - progress.ProgressChanged += new(delegate (object sender, double _progress) + progress.ProgressChanged += delegate(object sender, double _progress) { progressLabel.Text = $"Updating . . . {(int)_progress}%"; progressBar.Value = (int)_progress; - }); - + }; progressLabel.Text = "Updating . . . "; - cancellationTokenSource = new(); + cancellationTokenSource = new CancellationTokenSource(); try { await updateManager.PrepareUpdateAsync(latestVersion, progress, cancellationTokenSource.Token); @@ -211,7 +205,8 @@ internal partial class MainForm : CustomForm catch (TaskCanceledException) { } catch (Exception ex) { - DebugForm.Current.Log($"Exception while preparing update: {ex.GetType()} ({ex.Message})", LogTextBox.Warning); + DebugForm.Current.Log($"Exception while preparing update: {ex.GetType()} ({ex.Message})", + LogTextBox.Warning); } #else catch { } @@ -221,14 +216,13 @@ internal partial class MainForm : CustomForm cancellationTokenSource.Dispose(); cancellationTokenSource = null; } - if (updateManager is not null && updateManager.IsUpdatePrepared(latestVersion)) { updateManager.LaunchUpdater(latestVersion); Application.Exit(); return; } - else OnLoad(); + OnLoad(); } private void OnUpdateCancel(object sender, EventArgs e) diff --git a/CreamInstaller/Forms/SelectDialogForm.Designer.cs b/CreamInstaller/Forms/SelectDialogForm.Designer.cs index 84c9c7c..1869b17 100644 --- a/CreamInstaller/Forms/SelectDialogForm.Designer.cs +++ b/CreamInstaller/Forms/SelectDialogForm.Designer.cs @@ -1,10 +1,8 @@ - +using System.ComponentModel; +using System.Windows.Forms; using CreamInstaller.Components; -using System.ComponentModel; -using System.Windows.Forms; - -namespace CreamInstaller +namespace CreamInstaller.Forms { partial class SelectDialogForm { diff --git a/CreamInstaller/Forms/SelectDialogForm.cs b/CreamInstaller/Forms/SelectDialogForm.cs index e31e5f7..8e71d29 100644 --- a/CreamInstaller/Forms/SelectDialogForm.cs +++ b/CreamInstaller/Forms/SelectDialogForm.cs @@ -1,20 +1,19 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using System; +using System; using System.Collections.Generic; -using System.Drawing; using System.Linq; using System.Windows.Forms; +using CreamInstaller.Components; +using CreamInstaller.Utility; -namespace CreamInstaller; +namespace CreamInstaller.Forms; internal partial class SelectDialogForm : CustomForm { + private readonly List<(Platform platform, string id, string name)> selected = new(); internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent(); - private readonly List<(Platform platform, string id, string name)> selected = new(); - internal List<(Platform platform, string id, string name)> QueryUser(string groupBoxText, List<(Platform 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; groupBox.Text = groupBoxText; @@ -23,13 +22,7 @@ internal partial class SelectDialogForm : CustomForm selectionTreeView.AfterCheck += OnTreeNodeChecked; foreach ((Platform platform, string id, string name, bool alreadySelected) in choices) { - TreeNode node = new() - { - Tag = platform, - Name = id, - Text = name, - Checked = alreadySelected - }; + TreeNode node = new() { Tag = platform, Name = id, Text = name, Checked = alreadySelected }; OnTreeNodeChecked(node); _ = selectionTreeView.Nodes.Add(node); } diff --git a/CreamInstaller/Forms/SelectForm.Designer.cs b/CreamInstaller/Forms/SelectForm.Designer.cs index 07d1245..bedda3b 100644 --- a/CreamInstaller/Forms/SelectForm.Designer.cs +++ b/CreamInstaller/Forms/SelectForm.Designer.cs @@ -1,10 +1,8 @@ -using System; +using System.ComponentModel; using System.Windows.Forms; -using System.Drawing; -using System.ComponentModel; using CreamInstaller.Components; -namespace CreamInstaller +namespace CreamInstaller.Forms { partial class SelectForm { diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 5f444ff..6e3cde6 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -1,15 +1,5 @@ #pragma warning disable IDE0058 -using CreamInstaller.Components; -using CreamInstaller.Platforms.Epic; -using CreamInstaller.Platforms.Paradox; -using CreamInstaller.Platforms.Steam; -using CreamInstaller.Platforms.Ubisoft; -using CreamInstaller.Resources; -using CreamInstaller.Utility; - -using Gameloop.Vdf.Linq; - using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -20,26 +10,45 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; - +using CreamInstaller.Components; +using CreamInstaller.Platforms.Epic; +using CreamInstaller.Platforms.Paradox; +using CreamInstaller.Platforms.Steam; +using CreamInstaller.Platforms.Ubisoft; +using CreamInstaller.Resources; +using CreamInstaller.Utility; +using Gameloop.Vdf.Linq; using static CreamInstaller.Resources.Resources; -namespace CreamInstaller; +namespace CreamInstaller.Forms; internal partial class SelectForm : CustomForm { - internal SelectForm() : base() + private readonly string helpButtonListPrefix = "\n • "; + + private readonly SynchronizedCollection RemainingDLCs = new(); + + private readonly SynchronizedCollection RemainingGames = new(); + + private List<(Platform platform, string id, string name)> ProgramsToScan; + + internal SelectForm() { InitializeComponent(); Text = Program.ApplicationName; } - public override ContextMenuStrip ContextMenuStrip => base.ContextMenuStrip ??= new(); + public override ContextMenuStrip ContextMenuStrip => base.ContextMenuStrip ??= new ContextMenuStrip(); + + internal List TreeNodes => GatherTreeNodes(selectionTreeView.Nodes); private static void UpdateRemaining(Label label, SynchronizedCollection list, string descriptor) => - label.Text = list.Any() ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") : ""; + label.Text = list.Any() + ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") + : ""; - private readonly SynchronizedCollection RemainingGames = new(); private void UpdateRemainingGames() => UpdateRemaining(progressLabelGames, RemainingGames, "games"); + private void AddToRemainingGames(string gameName) { if (Program.Canceled) return; @@ -51,6 +60,7 @@ internal partial class SelectForm : CustomForm UpdateRemainingGames(); }); } + private void RemoveFromRemainingGames(string gameName) { if (Program.Canceled) return; @@ -62,8 +72,8 @@ internal partial class SelectForm : CustomForm }); } - private readonly SynchronizedCollection RemainingDLCs = new(); private void UpdateRemainingDLCs() => UpdateRemaining(progressLabelDLCs, RemainingDLCs, "DLCs"); + private void AddToRemainingDLCs(string dlcId) { if (Program.Canceled) return; @@ -75,6 +85,7 @@ internal partial class SelectForm : CustomForm UpdateRemainingDLCs(); }); } + private void RemoveFromRemainingDLCs(string dlcId) { if (Program.Canceled) return; @@ -109,21 +120,23 @@ internal partial class SelectForm : CustomForm List appTasks = new(); if (ProgramsToScan.Any(c => c.platform is Platform.Paradox)) { - List dllDirectories = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox); + List dllDirectories + = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox); if (dllDirectories is not null) { ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL"); - selection ??= new(); + selection ??= new ProgramSelection(); if (allCheckBox.Checked) selection.Enabled = true; if (koaloaderAllCheckBox.Checked) selection.Koaloader = true; selection.Id = "PL"; selection.Name = "Paradox Launcher"; selection.RootDirectory = ParadoxLauncher.InstallPath; - selection.ExecutableDirectories = await ParadoxLauncher.GetExecutableDirectories(selection.RootDirectory); + selection.ExecutableDirectories + = await ParadoxLauncher.GetExecutableDirectories(selection.RootDirectory); selection.DllDirectories = dllDirectories; selection.Platform = Platform.Paradox; - - TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Paradox && s.Name == selection.Id) ?? new(); + TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Paradox && s.Name == selection.Id) + ?? new TreeNode(); programNode.Tag = selection.Platform; programNode.Name = selection.Id; programNode.Text = selection.Name; @@ -135,12 +148,14 @@ internal partial class SelectForm : CustomForm 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(); + List<(string appId, string name, string branch, int buildId, string gameDirectory)> steamGames + = await SteamLibrary.GetGames(); 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)) + if (Program.IsGameBlocked(name, gameDirectory) + || !ProgramsToScan.Any(c => c.platform is Platform.Steam && c.id == appId)) { Interlocked.Decrement(ref steamGamesToCheck); continue; @@ -149,7 +164,8 @@ internal partial class SelectForm : CustomForm Task task = Task.Run(async () => { if (Program.Canceled) return; - List dllDirectories = await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Steam); + List dllDirectories + = await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Steam); if (dllDirectories is null) { Interlocked.Decrement(ref steamGamesToCheck); @@ -199,11 +215,15 @@ internal partial class SelectForm : CustomForm if (dlcAppInfo is not null) { dlcName = dlcAppInfo.Value?.GetChild("common")?.GetChild("name")?.ToString(); - string dlcIconStaticId = dlcAppInfo.Value?.GetChild("common")?.GetChild("icon")?.ToString(); - dlcIconStaticId ??= dlcAppInfo.Value?.GetChild("common")?.GetChild("logo_small")?.ToString(); - dlcIconStaticId ??= dlcAppInfo.Value?.GetChild("common")?.GetChild("logo")?.ToString(); + string dlcIconStaticId = dlcAppInfo.Value?.GetChild("common")?.GetChild("icon") + ?.ToString(); + dlcIconStaticId ??= dlcAppInfo.Value?.GetChild("common")?.GetChild("logo_small") + ?.ToString(); + dlcIconStaticId ??= dlcAppInfo.Value?.GetChild("common")?.GetChild("logo") + ?.ToString(); if (dlcIconStaticId is not null) - dlcIcon = IconGrabber.SteamAppImagesPath + @$"\{dlcAppId}\{dlcIconStaticId}.jpg"; + dlcIcon = IconGrabber.SteamAppImagesPath + + @$"\{dlcAppId}\{dlcIconStaticId}.jpg"; } } if (Program.Canceled) return; @@ -227,27 +247,32 @@ internal partial class SelectForm : CustomForm await task; } steamGamesToCheck = 0; - - ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Steam, appId) ?? new(); - selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); + ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Steam, appId) + ?? new ProgramSelection(); + 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; - selection.ExecutableDirectories = await SteamLibrary.GetExecutableDirectories(selection.RootDirectory); + selection.ExecutableDirectories + = await SteamLibrary.GetExecutableDirectories(selection.RootDirectory); selection.DllDirectories = dllDirectories; selection.Platform = Platform.Steam; selection.ProductUrl = "https://store.steampowered.com/app/" + appId; - 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.Publisher = appData?.publishers[0] ?? appInfo?.Value?.GetChild("extended")?.GetChild("publisher")?.ToString(); + 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.Publisher = appData?.publishers[0] + ?? appInfo?.Value?.GetChild("extended")?.GetChild("publisher")?.ToString(); selection.WebsiteUrl = appData?.website; - if (Program.Canceled) return; selectionTreeView.Invoke(delegate { if (Program.Canceled) return; - TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Steam && s.Name == appId) ?? new(); + TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Steam && s.Name == appId) + ?? new TreeNode(); programNode.Tag = selection.Platform; programNode.Name = appId; programNode.Text = appData?.name ?? name; @@ -261,7 +286,8 @@ internal partial class SelectForm : CustomForm (DlcType type, string name, string icon) dlcApp = pair.Value; selection.AllDlc[appId] = dlcApp; if (allCheckBox.Checked && dlcApp.name != "Unknown") selection.SelectedDlc[appId] = dlcApp; - TreeNode dlcNode = treeNodes.Find(s => s.Tag is Platform.Steam && s.Name == appId) ?? new(); + TreeNode dlcNode = treeNodes.Find(s => s.Tag is Platform.Steam && s.Name == appId) + ?? new TreeNode(); dlcNode.Tag = selection.Platform; dlcNode.Name = appId; dlcNode.Text = dlcApp.name; @@ -285,7 +311,8 @@ internal partial class SelectForm : CustomForm string name = manifest.DisplayName; string directory = manifest.InstallLocation; if (Program.Canceled) return; - if (Program.IsGameBlocked(name, directory) || !ProgramsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace)) continue; + if (Program.IsGameBlocked(name, directory) + || !ProgramsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace)) continue; AddToRemainingGames(name); Task task = Task.Run(async () => { @@ -297,12 +324,14 @@ internal partial class SelectForm : CustomForm return; } if (Program.Canceled) return; - ConcurrentDictionary entitlements = new(); + ConcurrentDictionary + entitlements = new(); List dlcTasks = new(); - List<(string id, string name, string product, string icon, string developer)> entitlementIds = await EpicStore.QueryEntitlements(@namespace); + List<(string id, string name, string product, string icon, string developer)> entitlementIds + = await EpicStore.QueryEntitlements(@namespace); if (entitlementIds.Any()) - { - foreach ((string id, string name, string product, string icon, string developer) in entitlementIds) + foreach ((string id, string name, string product, string icon, string developer) in + entitlementIds) { if (Program.Canceled) return; AddToRemainingDLCs(id); @@ -314,8 +343,7 @@ internal partial class SelectForm : CustomForm }); dlcTasks.Add(task); } - } - if (/*!catalogItems.Any() && */!entitlements.Any()) + if ( /*!catalogItems.Any() && */!entitlements.Any()) { RemoveFromRemainingGames(name); return; @@ -326,28 +354,31 @@ internal partial class SelectForm : CustomForm if (Program.Canceled) return; await task; } - - ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Epic, @namespace) ?? new(); - selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); + ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Epic, @namespace) + ?? new ProgramSelection(); + 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; - selection.ExecutableDirectories = await EpicLibrary.GetExecutableDirectories(selection.RootDirectory); + selection.ExecutableDirectories + = await EpicLibrary.GetExecutableDirectories(selection.RootDirectory); selection.DllDirectories = dllDirectories; selection.Platform = Platform.Epic; - foreach (KeyValuePair pair in entitlements.Where(p => p.Value.name == selection.Name)) + foreach (KeyValuePair pair in + entitlements.Where(p => p.Value.name == selection.Name)) { selection.ProductUrl = "https://www.epicgames.com/store/product/" + pair.Value.product; selection.IconUrl = pair.Value.icon; selection.Publisher = pair.Value.developer; } - if (Program.Canceled) return; selectionTreeView.Invoke(delegate { if (Program.Canceled) return; - TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Epic && s.Name == @namespace) ?? new(); + TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Epic && s.Name == @namespace) + ?? new TreeNode(); programNode.Tag = selection.Platform; programNode.Name = @namespace; programNode.Text = name; @@ -362,7 +393,6 @@ internal partial class SelectForm : CustomForm if (catalogItemsNode.Parent is null) programNode.Nodes.Add(catalogItemsNode);*/ if (entitlements.Any()) - { /*TreeNode entitlementsNode = treeNodes.Find(s => s.Tag is Platform.Epic && s.Name == @namespace + "_entitlements") ?? new(); entitlementsNode.Tag = selection.Platform; entitlementsNode.Name = @namespace + "_entitlements"; @@ -370,14 +400,17 @@ internal partial class SelectForm : CustomForm entitlementsNode.Checked = selection.SelectedDlc.Any(pair => pair.Value.type == DlcType.Entitlement); if (entitlementsNode.Parent is null) programNode.Nodes.Add(entitlementsNode);*/ - foreach (KeyValuePair pair in entitlements) + foreach (KeyValuePair + pair in entitlements) { - if (programNode is null/* || entitlementsNode is null*/) return; + if (programNode is null /* || entitlementsNode is null*/) return; string dlcId = pair.Key; - (DlcType type, string name, string icon) dlcApp = (DlcType.EpicEntitlement, pair.Value.name, pair.Value.icon); + (DlcType type, string name, string icon) dlcApp = ( + DlcType.EpicEntitlement, pair.Value.name, pair.Value.icon); selection.AllDlc[dlcId] = dlcApp; if (allCheckBox.Checked) selection.SelectedDlc[dlcId] = dlcApp; - TreeNode dlcNode = treeNodes.Find(s => s.Tag is Platform.Epic && s.Name == dlcId) ?? new(); + TreeNode dlcNode = treeNodes.Find(s => s.Tag is Platform.Epic && s.Name == dlcId) + ?? new TreeNode(); dlcNode.Tag = selection.Platform; dlcNode.Name = dlcId; dlcNode.Text = dlcApp.name; @@ -385,7 +418,6 @@ internal partial class SelectForm : CustomForm if (dlcNode.Parent is null) _ = programNode.Nodes.Add(dlcNode); //entitlementsNode.Nodes.Add(dlcNode); } - } }); if (Program.Canceled) return; RemoveFromRemainingGames(name); @@ -399,34 +431,38 @@ internal partial class SelectForm : CustomForm foreach ((string gameId, string name, string gameDirectory) in ubisoftGames) { if (Program.Canceled) return; - if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Ubisoft && c.id == gameId)) continue; + if (Program.IsGameBlocked(name, gameDirectory) + || !ProgramsToScan.Any(c => c.platform is Platform.Ubisoft && c.id == gameId)) continue; AddToRemainingGames(name); Task task = Task.Run(async () => { if (Program.Canceled) return; - List dllDirectories = await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Ubisoft); + List dllDirectories + = await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Ubisoft); if (dllDirectories is null) { RemoveFromRemainingGames(name); return; } if (Program.Canceled) return; - - ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Ubisoft, gameId) ?? new(); - selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any() || selection.ExtraSelectedDlc.Any(); + ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Ubisoft, gameId) + ?? new ProgramSelection(); + 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; - selection.ExecutableDirectories = await UbisoftLibrary.GetExecutableDirectories(selection.RootDirectory); + selection.ExecutableDirectories + = await UbisoftLibrary.GetExecutableDirectories(selection.RootDirectory); selection.DllDirectories = dllDirectories; selection.Platform = Platform.Ubisoft; selection.IconUrl = IconGrabber.GetDomainFaviconUrl("store.ubi.com"); - selectionTreeView.Invoke(delegate { if (Program.Canceled) return; - TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Ubisoft && s.Name == gameId) ?? new(); + TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Ubisoft && s.Name == gameId) + ?? new TreeNode(); programNode.Tag = selection.Platform; programNode.Name = gameId; programNode.Text = name; @@ -448,7 +484,6 @@ internal partial class SelectForm : CustomForm steamGamesToCheck = 0; } - private List<(Platform platform, string id, string name)> ProgramsToScan; private async void OnLoad(bool forceScan = false, bool forceProvideChoices = false) { Program.Canceled = false; @@ -470,27 +505,37 @@ internal partial class SelectForm : CustomForm resetKoaloaderButton.Enabled = false; progressLabel.Text = "Waiting for user to select which programs/games to scan . . ."; ShowProgressBar(); - await ProgramData.Setup(); - bool scan = forceScan; if (!scan && (ProgramsToScan is null || !ProgramsToScan.Any() || forceProvideChoices)) { List<(Platform platform, string id, string name, bool alreadySelected)> gameChoices = new(); if (Directory.Exists(ParadoxLauncher.InstallPath)) - gameChoices.Add((Platform.Paradox, "PL", "Paradox Launcher", ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL"))); + 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)) - foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in (await SteamLibrary.GetGames()).Where(g => !Program.IsGameBlocked(g.name, g.gameDirectory))) - gameChoices.Add((Platform.Steam, appId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Steam && p.id == appId))); + foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in + (await SteamLibrary.GetGames()).Where(g => !Program.IsGameBlocked(g.name, g.gameDirectory))) + gameChoices.Add((Platform.Steam, appId, name, + ProgramsToScan is not null + && ProgramsToScan.Any(p => p.platform is Platform.Steam && p.id == appId))); if (Directory.Exists(EpicLibrary.EpicManifestsPath)) - foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation))) - 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()).Where(g => !Program.IsGameBlocked(g.name, g.gameDirectory))) - gameChoices.Add((Platform.Ubisoft, gameId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Ubisoft && p.id == gameId))); + foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where( + m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation))) + 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()).Where( + g => !Program.IsGameBlocked(g.name, g.gameDirectory))) + gameChoices.Add((Platform.Ubisoft, gameId, name, + ProgramsToScan is not null + && ProgramsToScan.Any(p => p.platform is Platform.Ubisoft && p.id == gameId))); if (gameChoices.Any()) { using SelectDialogForm form = new(this); - List<(Platform 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(); string retry = "\n\nPress the \"Rescan Programs / Games\" button to re-choose."; if (scan) @@ -499,12 +544,15 @@ internal partial class SelectForm : CustomForm noneFoundLabel.Text = "None of the chosen programs nor games were applicable!" + retry; } else + { noneFoundLabel.Text = "You didn't choose any programs nor games!" + retry; + } } else + { noneFoundLabel.Text = "No applicable programs nor games were found on your computer!"; + } } - if (scan) { bool setup = true; @@ -518,13 +566,15 @@ internal partial class SelectForm : CustomForm if (_progress < 0 || _progress > maxProgress) maxProgress = -_progress; else curProgress = _progress; int p = Math.Max(Math.Min((int)((float)curProgress / maxProgress * 100), 100), 0); - progressLabel.Text = setup ? $"Setting up SteamCMD . . . {p}%" + progressLabel.Text = setup + ? $"Setting up SteamCMD . . . {p}%" : $"Gathering and caching your applicable games and their DLCs . . . {p}%"; progressBar.Value = p; }; - if (Directory.Exists(SteamLibrary.InstallPath) && ProgramsToScan is not null && ProgramsToScan.Any(c => c.platform is 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); } setup = false; @@ -542,10 +592,8 @@ internal partial class SelectForm : CustomForm await GetApplicablePrograms(iProgress); await SteamCMD.Cleanup(); } - OnLoadDlc(null, null); OnLoadKoaloader(null, null); - HideProgressBar(); selectionTreeView.Enabled = ProgramSelection.All.Any(); allCheckBox.Enabled = selectionTreeView.Enabled; @@ -605,7 +653,8 @@ internal partial class SelectForm : CustomForm { string id = node.Name; Platform platform = (Platform)node.Tag; - (string gameId, (DlcType type, string name, string icon) app)? dlc = ProgramSelection.GetDlcFromPlatformId(platform, id); + (string gameId, (DlcType type, string name, string icon) app)? dlc + = ProgramSelection.GetDlcFromPlatformId(platform, id); if (dlc.HasValue) { (string gameId, _) = dlc.Value; @@ -620,7 +669,6 @@ internal partial class SelectForm : CustomForm } } - internal List TreeNodes => GatherTreeNodes(selectionTreeView.Nodes); private List GatherTreeNodes(TreeNodeCollection nodeCollection) { List treeNodes = new(); @@ -642,12 +690,13 @@ internal partial class SelectForm : CustomForm progressLabelDLCs.Text = ""; progressLabelDLCs.Visible = true; progressBar.Visible = true; - programsGroupBox.Size = new(programsGroupBox.Size.Width, programsGroupBox.Size.Height - 3 - - progressLabel.Size.Height - - progressLabelGames.Size.Height - - progressLabelDLCs.Size.Height - - progressBar.Size.Height); + programsGroupBox.Size = new Size(programsGroupBox.Size.Width, programsGroupBox.Size.Height - 3 + - progressLabel.Size.Height + - progressLabelGames.Size.Height + - progressLabelDLCs.Size.Height + - progressBar.Size.Height); } + private void HideProgressBar() { progressBar.Value = 100; @@ -655,11 +704,11 @@ internal partial class SelectForm : CustomForm progressLabelGames.Visible = false; progressLabelDLCs.Visible = false; progressBar.Visible = false; - programsGroupBox.Size = new(programsGroupBox.Size.Width, programsGroupBox.Size.Height + 3 - + progressLabel.Size.Height - + progressLabelGames.Size.Height - + progressLabelDLCs.Size.Height - + progressBar.Size.Height); + programsGroupBox.Size = new Size(programsGroupBox.Size.Width, programsGroupBox.Size.Height + 3 + + progressLabel.Size.Height + + progressLabelGames.Size.Height + + progressLabelDLCs.Size.Height + + progressBar.Size.Height); } internal void OnNodeRightClick(TreeNode node, Point location) => Invoke(() => @@ -683,11 +732,11 @@ internal partial class SelectForm : CustomForm return; ContextMenuItem header = null; if (id == "PL") - header = new(node.Text, "Paradox Launcher"); + header = new ContextMenuItem(node.Text, "Paradox Launcher"); else if (selection is not null) - header = new(node.Text, (id, selection.IconUrl)); + header = new ContextMenuItem(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)); + header = new ContextMenuItem(node.Text, (id, dlc.Value.app.icon), (id, dlcParentSelection.IconUrl)); items.Add(header ?? new ContextMenuItem(node.Text)); string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf"; string appInfoJSON = $@"{SteamCMD.AppInfoPath}\{id}.json"; @@ -697,39 +746,42 @@ internal partial class SelectForm : CustomForm List queries = new(); if (File.Exists(appInfoJSON)) { - string platformString = (selection is null || selection.Platform is Platform.Steam) ? "Steam Store " - : selection.Platform is Platform.Epic ? "Epic GraphQL " : ""; + 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)))); + (sender, e) => Diagnostics.OpenFileInNotepad(appInfoJSON))); } if (File.Exists(appInfoVDF)) queries.Add(new ContextMenuItem("Open SteamCMD Query", "Notepad", - new EventHandler((sender, e) => Diagnostics.OpenFileInNotepad(appInfoVDF)))); + (sender, e) => Diagnostics.OpenFileInNotepad(appInfoVDF))); if (queries.Any()) { items.Add(new ToolStripSeparator()); foreach (ContextMenuItem query in queries) items.Add(query); 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); - }))); + (sender, e) => + { + try + { + File.Delete(appInfoVDF); + } + catch { } + try + { + File.Delete(appInfoJSON); + } + catch { } + try + { + File.Delete(cooldown); + } + catch { } + OnLoad(true); + })); } } if (selection is not null) @@ -738,89 +790,109 @@ internal partial class SelectForm : CustomForm { items.Add(new ToolStripSeparator()); items.Add(new ContextMenuItem("Repair", "Command Prompt", - new EventHandler(async (sender, e) => await ParadoxLauncher.Repair(this, selection)))); + async (sender, e) => await ParadoxLauncher.Repair(this, selection))); } items.Add(new ToolStripSeparator()); items.Add(new ContextMenuItem("Open Root Directory", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory)))); + (sender, e) => Diagnostics.OpenDirectoryInFileExplorer( + selection.RootDirectory))); int executables = 0; foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories.ToList()) - { - items.Add(new ContextMenuItem($"Open Executable Directory #{++executables} ({(binaryType == BinaryType.BIT32 ? "32" : "64")}-bit)", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); - } + items.Add(new ContextMenuItem( + $"Open Executable Directory #{++executables} ({(binaryType == BinaryType.BIT32 ? "32" : "64")}-bit)", + "File Explorer", + (sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory))); List directories = selection.DllDirectories.ToList(); int steam = 0, epic = 0, r1 = 0, r2 = 0; if (selection.Platform is Platform.Steam or Platform.Paradox) foreach (string directory in directories) { - directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string cache); - if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)) + 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)) items.Add(new ContextMenuItem($"Open Steamworks Directory #{++steam}", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + (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)) + 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)) items.Add(new ContextMenuItem($"Open EOS Directory #{++epic}", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + (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)) + 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)) 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)) + (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)) items.Add(new ContextMenuItem($"Open Uplay R2 Directory #{++r2}", "File Explorer", - new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); + (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) + if ((selection is not null && selection.Platform is Platform.Steam) + || (dlcParentSelection is not null && dlcParentSelection.Platform is Platform.Steam)) { items.Add(new ToolStripSeparator()); items.Add(new ContextMenuItem("Open SteamDB", "SteamDB", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamdb.info/app/" + id)))); + (sender, e) => Diagnostics.OpenUrlInInternetBrowser( + "https://steamdb.info/app/" + id))); } if (selection is not null) { if (selection.Platform is Platform.Steam) { items.Add(new ContextMenuItem("Open Steam Store", "Steam Store", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); - items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), "Steam Community", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id)))); + (sender, e) => Diagnostics.OpenUrlInInternetBrowser( + selection.ProductUrl))); + items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), + "Steam Community", + (sender, e) => Diagnostics.OpenUrlInInternetBrowser( + "https://steamcommunity.com/app/" + id))); } if (selection.Platform is Platform.Epic) { items.Add(new ToolStripSeparator()); items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://scream-db.web.app/offers/" + id)))); + (sender, e) => Diagnostics.OpenUrlInInternetBrowser( + "https://scream-db.web.app/offers/" + id))); items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)))); + (sender, e) => Diagnostics.OpenUrlInInternetBrowser( + selection.ProductUrl))); } if (selection.Platform is Platform.Ubisoft) { items.Add(new ToolStripSeparator()); #pragma warning disable CA1308 // Normalize strings to uppercase items.Add(new ContextMenuItem("Open Ubisoft Store", "Ubisoft Store", - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://store.ubi.com/us/" + selection.Name.Replace(" ", "-").ToLowerInvariant())))); + (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) - { - items.Add(new ContextMenuItem("Open Official Website", ("Web_" + id, IconGrabber.GetDomainFaviconUrl(selection.WebsiteUrl)), - new EventHandler((sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.WebsiteUrl)))); - } + items.Add(new ContextMenuItem("Open Official Website", + ("Web_" + id, IconGrabber.GetDomainFaviconUrl(selection.WebsiteUrl)), + (sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.WebsiteUrl))); contextMenuStrip.Show(selectionTreeView, location); contextMenuStrip.Refresh(); ContextMenuStrip.Tag = null; @@ -828,7 +900,7 @@ internal partial class SelectForm : CustomForm private void OnLoad(object sender, EventArgs _) { - retry: + retry: try { HideProgressBar(); @@ -837,7 +909,7 @@ internal partial class SelectForm : CustomForm } catch (Exception e) { - if (e.HandleException(form: this)) goto retry; + if (e.HandleException(this)) goto retry; Close(); } } @@ -847,7 +919,8 @@ internal partial class SelectForm : CustomForm if (ProgramSelection.All.Any()) { foreach (ProgramSelection selection in ProgramSelection.AllEnabled) - if (!Program.IsProgramRunningDialog(this, selection)) return; + if (!Program.IsProgramRunningDialog(this, selection)) + return; if (!uninstall && ParadoxLauncher.DlcDialog(this)) return; Hide(); #pragma warning disable CA2000 // Dispose objects before losing scope @@ -865,7 +938,10 @@ internal partial class SelectForm : CustomForm #endif OnLoad(); } - else Close(); + else + { + Close(); + } }; form.Show(); Hide(); @@ -875,7 +951,7 @@ internal partial class SelectForm : CustomForm } } - private void OnInstall(object sender, EventArgs e) => OnAccept(false); + private void OnInstall(object sender, EventArgs e) => OnAccept(); private void OnUninstall(object sender, EventArgs e) => OnAccept(true); @@ -900,7 +976,7 @@ internal partial class SelectForm : CustomForm if (node.Parent is null && node.Checked != shouldCheck) { node.Checked = shouldCheck; - OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse)); + OnTreeViewNodeCheckedChanged(null, new TreeViewEventArgs(node, TreeViewAction.ByMouse)); } allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; allCheckBox.Checked = shouldCheck; @@ -927,16 +1003,20 @@ internal partial class SelectForm : CustomForm private bool AreSelectionsDefault() { foreach (TreeNode node in TreeNodes) - if (node.Parent is not null && node.Tag is Platform && (node.Text == "Unknown" ? node.Checked : !node.Checked)) + if (node.Parent is not null && node.Tag is Platform + && (node.Text == "Unknown" ? node.Checked : !node.Checked)) return false; return true; } - private bool CanSaveDlc() => installButton.Enabled && (ProgramData.ReadDlcChoices() is not null || !AreSelectionsDefault()); + private bool CanSaveDlc() + => installButton.Enabled && (ProgramData.ReadDlcChoices() is not null || !AreSelectionsDefault()); private void OnSaveDlc(object sender, EventArgs e) { - List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices() ?? new(); + List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices() + ?? new List<(Platform platform, string gameId, + string dlcId)>(); foreach (TreeNode node in TreeNodes) if (node.Parent is TreeNode parent && node.Tag is Platform platform) { @@ -960,10 +1040,11 @@ internal partial class SelectForm : CustomForm foreach (TreeNode node in TreeNodes) if (node.Parent is TreeNode parent && node.Tag is Platform platform) { - node.Checked = choices.Any(c => c.platform == platform && c.gameId == parent.Name && c.dlcId == node.Name) - ? node.Text == "Unknown" - : node.Text != "Unknown"; - OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse)); + node.Checked + = choices.Any(c => c.platform == platform && c.gameId == parent.Name && c.dlcId == node.Name) + ? node.Text == "Unknown" + : node.Text != "Unknown"; + OnTreeViewNodeCheckedChanged(null, new TreeViewEventArgs(node, TreeViewAction.ByMouse)); } } @@ -975,7 +1056,7 @@ internal partial class SelectForm : CustomForm if (node.Parent is not null && node.Tag is Platform) { node.Checked = node.Text != "Unknown"; - OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse)); + OnTreeViewNodeCheckedChanged(null, new TreeViewEventArgs(node, TreeViewAction.ByMouse)); } resetButton.Enabled = CanResetDlc(); } @@ -988,16 +1069,22 @@ internal partial class SelectForm : CustomForm return true; } - private static bool CanSaveKoaloader() => ProgramData.ReadKoaloaderChoices() is not null || !AreKoaloaderSelectionsDefault(); + private static bool CanSaveKoaloader() + => ProgramData.ReadKoaloaderChoices() is not null || !AreKoaloaderSelectionsDefault(); private void OnSaveKoaloader(object sender, EventArgs e) { - List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices() ?? new(); + List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices() + ?? new List<(Platform platform, string id, string proxy, bool enabled)>(); foreach (ProgramSelection selection in ProgramSelection.AllSafe) { _ = choices.RemoveAll(c => c.platform == selection.Platform && c.id == selection.Id); - if (selection.KoaloaderProxy is not null and not ProgramSelection.DefaultKoaloaderProxy || !selection.Koaloader) - choices.Add((selection.Platform, selection.Id, selection.KoaloaderProxy == ProgramSelection.DefaultKoaloaderProxy ? null : selection.KoaloaderProxy, selection.Koaloader)); + if (selection.KoaloaderProxy is not null and not ProgramSelection.DefaultKoaloaderProxy + || !selection.Koaloader) + choices.Add((selection.Platform, selection.Id, + selection.KoaloaderProxy == ProgramSelection.DefaultKoaloaderProxy + ? null + : selection.KoaloaderProxy, selection.Koaloader)); } ProgramData.WriteKoaloaderProxyChoices(choices); saveKoaloaderButton.Enabled = CanSaveKoaloader(); @@ -1011,7 +1098,6 @@ internal partial class SelectForm : CustomForm List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices(); if (choices is null) return; foreach (ProgramSelection selection in ProgramSelection.AllSafe) - { if (choices.Any(c => c.platform == selection.Platform && c.id == selection.Id)) { (Platform platform, string id, string proxy, bool enabled) choice = @@ -1023,11 +1109,14 @@ internal partial class SelectForm : CustomForm if (proxy != currentProxy && choices.Remove(choice)) // convert pre-v4.1.0.0 choices choices.Add((platform, id, currentProxy, enabled)); if (currentProxy is null or ProgramSelection.DefaultKoaloaderProxy && enabled) + { _ = choices.RemoveAll(c => c.platform == platform && c.id == id); + } else { selection.Koaloader = enabled; - selection.KoaloaderProxy = currentProxy == ProgramSelection.DefaultKoaloaderProxy ? currentProxy : proxy; + selection.KoaloaderProxy + = currentProxy == ProgramSelection.DefaultKoaloaderProxy ? currentProxy : proxy; } } else @@ -1035,7 +1124,6 @@ internal partial class SelectForm : CustomForm selection.Koaloader = true; selection.KoaloaderProxy = null; } - } ProgramData.WriteKoaloaderProxyChoices(choices); loadKoaloaderButton.Enabled = CanLoadKoaloader(); OnKoaloaderChanged(); @@ -1069,7 +1157,6 @@ internal partial class SelectForm : CustomForm OnLoad(forceProvideChoices: true); } - private readonly string helpButtonListPrefix = "\n • "; private void OnBlockProtectedGamesHelpButtonClicked(object sender, EventArgs e) { StringBuilder blockedGames = new(); @@ -1083,12 +1170,18 @@ internal partial class SelectForm : CustomForm _ = blockedDirectoryExceptions.Append(helpButtonListPrefix + name); using DialogForm form = new(this); _ = form.Show(SystemIcons.Information, - "Blocks the program from caching and displaying games protected by anti-cheats." + - "\nYou disable this option and install DLC unlockers to protected games at your own risk!" + - "\n\nBlocked games: " + (string.IsNullOrWhiteSpace(blockedGames.ToString()) ? "(none)" : blockedGames) + - "\n\nBlocked game sub-directories: " + (string.IsNullOrWhiteSpace(blockedDirectories.ToString()) ? "(none)" : blockedDirectories) + - "\n\nBlocked game sub-directory exceptions: " + (string.IsNullOrWhiteSpace(blockedDirectoryExceptions.ToString()) ? "(none)" : blockedDirectoryExceptions), - "OK", customFormText: "Block Protected Games"); + "Blocks the program from caching and displaying games protected by anti-cheats." + + "\nYou disable this option and install DLC unlockers to protected games at your own risk!" + + "\n\nBlocked games: " + + (string.IsNullOrWhiteSpace(blockedGames.ToString()) ? "(none)" : blockedGames) + + "\n\nBlocked game sub-directories: " + (string.IsNullOrWhiteSpace(blockedDirectories.ToString()) + ? "(none)" + : blockedDirectories) + + "\n\nBlocked game sub-directory exceptions: " + + (string.IsNullOrWhiteSpace(blockedDirectoryExceptions.ToString()) + ? "(none)" + : blockedDirectoryExceptions), + "OK", customFormText: "Block Protected Games"); } private void OnSortCheckBoxChanged(object sender, EventArgs e) => selectionTreeView.TreeViewNodeSorter diff --git a/CreamInstaller/GlobalSuppressions.cs b/CreamInstaller/GlobalSuppressions.cs index 4e35a55..18fd301 100644 --- a/CreamInstaller/GlobalSuppressions.cs +++ b/CreamInstaller/GlobalSuppressions.cs @@ -10,4 +10,4 @@ [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types")] -[assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task")] +[assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task")] \ No newline at end of file diff --git a/CreamInstaller/Platforms/Epic/EpicLibrary.cs b/CreamInstaller/Platforms/Epic/EpicLibrary.cs index 77e2d6f..3ecd0f8 100644 --- a/CreamInstaller/Platforms/Epic/EpicLibrary.cs +++ b/CreamInstaller/Platforms/Epic/EpicLibrary.cs @@ -1,14 +1,10 @@ -using CreamInstaller.Resources; -using CreamInstaller.Utility; - -using Microsoft.Win32; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; - +using CreamInstaller.Utility; +using Microsoft.Win32; using static CreamInstaller.Resources.Resources; namespace CreamInstaller.Platforms.Epic; @@ -16,21 +12,32 @@ namespace CreamInstaller.Platforms.Epic; internal static class EpicLibrary { private static string epicManifestsPath; + internal static string EpicManifestsPath { get { - epicManifestsPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Epic Games\EOS", "ModSdkMetadataDir", null) as string; - epicManifestsPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Wow6432Node\Epic Games\EOS", "ModSdkMetadataDir", null) as string; - epicManifestsPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Epic Games\EpicGamesLauncher", "AppDataPath", null) as string; - epicManifestsPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Epic Games\EpicGamesLauncher", "AppDataPath", null) as string; - if (epicManifestsPath is not null && epicManifestsPath.EndsWith(@"\Data")) epicManifestsPath += @"\Manifests"; + epicManifestsPath + ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Epic Games\EOS", "ModSdkMetadataDir", + null) as string; + epicManifestsPath + ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Wow6432Node\Epic Games\EOS", "ModSdkMetadataDir", + null) as string; + epicManifestsPath + ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Epic Games\EpicGamesLauncher", "AppDataPath", + null) as string; + epicManifestsPath + ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Epic Games\EpicGamesLauncher", + "AppDataPath", null) as string; + if (epicManifestsPath is not null && epicManifestsPath.EndsWith(@"\Data")) + epicManifestsPath += @"\Manifests"; return epicManifestsPath.BeautifyPath(); } } - internal static async Task> GetExecutableDirectories(string gameDirectory) => - await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true)); + internal static async Task> GetExecutableDirectories( + string gameDirectory) => + await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true)); internal static async Task> GetGames() => await Task.Run(() => { @@ -45,10 +52,12 @@ internal static class EpicLibrary { Manifest manifest = JsonSerializer.Deserialize(json); if (manifest is not null && manifest.CatalogItemId == manifest.MainGameCatalogItemId - && !games.Any(g => g.CatalogItemId == manifest.CatalogItemId && g.InstallLocation == manifest.InstallLocation)) + && !games.Any(g => g.CatalogItemId == manifest.CatalogItemId + && g.InstallLocation == manifest.InstallLocation)) games.Add(manifest); } - catch { }; + catch { } + ; } return games; }); diff --git a/CreamInstaller/Platforms/Epic/EpicStore.cs b/CreamInstaller/Platforms/Epic/EpicStore.cs index 1996e02..983e1d8 100644 --- a/CreamInstaller/Platforms/Epic/EpicStore.cs +++ b/CreamInstaller/Platforms/Epic/EpicStore.cs @@ -1,9 +1,4 @@ -using CreamInstaller.Platforms.Epic.GraphQL; -using CreamInstaller.Utility; - -using Newtonsoft.Json; - -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -11,6 +6,9 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web; +using CreamInstaller.Platforms.Epic.GraphQL; +using CreamInstaller.Utility; +using Newtonsoft.Json; namespace CreamInstaller.Platforms.Epic; @@ -24,7 +22,9 @@ internal static class EpicStore }*/ private const int COOLDOWN_ENTITLEMENT = 600; - internal static async Task> QueryEntitlements(string categoryNamespace) + + internal static async Task> + QueryEntitlements(string categoryNamespace) { List<(string id, string name, string product, string icon, string developer)> dlcIds = new(); string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json"; @@ -35,19 +35,21 @@ internal static class EpicStore response = await QueryGraphQL(categoryNamespace); try { - File.WriteAllText(cacheFile, JsonConvert.SerializeObject(response, Formatting.Indented)); + await File.WriteAllTextAsync(cacheFile, JsonConvert.SerializeObject(response, Formatting.Indented)); } catch { } } else if (cachedExists) + { try { - response = JsonConvert.DeserializeObject(File.ReadAllText(cacheFile)); + response = JsonConvert.DeserializeObject(await File.ReadAllTextAsync(cacheFile)); } catch { File.Delete(cacheFile); } + } if (response is null) return dlcIds; List searchStore = new(response.Data.Catalog.SearchStore.Elements); @@ -55,7 +57,8 @@ internal static class EpicStore { string title = element.Title; string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any() - ? element.CatalogNs.Mappings.First().PageSlug : null; + ? element.CatalogNs.Mappings.First().PageSlug + : null; string icon = null; for (int i = 0; i < element.KeyImages?.Length; i++) { @@ -67,14 +70,15 @@ internal static class EpicStore } } foreach (Item item in element.Items) - dlcIds.Populate(item.Id, title, product, icon, null, canOverwrite: element.Items.Length == 1); + dlcIds.Populate(item.Id, title, product, icon, null, element.Items.Length == 1); } List catalogOffers = new(response.Data.Catalog.CatalogOffers.Elements); foreach (Element element in catalogOffers) { string title = element.Title; string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any() - ? element.CatalogNs.Mappings.First().PageSlug : null; + ? element.CatalogNs.Mappings.First().PageSlug + : null; string icon = null; for (int i = 0; i < element.KeyImages?.Length; i++) { @@ -86,12 +90,14 @@ internal static class EpicStore } } foreach (Item item in element.Items) - dlcIds.Populate(item.Id, title, product, icon, item.Developer, canOverwrite: element.Items.Length == 1); + dlcIds.Populate(item.Id, title, product, icon, item.Developer, element.Items.Length == 1); } return dlcIds; } - private static void Populate(this List<(string id, string name, string product, string icon, string developer)> dlcIds, string id, string title, string product, string icon, string developer, bool canOverwrite = false) + private static void Populate( + this List<(string id, string name, string product, string icon, string developer)> dlcIds, string id, + string title, string product, string icon, string developer, bool canOverwrite = false) { if (id == null) return; bool found = false; @@ -121,7 +127,8 @@ internal static class EpicStore content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpClient client = HttpClientManager.HttpClient; if (client is null) return null; - HttpResponseMessage httpResponse = await client.PostAsync(new Uri("https://graphql.epicgames.com/graphql"), content); + HttpResponseMessage httpResponse + = await client.PostAsync(new Uri("https://graphql.epicgames.com/graphql"), content); _ = httpResponse.EnsureSuccessStatusCode(); string response = await httpResponse.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(response); diff --git a/CreamInstaller/Platforms/Epic/GraphQL/Request.cs b/CreamInstaller/Platforms/Epic/GraphQL/Request.cs index c6d75fe..c4e2e4d 100644 --- a/CreamInstaller/Platforms/Epic/GraphQL/Request.cs +++ b/CreamInstaller/Platforms/Epic/GraphQL/Request.cs @@ -64,7 +64,6 @@ internal class Request { [JsonProperty(PropertyName = "Content-Type")] private string ContentType => "application/graphql"; - } private class Variables diff --git a/CreamInstaller/Platforms/Epic/GraphQL/Response.cs b/CreamInstaller/Platforms/Epic/GraphQL/Response.cs index ffb9cb7..612dc97 100644 --- a/CreamInstaller/Platforms/Epic/GraphQL/Response.cs +++ b/CreamInstaller/Platforms/Epic/GraphQL/Response.cs @@ -1,15 +1,13 @@ #pragma warning disable CA1819 // Properties should not return arrays -using Newtonsoft.Json; - using System; +using Newtonsoft.Json; namespace CreamInstaller.Platforms.Epic.GraphQL; public class Response { - [JsonProperty(PropertyName = "data")] - public ResponseData Data { get; protected set; } + [JsonProperty(PropertyName = "data")] public ResponseData Data { get; protected set; } } public class ResponseData @@ -35,17 +33,14 @@ public class ElementContainer public class Element { - [JsonProperty(PropertyName = "id")] - public string Id { get; protected set; } + [JsonProperty(PropertyName = "id")] public string Id { get; protected set; } - [JsonProperty(PropertyName = "title")] - public string Title { get; protected set; } + [JsonProperty(PropertyName = "title")] public string Title { get; protected set; } [JsonProperty(PropertyName = "keyImages")] public KeyImage[] KeyImages { get; protected set; } - [JsonProperty(PropertyName = "items")] - public Item[] Items { get; protected set; } + [JsonProperty(PropertyName = "items")] public Item[] Items { get; protected set; } [JsonProperty(PropertyName = "catalogNs")] public CatalogNs CatalogNs { get; protected set; } @@ -53,11 +48,9 @@ public class Element public class Item { - [JsonProperty(PropertyName = "id")] - public string Id { get; protected set; } + [JsonProperty(PropertyName = "id")] public string Id { get; protected set; } - [JsonProperty(PropertyName = "title")] - public string Title { get; protected set; } + [JsonProperty(PropertyName = "title")] public string Title { get; protected set; } [JsonProperty(PropertyName = "developer")] public string Developer { get; protected set; } @@ -65,11 +58,9 @@ public class Item public class KeyImage { - [JsonProperty(PropertyName = "type")] - public string Type { get; protected set; } + [JsonProperty(PropertyName = "type")] public string Type { get; protected set; } - [JsonProperty(PropertyName = "url")] - public Uri Url { get; protected set; } + [JsonProperty(PropertyName = "url")] public Uri Url { get; protected set; } } public class CatalogNs diff --git a/CreamInstaller/Platforms/Paradox/ParadoxLauncher.cs b/CreamInstaller/Platforms/Paradox/ParadoxLauncher.cs index 143d10b..5c0f0d9 100644 --- a/CreamInstaller/Platforms/Paradox/ParadoxLauncher.cs +++ b/CreamInstaller/Platforms/Paradox/ParadoxLauncher.cs @@ -1,34 +1,46 @@ -using CreamInstaller.Resources; -using CreamInstaller.Utility; - -using Microsoft.Win32; - +using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; - +using CreamInstaller.Forms; +using CreamInstaller.Resources; +using CreamInstaller.Utility; +using Microsoft.Win32; using static CreamInstaller.Resources.Resources; namespace CreamInstaller.Platforms.Paradox; internal static class ParadoxLauncher { + public enum RepairResult + { + ProgramRunning = -2, Failure, Unnecessary = 0, + Success + } + private static string installPath; + internal static string InstallPath { get { - installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation", null) as string; - installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Wow6432Node\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation", null) as string; + installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Paradox Interactive\Paradox Launcher v2", + "LauncherInstallation", null) as string; + installPath ??= Registry.GetValue( + @"HKEY_CURRENT_USER\Software\Wow6432Node\Paradox Interactive\Paradox Launcher v2", + "LauncherInstallation", null) as string; return installPath.BeautifyPath(); } } - internal static async Task> GetExecutableDirectories(string gameDirectory) => - await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: path => !Path.GetFileName(path).Contains("bootstrapper"))); + internal static async Task> GetExecutableDirectories( + string gameDirectory) => + await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: path + => !Path.GetFileName(path) + .Contains("bootstrapper"))); private static void PopulateDlc(ProgramSelection paradoxLauncher = null) { @@ -37,16 +49,26 @@ internal static class ParadoxLauncher { paradoxLauncher.ExtraDlc.Clear(); paradoxLauncher.ExtraSelectedDlc.Clear(); - foreach (ProgramSelection selection in ProgramSelection.AllEnabled.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive")) + foreach (ProgramSelection selection in ProgramSelection.AllEnabled.Where( + s => s != paradoxLauncher && s.Publisher == "Paradox Interactive")) { - paradoxLauncher.ExtraDlc.Add(new(selection.Id, selection.Name, selection.AllDlc)); - paradoxLauncher.ExtraSelectedDlc.Add(new(selection.Id, selection.Name, selection.SelectedDlc)); + paradoxLauncher.ExtraDlc.Add( + new ValueTuple>( + selection.Id, selection.Name, selection.AllDlc)); + paradoxLauncher.ExtraSelectedDlc.Add( + new ValueTuple>( + selection.Id, selection.Name, selection.SelectedDlc)); } if (!paradoxLauncher.ExtraDlc.Any()) - foreach (ProgramSelection selection in ProgramSelection.AllSafe.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive")) + foreach (ProgramSelection selection in ProgramSelection.AllSafe.Where( + s => s != paradoxLauncher && s.Publisher == "Paradox Interactive")) { - paradoxLauncher.ExtraDlc.Add(new(selection.Id, selection.Name, selection.AllDlc)); - paradoxLauncher.ExtraSelectedDlc.Add(new(selection.Id, selection.Name, selection.AllDlc)); + paradoxLauncher.ExtraDlc.Add( + new ValueTuple>( + selection.Id, selection.Name, selection.AllDlc)); + paradoxLauncher.ExtraSelectedDlc.Add( + new ValueTuple>( + selection.Id, selection.Name, selection.AllDlc)); } } } @@ -61,27 +83,21 @@ internal static class ParadoxLauncher { using DialogForm dialogForm = new(form); return dialogForm.Show(SystemIcons.Warning, - $"WARNING: There are no scanned games with DLC that can be added to the Paradox Launcher!" + - "\n\nInstalling DLC unlockers for the Paradox Launcher alone can cause existing configurations to be deleted!", - "Ignore", "Cancel", customFormText: "Paradox Launcher") != DialogResult.OK; + "WARNING: There are no scanned games with DLC that can be added to the Paradox Launcher!" + + + "\n\nInstalling DLC unlockers for the Paradox Launcher alone can cause existing configurations to be deleted!", + "Ignore", "Cancel", "Paradox Launcher") != DialogResult.OK; } } return false; } - public enum RepairResult - { - ProgramRunning = -2, - Failure, - Unnecessary = 0, - Success - } - internal static async Task Repair(Form form, ProgramSelection selection) { InstallForm installForm = form as InstallForm; if (!Program.IsProgramRunningDialog(form, selection)) - return form is InstallForm ? throw new CustomMessageException("Repair failed! The launcher is currently running!") + return form is InstallForm + ? throw new CustomMessageException("Repair failed! The launcher is currently running!") : RepairResult.ProgramRunning; bool smokeInstalled = false; byte[] steamOriginalSdk32 = null; @@ -92,33 +108,39 @@ internal static class ParadoxLauncher foreach (string directory in selection.DllDirectories) { bool koaloaderInstalled = Koaloader.AutoLoadDlls - .Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) - .Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile()); - directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out _); + .Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) + .Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile()); + directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, + out string config, out _); smokeInstalled = smokeInstalled - || File.Exists(api32_o) || File.Exists(api64_o) - || File.Exists(config) && !koaloaderInstalled - || File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.Steamworks32) - || File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.Steamworks64); + || File.Exists(api32_o) || File.Exists(api64_o) + || (File.Exists(config) && !koaloaderInstalled) + || (File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.Steamworks32)) + || (File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.Steamworks64)); await SmokeAPI.Uninstall(directory, deleteConfig: false); - if (steamOriginalSdk32 is null && File.Exists(api32) && !api32.IsResourceFile(ResourceIdentifier.Steamworks32)) - steamOriginalSdk32 = File.ReadAllBytes(api32); - if (steamOriginalSdk64 is null && File.Exists(api64) && !api64.IsResourceFile(ResourceIdentifier.Steamworks64)) - steamOriginalSdk64 = File.ReadAllBytes(api64); + if (steamOriginalSdk32 is null && File.Exists(api32) + && !api32.IsResourceFile(ResourceIdentifier.Steamworks32)) + steamOriginalSdk32 = await File.ReadAllBytesAsync(api32); + if (steamOriginalSdk64 is null && File.Exists(api64) + && !api64.IsResourceFile(ResourceIdentifier.Steamworks64)) + steamOriginalSdk64 = await File.ReadAllBytesAsync(api64); directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out config); screamInstalled = screamInstalled - || File.Exists(api32_o) || File.Exists(api64_o) - || File.Exists(config) && !koaloaderInstalled - || File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32) - || File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64); + || File.Exists(api32_o) || File.Exists(api64_o) + || (File.Exists(config) && !koaloaderInstalled) + || (File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)) + || (File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64)); await ScreamAPI.Uninstall(directory, deleteConfig: false); - if (epicOriginalSdk32 is null && File.Exists(api32) && !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)) - epicOriginalSdk32 = File.ReadAllBytes(api32); - if (epicOriginalSdk64 is null && File.Exists(api64) && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64)) - epicOriginalSdk64 = File.ReadAllBytes(api64); + if (epicOriginalSdk32 is null && File.Exists(api32) + && !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)) + epicOriginalSdk32 = await File.ReadAllBytesAsync(api32); + if (epicOriginalSdk64 is null && File.Exists(api64) + && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64)) + epicOriginalSdk64 = await File.ReadAllBytesAsync(api64); } using DialogForm dialogForm = new(form); - if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null || epicOriginalSdk64 is not null) + if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null + || epicOriginalSdk64 is not null) { bool neededRepair = false; foreach (string directory in selection.DllDirectories) @@ -159,28 +181,26 @@ internal static class ParadoxLauncher if (installForm is not null) installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success); else - _ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", "OK", customFormText: "Paradox Launcher"); + _ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", "OK", + customFormText: "Paradox Launcher"); return RepairResult.Success; } + if (installForm is not null) + installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success); else - { - if (installForm is not null) - installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success); - else - _ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", "OK", customFormText: "Paradox Launcher"); - return RepairResult.Unnecessary; - } - } - else - { - _ = form is InstallForm - ? throw new CustomMessageException("Repair failed! " + - "An original Steamworks and/or Epic Online Services file could not be found. " + - "You will likely have to reinstall Paradox Launcher to fix this issue.") - : dialogForm.Show(SystemIcons.Error, "Paradox Launcher repair failed!" - + "\n\nAn original Steamworks and/or Epic Online Services file could not be found." - + "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", "OK", customFormText: "Paradox Launcher"); - return RepairResult.Failure; + _ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", "OK", + customFormText: "Paradox Launcher"); + return RepairResult.Unnecessary; } + _ = form is InstallForm + ? throw new CustomMessageException("Repair failed! " + + "An original Steamworks and/or Epic Online Services file could not be found. " + + + "You will likely have to reinstall Paradox Launcher to fix this issue.") + : dialogForm.Show(SystemIcons.Error, "Paradox Launcher repair failed!" + + "\n\nAn original Steamworks and/or Epic Online Services file could not be found." + + "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", + "OK", customFormText: "Paradox Launcher"); + return RepairResult.Failure; } } diff --git a/CreamInstaller/Platforms/Steam/SteamCMD.cs b/CreamInstaller/Platforms/Steam/SteamCMD.cs index 41d5c7a..12fc237 100644 --- a/CreamInstaller/Platforms/Steam/SteamCMD.cs +++ b/CreamInstaller/Platforms/Steam/SteamCMD.cs @@ -1,9 +1,4 @@ -using CreamInstaller.Resources; -using CreamInstaller.Utility; - -using Gameloop.Vdf.Linq; - -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; @@ -14,6 +9,9 @@ using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; +using CreamInstaller.Resources; +using CreamInstaller.Utility; +using Gameloop.Vdf.Linq; namespace CreamInstaller.Platforms.Steam; @@ -21,20 +19,33 @@ internal static class SteamCMD { internal const int ProcessLimit = 20; + internal static readonly string FilePath = DirectoryPath + @"\steamcmd.exe"; + + private static readonly ConcurrentDictionary + AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print + + private static readonly int[] locks = new int[ProcessLimit]; + + internal static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip"; + internal static readonly string DllPath = DirectoryPath + @"\steamclient.dll"; + + internal static readonly string AppCachePath = DirectoryPath + @"\appcache"; + internal static readonly string ConfigPath = DirectoryPath + @"\config"; + internal static readonly string DumpsPath = DirectoryPath + @"\dumps"; + internal static readonly string LogsPath = DirectoryPath + @"\logs"; + internal static readonly string SteamAppsPath = DirectoryPath + @"\steamapps"; + internal static string DirectoryPath => ProgramData.DirectoryPath; internal static string AppInfoPath => ProgramData.AppInfoPath; - internal static readonly string FilePath = DirectoryPath + @"\steamcmd.exe"; - - private static readonly ConcurrentDictionary AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print private static string GetArguments(string appId) => AttemptCount.TryGetValue(appId, out int attempts) - ? $@"@ShutdownOnFailedCommand 0 +force_install_dir {DirectoryPath} +login anonymous +app_info_print {appId} " + string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit" + ? $@"@ShutdownOnFailedCommand 0 +force_install_dir {DirectoryPath} +login anonymous +app_info_print {appId} " + + string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit" : $"+login anonymous +app_info_print {appId} +quit"; - private static readonly int[] locks = new int[ProcessLimit]; internal static async Task Run(string appId) => await Task.Run(() => { - wait_for_lock: + wait_for_lock: if (Program.Canceled) return ""; for (int i = 0; i < locks.Length; i++) { @@ -42,22 +53,17 @@ internal static class SteamCMD if (Interlocked.CompareExchange(ref locks[i], 1, 0) == 0) { if (appId is not null) - if (AttemptCount.ContainsKey(appId)) - AttemptCount[appId]++; - else - AttemptCount[appId] = 0; + { + AttemptCount.TryGetValue(appId, out int count); + AttemptCount[appId] = ++count; + } if (Program.Canceled) return ""; ProcessStartInfo processStartInfo = new() { - FileName = FilePath, - RedirectStandardOutput = true, - RedirectStandardInput = true, - RedirectStandardError = true, - UseShellExecute = false, - Arguments = appId is null ? "+quit" : GetArguments(appId), - CreateNoWindow = true, - StandardInputEncoding = Encoding.UTF8, - StandardOutputEncoding = Encoding.UTF8, + FileName = FilePath, RedirectStandardOutput = true, RedirectStandardInput = true, + RedirectStandardError = true, UseShellExecute = false, + Arguments = appId is null ? "+quit" : GetArguments(appId), CreateNoWindow = true, + StandardInputEncoding = Encoding.UTF8, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; Process process = Process.Start(processStartInfo); @@ -96,7 +102,10 @@ internal static class SteamCMD _ = output.Clear(); _ = appInfo.Clear(); } - else break; + else + { + break; + } } } _ = Interlocked.Decrement(ref locks[i]); @@ -108,9 +117,6 @@ internal static class SteamCMD goto wait_for_lock; }); - internal static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip"; - internal static readonly string DllPath = DirectoryPath + @"\steamclient.dll"; - internal static async Task Setup(IProgress progress) { await Cleanup(); @@ -118,7 +124,8 @@ internal static class SteamCMD { HttpClient httpClient = HttpClientManager.HttpClient; if (httpClient is null) return; - byte[] file = await httpClient.GetByteArrayAsync(new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip")); + byte[] file = await httpClient.GetByteArrayAsync( + new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip")); file.Write(ArchivePath); ZipFile.ExtractToDirectory(ArchivePath, DirectoryPath); File.Delete(ArchivePath); @@ -127,9 +134,7 @@ internal static class SteamCMD { FileSystemWatcher watcher = new(DirectoryPath) { - Filter = "*", - IncludeSubdirectories = true, - EnableRaisingEvents = true + Filter = "*", IncludeSubdirectories = true, EnableRaisingEvents = true }; if (File.Exists(DllPath)) progress.Report(-15); // update (not used at the moment) else progress.Report(-1660); // install @@ -141,12 +146,6 @@ internal static class SteamCMD } } - internal static readonly string AppCachePath = DirectoryPath + @"\appcache"; - internal static readonly string ConfigPath = DirectoryPath + @"\config"; - internal static readonly string DumpsPath = DirectoryPath + @"\dumps"; - internal static readonly string LogsPath = DirectoryPath + @"\logs"; - internal static readonly string SteamAppsPath = DirectoryPath + @"\steamapps"; - internal static async Task Cleanup() => await Task.Run(async () => { if (!Directory.Exists(DirectoryPath)) return; @@ -165,7 +164,8 @@ internal static class SteamCMD foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.ntfs_transaction_failed")) File.Delete(file); if (Directory.Exists(AppCachePath)) - Directory.Delete(AppCachePath, true); // this is definitely needed, so SteamCMD gets the latest information for us + Directory.Delete(AppCachePath, + true); // this is definitely needed, so SteamCMD gets the latest information for us if (Directory.Exists(DumpsPath)) Directory.Delete(DumpsPath, true); if (Directory.Exists(LogsPath)) @@ -181,21 +181,41 @@ internal static class SteamCMD if (Program.Canceled) return null; string output; string appUpdateFile = $@"{AppInfoPath}\{appId}.vdf"; - restart: + restart: if (Program.Canceled) return null; - if (File.Exists(appUpdateFile)) output = File.ReadAllText(appUpdateFile, Encoding.UTF8); + if (File.Exists(appUpdateFile)) + { + try + { + output = await File.ReadAllTextAsync(appUpdateFile, Encoding.UTF8); + } + catch + { + goto restart; + } + } else { output = await Run(appId) ?? ""; - int openBracket = output.IndexOf("{"); - int closeBracket = output.LastIndexOf("}"); - if (output is not null && openBracket != -1 && closeBracket != -1 && closeBracket > openBracket) + int openBracket = output.IndexOf("{", StringComparison.Ordinal); + int closeBracket = output.LastIndexOf("}", StringComparison.Ordinal); + if (openBracket != -1 && closeBracket != -1 && closeBracket > openBracket) { output = $"\"{appId}\"\n" + output[openBracket..(1 + closeBracket)]; output = output.Replace("ERROR! Failed to install app '4' (Invalid platform)", ""); - File.WriteAllText(appUpdateFile, output, Encoding.UTF8); + try + { + await File.WriteAllTextAsync(appUpdateFile, output, Encoding.UTF8); + } + catch + { + goto restart; + } + } + else + { + goto restart; } - else goto restart; } if (Program.Canceled || output is null) return null; if (!ValveDataFile.TryDeserialize(output, out VProperty appInfo) || appInfo.Value is VValue) @@ -207,13 +227,15 @@ internal static class SteamCMD VToken type = appInfo.Value?.GetChild("common")?.GetChild("type"); if (type is null || type.ToString() == "Game") { - string buildid = appInfo.Value?.GetChild("depots")?.GetChild("branches")?.GetChild(branch)?.GetChild("buildid")?.ToString(); + string buildid = appInfo.Value?.GetChild("depots")?.GetChild("branches")?.GetChild(branch) + ?.GetChild("buildid")?.ToString(); if (buildid is null && type is not null) return appInfo; - if (type is null || int.TryParse(buildid, out int gamebuildId) && gamebuildId < buildId) + if (type is null || (int.TryParse(buildid, out int gamebuildId) && gamebuildId < buildId)) { List dlcAppIds = await ParseDlcAppIds(appInfo); foreach (string dlcAppUpdateFile in dlcAppIds.Select(id => $@"{AppInfoPath}\{id}.vdf")) - if (File.Exists(dlcAppUpdateFile)) File.Delete(dlcAppUpdateFile); + if (File.Exists(dlcAppUpdateFile)) + File.Delete(dlcAppUpdateFile); if (File.Exists(appUpdateFile)) File.Delete(appUpdateFile); goto restart; } @@ -236,8 +258,10 @@ internal static class SteamCMD dlcIds.Add("" + appId); VToken depots = appInfo.Value.GetChild("depots"); if (depots is not null) - foreach (VProperty property in depots.Where(p => p is VProperty && int.TryParse((p as VProperty).Key, out int _))) - if (int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appId) && !dlcIds.Contains("" + appId)) + foreach (VProperty property in depots.Where( + p => p is VProperty && int.TryParse((p as VProperty).Key, out int _))) + if (int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appId) + && !dlcIds.Contains("" + appId)) dlcIds.Add("" + appId); #pragma warning restore IDE0220 // Add explicit cast return dlcIds; diff --git a/CreamInstaller/Platforms/Steam/SteamLibrary.cs b/CreamInstaller/Platforms/Steam/SteamLibrary.cs index 9670fed..f59fe8d 100644 --- a/CreamInstaller/Platforms/Steam/SteamLibrary.cs +++ b/CreamInstaller/Platforms/Steam/SteamLibrary.cs @@ -1,16 +1,11 @@ -using CreamInstaller.Resources; -using CreamInstaller.Utility; - -using Gameloop.Vdf.Linq; - -using Microsoft.Win32; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; - +using CreamInstaller.Utility; +using Gameloop.Vdf.Linq; +using Microsoft.Win32; using static CreamInstaller.Resources.Resources; namespace CreamInstaller.Platforms.Steam; @@ -18,34 +13,42 @@ namespace CreamInstaller.Platforms.Steam; internal static class SteamLibrary { private static string installPath; + internal static string InstallPath { get { - installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", null) as string; - installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam", "InstallPath", null) as string; + installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", + null) as string; + installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam", "InstallPath", + null) as string; return installPath.BeautifyPath(); } } - internal static async Task> GetExecutableDirectories(string gameDirectory) => - await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true)); + internal static async Task> GetExecutableDirectories( + string gameDirectory) => + await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true)); - internal static async Task> GetGames() => await Task.Run(async () => + internal static async Task> + GetGames() => await Task.Run(async () => { List<(string appId, string name, string branch, int buildId, string gameDirectory)> games = new(); List gameLibraryDirectories = await GetLibraryDirectories(); foreach (string libraryDirectory in gameLibraryDirectories) { if (Program.Canceled) return games; - foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in (await GetGamesFromLibraryDirectory(libraryDirectory)) - .Where(game => !games.Any(_game => _game.appId == game.appId && _game.gameDirectory == game.gameDirectory))) + foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in + (await GetGamesFromLibraryDirectory(libraryDirectory)) + .Where(game => !games.Any(_game => _game.appId == game.appId + && _game.gameDirectory == game.gameDirectory))) games.Add(game); } return games; }); - internal static async Task> GetGamesFromLibraryDirectory(string libraryDirectory) => await Task.Run(() => + internal static async Task> + GetGamesFromLibraryDirectory(string libraryDirectory) => await Task.Run(() => { List<(string appId, string name, string branch, int buildId, string gameDirectory)> games = new(); if (Program.Canceled || !Directory.Exists(libraryDirectory)) return games; @@ -59,9 +62,9 @@ internal static class SteamLibrary string name = result.Value.GetChild("name")?.ToString(); string buildId = result.Value.GetChild("buildid")?.ToString(); if (string.IsNullOrWhiteSpace(appId) - || string.IsNullOrWhiteSpace(installdir) - || string.IsNullOrWhiteSpace(name) - || string.IsNullOrWhiteSpace(buildId)) + || string.IsNullOrWhiteSpace(installdir) + || string.IsNullOrWhiteSpace(name) + || string.IsNullOrWhiteSpace(buildId)) continue; string gameDirectory = (libraryDirectory + @"\common\" + installdir).BeautifyPath(); if (games.Any(g => g.appId == appId && g.gameDirectory == gameDirectory)) continue; @@ -87,9 +90,11 @@ internal static class SteamLibrary { gameDirectories.Add(libraryFolder); string libraryFolders = libraryFolder + @"\libraryfolders.vdf"; - if (File.Exists(libraryFolders) && ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, Encoding.UTF8), out VProperty result)) + if (File.Exists(libraryFolders) + && ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, Encoding.UTF8), out VProperty result)) #pragma warning disable IDE0220 // Add explicit cast - foreach (VProperty property in result.Value.Where(p => p is VProperty && int.TryParse((p as VProperty).Key, out int _))) + foreach (VProperty property in result.Value.Where( + p => p is VProperty && int.TryParse((p as VProperty).Key, out int _))) { string path = property.Value.GetChild("path")?.ToString(); if (string.IsNullOrWhiteSpace(path)) continue; diff --git a/CreamInstaller/Platforms/Steam/SteamStore.cs b/CreamInstaller/Platforms/Steam/SteamStore.cs index 4c96369..ae6d11e 100644 --- a/CreamInstaller/Platforms/Steam/SteamStore.cs +++ b/CreamInstaller/Platforms/Steam/SteamStore.cs @@ -1,13 +1,11 @@ -using CreamInstaller.Utility; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; - +using CreamInstaller.Forms; +using CreamInstaller.Utility; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; #if DEBUG using System; #endif @@ -16,6 +14,9 @@ namespace CreamInstaller.Platforms.Steam; internal static class SteamStore { + private const int COOLDOWN_GAME = 600; + private const int COOLDOWN_DLC = 1200; + internal static async Task> ParseDlcAppIds(AppData appData) => await Task.Run(() => { List dlcIds = new(); @@ -25,17 +26,15 @@ internal static class SteamStore return dlcIds; }); - private const int COOLDOWN_GAME = 600; - private const int COOLDOWN_DLC = 1200; - - internal static async Task QueryStoreAPI(string appId, bool isDlc = false) + internal static async Task QueryStoreAPI(string appId, bool isDlc = false, int attempts = 0) { if (Program.Canceled) return null; string cacheFile = ProgramData.AppInfoPath + @$"\{appId}.json"; bool cachedExists = File.Exists(cacheFile); if (!cachedExists || ProgramData.CheckCooldown(appId, isDlc ? COOLDOWN_DLC : COOLDOWN_GAME)) { - string response = await HttpClientManager.EnsureGet($"https://store.steampowered.com/api/appdetails?appids={appId}"); + string response + = await HttpClientManager.EnsureGet($"https://store.steampowered.com/api/appdetails?appids={appId}"); if (response is not null) { IDictionary apps = (IDictionary)JsonConvert.DeserializeObject(response); @@ -50,7 +49,9 @@ internal static class SteamStore if (!appDetails.success) { #if DEBUG - DebugForm.Current.Log($"Query unsuccessful for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}", LogTextBox.Warning); + DebugForm.Current.Log( + $"Query unsuccessful for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}", + LogTextBox.Warning); #endif if (data is null) return null; @@ -59,13 +60,15 @@ internal static class SteamStore { try { - File.WriteAllText(cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented)); + await File.WriteAllTextAsync( + cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented)); } catch #if DEBUG - (Exception e) + (Exception e) { - DebugForm.Current.Log($"Unsuccessful serialization of query for appid {appId}{(isDlc ? " (DLC)" : "")}: {e.GetType()} ({e.Message})"); + DebugForm.Current.Log( + $"Unsuccessful serialization of query for appid {appId}{(isDlc ? " (DLC)" : "")}: {e.GetType()} ({e.Message})"); } #else { } @@ -73,18 +76,24 @@ internal static class SteamStore return data; } #if DEBUG - else DebugForm.Current.Log($"Response data null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}"); + DebugForm.Current.Log( + $"Response data null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}"); #endif } #if DEBUG - else DebugForm.Current.Log($"Response details null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}"); + else + { + DebugForm.Current.Log( + $"Response details null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}"); + } #endif } catch #if DEBUG - (Exception e) + (Exception e) { - DebugForm.Current.Log($"Unsuccessful deserialization of query for appid {appId}{(isDlc ? " (DLC)" : "")}: {e.GetType()} ({e.Message})"); + DebugForm.Current.Log( + $"Unsuccessful deserialization of query for appid {appId}{(isDlc ? " (DLC)" : "")}: {e.GetType()} ({e.Message})"); } #else { } @@ -93,23 +102,26 @@ internal static class SteamStore else DebugForm.Current.Log("Response deserialization null for appid " + appId); #endif } + else + { #if DEBUG - else DebugForm.Current.Log("Response null for appid " + appId, LogTextBox.Warning); + DebugForm.Current.Log("Response null for appid " + appId, LogTextBox.Warning); #endif + } } if (cachedExists) try { - return JsonConvert.DeserializeObject(File.ReadAllText(cacheFile)); + return JsonConvert.DeserializeObject(await File.ReadAllTextAsync(cacheFile)); } catch { File.Delete(cacheFile); } - if (!isDlc) + if (!isDlc && attempts < 10) { Thread.Sleep(1000); - return await QueryStoreAPI(appId, isDlc); + return await QueryStoreAPI(appId, isDlc, ++attempts); } return null; } diff --git a/CreamInstaller/Platforms/Ubisoft/UbisoftLibrary.cs b/CreamInstaller/Platforms/Ubisoft/UbisoftLibrary.cs index d56f20f..6b59b0a 100644 --- a/CreamInstaller/Platforms/Ubisoft/UbisoftLibrary.cs +++ b/CreamInstaller/Platforms/Ubisoft/UbisoftLibrary.cs @@ -1,13 +1,9 @@ -using CreamInstaller.Resources; -using CreamInstaller.Utility; - -using Microsoft.Win32; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; - +using CreamInstaller.Utility; +using Microsoft.Win32; using static CreamInstaller.Resources.Resources; namespace CreamInstaller.Platforms.Ubisoft; @@ -15,6 +11,7 @@ namespace CreamInstaller.Platforms.Ubisoft; internal static class UbisoftLibrary { private static RegistryKey installsKey; + internal static RegistryKey InstallsKey { get @@ -25,21 +22,23 @@ internal static class UbisoftLibrary } } - internal static async Task> GetExecutableDirectories(string gameDirectory) => - await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true)); + internal static async Task> GetExecutableDirectories( + string gameDirectory) => + await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true)); - internal static async Task> GetGames() => await Task.Run(() => - { - List<(string gameId, string name, string gameDirectory)> games = new(); - RegistryKey installsKey = InstallsKey; - if (installsKey is null) return games; - foreach (string gameId in installsKey.GetSubKeyNames()) + internal static async Task> GetGames() => await Task.Run( + () => { - RegistryKey installKey = installsKey.OpenSubKey(gameId); - string installDir = installKey?.GetValue("InstallDir")?.ToString()?.BeautifyPath(); - if (installDir is not null && !games.Any(g => g.gameId == gameId && g.gameDirectory == installDir)) - games.Add((gameId, new DirectoryInfo(installDir).Name, installDir)); - } - return games; - }); + List<(string gameId, string name, string gameDirectory)> games = new(); + RegistryKey installsKey = InstallsKey; + if (installsKey is null) return games; + foreach (string gameId in installsKey.GetSubKeyNames()) + { + RegistryKey installKey = installsKey.OpenSubKey(gameId); + string installDir = installKey?.GetValue("InstallDir")?.ToString()?.BeautifyPath(); + if (installDir is not null && !games.Any(g => g.gameId == gameId && g.gameDirectory == installDir)) + games.Add((gameId, new DirectoryInfo(installDir).Name, installDir)); + } + return games; + }); } diff --git a/CreamInstaller/Program.cs b/CreamInstaller/Program.cs index 385271c..cab718c 100644 --- a/CreamInstaller/Program.cs +++ b/CreamInstaller/Program.cs @@ -1,6 +1,3 @@ -using CreamInstaller.Platforms.Steam; -using CreamInstaller.Utility; - using System; using System.Diagnostics; using System.Drawing; @@ -9,6 +6,9 @@ using System.Linq; using System.Reflection; using System.Threading; using System.Windows.Forms; +using CreamInstaller.Forms; +using CreamInstaller.Platforms.Steam; +using CreamInstaller.Utility; namespace CreamInstaller; @@ -46,7 +46,8 @@ internal static class Program if (ProtectedGames.Contains(name)) return true; if (directory is not null && !ProtectedGameDirectoryExceptions.Contains(name)) foreach (string path in ProtectedGameDirectories) - if (Directory.Exists(directory + path)) return true; + if (Directory.Exists(directory + path)) + return true; return false; } @@ -56,12 +57,15 @@ internal static class Program { using DialogForm dialogForm = new(form); if (dialogForm.Show(SystemIcons.Error, - $"ERROR: {selection.Name} is currently running!" + - "\n\nPlease close the program/game to continue . . . ", - "Retry", "Cancel") == DialogResult.OK) + $"ERROR: {selection.Name} is currently running!" + + "\n\nPlease close the program/game to continue . . . ", + "Retry", "Cancel") == DialogResult.OK) return IsProgramRunningDialog(form, selection); } - else return true; + else + { + return true; + } return false; } @@ -74,11 +78,12 @@ internal static class Program _ = Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - Application.ApplicationExit += new(OnApplicationExit); - Application.ThreadException += new((s, e) => e.Exception?.HandleFatalException()); + Application.ApplicationExit += OnApplicationExit; + Application.ThreadException += (s, e) => e.Exception?.HandleFatalException(); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); - AppDomain.CurrentDomain.UnhandledException += new((s, e) => (e.ExceptionObject as Exception)?.HandleFatalException()); - retry: + AppDomain.CurrentDomain.UnhandledException += (s, e) + => (e.ExceptionObject as Exception)?.HandleFatalException(); + retry: try { HttpClientManager.Setup(); @@ -99,6 +104,7 @@ internal static class Program } internal static bool Canceled; + internal static async void Cleanup(bool cancel = true) { Canceled = cancel; diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 48439a0..caa38d1 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -1,28 +1,21 @@ -using CreamInstaller.Components; -using CreamInstaller.Resources; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; - +using CreamInstaller.Components; +using CreamInstaller.Resources; using static CreamInstaller.Resources.Resources; namespace CreamInstaller; public enum Platform { - None = 0, - Paradox, - Steam, - Epic, - Ubisoft + None = 0, Paradox, Steam, + Epic, Ubisoft } public enum DlcType { - Steam, - SteamHidden, - EpicCatalogItem, + Steam, SteamHidden, EpicCatalogItem, EpicEntitlement } @@ -49,11 +42,17 @@ internal class ProgramSelection internal List<(string directory, BinaryType binaryType)> ExecutableDirectories; internal List DllDirectories; - internal readonly SortedList AllDlc = new(PlatformIdComparer.String); - internal readonly SortedList SelectedDlc = new(PlatformIdComparer.String); + internal readonly SortedList AllDlc + = new(PlatformIdComparer.String); - internal readonly List<(string id, string name, SortedList dlc)> ExtraDlc = new(); // for Paradox Launcher - internal readonly List<(string id, string name, SortedList dlc)> ExtraSelectedDlc = new(); // for Paradox Launcher + internal readonly SortedList SelectedDlc + = new(PlatformIdComparer.String); + + internal readonly List<(string id, string name, SortedList dlc)> + ExtraDlc = new(); // for Paradox Launcher + + internal readonly List<(string id, string name, SortedList dlc)> + ExtraSelectedDlc = new(); // for Paradox Launcher internal bool AreDllsLocked { @@ -63,49 +62,54 @@ internal class ProgramSelection { if (Platform is Platform.Steam or Platform.Paradox) { - directory.GetCreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + directory.GetCreamApiComponents(out string api32, out string api32_o, out string api64, + out string api64_o, out string config); if (api32.IsFilePathLocked() - || api32_o.IsFilePathLocked() - || api64.IsFilePathLocked() - || api64_o.IsFilePathLocked() - || config.IsFilePathLocked()) + || api32_o.IsFilePathLocked() + || api64.IsFilePathLocked() + || api64_o.IsFilePathLocked() + || config.IsFilePathLocked()) return true; - directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out config, out string cache); + directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out config, + out string cache); if (api32.IsFilePathLocked() - || api32_o.IsFilePathLocked() - || api64.IsFilePathLocked() - || api64_o.IsFilePathLocked() - || config.IsFilePathLocked() - || cache.IsFilePathLocked()) + || api32_o.IsFilePathLocked() + || api64.IsFilePathLocked() + || api64_o.IsFilePathLocked() + || config.IsFilePathLocked() + || cache.IsFilePathLocked()) return true; } if (Platform is Platform.Epic or Platform.Paradox) { - directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, + out string api64_o, out string config); if (api32.IsFilePathLocked() - || api32_o.IsFilePathLocked() - || api64.IsFilePathLocked() - || api64_o.IsFilePathLocked() - || config.IsFilePathLocked()) + || api32_o.IsFilePathLocked() + || api64.IsFilePathLocked() + || api64_o.IsFilePathLocked() + || config.IsFilePathLocked()) return true; } if (Platform is Platform.Ubisoft) { - directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, + out string api64_o, out string config); if (api32.IsFilePathLocked() - || api32_o.IsFilePathLocked() - || api64.IsFilePathLocked() - || api64_o.IsFilePathLocked() - || config.IsFilePathLocked()) + || api32_o.IsFilePathLocked() + || api64.IsFilePathLocked() + || api64_o.IsFilePathLocked() + || config.IsFilePathLocked()) return true; - directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config); + directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, + out api64, out api64_o, out config); if (old_api32.IsFilePathLocked() - || old_api64.IsFilePathLocked() - || api32.IsFilePathLocked() - || api32_o.IsFilePathLocked() - || api64.IsFilePathLocked() - || api64_o.IsFilePathLocked() - || config.IsFilePathLocked()) + || old_api64.IsFilePathLocked() + || api32.IsFilePathLocked() + || api32_o.IsFilePathLocked() + || api64.IsFilePathLocked() + || api64_o.IsFilePathLocked() + || config.IsFilePathLocked()) return true; } } @@ -164,7 +168,8 @@ internal class ProgramSelection internal static void ValidateAll() => AllSafe.ForEach(selection => selection.Validate()); - internal static void ValidateAll(List<(Platform 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 All = new(); @@ -172,12 +177,15 @@ internal class ProgramSelection internal static List AllEnabled => AllSafe.FindAll(s => s.Enabled); - internal static ProgramSelection FromPlatformId(Platform platform, string gameId) => AllSafe.Find(s => s.Platform == platform && 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)? GetDlcFromPlatformId(Platform platform, string dlcId) + internal static (string gameId, (DlcType type, string name, string icon) app)? GetDlcFromPlatformId( + Platform platform, string dlcId) { foreach (ProgramSelection selection in AllSafe.Where(s => s.Platform == platform)) - foreach (KeyValuePair pair in selection.AllDlc.Where(p => p.Key == dlcId)) + foreach (KeyValuePair pair in selection.AllDlc.Where( + p => p.Key == dlcId)) return (selection.Id, pair.Value); return null; } diff --git a/CreamInstaller/Properties/Resources.Designer.cs b/CreamInstaller/Properties/Resources.Designer.cs index b4bea93..ee75ee5 100644 --- a/CreamInstaller/Properties/Resources.Designer.cs +++ b/CreamInstaller/Properties/Resources.Designer.cs @@ -8,10 +8,16 @@ // //------------------------------------------------------------------------------ +using System.CodeDom.Compiler; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Globalization; +using System.Resources; +using System.Runtime.CompilerServices; + namespace CreamInstaller.Properties { - using System; - - /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,27 +25,27 @@ namespace CreamInstaller.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [DebuggerNonUserCode()] + [CompilerGenerated()] internal class Resources { - private static global::System.Resources.ResourceManager resourceMan; + private static ResourceManager resourceMan; - private static global::System.Globalization.CultureInfo resourceCulture; + private static CultureInfo resourceCulture; - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { + [EditorBrowsable(EditorBrowsableState.Advanced)] + internal static ResourceManager ResourceManager { get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CreamInstaller.Properties.Resources", typeof(Resources).Assembly); + if (ReferenceEquals(resourceMan, null)) { + ResourceManager temp = new ResourceManager("CreamInstaller.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -50,8 +56,8 @@ namespace CreamInstaller.Properties { /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { + [EditorBrowsable(EditorBrowsableState.Advanced)] + internal static CultureInfo Culture { get { return resourceCulture; } @@ -63,10 +69,10 @@ namespace CreamInstaller.Properties { /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// - internal static System.Drawing.Icon Icon { + internal static Icon Icon { get { object obj = ResourceManager.GetObject("Icon", resourceCulture); - return ((System.Drawing.Icon)(obj)); + return ((Icon)(obj)); } } } diff --git a/CreamInstaller/Resources/Koaloader.cs b/CreamInstaller/Resources/Koaloader.cs index 1d13b24..b931656 100644 --- a/CreamInstaller/Resources/Koaloader.cs +++ b/CreamInstaller/Resources/Koaloader.cs @@ -1,25 +1,35 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; - +using CreamInstaller.Components; +using CreamInstaller.Forms; +using CreamInstaller.Utility; using static CreamInstaller.Resources.Resources; namespace CreamInstaller.Resources; internal static class Koaloader { - internal static void GetKoaloaderComponents( - this string directory, - out List proxies, - out string config - ) + internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new() { - proxies = new(); + ("Koaloader", "Unlocker.dll"), ("Koaloader", "Unlocker32.dll"), ("Koaloader", "Unlocker64.dll"), + ("Lyptus", "Lyptus.dll"), ("Lyptus", "Lyptus32.dll"), ("Lyptus", "Lyptus64.dll"), + ("SmokeAPI", "SmokeAPI.dll"), ("SmokeAPI", "SmokeAPI32.dll"), ("SmokeAPI", "SmokeAPI64.dll"), + ("ScreamAPI", "ScreamAPI.dll"), ("ScreamAPI", "ScreamAPI32.dll"), ("ScreamAPI", "ScreamAPI64.dll"), + ("Uplay R1 Unlocker", "UplayR1Unlocker.dll"), ("Uplay R1 Unlocker", "UplayR1Unlocker32.dll"), + ("Uplay R1 Unlocker", "UplayR1Unlocker64.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker.dll"), + ("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll") + }; + + internal static void GetKoaloaderComponents( + this string directory, + out List proxies, + out string config + ) + { + proxies = new List(); foreach (string proxy in EmbeddedResources.Select(proxy => { proxy = proxy[(proxy.IndexOf('.') + 1)..]; @@ -41,25 +51,20 @@ internal static class Koaloader } } - internal static void GetProxyInfoFromIdentifier(this string resourceIdentifier, out string proxyName, out BinaryType binaryType) + internal static void GetProxyInfoFromIdentifier(this string resourceIdentifier, out string proxyName, + out BinaryType binaryType) { string baseIdentifier = resourceIdentifier[(resourceIdentifier.IndexOf('.') + 1)..]; baseIdentifier = baseIdentifier[..baseIdentifier.IndexOf('.')]; proxyName = baseIdentifier[..baseIdentifier.LastIndexOf('_')]; string bitness = baseIdentifier[(baseIdentifier.LastIndexOf('_') + 1)..]; - binaryType = bitness == "32" ? BinaryType.BIT32 : bitness == "64" ? BinaryType.BIT64 : BinaryType.Unknown; + binaryType = bitness == "32" + ? BinaryType.BIT32 + : bitness == "64" + ? BinaryType.BIT64 + : BinaryType.Unknown; } - internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new() - { - ("Koaloader", "Unlocker.dll"), ("Koaloader", "Unlocker32.dll"), ("Koaloader", "Unlocker64.dll"), - ("Lyptus", "Lyptus.dll"), ("Lyptus", "Lyptus32.dll"), ("Lyptus", "Lyptus64.dll"), - ("SmokeAPI", "SmokeAPI.dll"), ("SmokeAPI", "SmokeAPI32.dll"), ("SmokeAPI", "SmokeAPI64.dll"), - ("ScreamAPI", "ScreamAPI.dll"), ("ScreamAPI", "ScreamAPI32.dll"), ("ScreamAPI", "ScreamAPI64.dll"), - ("Uplay R1 Unlocker", "UplayR1Unlocker.dll"), ("Uplay R1 Unlocker", "UplayR1Unlocker32.dll"), ("Uplay R1 Unlocker", "UplayR1Unlocker64.dll"), - ("Uplay R2 Unlocker", "UplayR2Unlocker.dll"), ("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); @@ -78,11 +83,13 @@ internal static class Koaloader else if (File.Exists(config)) { File.Delete(config); - installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, + false); } } - internal static void WriteConfig(StreamWriter writer, SortedList targets, SortedList modules, InstallForm installForm = null) + internal static void WriteConfig(StreamWriter writer, SortedList targets, + SortedList modules, InstallForm installForm = null) { writer.WriteLine("{"); writer.WriteLine(" \"logging\": false,"); @@ -96,12 +103,14 @@ internal static class Koaloader { string path = pair.Value; writer.WriteLine($" \"{path}\"{(pair.Equals(lastTarget) ? "" : ",")}"); - installForm?.UpdateUser($"Added target to Koaloader.json with path {path}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added target to Koaloader.json with path {path}", LogTextBox.Action, false); } writer.WriteLine(" ]"); } else + { writer.WriteLine(" \"targets\": []"); + } if (modules.Any()) { writer.WriteLine(" \"modules\": ["); @@ -110,37 +119,41 @@ internal static class Koaloader { string path = pair.Value; writer.WriteLine(" {"); - writer.WriteLine($" \"path\": \"" + path + "\","); - writer.WriteLine($" \"required\": true"); + writer.WriteLine(" \"path\": \"" + path + "\","); + writer.WriteLine(" \"required\": true"); writer.WriteLine(" }" + (pair.Equals(lastModule) ? "" : ",")); - installForm?.UpdateUser($"Added module to Koaloader.json with path {path}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added module to Koaloader.json with path {path}", LogTextBox.Action, false); } writer.WriteLine(" ]"); } else + { writer.WriteLine(" \"modules\": []"); + } writer.WriteLine("}"); } - internal static async Task Uninstall(string directory, string rootDirectory = null, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(async () => + internal static async Task Uninstall(string directory, string rootDirectory = null, InstallForm installForm = null, + bool deleteConfig = true) => await Task.Run(async () => { directory.GetKoaloaderComponents(out List proxies, out string config); - foreach (string proxyPath in proxies.Where(proxyPath => File.Exists(proxyPath) && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader))) + foreach (string proxyPath in proxies.Where( + proxyPath => File.Exists(proxyPath) && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader))) { File.Delete(proxyPath); - installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false); } foreach ((string unlocker, string path) in AutoLoadDlls - .Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) - .Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile())) + .Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) + .Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile())) { File.Delete(path); - installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false); } if (deleteConfig && File.Exists(config)) { File.Delete(config); - installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false); } await SmokeAPI.Uninstall(directory, installForm, deleteConfig); await ScreamAPI.Uninstall(directory, installForm, deleteConfig); @@ -150,20 +163,26 @@ internal static class Koaloader await Uninstall(rootDirectory, null, installForm, deleteConfig); }); - internal static async Task Install(string directory, BinaryType binaryType, ProgramSelection selection, string rootDirectory = null, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() => + internal static async Task Install(string directory, BinaryType binaryType, ProgramSelection selection, + string rootDirectory = null, InstallForm installForm = null, + bool generateConfig = true) => await Task.Run(() => { directory.GetKoaloaderComponents(out List proxies, out string config); string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy; string path = directory + @"\" + proxy + ".dll"; - foreach (string _path in proxies.Where(p => p != path && File.Exists(p) && p.IsResourceFile(ResourceIdentifier.Koaloader))) + foreach (string _path in proxies.Where(p => p != path && File.Exists(p) + && p.IsResourceFile(ResourceIdentifier.Koaloader))) { File.Delete(_path); - installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, false); } if (File.Exists(path) && !path.IsResourceFile(ResourceIdentifier.Koaloader)) - throw new CustomMessageException("A non-Koaloader DLL named " + proxy + ".dll already exists in this directory!"); + throw new CustomMessageException("A non-Koaloader DLL named " + proxy + + ".dll already exists in this directory!"); path.WriteProxy(proxy, binaryType); - installForm?.UpdateUser($"Wrote {(binaryType == BinaryType.BIT32 ? "32-bit" : "64-bit")} Koaloader: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote {(binaryType == BinaryType.BIT32 ? "32-bit" : "64-bit")} Koaloader: {Path.GetFileName(path)}", + LogTextBox.Action, false); bool bit32 = false, bit64 = false; foreach (string executable in Directory.EnumerateFiles(directory, "*.exe")) if (executable.TryGetFileBinaryType(out BinaryType binaryType)) @@ -185,12 +204,15 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\SmokeAPI32.dll"; } "SmokeAPI.steam_api.dll".Write(path); - installForm?.UpdateUser($"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } if (bit64) { @@ -200,12 +222,15 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\SmokeAPI64.dll"; } "SmokeAPI.steam_api64.dll".Write(path); - installForm?.UpdateUser($"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } SmokeAPI.CheckConfig(rootDirectory ?? directory, selection, installForm); } @@ -219,12 +244,15 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\ScreamAPI32.dll"; } "ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(path); - installForm?.UpdateUser($"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } if (bit64) { @@ -234,12 +262,15 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\ScreamAPI64.dll"; } "ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(path); - installForm?.UpdateUser($"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } ScreamAPI.CheckConfig(rootDirectory ?? directory, selection, installForm); } @@ -253,12 +284,16 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\UplayR1Unlocker32.dll"; } "UplayR1.uplay_r1_loader.dll".Write(path); - installForm?.UpdateUser($"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } if (bit64) { @@ -268,12 +303,16 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\UplayR1Unlocker64.dll"; } "UplayR1.uplay_r1_loader64.dll".Write(path); - installForm?.UpdateUser($"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } UplayR1.CheckConfig(rootDirectory ?? directory, selection, installForm); if (bit32) @@ -284,12 +323,16 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\UplayR2Unlocker32.dll"; } "UplayR2.upc_r2_loader.dll".Write(path); - installForm?.UpdateUser($"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } if (bit64) { @@ -299,12 +342,16 @@ internal static class Koaloader if (File.Exists(path)) { File.Delete(path); - installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", + LogTextBox.Action, false); } path = rootDirectory + @"\UplayR2Unlocker64.dll"; } "UplayR2.upc_r2_loader64.dll".Write(path); - installForm?.UpdateUser($"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", LogTextBox.Action, info: false); + installForm?.UpdateUser( + $"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}", + LogTextBox.Action, false); } UplayR2.CheckConfig(rootDirectory ?? directory, selection, installForm); } diff --git a/CreamInstaller/Resources/Resources.cs b/CreamInstaller/Resources/Resources.cs index 190102f..085e4d7 100644 --- a/CreamInstaller/Resources/Resources.cs +++ b/CreamInstaller/Resources/Resources.cs @@ -1,6 +1,4 @@ -using CreamInstaller.Utility; - -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -9,12 +7,14 @@ using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; +using CreamInstaller.Utility; namespace CreamInstaller.Resources; internal static class Resources { internal static List embeddedResources; + internal static List EmbeddedResources { get @@ -22,7 +22,7 @@ internal static class Resources if (embeddedResources is null) { string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames(); - embeddedResources = new(); + embeddedResources = new List(); foreach (string resourceName in names.Where(n => n.StartsWith("CreamInstaller.Resources."))) embeddedResources.Add(resourceName[25..]); } @@ -32,7 +32,8 @@ internal static class Resources internal static void Write(this string resourceIdentifier, string filePath) { - using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier); + using Stream resource = Assembly.GetExecutingAssembly() + .GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier); using FileStream file = new(filePath, FileMode.Create, FileAccess.Write); resource.CopyTo(file); } @@ -62,55 +63,59 @@ internal static class Resources internal enum BinaryType { - Unknown = -1, - BIT32 = 0, - DOS = 1, - WOW = 2, - PIF = 3, - POSIX = 4, - OS216 = 5, - BIT64 = 6, + Unknown = -1, BIT32 = 0, DOS = 1, + WOW = 2, PIF = 3, POSIX = 4, + OS216 = 5, BIT64 = 6 } [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern bool GetBinaryType(string lpApplicationName, out BinaryType lpBinaryType); - internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => GetBinaryType(path, out binaryType); - internal static async Task> GetExecutableDirectories(this string rootDirectory, bool filterCommon = false, Func validFunc = null) => - await Task.Run(async () => (await rootDirectory.GetExecutables(filterCommon: filterCommon, validFunc: validFunc) - ?? (filterCommon || validFunc is not null ? await rootDirectory.GetExecutables() : null))?.Select(e => + internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) + => GetBinaryType(path, out binaryType); + + internal static async Task> GetExecutableDirectories( + this string rootDirectory, bool filterCommon = false, Func validFunc = null) => + await Task.Run(async () => (await rootDirectory.GetExecutables(filterCommon, validFunc) + ?? (filterCommon || validFunc is not null + ? await rootDirectory.GetExecutables() + : null))?.Select(e => { e.path = Path.GetDirectoryName(e.path); return e; })?.DistinctBy(e => e.path).ToList()); - internal static async Task> GetExecutables(this string rootDirectory, bool filterCommon = false, Func validFunc = null) => await Task.Run(() => - { - List<(string path, BinaryType binaryType)> executables = new(); - if (Program.Canceled || !Directory.Exists(rootDirectory)) return null; - foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe", new EnumerationOptions() { RecurseSubdirectories = true })) + internal static async Task> GetExecutables( + this string rootDirectory, bool filterCommon = false, Func validFunc = null) => await Task.Run( + () => { - if (Program.Canceled) return null; - if (!executables.Any(e => e.path == path) - && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) - && (validFunc is null || validFunc(path)) - && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64) - executables.Add((path, binaryType)); - Thread.Sleep(1); - } - foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe", new EnumerationOptions() { RecurseSubdirectories = true })) - { - if (Program.Canceled) return null; - if (!executables.Any(e => e.path == path) - && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) - && (validFunc is null || validFunc(path)) - && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32) - executables.Add((path, binaryType)); - Thread.Sleep(1); - } - return !executables.Any() ? null : executables; - }); + List<(string path, BinaryType binaryType)> executables = new(); + if (Program.Canceled || !Directory.Exists(rootDirectory)) return null; + foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe", + new EnumerationOptions { RecurseSubdirectories = true })) + { + if (Program.Canceled) return null; + if (!executables.Any(e => e.path == path) + && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) + && (validFunc is null || validFunc(path)) + && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64) + executables.Add((path, binaryType)); + Thread.Sleep(1); + } + foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe", + new EnumerationOptions { RecurseSubdirectories = true })) + { + if (Program.Canceled) return null; + if (!executables.Any(e => e.path == path) + && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) + && (validFunc is null || validFunc(path)) + && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32) + executables.Add((path, binaryType)); + Thread.Sleep(1); + } + return !executables.Any() ? null : executables; + }); internal static bool IsCommonIncorrectExecutable(this string rootDirectory, string path) { @@ -118,69 +123,77 @@ internal static class Resources return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT") - || subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")) + || (subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT"))) || subPath.Contains("HELPER") || subPath.Contains("CEFPROCESS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS") || subPath.Contains("MODDING") - || subPath.Contains("MOD") && subPath.Contains("MANAGER") + || (subPath.Contains("MOD") && subPath.Contains("MANAGER")) || subPath.Contains("BATTLEYE") || subPath.Contains("ANTICHEAT"); } - internal static async Task> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform) => await Task.Run(() => + internal static async Task> GetDllDirectoriesFromGameDirectory( + this string gameDirectory, Platform platform) => await Task.Run(() => { List dllDirectories = new(); if (Program.Canceled || !Directory.Exists(gameDirectory)) return null; - foreach (string directory in Directory.EnumerateDirectories(gameDirectory, "*", new EnumerationOptions() { RecurseSubdirectories = true }).Append(gameDirectory)) + foreach (string directory in Directory + .EnumerateDirectories(gameDirectory, "*", + new EnumerationOptions { RecurseSubdirectories = true }) + .Append(gameDirectory)) { if (Program.Canceled) return null; string subDirectory = directory.BeautifyPath(); if (!dllDirectories.Contains(subDirectory)) { bool koaloaderInstalled = Koaloader.AutoLoadDlls - .Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) - .Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile()); + .Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) + .Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile()); if (platform is Platform.Steam or Platform.Paradox) { - subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string config, out string cache); + subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, + out string api64_o, out string config, out string cache); if (File.Exists(api) - || File.Exists(api_o) - || File.Exists(api64) - || File.Exists(api64_o) - || File.Exists(config) && !koaloaderInstalled - || File.Exists(cache) && !koaloaderInstalled) + || File.Exists(api_o) + || File.Exists(api64) + || File.Exists(api64_o) + || (File.Exists(config) && !koaloaderInstalled) + || (File.Exists(cache) && !koaloaderInstalled)) dllDirectories.Add(subDirectory); } if (platform is Platform.Epic or Platform.Paradox) { - subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + subDirectory.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) && !koaloaderInstalled) + || File.Exists(api32_o) + || File.Exists(api64) + || File.Exists(api64_o) + || (File.Exists(config) && !koaloaderInstalled)) dllDirectories.Add(subDirectory); } if (platform is Platform.Ubisoft) { - subDirectory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + subDirectory.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) && !koaloaderInstalled) + || File.Exists(api32_o) + || File.Exists(api64) + || File.Exists(api64_o) + || (File.Exists(config) && !koaloaderInstalled)) dllDirectories.Add(subDirectory); - subDirectory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config); + subDirectory.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) && !koaloaderInstalled) + || File.Exists(old_api64) + || File.Exists(api32) + || File.Exists(api32_o) + || File.Exists(api64) + || File.Exists(api64_o) + || (File.Exists(config) && !koaloaderInstalled)) dllDirectories.Add(subDirectory); } } @@ -189,10 +202,10 @@ internal static class Resources }); internal static void GetCreamApiComponents( - this string directory, - out string api32, out string api32_o, - out string api64, out string api64_o, - out string config) + this string directory, + out string api32, out string api32_o, + out string api64, out string api64_o, + out string config) { api32 = directory + @"\steam_api.dll"; api32_o = directory + @"\steam_api_o.dll"; @@ -203,22 +216,15 @@ internal static class Resources internal enum ResourceIdentifier { - Koaloader, - Steamworks32, - Steamworks64, - EpicOnlineServices32, - EpicOnlineServices64, - Uplay32, - Uplay64, - Upc32, - Upc64, + Koaloader, Steamworks32, Steamworks64, + EpicOnlineServices32, EpicOnlineServices64, Uplay32, + Uplay64, Upc32, Upc64 } internal static readonly Dictionary> ResourceMD5s = new() { { - ResourceIdentifier.Koaloader, - new List() + ResourceIdentifier.Koaloader, new List { "8A0958687B5ED7C34DAD037856DD1530", // Koaloader v2.0.0 "8FECDEB40980F4E687C10E056232D96B", // Koaloader v2.0.0 @@ -463,75 +469,67 @@ internal static class Resources "76CAB00C7DD33FC19F7CDD1849FF9CA2", // Koaloader v2.4.0 "DA4D6A7C0872757A74DDAE05A2C1D160", // Koaloader v2.4.0 "1F46DE8747C0A157841AFFE6185CE4C9", // Koaloader v2.4.0 - "BE16B588D018D8EFF1F3B6A600F26BED" // Koaloader v2.4.0 + "BE16B588D018D8EFF1F3B6A600F26BED" // Koaloader v2.4.0 } }, { - ResourceIdentifier.EpicOnlineServices32, - new List() + ResourceIdentifier.EpicOnlineServices32, new List { "069A57B1834A960193D2AD6B96926D70", // ScreamAPI v3.0.0 - "E2FB3A4A9583FDC215832E5F935E4440" // ScreamAPI v3.0.1 + "E2FB3A4A9583FDC215832E5F935E4440" // ScreamAPI v3.0.1 } }, { - ResourceIdentifier.EpicOnlineServices64, - new List() + ResourceIdentifier.EpicOnlineServices64, new List { "0D62E57139F1A64F807A9934946A9474", // ScreamAPI v3.0.0 - "3875C7B735EE80C23239CC4749FDCBE6" // ScreamAPI v3.0.1 + "3875C7B735EE80C23239CC4749FDCBE6" // ScreamAPI v3.0.1 } }, { - ResourceIdentifier.Steamworks32, - new List() + ResourceIdentifier.Steamworks32, new List { "02594110FE56B2945955D46670B9A094", // CreamAPI v4.5.0.0 Hotfix "B2434578957CBE38BDCE0A671C1262FC", // SmokeAPI v1.0.0 "973AB1632B747D4BF3B2666F32E34327", // SmokeAPI v1.0.1 "C7E41F569FC6A347D67D2BFB2BD10F25", // SmokeAPI v1.0.2 - "F9E7D5B248B86D1C2F2F2905A9F37755" // SmokeAPI v1.0.3 + "F9E7D5B248B86D1C2F2F2905A9F37755" // SmokeAPI v1.0.3 } }, { - ResourceIdentifier.Steamworks64, - new List() + ResourceIdentifier.Steamworks64, new List { "30091B91923D9583A54A93ED1145554B", // CreamAPI v4.5.0.0 Hotfix "08713035CAD6F52548FF324D0487B88D", // SmokeAPI v1.0.0 "D077737B9979D32458AC938A2978FA3C", // SmokeAPI v1.0.1 "49122A2E2E51CBB0AE5E1D59B280E4CD", // SmokeAPI v1.0.2 - "13F3E9476116F7670E21365A400357AC" // SmokeAPI v1.0.3 + "13F3E9476116F7670E21365A400357AC" // SmokeAPI v1.0.3 } }, { - ResourceIdentifier.Uplay32, - new List() + ResourceIdentifier.Uplay32, new List { "1977967B2549A38EC2DB39D4C8ED499B" // Uplay R1 Unlocker v2.0.0 } }, { - ResourceIdentifier.Uplay64, - new List() + ResourceIdentifier.Uplay64, new List { "333FEDD9DC2B299419B37ED1624FF8DB" // Uplay R1 Unlocker v2.0.0 } }, { - ResourceIdentifier.Upc32, - new List() + ResourceIdentifier.Upc32, new List { "C14368BC4EE19FDE8DBAC07E31C67AE4", // Uplay R2 Unlocker v3.0.0 - "DED3A3EA1876E3110D7D87B9A22946B0" // Uplay R2 Unlocker v3.0.1 + "DED3A3EA1876E3110D7D87B9A22946B0" // Uplay R2 Unlocker v3.0.1 } }, { - ResourceIdentifier.Upc64, - new List() + ResourceIdentifier.Upc64, new List { "7D9A4C12972BAABCB6C181920CC0F19B", // Uplay R2 Unlocker v3.0.0 - "D7FDBFE0FC8D7600FEB8EC0A97713184" // Uplay R2 Unlocker v3.0.1 + "D7FDBFE0FC8D7600FEB8EC0A97713184" // Uplay R2 Unlocker v3.0.1 } } }; @@ -547,7 +545,10 @@ internal static class Resources return BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant(); } - internal static bool IsResourceFile(this string filePath, ResourceIdentifier identifier) => filePath.ComputeMD5() is string hash && ResourceMD5s[identifier].Contains(hash); + internal static bool IsResourceFile(this string filePath, ResourceIdentifier identifier) + => filePath.ComputeMD5() is string hash && ResourceMD5s[identifier].Contains(hash); - internal static bool IsResourceFile(this string filePath) => filePath.ComputeMD5() is string hash && ResourceMD5s.Values.Any(hashes => hashes.Contains(hash)); + internal static bool IsResourceFile(this string filePath) => filePath.ComputeMD5() is string hash + && ResourceMD5s.Values.Any( + hashes => hashes.Contains(hash)); } diff --git a/CreamInstaller/Resources/ScreamAPI.cs b/CreamInstaller/Resources/ScreamAPI.cs index 44b1d7e..84c4fe3 100644 --- a/CreamInstaller/Resources/ScreamAPI.cs +++ b/CreamInstaller/Resources/ScreamAPI.cs @@ -1,22 +1,22 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using CreamInstaller.Components; +using CreamInstaller.Forms; +using CreamInstaller.Utility; namespace CreamInstaller.Resources; internal static class ScreamAPI { internal static void GetScreamApiComponents( - this string directory, - out string api32, out string api32_o, - out string api64, out string api64_o, - out string config - ) + this string directory, + out string api32, out string api32_o, + out string api64, out string api64_o, + out string config + ) { api32 = directory + @"\EOSSDK-Win32-Shipping.dll"; api32_o = directory + @"\EOSSDK-Win32-Shipping_o.dll"; @@ -28,11 +28,15 @@ internal static class ScreamAPI internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) { directory.GetScreamApiComponents(out _, out _, out _, out _, out string config); - IEnumerable> overrideCatalogItems = selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + IEnumerable> overrideCatalogItems + = selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in + selection.ExtraSelectedDlc) overrideCatalogItems = overrideCatalogItems.Except(extraDlc); - IEnumerable> entitlements = selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement); - foreach ((string id, string name, SortedList _dlc) in selection.ExtraSelectedDlc) + IEnumerable> entitlements + = selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement); + foreach ((string id, string name, SortedList _dlc) in + selection.ExtraSelectedDlc) entitlements = entitlements.Concat(_dlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement)); if (overrideCatalogItems.Any() || entitlements.Any()) { @@ -41,20 +45,27 @@ internal static class ScreamAPI 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); + new SortedList( + overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value), + PlatformIdComparer.String), + new SortedList( + entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + installForm); writer.Flush(); writer.Close(); } else if (File.Exists(config)) { File.Delete(config); - installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, + false); } } - internal static void WriteConfig(StreamWriter writer, SortedList overrideCatalogItems, SortedList entitlements, InstallForm installForm = null) + internal static void WriteConfig(StreamWriter writer, + SortedList overrideCatalogItems, + SortedList entitlements, + InstallForm installForm = null) { writer.WriteLine("{"); writer.WriteLine(" \"version\": 2,"); @@ -66,18 +77,22 @@ internal static class ScreamAPI if (overrideCatalogItems.Any()) { writer.WriteLine(" \"override\": ["); - KeyValuePair lastOverrideCatalogItem = overrideCatalogItems.Last(); + KeyValuePair lastOverrideCatalogItem + = overrideCatalogItems.Last(); foreach (KeyValuePair pair in overrideCatalogItems) { string id = pair.Key; (_, string name, _) = pair.Value; writer.WriteLine($" \"{id}\"{(pair.Equals(lastOverrideCatalogItem) ? "" : ",")}"); - installForm?.UpdateUser($"Added override catalog item to ScreamAPI.json with id {id} ({name})", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added override catalog item to ScreamAPI.json with id {id} ({name})", + LogTextBox.Action, false); } writer.WriteLine(" ]"); } else + { writer.WriteLine(" \"override\": []"); + } writer.WriteLine(" },"); writer.WriteLine(" \"entitlements\": {"); writer.WriteLine(" \"unlock_all\": true,"); @@ -91,68 +106,79 @@ internal static class ScreamAPI string id = pair.Key; (_, string name, _) = pair.Value; writer.WriteLine($" \"{id}\"{(pair.Equals(lastEntitlement) ? "" : ",")}"); - installForm?.UpdateUser($"Added entitlement to ScreamAPI.json with id {id} ({name})", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added entitlement to ScreamAPI.json with id {id} ({name})", LogTextBox.Action, + false); } writer.WriteLine(" ]"); } else + { writer.WriteLine(" \"inject\": []"); + } writer.WriteLine(" }"); writer.WriteLine("}"); } - internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(() => - { - directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); - if (File.Exists(api32_o)) + internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) + => await Task.Run(() => { - if (File.Exists(api32)) + directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, + out string config); + if (File.Exists(api32_o)) { - File.Delete(api32); - installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, info: false); + if (File.Exists(api32)) + { + File.Delete(api32); + installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false); + } + File.Move(api32_o, api32); + installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", + LogTextBox.Action, false); } - File.Move(api32_o, api32); - installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, info: false); - } - if (File.Exists(api64_o)) - { - if (File.Exists(api64)) + if (File.Exists(api64_o)) { - File.Delete(api64); - installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, info: false); + if (File.Exists(api64)) + { + File.Delete(api64); + installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false); + } + File.Move(api64_o, api64); + installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", + LogTextBox.Action, false); } - File.Move(api64_o, api64); - installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, info: false); - } - if (deleteConfig && File.Exists(config)) - { - File.Delete(config); - installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); - } - }); + if (deleteConfig && File.Exists(config)) + { + File.Delete(config); + installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false); + } + }); - internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() => + internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, + bool generateConfig = true) => await Task.Run(() => { - directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + 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.Move(api32, api32_o); - installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", + LogTextBox.Action, false); } if (File.Exists(api32_o)) { "ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(api32); - installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false); } if (File.Exists(api64) && !File.Exists(api64_o)) { File.Move(api64, api64_o); - installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", + LogTextBox.Action, false); } if (File.Exists(api64_o)) { "ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(api64); - installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false); } if (generateConfig) CheckConfig(directory, selection, installForm); diff --git a/CreamInstaller/Resources/SmokeAPI.cs b/CreamInstaller/Resources/SmokeAPI.cs index 005057d..6b3c96d 100644 --- a/CreamInstaller/Resources/SmokeAPI.cs +++ b/CreamInstaller/Resources/SmokeAPI.cs @@ -1,22 +1,22 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using CreamInstaller.Components; +using CreamInstaller.Forms; +using CreamInstaller.Utility; namespace CreamInstaller.Resources; internal static class SmokeAPI { internal static void GetSmokeApiComponents( - this string directory, - out string api32, out string api32_o, - out string api64, out string api64_o, - out string config, - out string cache) + this string directory, + out string api32, out string api32_o, + out string api64, out string api64_o, + out string config, + out string cache) { api32 = directory + @"\steam_api.dll"; api32_o = directory + @"\steam_api_o.dll"; @@ -29,14 +29,18 @@ internal static class SmokeAPI internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) { directory.GetSmokeApiComponents(out _, out _, out _, out _, out string config, out _); - IEnumerable> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + IEnumerable> overrideDlc + = selection.AllDlc.Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in + selection.ExtraSelectedDlc) overrideDlc = overrideDlc.Except(extraDlc); - IEnumerable> injectDlc = new List>(); + IEnumerable> injectDlc + = new List>(); if (selection.AllDlc.Count > 64 || selection.ExtraDlc.Any(e => e.dlc.Count > 64)) { injectDlc = injectDlc.Concat(selection.SelectedDlc.Where(pair => pair.Value.type is DlcType.SteamHidden)); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + foreach ((string id, string name, SortedList extraDlc) in + selection.ExtraSelectedDlc) if (selection.ExtraDlc.Where(e => e.id == id).Single().dlc.Count > 64) injectDlc = injectDlc.Concat(extraDlc.Where(pair => pair.Value.type is DlcType.SteamHidden)); } @@ -47,20 +51,26 @@ internal static class SmokeAPI 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); + new SortedList( + overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + new SortedList( + injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + installForm); writer.Flush(); writer.Close(); } else if (File.Exists(config)) { File.Delete(config); - installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, + false); } } - internal static void WriteConfig(StreamWriter writer, SortedList overrideDlc, SortedList injectDlc, InstallForm installForm = null) + internal static void WriteConfig(StreamWriter writer, + SortedList overrideDlc, + SortedList injectDlc, + InstallForm installForm = null) { writer.WriteLine("{"); writer.WriteLine(" \"$version\": 1,"); @@ -76,12 +86,15 @@ internal static class SmokeAPI string dlcId = pair.Key; (_, string dlcName, _) = pair.Value; writer.WriteLine($" {dlcId}{(pair.Equals(lastOverrideDlc) ? "" : ",")}"); - installForm?.UpdateUser($"Added override DLC to SmokeAPI.json with appid {dlcId} ({dlcName})", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added override DLC to SmokeAPI.json with appid {dlcId} ({dlcName})", + LogTextBox.Action, false); } writer.WriteLine(" ],"); } else + { writer.WriteLine(" \"override\": [],"); + } if (injectDlc.Count > 0) { writer.WriteLine(" \"dlc_ids\": ["); @@ -91,86 +104,101 @@ internal static class SmokeAPI string dlcId = pair.Key; (_, string dlcName, _) = pair.Value; writer.WriteLine($" {dlcId}{(pair.Equals(lastInjectDlc) ? "" : ",")}"); - installForm?.UpdateUser($"Added inject DLC to SmokeAPI.json with appid {dlcId} ({dlcName})", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added inject DLC to SmokeAPI.json with appid {dlcId} ({dlcName})", + LogTextBox.Action, false); } writer.WriteLine(" ],"); } else + { writer.WriteLine(" \"dlc_ids\": [],"); + } writer.WriteLine(" \"auto_inject_inventory\": true,"); writer.WriteLine(" \"inventory_items\": []"); writer.WriteLine("}"); } - internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(() => - { - directory.GetCreamApiComponents(out _, out _, out _, out _, out string oldConfig); - if (File.Exists(oldConfig)) + internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) + => await Task.Run(() => { - File.Delete(oldConfig); - installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, info: false); - } - 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_o)) - { - if (File.Exists(api32)) + directory.GetCreamApiComponents(out _, out _, out _, out _, out string oldConfig); + if (File.Exists(oldConfig)) { - File.Delete(api32); - installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, info: false); + File.Delete(oldConfig); + installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", + LogTextBox.Action, false); } - File.Move(api32_o, api32); - installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, info: false); - } - if (File.Exists(api64_o)) - { - if (File.Exists(api64)) + 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_o)) { - File.Delete(api64); - installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, info: false); + if (File.Exists(api32)) + { + File.Delete(api32); + installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false); + } + File.Move(api32_o, api32); + installForm?.UpdateUser( + $"Restored Steamworks: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, + false); } - File.Move(api64_o, api64); - installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, info: false); - } - if (deleteConfig && File.Exists(config)) - { - File.Delete(config); - installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); - } - if (deleteConfig && File.Exists(cache)) - { - File.Delete(cache); - installForm?.UpdateUser($"Deleted cache: {Path.GetFileName(cache)}", LogTextBox.Action, info: false); - } - }); + if (File.Exists(api64_o)) + { + if (File.Exists(api64)) + { + File.Delete(api64); + installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false); + } + File.Move(api64_o, api64); + installForm?.UpdateUser( + $"Restored Steamworks: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, + false); + } + if (deleteConfig && File.Exists(config)) + { + File.Delete(config); + installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false); + } + if (deleteConfig && File.Exists(cache)) + { + File.Delete(cache); + installForm?.UpdateUser($"Deleted cache: {Path.GetFileName(cache)}", LogTextBox.Action, false); + } + }); - internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() => + internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, + bool generateConfig = true) => await Task.Run(() => { directory.GetCreamApiComponents(out _, out _, out _, out _, out string oldConfig); if (File.Exists(oldConfig)) { File.Delete(oldConfig); - installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", + LogTextBox.Action, false); } - directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out _); + directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, + out string config, out _); if (File.Exists(api32) && !File.Exists(api32_o)) { File.Move(api32, api32_o); - installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", + LogTextBox.Action, false); } if (File.Exists(api32_o)) { "SmokeAPI.steam_api.dll".Write(api32); - installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false); } if (File.Exists(api64) && !File.Exists(api64_o)) { File.Move(api64, api64_o); - installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", + LogTextBox.Action, false); } if (File.Exists(api64_o)) { "SmokeAPI.steam_api64.dll".Write(api64); - installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false); } if (generateConfig) CheckConfig(directory, selection, installForm); diff --git a/CreamInstaller/Resources/UplayR1.cs b/CreamInstaller/Resources/UplayR1.cs index f2f2347..8177cd9 100644 --- a/CreamInstaller/Resources/UplayR1.cs +++ b/CreamInstaller/Resources/UplayR1.cs @@ -1,22 +1,22 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using CreamInstaller.Components; +using CreamInstaller.Forms; +using CreamInstaller.Utility; namespace CreamInstaller.Resources; internal static class UplayR1 { internal static void GetUplayR1Components( - this string directory, - out string api32, out string api32_o, - out string api64, out string api64_o, - out string config - ) + this string directory, + out string api32, out string api32_o, + out string api64, out string api64_o, + out string config + ) { api32 = directory + @"\uplay_r1_loader.dll"; api32_o = directory + @"\uplay_r1_loader_o.dll"; @@ -28,8 +28,10 @@ internal static class UplayR1 internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) { directory.GetUplayR1Components(out _, out _, out _, out _, out string config); - IEnumerable> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + IEnumerable> blacklistDlc + = selection.AllDlc.Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in + selection.ExtraSelectedDlc) blacklistDlc = blacklistDlc.Except(extraDlc); if (blacklistDlc.Any()) { @@ -37,18 +39,24 @@ internal static class UplayR1 installForm.UpdateUser("Generating Uplay R1 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.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); + WriteConfig(writer, + new SortedList( + blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + installForm); writer.Flush(); writer.Close(); } else if (File.Exists(config)) { File.Delete(config); - installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, + false); } } - internal static void WriteConfig(StreamWriter writer, SortedList blacklistDlc, InstallForm installForm = null) + internal static void WriteConfig(StreamWriter writer, + SortedList blacklistDlc, + InstallForm installForm = null) { writer.WriteLine("{"); writer.WriteLine(" \"logging\": false,"); @@ -63,67 +71,80 @@ internal static class UplayR1 string dlcId = pair.Key; (_, string dlcName, _) = pair.Value; writer.WriteLine($" {dlcId}{(pair.Equals(lastBlacklistDlc) ? "" : ",")}"); - installForm?.UpdateUser($"Added blacklist DLC to UplayR1Unlocker.jsonc with appid {dlcId} ({dlcName})", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added blacklist DLC to UplayR1Unlocker.jsonc with appid {dlcId} ({dlcName})", + LogTextBox.Action, false); } writer.WriteLine(" ],"); } else + { writer.WriteLine(" \"blacklist\": [],"); + } writer.WriteLine("}"); } - internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(() => - { - directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config); - if (File.Exists(api32_o)) + internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) + => await Task.Run(() => { - if (File.Exists(api32)) + directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, + out string config); + if (File.Exists(api32_o)) { - File.Delete(api32); - installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, info: false); + if (File.Exists(api32)) + { + File.Delete(api32); + installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, + false); + } + File.Move(api32_o, api32); + installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", + LogTextBox.Action, false); } - File.Move(api32_o, api32); - installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, info: false); - } - if (File.Exists(api64_o)) - { - if (File.Exists(api64)) + if (File.Exists(api64_o)) { - File.Delete(api64); - installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, info: false); + if (File.Exists(api64)) + { + File.Delete(api64); + installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, + false); + } + File.Move(api64_o, api64); + installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", + LogTextBox.Action, false); } - File.Move(api64_o, api64); - installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, info: false); - } - if (deleteConfig && File.Exists(config)) - { - File.Delete(config); - installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); - } - }); + if (deleteConfig && File.Exists(config)) + { + File.Delete(config); + installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false); + } + }); - internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() => + internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, + bool generateConfig = true) => await Task.Run(() => { - directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config); + 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.Move(api32, api32_o); - installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", + LogTextBox.Action, false); } if (File.Exists(api32_o)) { "UplayR1.uplay_r1_loader.dll".Write(api32); - installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, false); } if (File.Exists(api64) && !File.Exists(api64_o)) { File.Move(api64, api64_o); - installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", + LogTextBox.Action, false); } if (File.Exists(api64_o)) { "UplayR1.uplay_r1_loader64.dll".Write(api64); - installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, false); } if (generateConfig) CheckConfig(directory, selection, installForm); diff --git a/CreamInstaller/Resources/UplayR2.cs b/CreamInstaller/Resources/UplayR2.cs index 1bf9b58..d9845e3 100644 --- a/CreamInstaller/Resources/UplayR2.cs +++ b/CreamInstaller/Resources/UplayR2.cs @@ -1,22 +1,22 @@ -using CreamInstaller.Components; -using CreamInstaller.Utility; - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using CreamInstaller.Components; +using CreamInstaller.Forms; +using CreamInstaller.Utility; namespace CreamInstaller.Resources; internal static class UplayR2 { internal static void GetUplayR2Components( - this string directory, - out string old_api32, out string old_api64, - out string api32, out string api32_o, - out string api64, out string api64_o, - out string config) + this string directory, + out string old_api32, out string old_api64, + out string api32, out string api32_o, + out string api64, out string api64_o, + out string config) { old_api32 = directory + @"\uplay_r2_loader.dll"; old_api64 = directory + @"\uplay_r2_loader64.dll"; @@ -30,8 +30,10 @@ internal static class UplayR2 internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null) { directory.GetUplayR2Components(out _, out _, out _, out _, out _, out _, out string config); - IEnumerable> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc); - foreach ((string id, string name, SortedList extraDlc) in selection.ExtraSelectedDlc) + IEnumerable> blacklistDlc + = selection.AllDlc.Except(selection.SelectedDlc); + foreach ((string id, string name, SortedList extraDlc) in + selection.ExtraSelectedDlc) blacklistDlc = blacklistDlc.Except(extraDlc); if (blacklistDlc.Any()) { @@ -39,18 +41,24 @@ internal static class UplayR2 installForm.UpdateUser("Generating Uplay R2 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.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); + WriteConfig(writer, + new SortedList( + blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), + installForm); writer.Flush(); writer.Close(); } else if (File.Exists(config)) { File.Delete(config); - installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, + false); } } - internal static void WriteConfig(StreamWriter writer, SortedList blacklistDlc, InstallForm installForm = null) + internal static void WriteConfig(StreamWriter writer, + SortedList blacklistDlc, + InstallForm installForm = null) { writer.WriteLine("{"); writer.WriteLine(" \"logging\": false,"); @@ -67,71 +75,84 @@ internal static class UplayR2 string dlcId = pair.Key; (_, string dlcName, _) = pair.Value; writer.WriteLine($" {dlcId}{(pair.Equals(lastBlacklistDlc) ? "" : ",")}"); - installForm?.UpdateUser($"Added blacklist DLC to UplayR2Unlocker.jsonc with appid {dlcId} ({dlcName})", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Added blacklist DLC to UplayR2Unlocker.jsonc with appid {dlcId} ({dlcName})", + LogTextBox.Action, false); } writer.WriteLine(" ],"); } else + { writer.WriteLine(" \"blacklist\": [],"); + } writer.WriteLine("}"); } - internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(() => - { - directory.GetUplayR2Components(out string old_api32, out string old_api64, out string api32, out string api32_o, out string api64, out string api64_o, out string config); - if (File.Exists(api32_o)) + internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) + => await Task.Run(() => { - string api = File.Exists(old_api32) ? old_api32 : api32; - if (File.Exists(api)) + directory.GetUplayR2Components(out string old_api32, out string old_api64, out string api32, + out string api32_o, out string api64, out string api64_o, out string config); + if (File.Exists(api32_o)) { - File.Delete(api); - installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, info: false); + string api = File.Exists(old_api32) ? old_api32 : api32; + if (File.Exists(api)) + { + File.Delete(api); + installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, + false); + } + File.Move(api32_o, api); + installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api)}", + LogTextBox.Action, false); } - File.Move(api32_o, api); - installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api)}", LogTextBox.Action, info: false); - } - if (File.Exists(api64_o)) - { - string api = File.Exists(old_api64) ? old_api64 : api64; - if (File.Exists(api)) + if (File.Exists(api64_o)) { - File.Delete(api); - installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, info: false); + string api = File.Exists(old_api64) ? old_api64 : api64; + if (File.Exists(api)) + { + File.Delete(api); + installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, + false); + } + File.Move(api64_o, api); + installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api)}", + LogTextBox.Action, false); } - File.Move(api64_o, api); - installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api)}", LogTextBox.Action, info: false); - } - if (deleteConfig && File.Exists(config)) - { - File.Delete(config); - installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, info: false); - } - }); + if (deleteConfig && File.Exists(config)) + { + File.Delete(config); + installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false); + } + }); - internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() => + internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, + bool generateConfig = true) => await Task.Run(() => { - directory.GetUplayR2Components(out string old_api32, out string old_api64, out string api32, out string api32_o, out string api64, out string api64_o, out string config); + directory.GetUplayR2Components(out string old_api32, out string old_api64, out string api32, out string api32_o, + out string api64, out string api64_o, out string config); string api = File.Exists(old_api32) ? old_api32 : api32; if (File.Exists(api) && !File.Exists(api32_o)) { File.Move(api, api32_o); - installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}", + LogTextBox.Action, false); } if (File.Exists(api32_o)) { "UplayR2.upc_r2_loader.dll".Write(api); - installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false); } api = File.Exists(old_api64) ? old_api64 : api64; if (File.Exists(api) && !File.Exists(api64_o)) { File.Move(api, api64_o); - installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}", + LogTextBox.Action, false); } if (File.Exists(api64_o)) { "UplayR2.upc_r2_loader64.dll".Write(api); - installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, info: false); + installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false); } if (generateConfig) CheckConfig(directory, selection, installForm); diff --git a/CreamInstaller/Utility/Diagnostics.cs b/CreamInstaller/Utility/Diagnostics.cs index dcc03c4..05123d7 100644 --- a/CreamInstaller/Utility/Diagnostics.cs +++ b/CreamInstaller/Utility/Diagnostics.cs @@ -1,20 +1,21 @@ -using Microsoft.Win32; - -using System; +using System; using System.Diagnostics; using System.IO; +using Microsoft.Win32; namespace CreamInstaller.Utility; internal static class Diagnostics { private static string notepadPlusPlusPath; + internal static string NotepadPlusPlusPath { get { notepadPlusPlusPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Notepad++", "", null) as string; - notepadPlusPlusPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\Notepad++", "", null) as string; + notepadPlusPlusPath + ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\Notepad++", "", null) as string; return notepadPlusPlusPath; } } @@ -34,29 +35,18 @@ internal static class Diagnostics OpenFileInWindowsNotepad(path); } - private static void OpenFileInNotepadPlusPlus(string npp, string path) => Process.Start(new ProcessStartInfo - { - FileName = npp, - Arguments = path - }); + private static void OpenFileInNotepadPlusPlus(string npp, string path) + => Process.Start(new ProcessStartInfo { FileName = npp, Arguments = path }); - private static void OpenFileInWindowsNotepad(string path) => Process.Start(new ProcessStartInfo - { - FileName = "notepad.exe", - Arguments = path - }); + private static void OpenFileInWindowsNotepad(string path) + => Process.Start(new ProcessStartInfo { FileName = "notepad.exe", Arguments = path }); - internal static void OpenDirectoryInFileExplorer(string path) => Process.Start(new ProcessStartInfo - { - FileName = "explorer.exe", - Arguments = path - }); + internal static void OpenDirectoryInFileExplorer(string path) + => Process.Start(new ProcessStartInfo { FileName = "explorer.exe", Arguments = path }); - internal static void OpenUrlInInternetBrowser(string url) => Process.Start(new ProcessStartInfo - { - FileName = url, - UseShellExecute = true - }); + internal static void OpenUrlInInternetBrowser(string url) + => Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true }); - internal static string BeautifyPath(this string path) => path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path)); + internal static string BeautifyPath(this string path) + => path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path)); } diff --git a/CreamInstaller/Utility/ExceptionHandler.cs b/CreamInstaller/Utility/ExceptionHandler.cs index 1d820a4..92d8c9f 100644 --- a/CreamInstaller/Utility/ExceptionHandler.cs +++ b/CreamInstaller/Utility/ExceptionHandler.cs @@ -2,12 +2,14 @@ using System.Drawing; using System.Text; using System.Windows.Forms; +using CreamInstaller.Forms; namespace CreamInstaller.Utility; internal static class ExceptionHandler { - internal static bool HandleException(this Exception e, Form form = null, string caption = null, string acceptButtonText = "Retry", string cancelButtonText = "Cancel") + internal static bool HandleException(this Exception e, Form form = null, string caption = null, + string acceptButtonText = "Retry", string cancelButtonText = "Cancel") { caption ??= Program.Name + " encountered an exception"; StringBuilder output = new(); @@ -21,35 +23,40 @@ internal static class ExceptionHandler string[] stackTrace = e.StackTrace?.Split('\n'); if (stackTrace is not null && stackTrace.Length > 0) { - _ = output.Append(e.GetType() + (e.Message is not null ? (": " + e.Message) : "")); + _ = output.Append(e.GetType() + (": " + e.Message)); for (int i = 0; i < stackTrace.Length; i++) { string line = stackTrace[i]; - int atNum = line.IndexOf("at "); - int inNum = line.IndexOf("in "); - int ciNum = line.LastIndexOf(@"CreamInstaller\"); - int lineNum = line.LastIndexOf(":line "); - if (line is not null && atNum != -1) + int atNum = line.IndexOf("at ", StringComparison.Ordinal); + int inNum = line.IndexOf("in ", StringComparison.Ordinal); + int ciNum = line.LastIndexOf(@"CreamInstaller\", StringComparison.Ordinal); + int lineNum = line.LastIndexOf(":line ", StringComparison.Ordinal); + if (atNum != -1) _ = output.Append("\n " + (inNum != -1 ? line[atNum..(inNum - 1)] : line[atNum..]) - + (inNum != -1 ? ("\n " - + (ciNum != -1 ? ("in " - + (lineNum != -1 ? line[ciNum..lineNum] - + "\n on " + line[(lineNum + 1)..] - : line[ciNum..])) - : line[inNum..])) - : null)); + + (inNum != -1 + ? "\n " + + (ciNum != -1 + ? "in " + + (lineNum != -1 + ? line[ciNum..lineNum] + + "\n on " + line[(lineNum + 1)..] + : line[ciNum..]) + : line[inNum..]) + : null)); } } e = e.InnerException; stackDepth++; } using DialogForm dialogForm = new(form ?? Form.ActiveForm); - return dialogForm.Show(SystemIcons.Error, output.ToString(), acceptButtonText, cancelButtonText, customFormText: caption) == DialogResult.OK; + return dialogForm.Show(SystemIcons.Error, output.ToString(), acceptButtonText, cancelButtonText, caption) + == DialogResult.OK; } internal static void HandleFatalException(this Exception e) { - bool? restart = e?.HandleException(caption: Program.Name + " encountered a fatal exception", acceptButtonText: "Restart"); + bool? restart = e?.HandleException(caption: Program.Name + " encountered a fatal exception", + acceptButtonText: "Restart"); if (restart.HasValue && restart.Value) Application.Restart(); Application.Exit(); @@ -58,14 +65,12 @@ internal static class ExceptionHandler public class CustomMessageException : Exception { - private readonly string message; - public override string Message => message; + public CustomMessageException() => Message = "CustomMessageException"; + + public CustomMessageException(string message) : base(message) => Message = message; + + public CustomMessageException(string message, Exception e) : base(message, e) => Message = message; + public override string Message { get; } public override string ToString() => Message; - - public CustomMessageException() : base() => message = "CustomMessageException"; - - public CustomMessageException(string message) : base(message) => this.message = message; - - public CustomMessageException(string message, Exception e) : base(message, e) => this.message = message; } diff --git a/CreamInstaller/Utility/HttpClientManager.cs b/CreamInstaller/Utility/HttpClientManager.cs index fa568c2..5232845 100644 --- a/CreamInstaller/Utility/HttpClientManager.cs +++ b/CreamInstaller/Utility/HttpClientManager.cs @@ -1,18 +1,18 @@ -using HtmlAgilityPack; - -using System; +using System; using System.Drawing; using System.Net.Http; using System.Threading.Tasks; +using HtmlAgilityPack; namespace CreamInstaller.Utility; internal static class HttpClientManager { internal static HttpClient HttpClient; + internal static void Setup() { - HttpClient = new(); + HttpClient = new HttpClient(); HttpClient.DefaultRequestHeaders.Add("User-Agent", $"CI{Program.Version.Replace(".", "")}"); } @@ -21,7 +21,8 @@ internal static class HttpClientManager try { using HttpRequestMessage request = new(HttpMethod.Get, url); - using HttpResponseMessage response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + using HttpResponseMessage response + = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); _ = response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } @@ -31,16 +32,18 @@ internal static class HttpClientManager } } - internal static HtmlAgilityPack.HtmlDocument ToHtmlDocument(this string html) + internal static HtmlDocument ToHtmlDocument(this string html) { - HtmlAgilityPack.HtmlDocument document = new(); + HtmlDocument document = new(); document.LoadHtml(html); return document; } - internal static async Task GetDocumentNodes(string url, string xpath) => (await EnsureGet(url))?.ToHtmlDocument()?.DocumentNode?.SelectNodes(xpath); + internal static async Task GetDocumentNodes(string url, string xpath) + => (await EnsureGet(url))?.ToHtmlDocument()?.DocumentNode?.SelectNodes(xpath); - internal static HtmlNodeCollection GetDocumentNodes(this HtmlAgilityPack.HtmlDocument htmlDocument, string xpath) => htmlDocument.DocumentNode?.SelectNodes(xpath); + internal static HtmlNodeCollection GetDocumentNodes(this HtmlDocument htmlDocument, string xpath) + => htmlDocument.DocumentNode?.SelectNodes(xpath); internal static async Task GetImageFromUrl(string url) { diff --git a/CreamInstaller/Utility/IconGrabber.cs b/CreamInstaller/Utility/IconGrabber.cs index b24cd8c..7cceb2c 100644 --- a/CreamInstaller/Utility/IconGrabber.cs +++ b/CreamInstaller/Utility/IconGrabber.cs @@ -12,17 +12,21 @@ internal static class IconGrabber return Icon.FromHandle(dialogIconBitmap.GetHicon()); } - internal const string SteamAppImagesPath = "https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/"; + internal const string SteamAppImagesPath + = "https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/"; internal const string GoogleFaviconsApiUrl = "https://www.google.com/s2/favicons"; - internal static string GetDomainFaviconUrl(string domain, int size = 16) => GoogleFaviconsApiUrl + $"?domain={domain}&sz={size}"; + internal static string GetDomainFaviconUrl(string domain, int size = 16) + => GoogleFaviconsApiUrl + $"?domain={domain}&sz={size}"; - internal static Image GetFileIconImage(this string path) => File.Exists(path) ? Icon.ExtractAssociatedIcon(path)?.ToBitmap() : null; + internal static Image GetFileIconImage(this string path) + => File.Exists(path) ? Icon.ExtractAssociatedIcon(path)?.ToBitmap() : null; internal static Image GetNotepadImage() => GetFileIconImage(Diagnostics.GetNotepadPath()); internal static Image GetCommandPromptImage() => GetFileIconImage(Environment.SystemDirectory + @"\cmd.exe"); - internal static Image GetFileExplorerImage() => GetFileIconImage(Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\explorer.exe"); + internal static Image GetFileExplorerImage() + => GetFileIconImage(Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\explorer.exe"); } diff --git a/CreamInstaller/Utility/ProgramData.cs b/CreamInstaller/Utility/ProgramData.cs index 0b2a159..ddecc48 100644 --- a/CreamInstaller/Utility/ProgramData.cs +++ b/CreamInstaller/Utility/ProgramData.cs @@ -1,18 +1,21 @@ -using Newtonsoft.Json; - -using System; +using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using Newtonsoft.Json; namespace CreamInstaller.Utility; internal static class ProgramData { - internal static readonly string DirectoryPathOld = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller"; - internal static readonly string DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\CreamInstaller"; + internal static readonly string DirectoryPathOld + = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller"; + + internal static readonly string DirectoryPath + = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\CreamInstaller"; internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo"; internal static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt"; @@ -34,7 +37,9 @@ internal static class ProgramData Directory.Move(DirectoryPathOld, DirectoryPath); } if (!Directory.Exists(DirectoryPath)) _ = Directory.CreateDirectory(DirectoryPath); - if (!File.Exists(AppInfoVersionPath) || !Version.TryParse(File.ReadAllText(AppInfoVersionPath, Encoding.UTF8), out Version version) || version < MinimumAppInfoVersion) + if (!File.Exists(AppInfoVersionPath) + || !Version.TryParse(File.ReadAllText(AppInfoVersionPath, Encoding.UTF8), out Version version) + || version < MinimumAppInfoVersion) { if (Directory.Exists(AppInfoPath)) Directory.Delete(AppInfoPath, true); _ = Directory.CreateDirectory(AppInfoPath); @@ -55,23 +60,23 @@ internal static class ProgramData SetCooldown(identifier, now); return cooldownOver; } + private static DateTime? GetCooldown(string identifier) { if (Directory.Exists(CooldownPath)) { string cooldownFile = CooldownPath + @$"\{identifier}.txt"; if (File.Exists(cooldownFile)) - { try { if (DateTime.TryParse(File.ReadAllText(cooldownFile), out DateTime cooldown)) return cooldown; } catch { } - } } return null; } + private static void SetCooldown(string identifier, DateTime time) { if (!Directory.Exists(CooldownPath)) @@ -79,7 +84,7 @@ internal static class ProgramData string cooldownFile = CooldownPath + @$"\{identifier}.txt"; try { - File.WriteAllText(cooldownFile, time.ToString()); + File.WriteAllText(cooldownFile, time.ToString(CultureInfo.InvariantCulture)); } catch { } } @@ -90,13 +95,15 @@ internal static class ProgramData try { return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath), - typeof(List<(Platform platform, string id)>)) as List<(Platform platform, string id)>; + typeof(List<(Platform platform, string id)>)) as + List<(Platform platform, string id)>; } catch { - return new(); + return new List<(Platform platform, string id)>(); } } + internal static void WriteProgramChoices(List<(Platform platform, string id)> choices) { try @@ -115,13 +122,15 @@ internal static class ProgramData try { return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath), - typeof(List<(Platform platform, string gameId, string dlcId)>)) as List<(Platform platform, string gameId, string dlcId)>; + typeof(List<(Platform platform, string gameId, string dlcId)>)) as + List<(Platform platform, string gameId, string dlcId)>; } catch { - return new(); + return new List<(Platform platform, string gameId, string dlcId)>(); } } + internal static void WriteDlcChoices(List<(Platform platform, string gameId, string dlcId)> choices) { try @@ -140,15 +149,18 @@ internal static class ProgramData try { return JsonConvert.DeserializeObject(File.ReadAllText(KoaloaderProxyChoicesPath), - typeof(List<(Platform platform, string id, string proxy, bool enabled)>)) as List<(Platform platform, string id, string proxy, bool enabled)>; + typeof( + List<(Platform platform, string id, string proxy, bool enabled)>)) + as List<(Platform platform, string id, string proxy, bool enabled)>; } catch { - return new(); + return new List<(Platform platform, string id, string proxy, bool enabled)>(); } } - internal static void WriteKoaloaderProxyChoices(List<(Platform platform, string id, string proxy, bool enabled)> choices) + internal static void WriteKoaloaderProxyChoices( + List<(Platform platform, string id, string proxy, bool enabled)> choices) { try {