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;
|
OnClickEvent = onClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null)
|
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null) : this(text, onClick)
|
||||||
: this(text, onClick) => _ = TryImageIdentifier(this, imageIdentifier);
|
=> _ = TryImageIdentifier(this, imageIdentifier);
|
||||||
|
|
||||||
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, EventHandler onClick = null)
|
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, EventHandler onClick = null) : this(text, onClick)
|
||||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo);
|
=> _ = TryImageIdentifierInfo(this, imageIdentifierInfo);
|
||||||
|
|
||||||
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo,
|
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, string imageIdentifierFallback, EventHandler onClick = null) :
|
||||||
string imageIdentifierFallback, EventHandler onClick = null)
|
this(text, onClick)
|
||||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo,
|
=> _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifier(this, imageIdentifierFallback));
|
||||||
async () => await TryImageIdentifier(
|
|
||||||
this, imageIdentifierFallback));
|
|
||||||
|
|
||||||
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo,
|
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, (string id, string iconUrl) imageIdentifierInfoFallback,
|
||||||
(string id, string iconUrl) imageIdentifierInfoFallback, EventHandler onClick = null)
|
EventHandler onClick = null) : this(text, onClick)
|
||||||
: this(text, onClick) => _ = TryImageIdentifierInfo(this, imageIdentifierInfo,
|
=> _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifierInfo(this, imageIdentifierInfoFallback));
|
||||||
async () => await TryImageIdentifierInfo(
|
|
||||||
this, imageIdentifierInfoFallback));
|
|
||||||
|
|
||||||
private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier) => await Task.Run(
|
private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier)
|
||||||
async () =>
|
=> await Task.Run(async () =>
|
||||||
{
|
{
|
||||||
if (images.TryGetValue(imageIdentifier, out Image image) && image is not null)
|
if (images.TryGetValue(imageIdentifier, out Image image) && image is not null)
|
||||||
{
|
|
||||||
item.Image = image;
|
item.Image = image;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (imageIdentifier)
|
switch (imageIdentifier)
|
||||||
|
@ -68,28 +62,22 @@ internal class ContextMenuItem : ToolStripMenuItem
|
||||||
image = IconGrabber.GetFileExplorerImage();
|
image = IconGrabber.GetFileExplorerImage();
|
||||||
break;
|
break;
|
||||||
case "SteamDB":
|
case "SteamDB":
|
||||||
image = await HttpClientManager.GetImageFromUrl(
|
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("steamdb.info"));
|
||||||
IconGrabber.GetDomainFaviconUrl("steamdb.info"));
|
|
||||||
break;
|
break;
|
||||||
case "Steam Store":
|
case "Steam Store":
|
||||||
image = await HttpClientManager.GetImageFromUrl(
|
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("store.steampowered.com"));
|
||||||
IconGrabber.GetDomainFaviconUrl("store.steampowered.com"));
|
|
||||||
break;
|
break;
|
||||||
case "Steam Community":
|
case "Steam Community":
|
||||||
image = await HttpClientManager.GetImageFromUrl(
|
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("steamcommunity.com"));
|
||||||
IconGrabber.GetDomainFaviconUrl("steamcommunity.com"));
|
|
||||||
break;
|
break;
|
||||||
case "ScreamDB":
|
case "ScreamDB":
|
||||||
image = await HttpClientManager.GetImageFromUrl(
|
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("scream-db.web.app"));
|
||||||
IconGrabber.GetDomainFaviconUrl("scream-db.web.app"));
|
|
||||||
break;
|
break;
|
||||||
case "Epic Games":
|
case "Epic Games":
|
||||||
image = await HttpClientManager.GetImageFromUrl(
|
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("epicgames.com"));
|
||||||
IconGrabber.GetDomainFaviconUrl("epicgames.com"));
|
|
||||||
break;
|
break;
|
||||||
case "Ubisoft Store":
|
case "Ubisoft Store":
|
||||||
image = await HttpClientManager.GetImageFromUrl(
|
image = await HttpClientManager.GetImageFromUrl(IconGrabber.GetDomainFaviconUrl("store.ubi.com"));
|
||||||
IconGrabber.GetDomainFaviconUrl("store.ubi.com"));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
@ -102,35 +90,31 @@ internal class ContextMenuItem : ToolStripMenuItem
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
private static async Task TryImageIdentifierInfo(ContextMenuItem item,
|
private static async Task TryImageIdentifierInfo(ContextMenuItem item, (string id, string iconUrl) imageIdentifierInfo, Action onFail = null)
|
||||||
(string id, string iconUrl) imageIdentifierInfo,
|
=> await Task.Run(async () =>
|
||||||
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;
|
(string id, string iconUrl) = imageIdentifierInfo;
|
||||||
}
|
string imageIdentifier = "Icon_" + id;
|
||||||
else
|
if (images.TryGetValue(imageIdentifier, out Image image) && image is not null)
|
||||||
{
|
|
||||||
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
|
||||||
if (image is not null)
|
|
||||||
{
|
|
||||||
images[imageIdentifier] = image;
|
|
||||||
item.Image = image;
|
item.Image = image;
|
||||||
}
|
else
|
||||||
else if (onFail is not null)
|
|
||||||
{
|
{
|
||||||
onFail();
|
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
||||||
|
if (image is not null)
|
||||||
|
{
|
||||||
|
images[imageIdentifier] = image;
|
||||||
|
item.Image = image;
|
||||||
|
}
|
||||||
|
else if (onFail is not null)
|
||||||
|
onFail();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
protected override void OnClick(EventArgs e)
|
protected override void OnClick(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnClick(e);
|
base.OnClick(e);
|
||||||
if (OnClickEvent is null) return;
|
if (OnClickEvent is null)
|
||||||
|
return;
|
||||||
OnClickEvent.Invoke(this, e);
|
OnClickEvent.Invoke(this, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -58,46 +58,38 @@ internal class CustomForm : Form
|
||||||
string acidicoala = "https://github.com/acidicoala";
|
string acidicoala = "https://github.com/acidicoala";
|
||||||
string repository = $"https://github.com/{Program.RepositoryOwner}/{Program.RepositoryName}";
|
string repository = $"https://github.com/{Program.RepositoryOwner}/{Program.RepositoryName}";
|
||||||
_ = helpDialog.Show(SystemIcons.Information,
|
_ = 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"
|
"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"
|
+ "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"
|
+ "utilizing the gathered information for the maintenance of DLC unlockers.\n" + "\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 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"
|
||||||
+ $"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"
|
+ "only a DLC Unlocker installer. Should the game you wish to unlock DLC for not already come with the DLCs installed (very many\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"
|
+ "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"
|
||||||
+ "only a DLC Unlocker installer. Should the game you wish to unlock DLC for not already come with the DLCs installed (very many\n"
|
+ "the game(s) you're tinkering with; you'll usually find any answer to your problems there.\n" + "\n" + "USAGE:\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"
|
+ " 1. Choose which programs and/or games the program should scan for DLC.\n"
|
||||||
+ "the game(s) you're tinkering with; you'll usually find any answer to your problems there.\n"
|
+ " The program automatically gathers all installed games from Steam, Epic and Ubisoft directories.\n"
|
||||||
+ "\n"
|
+ " 2. Wait for the program to download and install SteamCMD (if you chose a Steam game).\n"
|
||||||
+ "USAGE:\n"
|
+ " 3. Wait for the program to gather and cache the chosen games' information && DLCs.\n"
|
||||||
+ " 1. Choose which programs and/or games the program should scan for DLC.\n"
|
+ " May take some time on the first run; depends on how many DLCs the games you chose have.\n"
|
||||||
+ " The program automatically gathers all installed games from Steam, Epic and Ubisoft directories.\n"
|
+ " 4. CAREFULLY select which games' DLCs you wish to unlock.\n"
|
||||||
+ " 2. Wait for the program to download and install SteamCMD (if you chose a Steam game).\n"
|
+ " Obviously none of the DLC unlockers are tested for every single game!\n"
|
||||||
+ " 3. Wait for the program to gather and cache the chosen games' information && DLCs.\n"
|
+ " 5. Choose whether or not to install with Koaloader, and if so then also pick the proxy DLL to use.\n"
|
||||||
+ " May take some time on the first run; depends on how many DLCs the games you chose have.\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"
|
||||||
+ " 4. CAREFULLY select which games' DLCs you wish to unlock.\n"
|
+ " 6. Click the \"Generate and Install\" button.\n" + " 7. Click the \"OK\" button to close the program.\n"
|
||||||
+ " Obviously none of the DLC unlockers are tested for every single game!\n"
|
+ " 8. If any of the DLC unlockers cause problems with any of the games you installed them on, simply go back\n"
|
||||||
+ " 5. Choose whether or not to install with Koaloader, and if so then also pick the proxy DLL to use.\n"
|
+ " to step 5 and select what games you wish you revert changes to, and instead click the \"Uninstall\" button this time.\n" + "\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"
|
+ $"For reliable and quick assistance, all bugs, crashes and other issues should be referred to the [GitHub Issues]({repository}/issues) page!\n"
|
||||||
+ " 6. Click the \"Generate and Install\" button.\n"
|
+ "\n" + "SteamCMD installation and appinfo cache can be found at [C:\\ProgramData\\CreamInstaller]().\n"
|
||||||
+ " 7. Click the \"OK\" button to close the program.\n"
|
+ $"The program automatically and very quickly updates from [GitHub]({repository}) using [Onova](https://github.com/Tyrrrz/Onova). (updates can be ignored)\n"
|
||||||
+ " 8. If any of the DLC unlockers cause problems with any of the games you installed them on, simply go back\n"
|
+ $"The program source and other information can be found on [GitHub]({repository}).");
|
||||||
+ " to step 5 and select what games you wish you revert changes to, and instead click the \"Uninstall\" button this time.\n"
|
|
||||||
+ "\n"
|
|
||||||
+ $"For reliable and quick assistance, all bugs, crashes and other issues should be referred to the [GitHub Issues]({repository}/issues) page!\n"
|
|
||||||
+ "\n"
|
|
||||||
+ "SteamCMD installation and appinfo cache can be found at [C:\\ProgramData\\CreamInstaller]().\n"
|
|
||||||
+ $"The program automatically and very quickly updates from [GitHub]({repository}) using [Onova](https://github.com/Tyrrrz/Onova). (updates can be ignored)\n"
|
|
||||||
+ $"The program source and other information can be found on [GitHub]({repository}).");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnActivation(object sender, EventArgs args) => Activate();
|
internal void OnActivation(object sender, EventArgs args) => Activate();
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||||
internal static extern void SetWindowPos(nint hWnd, nint hWndInsertAfter, int x, int y, int cx, int cy,
|
internal static extern void SetWindowPos(nint hWnd, nint hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
|
||||||
uint uFlags);
|
|
||||||
|
|
||||||
internal void BringToFrontWithoutActivation()
|
internal void BringToFrontWithoutActivation()
|
||||||
{
|
{
|
||||||
|
@ -113,12 +105,13 @@ internal class CustomForm : Form
|
||||||
return;
|
return;
|
||||||
int X = fromForm.Location.X + fromForm.Size.Width / 2 - Size.Width / 2;
|
int X = fromForm.Location.X + fromForm.Size.Width / 2 - Size.Width / 2;
|
||||||
int Y = fromForm.Location.Y + fromForm.Size.Height / 2 - Size.Height / 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)
|
private void OnKeyPress(object s, KeyPressEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.KeyChar != 'S') return; // Shift + S
|
if (e.KeyChar != 'S')
|
||||||
|
return; // Shift + S
|
||||||
UpdateBounds();
|
UpdateBounds();
|
||||||
Rectangle bounds = Bounds;
|
Rectangle bounds = Bounds;
|
||||||
using Bitmap bitmap = new(Size.Width - 14, Size.Height - 7);
|
using Bitmap bitmap = new(Size.Width - 14, Size.Height - 7);
|
||||||
|
@ -127,8 +120,7 @@ internal class CustomForm : Form
|
||||||
using EncoderParameters encoding = new(1);
|
using EncoderParameters encoding = new(1);
|
||||||
using EncoderParameter encoderParam = new(Encoder.Quality, 100L);
|
using EncoderParameter encoderParam = new(Encoder.Quality, 100L);
|
||||||
encoding.Param[0] = encoderParam;
|
encoding.Param[0] = encoderParam;
|
||||||
graphics.CopyFromScreen(new Point(bounds.Left + 7, bounds.Top), Point.Empty,
|
graphics.CopyFromScreen(new(bounds.Left + 7, bounds.Top), Point.Empty, new(Size.Width - 14, Size.Height - 7));
|
||||||
new Size(Size.Width - 14, Size.Height - 7));
|
|
||||||
Clipboard.SetImage(bitmap);
|
Clipboard.SetImage(bitmap);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,8 +65,7 @@ internal class CustomTreeView : TreeView
|
||||||
Size size;
|
Size size;
|
||||||
Rectangle bounds = node.Bounds;
|
Rectangle bounds = node.Bounds;
|
||||||
Rectangle selectionBounds = bounds;
|
Rectangle selectionBounds = bounds;
|
||||||
Color
|
Color color; // = highlighted ? SystemColors.HighlightText : (node.ForeColor != Color.Empty) ? node.ForeColor : node.TreeView.ForeColor;
|
||||||
color; // = highlighted ? SystemColors.HighlightText : (node.ForeColor != Color.Empty) ? node.ForeColor : node.TreeView.ForeColor;
|
|
||||||
Point point;
|
Point point;
|
||||||
/*Size textSize = TextRenderer.MeasureText(text, font);
|
/*Size textSize = TextRenderer.MeasureText(text, font);
|
||||||
Point textLoc = new(bounds.X - 1, bounds.Y);
|
Point textLoc = new(bounds.X - 1, bounds.Y);
|
||||||
|
@ -88,8 +87,7 @@ internal class CustomTreeView : TreeView
|
||||||
text = platform.ToString();
|
text = platform.ToString();
|
||||||
size = TextRenderer.MeasureText(graphics, text, font);
|
size = TextRenderer.MeasureText(graphics, text, font);
|
||||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||||
selectionBounds
|
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||||
= new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
|
||||||
graphics.FillRectangle(brush, bounds);
|
graphics.FillRectangle(brush, bounds);
|
||||||
point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1);
|
point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1);
|
||||||
TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default);
|
TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default);
|
||||||
|
@ -104,8 +102,7 @@ internal class CustomTreeView : TreeView
|
||||||
size = TextRenderer.MeasureText(graphics, text, font);
|
size = TextRenderer.MeasureText(graphics, text, font);
|
||||||
int left = -4;
|
int left = -4;
|
||||||
bounds = bounds with { X = bounds.X + bounds.Width + left, Width = size.Width };
|
bounds = bounds with { X = bounds.X + bounds.Width + left, Width = size.Width };
|
||||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
||||||
selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
|
||||||
graphics.FillRectangle(brush, bounds);
|
graphics.FillRectangle(brush, bounds);
|
||||||
point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1);
|
point = new Point(bounds.Location.X - 1, bounds.Location.Y + 1);
|
||||||
TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default);
|
TextRenderer.DrawText(graphics, text, font, point, color, TextFormatFlags.Default);
|
||||||
|
@ -130,8 +127,7 @@ internal class CustomTreeView : TreeView
|
||||||
: CheckBoxState.UncheckedDisabled;
|
: CheckBoxState.UncheckedDisabled;
|
||||||
size = CheckBoxRenderer.GetGlyphSize(graphics, checkBoxState);
|
size = CheckBoxRenderer.GetGlyphSize(graphics, checkBoxState);
|
||||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||||
selectionBounds.Size + bounds.Size with { Height = 0 });
|
|
||||||
Rectangle checkBoxBounds = bounds;
|
Rectangle checkBoxBounds = bounds;
|
||||||
graphics.FillRectangle(backBrush, bounds);
|
graphics.FillRectangle(backBrush, bounds);
|
||||||
point = new Point(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1);
|
point = new Point(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1);
|
||||||
|
@ -140,41 +136,31 @@ internal class CustomTreeView : TreeView
|
||||||
size = TextRenderer.MeasureText(graphics, text, font);
|
size = TextRenderer.MeasureText(graphics, text, font);
|
||||||
int left = 1;
|
int left = 1;
|
||||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width + left };
|
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width + left };
|
||||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||||
selectionBounds.Size + bounds.Size with { Height = 0 });
|
checkBoxBounds = new Rectangle(checkBoxBounds.Location, checkBoxBounds.Size + bounds.Size with { Height = 0 });
|
||||||
checkBoxBounds = new Rectangle(checkBoxBounds.Location,
|
|
||||||
checkBoxBounds.Size + bounds.Size with { Height = 0 });
|
|
||||||
graphics.FillRectangle(backBrush, bounds);
|
graphics.FillRectangle(backBrush, bounds);
|
||||||
point = new Point(bounds.Location.X - 1 + left, bounds.Location.Y + 1);
|
point = new Point(bounds.Location.X - 1 + left, bounds.Location.Y + 1);
|
||||||
TextRenderer.DrawText(graphics, text, font, point,
|
TextRenderer.DrawText(graphics, text, font, point, Enabled ? ColorTranslator.FromHtml("#006900") : ColorTranslator.FromHtml("#69AA69"),
|
||||||
Enabled
|
TextFormatFlags.Default);
|
||||||
? ColorTranslator.FromHtml("#006900")
|
|
||||||
: ColorTranslator.FromHtml("#69AA69"),
|
|
||||||
TextFormatFlags.Default);
|
|
||||||
this.checkBoxBounds[selection] = RectangleToClient(checkBoxBounds);
|
this.checkBoxBounds[selection] = RectangleToClient(checkBoxBounds);
|
||||||
string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy;
|
string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy;
|
||||||
if (selection.Koaloader && proxy is not null)
|
if (selection.Koaloader && proxy is not null)
|
||||||
{
|
{
|
||||||
comboBoxFont ??= new Font(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet,
|
comboBoxFont ??= new Font(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, font.GdiVerticalFont);
|
||||||
font.GdiVerticalFont);
|
|
||||||
ComboBoxState comboBoxState = Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled;
|
ComboBoxState comboBoxState = Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled;
|
||||||
text = proxy + ".dll";
|
text = proxy + ".dll";
|
||||||
size = TextRenderer.MeasureText(graphics, text, comboBoxFont) + new Size(6, 0);
|
size = TextRenderer.MeasureText(graphics, text, comboBoxFont) + new Size(6, 0);
|
||||||
int padding = 2;
|
int padding = 2;
|
||||||
bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width,
|
bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding);
|
||||||
bounds.Height - padding);
|
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 comboBoxBounds = bounds;
|
Rectangle comboBoxBounds = bounds;
|
||||||
graphics.FillRectangle(backBrush, bounds);
|
graphics.FillRectangle(backBrush, bounds);
|
||||||
ComboBoxRenderer.DrawTextBox(graphics, bounds, text, comboBoxFont, comboBoxState);
|
ComboBoxRenderer.DrawTextBox(graphics, bounds, text, comboBoxFont, comboBoxState);
|
||||||
size = new Size(14, 0);
|
size = new Size(14, 0);
|
||||||
left = -1;
|
left = -1;
|
||||||
bounds = bounds with { X = bounds.X + bounds.Width + left, Width = size.Width };
|
bounds = bounds with { X = bounds.X + bounds.Width + left, Width = size.Width };
|
||||||
selectionBounds = new Rectangle(selectionBounds.Location,
|
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
||||||
selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
comboBoxBounds = new Rectangle(comboBoxBounds.Location, comboBoxBounds.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);
|
ComboBoxRenderer.DrawDropDownButton(graphics, bounds, comboBoxState);
|
||||||
this.comboBoxBounds[selection] = RectangleToClient(comboBoxBounds);
|
this.comboBoxBounds[selection] = RectangleToClient(comboBoxBounds);
|
||||||
}
|
}
|
||||||
|
@ -215,13 +201,11 @@ internal class CustomTreeView : TreeView
|
||||||
}
|
}
|
||||||
else if (pair.Value.Contains(clickPoint))
|
else if (pair.Value.Contains(clickPoint))
|
||||||
{
|
{
|
||||||
List<string> proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader"))
|
List<string> proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")).Select(p =>
|
||||||
.Select(p =>
|
{
|
||||||
{
|
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
|
||||||
p.GetProxyInfoFromIdentifier(
|
return proxyName;
|
||||||
out string proxyName, out _);
|
}).Distinct().ToList();
|
||||||
return proxyName;
|
|
||||||
}).Distinct().ToList();
|
|
||||||
comboBoxDropDown ??= new ToolStripDropDown();
|
comboBoxDropDown ??= new ToolStripDropDown();
|
||||||
comboBoxDropDown.ShowItemToolTips = false;
|
comboBoxDropDown.ShowItemToolTips = false;
|
||||||
comboBoxDropDown.Items.Clear();
|
comboBoxDropDown.Items.Clear();
|
||||||
|
@ -240,8 +224,7 @@ internal class CustomTreeView : TreeView
|
||||||
if (canUse)
|
if (canUse)
|
||||||
_ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (s, e) =>
|
_ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (s, e) =>
|
||||||
{
|
{
|
||||||
pair.Key.KoaloaderProxy
|
pair.Key.KoaloaderProxy = proxy == ProgramSelection.DefaultKoaloaderProxy ? null : proxy;
|
||||||
= proxy == ProgramSelection.DefaultKoaloaderProxy ? null : proxy;
|
|
||||||
selectForm.OnKoaloaderChanged();
|
selectForm.OnKoaloaderChanged();
|
||||||
}) { Font = comboBoxFont });
|
}) { Font = comboBoxFont });
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,16 @@ internal static class PlatformIdComparer
|
||||||
private static NodeNameComparer nodeNameComparer;
|
private static NodeNameComparer nodeNameComparer;
|
||||||
|
|
||||||
private static NodeTextComparer nodeTextComparer;
|
private static NodeTextComparer nodeTextComparer;
|
||||||
internal static StringComparer String => stringComparer ??= new StringComparer();
|
internal static StringComparer String => stringComparer ??= new();
|
||||||
internal static NodeComparer Node => nodeComparer ??= new NodeComparer();
|
internal static NodeComparer Node => nodeComparer ??= new();
|
||||||
internal static NodeNameComparer NodeName => nodeNameComparer ??= new NodeNameComparer();
|
internal static NodeNameComparer NodeName => nodeNameComparer ??= new();
|
||||||
internal static NodeTextComparer NodeText => nodeTextComparer ??= new NodeTextComparer();
|
internal static NodeTextComparer NodeText => nodeTextComparer ??= new();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class StringComparer : IComparer<string>
|
internal class StringComparer : IComparer<string>
|
||||||
{
|
{
|
||||||
public int Compare(string a, string b) =>
|
public int Compare(string a, string b)
|
||||||
!int.TryParse(a, out _) && !int.TryParse(b, out _)
|
=> !int.TryParse(a, out _) && !int.TryParse(b, out _)
|
||||||
? string.Compare(a, b, StringComparison.Ordinal)
|
? string.Compare(a, b, StringComparison.Ordinal)
|
||||||
: !int.TryParse(a, out int A)
|
: !int.TryParse(a, out int A)
|
||||||
? 1
|
? 1
|
||||||
|
@ -38,8 +38,8 @@ internal class StringComparer : IComparer<string>
|
||||||
|
|
||||||
internal class NodeComparer : IComparer<TreeNode>
|
internal class NodeComparer : IComparer<TreeNode>
|
||||||
{
|
{
|
||||||
public int Compare(TreeNode a, TreeNode b) =>
|
public int Compare(TreeNode a, TreeNode b)
|
||||||
a.Tag is not Platform A
|
=> a.Tag is not Platform A
|
||||||
? 1
|
? 1
|
||||||
: b.Tag is not Platform B
|
: b.Tag is not Platform B
|
||||||
? -1
|
? -1
|
||||||
|
@ -52,8 +52,8 @@ internal class NodeComparer : IComparer<TreeNode>
|
||||||
|
|
||||||
internal class NodeNameComparer : IComparer
|
internal class NodeNameComparer : IComparer
|
||||||
{
|
{
|
||||||
public int Compare(object a, object b) =>
|
public int Compare(object a, object b)
|
||||||
a is not TreeNode A
|
=> a is not TreeNode A
|
||||||
? 1
|
? 1
|
||||||
: b is not TreeNode B
|
: b is not TreeNode B
|
||||||
? -1
|
? -1
|
||||||
|
@ -64,8 +64,8 @@ internal class NodeNameComparer : IComparer
|
||||||
|
|
||||||
internal class NodeTextComparer : IComparer
|
internal class NodeTextComparer : IComparer
|
||||||
{
|
{
|
||||||
public int Compare(object a, object b) =>
|
public int Compare(object a, object b)
|
||||||
a is not TreeNode A
|
=> a is not TreeNode A
|
||||||
? 1
|
? 1
|
||||||
: b is not TreeNode B
|
: b is not TreeNode B
|
||||||
? -1
|
? -1
|
||||||
|
|
|
@ -24,7 +24,7 @@ internal partial class DebugForm : CustomForm
|
||||||
{
|
{
|
||||||
if (current is not null && (current.Disposing || current.IsDisposed))
|
if (current is not null && (current.Disposing || current.IsDisposed))
|
||||||
current = null;
|
current = null;
|
||||||
return current ??= new DebugForm();
|
return current ??= new();
|
||||||
}
|
}
|
||||||
set => current = value;
|
set => current = value;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ internal partial class DebugForm : CustomForm
|
||||||
if (attachedForm is not null && attachedForm.Visible)
|
if (attachedForm is not null && attachedForm.Visible)
|
||||||
{
|
{
|
||||||
//Size = new(Size.Width, attachedForm.Size.Height);
|
//Size = new(Size.Width, attachedForm.Size.Height);
|
||||||
Location = new Point(attachedForm.Right, attachedForm.Top);
|
Location = new(attachedForm.Right, attachedForm.Top);
|
||||||
BringToFrontWithoutActivation();
|
BringToFrontWithoutActivation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ internal partial class DialogForm : CustomForm
|
||||||
{
|
{
|
||||||
internal DialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
internal DialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
||||||
|
|
||||||
internal DialogResult Show(Icon descriptionIcon, string descriptionText, string acceptButtonText = "OK",
|
internal DialogResult Show(Icon descriptionIcon, string descriptionText, string acceptButtonText = "OK", string cancelButtonText = null,
|
||||||
string cancelButtonText = null, string customFormText = null, Icon customFormIcon = null)
|
string customFormText = null, Icon customFormIcon = null)
|
||||||
{
|
{
|
||||||
descriptionIcon ??= Icon;
|
descriptionIcon ??= Icon;
|
||||||
icon.Image = descriptionIcon.ToBitmap();
|
icon.Image = descriptionIcon.ToBitmap();
|
||||||
|
@ -32,7 +32,7 @@ internal partial class DialogForm : CustomForm
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
if (string.IsNullOrWhiteSpace(link))
|
||||||
link = text;
|
link = text;
|
||||||
descriptionText = descriptionText.Remove(i, linkRight + 1 - i).Insert(i, 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;
|
descriptionLabel.Text = descriptionText;
|
||||||
|
@ -43,13 +43,9 @@ internal partial class DialogForm : CustomForm
|
||||||
cancelButton.Visible = false;
|
cancelButton.Visible = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
cancelButton.Text = cancelButtonText;
|
cancelButton.Text = cancelButtonText;
|
||||||
}
|
|
||||||
if (customFormText is not null)
|
if (customFormText is not null)
|
||||||
{
|
|
||||||
Text = customFormText;
|
Text = customFormText;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OnResize(null, null);
|
OnResize(null, null);
|
||||||
|
@ -61,16 +57,13 @@ internal partial class DialogForm : CustomForm
|
||||||
{
|
{
|
||||||
foreach (LinkLabel.Link link in links)
|
foreach (LinkLabel.Link link in links)
|
||||||
_ = descriptionLabel.Links.Add(link);
|
_ = descriptionLabel.Links.Add(link);
|
||||||
descriptionLabel.LinkClicked += (s, e)
|
descriptionLabel.LinkClicked += (s, e) => Process.Start(new ProcessStartInfo((string)e.Link.LinkData) { UseShellExecute = true });
|
||||||
=> Process.Start(new ProcessStartInfo((string)e.Link.LinkData) { UseShellExecute = true });
|
|
||||||
}
|
}
|
||||||
return ShowDialog();
|
return ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResize(object s, EventArgs e) =>
|
private void OnResize(object s, EventArgs e)
|
||||||
Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100
|
=> Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100
|
||||||
? TextRenderer.MeasureText(Program.ApplicationNameShort, Font).Width > Size.Width - 100
|
? TextRenderer.MeasureText(Program.ApplicationNameShort, Font).Width > Size.Width - 100 ? Program.Name : Program.ApplicationNameShort
|
||||||
? Program.Name
|
|
||||||
: Program.ApplicationNameShort
|
|
||||||
: Program.ApplicationName;
|
: Program.ApplicationName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,18 +38,21 @@ internal partial class InstallForm : CustomForm
|
||||||
userProgressBar.Invoke(() =>
|
userProgressBar.Invoke(() =>
|
||||||
{
|
{
|
||||||
int value = (int)((float)CompleteOperationsCount / OperationsCount * 100) + progress / OperationsCount;
|
int value = (int)((float)CompleteOperationsCount / OperationsCount * 100) + progress / OperationsCount;
|
||||||
if (value < userProgressBar.Value) return;
|
if (value < userProgressBar.Value)
|
||||||
|
return;
|
||||||
userProgressBar.Value = value;
|
userProgressBar.Value = value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateUser(string text, Color color, bool info = true, bool log = true)
|
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)
|
if (log && !logTextBox.Disposing && !logTextBox.IsDisposed)
|
||||||
logTextBox.Invoke(() =>
|
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.AppendText(text, color);
|
||||||
logTextBox.Invalidate();
|
logTextBox.Invalidate();
|
||||||
});
|
});
|
||||||
|
@ -63,12 +66,11 @@ internal partial class InstallForm : CustomForm
|
||||||
UpdateUser("Repairing Paradox Launcher . . . ", LogTextBox.Operation);
|
UpdateUser("Repairing Paradox Launcher . . . ", LogTextBox.Operation);
|
||||||
_ = await Repair(this, selection);
|
_ = await Repair(this, selection);
|
||||||
}
|
}
|
||||||
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")}" +
|
UpdateUser(
|
||||||
$" {(Uninstalling ? "from" : "for")} " + selection.Name
|
$"{(Uninstalling ? "Uninstalling" : "Installing")}" + $" {(Uninstalling ? "from" : "for")} " + selection.Name
|
||||||
+ $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation);
|
+ $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation);
|
||||||
IEnumerable<string> invalidDirectories = (await selection.RootDirectory.GetExecutables())
|
IEnumerable<string> invalidDirectories = (await selection.RootDirectory.GetExecutables())
|
||||||
?.Where(d => !selection.ExecutableDirectories.Any(
|
?.Where(d => !selection.ExecutableDirectories.Any(s => s.directory == Path.GetDirectoryName(d.path)))
|
||||||
s => s.directory == Path.GetDirectoryName(d.path)))
|
|
||||||
?.Select(d => Path.GetDirectoryName(d.path));
|
?.Select(d => Path.GetDirectoryName(d.path));
|
||||||
if (!selection.ExecutableDirectories.Any(s => s.directory == selection.RootDirectory))
|
if (!selection.ExecutableDirectories.Any(s => s.directory == selection.RootDirectory))
|
||||||
invalidDirectories = invalidDirectories?.Append(selection.RootDirectory);
|
invalidDirectories = invalidDirectories?.Append(selection.RootDirectory);
|
||||||
|
@ -76,16 +78,13 @@ internal partial class InstallForm : CustomForm
|
||||||
if (invalidDirectories is not null)
|
if (invalidDirectories is not null)
|
||||||
foreach (string directory in invalidDirectories)
|
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);
|
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
|
||||||
if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|
if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|
||||||
|| (directory != selection.RootDirectory
|
|| directory != selection.RootDirectory && 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
|
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
+ $" in incorrect directory \"{directory}\" . . . ",
|
|
||||||
LogTextBox.Operation);
|
|
||||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||||
}
|
}
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
|
@ -93,15 +92,13 @@ internal partial class InstallForm : CustomForm
|
||||||
if (Uninstalling || !selection.Koaloader)
|
if (Uninstalling || !selection.Koaloader)
|
||||||
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
|
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);
|
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
|
||||||
if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|
if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|
||||||
|| Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll))
|
|| Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) || File.Exists(config))
|
||||||
|| File.Exists(config))
|
|
||||||
{
|
{
|
||||||
UpdateUser(
|
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
"Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ",
|
|
||||||
LogTextBox.Operation);
|
|
||||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||||
}
|
}
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
|
@ -110,18 +107,19 @@ internal partial class InstallForm : CustomForm
|
||||||
int count = selection.DllDirectories.Count, cur = 0;
|
int count = selection.DllDirectories.Count, cur = 0;
|
||||||
foreach (string directory in selection.DllDirectories)
|
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)
|
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
||||||
{
|
{
|
||||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64,
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
|
||||||
out string api64_o, out string config, out string cache);
|
out string cache);
|
||||||
if (uninstallProxy
|
if (uninstallProxy
|
||||||
? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)
|
? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)
|
||||||
: File.Exists(api32) || File.Exists(api64))
|
: File.Exists(api32) || File.Exists(api64))
|
||||||
{
|
{
|
||||||
UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" +
|
UpdateUser(
|
||||||
$" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
$"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
||||||
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
if (uninstallProxy)
|
if (uninstallProxy)
|
||||||
await SmokeAPI.Uninstall(directory, this);
|
await SmokeAPI.Uninstall(directory, this);
|
||||||
else
|
else
|
||||||
|
@ -130,15 +128,12 @@ internal partial class InstallForm : CustomForm
|
||||||
}
|
}
|
||||||
if (selection.Platform is Platform.Epic or Platform.Paradox)
|
if (selection.Platform is Platform.Epic or Platform.Paradox)
|
||||||
{
|
{
|
||||||
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64,
|
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
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))
|
||||||
if (uninstallProxy
|
|
||||||
? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config)
|
|
||||||
: File.Exists(api32) || File.Exists(api64))
|
|
||||||
{
|
{
|
||||||
UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" +
|
UpdateUser(
|
||||||
$" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
$"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
||||||
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
if (uninstallProxy)
|
if (uninstallProxy)
|
||||||
await ScreamAPI.Uninstall(directory, this);
|
await ScreamAPI.Uninstall(directory, this);
|
||||||
else
|
else
|
||||||
|
@ -147,29 +142,25 @@ internal partial class InstallForm : CustomForm
|
||||||
}
|
}
|
||||||
if (selection.Platform is Platform.Ubisoft)
|
if (selection.Platform is Platform.Ubisoft)
|
||||||
{
|
{
|
||||||
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64,
|
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
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))
|
||||||
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" +
|
UpdateUser(
|
||||||
$" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
||||||
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
if (uninstallProxy)
|
if (uninstallProxy)
|
||||||
await UplayR1.Uninstall(directory, this);
|
await UplayR1.Uninstall(directory, this);
|
||||||
else
|
else
|
||||||
await UplayR1.Install(directory, selection, this);
|
await UplayR1.Install(directory, selection, this);
|
||||||
}
|
}
|
||||||
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o,
|
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config);
|
||||||
out api64, out api64_o, out config);
|
|
||||||
if (uninstallProxy
|
if (uninstallProxy
|
||||||
? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config)
|
? 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))
|
: File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api64))
|
||||||
{
|
{
|
||||||
UpdateUser($"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" +
|
UpdateUser(
|
||||||
$" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
|
||||||
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
if (uninstallProxy)
|
if (uninstallProxy)
|
||||||
await UplayR2.Uninstall(directory, this);
|
await UplayR2.Uninstall(directory, this);
|
||||||
else
|
else
|
||||||
|
@ -182,9 +173,9 @@ internal partial class InstallForm : CustomForm
|
||||||
if (selection.Koaloader && !Uninstalling)
|
if (selection.Koaloader && !Uninstalling)
|
||||||
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
|
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
|
||||||
{
|
{
|
||||||
if (Program.Canceled) throw new CustomMessageException("The operation was canceled.");
|
if (Program.Canceled)
|
||||||
UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ",
|
throw new CustomMessageException("The operation was canceled.");
|
||||||
LogTextBox.Operation);
|
UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
await Koaloader.Install(directory, binaryType, selection, selection.RootDirectory, this);
|
await Koaloader.Install(directory, binaryType, selection, selection.RootDirectory, this);
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
|
@ -236,13 +227,12 @@ internal partial class InstallForm : CustomForm
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Operate();
|
await Operate();
|
||||||
UpdateUser($"DLC unlocker(s) successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for "
|
UpdateUser($"DLC unlocker(s) successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + ProgramCount + " program(s).",
|
||||||
+ ProgramCount + " program(s).", LogTextBox.Success);
|
LogTextBox.Success);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
UpdateUser($"DLC unlocker {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: "
|
UpdateUser($"DLC unlocker {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception, LogTextBox.Error);
|
||||||
+ exception, LogTextBox.Error);
|
|
||||||
retryButton.Enabled = true;
|
retryButton.Enabled = true;
|
||||||
}
|
}
|
||||||
userProgressBar.Value = userProgressBar.Maximum;
|
userProgressBar.Value = userProgressBar.Maximum;
|
||||||
|
@ -262,7 +252,8 @@ internal partial class InstallForm : CustomForm
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (e.HandleException(this)) goto retry;
|
if (e.HandleException(this))
|
||||||
|
goto retry;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,24 +58,18 @@ internal partial class MainForm : CustomForm
|
||||||
updateButton.Click -= OnUpdateCancel;
|
updateButton.Click -= OnUpdateCancel;
|
||||||
progressLabel.Text = "Checking for updates . . .";
|
progressLabel.Text = "Checking for updates . . .";
|
||||||
changelogTreeView.Visible = false;
|
changelogTreeView.Visible = false;
|
||||||
changelogTreeView.Location = progressLabel.Location with
|
changelogTreeView.Location = progressLabel.Location with { Y = progressLabel.Location.Y + progressLabel.Size.Height + 13 };
|
||||||
{
|
|
||||||
Y = progressLabel.Location.Y + progressLabel.Size.Height + 13
|
|
||||||
};
|
|
||||||
Refresh();
|
Refresh();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugForm.Current.Attach(this);
|
DebugForm.Current.Attach(this);
|
||||||
#endif
|
#endif
|
||||||
GithubPackageResolver resolver = new(Program.RepositoryOwner, Program.RepositoryName,
|
GithubPackageResolver resolver = new(Program.RepositoryOwner, Program.RepositoryName, Program.RepositoryPackage);
|
||||||
Program.RepositoryPackage);
|
|
||||||
ZipPackageExtractor extractor = new();
|
ZipPackageExtractor extractor = new();
|
||||||
updateManager
|
updateManager = new(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath), resolver, extractor);
|
||||||
= new UpdateManager(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath),
|
|
||||||
resolver, extractor);
|
|
||||||
if (latestVersion is null)
|
if (latestVersion is null)
|
||||||
{
|
{
|
||||||
CheckForUpdatesResult checkForUpdatesResult = null;
|
CheckForUpdatesResult checkForUpdatesResult = null;
|
||||||
cancellationTokenSource = new CancellationTokenSource();
|
cancellationTokenSource = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token);
|
checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token);
|
||||||
|
@ -93,8 +87,7 @@ internal partial class MainForm : CustomForm
|
||||||
catch (TaskCanceledException) { }
|
catch (TaskCanceledException) { }
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
DebugForm.Current.Log($"Exception while checking for updates: {e.GetType()} ({e.Message})",
|
DebugForm.Current.Log($"Exception while checking for updates: {e.GetType()} ({e.Message})", LogTextBox.Warning);
|
||||||
LogTextBox.Warning);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
catch { }
|
catch { }
|
||||||
|
@ -120,8 +113,7 @@ internal partial class MainForm : CustomForm
|
||||||
changelogTreeView.Visible = true;
|
changelogTreeView.Visible = true;
|
||||||
Version currentVersion = new(Program.Version);
|
Version currentVersion = new(Program.Version);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
foreach (Version version in versions.Where(v => (v > currentVersion || v == latestVersion)
|
foreach (Version version in versions.Where(v => (v > currentVersion || v == latestVersion) && !changelogTreeView.Nodes.ContainsKey(v.ToString())))
|
||||||
&& !changelogTreeView.Nodes.ContainsKey(v.ToString())))
|
|
||||||
#else
|
#else
|
||||||
foreach (Version version in versions.Where(v => v > currentVersion && !changelogTreeView.Nodes.ContainsKey(v.ToString())))
|
foreach (Version version in versions.Where(v => v > currentVersion && !changelogTreeView.Nodes.ContainsKey(v.ToString())))
|
||||||
#endif
|
#endif
|
||||||
|
@ -162,9 +154,8 @@ internal partial class MainForm : CustomForm
|
||||||
{
|
{
|
||||||
using DialogForm form = new(this);
|
using DialogForm form = new(this);
|
||||||
if (form.Show(SystemIcons.Warning,
|
if (form.Show(SystemIcons.Warning,
|
||||||
"WARNING: " + Program.ApplicationExecutable + " was renamed!" +
|
"WARNING: " + Program.ApplicationExecutable + " was renamed!" + "\n\nThis will cause undesirable behavior when updating the program!",
|
||||||
"\n\nThis will cause undesirable behavior when updating the program!",
|
"Ignore", "Abort") == DialogResult.Cancel)
|
||||||
"Ignore", "Abort") == DialogResult.Cancel)
|
|
||||||
{
|
{
|
||||||
Application.Exit();
|
Application.Exit();
|
||||||
return;
|
return;
|
||||||
|
@ -174,7 +165,8 @@ internal partial class MainForm : CustomForm
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (e.HandleException(this)) goto retry;
|
if (e.HandleException(this))
|
||||||
|
goto retry;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,8 +180,7 @@ internal partial class MainForm : CustomForm
|
||||||
updateButton.Text = "Cancel";
|
updateButton.Text = "Cancel";
|
||||||
updateButton.Click -= OnUpdate;
|
updateButton.Click -= OnUpdate;
|
||||||
updateButton.Click += OnUpdateCancel;
|
updateButton.Click += OnUpdateCancel;
|
||||||
changelogTreeView.Location
|
changelogTreeView.Location = progressBar.Location with { Y = progressBar.Location.Y + progressBar.Size.Height + 6 };
|
||||||
= progressBar.Location with { Y = progressBar.Location.Y + progressBar.Size.Height + 6 };
|
|
||||||
Refresh();
|
Refresh();
|
||||||
Progress<double> progress = new();
|
Progress<double> progress = new();
|
||||||
progress.ProgressChanged += delegate(object sender, double _progress)
|
progress.ProgressChanged += delegate(object sender, double _progress)
|
||||||
|
@ -198,7 +189,7 @@ internal partial class MainForm : CustomForm
|
||||||
progressBar.Value = (int)_progress;
|
progressBar.Value = (int)_progress;
|
||||||
};
|
};
|
||||||
progressLabel.Text = "Updating . . . ";
|
progressLabel.Text = "Updating . . . ";
|
||||||
cancellationTokenSource = new CancellationTokenSource();
|
cancellationTokenSource = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await updateManager.PrepareUpdateAsync(latestVersion, progress, cancellationTokenSource.Token);
|
await updateManager.PrepareUpdateAsync(latestVersion, progress, cancellationTokenSource.Token);
|
||||||
|
@ -207,8 +198,7 @@ internal partial class MainForm : CustomForm
|
||||||
catch (TaskCanceledException) { }
|
catch (TaskCanceledException) { }
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
DebugForm.Current.Log($"Exception while preparing update: {ex.GetType()} ({ex.Message})",
|
DebugForm.Current.Log($"Exception while preparing update: {ex.GetType()} ({ex.Message})", LogTextBox.Warning);
|
||||||
LogTextBox.Warning);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
catch { }
|
catch { }
|
||||||
|
|
|
@ -12,10 +12,11 @@ internal partial class SelectDialogForm : CustomForm
|
||||||
private readonly List<(Platform platform, string id, string name)> selected = new();
|
private readonly List<(Platform platform, string id, string name)> selected = new();
|
||||||
internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
||||||
|
|
||||||
internal List<(Platform platform, string id, string name)> QueryUser(
|
internal List<(Platform platform, string id, string name)> QueryUser(string groupBoxText,
|
||||||
string groupBoxText, List<(Platform platform, string id, string name, bool alreadySelected)> choices)
|
List<(Platform platform, string id, string name, bool alreadySelected)> choices)
|
||||||
{
|
{
|
||||||
if (!choices.Any()) return null;
|
if (!choices.Any())
|
||||||
|
return null;
|
||||||
groupBox.Text = groupBoxText;
|
groupBox.Text = groupBoxText;
|
||||||
allCheckBox.Enabled = false;
|
allCheckBox.Enabled = false;
|
||||||
acceptButton.Enabled = false;
|
acceptButton.Enabled = false;
|
||||||
|
@ -26,7 +27,8 @@ internal partial class SelectDialogForm : CustomForm
|
||||||
OnTreeNodeChecked(node);
|
OnTreeNodeChecked(node);
|
||||||
_ = selectionTreeView.Nodes.Add(node);
|
_ = selectionTreeView.Nodes.Add(node);
|
||||||
}
|
}
|
||||||
if (!selected.Any()) OnLoad(null, null);
|
if (!selected.Any())
|
||||||
|
OnLoad(null, null);
|
||||||
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
|
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
|
||||||
allCheckBox.Checked = selectionTreeView.Nodes.Cast<TreeNode>().All(n => n.Checked);
|
allCheckBox.Checked = selectionTreeView.Nodes.Cast<TreeNode>().All(n => n.Checked);
|
||||||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||||
|
@ -59,13 +61,11 @@ internal partial class SelectDialogForm : CustomForm
|
||||||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResize(object s, EventArgs e) =>
|
private void OnResize(object s, EventArgs e)
|
||||||
Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100
|
=> Text = TextRenderer.MeasureText(Program.ApplicationName, Font).Width > Size.Width - 100 ? Program.ApplicationNameShort : Program.ApplicationName;
|
||||||
? Program.ApplicationNameShort
|
|
||||||
: Program.ApplicationName;
|
|
||||||
|
|
||||||
private void OnSortCheckBoxChanged(object sender, EventArgs e) => selectionTreeView.TreeViewNodeSorter
|
private void OnSortCheckBoxChanged(object sender, EventArgs e)
|
||||||
= sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
=> selectionTreeView.TreeViewNodeSorter = sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
||||||
|
|
||||||
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
@ -85,7 +85,8 @@ internal partial class SelectDialogForm : CustomForm
|
||||||
private void OnLoad(object sender, EventArgs e)
|
private void OnLoad(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
List<(Platform platform, string id)> choices = ProgramData.ReadProgramChoices();
|
List<(Platform platform, string id)> choices = ProgramData.ReadProgramChoices();
|
||||||
if (choices is null) return;
|
if (choices is null)
|
||||||
|
return;
|
||||||
foreach (TreeNode node in selectionTreeView.Nodes)
|
foreach (TreeNode node in selectionTreeView.Nodes)
|
||||||
{
|
{
|
||||||
node.Checked = choices.Any(n => n.platform == (Platform)node.Tag && n.id == node.Name);
|
node.Checked = choices.Any(n => n.platform == (Platform)node.Tag && n.id == node.Name);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,48 +17,41 @@ internal static class EpicLibrary
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
epicManifestsPath
|
epicManifestsPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Epic Games\EOS", "ModSdkMetadataDir", null) as string;
|
||||||
??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Epic Games\EOS", "ModSdkMetadataDir",
|
epicManifestsPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Wow6432Node\Epic Games\EOS", "ModSdkMetadataDir", null) as string;
|
||||||
null) as string;
|
epicManifestsPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Epic Games\EpicGamesLauncher", "AppDataPath", null) as string;
|
||||||
epicManifestsPath
|
epicManifestsPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Epic Games\EpicGamesLauncher", "AppDataPath", null) as string;
|
||||||
??= 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"))
|
if (epicManifestsPath is not null && epicManifestsPath.EndsWith(@"\Data"))
|
||||||
epicManifestsPath += @"\Manifests";
|
epicManifestsPath += @"\Manifests";
|
||||||
return epicManifestsPath.BeautifyPath();
|
return epicManifestsPath.BeautifyPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||||
string gameDirectory) =>
|
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||||
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;
|
|
||||||
foreach (string file in Directory.EnumerateFiles(manifests, "*.item"))
|
|
||||||
{
|
{
|
||||||
if (Program.Canceled) return games;
|
List<Manifest> games = new();
|
||||||
string json = File.ReadAllText(file);
|
string manifests = EpicManifestsPath;
|
||||||
try
|
if (!Directory.Exists(manifests))
|
||||||
|
return games;
|
||||||
|
foreach (string file in Directory.EnumerateFiles(manifests, "*.item"))
|
||||||
{
|
{
|
||||||
Manifest manifest = JsonSerializer.Deserialize<Manifest>(json);
|
if (Program.Canceled)
|
||||||
if (manifest is not null && manifest.CatalogItemId == manifest.MainGameCatalogItemId
|
return games;
|
||||||
&& !games.Any(g => g.CatalogItemId == manifest.CatalogItemId
|
string json = File.ReadAllText(file);
|
||||||
&& g.InstallLocation == manifest.InstallLocation))
|
try
|
||||||
games.Add(manifest);
|
{
|
||||||
|
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))
|
||||||
|
games.Add(manifest);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
;
|
||||||
}
|
}
|
||||||
catch { }
|
return games;
|
||||||
;
|
});
|
||||||
}
|
|
||||||
return games;
|
|
||||||
});
|
|
||||||
}
|
}
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using CreamInstaller.Platforms.Epic.GraphQL;
|
using CreamInstaller.Platforms.Epic.GraphQL;
|
||||||
|
@ -23,8 +22,7 @@ internal static class EpicStore
|
||||||
|
|
||||||
private const int COOLDOWN_ENTITLEMENT = 600;
|
private const int COOLDOWN_ENTITLEMENT = 600;
|
||||||
|
|
||||||
internal static async Task<List<(string id, string name, string product, string icon, string developer)>>
|
internal static async Task<List<(string id, string name, string product, string icon, string developer)>> QueryEntitlements(string categoryNamespace)
|
||||||
QueryEntitlements(string categoryNamespace)
|
|
||||||
{
|
{
|
||||||
List<(string id, string name, string product, string icon, string developer)> dlcIds = new();
|
List<(string id, string name, string product, string icon, string developer)> dlcIds = new();
|
||||||
string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json";
|
string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json";
|
||||||
|
@ -40,7 +38,6 @@ internal static class EpicStore
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
else if (cachedExists)
|
else if (cachedExists)
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = JsonConvert.DeserializeObject<Response>(await File.ReadAllTextAsync(cacheFile));
|
response = JsonConvert.DeserializeObject<Response>(await File.ReadAllTextAsync(cacheFile));
|
||||||
|
@ -49,16 +46,13 @@ internal static class EpicStore
|
||||||
{
|
{
|
||||||
File.Delete(cacheFile);
|
File.Delete(cacheFile);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (response is null)
|
if (response is null)
|
||||||
return dlcIds;
|
return dlcIds;
|
||||||
List<Element> searchStore = new(response.Data.Catalog.SearchStore.Elements);
|
List<Element> searchStore = new(response.Data.Catalog.SearchStore.Elements);
|
||||||
foreach (Element element in searchStore)
|
foreach (Element element in searchStore)
|
||||||
{
|
{
|
||||||
string title = element.Title;
|
string title = element.Title;
|
||||||
string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any()
|
string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any() ? element.CatalogNs.Mappings.First().PageSlug : null;
|
||||||
? element.CatalogNs.Mappings.First().PageSlug
|
|
||||||
: null;
|
|
||||||
string icon = null;
|
string icon = null;
|
||||||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -76,9 +70,7 @@ internal static class EpicStore
|
||||||
foreach (Element element in catalogOffers)
|
foreach (Element element in catalogOffers)
|
||||||
{
|
{
|
||||||
string title = element.Title;
|
string title = element.Title;
|
||||||
string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any()
|
string product = element.CatalogNs is not null && element.CatalogNs.Mappings.Any() ? element.CatalogNs.Mappings.First().PageSlug : null;
|
||||||
? element.CatalogNs.Mappings.First().PageSlug
|
|
||||||
: null;
|
|
||||||
string icon = null;
|
string icon = null;
|
||||||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -95,11 +87,11 @@ internal static class EpicStore
|
||||||
return dlcIds;
|
return dlcIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Populate(
|
private static void Populate(this List<(string id, string name, string product, string icon, string developer)> dlcIds, string id, string title,
|
||||||
this List<(string id, string name, string product, string icon, string developer)> dlcIds, string id,
|
string product, string icon, string developer, bool canOverwrite = false)
|
||||||
string title, string product, string icon, string developer, bool canOverwrite = false)
|
|
||||||
{
|
{
|
||||||
if (id == null) return;
|
if (id == null)
|
||||||
|
return;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; i < dlcIds.Count; i++)
|
for (int i = 0; i < dlcIds.Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +105,8 @@ internal static class EpicStore
|
||||||
break;
|
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)
|
private static async Task<Response> QueryGraphQL(string categoryNamespace)
|
||||||
|
@ -124,11 +117,11 @@ internal static class EpicStore
|
||||||
Request request = new(encoded);
|
Request request = new(encoded);
|
||||||
string payload = JsonConvert.SerializeObject(request);
|
string payload = JsonConvert.SerializeObject(request);
|
||||||
using HttpContent content = new StringContent(payload);
|
using HttpContent content = new StringContent(payload);
|
||||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
content.Headers.ContentType = new("application/json");
|
||||||
HttpClient client = HttpClientManager.HttpClient;
|
HttpClient client = HttpClientManager.HttpClient;
|
||||||
if (client is null) return null;
|
if (client is null)
|
||||||
HttpResponseMessage httpResponse
|
return null;
|
||||||
= await client.PostAsync(new Uri("https://graphql.epicgames.com/graphql"), content);
|
HttpResponseMessage httpResponse = await client.PostAsync(new Uri("https://graphql.epicgames.com/graphql"), content);
|
||||||
_ = httpResponse.EnsureSuccessStatusCode();
|
_ = httpResponse.EnsureSuccessStatusCode();
|
||||||
string response = await httpResponse.Content.ReadAsStringAsync();
|
string response = await httpResponse.Content.ReadAsStringAsync();
|
||||||
return JsonConvert.DeserializeObject<Response>(response);
|
return JsonConvert.DeserializeObject<Response>(response);
|
||||||
|
|
|
@ -9,10 +9,11 @@ namespace CreamInstaller.Platforms.Epic.GraphQL;
|
||||||
|
|
||||||
internal class Request
|
internal class Request
|
||||||
{
|
{
|
||||||
internal Request(string @namespace) => Vars = new Variables(@namespace);
|
internal Request(string @namespace) => Vars = new(@namespace);
|
||||||
|
|
||||||
[JsonProperty(PropertyName = "query")]
|
[JsonProperty(PropertyName = "query")]
|
||||||
private string Query => @"query searchOffers($namespace: String!) {
|
private string Query
|
||||||
|
=> @"query searchOffers($namespace: String!) {
|
||||||
Catalog {
|
Catalog {
|
||||||
searchStore(category: ""*"", namespace: $namespace){
|
searchStore(category: ""*"", namespace: $namespace){
|
||||||
elements {
|
elements {
|
||||||
|
|
|
@ -27,20 +27,16 @@ internal static class ParadoxLauncher
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Paradox Interactive\Paradox Launcher v2",
|
installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation", null) as string;
|
||||||
"LauncherInstallation", null) as string;
|
installPath
|
||||||
installPath ??= Registry.GetValue(
|
??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Wow6432Node\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation",
|
||||||
@"HKEY_CURRENT_USER\Software\Wow6432Node\Paradox Interactive\Paradox Launcher v2",
|
null) as string;
|
||||||
"LauncherInstallation", null) as string;
|
|
||||||
return installPath.BeautifyPath();
|
return installPath.BeautifyPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||||
string gameDirectory) =>
|
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: path => !Path.GetFileName(path).Contains("bootstrapper")));
|
||||||
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: path
|
|
||||||
=> !Path.GetFileName(path)
|
|
||||||
.Contains("bootstrapper")));
|
|
||||||
|
|
||||||
private static void PopulateDlc(ProgramSelection paradoxLauncher = null)
|
private static void PopulateDlc(ProgramSelection paradoxLauncher = null)
|
||||||
{
|
{
|
||||||
|
@ -49,26 +45,24 @@ internal static class ParadoxLauncher
|
||||||
{
|
{
|
||||||
paradoxLauncher.ExtraDlc.Clear();
|
paradoxLauncher.ExtraDlc.Clear();
|
||||||
paradoxLauncher.ExtraSelectedDlc.Clear();
|
paradoxLauncher.ExtraSelectedDlc.Clear();
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllEnabled.Where(
|
foreach (ProgramSelection selection in ProgramSelection.AllEnabled.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
|
||||||
s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
|
|
||||||
{
|
{
|
||||||
paradoxLauncher.ExtraDlc.Add(
|
paradoxLauncher.ExtraDlc.Add(
|
||||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(selection.Id, selection.Name,
|
||||||
selection.Id, selection.Name, selection.AllDlc));
|
selection.AllDlc));
|
||||||
paradoxLauncher.ExtraSelectedDlc.Add(
|
paradoxLauncher.ExtraSelectedDlc.Add(
|
||||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(selection.Id, selection.Name,
|
||||||
selection.Id, selection.Name, selection.SelectedDlc));
|
selection.SelectedDlc));
|
||||||
}
|
}
|
||||||
if (!paradoxLauncher.ExtraDlc.Any())
|
if (!paradoxLauncher.ExtraDlc.Any())
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe.Where(
|
foreach (ProgramSelection selection in ProgramSelection.AllSafe.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
|
||||||
s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
|
|
||||||
{
|
{
|
||||||
paradoxLauncher.ExtraDlc.Add(
|
paradoxLauncher.ExtraDlc.Add(
|
||||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(selection.Id, selection.Name,
|
||||||
selection.Id, selection.Name, selection.AllDlc));
|
selection.AllDlc));
|
||||||
paradoxLauncher.ExtraSelectedDlc.Add(
|
paradoxLauncher.ExtraSelectedDlc.Add(
|
||||||
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(
|
new ValueTuple<string, string, SortedList<string, (DlcType type, string name, string icon)>>(selection.Id, selection.Name,
|
||||||
selection.Id, selection.Name, selection.AllDlc));
|
selection.AllDlc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,10 +77,9 @@ internal static class ParadoxLauncher
|
||||||
{
|
{
|
||||||
using DialogForm dialogForm = new(form);
|
using DialogForm dialogForm = new(form);
|
||||||
return dialogForm.Show(SystemIcons.Warning,
|
return dialogForm.Show(SystemIcons.Warning,
|
||||||
"WARNING: There are no scanned games with DLC that can be added to the Paradox Launcher!"
|
"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",
|
||||||
"\n\nInstalling DLC unlockers for the Paradox Launcher alone can cause existing configurations to be deleted!",
|
"Paradox Launcher") != DialogResult.OK;
|
||||||
"Ignore", "Cancel", "Paradox Launcher") != DialogResult.OK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -96,9 +89,7 @@ internal static class ParadoxLauncher
|
||||||
{
|
{
|
||||||
InstallForm installForm = form as InstallForm;
|
InstallForm installForm = form as InstallForm;
|
||||||
if (!Program.IsProgramRunningDialog(form, selection))
|
if (!Program.IsProgramRunningDialog(form, selection))
|
||||||
return form is InstallForm
|
return form is InstallForm ? throw new CustomMessageException("Repair failed! The launcher is currently running!") : RepairResult.ProgramRunning;
|
||||||
? throw new CustomMessageException("Repair failed! The launcher is currently running!")
|
|
||||||
: RepairResult.ProgramRunning;
|
|
||||||
bool smokeInstalled = false;
|
bool smokeInstalled = false;
|
||||||
byte[] steamOriginalSdk32 = null;
|
byte[] steamOriginalSdk32 = null;
|
||||||
byte[] steamOriginalSdk64 = null;
|
byte[] steamOriginalSdk64 = null;
|
||||||
|
@ -107,40 +98,29 @@ internal static class ParadoxLauncher
|
||||||
byte[] epicOriginalSdk64 = null;
|
byte[] epicOriginalSdk64 = null;
|
||||||
foreach (string directory in selection.DllDirectories)
|
foreach (string directory in selection.DllDirectories)
|
||||||
{
|
{
|
||||||
bool koaloaderInstalled = Koaloader.AutoLoadDlls
|
bool koaloaderInstalled = Koaloader.AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||||
.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
|
||||||
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
.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,
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out _);
|
||||||
out string config, out _);
|
smokeInstalled = smokeInstalled || File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled
|
||||||
smokeInstalled = smokeInstalled
|
|| File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|
||||||
|| File.Exists(api32_o) || File.Exists(api64_o)
|
|| File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
|
||||||
|| (File.Exists(config) && !koaloaderInstalled)
|
|
||||||
|| (File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.Steamworks32))
|
|
||||||
|| (File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.Steamworks64));
|
|
||||||
await SmokeAPI.Uninstall(directory, deleteConfig: false);
|
await SmokeAPI.Uninstall(directory, deleteConfig: false);
|
||||||
if (steamOriginalSdk32 is null && File.Exists(api32)
|
if (steamOriginalSdk32 is null && File.Exists(api32) && !api32.IsResourceFile(ResourceIdentifier.Steamworks32))
|
||||||
&& !api32.IsResourceFile(ResourceIdentifier.Steamworks32))
|
|
||||||
steamOriginalSdk32 = await File.ReadAllBytesAsync(api32);
|
steamOriginalSdk32 = await File.ReadAllBytesAsync(api32);
|
||||||
if (steamOriginalSdk64 is null && File.Exists(api64)
|
if (steamOriginalSdk64 is null && File.Exists(api64) && !api64.IsResourceFile(ResourceIdentifier.Steamworks64))
|
||||||
&& !api64.IsResourceFile(ResourceIdentifier.Steamworks64))
|
|
||||||
steamOriginalSdk64 = await File.ReadAllBytesAsync(api64);
|
steamOriginalSdk64 = await File.ReadAllBytesAsync(api64);
|
||||||
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out config);
|
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out config);
|
||||||
screamInstalled = screamInstalled
|
screamInstalled = screamInstalled || File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled
|
||||||
|| File.Exists(api32_o) || File.Exists(api64_o)
|
|| File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)
|
||||||
|| (File.Exists(config) && !koaloaderInstalled)
|
|| File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64);
|
||||||
|| (File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))
|
|
||||||
|| (File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64));
|
|
||||||
await ScreamAPI.Uninstall(directory, deleteConfig: false);
|
await ScreamAPI.Uninstall(directory, deleteConfig: false);
|
||||||
if (epicOriginalSdk32 is null && File.Exists(api32)
|
if (epicOriginalSdk32 is null && File.Exists(api32) && !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))
|
||||||
&& !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))
|
|
||||||
epicOriginalSdk32 = await File.ReadAllBytesAsync(api32);
|
epicOriginalSdk32 = await File.ReadAllBytesAsync(api32);
|
||||||
if (epicOriginalSdk64 is null && File.Exists(api64)
|
if (epicOriginalSdk64 is null && File.Exists(api64) && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64))
|
||||||
&& !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64))
|
|
||||||
epicOriginalSdk64 = await File.ReadAllBytesAsync(api64);
|
epicOriginalSdk64 = await File.ReadAllBytesAsync(api64);
|
||||||
}
|
}
|
||||||
using DialogForm dialogForm = new(form);
|
using DialogForm dialogForm = new(form);
|
||||||
if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null
|
if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null || epicOriginalSdk64 is not null)
|
||||||
|| epicOriginalSdk64 is not null)
|
|
||||||
{
|
{
|
||||||
bool neededRepair = false;
|
bool neededRepair = false;
|
||||||
foreach (string directory in selection.DllDirectories)
|
foreach (string directory in selection.DllDirectories)
|
||||||
|
@ -181,26 +161,22 @@ internal static class ParadoxLauncher
|
||||||
if (installForm is not null)
|
if (installForm is not null)
|
||||||
installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success);
|
installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success);
|
||||||
else
|
else
|
||||||
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", "OK",
|
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", "OK", customFormText: "Paradox Launcher");
|
||||||
customFormText: "Paradox Launcher");
|
|
||||||
return RepairResult.Success;
|
return RepairResult.Success;
|
||||||
}
|
}
|
||||||
if (installForm is not null)
|
if (installForm is not null)
|
||||||
installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success);
|
installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success);
|
||||||
else
|
else
|
||||||
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", "OK",
|
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", "OK", customFormText: "Paradox Launcher");
|
||||||
customFormText: "Paradox Launcher");
|
|
||||||
return RepairResult.Unnecessary;
|
return RepairResult.Unnecessary;
|
||||||
}
|
}
|
||||||
_ = form is InstallForm
|
_ = form is InstallForm
|
||||||
? throw new CustomMessageException("Repair failed! " +
|
? throw new CustomMessageException("Repair failed! " + "An original Steamworks and/or Epic Online Services file could not be found. "
|
||||||
"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,
|
||||||
"You will likely have to reinstall Paradox Launcher to fix this issue.")
|
"Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found."
|
||||||
: dialogForm.Show(SystemIcons.Error, "Paradox Launcher repair failed!"
|
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", "OK",
|
||||||
+ "\n\nAn original Steamworks and/or Epic Online Services file could not be found."
|
customFormText: "Paradox Launcher");
|
||||||
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.",
|
|
||||||
"OK", customFormText: "Paradox Launcher");
|
|
||||||
return RepairResult.Failure;
|
return RepairResult.Failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,7 @@ internal static class SteamCMD
|
||||||
|
|
||||||
internal static readonly string FilePath = DirectoryPath + @"\steamcmd.exe";
|
internal static readonly string FilePath = DirectoryPath + @"\steamcmd.exe";
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<string, int>
|
private static readonly ConcurrentDictionary<string, int> AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print
|
||||||
AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print
|
|
||||||
|
|
||||||
private static readonly int[] locks = new int[ProcessLimit];
|
private static readonly int[] locks = new int[ProcessLimit];
|
||||||
|
|
||||||
|
@ -38,84 +37,86 @@ internal static class SteamCMD
|
||||||
internal static string DirectoryPath => ProgramData.DirectoryPath;
|
internal static string DirectoryPath => ProgramData.DirectoryPath;
|
||||||
internal static string AppInfoPath => ProgramData.AppInfoPath;
|
internal static string AppInfoPath => ProgramData.AppInfoPath;
|
||||||
|
|
||||||
private static string GetArguments(string appId) => AttemptCount.TryGetValue(appId, out int attempts)
|
private static string GetArguments(string appId)
|
||||||
? $@"@ShutdownOnFailedCommand 0 +force_install_dir {DirectoryPath} +login anonymous +app_info_print {appId} "
|
=> AttemptCount.TryGetValue(appId, out int attempts)
|
||||||
+ string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit"
|
? $@"@ShutdownOnFailedCommand 0 +force_install_dir {DirectoryPath} +login anonymous +app_info_print {appId} "
|
||||||
: $"+login anonymous +app_info_print {appId} +quit";
|
+ 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 "";
|
|
||||||
for (int i = 0; i < locks.Length; i++)
|
|
||||||
{
|
{
|
||||||
if (Program.Canceled) return "";
|
wait_for_lock:
|
||||||
if (Interlocked.CompareExchange(ref locks[i], 1, 0) == 0)
|
if (Program.Canceled)
|
||||||
|
return "";
|
||||||
|
for (int i = 0; i < locks.Length; i++)
|
||||||
{
|
{
|
||||||
if (appId is not null)
|
if (Program.Canceled)
|
||||||
{
|
return "";
|
||||||
AttemptCount.TryGetValue(appId, out int count);
|
if (Interlocked.CompareExchange(ref locks[i], 1, 0) == 0)
|
||||||
AttemptCount[appId] = ++count;
|
|
||||||
}
|
|
||||||
if (Program.Canceled) return "";
|
|
||||||
ProcessStartInfo processStartInfo = new()
|
|
||||||
{
|
|
||||||
FileName = FilePath, RedirectStandardOutput = true, RedirectStandardInput = true,
|
|
||||||
RedirectStandardError = true, UseShellExecute = false,
|
|
||||||
Arguments = appId is null ? "+quit" : GetArguments(appId), CreateNoWindow = true,
|
|
||||||
StandardInputEncoding = Encoding.UTF8, StandardOutputEncoding = Encoding.UTF8,
|
|
||||||
StandardErrorEncoding = Encoding.UTF8
|
|
||||||
};
|
|
||||||
Process process = Process.Start(processStartInfo);
|
|
||||||
StringBuilder output = new();
|
|
||||||
StringBuilder appInfo = new();
|
|
||||||
bool appInfoStarted = false;
|
|
||||||
DateTime lastOutput = DateTime.UtcNow;
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
|
if (appId is not null)
|
||||||
|
{
|
||||||
|
AttemptCount.TryGetValue(appId, out int count);
|
||||||
|
AttemptCount[appId] = ++count;
|
||||||
|
}
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
|
return "";
|
||||||
|
ProcessStartInfo processStartInfo = new()
|
||||||
{
|
{
|
||||||
process.Kill(true);
|
FileName = FilePath, RedirectStandardOutput = true, RedirectStandardInput = true, RedirectStandardError = true,
|
||||||
process.Close();
|
UseShellExecute = false, Arguments = appId is null ? "+quit" : GetArguments(appId), CreateNoWindow = true,
|
||||||
break;
|
StandardInputEncoding = Encoding.UTF8, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8
|
||||||
}
|
};
|
||||||
int c = process.StandardOutput.Read();
|
Process process = Process.Start(processStartInfo);
|
||||||
if (c != -1)
|
StringBuilder output = new();
|
||||||
|
StringBuilder appInfo = new();
|
||||||
|
bool appInfoStarted = false;
|
||||||
|
DateTime lastOutput = DateTime.UtcNow;
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
lastOutput = DateTime.UtcNow;
|
if (Program.Canceled)
|
||||||
char ch = (char)c;
|
|
||||||
if (ch == '{') appInfoStarted = true;
|
|
||||||
_ = appInfoStarted ? appInfo.Append(ch) : output.Append(ch);
|
|
||||||
}
|
|
||||||
DateTime now = DateTime.UtcNow;
|
|
||||||
TimeSpan timeDiff = now - lastOutput;
|
|
||||||
if (timeDiff.TotalSeconds > 0.1)
|
|
||||||
{
|
|
||||||
process.Kill(true);
|
|
||||||
process.Close();
|
|
||||||
if (output.ToString().Contains($"No app info for AppID {appId} found, requesting..."))
|
|
||||||
{
|
|
||||||
AttemptCount[appId]++;
|
|
||||||
processStartInfo.Arguments = GetArguments(appId);
|
|
||||||
process = Process.Start(processStartInfo);
|
|
||||||
appInfoStarted = false;
|
|
||||||
_ = output.Clear();
|
|
||||||
_ = appInfo.Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
process.Kill(true);
|
||||||
|
process.Close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
int c = process.StandardOutput.Read();
|
||||||
|
if (c != -1)
|
||||||
|
{
|
||||||
|
lastOutput = DateTime.UtcNow;
|
||||||
|
char ch = (char)c;
|
||||||
|
if (ch == '{')
|
||||||
|
appInfoStarted = true;
|
||||||
|
_ = appInfoStarted ? appInfo.Append(ch) : output.Append(ch);
|
||||||
|
}
|
||||||
|
DateTime now = DateTime.UtcNow;
|
||||||
|
TimeSpan timeDiff = now - lastOutput;
|
||||||
|
if (timeDiff.TotalSeconds > 0.1)
|
||||||
|
{
|
||||||
|
process.Kill(true);
|
||||||
|
process.Close();
|
||||||
|
if (output.ToString().Contains($"No app info for AppID {appId} found, requesting..."))
|
||||||
|
{
|
||||||
|
AttemptCount[appId]++;
|
||||||
|
processStartInfo.Arguments = GetArguments(appId);
|
||||||
|
process = Process.Start(processStartInfo);
|
||||||
|
appInfoStarted = false;
|
||||||
|
_ = output.Clear();
|
||||||
|
_ = appInfo.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_ = Interlocked.Decrement(ref locks[i]);
|
||||||
|
return appInfo.ToString();
|
||||||
}
|
}
|
||||||
_ = Interlocked.Decrement(ref locks[i]);
|
Thread.Sleep(200);
|
||||||
return appInfo.ToString();
|
|
||||||
}
|
}
|
||||||
Thread.Sleep(200);
|
Thread.Sleep(200);
|
||||||
}
|
goto wait_for_lock;
|
||||||
Thread.Sleep(200);
|
});
|
||||||
goto wait_for_lock;
|
|
||||||
});
|
|
||||||
|
|
||||||
internal static async Task Setup(IProgress<int> progress)
|
internal static async Task Setup(IProgress<int> progress)
|
||||||
{
|
{
|
||||||
|
@ -123,21 +124,20 @@ internal static class SteamCMD
|
||||||
if (!File.Exists(FilePath))
|
if (!File.Exists(FilePath))
|
||||||
{
|
{
|
||||||
HttpClient httpClient = HttpClientManager.HttpClient;
|
HttpClient httpClient = HttpClientManager.HttpClient;
|
||||||
if (httpClient is null) return;
|
if (httpClient is null)
|
||||||
byte[] file = await httpClient.GetByteArrayAsync(
|
return;
|
||||||
new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"));
|
byte[] file = await httpClient.GetByteArrayAsync(new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"));
|
||||||
file.Write(ArchivePath);
|
file.Write(ArchivePath);
|
||||||
ZipFile.ExtractToDirectory(ArchivePath, DirectoryPath);
|
ZipFile.ExtractToDirectory(ArchivePath, DirectoryPath);
|
||||||
File.Delete(ArchivePath);
|
File.Delete(ArchivePath);
|
||||||
}
|
}
|
||||||
if (!File.Exists(DllPath))
|
if (!File.Exists(DllPath))
|
||||||
{
|
{
|
||||||
FileSystemWatcher watcher = new(DirectoryPath)
|
FileSystemWatcher watcher = new(DirectoryPath) { Filter = "*", IncludeSubdirectories = true, EnableRaisingEvents = true };
|
||||||
{
|
if (File.Exists(DllPath))
|
||||||
Filter = "*", IncludeSubdirectories = true, EnableRaisingEvents = true
|
progress.Report(-15); // update (not used at the moment)
|
||||||
};
|
else
|
||||||
if (File.Exists(DllPath)) progress.Report(-15); // update (not used at the moment)
|
progress.Report(-1660); // install
|
||||||
else progress.Report(-1660); // install
|
|
||||||
int cur = 0;
|
int cur = 0;
|
||||||
progress.Report(cur);
|
progress.Report(cur);
|
||||||
watcher.Changed += (sender, e) => progress.Report(++cur);
|
watcher.Changed += (sender, e) => progress.Report(++cur);
|
||||||
|
@ -146,45 +146,47 @@ 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;
|
|
||||||
await Kill();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (Directory.Exists(ConfigPath))
|
if (!Directory.Exists(DirectoryPath))
|
||||||
foreach (string file in Directory.EnumerateFiles(ConfigPath, "*.tmp"))
|
return;
|
||||||
|
await Kill();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(ConfigPath))
|
||||||
|
foreach (string file in Directory.EnumerateFiles(ConfigPath, "*.tmp"))
|
||||||
|
File.Delete(file);
|
||||||
|
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.old"))
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.old"))
|
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.delete"))
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.delete"))
|
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.crash"))
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.crash"))
|
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.ntfs_transaction_failed"))
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.ntfs_transaction_failed"))
|
if (Directory.Exists(AppCachePath))
|
||||||
File.Delete(file);
|
Directory.Delete(AppCachePath, true); // this is definitely needed, so SteamCMD gets the latest information for us
|
||||||
if (Directory.Exists(AppCachePath))
|
if (Directory.Exists(DumpsPath))
|
||||||
Directory.Delete(AppCachePath,
|
Directory.Delete(DumpsPath, true);
|
||||||
true); // this is definitely needed, so SteamCMD gets the latest information for us
|
if (Directory.Exists(LogsPath))
|
||||||
if (Directory.Exists(DumpsPath))
|
Directory.Delete(LogsPath, true);
|
||||||
Directory.Delete(DumpsPath, true);
|
if (Directory.Exists(SteamAppsPath))
|
||||||
if (Directory.Exists(LogsPath))
|
Directory.Delete(SteamAppsPath, true); // this is just a useless folder created from +app_update 4
|
||||||
Directory.Delete(LogsPath, true);
|
}
|
||||||
if (Directory.Exists(SteamAppsPath))
|
catch { }
|
||||||
Directory.Delete(SteamAppsPath, true); // this is just a useless folder created from +app_update 4
|
});
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
});
|
|
||||||
|
|
||||||
internal static async Task<VProperty> GetAppInfo(string appId, string branch = "public", int buildId = 0)
|
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 output;
|
||||||
string appUpdateFile = $@"{AppInfoPath}\{appId}.vdf";
|
string appUpdateFile = $@"{AppInfoPath}\{appId}.vdf";
|
||||||
restart:
|
restart:
|
||||||
if (Program.Canceled) return null;
|
if (Program.Canceled)
|
||||||
|
return null;
|
||||||
if (File.Exists(appUpdateFile))
|
if (File.Exists(appUpdateFile))
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
output = await File.ReadAllTextAsync(appUpdateFile, Encoding.UTF8);
|
output = await File.ReadAllTextAsync(appUpdateFile, Encoding.UTF8);
|
||||||
|
@ -193,7 +195,6 @@ internal static class SteamCMD
|
||||||
{
|
{
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
output = await Run(appId) ?? "";
|
output = await Run(appId) ?? "";
|
||||||
|
@ -213,74 +214,75 @@ internal static class SteamCMD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Program.Canceled) return null;
|
if (Program.Canceled)
|
||||||
|
return null;
|
||||||
if (!ValveDataFile.TryDeserialize(output, out VProperty appInfo) || appInfo.Value is VValue)
|
if (!ValveDataFile.TryDeserialize(output, out VProperty appInfo) || appInfo.Value is VValue)
|
||||||
{
|
{
|
||||||
File.Delete(appUpdateFile);
|
File.Delete(appUpdateFile);
|
||||||
goto restart;
|
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");
|
VToken type = appInfo.Value?.GetChild("common")?.GetChild("type");
|
||||||
if (type is not null && type.ToString() != "Game")
|
if (type is not null && type.ToString() != "Game")
|
||||||
return appInfo;
|
return appInfo;
|
||||||
string buildid = appInfo.Value?.GetChild("depots")?.GetChild("branches")?.GetChild(branch)
|
string buildid = appInfo.Value?.GetChild("depots")?.GetChild("branches")?.GetChild(branch)?.GetChild("buildid")?.ToString();
|
||||||
?.GetChild("buildid")?.ToString();
|
if (buildid is null && type is not null)
|
||||||
if (buildid is null && type is not null) return appInfo;
|
return appInfo;
|
||||||
if (type is not null && (!int.TryParse(buildid, out int gamebuildId) || gamebuildId >= buildId))
|
if (type is not null && (!int.TryParse(buildid, out int gamebuildId) || gamebuildId >= buildId))
|
||||||
return appInfo;
|
return appInfo;
|
||||||
List<string> dlcAppIds = await ParseDlcAppIds(appInfo);
|
List<string> dlcAppIds = await ParseDlcAppIds(appInfo);
|
||||||
foreach (string dlcAppUpdateFile in dlcAppIds.Select(id => $@"{AppInfoPath}\{id}.vdf"))
|
foreach (string dlcAppUpdateFile in dlcAppIds.Select(id => $@"{AppInfoPath}\{id}.vdf"))
|
||||||
if (File.Exists(dlcAppUpdateFile))
|
if (File.Exists(dlcAppUpdateFile))
|
||||||
File.Delete(dlcAppUpdateFile);
|
File.Delete(dlcAppUpdateFile);
|
||||||
if (File.Exists(appUpdateFile)) File.Delete(appUpdateFile);
|
if (File.Exists(appUpdateFile))
|
||||||
|
File.Delete(appUpdateFile);
|
||||||
goto restart;
|
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;
|
List<string> dlcIds = new();
|
||||||
VToken extended = appInfo.Value.GetChild("extended");
|
if (Program.Canceled || appInfo is null)
|
||||||
if (extended is not null)
|
return dlcIds;
|
||||||
foreach (VToken vToken in extended.Where(p => p is VProperty { Key: "listofdlc" }))
|
VToken extended = appInfo.Value.GetChild("extended");
|
||||||
|
if (extended is not null)
|
||||||
|
foreach (VToken vToken in extended.Where(p => p is VProperty { Key: "listofdlc" }))
|
||||||
|
{
|
||||||
|
VProperty property = (VProperty)vToken;
|
||||||
|
foreach (string id in property.Value.ToString().Split(","))
|
||||||
|
if (int.TryParse(id, out int appId) && appId > 0 && !dlcIds.Contains("" + appId))
|
||||||
|
dlcIds.Add("" + appId);
|
||||||
|
}
|
||||||
|
VToken depots = appInfo.Value.GetChild("depots");
|
||||||
|
if (depots is null)
|
||||||
|
return dlcIds;
|
||||||
|
foreach (VToken vToken in depots.Where(p => p is VProperty property && int.TryParse(property.Key, out int _)))
|
||||||
{
|
{
|
||||||
VProperty property = (VProperty)vToken;
|
VProperty property = (VProperty)vToken;
|
||||||
foreach (string id in property.Value.ToString().Split(","))
|
if (int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appId) && appId > 0 && !dlcIds.Contains("" + appId))
|
||||||
if (int.TryParse(id, out int appId) && appId > 0 && !dlcIds.Contains("" + appId))
|
dlcIds.Add("" + appId);
|
||||||
dlcIds.Add("" + appId);
|
|
||||||
}
|
}
|
||||||
VToken depots = appInfo.Value.GetChild("depots");
|
|
||||||
if (depots is null)
|
|
||||||
return dlcIds;
|
return dlcIds;
|
||||||
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))
|
|
||||||
dlcIds.Add("" + appId);
|
|
||||||
}
|
|
||||||
return dlcIds;
|
|
||||||
});
|
|
||||||
|
|
||||||
private static async Task Kill()
|
private static async Task Kill()
|
||||||
{
|
{
|
||||||
List<Task> tasks = Process.GetProcessesByName("steamcmd")
|
List<Task> tasks = Process.GetProcessesByName("steamcmd").Select(process => Task.Run(() =>
|
||||||
.Select(process => Task.Run(() =>
|
{
|
||||||
{
|
try
|
||||||
try
|
{
|
||||||
{
|
process.Kill(true);
|
||||||
process.Kill(true);
|
process.WaitForExit();
|
||||||
process.WaitForExit();
|
process.Close();
|
||||||
process.Close();
|
}
|
||||||
}
|
catch { }
|
||||||
catch { }
|
})).ToList();
|
||||||
}))
|
foreach (Task task in tasks)
|
||||||
.ToList();
|
await task;
|
||||||
foreach (Task task in tasks) await task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Dispose()
|
internal static void Dispose()
|
||||||
|
|
|
@ -18,93 +18,96 @@ internal static class SteamLibrary
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath",
|
installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", null) as string;
|
||||||
null) as string;
|
installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam", "InstallPath", null) as string;
|
||||||
installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam", "InstallPath",
|
|
||||||
null) as string;
|
|
||||||
return installPath.BeautifyPath();
|
return installPath.BeautifyPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||||
string gameDirectory) =>
|
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||||
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
|
||||||
|
|
||||||
internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>>
|
internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>> GetGames()
|
||||||
GetGames() => await Task.Run(async () =>
|
=> 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;
|
List<(string appId, string name, string branch, int buildId, string gameDirectory)> games = new();
|
||||||
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in
|
List<string> gameLibraryDirectories = await GetLibraryDirectories();
|
||||||
(await GetGamesFromLibraryDirectory(libraryDirectory))
|
foreach (string libraryDirectory in gameLibraryDirectories)
|
||||||
.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(() =>
|
|
||||||
{
|
|
||||||
List<(string appId, string name, string branch, int buildId, string gameDirectory)> games = new();
|
|
||||||
if (Program.Canceled || !Directory.Exists(libraryDirectory)) return games;
|
|
||||||
foreach (string file in Directory.EnumerateFiles(libraryDirectory, "*.acf"))
|
|
||||||
{
|
|
||||||
if (Program.Canceled) return games;
|
|
||||||
if (ValveDataFile.TryDeserialize(File.ReadAllText(file, Encoding.UTF8), out VProperty result))
|
|
||||||
{
|
{
|
||||||
string appId = result.Value.GetChild("appid")?.ToString();
|
if (Program.Canceled)
|
||||||
string installdir = result.Value.GetChild("installdir")?.ToString();
|
return games;
|
||||||
string name = result.Value.GetChild("name")?.ToString();
|
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in
|
||||||
string buildId = result.Value.GetChild("buildid")?.ToString();
|
(await GetGamesFromLibraryDirectory(libraryDirectory)).Where(game
|
||||||
if (string.IsNullOrWhiteSpace(appId)
|
=> !games.Any(_game => _game.appId == game.appId && _game.gameDirectory == game.gameDirectory)))
|
||||||
|| string.IsNullOrWhiteSpace(installdir)
|
games.Add(game);
|
||||||
|| 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;
|
|
||||||
string branch = result.Value.GetChild("UserConfig")?.GetChild("betakey")?.ToString();
|
|
||||||
if (string.IsNullOrWhiteSpace(branch)) branch = "public";
|
|
||||||
games.Add((appId, name, branch, buildIdInt, gameDirectory));
|
|
||||||
}
|
}
|
||||||
}
|
return games;
|
||||||
return games;
|
});
|
||||||
});
|
|
||||||
|
|
||||||
internal static async Task<List<string>> GetLibraryDirectories() => await Task.Run(() =>
|
internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>>
|
||||||
{
|
GetGamesFromLibraryDirectory(string libraryDirectory)
|
||||||
List<string> gameDirectories = new();
|
=> await Task.Run(() =>
|
||||||
if (Program.Canceled) return gameDirectories;
|
|
||||||
string steamInstallPath = InstallPath;
|
|
||||||
if (steamInstallPath != null && Directory.Exists(steamInstallPath))
|
|
||||||
{
|
{
|
||||||
string libraryFolder = steamInstallPath + @"\steamapps";
|
List<(string appId, string name, string branch, int buildId, string gameDirectory)> games = new();
|
||||||
if (Directory.Exists(libraryFolder))
|
if (Program.Canceled || !Directory.Exists(libraryDirectory))
|
||||||
|
return games;
|
||||||
|
foreach (string file in Directory.EnumerateFiles(libraryDirectory, "*.acf"))
|
||||||
{
|
{
|
||||||
gameDirectories.Add(libraryFolder);
|
if (Program.Canceled)
|
||||||
string libraryFolders = libraryFolder + @"\libraryfolders.vdf";
|
return games;
|
||||||
if (File.Exists(libraryFolders)
|
if (ValveDataFile.TryDeserialize(File.ReadAllText(file, Encoding.UTF8), out VProperty result))
|
||||||
&& ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, 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)
|
||||||
|
|| 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;
|
||||||
|
string branch = result.Value.GetChild("UserConfig")?.GetChild("betakey")?.ToString();
|
||||||
|
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(() =>
|
||||||
|
{
|
||||||
|
List<string> gameDirectories = new();
|
||||||
|
if (Program.Canceled)
|
||||||
|
return gameDirectories;
|
||||||
|
string steamInstallPath = InstallPath;
|
||||||
|
if (steamInstallPath != null && Directory.Exists(steamInstallPath))
|
||||||
|
{
|
||||||
|
string libraryFolder = steamInstallPath + @"\steamapps";
|
||||||
|
if (Directory.Exists(libraryFolder))
|
||||||
|
{
|
||||||
|
gameDirectories.Add(libraryFolder);
|
||||||
|
string libraryFolders = libraryFolder + @"\libraryfolders.vdf";
|
||||||
|
if (File.Exists(libraryFolders) && ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, Encoding.UTF8), out VProperty result))
|
||||||
#pragma warning disable IDE0220 // Add explicit cast
|
#pragma warning disable IDE0220 // Add explicit cast
|
||||||
foreach (VProperty property in result.Value.Where(
|
foreach (VProperty property in result.Value.Where(p => p is VProperty && int.TryParse((p as VProperty).Key, out int _)))
|
||||||
p => p is VProperty && int.TryParse((p as VProperty).Key, out int _)))
|
{
|
||||||
{
|
string path = property.Value.GetChild("path")?.ToString();
|
||||||
string path = property.Value.GetChild("path")?.ToString();
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
if (string.IsNullOrWhiteSpace(path)) continue;
|
continue;
|
||||||
path += @"\steamapps";
|
path += @"\steamapps";
|
||||||
if (Directory.Exists(path) && !gameDirectories.Contains(path))
|
if (Directory.Exists(path) && !gameDirectories.Contains(path))
|
||||||
gameDirectories.Add(path);
|
gameDirectories.Add(path);
|
||||||
}
|
}
|
||||||
#pragma warning restore IDE0220 // Add explicit cast
|
#pragma warning restore IDE0220 // Add explicit cast
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return gameDirectories;
|
||||||
return gameDirectories;
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,23 +18,25 @@ internal static class SteamStore
|
||||||
private const int COOLDOWN_GAME = 600;
|
private const int COOLDOWN_GAME = 600;
|
||||||
private const int COOLDOWN_DLC = 1200;
|
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;
|
List<string> dlcIds = new();
|
||||||
dlcIds.AddRange(from appId in appData.dlc where appId > 0 select appId.ToString());
|
if (appData.dlc is null)
|
||||||
return dlcIds;
|
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)
|
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";
|
string cacheFile = ProgramData.AppInfoPath + @$"\{appId}.json";
|
||||||
bool cachedExists = File.Exists(cacheFile);
|
bool cachedExists = File.Exists(cacheFile);
|
||||||
if (!cachedExists || ProgramData.CheckCooldown(appId, isDlc ? COOLDOWN_DLC : COOLDOWN_GAME))
|
if (!cachedExists || ProgramData.CheckCooldown(appId, isDlc ? COOLDOWN_DLC : COOLDOWN_GAME))
|
||||||
{
|
{
|
||||||
string response
|
string response = await HttpClientManager.EnsureGet($"https://store.steampowered.com/api/appdetails?appids={appId}");
|
||||||
= await HttpClientManager.EnsureGet($"https://store.steampowered.com/api/appdetails?appids={appId}");
|
|
||||||
if (response is not null)
|
if (response is not null)
|
||||||
{
|
{
|
||||||
IDictionary<string, JToken> apps = (IDictionary<string, JToken>)JsonConvert.DeserializeObject(response);
|
IDictionary<string, JToken> apps = (IDictionary<string, JToken>)JsonConvert.DeserializeObject(response);
|
||||||
|
@ -60,8 +62,7 @@ internal static class SteamStore
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await File.WriteAllTextAsync(
|
await File.WriteAllTextAsync(cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented));
|
||||||
cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented));
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -76,16 +77,13 @@ internal static class SteamStore
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugForm.Current.Log(
|
DebugForm.Current.Log($"Response data null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}");
|
||||||
$"Response data null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
else
|
else
|
||||||
{
|
|
||||||
DebugForm.Current.Log(
|
DebugForm.Current.Log(
|
||||||
$"Response details null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}");
|
$"Response details null for appid {appId}{(isDlc ? " (DLC)" : "")}: {app.Value.ToString(Formatting.None)}");
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -99,7 +97,8 @@ internal static class SteamStore
|
||||||
{ }
|
{ }
|
||||||
#endif
|
#endif
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
else DebugForm.Current.Log("Response deserialization null for appid " + appId);
|
else
|
||||||
|
DebugForm.Current.Log("Response deserialization null for appid " + appId);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -22,16 +22,16 @@ internal static class UbisoftLibrary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory)
|
||||||
string gameDirectory) =>
|
=> await Task.Run(async () => await gameDirectory.GetExecutableDirectories(true));
|
||||||
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();
|
List<(string gameId, string name, string gameDirectory)> games = new();
|
||||||
RegistryKey installsKey = InstallsKey;
|
RegistryKey installsKey = InstallsKey;
|
||||||
if (installsKey is null) return games;
|
if (installsKey is null)
|
||||||
|
return games;
|
||||||
foreach (string gameId in installsKey.GetSubKeyNames())
|
foreach (string gameId in installsKey.GetSubKeyNames())
|
||||||
{
|
{
|
||||||
RegistryKey installKey = installsKey.OpenSubKey(gameId);
|
RegistryKey installKey = installsKey.OpenSubKey(gameId);
|
||||||
|
|
|
@ -42,8 +42,10 @@ internal static class Program
|
||||||
|
|
||||||
internal static bool IsGameBlocked(string name, string directory = null)
|
internal static bool IsGameBlocked(string name, string directory = null)
|
||||||
{
|
{
|
||||||
if (!BlockProtectedGames) return false;
|
if (!BlockProtectedGames)
|
||||||
if (ProtectedGames.Contains(name)) return true;
|
return false;
|
||||||
|
if (ProtectedGames.Contains(name))
|
||||||
|
return true;
|
||||||
if (directory is not null && !ProtectedGameDirectoryExceptions.Contains(name))
|
if (directory is not null && !ProtectedGameDirectoryExceptions.Contains(name))
|
||||||
foreach (string path in ProtectedGameDirectories)
|
foreach (string path in ProtectedGameDirectories)
|
||||||
if (Directory.Exists(directory + path))
|
if (Directory.Exists(directory + path))
|
||||||
|
@ -56,16 +58,12 @@ internal static class Program
|
||||||
if (selection.AreDllsLocked)
|
if (selection.AreDllsLocked)
|
||||||
{
|
{
|
||||||
using DialogForm dialogForm = new(form);
|
using DialogForm dialogForm = new(form);
|
||||||
if (dialogForm.Show(SystemIcons.Error,
|
if (dialogForm.Show(SystemIcons.Error, $"ERROR: {selection.Name} is currently running!" + "\n\nPlease close the program/game to continue . . . ",
|
||||||
$"ERROR: {selection.Name} is currently running!" +
|
"Retry", "Cancel") == DialogResult.OK)
|
||||||
"\n\nPlease close the program/game to continue . . . ",
|
|
||||||
"Retry", "Cancel") == DialogResult.OK)
|
|
||||||
return IsProgramRunningDialog(form, selection);
|
return IsProgramRunningDialog(form, selection);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +79,7 @@ internal static class Program
|
||||||
Application.ApplicationExit += OnApplicationExit;
|
Application.ApplicationExit += OnApplicationExit;
|
||||||
Application.ThreadException += (s, e) => e.Exception?.HandleFatalException();
|
Application.ThreadException += (s, e) => e.Exception?.HandleFatalException();
|
||||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
||||||
AppDomain.CurrentDomain.UnhandledException += (s, e)
|
AppDomain.CurrentDomain.UnhandledException += (s, e) => (e.ExceptionObject as Exception)?.HandleFatalException();
|
||||||
=> (e.ExceptionObject as Exception)?.HandleFatalException();
|
|
||||||
retry:
|
retry:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -95,7 +92,8 @@ internal static class Program
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (e.HandleException()) goto retry;
|
if (e.HandleException())
|
||||||
|
goto retry;
|
||||||
Application.Exit();
|
Application.Exit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,17 +25,14 @@ internal class ProgramSelection
|
||||||
|
|
||||||
internal static readonly List<ProgramSelection> All = new();
|
internal static readonly List<ProgramSelection> All = new();
|
||||||
|
|
||||||
internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc
|
internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc = new(PlatformIdComparer.String);
|
||||||
= new(PlatformIdComparer.String);
|
|
||||||
|
|
||||||
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)>
|
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)> ExtraDlc = new(); // for Paradox Launcher
|
||||||
ExtraDlc = new(); // for Paradox Launcher
|
|
||||||
|
|
||||||
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)>
|
internal readonly List<(string id, string name, SortedList<string, (DlcType type, string name, string icon)> dlc)>
|
||||||
ExtraSelectedDlc = new(); // for Paradox Launcher
|
ExtraSelectedDlc = new(); // for Paradox Launcher
|
||||||
|
|
||||||
internal readonly SortedList<string, (DlcType type, string name, string icon)> SelectedDlc
|
internal readonly SortedList<string, (DlcType type, string name, string icon)> SelectedDlc = new(PlatformIdComparer.String);
|
||||||
= new(PlatformIdComparer.String);
|
|
||||||
|
|
||||||
internal List<string> DllDirectories;
|
internal List<string> DllDirectories;
|
||||||
internal bool Enabled;
|
internal bool Enabled;
|
||||||
|
@ -67,54 +64,31 @@ internal class ProgramSelection
|
||||||
{
|
{
|
||||||
if (Platform is Platform.Steam or Platform.Paradox)
|
if (Platform is Platform.Steam or Platform.Paradox)
|
||||||
{
|
{
|
||||||
directory.GetCreamApiComponents(out string api32, out string api32_o, out string api64,
|
directory.GetCreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
out string api64_o, out string config);
|
if (api32.IsFilePathLocked() || api32_o.IsFilePathLocked() || api64.IsFilePathLocked() || api64_o.IsFilePathLocked()
|
||||||
if (api32.IsFilePathLocked()
|
|
||||||
|| api32_o.IsFilePathLocked()
|
|
||||||
|| api64.IsFilePathLocked()
|
|
||||||
|| api64_o.IsFilePathLocked()
|
|
||||||
|| config.IsFilePathLocked())
|
|| config.IsFilePathLocked())
|
||||||
return true;
|
return true;
|
||||||
directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out config,
|
directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out config, out string cache);
|
||||||
out string cache);
|
if (api32.IsFilePathLocked() || api32_o.IsFilePathLocked() || api64.IsFilePathLocked() || api64_o.IsFilePathLocked()
|
||||||
if (api32.IsFilePathLocked()
|
|| config.IsFilePathLocked() || cache.IsFilePathLocked())
|
||||||
|| api32_o.IsFilePathLocked()
|
|
||||||
|| api64.IsFilePathLocked()
|
|
||||||
|| api64_o.IsFilePathLocked()
|
|
||||||
|| config.IsFilePathLocked()
|
|
||||||
|| cache.IsFilePathLocked())
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (Platform is Platform.Epic or Platform.Paradox)
|
if (Platform is Platform.Epic or Platform.Paradox)
|
||||||
{
|
{
|
||||||
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64,
|
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
out string api64_o, out string config);
|
if (api32.IsFilePathLocked() || api32_o.IsFilePathLocked() || api64.IsFilePathLocked() || api64_o.IsFilePathLocked()
|
||||||
if (api32.IsFilePathLocked()
|
|
||||||
|| api32_o.IsFilePathLocked()
|
|
||||||
|| api64.IsFilePathLocked()
|
|
||||||
|| api64_o.IsFilePathLocked()
|
|
||||||
|| config.IsFilePathLocked())
|
|| config.IsFilePathLocked())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (Platform is Platform.Ubisoft)
|
if (Platform is Platform.Ubisoft)
|
||||||
{
|
{
|
||||||
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64,
|
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
out string api64_o, out string config);
|
if (api32.IsFilePathLocked() || api32_o.IsFilePathLocked() || api64.IsFilePathLocked() || api64_o.IsFilePathLocked()
|
||||||
if (api32.IsFilePathLocked()
|
|
||||||
|| api32_o.IsFilePathLocked()
|
|
||||||
|| api64.IsFilePathLocked()
|
|
||||||
|| api64_o.IsFilePathLocked()
|
|
||||||
|| config.IsFilePathLocked())
|
|| config.IsFilePathLocked())
|
||||||
return true;
|
return true;
|
||||||
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o,
|
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config);
|
||||||
out api64, out api64_o, out config);
|
if (old_api32.IsFilePathLocked() || old_api64.IsFilePathLocked() || api32.IsFilePathLocked() || api32_o.IsFilePathLocked()
|
||||||
if (old_api32.IsFilePathLocked()
|
|| api64.IsFilePathLocked() || api64_o.IsFilePathLocked() || config.IsFilePathLocked())
|
||||||
|| old_api64.IsFilePathLocked()
|
|
||||||
|| api32.IsFilePathLocked()
|
|
||||||
|| api32_o.IsFilePathLocked()
|
|
||||||
|| api64.IsFilePathLocked()
|
|
||||||
|| api64_o.IsFilePathLocked()
|
|
||||||
|| config.IsFilePathLocked())
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,8 +102,10 @@ internal class ProgramSelection
|
||||||
|
|
||||||
private void Toggle(string dlcAppId, (DlcType type, string name, string icon) dlcApp, bool enabled)
|
private void Toggle(string dlcAppId, (DlcType type, string name, string icon) dlcApp, bool enabled)
|
||||||
{
|
{
|
||||||
if (enabled) SelectedDlc[dlcAppId] = dlcApp;
|
if (enabled)
|
||||||
else _ = SelectedDlc.Remove(dlcAppId);
|
SelectedDlc[dlcAppId] = dlcApp;
|
||||||
|
else
|
||||||
|
_ = SelectedDlc.Remove(dlcAppId);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ToggleDlc(string dlcId, bool enabled)
|
internal void ToggleDlc(string dlcId, bool enabled)
|
||||||
|
@ -160,7 +136,8 @@ internal class ProgramSelection
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ = DllDirectories.RemoveAll(directory => !Directory.Exists(directory));
|
_ = 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)
|
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)
|
internal static void ValidateAll(List<(Platform platform, string id, string name)> programsToScan)
|
||||||
=> AllSafe.ForEach(selection => selection.Validate(programsToScan));
|
=> AllSafe.ForEach(selection => selection.Validate(programsToScan));
|
||||||
|
|
||||||
internal static ProgramSelection FromPlatformId(Platform platform, string gameId)
|
internal static ProgramSelection FromPlatformId(Platform platform, string gameId) => AllSafe.Find(s => s.Platform == platform && s.Id == gameId);
|
||||||
=> AllSafe.Find(s => s.Platform == platform && s.Id == gameId);
|
|
||||||
|
|
||||||
internal static (string gameId, (DlcType type, string name, string icon) app)? GetDlcFromPlatformId(
|
internal static (string gameId, (DlcType type, string name, string icon) app)? GetDlcFromPlatformId(Platform platform, string dlcId)
|
||||||
Platform platform, string dlcId)
|
|
||||||
{
|
{
|
||||||
foreach (ProgramSelection selection in AllSafe.Where(s => s.Platform == platform))
|
foreach (ProgramSelection selection in AllSafe.Where(s => s.Platform == platform))
|
||||||
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(
|
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(p => p.Key == dlcId))
|
||||||
p => p.Key == dlcId))
|
|
||||||
return (selection.Id, pair.Value);
|
return (selection.Id, pair.Value);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,27 +14,22 @@ internal static class Koaloader
|
||||||
{
|
{
|
||||||
internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new()
|
internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new()
|
||||||
{
|
{
|
||||||
("Koaloader", "Unlocker.dll"), ("Koaloader", "Unlocker32.dll"), ("Koaloader", "Unlocker64.dll"),
|
("Koaloader", "Unlocker.dll"), ("Koaloader", "Unlocker32.dll"), ("Koaloader", "Unlocker64.dll"), ("Lyptus", "Lyptus.dll"),
|
||||||
("Lyptus", "Lyptus.dll"), ("Lyptus", "Lyptus32.dll"), ("Lyptus", "Lyptus64.dll"),
|
("Lyptus", "Lyptus32.dll"), ("Lyptus", "Lyptus64.dll"), ("SmokeAPI", "SmokeAPI.dll"), ("SmokeAPI", "SmokeAPI32.dll"),
|
||||||
("SmokeAPI", "SmokeAPI.dll"), ("SmokeAPI", "SmokeAPI32.dll"), ("SmokeAPI", "SmokeAPI64.dll"),
|
("SmokeAPI", "SmokeAPI64.dll"), ("ScreamAPI", "ScreamAPI.dll"), ("ScreamAPI", "ScreamAPI32.dll"), ("ScreamAPI", "ScreamAPI64.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 R1 Unlocker", "UplayR1Unlocker.dll"), ("Uplay R1 Unlocker", "UplayR1Unlocker32.dll"),
|
("Uplay R2 Unlocker", "UplayR2Unlocker.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.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(
|
internal static void GetKoaloaderComponents(this string directory, out List<string> proxies, out string config)
|
||||||
this string directory,
|
|
||||||
out List<string> proxies,
|
|
||||||
out string config
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
proxies = new List<string>();
|
proxies = new();
|
||||||
foreach (string proxy in EmbeddedResources.Select(proxy =>
|
foreach (string proxy in EmbeddedResources.Select(proxy =>
|
||||||
{
|
{
|
||||||
proxy = proxy[(proxy.IndexOf('.') + 1)..];
|
proxy = proxy[(proxy.IndexOf('.') + 1)..];
|
||||||
return proxy[(proxy.IndexOf('.') + 1)..];
|
return proxy[(proxy.IndexOf('.') + 1)..];
|
||||||
})) proxies.Add(directory + @"\" + proxy);
|
}))
|
||||||
|
proxies.Add(directory + @"\" + proxy);
|
||||||
config = directory + @"\Koaloader.json";
|
config = directory + @"\Koaloader.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +46,7 @@ internal static class Koaloader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void GetProxyInfoFromIdentifier(this string resourceIdentifier, out string proxyName,
|
internal static void GetProxyInfoFromIdentifier(this string resourceIdentifier, out string proxyName, out BinaryType binaryType)
|
||||||
out BinaryType binaryType)
|
|
||||||
{
|
{
|
||||||
string baseIdentifier = resourceIdentifier[(resourceIdentifier.IndexOf('.') + 1)..];
|
string baseIdentifier = resourceIdentifier[(resourceIdentifier.IndexOf('.') + 1)..];
|
||||||
baseIdentifier = baseIdentifier[..baseIdentifier.IndexOf('.')];
|
baseIdentifier = baseIdentifier[..baseIdentifier.IndexOf('.')];
|
||||||
|
@ -83,13 +77,12 @@ internal static class Koaloader
|
||||||
else if (File.Exists(config))
|
else if (File.Exists(config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(config);
|
||||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, string> targets,
|
internal static void WriteConfig(StreamWriter writer, SortedList<string, string> targets, SortedList<string, string> modules,
|
||||||
SortedList<string, string> modules, InstallForm installForm = null)
|
InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
writer.WriteLine(" \"logging\": false,");
|
writer.WriteLine(" \"logging\": false,");
|
||||||
|
@ -108,9 +101,7 @@ internal static class Koaloader
|
||||||
writer.WriteLine(" ]");
|
writer.WriteLine(" ]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"targets\": []");
|
writer.WriteLine(" \"targets\": []");
|
||||||
}
|
|
||||||
if (modules.Any())
|
if (modules.Any())
|
||||||
{
|
{
|
||||||
writer.WriteLine(" \"modules\": [");
|
writer.WriteLine(" \"modules\": [");
|
||||||
|
@ -127,235 +118,216 @@ internal static class Koaloader
|
||||||
writer.WriteLine(" ]");
|
writer.WriteLine(" ]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"modules\": []");
|
writer.WriteLine(" \"modules\": []");
|
||||||
}
|
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task Uninstall(string directory, string rootDirectory = null, InstallForm installForm = null,
|
internal static async Task Uninstall(string directory, string rootDirectory = null, InstallForm installForm = null, bool deleteConfig = true)
|
||||||
bool deleteConfig = true) => await Task.Run(async () =>
|
=> 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)))
|
|
||||||
{
|
{
|
||||||
File.Delete(proxyPath);
|
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
|
||||||
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false);
|
foreach (string proxyPath in proxies.Where(proxyPath => File.Exists(proxyPath) && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader)))
|
||||||
}
|
{
|
||||||
foreach ((string unlocker, string path) in AutoLoadDlls
|
File.Delete(proxyPath);
|
||||||
.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false);
|
||||||
.Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile()))
|
}
|
||||||
{
|
foreach ((string unlocker, string path) in AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||||
File.Delete(path);
|
.Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile()))
|
||||||
installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
{
|
||||||
}
|
File.Delete(path);
|
||||||
if (deleteConfig && File.Exists(config))
|
installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
{
|
}
|
||||||
File.Delete(config);
|
if (deleteConfig && File.Exists(config))
|
||||||
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
{
|
||||||
}
|
File.Delete(config);
|
||||||
await SmokeAPI.Uninstall(directory, installForm, deleteConfig);
|
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||||
await ScreamAPI.Uninstall(directory, installForm, deleteConfig);
|
}
|
||||||
await UplayR1.Uninstall(directory, installForm, deleteConfig);
|
await SmokeAPI.Uninstall(directory, installForm, deleteConfig);
|
||||||
await UplayR2.Uninstall(directory, installForm, deleteConfig);
|
await ScreamAPI.Uninstall(directory, installForm, deleteConfig);
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
await UplayR1.Uninstall(directory, installForm, deleteConfig);
|
||||||
await Uninstall(rootDirectory, null, installForm, deleteConfig);
|
await UplayR2.Uninstall(directory, installForm, deleteConfig);
|
||||||
});
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
|
await Uninstall(rootDirectory, null, installForm, deleteConfig);
|
||||||
|
});
|
||||||
|
|
||||||
internal static async Task Install(string directory, BinaryType binaryType, ProgramSelection selection,
|
internal static async Task Install(string directory, BinaryType binaryType, ProgramSelection selection, string rootDirectory = null,
|
||||||
string rootDirectory = null, InstallForm installForm = null,
|
InstallForm installForm = null, bool generateConfig = true)
|
||||||
bool generateConfig = true) => await Task.Run(() =>
|
=> 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)))
|
|
||||||
{
|
{
|
||||||
File.Delete(_path);
|
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
|
||||||
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, false);
|
string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy;
|
||||||
}
|
string path = directory + @"\" + proxy + ".dll";
|
||||||
if (File.Exists(path) && !path.IsResourceFile(ResourceIdentifier.Koaloader))
|
foreach (string _path in proxies.Where(p => p != path && File.Exists(p) && p.IsResourceFile(ResourceIdentifier.Koaloader)))
|
||||||
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);
|
|
||||||
bool bit32 = false, bit64 = false;
|
|
||||||
foreach (string executable in Directory.EnumerateFiles(directory, "*.exe"))
|
|
||||||
if (executable.TryGetFileBinaryType(out BinaryType binaryType))
|
|
||||||
{
|
{
|
||||||
if (binaryType == BinaryType.BIT32)
|
File.Delete(_path);
|
||||||
bit32 = true;
|
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, false);
|
||||||
else if (binaryType == BinaryType.BIT64)
|
|
||||||
bit64 = true;
|
|
||||||
if (bit32 && bit64)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
if (File.Exists(path) && !path.IsResourceFile(ResourceIdentifier.Koaloader))
|
||||||
{
|
throw new CustomMessageException("A non-Koaloader DLL named " + proxy + ".dll already exists in this directory!");
|
||||||
if (bit32)
|
path.WriteProxy(proxy, binaryType);
|
||||||
{
|
installForm?.UpdateUser($"Wrote {(binaryType == BinaryType.BIT32 ? "32-bit" : "64-bit")} Koaloader: {Path.GetFileName(path)}", LogTextBox.Action,
|
||||||
path = directory + @"\SmokeAPI32.dll";
|
false);
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
bool bit32 = false, bit64 = false;
|
||||||
|
foreach (string executable in Directory.EnumerateFiles(directory, "*.exe"))
|
||||||
|
if (executable.TryGetFileBinaryType(out BinaryType binaryType))
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
if (binaryType == BinaryType.BIT32)
|
||||||
{
|
bit32 = true;
|
||||||
File.Delete(path);
|
else if (binaryType == BinaryType.BIT64)
|
||||||
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}",
|
bit64 = true;
|
||||||
LogTextBox.Action, false);
|
if (bit32 && bit64)
|
||||||
}
|
break;
|
||||||
path = rootDirectory + @"\SmokeAPI32.dll";
|
|
||||||
}
|
}
|
||||||
"SmokeAPI.steam_api.dll".Write(path);
|
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
||||||
installForm?.UpdateUser(
|
|
||||||
$"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
|
||||||
if (bit64)
|
|
||||||
{
|
{
|
||||||
path = directory + @"\SmokeAPI64.dll";
|
if (bit32)
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
path = directory + @"\SmokeAPI32.dll";
|
||||||
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
{
|
{
|
||||||
File.Delete(path);
|
if (File.Exists(path))
|
||||||
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}",
|
{
|
||||||
LogTextBox.Action, false);
|
File.Delete(path);
|
||||||
|
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\SmokeAPI32.dll";
|
||||||
}
|
}
|
||||||
path = rootDirectory + @"\SmokeAPI64.dll";
|
"SmokeAPI.steam_api.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
"SmokeAPI.steam_api64.dll".Write(path);
|
if (bit64)
|
||||||
installForm?.UpdateUser(
|
{
|
||||||
$"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
path = directory + @"\SmokeAPI64.dll";
|
||||||
LogTextBox.Action, false);
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
installForm?.UpdateUser($"Deleted SmokeAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\SmokeAPI64.dll";
|
||||||
|
}
|
||||||
|
"SmokeAPI.steam_api64.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote SmokeAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
SmokeAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||||
}
|
}
|
||||||
SmokeAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
if (selection.Platform is Platform.Epic or Platform.Paradox)
|
||||||
}
|
|
||||||
if (selection.Platform is Platform.Epic or Platform.Paradox)
|
|
||||||
{
|
|
||||||
if (bit32)
|
|
||||||
{
|
{
|
||||||
path = directory + @"\ScreamAPI32.dll";
|
if (bit32)
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
path = directory + @"\ScreamAPI32.dll";
|
||||||
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
{
|
{
|
||||||
File.Delete(path);
|
if (File.Exists(path))
|
||||||
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}",
|
{
|
||||||
LogTextBox.Action, false);
|
File.Delete(path);
|
||||||
|
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\ScreamAPI32.dll";
|
||||||
}
|
}
|
||||||
path = rootDirectory + @"\ScreamAPI32.dll";
|
"ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
"ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(path);
|
if (bit64)
|
||||||
installForm?.UpdateUser(
|
{
|
||||||
$"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
path = directory + @"\ScreamAPI64.dll";
|
||||||
LogTextBox.Action, false);
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\ScreamAPI64.dll";
|
||||||
|
}
|
||||||
|
"ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
ScreamAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||||
}
|
}
|
||||||
if (bit64)
|
if (selection.Platform is Platform.Ubisoft)
|
||||||
{
|
{
|
||||||
path = directory + @"\ScreamAPI64.dll";
|
if (bit32)
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
path = directory + @"\UplayR1Unlocker32.dll";
|
||||||
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
{
|
{
|
||||||
File.Delete(path);
|
if (File.Exists(path))
|
||||||
installForm?.UpdateUser($"Deleted ScreamAPI from non-root directory: {Path.GetFileName(path)}",
|
{
|
||||||
LogTextBox.Action, false);
|
File.Delete(path);
|
||||||
|
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\UplayR1Unlocker32.dll";
|
||||||
}
|
}
|
||||||
path = rootDirectory + @"\ScreamAPI64.dll";
|
"UplayR1.uplay_r1_loader.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
"ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(path);
|
if (bit64)
|
||||||
installForm?.UpdateUser(
|
|
||||||
$"Wrote ScreamAPI{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
|
||||||
ScreamAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
|
||||||
}
|
|
||||||
if (selection.Platform is Platform.Ubisoft)
|
|
||||||
{
|
|
||||||
if (bit32)
|
|
||||||
{
|
|
||||||
path = directory + @"\UplayR1Unlocker32.dll";
|
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
path = directory + @"\UplayR1Unlocker64.dll";
|
||||||
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
{
|
{
|
||||||
File.Delete(path);
|
if (File.Exists(path))
|
||||||
installForm?.UpdateUser(
|
{
|
||||||
$"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}",
|
File.Delete(path);
|
||||||
LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\UplayR1Unlocker64.dll";
|
||||||
}
|
}
|
||||||
path = rootDirectory + @"\UplayR1Unlocker32.dll";
|
"UplayR1.uplay_r1_loader64.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
"UplayR1.uplay_r1_loader.dll".Write(path);
|
UplayR1.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||||
installForm?.UpdateUser(
|
if (bit32)
|
||||||
$"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
|
||||||
if (bit64)
|
|
||||||
{
|
|
||||||
path = directory + @"\UplayR1Unlocker64.dll";
|
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
path = directory + @"\UplayR2Unlocker32.dll";
|
||||||
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
{
|
{
|
||||||
File.Delete(path);
|
if (File.Exists(path))
|
||||||
installForm?.UpdateUser(
|
{
|
||||||
$"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}",
|
File.Delete(path);
|
||||||
LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\UplayR2Unlocker32.dll";
|
||||||
}
|
}
|
||||||
path = rootDirectory + @"\UplayR1Unlocker64.dll";
|
"UplayR2.upc_r2_loader.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
"UplayR1.uplay_r1_loader64.dll".Write(path);
|
if (bit64)
|
||||||
installForm?.UpdateUser(
|
|
||||||
$"Wrote Uplay R1 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
|
||||||
UplayR1.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
|
||||||
if (bit32)
|
|
||||||
{
|
|
||||||
path = directory + @"\UplayR2Unlocker32.dll";
|
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
path = directory + @"\UplayR2Unlocker64.dll";
|
||||||
|
if (rootDirectory is not null && directory != rootDirectory)
|
||||||
{
|
{
|
||||||
File.Delete(path);
|
if (File.Exists(path))
|
||||||
installForm?.UpdateUser(
|
{
|
||||||
$"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}",
|
File.Delete(path);
|
||||||
LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
|
path = rootDirectory + @"\UplayR2Unlocker64.dll";
|
||||||
}
|
}
|
||||||
path = rootDirectory + @"\UplayR2Unlocker32.dll";
|
"UplayR2.upc_r2_loader64.dll".Write(path);
|
||||||
|
installForm?.UpdateUser(
|
||||||
|
$"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
||||||
|
LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
"UplayR2.upc_r2_loader.dll".Write(path);
|
UplayR2.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||||
installForm?.UpdateUser(
|
|
||||||
$"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (bit64)
|
if (generateConfig)
|
||||||
{
|
CheckConfig(directory, selection, installForm);
|
||||||
path = directory + @"\UplayR2Unlocker64.dll";
|
});
|
||||||
if (rootDirectory is not null && directory != rootDirectory)
|
|
||||||
{
|
|
||||||
if (File.Exists(path))
|
|
||||||
{
|
|
||||||
File.Delete(path);
|
|
||||||
installForm?.UpdateUser(
|
|
||||||
$"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
|
||||||
path = rootDirectory + @"\UplayR2Unlocker64.dll";
|
|
||||||
}
|
|
||||||
"UplayR2.upc_r2_loader64.dll".Write(path);
|
|
||||||
installForm?.UpdateUser(
|
|
||||||
$"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
|
||||||
UplayR2.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
|
||||||
}
|
|
||||||
if (generateConfig)
|
|
||||||
CheckConfig(directory, selection, installForm);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,7 +335,7 @@ internal static class Resources
|
||||||
if (embeddedResources is null)
|
if (embeddedResources is null)
|
||||||
{
|
{
|
||||||
string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
||||||
embeddedResources = new List<string>();
|
embeddedResources = new();
|
||||||
foreach (string resourceName in names.Where(n => n.StartsWith("CreamInstaller.Resources.")))
|
foreach (string resourceName in names.Where(n => n.StartsWith("CreamInstaller.Resources.")))
|
||||||
embeddedResources.Add(resourceName[25..]);
|
embeddedResources.Add(resourceName[25..]);
|
||||||
}
|
}
|
||||||
|
@ -345,8 +345,7 @@ internal static class Resources
|
||||||
|
|
||||||
internal static void Write(this string resourceIdentifier, string filePath)
|
internal static void Write(this string resourceIdentifier, string filePath)
|
||||||
{
|
{
|
||||||
using Stream resource = Assembly.GetExecutingAssembly()
|
using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier);
|
||||||
.GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier);
|
|
||||||
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
|
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
|
||||||
resource.CopyTo(file);
|
resource.CopyTo(file);
|
||||||
}
|
}
|
||||||
|
@ -378,45 +377,42 @@ internal static class Resources
|
||||||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
|
||||||
private static extern bool GetBinaryType(string lpApplicationName, out BinaryType lpBinaryType);
|
private static extern bool GetBinaryType(string lpApplicationName, out BinaryType lpBinaryType);
|
||||||
|
|
||||||
internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType)
|
internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => GetBinaryType(path, out binaryType);
|
||||||
=> GetBinaryType(path, out binaryType);
|
|
||||||
|
|
||||||
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(
|
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(this string rootDirectory, bool filterCommon = false,
|
||||||
this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) =>
|
Func<string, bool> validFunc = null)
|
||||||
await Task.Run(async () => (await rootDirectory.GetExecutables(filterCommon, validFunc)
|
=> await Task.Run(async ()
|
||||||
?? (filterCommon || validFunc is not null
|
=> (await rootDirectory.GetExecutables(filterCommon, validFunc)
|
||||||
? await rootDirectory.GetExecutables()
|
?? (filterCommon || validFunc is not null ? await rootDirectory.GetExecutables() : null))?.Select(e =>
|
||||||
: null))?.Select(e =>
|
{
|
||||||
{
|
e.path = Path.GetDirectoryName(e.path);
|
||||||
e.path = Path.GetDirectoryName(e.path);
|
return e;
|
||||||
return e;
|
})?.DistinctBy(e => e.path).ToList());
|
||||||
})?.DistinctBy(e => e.path).ToList());
|
|
||||||
|
|
||||||
internal static async Task<List<(string path, BinaryType binaryType)>> GetExecutables(
|
internal static async Task<List<(string path, BinaryType binaryType)>> GetExecutables(this string rootDirectory, bool filterCommon = false,
|
||||||
this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) => await Task.Run(
|
Func<string, bool> validFunc = null)
|
||||||
() =>
|
=> await Task.Run(() =>
|
||||||
{
|
{
|
||||||
List<(string path, BinaryType binaryType)> executables = new();
|
List<(string path, BinaryType binaryType)> executables = new();
|
||||||
if (Program.Canceled || !Directory.Exists(rootDirectory)) return null;
|
if (Program.Canceled || !Directory.Exists(rootDirectory))
|
||||||
foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe",
|
return null;
|
||||||
new EnumerationOptions { RecurseSubdirectories = true }))
|
foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe", new EnumerationOptions { RecurseSubdirectories = true }))
|
||||||
{
|
{
|
||||||
if (Program.Canceled) return null;
|
if (Program.Canceled)
|
||||||
if (executables.All(e => e.path != path)
|
return null;
|
||||||
&& (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
|
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
|
||||||
&& (validFunc is null || validFunc(path))
|
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType)
|
||||||
&& path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64)
|
&& binaryType is BinaryType.BIT64)
|
||||||
executables.Add((path, binaryType));
|
executables.Add((path, binaryType));
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe",
|
foreach (string path in Directory.EnumerateFiles(rootDirectory, "*.exe", new EnumerationOptions { RecurseSubdirectories = true }))
|
||||||
new EnumerationOptions { RecurseSubdirectories = true }))
|
|
||||||
{
|
{
|
||||||
if (Program.Canceled) return null;
|
if (Program.Canceled)
|
||||||
if (executables.All(e => e.path != path)
|
return null;
|
||||||
&& (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
|
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
|
||||||
&& (validFunc is null || validFunc(path))
|
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType)
|
||||||
&& path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32)
|
&& binaryType is BinaryType.BIT32)
|
||||||
executables.Add((path, binaryType));
|
executables.Add((path, binaryType));
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
|
@ -426,91 +422,62 @@ internal static class Resources
|
||||||
internal static bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
|
internal static bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
|
||||||
{
|
{
|
||||||
string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath();
|
string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath();
|
||||||
return subPath.Contains("SETUP")
|
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|
||||||
|| subPath.Contains("REDIST")
|
|| subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")) || subPath.Contains("HELPER")
|
||||||
|| subPath.Contains("SUPPORT")
|
|| subPath.Contains("CEFPROCESS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS")
|
||||||
|| (subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")))
|
|| subPath.Contains("MODDING") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE")
|
||||||
|| 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");
|
|| subPath.Contains("ANTICHEAT");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(
|
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform)
|
||||||
this string gameDirectory, Platform platform) => await Task.Run(() =>
|
=> 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 })
|
|
||||||
.Append(gameDirectory))
|
|
||||||
{
|
{
|
||||||
if (Program.Canceled) return null;
|
List<string> dllDirectories = new();
|
||||||
string subDirectory = directory.BeautifyPath();
|
if (Program.Canceled || !Directory.Exists(gameDirectory))
|
||||||
if (!dllDirectories.Contains(subDirectory))
|
return null;
|
||||||
|
foreach (string directory in Directory.EnumerateDirectories(gameDirectory, "*", new EnumerationOptions { RecurseSubdirectories = true })
|
||||||
|
.Append(gameDirectory))
|
||||||
{
|
{
|
||||||
bool koaloaderInstalled = Koaloader.AutoLoadDlls
|
if (Program.Canceled)
|
||||||
.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
return null;
|
||||||
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
string subDirectory = directory.BeautifyPath();
|
||||||
if (platform is Platform.Steam or Platform.Paradox)
|
if (!dllDirectories.Contains(subDirectory))
|
||||||
{
|
{
|
||||||
subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64,
|
bool koaloaderInstalled = Koaloader.AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||||
out string api64_o, out string config, out string cache);
|
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
||||||
if (File.Exists(api)
|
if (platform is Platform.Steam or Platform.Paradox)
|
||||||
|| File.Exists(api_o)
|
{
|
||||||
|| File.Exists(api64)
|
subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string config,
|
||||||
|| File.Exists(api64_o)
|
out string cache);
|
||||||
|| (File.Exists(config) && !koaloaderInstalled)
|
if (File.Exists(api) || File.Exists(api_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled
|
||||||
|| (File.Exists(cache) && !koaloaderInstalled))
|
|| File.Exists(cache) && !koaloaderInstalled)
|
||||||
dllDirectories.Add(subDirectory);
|
dllDirectories.Add(subDirectory);
|
||||||
}
|
}
|
||||||
if (platform is Platform.Epic or Platform.Paradox)
|
if (platform is Platform.Epic or Platform.Paradox)
|
||||||
{
|
{
|
||||||
subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64,
|
subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
out string api64_o, out string config);
|
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o)
|
||||||
if (File.Exists(api32)
|
|| File.Exists(config) && !koaloaderInstalled)
|
||||||
|| File.Exists(api32_o)
|
dllDirectories.Add(subDirectory);
|
||||||
|| File.Exists(api64)
|
}
|
||||||
|| File.Exists(api64_o)
|
if (platform is Platform.Ubisoft)
|
||||||
|| (File.Exists(config) && !koaloaderInstalled))
|
{
|
||||||
dllDirectories.Add(subDirectory);
|
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)
|
||||||
if (platform is Platform.Ubisoft)
|
|| File.Exists(config) && !koaloaderInstalled)
|
||||||
{
|
dllDirectories.Add(subDirectory);
|
||||||
subDirectory.GetUplayR1Components(out string api32, out string api32_o, out string api64,
|
subDirectory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o,
|
||||||
out string api64_o, out string config);
|
out config);
|
||||||
if (File.Exists(api32)
|
if (File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64)
|
||||||
|| File.Exists(api32_o)
|
|| File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled)
|
||||||
|| File.Exists(api64)
|
dllDirectories.Add(subDirectory);
|
||||||
|| 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))
|
|
||||||
dllDirectories.Add(subDirectory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return !dllDirectories.Any() ? null : dllDirectories;
|
||||||
return !dllDirectories.Any() ? null : dllDirectories;
|
});
|
||||||
});
|
|
||||||
|
|
||||||
internal static void GetCreamApiComponents(
|
internal static void GetCreamApiComponents(this string directory, out string api32, out string api32_o, out string api64, out string api64_o,
|
||||||
this string directory,
|
|
||||||
out string api32, out string api32_o,
|
|
||||||
out string api64, out string api64_o,
|
|
||||||
out string config)
|
out string config)
|
||||||
{
|
{
|
||||||
api32 = directory + @"\steam_api.dll";
|
api32 = directory + @"\steam_api.dll";
|
||||||
|
@ -522,7 +489,8 @@ internal static class Resources
|
||||||
|
|
||||||
internal static string ComputeMD5(this string filePath)
|
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
|
#pragma warning disable CA5351 // Do Not Use Broken Cryptographic Algorithms
|
||||||
using MD5 md5 = MD5.Create();
|
using MD5 md5 = MD5.Create();
|
||||||
#pragma warning restore CA5351 // Do Not Use Broken Cryptographic Algorithms
|
#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)
|
internal static bool IsResourceFile(this string filePath, ResourceIdentifier identifier)
|
||||||
=> filePath.ComputeMD5() is string hash && ResourceMD5s[identifier].Contains(hash);
|
=> filePath.ComputeMD5() is string hash && ResourceMD5s[identifier].Contains(hash);
|
||||||
|
|
||||||
internal static bool IsResourceFile(this string filePath) => filePath.ComputeMD5() is string hash
|
internal static bool IsResourceFile(this string filePath)
|
||||||
&& ResourceMD5s.Values.Any(
|
=> filePath.ComputeMD5() is string hash && ResourceMD5s.Values.Any(hashes => hashes.Contains(hash));
|
||||||
hashes => hashes.Contains(hash));
|
|
||||||
|
|
||||||
internal enum BinaryType
|
internal enum BinaryType
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,12 +11,8 @@ namespace CreamInstaller.Resources;
|
||||||
|
|
||||||
internal static class ScreamAPI
|
internal static class ScreamAPI
|
||||||
{
|
{
|
||||||
internal static void GetScreamApiComponents(
|
internal static void GetScreamApiComponents(this string directory, out string api32, out string api32_o, out string api64, out string api64_o,
|
||||||
this string directory,
|
out string config)
|
||||||
out string api32, out string api32_o,
|
|
||||||
out string api64, out string api64_o,
|
|
||||||
out string config
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
api32 = directory + @"\EOSSDK-Win32-Shipping.dll";
|
api32 = directory + @"\EOSSDK-Win32-Shipping.dll";
|
||||||
api32_o = directory + @"\EOSSDK-Win32-Shipping_o.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);
|
directory.GetScreamApiComponents(out _, out _, out _, out _, out string config);
|
||||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideCatalogItems
|
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideCatalogItems
|
||||||
= selection.AllDlc.Where(pair => pair.Value.type is DlcType.EpicCatalogItem).Except(selection.SelectedDlc);
|
= 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
|
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||||
selection.ExtraSelectedDlc)
|
|
||||||
overrideCatalogItems = overrideCatalogItems.Except(extraDlc);
|
overrideCatalogItems = overrideCatalogItems.Except(extraDlc);
|
||||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> entitlements
|
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> entitlements
|
||||||
= selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement);
|
= selection.SelectedDlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement);
|
||||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> _dlc) in
|
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> _dlc) in selection.ExtraSelectedDlc)
|
||||||
selection.ExtraSelectedDlc)
|
|
||||||
entitlements = entitlements.Concat(_dlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement));
|
entitlements = entitlements.Concat(_dlc.Where(pair => pair.Value.type == DlcType.EpicEntitlement));
|
||||||
if (overrideCatalogItems.Any() || entitlements.Any())
|
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);*/
|
installForm.UpdateUser("Generating ScreamAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
||||||
File.Create(config).Close();
|
File.Create(config).Close();
|
||||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
StreamWriter writer = new(config, true, Encoding.UTF8);
|
||||||
WriteConfig(writer,
|
WriteConfig(writer, new(overrideCatalogItems.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
new(entitlements.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||||
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);
|
|
||||||
writer.Flush();
|
writer.Flush();
|
||||||
writer.Close();
|
writer.Close();
|
||||||
}
|
}
|
||||||
else if (File.Exists(config))
|
else if (File.Exists(config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(config);
|
||||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer,
|
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideCatalogItems,
|
||||||
SortedList<string, (DlcType type, string name, string icon)> overrideCatalogItems,
|
SortedList<string, (DlcType type, string name, string icon)> entitlements, InstallForm installForm = null)
|
||||||
SortedList<string, (DlcType type, string name, string icon)> entitlements,
|
|
||||||
InstallForm installForm = null)
|
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
writer.WriteLine(" \"version\": 2,");
|
writer.WriteLine(" \"version\": 2,");
|
||||||
|
@ -77,22 +63,18 @@ internal static class ScreamAPI
|
||||||
if (overrideCatalogItems.Any())
|
if (overrideCatalogItems.Any())
|
||||||
{
|
{
|
||||||
writer.WriteLine(" \"override\": [");
|
writer.WriteLine(" \"override\": [");
|
||||||
KeyValuePair<string, (DlcType type, string name, string icon)> lastOverrideCatalogItem
|
KeyValuePair<string, (DlcType type, string name, string icon)> lastOverrideCatalogItem = overrideCatalogItems.Last();
|
||||||
= overrideCatalogItems.Last();
|
|
||||||
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in overrideCatalogItems)
|
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in overrideCatalogItems)
|
||||||
{
|
{
|
||||||
string id = pair.Key;
|
string id = pair.Key;
|
||||||
(_, string name, _) = pair.Value;
|
(_, string name, _) = pair.Value;
|
||||||
writer.WriteLine($" \"{id}\"{(pair.Equals(lastOverrideCatalogItem) ? "" : ",")}");
|
writer.WriteLine($" \"{id}\"{(pair.Equals(lastOverrideCatalogItem) ? "" : ",")}");
|
||||||
installForm?.UpdateUser($"Added override catalog item to ScreamAPI.json with id {id} ({name})",
|
installForm?.UpdateUser($"Added override catalog item to ScreamAPI.json with id {id} ({name})", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
writer.WriteLine(" ]");
|
writer.WriteLine(" ]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"override\": []");
|
writer.WriteLine(" \"override\": []");
|
||||||
}
|
|
||||||
writer.WriteLine(" },");
|
writer.WriteLine(" },");
|
||||||
writer.WriteLine(" \"entitlements\": {");
|
writer.WriteLine(" \"entitlements\": {");
|
||||||
writer.WriteLine(" \"unlock_all\": true,");
|
writer.WriteLine(" \"unlock_all\": true,");
|
||||||
|
@ -106,15 +88,12 @@ internal static class ScreamAPI
|
||||||
string id = pair.Key;
|
string id = pair.Key;
|
||||||
(_, string name, _) = pair.Value;
|
(_, string name, _) = pair.Value;
|
||||||
writer.WriteLine($" \"{id}\"{(pair.Equals(lastEntitlement) ? "" : ",")}");
|
writer.WriteLine($" \"{id}\"{(pair.Equals(lastEntitlement) ? "" : ",")}");
|
||||||
installForm?.UpdateUser($"Added entitlement to ScreamAPI.json with id {id} ({name})", LogTextBox.Action,
|
installForm?.UpdateUser($"Added entitlement to ScreamAPI.json with id {id} ({name})", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
writer.WriteLine(" ]");
|
writer.WriteLine(" ]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"inject\": []");
|
writer.WriteLine(" \"inject\": []");
|
||||||
}
|
|
||||||
writer.WriteLine(" }");
|
writer.WriteLine(" }");
|
||||||
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)
|
internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true)
|
||||||
=> await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
{
|
||||||
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o,
|
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
out string config);
|
|
||||||
if (File.Exists(api32_o))
|
if (File.Exists(api32_o))
|
||||||
{
|
{
|
||||||
if (File.Exists(api32))
|
if (File.Exists(api32))
|
||||||
|
@ -132,8 +110,7 @@ internal static class ScreamAPI
|
||||||
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
File.Move(api32_o, api32);
|
File.Move(api32_o, api32);
|
||||||
installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}",
|
installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (File.Exists(api64_o))
|
if (File.Exists(api64_o))
|
||||||
{
|
{
|
||||||
|
@ -143,8 +120,7 @@ internal static class ScreamAPI
|
||||||
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
File.Move(api64_o, api64);
|
File.Move(api64_o, api64);
|
||||||
installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}",
|
installForm?.UpdateUser($"Restored EOS: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (deleteConfig && File.Exists(config))
|
if (deleteConfig && File.Exists(config))
|
||||||
{
|
{
|
||||||
|
@ -153,34 +129,31 @@ internal static class ScreamAPI
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null,
|
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true)
|
||||||
bool generateConfig = true) => await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
|
||||||
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o,
|
|
||||||
out string config);
|
|
||||||
if (File.Exists(api32) && !File.Exists(api32_o))
|
|
||||||
{
|
{
|
||||||
File.Move(api32, api32_o);
|
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}",
|
if (File.Exists(api32) && !File.Exists(api32_o))
|
||||||
LogTextBox.Action, false);
|
{
|
||||||
}
|
File.Move(api32, api32_o);
|
||||||
if (File.Exists(api32_o))
|
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||||
{
|
}
|
||||||
"ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(api32);
|
if (File.Exists(api32_o))
|
||||||
installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
{
|
||||||
}
|
"ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(api32);
|
||||||
if (File.Exists(api64) && !File.Exists(api64_o))
|
installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
{
|
}
|
||||||
File.Move(api64, api64_o);
|
if (File.Exists(api64) && !File.Exists(api64_o))
|
||||||
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}",
|
{
|
||||||
LogTextBox.Action, false);
|
File.Move(api64, api64_o);
|
||||||
}
|
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||||
if (File.Exists(api64_o))
|
}
|
||||||
{
|
if (File.Exists(api64_o))
|
||||||
"ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(api64);
|
{
|
||||||
installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
"ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(api64);
|
||||||
}
|
installForm?.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
if (generateConfig)
|
}
|
||||||
CheckConfig(directory, selection, installForm);
|
if (generateConfig)
|
||||||
});
|
CheckConfig(directory, selection, installForm);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,8 @@ namespace CreamInstaller.Resources;
|
||||||
|
|
||||||
internal static class SmokeAPI
|
internal static class SmokeAPI
|
||||||
{
|
{
|
||||||
internal static void GetSmokeApiComponents(
|
internal static void GetSmokeApiComponents(this string directory, out string api32, out string api32_o, out string api64, out string api64_o,
|
||||||
this string directory,
|
out string config, out string cache)
|
||||||
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 = directory + @"\steam_api.dll";
|
||||||
api32_o = directory + @"\steam_api_o.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)
|
internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
directory.GetSmokeApiComponents(out _, out _, out _, out _, out string config, out _);
|
directory.GetSmokeApiComponents(out _, out _, out _, out _, out string config, out _);
|
||||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc
|
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
||||||
= selection.AllDlc.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)
|
|
||||||
overrideDlc = overrideDlc.Except(extraDlc);
|
overrideDlc = overrideDlc.Except(extraDlc);
|
||||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> injectDlc
|
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> injectDlc
|
||||||
= new List<KeyValuePair<string, (DlcType type, string name, string icon)>>();
|
= new List<KeyValuePair<string, (DlcType type, string name, string icon)>>();
|
||||||
if (selection.AllDlc.Count > 64 || selection.ExtraDlc.Any(e => e.dlc.Count > 64))
|
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));
|
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
|
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||||
selection.ExtraSelectedDlc)
|
|
||||||
if (selection.ExtraDlc.Where(e => e.id == id).Single().dlc.Count > 64)
|
if (selection.ExtraDlc.Where(e => e.id == id).Single().dlc.Count > 64)
|
||||||
injectDlc = injectDlc.Concat(extraDlc.Where(pair => pair.Value.type is DlcType.SteamHidden));
|
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);*/
|
installForm.UpdateUser("Generating SmokeAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
||||||
File.Create(config).Close();
|
File.Create(config).Close();
|
||||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
StreamWriter writer = new(config, true, Encoding.UTF8);
|
||||||
WriteConfig(writer,
|
WriteConfig(writer, new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||||
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);
|
|
||||||
writer.Flush();
|
writer.Flush();
|
||||||
writer.Close();
|
writer.Close();
|
||||||
}
|
}
|
||||||
else if (File.Exists(config))
|
else if (File.Exists(config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(config);
|
||||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer,
|
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideDlc,
|
||||||
SortedList<string, (DlcType type, string name, string icon)> overrideDlc,
|
SortedList<string, (DlcType type, string name, string icon)> injectDlc, InstallForm installForm = null)
|
||||||
SortedList<string, (DlcType type, string name, string icon)> injectDlc,
|
|
||||||
InstallForm installForm = null)
|
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
writer.WriteLine(" \"$version\": 1,");
|
writer.WriteLine(" \"$version\": 1,");
|
||||||
|
@ -86,15 +72,12 @@ internal static class SmokeAPI
|
||||||
string dlcId = pair.Key;
|
string dlcId = pair.Key;
|
||||||
(_, string dlcName, _) = pair.Value;
|
(_, string dlcName, _) = pair.Value;
|
||||||
writer.WriteLine($" {dlcId}{(pair.Equals(lastOverrideDlc) ? "" : ",")}");
|
writer.WriteLine($" {dlcId}{(pair.Equals(lastOverrideDlc) ? "" : ",")}");
|
||||||
installForm?.UpdateUser($"Added override DLC to SmokeAPI.json with appid {dlcId} ({dlcName})",
|
installForm?.UpdateUser($"Added override DLC to SmokeAPI.json with appid {dlcId} ({dlcName})", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
writer.WriteLine(" ],");
|
writer.WriteLine(" ],");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"override\": [],");
|
writer.WriteLine(" \"override\": [],");
|
||||||
}
|
|
||||||
if (injectDlc.Count > 0)
|
if (injectDlc.Count > 0)
|
||||||
{
|
{
|
||||||
writer.WriteLine(" \"dlc_ids\": [");
|
writer.WriteLine(" \"dlc_ids\": [");
|
||||||
|
@ -104,15 +87,12 @@ internal static class SmokeAPI
|
||||||
string dlcId = pair.Key;
|
string dlcId = pair.Key;
|
||||||
(_, string dlcName, _) = pair.Value;
|
(_, string dlcName, _) = pair.Value;
|
||||||
writer.WriteLine($" {dlcId}{(pair.Equals(lastInjectDlc) ? "" : ",")}");
|
writer.WriteLine($" {dlcId}{(pair.Equals(lastInjectDlc) ? "" : ",")}");
|
||||||
installForm?.UpdateUser($"Added inject DLC to SmokeAPI.json with appid {dlcId} ({dlcName})",
|
installForm?.UpdateUser($"Added inject DLC to SmokeAPI.json with appid {dlcId} ({dlcName})", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
writer.WriteLine(" ],");
|
writer.WriteLine(" ],");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"dlc_ids\": [],");
|
writer.WriteLine(" \"dlc_ids\": [],");
|
||||||
}
|
|
||||||
writer.WriteLine(" \"auto_inject_inventory\": true,");
|
writer.WriteLine(" \"auto_inject_inventory\": true,");
|
||||||
writer.WriteLine(" \"inventory_items\": []");
|
writer.WriteLine(" \"inventory_items\": []");
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
|
@ -125,11 +105,9 @@ internal static class SmokeAPI
|
||||||
if (File.Exists(oldConfig))
|
if (File.Exists(oldConfig))
|
||||||
{
|
{
|
||||||
File.Delete(oldConfig);
|
File.Delete(oldConfig);
|
||||||
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}",
|
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o,
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string cache);
|
||||||
out string config, out string cache);
|
|
||||||
if (File.Exists(api32_o))
|
if (File.Exists(api32_o))
|
||||||
{
|
{
|
||||||
if (File.Exists(api32))
|
if (File.Exists(api32))
|
||||||
|
@ -138,9 +116,7 @@ internal static class SmokeAPI
|
||||||
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
File.Move(api32_o, api32);
|
File.Move(api32_o, api32);
|
||||||
installForm?.UpdateUser(
|
installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
$"Restored Steamworks: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action,
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
if (File.Exists(api64_o))
|
if (File.Exists(api64_o))
|
||||||
{
|
{
|
||||||
|
@ -150,9 +126,7 @@ internal static class SmokeAPI
|
||||||
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
File.Move(api64_o, api64);
|
File.Move(api64_o, api64);
|
||||||
installForm?.UpdateUser(
|
installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
$"Restored Steamworks: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action,
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
if (deleteConfig && File.Exists(config))
|
if (deleteConfig && File.Exists(config))
|
||||||
{
|
{
|
||||||
|
@ -166,41 +140,37 @@ internal static class SmokeAPI
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null,
|
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true)
|
||||||
bool generateConfig = true) => await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
|
||||||
directory.GetCreamApiComponents(out _, out _, out _, out _, out string oldConfig);
|
|
||||||
if (File.Exists(oldConfig))
|
|
||||||
{
|
{
|
||||||
File.Delete(oldConfig);
|
directory.GetCreamApiComponents(out _, out _, out _, out _, out string oldConfig);
|
||||||
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}",
|
if (File.Exists(oldConfig))
|
||||||
LogTextBox.Action, false);
|
{
|
||||||
}
|
File.Delete(oldConfig);
|
||||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o,
|
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, false);
|
||||||
out string config, out _);
|
}
|
||||||
if (File.Exists(api32) && !File.Exists(api32_o))
|
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)}",
|
File.Move(api32, api32_o);
|
||||||
LogTextBox.Action, false);
|
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
if (File.Exists(api32_o))
|
if (File.Exists(api32_o))
|
||||||
{
|
{
|
||||||
"SmokeAPI.steam_api.dll".Write(api32);
|
"SmokeAPI.steam_api.dll".Write(api32);
|
||||||
installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
if (File.Exists(api64) && !File.Exists(api64_o))
|
if (File.Exists(api64) && !File.Exists(api64_o))
|
||||||
{
|
{
|
||||||
File.Move(api64, api64_o);
|
File.Move(api64, api64_o);
|
||||||
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}",
|
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
}
|
||||||
}
|
if (File.Exists(api64_o))
|
||||||
if (File.Exists(api64_o))
|
{
|
||||||
{
|
"SmokeAPI.steam_api64.dll".Write(api64);
|
||||||
"SmokeAPI.steam_api64.dll".Write(api64);
|
installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
installForm?.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
}
|
||||||
}
|
if (generateConfig)
|
||||||
if (generateConfig)
|
CheckConfig(directory, selection, installForm);
|
||||||
CheckConfig(directory, selection, installForm);
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,8 @@ namespace CreamInstaller.Resources;
|
||||||
|
|
||||||
internal static class UplayR1
|
internal static class UplayR1
|
||||||
{
|
{
|
||||||
internal static void GetUplayR1Components(
|
internal static void GetUplayR1Components(this string directory, out string api32, out string api32_o, out string api64, out string api64_o,
|
||||||
this string directory,
|
out string config)
|
||||||
out string api32, out string api32_o,
|
|
||||||
out string api64, out string api64_o,
|
|
||||||
out string config
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
api32 = directory + @"\uplay_r1_loader.dll";
|
api32 = directory + @"\uplay_r1_loader.dll";
|
||||||
api32_o = directory + @"\uplay_r1_loader_o.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)
|
internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
directory.GetUplayR1Components(out _, out _, out _, out _, out string config);
|
directory.GetUplayR1Components(out _, out _, out _, out _, out string config);
|
||||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc
|
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
||||||
= selection.AllDlc.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)
|
|
||||||
blacklistDlc = blacklistDlc.Except(extraDlc);
|
blacklistDlc = blacklistDlc.Except(extraDlc);
|
||||||
if (blacklistDlc.Any())
|
if (blacklistDlc.Any())
|
||||||
{
|
{
|
||||||
|
@ -39,24 +33,19 @@ internal static class UplayR1
|
||||||
installForm.UpdateUser("Generating Uplay R1 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
installForm.UpdateUser("Generating Uplay R1 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
||||||
File.Create(config).Close();
|
File.Create(config).Close();
|
||||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
StreamWriter writer = new(config, true, Encoding.UTF8);
|
||||||
WriteConfig(writer,
|
WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
|
||||||
blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
|
||||||
installForm);
|
|
||||||
writer.Flush();
|
writer.Flush();
|
||||||
writer.Close();
|
writer.Close();
|
||||||
}
|
}
|
||||||
else if (File.Exists(config))
|
else if (File.Exists(config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(config);
|
||||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer,
|
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||||
SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
InstallForm installForm = null)
|
||||||
InstallForm installForm = null)
|
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
writer.WriteLine(" \"logging\": false,");
|
writer.WriteLine(" \"logging\": false,");
|
||||||
|
@ -71,46 +60,38 @@ internal static class UplayR1
|
||||||
string dlcId = pair.Key;
|
string dlcId = pair.Key;
|
||||||
(_, string dlcName, _) = pair.Value;
|
(_, string dlcName, _) = pair.Value;
|
||||||
writer.WriteLine($" {dlcId}{(pair.Equals(lastBlacklistDlc) ? "" : ",")}");
|
writer.WriteLine($" {dlcId}{(pair.Equals(lastBlacklistDlc) ? "" : ",")}");
|
||||||
installForm?.UpdateUser($"Added blacklist DLC to UplayR1Unlocker.jsonc with appid {dlcId} ({dlcName})",
|
installForm?.UpdateUser($"Added blacklist DLC to UplayR1Unlocker.jsonc with appid {dlcId} ({dlcName})", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
writer.WriteLine(" ],");
|
writer.WriteLine(" ],");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"blacklist\": [],");
|
writer.WriteLine(" \"blacklist\": [],");
|
||||||
}
|
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true)
|
internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true)
|
||||||
=> await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
{
|
||||||
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o,
|
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
out string config);
|
|
||||||
if (File.Exists(api32_o))
|
if (File.Exists(api32_o))
|
||||||
{
|
{
|
||||||
if (File.Exists(api32))
|
if (File.Exists(api32))
|
||||||
{
|
{
|
||||||
File.Delete(api32);
|
File.Delete(api32);
|
||||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
File.Move(api32_o, api32);
|
File.Move(api32_o, api32);
|
||||||
installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}",
|
installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (File.Exists(api64_o))
|
if (File.Exists(api64_o))
|
||||||
{
|
{
|
||||||
if (File.Exists(api64))
|
if (File.Exists(api64))
|
||||||
{
|
{
|
||||||
File.Delete(api64);
|
File.Delete(api64);
|
||||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
File.Move(api64_o, api64);
|
File.Move(api64_o, api64);
|
||||||
installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}",
|
installForm?.UpdateUser($"Restored Uplay R1: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (deleteConfig && File.Exists(config))
|
if (deleteConfig && File.Exists(config))
|
||||||
{
|
{
|
||||||
|
@ -119,34 +100,31 @@ internal static class UplayR1
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null,
|
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true)
|
||||||
bool generateConfig = true) => await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
|
||||||
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o,
|
|
||||||
out string config);
|
|
||||||
if (File.Exists(api32) && !File.Exists(api32_o))
|
|
||||||
{
|
{
|
||||||
File.Move(api32, api32_o);
|
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}",
|
if (File.Exists(api32) && !File.Exists(api32_o))
|
||||||
LogTextBox.Action, false);
|
{
|
||||||
}
|
File.Move(api32, api32_o);
|
||||||
if (File.Exists(api32_o))
|
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||||
{
|
}
|
||||||
"UplayR1.uplay_r1_loader.dll".Write(api32);
|
if (File.Exists(api32_o))
|
||||||
installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
{
|
||||||
}
|
"UplayR1.uplay_r1_loader.dll".Write(api32);
|
||||||
if (File.Exists(api64) && !File.Exists(api64_o))
|
installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, false);
|
||||||
{
|
}
|
||||||
File.Move(api64, api64_o);
|
if (File.Exists(api64) && !File.Exists(api64_o))
|
||||||
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}",
|
{
|
||||||
LogTextBox.Action, false);
|
File.Move(api64, api64_o);
|
||||||
}
|
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||||
if (File.Exists(api64_o))
|
}
|
||||||
{
|
if (File.Exists(api64_o))
|
||||||
"UplayR1.uplay_r1_loader64.dll".Write(api64);
|
{
|
||||||
installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
"UplayR1.uplay_r1_loader64.dll".Write(api64);
|
||||||
}
|
installForm?.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
if (generateConfig)
|
}
|
||||||
CheckConfig(directory, selection, installForm);
|
if (generateConfig)
|
||||||
});
|
CheckConfig(directory, selection, installForm);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,8 @@ namespace CreamInstaller.Resources;
|
||||||
|
|
||||||
internal static class UplayR2
|
internal static class UplayR2
|
||||||
{
|
{
|
||||||
internal static void GetUplayR2Components(
|
internal static void GetUplayR2Components(this string directory, out string old_api32, out string old_api64, out string api32, out string api32_o,
|
||||||
this string directory,
|
out string api64, out string api64_o, out string config)
|
||||||
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_api32 = directory + @"\uplay_r2_loader.dll";
|
||||||
old_api64 = directory + @"\uplay_r2_loader64.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)
|
internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
directory.GetUplayR2Components(out _, out _, out _, out _, out _, out _, out string config);
|
directory.GetUplayR2Components(out _, out _, out _, out _, out _, out _, out string config);
|
||||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc
|
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> blacklistDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
||||||
= selection.AllDlc.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)
|
|
||||||
blacklistDlc = blacklistDlc.Except(extraDlc);
|
blacklistDlc = blacklistDlc.Except(extraDlc);
|
||||||
if (blacklistDlc.Any())
|
if (blacklistDlc.Any())
|
||||||
{
|
{
|
||||||
|
@ -41,24 +35,19 @@ internal static class UplayR2
|
||||||
installForm.UpdateUser("Generating Uplay R2 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
installForm.UpdateUser("Generating Uplay R2 Unlocker configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
||||||
File.Create(config).Close();
|
File.Create(config).Close();
|
||||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
StreamWriter writer = new(config, true, Encoding.UTF8);
|
||||||
WriteConfig(writer,
|
WriteConfig(writer, new(blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||||
new SortedList<string, (DlcType type, string name, string icon)>(
|
|
||||||
blacklistDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
|
||||||
installForm);
|
|
||||||
writer.Flush();
|
writer.Flush();
|
||||||
writer.Close();
|
writer.Close();
|
||||||
}
|
}
|
||||||
else if (File.Exists(config))
|
else if (File.Exists(config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(config);
|
||||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer,
|
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||||
SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
InstallForm installForm = null)
|
||||||
InstallForm installForm = null)
|
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
writer.WriteLine(" \"logging\": false,");
|
writer.WriteLine(" \"logging\": false,");
|
||||||
|
@ -75,35 +64,30 @@ internal static class UplayR2
|
||||||
string dlcId = pair.Key;
|
string dlcId = pair.Key;
|
||||||
(_, string dlcName, _) = pair.Value;
|
(_, string dlcName, _) = pair.Value;
|
||||||
writer.WriteLine($" {dlcId}{(pair.Equals(lastBlacklistDlc) ? "" : ",")}");
|
writer.WriteLine($" {dlcId}{(pair.Equals(lastBlacklistDlc) ? "" : ",")}");
|
||||||
installForm?.UpdateUser($"Added blacklist DLC to UplayR2Unlocker.jsonc with appid {dlcId} ({dlcName})",
|
installForm?.UpdateUser($"Added blacklist DLC to UplayR2Unlocker.jsonc with appid {dlcId} ({dlcName})", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
writer.WriteLine(" ],");
|
writer.WriteLine(" ],");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
writer.WriteLine(" \"blacklist\": [],");
|
writer.WriteLine(" \"blacklist\": [],");
|
||||||
}
|
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true)
|
internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true)
|
||||||
=> await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
{
|
||||||
directory.GetUplayR2Components(out string old_api32, out string old_api64, out string api32,
|
directory.GetUplayR2Components(out string old_api32, out string old_api64, out string api32, out string api32_o, out string api64,
|
||||||
out string api32_o, out string api64, out string api64_o, out string config);
|
out string api64_o, out string config);
|
||||||
if (File.Exists(api32_o))
|
if (File.Exists(api32_o))
|
||||||
{
|
{
|
||||||
string api = File.Exists(old_api32) ? old_api32 : api32;
|
string api = File.Exists(old_api32) ? old_api32 : api32;
|
||||||
if (File.Exists(api))
|
if (File.Exists(api))
|
||||||
{
|
{
|
||||||
File.Delete(api);
|
File.Delete(api);
|
||||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
File.Move(api32_o, api);
|
File.Move(api32_o, api);
|
||||||
installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api)}",
|
installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api32_o)} -> {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (File.Exists(api64_o))
|
if (File.Exists(api64_o))
|
||||||
{
|
{
|
||||||
|
@ -111,12 +95,10 @@ internal static class UplayR2
|
||||||
if (File.Exists(api))
|
if (File.Exists(api))
|
||||||
{
|
{
|
||||||
File.Delete(api);
|
File.Delete(api);
|
||||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action,
|
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
File.Move(api64_o, api);
|
File.Move(api64_o, api);
|
||||||
installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api)}",
|
installForm?.UpdateUser($"Restored Uplay R2: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (deleteConfig && File.Exists(config))
|
if (deleteConfig && File.Exists(config))
|
||||||
{
|
{
|
||||||
|
@ -125,36 +107,34 @@ internal static class UplayR2
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null,
|
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true)
|
||||||
bool generateConfig = true) => await Task.Run(() =>
|
=> 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);
|
|
||||||
string api = File.Exists(old_api32) ? old_api32 : api32;
|
|
||||||
if (File.Exists(api) && !File.Exists(api32_o))
|
|
||||||
{
|
{
|
||||||
File.Move(api, api32_o);
|
directory.GetUplayR2Components(out string old_api32, out string old_api64, out string api32, out string api32_o, out string api64,
|
||||||
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}",
|
out string api64_o, out string config);
|
||||||
LogTextBox.Action, false);
|
string api = File.Exists(old_api32) ? old_api32 : api32;
|
||||||
}
|
if (File.Exists(api) && !File.Exists(api32_o))
|
||||||
if (File.Exists(api32_o))
|
{
|
||||||
{
|
File.Move(api, api32_o);
|
||||||
"UplayR2.upc_r2_loader.dll".Write(api);
|
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
|
||||||
installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
|
}
|
||||||
}
|
if (File.Exists(api32_o))
|
||||||
api = File.Exists(old_api64) ? old_api64 : api64;
|
{
|
||||||
if (File.Exists(api) && !File.Exists(api64_o))
|
"UplayR2.upc_r2_loader.dll".Write(api);
|
||||||
{
|
installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||||
File.Move(api, api64_o);
|
}
|
||||||
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}",
|
api = File.Exists(old_api64) ? old_api64 : api64;
|
||||||
LogTextBox.Action, false);
|
if (File.Exists(api) && !File.Exists(api64_o))
|
||||||
}
|
{
|
||||||
if (File.Exists(api64_o))
|
File.Move(api, api64_o);
|
||||||
{
|
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
|
||||||
"UplayR2.upc_r2_loader64.dll".Write(api);
|
}
|
||||||
installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
|
if (File.Exists(api64_o))
|
||||||
}
|
{
|
||||||
if (generateConfig)
|
"UplayR2.upc_r2_loader64.dll".Write(api);
|
||||||
CheckConfig(directory, selection, installForm);
|
installForm?.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
|
||||||
});
|
}
|
||||||
|
if (generateConfig)
|
||||||
|
CheckConfig(directory, selection, installForm);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,7 @@ internal static class Diagnostics
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
notepadPlusPlusPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Notepad++", "", null) as string;
|
notepadPlusPlusPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Notepad++", "", null) as string;
|
||||||
notepadPlusPlusPath
|
notepadPlusPlusPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\Notepad++", "", null) as string;
|
||||||
??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\Notepad++", "", null) as string;
|
|
||||||
return notepadPlusPlusPath;
|
return notepadPlusPlusPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,18 +34,13 @@ internal static class Diagnostics
|
||||||
OpenFileInWindowsNotepad(path);
|
OpenFileInWindowsNotepad(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OpenFileInNotepadPlusPlus(string npp, string path)
|
private static void OpenFileInNotepadPlusPlus(string npp, string path) => Process.Start(new ProcessStartInfo { FileName = npp, Arguments = path });
|
||||||
=> Process.Start(new ProcessStartInfo { FileName = npp, Arguments = path });
|
|
||||||
|
|
||||||
private static void OpenFileInWindowsNotepad(string path)
|
private static void OpenFileInWindowsNotepad(string path) => Process.Start(new ProcessStartInfo { FileName = "notepad.exe", Arguments = path });
|
||||||
=> Process.Start(new ProcessStartInfo { FileName = "notepad.exe", Arguments = path });
|
|
||||||
|
|
||||||
internal static void OpenDirectoryInFileExplorer(string path)
|
internal static void OpenDirectoryInFileExplorer(string path) => Process.Start(new ProcessStartInfo { FileName = "explorer.exe", Arguments = path });
|
||||||
=> Process.Start(new ProcessStartInfo { FileName = "explorer.exe", Arguments = path });
|
|
||||||
|
|
||||||
internal static void OpenUrlInInternetBrowser(string url)
|
internal static void OpenUrlInInternetBrowser(string url) => Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
|
||||||
=> Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
|
|
||||||
|
|
||||||
internal static string BeautifyPath(this string path)
|
internal static string BeautifyPath(this string path) => path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path));
|
||||||
=> path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ namespace CreamInstaller.Utility;
|
||||||
|
|
||||||
internal static class ExceptionHandler
|
internal static class ExceptionHandler
|
||||||
{
|
{
|
||||||
internal static bool HandleException(this Exception e, Form form = null, string caption = null,
|
internal static bool HandleException(this Exception e, Form form = null, string caption = null, string acceptButtonText = "Retry",
|
||||||
string acceptButtonText = "Retry", string cancelButtonText = "Cancel")
|
string cancelButtonText = "Cancel")
|
||||||
{
|
{
|
||||||
caption ??= Program.Name + " encountered an exception";
|
caption ??= Program.Name + " encountered an exception";
|
||||||
StringBuilder output = new();
|
StringBuilder output = new();
|
||||||
|
@ -32,31 +32,23 @@ internal static class ExceptionHandler
|
||||||
int ciNum = line.LastIndexOf(@"CreamInstaller\", StringComparison.Ordinal);
|
int ciNum = line.LastIndexOf(@"CreamInstaller\", StringComparison.Ordinal);
|
||||||
int lineNum = line.LastIndexOf(":line ", StringComparison.Ordinal);
|
int lineNum = line.LastIndexOf(":line ", StringComparison.Ordinal);
|
||||||
if (atNum != -1)
|
if (atNum != -1)
|
||||||
_ = output.Append("\n " + (inNum != -1 ? line[atNum..(inNum - 1)] : line[atNum..])
|
_ = output.Append("\n " + (inNum != -1 ? line[atNum..(inNum - 1)] : line[atNum..]) + (inNum != -1
|
||||||
+ (inNum != -1
|
? "\n " + (ciNum != -1
|
||||||
? "\n "
|
? "in " + (lineNum != -1 ? line[ciNum..lineNum] + "\n on " + line[(lineNum + 1)..] : line[ciNum..])
|
||||||
+ (ciNum != -1
|
: line[inNum..])
|
||||||
? "in "
|
: null));
|
||||||
+ (lineNum != -1
|
|
||||||
? line[ciNum..lineNum]
|
|
||||||
+ "\n on " + line[(lineNum + 1)..]
|
|
||||||
: line[ciNum..])
|
|
||||||
: line[inNum..])
|
|
||||||
: null));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e = e.InnerException;
|
e = e.InnerException;
|
||||||
stackDepth++;
|
stackDepth++;
|
||||||
}
|
}
|
||||||
using DialogForm dialogForm = new(form ?? Form.ActiveForm);
|
using DialogForm dialogForm = new(form ?? Form.ActiveForm);
|
||||||
return dialogForm.Show(SystemIcons.Error, output.ToString(), acceptButtonText, cancelButtonText, caption)
|
return dialogForm.Show(SystemIcons.Error, output.ToString(), acceptButtonText, cancelButtonText, caption) == DialogResult.OK;
|
||||||
== DialogResult.OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void HandleFatalException(this Exception e)
|
internal static void HandleFatalException(this Exception e)
|
||||||
{
|
{
|
||||||
bool? restart = e?.HandleException(caption: Program.Name + " encountered a fatal exception",
|
bool? restart = e?.HandleException(caption: Program.Name + " encountered a fatal exception", acceptButtonText: "Restart");
|
||||||
acceptButtonText: "Restart");
|
|
||||||
if (restart.HasValue && restart.Value)
|
if (restart.HasValue && restart.Value)
|
||||||
Application.Restart();
|
Application.Restart();
|
||||||
Application.Exit();
|
Application.Exit();
|
||||||
|
|
|
@ -12,7 +12,7 @@ internal static class HttpClientManager
|
||||||
|
|
||||||
internal static void Setup()
|
internal static void Setup()
|
||||||
{
|
{
|
||||||
HttpClient = new HttpClient();
|
HttpClient = new();
|
||||||
HttpClient.DefaultRequestHeaders.Add("User-Agent", $"CI{Program.Version.Replace(".", "")}");
|
HttpClient.DefaultRequestHeaders.Add("User-Agent", $"CI{Program.Version.Replace(".", "")}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,7 @@ internal static class HttpClientManager
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using HttpRequestMessage request = new(HttpMethod.Get, url);
|
using HttpRequestMessage request = new(HttpMethod.Get, url);
|
||||||
using HttpResponseMessage response
|
using HttpResponseMessage response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||||
= await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
|
||||||
_ = response.EnsureSuccessStatusCode();
|
_ = response.EnsureSuccessStatusCode();
|
||||||
return await response.Content.ReadAsStringAsync();
|
return await response.Content.ReadAsStringAsync();
|
||||||
}
|
}
|
||||||
|
@ -42,8 +41,7 @@ internal static class HttpClientManager
|
||||||
internal static async Task<HtmlNodeCollection> GetDocumentNodes(string url, string xpath)
|
internal static async Task<HtmlNodeCollection> GetDocumentNodes(string url, string xpath)
|
||||||
=> (await EnsureGet(url))?.ToHtmlDocument()?.DocumentNode?.SelectNodes(xpath);
|
=> (await EnsureGet(url))?.ToHtmlDocument()?.DocumentNode?.SelectNodes(xpath);
|
||||||
|
|
||||||
internal static HtmlNodeCollection GetDocumentNodes(this HtmlDocument htmlDocument, string xpath)
|
internal static HtmlNodeCollection GetDocumentNodes(this HtmlDocument htmlDocument, string xpath) => htmlDocument.DocumentNode?.SelectNodes(xpath);
|
||||||
=> htmlDocument.DocumentNode?.SelectNodes(xpath);
|
|
||||||
|
|
||||||
internal static async Task<Image> GetImageFromUrl(string url)
|
internal static async Task<Image> GetImageFromUrl(string url)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,27 +6,23 @@ namespace CreamInstaller.Utility;
|
||||||
|
|
||||||
internal static class IconGrabber
|
internal static class IconGrabber
|
||||||
{
|
{
|
||||||
internal const string SteamAppImagesPath
|
internal const string SteamAppImagesPath = "https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/";
|
||||||
= "https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/";
|
|
||||||
|
|
||||||
internal const string GoogleFaviconsApiUrl = "https://www.google.com/s2/favicons";
|
internal const string GoogleFaviconsApiUrl = "https://www.google.com/s2/favicons";
|
||||||
|
|
||||||
internal static Icon ToIcon(this Image image)
|
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());
|
return Icon.FromHandle(dialogIconBitmap.GetHicon());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetDomainFaviconUrl(string domain, int size = 16)
|
internal static string GetDomainFaviconUrl(string domain, int size = 16) => GoogleFaviconsApiUrl + $"?domain={domain}&sz={size}";
|
||||||
=> GoogleFaviconsApiUrl + $"?domain={domain}&sz={size}";
|
|
||||||
|
|
||||||
internal static Image GetFileIconImage(this string path)
|
internal static Image GetFileIconImage(this string path) => File.Exists(path) ? Icon.ExtractAssociatedIcon(path)?.ToBitmap() : null;
|
||||||
=> File.Exists(path) ? Icon.ExtractAssociatedIcon(path)?.ToBitmap() : null;
|
|
||||||
|
|
||||||
internal static Image GetNotepadImage() => GetFileIconImage(Diagnostics.GetNotepadPath());
|
internal static Image GetNotepadImage() => GetFileIconImage(Diagnostics.GetNotepadPath());
|
||||||
|
|
||||||
internal static Image GetCommandPromptImage() => GetFileIconImage(Environment.SystemDirectory + @"\cmd.exe");
|
internal static Image GetCommandPromptImage() => GetFileIconImage(Environment.SystemDirectory + @"\cmd.exe");
|
||||||
|
|
||||||
internal static Image GetFileExplorerImage()
|
internal static Image GetFileExplorerImage() => GetFileIconImage(Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\explorer.exe");
|
||||||
=> GetFileIconImage(Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\explorer.exe");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,11 @@ internal static class LogTextBox
|
||||||
textBox.SelectionStart = textBox.TextLength;
|
textBox.SelectionStart = textBox.TextLength;
|
||||||
textBox.SelectionLength = 0;
|
textBox.SelectionLength = 0;
|
||||||
textBox.SelectionColor = color;
|
textBox.SelectionColor = color;
|
||||||
if (scroll) textBox.ScrollToCaret();
|
if (scroll)
|
||||||
|
textBox.ScrollToCaret();
|
||||||
textBox.AppendText(text);
|
textBox.AppendText(text);
|
||||||
if (scroll) textBox.ScrollToCaret();
|
if (scroll)
|
||||||
|
textBox.ScrollToCaret();
|
||||||
textBox.SelectionColor = textBox.ForeColor;
|
textBox.SelectionColor = textBox.ForeColor;
|
||||||
textBox.Invalidate();
|
textBox.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,9 @@ namespace CreamInstaller.Utility;
|
||||||
|
|
||||||
internal static class ProgramData
|
internal static class ProgramData
|
||||||
{
|
{
|
||||||
internal static readonly string DirectoryPathOld
|
internal static readonly string DirectoryPathOld = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller";
|
||||||
= Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller";
|
|
||||||
|
|
||||||
internal static readonly string DirectoryPath
|
internal static readonly string DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\CreamInstaller";
|
||||||
= Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\CreamInstaller";
|
|
||||||
|
|
||||||
internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo";
|
internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo";
|
||||||
internal static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt";
|
internal static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt";
|
||||||
|
@ -29,27 +27,30 @@ internal static class ProgramData
|
||||||
internal static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
internal static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
||||||
internal static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.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(DirectoryPathOld))
|
||||||
Directory.Move(DirectoryPathOld, DirectoryPath);
|
{
|
||||||
}
|
if (Directory.Exists(DirectoryPath))
|
||||||
if (!Directory.Exists(DirectoryPath)) _ = Directory.CreateDirectory(DirectoryPath);
|
Directory.Delete(DirectoryPath, true);
|
||||||
if (!File.Exists(AppInfoVersionPath)
|
Directory.Move(DirectoryPathOld, DirectoryPath);
|
||||||
|| !Version.TryParse(File.ReadAllText(AppInfoVersionPath, Encoding.UTF8), out Version version)
|
}
|
||||||
|| version < MinimumAppInfoVersion)
|
if (!Directory.Exists(DirectoryPath))
|
||||||
{
|
_ = Directory.CreateDirectory(DirectoryPath);
|
||||||
if (Directory.Exists(AppInfoPath)) Directory.Delete(AppInfoPath, true);
|
if (!File.Exists(AppInfoVersionPath) || !Version.TryParse(File.ReadAllText(AppInfoVersionPath, Encoding.UTF8), out Version version)
|
||||||
_ = Directory.CreateDirectory(AppInfoPath);
|
|| version < MinimumAppInfoVersion)
|
||||||
File.WriteAllText(AppInfoVersionPath, Program.Version, Encoding.UTF8);
|
{
|
||||||
}
|
if (Directory.Exists(AppInfoPath))
|
||||||
if (!Directory.Exists(CooldownPath))
|
Directory.Delete(AppInfoPath, true);
|
||||||
_ = Directory.CreateDirectory(CooldownPath);
|
_ = Directory.CreateDirectory(AppInfoPath);
|
||||||
if (File.Exists(OldProgramChoicesPath))
|
File.WriteAllText(AppInfoVersionPath, Program.Version, Encoding.UTF8);
|
||||||
File.Delete(OldProgramChoicesPath);
|
}
|
||||||
});
|
if (!Directory.Exists(CooldownPath))
|
||||||
|
_ = Directory.CreateDirectory(CooldownPath);
|
||||||
|
if (File.Exists(OldProgramChoicesPath))
|
||||||
|
File.Delete(OldProgramChoicesPath);
|
||||||
|
});
|
||||||
|
|
||||||
internal static bool CheckCooldown(string identifier, int cooldown)
|
internal static bool CheckCooldown(string identifier, int cooldown)
|
||||||
{
|
{
|
||||||
|
@ -91,16 +92,16 @@ internal static class ProgramData
|
||||||
|
|
||||||
internal static List<(Platform platform, string id)> ReadProgramChoices()
|
internal static List<(Platform platform, string id)> ReadProgramChoices()
|
||||||
{
|
{
|
||||||
if (!File.Exists(ProgramChoicesPath)) return null;
|
if (!File.Exists(ProgramChoicesPath))
|
||||||
|
return null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath),
|
return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath), typeof(List<(Platform platform, string id)>)) as
|
||||||
typeof(List<(Platform platform, string id)>)) as
|
|
||||||
List<(Platform platform, string id)>;
|
List<(Platform platform, string id)>;
|
||||||
}
|
}
|
||||||
catch
|
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()
|
internal static List<(Platform platform, string gameId, string dlcId)> ReadDlcChoices()
|
||||||
{
|
{
|
||||||
if (!File.Exists(DlcChoicesPath)) return null;
|
if (!File.Exists(DlcChoicesPath))
|
||||||
|
return null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath),
|
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath), typeof(List<(Platform platform, string gameId, string dlcId)>)) as
|
||||||
typeof(List<(Platform platform, string gameId, string dlcId)>)) as
|
|
||||||
List<(Platform platform, string gameId, string dlcId)>;
|
List<(Platform platform, string gameId, string dlcId)>;
|
||||||
}
|
}
|
||||||
catch
|
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()
|
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
|
try
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject(File.ReadAllText(KoaloaderProxyChoicesPath),
|
return JsonConvert.DeserializeObject(File.ReadAllText(KoaloaderProxyChoicesPath),
|
||||||
typeof(
|
typeof(List<(Platform platform, string id, string proxy, bool enabled)>)) as List<(Platform platform, string id, string proxy, bool enabled)>;
|
||||||
List<(Platform platform, string id, string proxy, bool enabled)>))
|
|
||||||
as List<(Platform platform, string id, string proxy, bool enabled)>;
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return new List<(Platform platform, string id, string proxy, bool enabled)>();
|
return new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteKoaloaderProxyChoices(
|
internal static void WriteKoaloaderProxyChoices(List<(Platform platform, string id, string proxy, bool enabled)> choices)
|
||||||
List<(Platform platform, string id, string proxy, bool enabled)> choices)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue