cleanup
This commit is contained in:
parent
0e48a18eee
commit
05e2ea5519
32 changed files with 1391 additions and 1735 deletions
|
@ -21,31 +21,25 @@ internal class ContextMenuItem : ToolStripMenuItem
|
|||
OnClickEvent = onClick;
|
||||
}
|
||||
|
||||
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null)
|
||||
: this(text, onClick) => _ = TryImageIdentifier(this, imageIdentifier);
|
||||
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null) : this(text, onClick)
|
||||
=> _ = TryImageIdentifier(this, imageIdentifier);
|
||||
|
||||
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, 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));
|
||||
|
||||
private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier) => await Task.Run(
|
||||
async () =>
|
||||
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
|
||||
{
|
||||
switch (imageIdentifier)
|
||||
|
@ -68,28 +62,22 @@ internal class ContextMenuItem : ToolStripMenuItem
|
|||
image = IconGrabber.GetFileExplorerImage();
|
||||
break;
|
||||
case "SteamDB":
|
||||
image = await HttpClientManager.GetImageFromUrl(
|
||||
IconGrabber.GetDomainFaviconUrl("steamdb.info"));
|
||||
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("steamdb.info"));
|
||||
break;
|
||||
case "Steam Store":
|
||||
image = await HttpClientManager.GetImageFromUrl(
|
||||
IconGrabber.GetDomainFaviconUrl("store.steampowered.com"));
|
||||
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("store.steampowered.com"));
|
||||
break;
|
||||
case "Steam Community":
|
||||
image = await HttpClientManager.GetImageFromUrl(
|
||||
IconGrabber.GetDomainFaviconUrl("steamcommunity.com"));
|
||||
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("steamcommunity.com"));
|
||||
break;
|
||||
case "ScreamDB":
|
||||
image = await HttpClientManager.GetImageFromUrl(
|
||||
IconGrabber.GetDomainFaviconUrl("scream-db.web.app"));
|
||||
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("scream-db.web.app"));
|
||||
break;
|
||||
case "Epic Games":
|
||||
image = await HttpClientManager.GetImageFromUrl(
|
||||
IconGrabber.GetDomainFaviconUrl("epicgames.com"));
|
||||
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("epicgames.com"));
|
||||
break;
|
||||
case "Ubisoft Store":
|
||||
image = await HttpClientManager.GetImageFromUrl(
|
||||
IconGrabber.GetDomainFaviconUrl("store.ubi.com"));
|
||||
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("store.ubi.com"));
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@ -102,16 +90,13 @@ internal class ContextMenuItem : ToolStripMenuItem
|
|||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
||||
|
@ -121,16 +106,15 @@ internal class ContextMenuItem : ToolStripMenuItem
|
|||
item.Image = image;
|
||||
}
|
||||
else if (onFail is not null)
|
||||
{
|
||||
onFail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
protected override void OnClick(EventArgs e)
|
||||
{
|
||||
base.OnClick(e);
|
||||
if (OnClickEvent is null) return;
|
||||
if (OnClickEvent is null)
|
||||
return;
|
||||
OnClickEvent.Invoke(this, e);
|
||||
}
|
||||
}
|
|
@ -60,17 +60,13 @@ internal class CustomForm : Form
|
|||
_ = 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"
|
||||
+ "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"
|
||||
+ "\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"
|
||||
+ "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"
|
||||
|
@ -80,14 +76,11 @@ internal class CustomForm : Form
|
|||
+ " 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"
|
||||
+ " 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"
|
||||
+ " 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"
|
||||
+ "\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}).");
|
||||
}
|
||||
|
@ -96,8 +89,7 @@ internal class CustomForm : Form
|
|||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||
internal static extern void SetWindowPos(nint hWnd, nint hWndInsertAfter, int x, int y, int cx, int cy,
|
||||
uint uFlags);
|
||||
internal static extern void SetWindowPos(nint hWnd, nint hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
|
||||
|
||||
internal void BringToFrontWithoutActivation()
|
||||
{
|
||||
|
@ -113,12 +105,13 @@ internal class CustomForm : Form
|
|||
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 Point(X, Y);
|
||||
Location = new(X, Y);
|
||||
}
|
||||
|
||||
private void OnKeyPress(object s, KeyPressEventArgs e)
|
||||
{
|
||||
if (e.KeyChar != 'S') return; // Shift + S
|
||||
if (e.KeyChar != 'S')
|
||||
return; // Shift + S
|
||||
UpdateBounds();
|
||||
Rectangle bounds = Bounds;
|
||||
using Bitmap bitmap = new(Size.Width - 14, Size.Height - 7);
|
||||
|
@ -127,8 +120,7 @@ internal class CustomForm : Form
|
|||
using EncoderParameters encoding = new(1);
|
||||
using EncoderParameter encoderParam = new(Encoder.Quality, 100L);
|
||||
encoding.Param[0] = encoderParam;
|
||||
graphics.CopyFromScreen(new Point(bounds.Left + 7, bounds.Top), Point.Empty,
|
||||
new Size(Size.Width - 14, Size.Height - 7));
|
||||
graphics.CopyFromScreen(new(bounds.Left + 7, bounds.Top), Point.Empty, new(Size.Width - 14, Size.Height - 7));
|
||||
Clipboard.SetImage(bitmap);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
|
|
@ -65,8 +65,7 @@ internal class CustomTreeView : TreeView
|
|||
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);
|
||||
|
@ -88,8 +87,7 @@ internal class CustomTreeView : TreeView
|
|||
text = platform.ToString();
|
||||
size = TextRenderer.MeasureText(graphics, text, font);
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||
selectionBounds
|
||||
= new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
graphics.FillRectangle(brush, bounds);
|
||||
point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1);
|
||||
TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default);
|
||||
|
@ -104,8 +102,7 @@ internal class CustomTreeView : TreeView
|
|||
size = TextRenderer.MeasureText(graphics, text, font);
|
||||
int left = -4;
|
||||
bounds = bounds with { X = bounds.X + bounds.Width + left, Width = size.Width };
|
||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
||||
selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
||||
graphics.FillRectangle(brush, bounds);
|
||||
point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1);
|
||||
TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default);
|
||||
|
@ -130,8 +127,7 @@ internal class CustomTreeView : TreeView
|
|||
: CheckBoxState.UncheckedDisabled;
|
||||
size = CheckBoxRenderer.GetGlyphSize(graphics, checkBoxState);
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
||||
selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
Rectangle checkBoxBounds = bounds;
|
||||
graphics.FillRectangle(backBrush, bounds);
|
||||
point = new Point(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1);
|
||||
|
@ -140,41 +136,31 @@ internal class CustomTreeView : TreeView
|
|||
size = TextRenderer.MeasureText(graphics, text, font);
|
||||
int left = 1;
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width + left };
|
||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
||||
selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
checkBoxBounds = new Rectangle(checkBoxBounds.Location,
|
||||
checkBoxBounds.Size + bounds.Size with { Height = 0 });
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
checkBoxBounds = new Rectangle(checkBoxBounds.Location, checkBoxBounds.Size + bounds.Size with { Height = 0 });
|
||||
graphics.FillRectangle(backBrush, bounds);
|
||||
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"),
|
||||
TextRenderer.DrawText(graphics, text, font, point, 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(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 Rectangle(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width,
|
||||
bounds.Height - padding);
|
||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
||||
selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding);
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
Rectangle comboBoxBounds = bounds;
|
||||
graphics.FillRectangle(backBrush, bounds);
|
||||
ComboBoxRenderer.DrawTextBox(graphics, bounds, text, comboBoxFont, comboBoxState);
|
||||
size = new Size(14, 0);
|
||||
left = -1;
|
||||
bounds = bounds with { X = bounds.X + bounds.Width + left, Width = size.Width };
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
@ -215,11 +201,9 @@ internal class CustomTreeView : TreeView
|
|||
}
|
||||
else if (pair.Value.Contains(clickPoint))
|
||||
{
|
||||
List<string> proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader"))
|
||||
.Select(p =>
|
||||
List<string> proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")).Select(p =>
|
||||
{
|
||||
p.GetProxyInfoFromIdentifier(
|
||||
out string proxyName, out _);
|
||||
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
|
||||
return proxyName;
|
||||
}).Distinct().ToList();
|
||||
comboBoxDropDown ??= new ToolStripDropDown();
|
||||
|
@ -240,8 +224,7 @@ 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 });
|
||||
}
|
||||
|
|
|
@ -14,16 +14,16 @@ internal static class PlatformIdComparer
|
|||
private static NodeNameComparer nodeNameComparer;
|
||||
|
||||
private static NodeTextComparer nodeTextComparer;
|
||||
internal static StringComparer String => stringComparer ??= new StringComparer();
|
||||
internal static NodeComparer Node => nodeComparer ??= new NodeComparer();
|
||||
internal static NodeNameComparer NodeName => nodeNameComparer ??= new NodeNameComparer();
|
||||
internal static NodeTextComparer NodeText => nodeTextComparer ??= new NodeTextComparer();
|
||||
internal static StringComparer String => stringComparer ??= new();
|
||||
internal static NodeComparer Node => nodeComparer ??= new();
|
||||
internal static NodeNameComparer NodeName => nodeNameComparer ??= new();
|
||||
internal static NodeTextComparer NodeText => nodeTextComparer ??= new();
|
||||
}
|
||||
|
||||
internal class StringComparer : IComparer<string>
|
||||
{
|
||||
public int Compare(string a, string b) =>
|
||||
!int.TryParse(a, out _) && !int.TryParse(b, out _)
|
||||
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
|
||||
|
@ -38,8 +38,8 @@ internal class StringComparer : IComparer<string>
|
|||
|
||||
internal class NodeComparer : IComparer<TreeNode>
|
||||
{
|
||||
public int Compare(TreeNode a, TreeNode b) =>
|
||||
a.Tag is not Platform A
|
||||
public int Compare(TreeNode a, TreeNode b)
|
||||
=> a.Tag is not Platform A
|
||||
? 1
|
||||
: b.Tag is not Platform B
|
||||
? -1
|
||||
|
@ -52,8 +52,8 @@ internal class NodeComparer : IComparer<TreeNode>
|
|||
|
||||
internal class NodeNameComparer : IComparer
|
||||
{
|
||||
public int Compare(object a, object b) =>
|
||||
a is not TreeNode A
|
||||
public int Compare(object a, object b)
|
||||
=> a is not TreeNode A
|
||||
? 1
|
||||
: b is not TreeNode B
|
||||
? -1
|
||||
|
@ -64,8 +64,8 @@ internal class NodeNameComparer : IComparer
|
|||
|
||||
internal class NodeTextComparer : IComparer
|
||||
{
|
||||
public int Compare(object a, object b) =>
|
||||
a is not TreeNode A
|
||||
public int Compare(object a, object b)
|
||||
=> a is not TreeNode A
|
||||
? 1
|
||||
: b is not TreeNode B
|
||||
? -1
|
||||
|
|
|
@ -24,7 +24,7 @@ internal partial class DebugForm : CustomForm
|
|||
{
|
||||
if (current is not null && (current.Disposing || current.IsDisposed))
|
||||
current = null;
|
||||
return current ??= new DebugForm();
|
||||
return current ??= new();
|
||||
}
|
||||
set => current = value;
|
||||
}
|
||||
|
@ -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 Point(attachedForm.Right, attachedForm.Top);
|
||||
Location = new(attachedForm.Right, attachedForm.Top);
|
||||
BringToFrontWithoutActivation();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ 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();
|
||||
|
@ -32,7 +32,7 @@ internal partial class DialogForm : CustomForm
|
|||
if (string.IsNullOrWhiteSpace(link))
|
||||
link = text;
|
||||
descriptionText = descriptionText.Remove(i, linkRight + 1 - i).Insert(i, text);
|
||||
links.Add(new LinkLabel.Link(i, text.Length, link));
|
||||
links.Add(new(i, text.Length, link));
|
||||
}
|
||||
}
|
||||
descriptionLabel.Text = descriptionText;
|
||||
|
@ -43,13 +43,9 @@ internal partial class DialogForm : CustomForm
|
|||
cancelButton.Visible = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
cancelButton.Text = cancelButtonText;
|
||||
}
|
||||
if (customFormText is not null)
|
||||
{
|
||||
Text = customFormText;
|
||||
}
|
||||
else
|
||||
{
|
||||
OnResize(null, null);
|
||||
|
@ -61,16 +57,13 @@ 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();
|
||||
}
|
||||
|
||||
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
|
||||
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.ApplicationName;
|
||||
}
|
||||
|
|
|
@ -38,18 +38,21 @@ internal partial class InstallForm : CustomForm
|
|||
userProgressBar.Invoke(() =>
|
||||
{
|
||||
int value = (int)((float)CompleteOperationsCount / OperationsCount * 100) + progress / OperationsCount;
|
||||
if (value < userProgressBar.Value) return;
|
||||
if (value < userProgressBar.Value)
|
||||
return;
|
||||
userProgressBar.Value = value;
|
||||
});
|
||||
}
|
||||
|
||||
internal void UpdateUser(string text, Color color, bool info = true, bool log = true)
|
||||
{
|
||||
if (info) _ = userInfoLabel.Invoke(() => userInfoLabel.Text = text);
|
||||
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);
|
||||
if (logTextBox.Text.Length > 0)
|
||||
logTextBox.AppendText(Environment.NewLine, color);
|
||||
logTextBox.AppendText(text, color);
|
||||
logTextBox.Invalidate();
|
||||
});
|
||||
|
@ -63,12 +66,11 @@ internal partial class InstallForm : CustomForm
|
|||
UpdateUser("Repairing Paradox Launcher . . . ", LogTextBox.Operation);
|
||||
_ = await Repair(this, selection);
|
||||
}
|
||||
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")}" +
|
||||
$" {(Uninstalling ? "from" : "for")} " + selection.Name
|
||||
UpdateUser(
|
||||
$"{(Uninstalling ? "Uninstalling" : "Installing")}" + $" {(Uninstalling ? "from" : "for")} " + selection.Name
|
||||
+ $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation);
|
||||
IEnumerable<string> invalidDirectories = (await selection.RootDirectory.GetExecutables())
|
||||
?.Where(d => !selection.ExecutableDirectories.Any(
|
||||
s => s.directory == 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);
|
||||
|
@ -76,16 +78,13 @@ internal partial class InstallForm : CustomForm
|
|||
if (invalidDirectories is not null)
|
||||
foreach (string directory in invalidDirectories)
|
||||
{
|
||||
if (Program.Canceled) throw new CustomMessageException("The operation was canceled.");
|
||||
if (Program.Canceled)
|
||||
throw new CustomMessageException("The operation was canceled.");
|
||||
directory.GetKoaloaderComponents(out List<string> 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);
|
||||
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||
}
|
||||
Thread.Sleep(1);
|
||||
|
@ -93,15 +92,13 @@ internal partial class InstallForm : CustomForm
|
|||
if (Uninstalling || !selection.Koaloader)
|
||||
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
|
||||
{
|
||||
if (Program.Canceled) throw new CustomMessageException("The operation was canceled.");
|
||||
if (Program.Canceled)
|
||||
throw new CustomMessageException("The operation was canceled.");
|
||||
directory.GetKoaloaderComponents(out List<string> 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);
|
||||
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||
}
|
||||
Thread.Sleep(1);
|
||||
|
@ -110,17 +107,18 @@ internal partial class InstallForm : CustomForm
|
|||
int count = selection.DllDirectories.Count, cur = 0;
|
||||
foreach (string directory in selection.DllDirectories)
|
||||
{
|
||||
if (Program.Canceled) throw new CustomMessageException("The operation was canceled.");
|
||||
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);
|
||||
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
|
||||
UpdateUser(
|
||||
$"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
||||
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||
if (uninstallProxy)
|
||||
await SmokeAPI.Uninstall(directory, this);
|
||||
|
@ -130,14 +128,11 @@ 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
|
||||
UpdateUser(
|
||||
$"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
||||
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||
if (uninstallProxy)
|
||||
await ScreamAPI.Uninstall(directory, this);
|
||||
|
@ -147,28 +142,24 @@ 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
|
||||
UpdateUser(
|
||||
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + $" {(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);
|
||||
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
|
||||
UpdateUser(
|
||||
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
||||
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||
if (uninstallProxy)
|
||||
await UplayR2.Uninstall(directory, this);
|
||||
|
@ -182,9 +173,9 @@ internal partial class InstallForm : CustomForm
|
|||
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);
|
||||
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, selection.RootDirectory, this);
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
@ -236,13 +227,12 @@ 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;
|
||||
|
@ -262,7 +252,8 @@ internal partial class InstallForm : CustomForm
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e.HandleException(this)) goto retry;
|
||||
if (e.HandleException(this))
|
||||
goto retry;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,24 +58,18 @@ internal partial class MainForm : CustomForm
|
|||
updateButton.Click -= OnUpdateCancel;
|
||||
progressLabel.Text = "Checking for updates . . .";
|
||||
changelogTreeView.Visible = false;
|
||||
changelogTreeView.Location = progressLabel.Location with
|
||||
{
|
||||
Y = progressLabel.Location.Y + progressLabel.Size.Height + 13
|
||||
};
|
||||
changelogTreeView.Location = progressLabel.Location with { Y = 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 UpdateManager(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath),
|
||||
resolver, extractor);
|
||||
updateManager = new(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath), resolver, extractor);
|
||||
if (latestVersion is null)
|
||||
{
|
||||
CheckForUpdatesResult checkForUpdatesResult = null;
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource = new();
|
||||
try
|
||||
{
|
||||
checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token);
|
||||
|
@ -93,8 +87,7 @@ 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 { }
|
||||
|
@ -120,8 +113,7 @@ internal partial class MainForm : CustomForm
|
|||
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
|
||||
|
@ -162,8 +154,7 @@ 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!",
|
||||
"WARNING: " + Program.ApplicationExecutable + " was renamed!" + "\n\nThis will cause undesirable behavior when updating the program!",
|
||||
"Ignore", "Abort") == DialogResult.Cancel)
|
||||
{
|
||||
Application.Exit();
|
||||
|
@ -174,7 +165,8 @@ internal partial class MainForm : CustomForm
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e.HandleException(this)) goto retry;
|
||||
if (e.HandleException(this))
|
||||
goto retry;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
@ -188,8 +180,7 @@ internal partial class MainForm : CustomForm
|
|||
updateButton.Text = "Cancel";
|
||||
updateButton.Click -= OnUpdate;
|
||||
updateButton.Click += OnUpdateCancel;
|
||||
changelogTreeView.Location
|
||||
= progressBar.Location with { Y = progressBar.Location.Y + progressBar.Size.Height + 6 };
|
||||
changelogTreeView.Location = progressBar.Location with { Y = progressBar.Location.Y + progressBar.Size.Height + 6 };
|
||||
Refresh();
|
||||
Progress<double> progress = new();
|
||||
progress.ProgressChanged += delegate(object sender, double _progress)
|
||||
|
@ -198,7 +189,7 @@ internal partial class MainForm : CustomForm
|
|||
progressBar.Value = (int)_progress;
|
||||
};
|
||||
progressLabel.Text = "Updating . . . ";
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource = new();
|
||||
try
|
||||
{
|
||||
await updateManager.PrepareUpdateAsync(latestVersion, progress, cancellationTokenSource.Token);
|
||||
|
@ -207,8 +198,7 @@ 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 { }
|
||||
|
|
|
@ -12,10 +12,11 @@ internal partial class SelectDialogForm : CustomForm
|
|||
private readonly List<(Platform platform, string id, string name)> selected = new();
|
||||
internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
||||
|
||||
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;
|
||||
if (!choices.Any())
|
||||
return null;
|
||||
groupBox.Text = groupBoxText;
|
||||
allCheckBox.Enabled = false;
|
||||
acceptButton.Enabled = false;
|
||||
|
@ -26,7 +27,8 @@ internal partial class SelectDialogForm : CustomForm
|
|||
OnTreeNodeChecked(node);
|
||||
_ = selectionTreeView.Nodes.Add(node);
|
||||
}
|
||||
if (!selected.Any()) OnLoad(null, null);
|
||||
if (!selected.Any())
|
||||
OnLoad(null, null);
|
||||
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
|
||||
allCheckBox.Checked = selectionTreeView.Nodes.Cast<TreeNode>().All(n => n.Checked);
|
||||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||
|
@ -59,13 +61,11 @@ internal partial class SelectDialogForm : CustomForm
|
|||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||
}
|
||||
|
||||
private void OnResize(object s, EventArgs e) =>
|
||||
Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100
|
||||
? Program.ApplicationNameShort
|
||||
: Program.ApplicationName;
|
||||
private void OnResize(object s, EventArgs e)
|
||||
=> Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100 ? Program.ApplicationNameShort : Program.ApplicationName;
|
||||
|
||||
private void OnSortCheckBoxChanged(object sender, EventArgs e) => selectionTreeView.TreeViewNodeSorter
|
||||
= sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
||||
private void OnSortCheckBoxChanged(object sender, EventArgs e)
|
||||
=> selectionTreeView.TreeViewNodeSorter = sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
||||
|
||||
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
||||
{
|
||||
|
@ -85,7 +85,8 @@ internal partial class SelectDialogForm : CustomForm
|
|||
private void OnLoad(object sender, EventArgs e)
|
||||
{
|
||||
List<(Platform platform, string id)> choices = ProgramData.ReadProgramChoices();
|
||||
if (choices is null) return;
|
||||
if (choices is null)
|
||||
return;
|
||||
foreach (TreeNode node in selectionTreeView.Nodes)
|
||||
{
|
||||
node.Checked = choices.Any(n => n.platform == (Platform)node.Tag && n.id == node.Name);
|
||||
|
|
|
@ -38,23 +38,23 @@ internal partial class SelectForm : CustomForm
|
|||
Text = Program.ApplicationName;
|
||||
}
|
||||
|
||||
public override ContextMenuStrip ContextMenuStrip => base.ContextMenuStrip ??= new ContextMenuStrip();
|
||||
public override ContextMenuStrip ContextMenuStrip => base.ContextMenuStrip ??= new();
|
||||
|
||||
internal List<TreeNode> TreeNodes => GatherTreeNodes(selectionTreeView.Nodes);
|
||||
|
||||
private static void UpdateRemaining(Label label, SynchronizedCollection<string> list, string descriptor) =>
|
||||
label.Text = list.Any()
|
||||
? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&")
|
||||
: "";
|
||||
private static void UpdateRemaining(Label label, SynchronizedCollection<string> list, string descriptor)
|
||||
=> label.Text = list.Any() ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") : "";
|
||||
|
||||
private void UpdateRemainingGames() => UpdateRemaining(progressLabelGames, RemainingGames, "games");
|
||||
|
||||
private void AddToRemainingGames(string gameName)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
progressLabelGames.Invoke(delegate
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
if (!RemainingGames.Contains(gameName))
|
||||
RemainingGames.Add(gameName);
|
||||
UpdateRemainingGames();
|
||||
|
@ -63,10 +63,12 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private void RemoveFromRemainingGames(string gameName)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
progressLabelGames.Invoke(delegate
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
RemainingGames.Remove(gameName);
|
||||
UpdateRemainingGames();
|
||||
});
|
||||
|
@ -76,10 +78,12 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private void AddToRemainingDLCs(string dlcId)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
progressLabelDLCs.Invoke(delegate
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
if (!RemainingDLCs.Contains(dlcId))
|
||||
RemainingDLCs.Add(dlcId);
|
||||
UpdateRemainingDLCs();
|
||||
|
@ -88,10 +92,12 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private void RemoveFromRemainingDLCs(string dlcId)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
progressLabelDLCs.Invoke(delegate
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
RemainingDLCs.Remove(dlcId);
|
||||
UpdateRemainingDLCs();
|
||||
});
|
||||
|
@ -99,7 +105,8 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private async Task GetApplicablePrograms(IProgress<int> progress)
|
||||
{
|
||||
if (ProgramsToScan is null || !ProgramsToScan.Any()) return;
|
||||
if (ProgramsToScan is null || !ProgramsToScan.Any())
|
||||
return;
|
||||
int TotalGameCount = 0;
|
||||
int CompleteGameCount = 0;
|
||||
void AddToRemainingGames(string gameName)
|
||||
|
@ -113,30 +120,30 @@ internal partial class SelectForm : CustomForm
|
|||
this.RemoveFromRemainingGames(gameName);
|
||||
progress.Report(Interlocked.Increment(ref CompleteGameCount));
|
||||
}
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
List<TreeNode> treeNodes = TreeNodes;
|
||||
RemainingGames.Clear(); // for display purposes only, otherwise ignorable
|
||||
RemainingDLCs.Clear(); // for display purposes only, otherwise ignorable
|
||||
List<Task> appTasks = new();
|
||||
if (ProgramsToScan.Any(c => c.platform is Platform.Paradox))
|
||||
{
|
||||
List<string> dllDirectories
|
||||
= await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox);
|
||||
List<string> dllDirectories = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox);
|
||||
if (dllDirectories is not null)
|
||||
{
|
||||
ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL");
|
||||
selection ??= new ProgramSelection();
|
||||
if (allCheckBox.Checked) selection.Enabled = true;
|
||||
if (koaloaderAllCheckBox.Checked) selection.Koaloader = true;
|
||||
selection ??= new();
|
||||
if (allCheckBox.Checked)
|
||||
selection.Enabled = true;
|
||||
if (koaloaderAllCheckBox.Checked)
|
||||
selection.Koaloader = true;
|
||||
selection.Id = "PL";
|
||||
selection.Name = "Paradox Launcher";
|
||||
selection.RootDirectory = ParadoxLauncher.InstallPath;
|
||||
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();
|
||||
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;
|
||||
|
@ -148,14 +155,13 @@ 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.Canceled)
|
||||
return;
|
||||
if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Steam && c.id == appId))
|
||||
{
|
||||
Interlocked.Decrement(ref steamGamesToCheck);
|
||||
continue;
|
||||
|
@ -163,9 +169,9 @@ internal partial class SelectForm : CustomForm
|
|||
AddToRemainingGames(name);
|
||||
Task task = Task.Run(async () =>
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
List<string> dllDirectories
|
||||
= await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Steam);
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
List<string> dllDirectories = await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Steam);
|
||||
if (dllDirectories is null)
|
||||
{
|
||||
Interlocked.Decrement(ref steamGamesToCheck);
|
||||
|
@ -180,25 +186,30 @@ internal partial class SelectForm : CustomForm
|
|||
RemoveFromRemainingGames(name);
|
||||
return;
|
||||
}
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
ConcurrentDictionary<string, (DlcType type, string name, string icon)> dlc = new();
|
||||
List<Task> dlcTasks = new();
|
||||
List<string> dlcIds = new();
|
||||
if (appData is not null) dlcIds.AddRange(await SteamStore.ParseDlcAppIds(appData));
|
||||
if (appInfo is not null) dlcIds.AddRange(await SteamCMD.ParseDlcAppIds(appInfo));
|
||||
if (appData is not null)
|
||||
dlcIds.AddRange(await SteamStore.ParseDlcAppIds(appData));
|
||||
if (appInfo is not null)
|
||||
dlcIds.AddRange(await SteamCMD.ParseDlcAppIds(appInfo));
|
||||
if (dlcIds.Count > 0)
|
||||
{
|
||||
foreach (string dlcAppId in dlcIds)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
AddToRemainingDLCs(dlcAppId);
|
||||
Task task = Task.Run(async () =>
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
do // give games steam store api limit priority
|
||||
Thread.Sleep(200);
|
||||
while (!Program.Canceled && steamGamesToCheck > 0);
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
string dlcName = null;
|
||||
string dlcIcon = null;
|
||||
bool onSteamStore = false;
|
||||
|
@ -215,18 +226,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;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
if (string.IsNullOrWhiteSpace(dlcName))
|
||||
dlcName = "Unknown";
|
||||
dlc[dlcAppId] = (onSteamStore ? DlcType.Steam : DlcType.SteamHidden, dlcName, dlcIcon);
|
||||
|
@ -234,45 +242,43 @@ internal partial class SelectForm : CustomForm
|
|||
});
|
||||
dlcTasks.Add(task);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveFromRemainingGames(name);
|
||||
return;
|
||||
}
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
foreach (Task task in dlcTasks)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
await task;
|
||||
}
|
||||
steamGamesToCheck = 0;
|
||||
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;
|
||||
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.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.Publisher = appData?.publishers[0] ?? appInfo?.Value?.GetChild("extended")?.GetChild("publisher")?.ToString();
|
||||
selection.WebsiteUrl = appData?.website;
|
||||
if (Program.Canceled) return;
|
||||
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();
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
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;
|
||||
|
@ -281,13 +287,14 @@ internal partial class SelectForm : CustomForm
|
|||
_ = selectionTreeView.Nodes.Add(programNode);
|
||||
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in dlc)
|
||||
{
|
||||
if (Program.Canceled || programNode is null) return;
|
||||
if (Program.Canceled || programNode is null)
|
||||
return;
|
||||
string appId = pair.Key;
|
||||
(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();
|
||||
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.Tag = selection.Platform;
|
||||
dlcNode.Name = appId;
|
||||
dlcNode.Text = dlcApp.name;
|
||||
|
@ -296,7 +303,8 @@ internal partial class SelectForm : CustomForm
|
|||
_ = programNode.Nodes.Add(dlcNode);
|
||||
}
|
||||
});
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
RemoveFromRemainingGames(name);
|
||||
});
|
||||
appTasks.Add(task);
|
||||
|
@ -310,34 +318,37 @@ internal partial class SelectForm : CustomForm
|
|||
string @namespace = manifest.CatalogNamespace;
|
||||
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.Canceled)
|
||||
return;
|
||||
if (Program.IsGameBlocked(name, directory) || !ProgramsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace))
|
||||
continue;
|
||||
AddToRemainingGames(name);
|
||||
Task task = Task.Run(async () =>
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
List<string> dllDirectories = await directory.GetDllDirectoriesFromGameDirectory(Platform.Epic);
|
||||
if (dllDirectories is null)
|
||||
{
|
||||
RemoveFromRemainingGames(name);
|
||||
return;
|
||||
}
|
||||
if (Program.Canceled) return;
|
||||
ConcurrentDictionary<string, (string name, string product, string icon, string developer)>
|
||||
entitlements = new();
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
ConcurrentDictionary<string, (string name, string product, string icon, string developer)> entitlements = new();
|
||||
List<Task> dlcTasks = new();
|
||||
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;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
AddToRemainingDLCs(id);
|
||||
Task task = Task.Run(() =>
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
entitlements[id] = (name, product, icon, developer);
|
||||
RemoveFromRemainingDLCs(id);
|
||||
});
|
||||
|
@ -348,37 +359,38 @@ internal partial class SelectForm : CustomForm
|
|||
RemoveFromRemainingGames(name);
|
||||
return;
|
||||
}
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
foreach (Task task in dlcTasks)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
await task;
|
||||
}
|
||||
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;
|
||||
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<string, (string name, string product, string icon, string developer)> pair in
|
||||
entitlements.Where(p => p.Value.name == selection.Name))
|
||||
foreach (KeyValuePair<string, (string name, string product, string icon, string developer)> pair in entitlements.Where(p
|
||||
=> p.Value.name == selection.Name))
|
||||
{
|
||||
selection.ProductUrl = "https://www.epicgames.com/store/product/" + pair.Value.product;
|
||||
selection.IconUrl = pair.Value.icon;
|
||||
selection.Publisher = pair.Value.developer;
|
||||
}
|
||||
if (Program.Canceled) return;
|
||||
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();
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
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;
|
||||
|
@ -400,17 +412,16 @@ 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<string, (string name, string product, string icon, string developer)>
|
||||
pair in entitlements)
|
||||
foreach (KeyValuePair<string, (string name, string product, string icon, string developer)> 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();
|
||||
if (allCheckBox.Checked)
|
||||
selection.SelectedDlc[dlcId] = dlcApp;
|
||||
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;
|
||||
|
@ -419,7 +430,8 @@ internal partial class SelectForm : CustomForm
|
|||
_ = programNode.Nodes.Add(dlcNode); //entitlementsNode.Nodes.Add(dlcNode);
|
||||
}
|
||||
});
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
RemoveFromRemainingGames(name);
|
||||
});
|
||||
appTasks.Add(task);
|
||||
|
@ -430,39 +442,39 @@ internal partial class SelectForm : CustomForm
|
|||
List<(string gameId, string name, string gameDirectory)> ubisoftGames = await UbisoftLibrary.GetGames();
|
||||
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.Canceled)
|
||||
return;
|
||||
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<string> dllDirectories
|
||||
= await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Ubisoft);
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
List<string> 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 ProgramSelection();
|
||||
selection.Enabled = allCheckBox.Checked || selection.SelectedDlc.Any()
|
||||
|| selection.ExtraSelectedDlc.Any();
|
||||
if (koaloaderAllCheckBox.Checked) selection.Koaloader = true;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
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();
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
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;
|
||||
|
@ -470,7 +482,8 @@ internal partial class SelectForm : CustomForm
|
|||
if (programNode.TreeView is null)
|
||||
_ = selectionTreeView.Nodes.Add(programNode);
|
||||
});
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
RemoveFromRemainingGames(name);
|
||||
});
|
||||
appTasks.Add(task);
|
||||
|
@ -478,7 +491,8 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
foreach (Task task in appTasks)
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
await task;
|
||||
}
|
||||
steamGamesToCheck = 0;
|
||||
|
@ -512,30 +526,24 @@ internal partial class SelectForm : CustomForm
|
|||
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")));
|
||||
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)))
|
||||
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)));
|
||||
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)))
|
||||
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)))
|
||||
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)));
|
||||
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)
|
||||
|
@ -544,15 +552,11 @@ 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;
|
||||
|
@ -562,17 +566,17 @@ internal partial class SelectForm : CustomForm
|
|||
IProgress<int> iProgress = progress;
|
||||
progress.ProgressChanged += (sender, _progress) =>
|
||||
{
|
||||
if (Program.Canceled) return;
|
||||
if (_progress < 0 || _progress > maxProgress) maxProgress = -_progress;
|
||||
else curProgress = _progress;
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
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}%"
|
||||
: $"Gathering and caching your applicable games and their DLCs . . . {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 . . . ";
|
||||
await SteamCMD.Setup(iProgress);
|
||||
|
@ -615,9 +619,11 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private void OnTreeViewNodeCheckedChanged(object sender, TreeViewEventArgs e)
|
||||
{
|
||||
if (e.Action == TreeViewAction.Unknown) return;
|
||||
if (e.Action == TreeViewAction.Unknown)
|
||||
return;
|
||||
TreeNode node = e.Node;
|
||||
if (node is null) return;
|
||||
if (node is null)
|
||||
return;
|
||||
SyncNode(node);
|
||||
SyncNodeAncestors(node);
|
||||
SyncNodeDescendants(node);
|
||||
|
@ -640,10 +646,11 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
}
|
||||
|
||||
private static void SyncNodeDescendants(TreeNode node) =>
|
||||
node.Nodes.Cast<TreeNode>().ToList().ForEach(childNode =>
|
||||
private static void SyncNodeDescendants(TreeNode node)
|
||||
=> node.Nodes.Cast<TreeNode>().ToList().ForEach(childNode =>
|
||||
{
|
||||
if (childNode.Text == "Unknown") return;
|
||||
if (childNode.Text == "Unknown")
|
||||
return;
|
||||
childNode.Checked = node.Checked;
|
||||
SyncNode(childNode);
|
||||
SyncNodeDescendants(childNode);
|
||||
|
@ -653,8 +660,7 @@ 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;
|
||||
|
@ -692,10 +698,7 @@ internal partial class SelectForm : CustomForm
|
|||
progressBar.Visible = true;
|
||||
programsGroupBox.Size = programsGroupBox.Size with
|
||||
{
|
||||
Height = programsGroupBox.Size.Height - 3
|
||||
- progressLabel.Size.Height
|
||||
- progressLabelGames.Size.Height
|
||||
- progressLabelDLCs.Size.Height
|
||||
Height = programsGroupBox.Size.Height - 3 - progressLabel.Size.Height - progressLabelGames.Size.Height - progressLabelDLCs.Size.Height
|
||||
- progressBar.Size.Height
|
||||
};
|
||||
}
|
||||
|
@ -709,15 +712,13 @@ internal partial class SelectForm : CustomForm
|
|||
progressBar.Visible = false;
|
||||
programsGroupBox.Size = programsGroupBox.Size with
|
||||
{
|
||||
Height = programsGroupBox.Size.Height + 3
|
||||
+ progressLabel.Size.Height
|
||||
+ progressLabelGames.Size.Height
|
||||
+ progressLabelDLCs.Size.Height
|
||||
Height = programsGroupBox.Size.Height + 3 + progressLabel.Size.Height + progressLabelGames.Size.Height + progressLabelDLCs.Size.Height
|
||||
+ progressBar.Size.Height
|
||||
};
|
||||
}
|
||||
|
||||
internal void OnNodeRightClick(TreeNode node, Point location) => Invoke(() =>
|
||||
internal void OnNodeRightClick(TreeNode node, Point location)
|
||||
=> Invoke(() =>
|
||||
{
|
||||
ContextMenuStrip contextMenuStrip = ContextMenuStrip;
|
||||
while (ContextMenuStrip.Tag is bool used && used)
|
||||
|
@ -738,11 +739,11 @@ internal partial class SelectForm : CustomForm
|
|||
return;
|
||||
ContextMenuItem header = null;
|
||||
if (id == "PL")
|
||||
header = new ContextMenuItem(node.Text, "Paradox Launcher");
|
||||
header = new(node.Text, "Paradox Launcher");
|
||||
else if (selection is not null)
|
||||
header = new ContextMenuItem(node.Text, (id, selection.IconUrl));
|
||||
header = new(node.Text, (id, selection.IconUrl));
|
||||
else if (dlc is not null && dlcParentSelection is not null)
|
||||
header = new ContextMenuItem(node.Text, (id, dlc.Value.app.icon), (id, dlcParentSelection.IconUrl));
|
||||
header = new(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";
|
||||
|
@ -757,19 +758,16 @@ internal partial class SelectForm : CustomForm
|
|||
: selection.Platform is Platform.Epic
|
||||
? "Epic GraphQL "
|
||||
: "";
|
||||
queries.Add(new ContextMenuItem($"Open {platformString}Query", "Notepad",
|
||||
(sender, e) => Diagnostics.OpenFileInNotepad(appInfoJSON)));
|
||||
queries.Add(new($"Open {platformString}Query", "Notepad", (sender, e) => Diagnostics.OpenFileInNotepad(appInfoJSON)));
|
||||
}
|
||||
if (File.Exists(appInfoVDF))
|
||||
queries.Add(new ContextMenuItem("Open SteamCMD Query", "Notepad",
|
||||
(sender, e) => Diagnostics.OpenFileInNotepad(appInfoVDF)));
|
||||
queries.Add(new("Open SteamCMD Query", "Notepad", (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",
|
||||
(sender, e) =>
|
||||
items.Add(new ContextMenuItem("Refresh Queries", "Command Prompt", (sender, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -795,109 +793,88 @@ internal partial class SelectForm : CustomForm
|
|||
if (id == "PL")
|
||||
{
|
||||
items.Add(new ToolStripSeparator());
|
||||
items.Add(new ContextMenuItem("Repair", "Command Prompt",
|
||||
async (sender, e) => await ParadoxLauncher.Repair(this, selection)));
|
||||
items.Add(new ContextMenuItem("Repair", "Command Prompt", async (sender, e) => await ParadoxLauncher.Repair(this, selection)));
|
||||
}
|
||||
items.Add(new ToolStripSeparator());
|
||||
items.Add(new ContextMenuItem("Open Root Directory", "File Explorer",
|
||||
(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",
|
||||
(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<string> directories = selection.DllDirectories.ToList();
|
||||
int steam = 0, epic = 0, r1 = 0, r2 = 0;
|
||||
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64,
|
||||
out string api64_o, out string config, out string cache);
|
||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o)
|
||||
|| File.Exists(config) || File.Exists(cache))
|
||||
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",
|
||||
(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",
|
||||
(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",
|
||||
(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",
|
||||
(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",
|
||||
(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",
|
||||
(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)));
|
||||
(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",
|
||||
(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",
|
||||
(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",
|
||||
(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)),
|
||||
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();
|
||||
|
@ -915,7 +892,8 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e.HandleException(this)) goto retry;
|
||||
if (e.HandleException(this))
|
||||
goto retry;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
@ -927,7 +905,8 @@ internal partial class SelectForm : CustomForm
|
|||
foreach (ProgramSelection selection in ProgramSelection.AllEnabled)
|
||||
if (!Program.IsProgramRunningDialog(this, selection))
|
||||
return;
|
||||
if (!uninstall && ParadoxLauncher.DlcDialog(this)) return;
|
||||
if (!uninstall && ParadoxLauncher.DlcDialog(this))
|
||||
return;
|
||||
Hide();
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
InstallForm form = new(uninstall);
|
||||
|
@ -945,9 +924,7 @@ internal partial class SelectForm : CustomForm
|
|||
OnLoad();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
form.Show();
|
||||
Hide();
|
||||
|
@ -982,7 +959,7 @@ internal partial class SelectForm : CustomForm
|
|||
if (node.Parent is null && node.Checked != shouldCheck)
|
||||
{
|
||||
node.Checked = shouldCheck;
|
||||
OnTreeViewNodeCheckedChanged(null, new TreeViewEventArgs(node, TreeViewAction.ByMouse));
|
||||
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
||||
}
|
||||
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
|
||||
allCheckBox.Checked = shouldCheck;
|
||||
|
@ -1009,20 +986,17 @@ 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)>();
|
||||
?? new List<(Platform platform, string gameId, string dlcId)>();
|
||||
foreach (TreeNode node in TreeNodes)
|
||||
if (node.Parent is TreeNode parent && node.Tag is Platform platform)
|
||||
{
|
||||
|
@ -1042,15 +1016,15 @@ internal partial class SelectForm : CustomForm
|
|||
private void OnLoadDlc(object sender, EventArgs e)
|
||||
{
|
||||
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices();
|
||||
if (choices is null) return;
|
||||
if (choices is null)
|
||||
return;
|
||||
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.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));
|
||||
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1062,7 +1036,7 @@ internal partial class SelectForm : CustomForm
|
|||
if (node.Parent is not null && node.Tag is Platform)
|
||||
{
|
||||
node.Checked = node.Text != "Unknown";
|
||||
OnTreeViewNodeCheckedChanged(null, new TreeViewEventArgs(node, TreeViewAction.ByMouse));
|
||||
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
||||
}
|
||||
resetButton.Enabled = CanResetDlc();
|
||||
}
|
||||
|
@ -1075,8 +1049,7 @@ 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)
|
||||
{
|
||||
|
@ -1085,12 +1058,9 @@ internal partial class SelectForm : CustomForm
|
|||
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)
|
||||
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));
|
||||
selection.KoaloaderProxy == ProgramSelection.DefaultKoaloaderProxy ? null : selection.KoaloaderProxy, selection.Koaloader));
|
||||
}
|
||||
ProgramData.WriteKoaloaderProxyChoices(choices);
|
||||
saveKoaloaderButton.Enabled = CanSaveKoaloader();
|
||||
|
@ -1102,12 +1072,13 @@ internal partial class SelectForm : CustomForm
|
|||
private void OnLoadKoaloader(object sender, EventArgs e)
|
||||
{
|
||||
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices();
|
||||
if (choices is null) return;
|
||||
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 =
|
||||
choices.First(c => c.platform == selection.Platform && c.id == selection.Id);
|
||||
(Platform platform, string id, string proxy, bool enabled)
|
||||
choice = choices.First(c => c.platform == selection.Platform && c.id == selection.Id);
|
||||
(Platform platform, string id, string proxy, bool enabled) = choice;
|
||||
string currentProxy = proxy;
|
||||
if (proxy is not null && proxy.Contains('.')) // convert pre-v4.1.0.0 choices
|
||||
|
@ -1115,14 +1086,11 @@ 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
|
||||
|
@ -1176,22 +1144,16 @@ 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
|
||||
= sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
||||
private void OnSortCheckBoxChanged(object sender, EventArgs e)
|
||||
=> selectionTreeView.TreeViewNodeSorter = sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0058
|
|
@ -17,43 +17,36 @@ internal static class EpicLibrary
|
|||
{
|
||||
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;
|
||||
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<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
||||
string gameDirectory) =>
|
||||
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||
|
||||
internal static async Task<List<Manifest>> GetGames() => await Task.Run(() =>
|
||||
internal static async Task<List<Manifest>> GetGames()
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
List<Manifest> games = new();
|
||||
string manifests = EpicManifestsPath;
|
||||
if (!Directory.Exists(manifests)) return games;
|
||||
if (!Directory.Exists(manifests))
|
||||
return games;
|
||||
foreach (string file in Directory.EnumerateFiles(manifests, "*.item"))
|
||||
{
|
||||
if (Program.Canceled) return games;
|
||||
if (Program.Canceled)
|
||||
return games;
|
||||
string json = File.ReadAllText(file);
|
||||
try
|
||||
{
|
||||
Manifest manifest = JsonSerializer.Deserialize<Manifest>(json);
|
||||
if (manifest is not null && manifest.CatalogItemId == manifest.MainGameCatalogItemId
|
||||
&& !games.Any(g => g.CatalogItemId == manifest.CatalogItemId
|
||||
&& g.InstallLocation == manifest.InstallLocation))
|
||||
if (manifest is not null && manifest.CatalogItemId == manifest.MainGameCatalogItemId && !games.Any(g
|
||||
=> g.CatalogItemId == manifest.CatalogItemId && g.InstallLocation == manifest.InstallLocation))
|
||||
games.Add(manifest);
|
||||
}
|
||||
catch { }
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using CreamInstaller.Platforms.Epic.GraphQL;
|
||||
|
@ -23,8 +22,7 @@ internal static class EpicStore
|
|||
|
||||
private const int COOLDOWN_ENTITLEMENT = 600;
|
||||
|
||||
internal static async Task<List<(string id, string name, string product, string icon, string developer)>>
|
||||
QueryEntitlements(string categoryNamespace)
|
||||
internal static async Task<List<(string id, string name, string product, string icon, string developer)>> QueryEntitlements(string categoryNamespace)
|
||||
{
|
||||
List<(string id, string name, string product, string icon, string developer)> dlcIds = new();
|
||||
string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json";
|
||||
|
@ -40,7 +38,6 @@ internal static class EpicStore
|
|||
catch { }
|
||||
}
|
||||
else if (cachedExists)
|
||||
{
|
||||
try
|
||||
{
|
||||
response = JsonConvert.DeserializeObject<Response>(await File.ReadAllTextAsync(cacheFile));
|
||||
|
@ -49,16 +46,13 @@ internal static class EpicStore
|
|||
{
|
||||
File.Delete(cacheFile);
|
||||
}
|
||||
}
|
||||
if (response is null)
|
||||
return dlcIds;
|
||||
List<Element> searchStore = new(response.Data.Catalog.SearchStore.Elements);
|
||||
foreach (Element element in searchStore)
|
||||
{
|
||||
string title = element.Title;
|
||||
string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any()
|
||||
? element.CatalogNs.Mappings.First().PageSlug
|
||||
: null;
|
||||
string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any() ? element.CatalogNs.Mappings.First().PageSlug : null;
|
||||
string icon = null;
|
||||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||
{
|
||||
|
@ -76,9 +70,7 @@ internal static class EpicStore
|
|||
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;
|
||||
string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any() ? element.CatalogNs.Mappings.First().PageSlug : null;
|
||||
string icon = null;
|
||||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||
{
|
||||
|
@ -95,11 +87,11 @@ internal static class EpicStore
|
|||
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;
|
||||
if (id == null)
|
||||
return;
|
||||
bool found = false;
|
||||
for (int i = 0; i < dlcIds.Count; i++)
|
||||
{
|
||||
|
@ -113,7 +105,8 @@ internal static class EpicStore
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!found) dlcIds.Add((id, title, product, icon, developer));
|
||||
if (!found)
|
||||
dlcIds.Add((id, title, product, icon, developer));
|
||||
}
|
||||
|
||||
private static async Task<Response> QueryGraphQL(string categoryNamespace)
|
||||
|
@ -124,11 +117,11 @@ internal static class EpicStore
|
|||
Request request = new(encoded);
|
||||
string payload = JsonConvert.SerializeObject(request);
|
||||
using HttpContent content = new StringContent(payload);
|
||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
content.Headers.ContentType = new("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);
|
||||
if (client is null)
|
||||
return null;
|
||||
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>(response);
|
||||
|
|
|
@ -9,10 +9,11 @@ namespace CreamInstaller.Platforms.Epic.GraphQL;
|
|||
|
||||
internal class Request
|
||||
{
|
||||
internal Request(string @namespace) => Vars = new Variables(@namespace);
|
||||
internal Request(string @namespace) => Vars = new(@namespace);
|
||||
|
||||
[JsonProperty(PropertyName = "query")]
|
||||
private string Query => @"query searchOffers($namespace: String!) {
|
||||
private string Query
|
||||
=> @"query searchOffers($namespace: String!) {
|
||||
Catalog {
|
||||
searchStore(category: ""*"", namespace: $namespace){
|
||||
elements {
|
||||
|
|
|
@ -27,20 +27,16 @@ internal static class ParadoxLauncher
|
|||
{
|
||||
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<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
||||
string gameDirectory) =>
|
||||
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: path
|
||||
=> !Path.GetFileName(path)
|
||||
.Contains("bootstrapper")));
|
||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: path => !Path.GetFileName(path).Contains("bootstrapper")));
|
||||
|
||||
private static void PopulateDlc(ProgramSelection paradoxLauncher = null)
|
||||
{
|
||||
|
@ -49,26 +45,24 @@ 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 ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
||||
selection.Id, selection.Name, selection.AllDlc));
|
||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(selection.Id, selection.Name,
|
||||
selection.AllDlc));
|
||||
paradoxLauncher.ExtraSelectedDlc.Add(
|
||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
||||
selection.Id, selection.Name, selection.SelectedDlc));
|
||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(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 ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
||||
selection.Id, selection.Name, selection.AllDlc));
|
||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(selection.Id, selection.Name,
|
||||
selection.AllDlc));
|
||||
paradoxLauncher.ExtraSelectedDlc.Add(
|
||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
||||
selection.Id, selection.Name, selection.AllDlc));
|
||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(selection.Id, selection.Name,
|
||||
selection.AllDlc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,9 +78,8 @@ 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", "Paradox Launcher") != DialogResult.OK;
|
||||
+ "\n\nInstalling DLC unlockers for the Paradox Launcher alone can cause existing configurations to be deleted!", "Ignore", "Cancel",
|
||||
"Paradox Launcher") != DialogResult.OK;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -96,9 +89,7 @@ internal static class ParadoxLauncher
|
|||
{
|
||||
InstallForm installForm = form as InstallForm;
|
||||
if (!Program.IsProgramRunningDialog(form, selection))
|
||||
return form is InstallForm
|
||||
? throw new CustomMessageException("Repair failed! The launcher is currently running!")
|
||||
: RepairResult.ProgramRunning;
|
||||
return form is InstallForm ? throw new CustomMessageException("Repair failed! The launcher is currently running!") : RepairResult.ProgramRunning;
|
||||
bool smokeInstalled = false;
|
||||
byte[] steamOriginalSdk32 = null;
|
||||
byte[] steamOriginalSdk64 = null;
|
||||
|
@ -107,40 +98,29 @@ internal static class ParadoxLauncher
|
|||
byte[] epicOriginalSdk64 = null;
|
||||
foreach (string directory in selection.DllDirectories)
|
||||
{
|
||||
bool koaloaderInstalled = Koaloader.AutoLoadDlls
|
||||
.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
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 _);
|
||||
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));
|
||||
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);
|
||||
await SmokeAPI.Uninstall(directory, deleteConfig: false);
|
||||
if (steamOriginalSdk32 is null && File.Exists(api32)
|
||||
&& !api32.IsResourceFile(ResourceIdentifier.Steamworks32))
|
||||
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))
|
||||
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));
|
||||
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);
|
||||
await ScreamAPI.Uninstall(directory, deleteConfig: false);
|
||||
if (epicOriginalSdk32 is null && File.Exists(api32)
|
||||
&& !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))
|
||||
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))
|
||||
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)
|
||||
|
@ -181,26 +161,22 @@ 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
|
||||
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", "OK",
|
||||
customFormText: "Paradox Launcher");
|
||||
_ = 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");
|
||||
? 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@ internal static class SteamCMD
|
|||
|
||||
internal static readonly string FilePath = DirectoryPath + @"\steamcmd.exe";
|
||||
|
||||
private static readonly ConcurrentDictionary<string, int>
|
||||
AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print
|
||||
private static readonly ConcurrentDictionary<string, int> AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print
|
||||
|
||||
private static readonly int[] locks = new int[ProcessLimit];
|
||||
|
||||
|
@ -38,18 +37,22 @@ internal static class SteamCMD
|
|||
internal static string DirectoryPath => ProgramData.DirectoryPath;
|
||||
internal static string AppInfoPath => ProgramData.AppInfoPath;
|
||||
|
||||
private static string GetArguments(string appId) => AttemptCount.TryGetValue(appId, out int attempts)
|
||||
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"
|
||||
: $"+login anonymous +app_info_print {appId} +quit";
|
||||
|
||||
internal static async Task<string> Run(string appId) => await Task.Run(() =>
|
||||
internal static async Task<string> Run(string appId)
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
wait_for_lock:
|
||||
if (Program.Canceled) return "";
|
||||
if (Program.Canceled)
|
||||
return "";
|
||||
for (int i = 0; i < locks.Length; i++)
|
||||
{
|
||||
if (Program.Canceled) return "";
|
||||
if (Program.Canceled)
|
||||
return "";
|
||||
if (Interlocked.CompareExchange(ref locks[i], 1, 0) == 0)
|
||||
{
|
||||
if (appId is not null)
|
||||
|
@ -57,14 +60,13 @@ internal static class SteamCMD
|
|||
AttemptCount.TryGetValue(appId, out int count);
|
||||
AttemptCount[appId] = ++count;
|
||||
}
|
||||
if (Program.Canceled) return "";
|
||||
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,
|
||||
StandardErrorEncoding = 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);
|
||||
StringBuilder output = new();
|
||||
|
@ -84,7 +86,8 @@ internal static class SteamCMD
|
|||
{
|
||||
lastOutput = DateTime.UtcNow;
|
||||
char ch = (char)c;
|
||||
if (ch == '{') appInfoStarted = true;
|
||||
if (ch == '{')
|
||||
appInfoStarted = true;
|
||||
_ = appInfoStarted ? appInfo.Append(ch) : output.Append(ch);
|
||||
}
|
||||
DateTime now = DateTime.UtcNow;
|
||||
|
@ -103,11 +106,9 @@ internal static class SteamCMD
|
|||
_ = appInfo.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = Interlocked.Decrement(ref locks[i]);
|
||||
return appInfo.ToString();
|
||||
}
|
||||
|
@ -123,21 +124,20 @@ internal static class SteamCMD
|
|||
if (!File.Exists(FilePath))
|
||||
{
|
||||
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"));
|
||||
if (httpClient is null)
|
||||
return;
|
||||
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);
|
||||
}
|
||||
if (!File.Exists(DllPath))
|
||||
{
|
||||
FileSystemWatcher watcher = new(DirectoryPath)
|
||||
{
|
||||
Filter = "*", IncludeSubdirectories = true, EnableRaisingEvents = true
|
||||
};
|
||||
if (File.Exists(DllPath)) progress.Report(-15); // update (not used at the moment)
|
||||
else progress.Report(-1660); // install
|
||||
FileSystemWatcher watcher = new(DirectoryPath) { Filter = "*", IncludeSubdirectories = true, EnableRaisingEvents = true };
|
||||
if (File.Exists(DllPath))
|
||||
progress.Report(-15); // update (not used at the moment)
|
||||
else
|
||||
progress.Report(-1660); // install
|
||||
int cur = 0;
|
||||
progress.Report(cur);
|
||||
watcher.Changed += (sender, e) => progress.Report(++cur);
|
||||
|
@ -146,9 +146,11 @@ internal static class SteamCMD
|
|||
}
|
||||
}
|
||||
|
||||
internal static async Task Cleanup() => await Task.Run(async () =>
|
||||
internal static async Task Cleanup()
|
||||
=> await Task.Run(async () =>
|
||||
{
|
||||
if (!Directory.Exists(DirectoryPath)) return;
|
||||
if (!Directory.Exists(DirectoryPath))
|
||||
return;
|
||||
await Kill();
|
||||
try
|
||||
{
|
||||
|
@ -164,8 +166,7 @@ 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))
|
||||
|
@ -178,13 +179,14 @@ internal static class SteamCMD
|
|||
|
||||
internal static async Task<VProperty> GetAppInfo(string appId, string branch = "public", int buildId = 0)
|
||||
{
|
||||
if (Program.Canceled) return null;
|
||||
if (Program.Canceled)
|
||||
return null;
|
||||
string output;
|
||||
string appUpdateFile = $@"{AppInfoPath}\{appId}.vdf";
|
||||
restart:
|
||||
if (Program.Canceled) return null;
|
||||
if (Program.Canceled)
|
||||
return null;
|
||||
if (File.Exists(appUpdateFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
output = await File.ReadAllTextAsync(appUpdateFile, Encoding.UTF8);
|
||||
|
@ -193,7 +195,6 @@ internal static class SteamCMD
|
|||
{
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output = await Run(appId) ?? "";
|
||||
|
@ -213,37 +214,40 @@ internal static class SteamCMD
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
if (Program.Canceled) return null;
|
||||
if (Program.Canceled)
|
||||
return null;
|
||||
if (!ValveDataFile.TryDeserialize(output, out VProperty appInfo) || appInfo.Value is VValue)
|
||||
{
|
||||
File.Delete(appUpdateFile);
|
||||
goto restart;
|
||||
}
|
||||
if (appInfo is null || appInfo.Value?.Children()?.ToList()?.Count == 0) return appInfo;
|
||||
if (appInfo is null || appInfo.Value?.Children()?.ToList()?.Count == 0)
|
||||
return appInfo;
|
||||
VToken type = appInfo.Value?.GetChild("common")?.GetChild("type");
|
||||
if (type is not null && type.ToString() != "Game")
|
||||
return appInfo;
|
||||
string buildid = appInfo.Value?.GetChild("depots")?.GetChild("branches")?.GetChild(branch)
|
||||
?.GetChild("buildid")?.ToString();
|
||||
if (buildid is null && type is not null) return appInfo;
|
||||
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 not null && (!int.TryParse(buildid, out int gamebuildId) || gamebuildId >= buildId))
|
||||
return appInfo;
|
||||
List<string> dlcAppIds = await ParseDlcAppIds(appInfo);
|
||||
foreach (string dlcAppUpdateFile in dlcAppIds.Select(id => $@"{AppInfoPath}\{id}.vdf"))
|
||||
if (File.Exists(dlcAppUpdateFile))
|
||||
File.Delete(dlcAppUpdateFile);
|
||||
if (File.Exists(appUpdateFile)) File.Delete(appUpdateFile);
|
||||
if (File.Exists(appUpdateFile))
|
||||
File.Delete(appUpdateFile);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
internal static async Task<List<string>> ParseDlcAppIds(VProperty appInfo) => await Task.Run(() =>
|
||||
internal static async Task<List<string>> ParseDlcAppIds(VProperty appInfo)
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
List<string> dlcIds = new();
|
||||
if (Program.Canceled || appInfo is null) return dlcIds;
|
||||
if (Program.Canceled || appInfo is null)
|
||||
return dlcIds;
|
||||
VToken extended = appInfo.Value.GetChild("extended");
|
||||
if (extended is not null)
|
||||
foreach (VToken vToken in extended.Where(p => p is VProperty { Key: "listofdlc" }))
|
||||
|
@ -259,8 +263,7 @@ internal static class SteamCMD
|
|||
foreach (VToken vToken in depots.Where(p => p is VProperty property && int.TryParse(property.Key, out int _)))
|
||||
{
|
||||
VProperty property = (VProperty)vToken;
|
||||
if (int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appId) && appId > 0
|
||||
&& !dlcIds.Contains("" + appId))
|
||||
if (int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appId) && appId > 0 && !dlcIds.Contains("" + appId))
|
||||
dlcIds.Add("" + appId);
|
||||
}
|
||||
return dlcIds;
|
||||
|
@ -268,8 +271,7 @@ internal static class SteamCMD
|
|||
|
||||
private static async Task Kill()
|
||||
{
|
||||
List<Task> tasks = Process.GetProcessesByName("steamcmd")
|
||||
.Select(process => Task.Run(() =>
|
||||
List<Task> tasks = Process.GetProcessesByName("steamcmd").Select(process => Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -278,9 +280,9 @@ internal static class SteamCMD
|
|||
process.Close();
|
||||
}
|
||||
catch { }
|
||||
}))
|
||||
.ToList();
|
||||
foreach (Task task in tasks) await task;
|
||||
})).ToList();
|
||||
foreach (Task task in tasks)
|
||||
await task;
|
||||
}
|
||||
|
||||
internal static void Dispose()
|
||||
|
|
|
@ -18,70 +18,74 @@ internal static class SteamLibrary
|
|||
{
|
||||
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<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
||||
string gameDirectory) =>
|
||||
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||
|
||||
internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>>
|
||||
GetGames() => await Task.Run(async () =>
|
||||
internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>> GetGames()
|
||||
=> await Task.Run(async () =>
|
||||
{
|
||||
List<(string appId, string name, string branch, int buildId, string gameDirectory)> games = new();
|
||||
List<string> gameLibraryDirectories = await GetLibraryDirectories();
|
||||
foreach (string libraryDirectory in gameLibraryDirectories)
|
||||
{
|
||||
if (Program.Canceled) return games;
|
||||
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)))
|
||||
(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<List<(string appId, string name, string branch, int buildId, string gameDirectory)>>
|
||||
GetGamesFromLibraryDirectory(string libraryDirectory) => await Task.Run(() =>
|
||||
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;
|
||||
if (Program.Canceled || !Directory.Exists(libraryDirectory))
|
||||
return games;
|
||||
foreach (string file in Directory.EnumerateFiles(libraryDirectory, "*.acf"))
|
||||
{
|
||||
if (Program.Canceled) return games;
|
||||
if (Program.Canceled)
|
||||
return games;
|
||||
if (ValveDataFile.TryDeserialize(File.ReadAllText(file, Encoding.UTF8), out VProperty result))
|
||||
{
|
||||
string appId = result.Value.GetChild("appid")?.ToString();
|
||||
string installdir = result.Value.GetChild("installdir")?.ToString();
|
||||
string name = result.Value.GetChild("name")?.ToString();
|
||||
string buildId = result.Value.GetChild("buildid")?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(appId)
|
||||
|| string.IsNullOrWhiteSpace(installdir)
|
||||
|| string.IsNullOrWhiteSpace(name)
|
||||
if (string.IsNullOrWhiteSpace(appId) || 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;
|
||||
if (!int.TryParse(appId, out int appIdInt)) continue;
|
||||
if (!int.TryParse(buildId, out int buildIdInt)) continue;
|
||||
if (games.Any(g => g.appId == appId && g.gameDirectory == gameDirectory))
|
||||
continue;
|
||||
if (!int.TryParse(appId, out int appIdInt))
|
||||
continue;
|
||||
if (!int.TryParse(buildId, out int buildIdInt))
|
||||
continue;
|
||||
string branch = result.Value.GetChild("UserConfig")?.GetChild("betakey")?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(branch)) branch = "public";
|
||||
if (string.IsNullOrWhiteSpace(branch))
|
||||
branch = "public";
|
||||
games.Add((appId, name, branch, buildIdInt, gameDirectory));
|
||||
}
|
||||
}
|
||||
return games;
|
||||
});
|
||||
|
||||
internal static async Task<List<string>> GetLibraryDirectories() => await Task.Run(() =>
|
||||
internal static async Task<List<string>> GetLibraryDirectories()
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
List<string> gameDirectories = new();
|
||||
if (Program.Canceled) return gameDirectories;
|
||||
if (Program.Canceled)
|
||||
return gameDirectories;
|
||||
string steamInstallPath = InstallPath;
|
||||
if (steamInstallPath != null && Directory.Exists(steamInstallPath))
|
||||
{
|
||||
|
@ -90,14 +94,13 @@ 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;
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
continue;
|
||||
path += @"\steamapps";
|
||||
if (Directory.Exists(path) && !gameDirectories.Contains(path))
|
||||
gameDirectories.Add(path);
|
||||
|
|
|
@ -18,23 +18,25 @@ internal static class SteamStore
|
|||
private const int COOLDOWN_GAME = 600;
|
||||
private const int COOLDOWN_DLC = 1200;
|
||||
|
||||
internal static async Task<List<string>> ParseDlcAppIds(AppData appData) => await Task.Run(() =>
|
||||
internal static async Task<List<string>> ParseDlcAppIds(AppData appData)
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
List<string> dlcIds = new();
|
||||
if (appData.dlc is null) return dlcIds;
|
||||
if (appData.dlc is null)
|
||||
return dlcIds;
|
||||
dlcIds.AddRange(from appId in appData.dlc where appId > 0 select appId.ToString());
|
||||
return dlcIds;
|
||||
});
|
||||
|
||||
internal static async Task<AppData> QueryStoreAPI(string appId, bool isDlc = false, int attempts = 0)
|
||||
{
|
||||
if (Program.Canceled) return null;
|
||||
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<string, JToken> apps = (IDictionary<string, JToken>)JsonConvert.DeserializeObject(response);
|
||||
|
@ -60,8 +62,7 @@ internal static class SteamStore
|
|||
{
|
||||
try
|
||||
{
|
||||
await File.WriteAllTextAsync(
|
||||
cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented));
|
||||
await File.WriteAllTextAsync(cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented));
|
||||
}
|
||||
catch
|
||||
#if DEBUG
|
||||
|
@ -76,16 +77,13 @@ internal static class SteamStore
|
|||
return data;
|
||||
}
|
||||
#if DEBUG
|
||||
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)}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch
|
||||
|
@ -99,7 +97,8 @@ internal static class SteamStore
|
|||
{ }
|
||||
#endif
|
||||
#if DEBUG
|
||||
else DebugForm.Current.Log("Response deserialization null for appid " + appId);
|
||||
else
|
||||
DebugForm.Current.Log("Response deserialization null for appid " + appId);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
|
|
@ -22,16 +22,16 @@ internal static class UbisoftLibrary
|
|||
}
|
||||
}
|
||||
|
||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
||||
string gameDirectory) =>
|
||||
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||
|
||||
internal static async Task<List<(string gameId, string name, string gameDirectory)>> GetGames() => await Task.Run(
|
||||
() =>
|
||||
internal static async Task<List<(string gameId, string name, string gameDirectory)>> GetGames()
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
List<(string gameId, string name, string gameDirectory)> games = new();
|
||||
RegistryKey installsKey = InstallsKey;
|
||||
if (installsKey is null) return games;
|
||||
if (installsKey is null)
|
||||
return games;
|
||||
foreach (string gameId in installsKey.GetSubKeyNames())
|
||||
{
|
||||
RegistryKey installKey = installsKey.OpenSubKey(gameId);
|
||||
|
|
|
@ -42,8 +42,10 @@ internal static class Program
|
|||
|
||||
internal static bool IsGameBlocked(string name, string directory = null)
|
||||
{
|
||||
if (!BlockProtectedGames) return false;
|
||||
if (ProtectedGames.Contains(name)) return true;
|
||||
if (!BlockProtectedGames)
|
||||
return false;
|
||||
if (ProtectedGames.Contains(name))
|
||||
return true;
|
||||
if (directory is not null && !ProtectedGameDirectoryExceptions.Contains(name))
|
||||
foreach (string path in ProtectedGameDirectories)
|
||||
if (Directory.Exists(directory + path))
|
||||
|
@ -56,16 +58,12 @@ internal static class Program
|
|||
if (selection.AreDllsLocked)
|
||||
{
|
||||
using DialogForm dialogForm = new(form);
|
||||
if (dialogForm.Show(SystemIcons.Error,
|
||||
$"ERROR: {selection.Name} is currently running!" +
|
||||
"\n\nPlease close the program/game to continue . . . ",
|
||||
if (dialogForm.Show(SystemIcons.Error, $"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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -81,8 +79,7 @@ internal static class Program
|
|||
Application.ApplicationExit += OnApplicationExit;
|
||||
Application.ThreadException += (s, e) => e.Exception?.HandleFatalException();
|
||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
||||
AppDomain.CurrentDomain.UnhandledException += (s, e)
|
||||
=> (e.ExceptionObject as Exception)?.HandleFatalException();
|
||||
AppDomain.CurrentDomain.UnhandledException += (s, e) => (e.ExceptionObject as Exception)?.HandleFatalException();
|
||||
retry:
|
||||
try
|
||||
{
|
||||
|
@ -95,7 +92,8 @@ internal static class Program
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e.HandleException()) goto retry;
|
||||
if (e.HandleException())
|
||||
goto retry;
|
||||
Application.Exit();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,17 +25,14 @@ internal class ProgramSelection
|
|||
|
||||
internal static readonly List<ProgramSelection> All = new();
|
||||
|
||||
internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc
|
||||
= new(PlatformIdComparer.String);
|
||||
internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc = new(PlatformIdComparer.String);
|
||||
|
||||
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)>
|
||||
ExtraDlc = new(); // for Paradox Launcher
|
||||
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)> ExtraDlc = new(); // for Paradox Launcher
|
||||
|
||||
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)>
|
||||
ExtraSelectedDlc = new(); // for Paradox Launcher
|
||||
|
||||
internal readonly SortedList<string, (DlcType type, string name, string icon)> SelectedDlc
|
||||
= new(PlatformIdComparer.String);
|
||||
internal readonly SortedList<string, (DlcType type, string name, string icon)> SelectedDlc = new(PlatformIdComparer.String);
|
||||
|
||||
internal List<string> DllDirectories;
|
||||
internal bool Enabled;
|
||||
|
@ -67,54 +64,31 @@ 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);
|
||||
if (api32.IsFilePathLocked()
|
||||
|| api32_o.IsFilePathLocked()
|
||||
|| api64.IsFilePathLocked()
|
||||
|| api64_o.IsFilePathLocked()
|
||||
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())
|
||||
return true;
|
||||
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())
|
||||
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())
|
||||
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);
|
||||
if (api32.IsFilePathLocked()
|
||||
|| api32_o.IsFilePathLocked()
|
||||
|| api64.IsFilePathLocked()
|
||||
|| api64_o.IsFilePathLocked()
|
||||
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())
|
||||
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);
|
||||
if (api32.IsFilePathLocked()
|
||||
|| api32_o.IsFilePathLocked()
|
||||
|| api64.IsFilePathLocked()
|
||||
|| api64_o.IsFilePathLocked()
|
||||
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())
|
||||
return true;
|
||||
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())
|
||||
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())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -128,8 +102,10 @@ internal class ProgramSelection
|
|||
|
||||
private void Toggle(string dlcAppId, (DlcType type, string name, string icon) dlcApp, bool enabled)
|
||||
{
|
||||
if (enabled) SelectedDlc[dlcAppId] = dlcApp;
|
||||
else _ = SelectedDlc.Remove(dlcAppId);
|
||||
if (enabled)
|
||||
SelectedDlc[dlcAppId] = dlcApp;
|
||||
else
|
||||
_ = SelectedDlc.Remove(dlcAppId);
|
||||
}
|
||||
|
||||
internal void ToggleDlc(string dlcId, bool enabled)
|
||||
|
@ -160,7 +136,8 @@ internal class ProgramSelection
|
|||
return;
|
||||
}
|
||||
_ = DllDirectories.RemoveAll(directory => !Directory.Exists(directory));
|
||||
if (!DllDirectories.Any()) _ = All.Remove(this);
|
||||
if (!DllDirectories.Any())
|
||||
_ = All.Remove(this);
|
||||
}
|
||||
|
||||
internal void Validate(List<(Platform platform, string id, string name)> programsToScan)
|
||||
|
@ -178,15 +155,12 @@ internal class ProgramSelection
|
|||
internal static void ValidateAll(List<(Platform platform, string id, string name)> programsToScan)
|
||||
=> AllSafe.ForEach(selection => selection.Validate(programsToScan));
|
||||
|
||||
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<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(
|
||||
p => p.Key == dlcId))
|
||||
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(p => p.Key == dlcId))
|
||||
return (selection.Id, pair.Value);
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -14,27 +14,22 @@ internal static class Koaloader
|
|||
{
|
||||
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")
|
||||
("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<string> proxies,
|
||||
out string config
|
||||
)
|
||||
internal static void GetKoaloaderComponents(this string directory, out List<string> proxies, out string config)
|
||||
{
|
||||
proxies = new List<string>();
|
||||
proxies = new();
|
||||
foreach (string proxy in EmbeddedResources.Select(proxy =>
|
||||
{
|
||||
proxy = proxy[(proxy.IndexOf('.') + 1)..];
|
||||
return proxy[(proxy.IndexOf('.') + 1)..];
|
||||
})) proxies.Add(directory + @"\" + proxy);
|
||||
}))
|
||||
proxies.Add(directory + @"\" + proxy);
|
||||
config = directory + @"\Koaloader.json";
|
||||
}
|
||||
|
||||
|
@ -51,8 +46,7 @@ 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('.')];
|
||||
|
@ -83,13 +77,12 @@ internal static class Koaloader
|
|||
else if (File.Exists(config))
|
||||
{
|
||||
File.Delete(config);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
||||
false);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, string> targets,
|
||||
SortedList<string, string> modules, InstallForm installForm = null)
|
||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, string> targets, SortedList<string, string> modules,
|
||||
InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
writer.WriteLine(" \"logging\": false,");
|
||||
|
@ -108,9 +101,7 @@ internal static class Koaloader
|
|||
writer.WriteLine(" ]");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteLine(" \"targets\": []");
|
||||
}
|
||||
if (modules.Any())
|
||||
{
|
||||
writer.WriteLine(" \"modules\": [");
|
||||
|
@ -127,24 +118,20 @@ internal static class Koaloader
|
|||
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<string> 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, false);
|
||||
}
|
||||
foreach ((string unlocker, string path) in AutoLoadDlls
|
||||
.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
foreach ((string unlocker, string path) in AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
.Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile()))
|
||||
{
|
||||
File.Delete(path);
|
||||
|
@ -163,26 +150,23 @@ 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<string> 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, 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, 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))
|
||||
|
@ -204,8 +188,7 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}",
|
||||
LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\SmokeAPI32.dll";
|
||||
}
|
||||
|
@ -222,8 +205,7 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}",
|
||||
LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\SmokeAPI64.dll";
|
||||
}
|
||||
|
@ -244,8 +226,7 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}",
|
||||
LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\ScreamAPI32.dll";
|
||||
}
|
||||
|
@ -262,8 +243,7 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}",
|
||||
LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\ScreamAPI64.dll";
|
||||
}
|
||||
|
@ -284,9 +264,7 @@ 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, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR1Unlocker32.dll";
|
||||
}
|
||||
|
@ -303,9 +281,7 @@ 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, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR1Unlocker64.dll";
|
||||
}
|
||||
|
@ -323,9 +299,7 @@ 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, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR2Unlocker32.dll";
|
||||
}
|
||||
|
@ -342,9 +316,7 @@ 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, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR2Unlocker64.dll";
|
||||
}
|
||||
|
|
|
@ -335,7 +335,7 @@ internal static class Resources
|
|||
if (embeddedResources is null)
|
||||
{
|
||||
string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
||||
embeddedResources = new List<string>();
|
||||
embeddedResources = new();
|
||||
foreach (string resourceName in names.Where(n => n.StartsWith("CreamInstaller.Resources.")))
|
||||
embeddedResources.Add(resourceName[25..]);
|
||||
}
|
||||
|
@ -345,8 +345,7 @@ 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);
|
||||
}
|
||||
|
@ -378,45 +377,42 @@ internal static class Resources
|
|||
[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 bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => GetBinaryType(path, out binaryType);
|
||||
|
||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
||||
this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) =>
|
||||
await Task.Run(async () => (await rootDirectory.GetExecutables(filterCommon, validFunc)
|
||||
?? (filterCommon || validFunc is not null
|
||||
? await rootDirectory.GetExecutables()
|
||||
: null))?.Select(e =>
|
||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(this string rootDirectory, bool filterCommon = false,
|
||||
Func<string, bool> 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<List<(string path, BinaryType binaryType)>> GetExecutables(
|
||||
this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) => await Task.Run(
|
||||
() =>
|
||||
internal static async Task<List<(string path, BinaryType binaryType)>> GetExecutables(this string rootDirectory, bool filterCommon = false,
|
||||
Func<string, bool> 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 }))
|
||||
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.All(e => e.path != path)
|
||||
&& (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
|
||||
&& (validFunc is null || validFunc(path))
|
||||
&& path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64)
|
||||
if (Program.Canceled)
|
||||
return null;
|
||||
if (executables.All(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 }))
|
||||
foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe", new EnumerationOptions { RecurseSubdirectories = true }))
|
||||
{
|
||||
if (Program.Canceled) return null;
|
||||
if (executables.All(e => e.path != path)
|
||||
&& (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
|
||||
&& (validFunc is null || validFunc(path))
|
||||
&& path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32)
|
||||
if (Program.Canceled)
|
||||
return null;
|
||||
if (executables.All(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);
|
||||
}
|
||||
|
@ -426,80 +422,54 @@ internal static class Resources
|
|||
internal static bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
|
||||
{
|
||||
string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath();
|
||||
return subPath.Contains("SETUP")
|
||||
|| subPath.Contains("REDIST")
|
||||
|| subPath.Contains("SUPPORT")
|
||||
|| (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("BATTLEYE")
|
||||
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|
||||
|| 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("BATTLEYE")
|
||||
|| subPath.Contains("ANTICHEAT");
|
||||
}
|
||||
|
||||
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(
|
||||
this string gameDirectory, Platform platform) => await Task.Run(() =>
|
||||
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform)
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
List<string> dllDirectories = new();
|
||||
if (Program.Canceled || !Directory.Exists(gameDirectory)) return null;
|
||||
foreach (string directory in Directory
|
||||
.EnumerateDirectories(gameDirectory, "*",
|
||||
new EnumerationOptions { RecurseSubdirectories = true })
|
||||
if (Program.Canceled || !Directory.Exists(gameDirectory))
|
||||
return null;
|
||||
foreach (string directory in Directory.EnumerateDirectories(gameDirectory, "*", new EnumerationOptions { RecurseSubdirectories = true })
|
||||
.Append(gameDirectory))
|
||||
{
|
||||
if (Program.Canceled) return null;
|
||||
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))
|
||||
bool koaloaderInstalled = Koaloader.AutoLoadDlls.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);
|
||||
if (File.Exists(api)
|
||||
|| File.Exists(api_o)
|
||||
|| File.Exists(api64)
|
||||
|| File.Exists(api64_o)
|
||||
|| (File.Exists(config) && !koaloaderInstalled)
|
||||
|| (File.Exists(cache) && !koaloaderInstalled))
|
||||
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)
|
||||
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);
|
||||
if (File.Exists(api32)
|
||||
|| File.Exists(api32_o)
|
||||
|| File.Exists(api64)
|
||||
|| File.Exists(api64_o)
|
||||
|| (File.Exists(config) && !koaloaderInstalled))
|
||||
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)
|
||||
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);
|
||||
if (File.Exists(api32)
|
||||
|| File.Exists(api32_o)
|
||||
|| File.Exists(api64)
|
||||
|| File.Exists(api64_o)
|
||||
|| (File.Exists(config) && !koaloaderInstalled))
|
||||
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)
|
||||
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);
|
||||
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))
|
||||
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)
|
||||
dllDirectories.Add(subDirectory);
|
||||
}
|
||||
}
|
||||
|
@ -507,10 +477,7 @@ internal static class Resources
|
|||
return !dllDirectories.Any() ? null : dllDirectories;
|
||||
});
|
||||
|
||||
internal static void GetCreamApiComponents(
|
||||
this string directory,
|
||||
out string api32, out string api32_o,
|
||||
out string api64, out string api64_o,
|
||||
internal static void GetCreamApiComponents(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";
|
||||
|
@ -522,7 +489,8 @@ internal static class Resources
|
|||
|
||||
internal static string ComputeMD5(this string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath)) return null;
|
||||
if (!File.Exists(filePath))
|
||||
return null;
|
||||
#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms
|
||||
using MD5 md5 = MD5.Create();
|
||||
#pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms
|
||||
|
@ -534,9 +502,8 @@ internal static class Resources
|
|||
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));
|
||||
|
||||
internal enum BinaryType
|
||||
{
|
||||
|
|
|
@ -11,12 +11,8 @@ 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
|
||||
)
|
||||
internal static void GetScreamApiComponents(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";
|
||||
|
@ -30,13 +26,11 @@ internal static class ScreamAPI
|
|||
directory.GetScreamApiComponents(out _, out _, out _, out _, out string config);
|
||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideCatalogItems
|
||||
= selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in
|
||||
selection.ExtraSelectedDlc)
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||
overrideCatalogItems = overrideCatalogItems.Except(extraDlc);
|
||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> entitlements
|
||||
= selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> _dlc) in
|
||||
selection.ExtraSelectedDlc)
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> _dlc) in selection.ExtraSelectedDlc)
|
||||
entitlements = entitlements.Concat(_dlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement));
|
||||
if (overrideCatalogItems.Any() || entitlements.Any())
|
||||
{
|
||||
|
@ -44,28 +38,20 @@ internal static class ScreamAPI
|
|||
installForm.UpdateUser("Generating ScreamAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
||||
File.Create(config).Close();
|
||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
||||
WriteConfig(writer,
|
||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
||||
overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value),
|
||||
PlatformIdComparer.String),
|
||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
||||
entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
installForm);
|
||||
WriteConfig(writer, new(overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
new(entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
}
|
||||
else if (File.Exists(config))
|
||||
{
|
||||
File.Delete(config);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
||||
false);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void WriteConfig(StreamWriter writer,
|
||||
SortedList<string, (DlcType type, string name, string icon)> overrideCatalogItems,
|
||||
SortedList<string, (DlcType type, string name, string icon)> entitlements,
|
||||
InstallForm installForm = null)
|
||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideCatalogItems,
|
||||
SortedList<string, (DlcType type, string name, string icon)> entitlements, InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
writer.WriteLine(" \"version\": 2,");
|
||||
|
@ -77,22 +63,18 @@ internal static class ScreamAPI
|
|||
if (overrideCatalogItems.Any())
|
||||
{
|
||||
writer.WriteLine(" \"override\": [");
|
||||
KeyValuePair<string, (DlcType type, string name, string icon)> lastOverrideCatalogItem
|
||||
= overrideCatalogItems.Last();
|
||||
KeyValuePair<string, (DlcType type, string name, string icon)> lastOverrideCatalogItem = overrideCatalogItems.Last();
|
||||
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> 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, 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,");
|
||||
|
@ -106,15 +88,12 @@ 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,
|
||||
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("}");
|
||||
}
|
||||
|
@ -122,8 +101,7 @@ internal static class ScreamAPI
|
|||
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);
|
||||
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||
if (File.Exists(api32_o))
|
||||
{
|
||||
if (File.Exists(api32))
|
||||
|
@ -132,8 +110,7 @@ internal static class ScreamAPI
|
|||
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);
|
||||
installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
|
@ -143,8 +120,7 @@ internal static class ScreamAPI
|
|||
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);
|
||||
installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (deleteConfig && File.Exists(config))
|
||||
{
|
||||
|
@ -153,16 +129,14 @@ internal static class ScreamAPI
|
|||
}
|
||||
});
|
||||
|
||||
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, false);
|
||||
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api32_o))
|
||||
{
|
||||
|
@ -172,8 +146,7 @@ internal static class ScreamAPI
|
|||
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, false);
|
||||
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
|
|
|
@ -11,12 +11,8 @@ 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)
|
||||
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)
|
||||
{
|
||||
api32 = directory + @"\steam_api.dll";
|
||||
api32_o = directory + @"\steam_api_o.dll";
|
||||
|
@ -29,18 +25,15 @@ 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<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc
|
||||
= selection.AllDlc.Except(selection.SelectedDlc);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in
|
||||
selection.ExtraSelectedDlc)
|
||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||
overrideDlc = overrideDlc.Except(extraDlc);
|
||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> injectDlc
|
||||
= new List<KeyValuePair<string, (DlcType type, string name, string icon)>>();
|
||||
if (selection.AllDlc.Count > 64 || selection.ExtraDlc.Any(e => e.dlc.Count > 64))
|
||||
{
|
||||
injectDlc = injectDlc.Concat(selection.SelectedDlc.Where(pair => pair.Value.type is DlcType.SteamHidden));
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in
|
||||
selection.ExtraSelectedDlc)
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||
if (selection.ExtraDlc.Where(e => e.id == id).Single().dlc.Count > 64)
|
||||
injectDlc = injectDlc.Concat(extraDlc.Where(pair => pair.Value.type is DlcType.SteamHidden));
|
||||
}
|
||||
|
@ -50,27 +43,20 @@ internal static class SmokeAPI
|
|||
installForm.UpdateUser("Generating SmokeAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
||||
File.Create(config).Close();
|
||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
||||
WriteConfig(writer,
|
||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
||||
overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
||||
injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
installForm);
|
||||
WriteConfig(writer, new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
}
|
||||
else if (File.Exists(config))
|
||||
{
|
||||
File.Delete(config);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
||||
false);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void WriteConfig(StreamWriter writer,
|
||||
SortedList<string, (DlcType type, string name, string icon)> overrideDlc,
|
||||
SortedList<string, (DlcType type, string name, string icon)> injectDlc,
|
||||
InstallForm installForm = null)
|
||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideDlc,
|
||||
SortedList<string, (DlcType type, string name, string icon)> injectDlc, InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
writer.WriteLine(" \"$version\": 1,");
|
||||
|
@ -86,15 +72,12 @@ 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, 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\": [");
|
||||
|
@ -104,15 +87,12 @@ 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, 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("}");
|
||||
|
@ -125,11 +105,9 @@ internal static class SmokeAPI
|
|||
if (File.Exists(oldConfig))
|
||||
{
|
||||
File.Delete(oldConfig);
|
||||
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}",
|
||||
LogTextBox.Action, 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 string 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_o))
|
||||
{
|
||||
if (File.Exists(api32))
|
||||
|
@ -138,9 +116,7 @@ internal static class SmokeAPI
|
|||
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);
|
||||
installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
|
@ -150,9 +126,7 @@ internal static class SmokeAPI
|
|||
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);
|
||||
installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (deleteConfig && File.Exists(config))
|
||||
{
|
||||
|
@ -166,23 +140,20 @@ internal static class SmokeAPI
|
|||
}
|
||||
});
|
||||
|
||||
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, 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, false);
|
||||
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api32_o))
|
||||
{
|
||||
|
@ -192,8 +163,7 @@ internal static class SmokeAPI
|
|||
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, false);
|
||||
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
|
|
|
@ -11,12 +11,8 @@ 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
|
||||
)
|
||||
internal static void GetUplayR1Components(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,10 +24,8 @@ 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<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc
|
||||
= selection.AllDlc.Except(selection.SelectedDlc);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in
|
||||
selection.ExtraSelectedDlc)
|
||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||
blacklistDlc = blacklistDlc.Except(extraDlc);
|
||||
if (blacklistDlc.Any())
|
||||
{
|
||||
|
@ -39,23 +33,18 @@ 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 SortedList<string, (DlcType type, string name, string icon)>(
|
||||
blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
installForm);
|
||||
WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
}
|
||||
else if (File.Exists(config))
|
||||
{
|
||||
File.Delete(config);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
||||
false);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void WriteConfig(StreamWriter writer,
|
||||
SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||
InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
|
@ -71,46 +60,38 @@ 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, 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);
|
||||
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||
if (File.Exists(api32_o))
|
||||
{
|
||||
if (File.Exists(api32))
|
||||
{
|
||||
File.Delete(api32);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action,
|
||||
false);
|
||||
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);
|
||||
installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
if (File.Exists(api64))
|
||||
{
|
||||
File.Delete(api64);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action,
|
||||
false);
|
||||
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);
|
||||
installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (deleteConfig && File.Exists(config))
|
||||
{
|
||||
|
@ -119,16 +100,14 @@ internal static class UplayR1
|
|||
}
|
||||
});
|
||||
|
||||
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, false);
|
||||
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api32_o))
|
||||
{
|
||||
|
@ -138,8 +117,7 @@ internal static class UplayR1
|
|||
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, false);
|
||||
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
|
|
|
@ -11,12 +11,8 @@ 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)
|
||||
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)
|
||||
{
|
||||
old_api32 = directory + @"\uplay_r2_loader.dll";
|
||||
old_api64 = directory + @"\uplay_r2_loader64.dll";
|
||||
|
@ -30,10 +26,8 @@ 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<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc
|
||||
= selection.AllDlc.Except(selection.SelectedDlc);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in
|
||||
selection.ExtraSelectedDlc)
|
||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||
blacklistDlc = blacklistDlc.Except(extraDlc);
|
||||
if (blacklistDlc.Any())
|
||||
{
|
||||
|
@ -41,23 +35,18 @@ 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 SortedList<string, (DlcType type, string name, string icon)>(
|
||||
blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
installForm);
|
||||
WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
}
|
||||
else if (File.Exists(config))
|
||||
{
|
||||
File.Delete(config);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
||||
false);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void WriteConfig(StreamWriter writer,
|
||||
SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||
InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
|
@ -75,35 +64,30 @@ 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, 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);
|
||||
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))
|
||||
{
|
||||
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);
|
||||
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);
|
||||
installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
|
@ -111,12 +95,10 @@ internal static class UplayR2
|
|||
if (File.Exists(api))
|
||||
{
|
||||
File.Delete(api);
|
||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action,
|
||||
false);
|
||||
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);
|
||||
installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (deleteConfig && File.Exists(config))
|
||||
{
|
||||
|
@ -125,17 +107,16 @@ internal static class UplayR2
|
|||
}
|
||||
});
|
||||
|
||||
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, false);
|
||||
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api32_o))
|
||||
{
|
||||
|
@ -146,8 +127,7 @@ internal static class UplayR2
|
|||
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, false);
|
||||
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
|
|
|
@ -14,8 +14,7 @@ internal static class Diagnostics
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -35,18 +34,13 @@ 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));
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ 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();
|
||||
|
@ -32,15 +32,9 @@ internal static class ExceptionHandler
|
|||
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..])
|
||||
_ = 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));
|
||||
}
|
||||
|
@ -49,14 +43,12 @@ internal static class ExceptionHandler
|
|||
stackDepth++;
|
||||
}
|
||||
using DialogForm dialogForm = new(form ?? Form.ActiveForm);
|
||||
return dialogForm.Show(SystemIcons.Error, output.ToString(), acceptButtonText, cancelButtonText, 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();
|
||||
|
|
|
@ -12,7 +12,7 @@ internal static class HttpClientManager
|
|||
|
||||
internal static void Setup()
|
||||
{
|
||||
HttpClient = new HttpClient();
|
||||
HttpClient = new();
|
||||
HttpClient.DefaultRequestHeaders.Add("User-Agent", $"CI{Program.Version.Replace(".", "")}");
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,7 @@ 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();
|
||||
}
|
||||
|
@ -42,8 +41,7 @@ internal static class HttpClientManager
|
|||
internal static async Task<HtmlNodeCollection> GetDocumentNodes(string url, string xpath)
|
||||
=> (await EnsureGet(url))?.ToHtmlDocument()?.DocumentNode?.SelectNodes(xpath);
|
||||
|
||||
internal static HtmlNodeCollection GetDocumentNodes(this 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<Image> GetImageFromUrl(string url)
|
||||
{
|
||||
|
|
|
@ -6,27 +6,23 @@ namespace CreamInstaller.Utility;
|
|||
|
||||
internal static class IconGrabber
|
||||
{
|
||||
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 Icon ToIcon(this Image image)
|
||||
{
|
||||
using Bitmap dialogIconBitmap = new(image, new Size(image.Width, image.Height));
|
||||
using Bitmap dialogIconBitmap = new(image, new(image.Width, image.Height));
|
||||
return Icon.FromHandle(dialogIconBitmap.GetHicon());
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -18,9 +18,11 @@ internal static class LogTextBox
|
|||
textBox.SelectionStart = textBox.TextLength;
|
||||
textBox.SelectionLength = 0;
|
||||
textBox.SelectionColor = color;
|
||||
if (scroll) textBox.ScrollToCaret();
|
||||
if (scroll)
|
||||
textBox.ScrollToCaret();
|
||||
textBox.AppendText(text);
|
||||
if (scroll) textBox.ScrollToCaret();
|
||||
if (scroll)
|
||||
textBox.ScrollToCaret();
|
||||
textBox.SelectionColor = textBox.ForeColor;
|
||||
textBox.Invalidate();
|
||||
}
|
||||
|
|
|
@ -11,11 +11,9 @@ namespace CreamInstaller.Utility;
|
|||
|
||||
internal static class ProgramData
|
||||
{
|
||||
internal static readonly string DirectoryPathOld
|
||||
= Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\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 DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\CreamInstaller";
|
||||
|
||||
internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo";
|
||||
internal static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt";
|
||||
|
@ -29,19 +27,22 @@ internal static class ProgramData
|
|||
internal static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
||||
internal static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.json";
|
||||
|
||||
internal static async Task Setup() => await Task.Run(() =>
|
||||
internal static async Task Setup()
|
||||
=> await Task.Run(() =>
|
||||
{
|
||||
if (Directory.Exists(DirectoryPathOld))
|
||||
{
|
||||
if (Directory.Exists(DirectoryPath)) Directory.Delete(DirectoryPath, true);
|
||||
if (Directory.Exists(DirectoryPath))
|
||||
Directory.Delete(DirectoryPath, true);
|
||||
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)
|
||||
if (!Directory.Exists(DirectoryPath))
|
||||
_ = Directory.CreateDirectory(DirectoryPath);
|
||||
if (!File.Exists(AppInfoVersionPath) || !Version.TryParse(File.ReadAllText(AppInfoVersionPath, Encoding.UTF8), out Version version)
|
||||
|| version < MinimumAppInfoVersion)
|
||||
{
|
||||
if (Directory.Exists(AppInfoPath)) Directory.Delete(AppInfoPath, true);
|
||||
if (Directory.Exists(AppInfoPath))
|
||||
Directory.Delete(AppInfoPath, true);
|
||||
_ = Directory.CreateDirectory(AppInfoPath);
|
||||
File.WriteAllText(AppInfoVersionPath, Program.Version, Encoding.UTF8);
|
||||
}
|
||||
|
@ -91,16 +92,16 @@ internal static class ProgramData
|
|||
|
||||
internal static List<(Platform platform, string id)> ReadProgramChoices()
|
||||
{
|
||||
if (!File.Exists(ProgramChoicesPath)) return null;
|
||||
if (!File.Exists(ProgramChoicesPath))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath),
|
||||
typeof(List<(Platform platform, string id)>)) as
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath), typeof(List<(Platform platform, string id)>)) as
|
||||
List<(Platform platform, string id)>;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new List<(Platform platform, string id)>();
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,16 +119,16 @@ internal static class ProgramData
|
|||
|
||||
internal static List<(Platform platform, string gameId, string dlcId)> ReadDlcChoices()
|
||||
{
|
||||
if (!File.Exists(DlcChoicesPath)) return null;
|
||||
if (!File.Exists(DlcChoicesPath))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath),
|
||||
typeof(List<(Platform platform, string gameId, string dlcId)>)) as
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath), typeof(List<(Platform platform, string gameId, string dlcId)>)) as
|
||||
List<(Platform platform, string gameId, string dlcId)>;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new List<(Platform platform, string gameId, string dlcId)>();
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,22 +146,20 @@ internal static class ProgramData
|
|||
|
||||
internal static List<(Platform platform, string id, string proxy, bool enabled)> ReadKoaloaderChoices()
|
||||
{
|
||||
if (!File.Exists(KoaloaderProxyChoicesPath)) return null;
|
||||
if (!File.Exists(KoaloaderProxyChoicesPath))
|
||||
return null;
|
||||
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 List<(Platform platform, string id, string proxy, bool enabled)>();
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue