v4.4.0.0
- Significant refactoring & optimizations - Updated to Koaloader v3.0.1
This commit is contained in:
parent
51db005c34
commit
45eaed35dd
80 changed files with 746 additions and 691 deletions
|
@ -9,16 +9,16 @@ using CreamInstaller.Utility;
|
||||||
|
|
||||||
namespace CreamInstaller.Components;
|
namespace CreamInstaller.Components;
|
||||||
|
|
||||||
internal class ContextMenuItem : ToolStripMenuItem
|
internal sealed class ContextMenuItem : ToolStripMenuItem
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<string, Image> images = new();
|
private static readonly ConcurrentDictionary<string, Image> Images = new();
|
||||||
|
|
||||||
private readonly EventHandler OnClickEvent;
|
private readonly EventHandler onClickEvent;
|
||||||
|
|
||||||
internal ContextMenuItem(string text, EventHandler onClick = null)
|
internal ContextMenuItem(string text, EventHandler onClick = null)
|
||||||
{
|
{
|
||||||
Text = text;
|
Text = text;
|
||||||
OnClickEvent = onClick;
|
onClickEvent = onClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null) : this(text, onClick)
|
internal ContextMenuItem(string text, string imageIdentifier, EventHandler onClick = null) : this(text, onClick)
|
||||||
|
@ -29,16 +29,22 @@ internal class ContextMenuItem : ToolStripMenuItem
|
||||||
|
|
||||||
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, string imageIdentifierFallback, EventHandler onClick = null) :
|
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, string imageIdentifierFallback, EventHandler onClick = null) :
|
||||||
this(text, onClick)
|
this(text, onClick)
|
||||||
=> _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifier(this, imageIdentifierFallback));
|
{
|
||||||
|
async void OnFail() => await TryImageIdentifier(this, imageIdentifierFallback);
|
||||||
|
_ = TryImageIdentifierInfo(this, imageIdentifierInfo, OnFail);
|
||||||
|
}
|
||||||
|
|
||||||
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, (string id, string iconUrl) imageIdentifierInfoFallback,
|
internal ContextMenuItem(string text, (string id, string iconUrl) imageIdentifierInfo, (string id, string iconUrl) imageIdentifierInfoFallback,
|
||||||
EventHandler onClick = null) : this(text, onClick)
|
EventHandler onClick = null) : this(text, onClick)
|
||||||
=> _ = TryImageIdentifierInfo(this, imageIdentifierInfo, async () => await TryImageIdentifierInfo(this, imageIdentifierInfoFallback));
|
{
|
||||||
|
async void OnFail() => await TryImageIdentifierInfo(this, imageIdentifierInfoFallback);
|
||||||
|
_ = TryImageIdentifierInfo(this, imageIdentifierInfo, OnFail);
|
||||||
|
}
|
||||||
|
|
||||||
private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier)
|
private static async Task TryImageIdentifier(ContextMenuItem item, string imageIdentifier)
|
||||||
=> await Task.Run(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
|
||||||
{
|
{
|
||||||
|
@ -84,7 +90,7 @@ internal class ContextMenuItem : ToolStripMenuItem
|
||||||
}
|
}
|
||||||
if (image is not null)
|
if (image is not null)
|
||||||
{
|
{
|
||||||
images[imageIdentifier] = image;
|
Images[imageIdentifier] = image;
|
||||||
item.Image = image;
|
item.Image = image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,26 +101,24 @@ internal class ContextMenuItem : ToolStripMenuItem
|
||||||
{
|
{
|
||||||
(string id, string iconUrl) = imageIdentifierInfo;
|
(string id, string iconUrl) = imageIdentifierInfo;
|
||||||
string imageIdentifier = "Icon_" + id;
|
string imageIdentifier = "Icon_" + id;
|
||||||
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
|
||||||
{
|
{
|
||||||
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
||||||
if (image is not null)
|
if (image is not null)
|
||||||
{
|
{
|
||||||
images[imageIdentifier] = image;
|
Images[imageIdentifier] = image;
|
||||||
item.Image = image;
|
item.Image = image;
|
||||||
}
|
}
|
||||||
else if (onFail is not null)
|
else
|
||||||
onFail();
|
onFail?.Invoke();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
protected override void OnClick(EventArgs e)
|
protected override void OnClick(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnClick(e);
|
base.OnClick(e);
|
||||||
if (OnClickEvent is null)
|
onClickEvent?.Invoke(this, e);
|
||||||
return;
|
|
||||||
OnClickEvent.Invoke(this, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -124,4 +124,4 @@ internal class CustomForm : Form
|
||||||
Clipboard.SetImage(bitmap);
|
Clipboard.SetImage(bitmap);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,9 +11,9 @@ using static CreamInstaller.Resources.Resources;
|
||||||
|
|
||||||
namespace CreamInstaller.Components;
|
namespace CreamInstaller.Components;
|
||||||
|
|
||||||
internal class CustomTreeView : TreeView
|
internal sealed class CustomTreeView : TreeView
|
||||||
{
|
{
|
||||||
private const string koaloaderToggleString = "Koaloader";
|
private const string KoaloaderToggleString = "Koaloader";
|
||||||
private readonly Dictionary<ProgramSelection, Rectangle> checkBoxBounds = new();
|
private readonly Dictionary<ProgramSelection, Rectangle> checkBoxBounds = new();
|
||||||
private readonly Dictionary<ProgramSelection, Rectangle> comboBoxBounds = new();
|
private readonly Dictionary<ProgramSelection, Rectangle> comboBoxBounds = new();
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ internal class CustomTreeView : TreeView
|
||||||
protected override void WndProc(ref Message m)
|
protected override void WndProc(ref Message m)
|
||||||
{
|
{
|
||||||
if (m.Msg == 0x203)
|
if (m.Msg == 0x203)
|
||||||
m.Result = IntPtr.Zero;
|
m.Result = nint.Zero;
|
||||||
else
|
else
|
||||||
base.WndProc(ref m);
|
base.WndProc(ref m);
|
||||||
form = FindForm();
|
form = FindForm();
|
||||||
|
@ -54,11 +54,11 @@ internal class CustomTreeView : TreeView
|
||||||
{
|
{
|
||||||
e.DrawDefault = true;
|
e.DrawDefault = true;
|
||||||
TreeNode node = e.Node;
|
TreeNode node = e.Node;
|
||||||
if (!node.IsVisible)
|
if (node is not { IsVisible: true })
|
||||||
return;
|
return;
|
||||||
bool highlighted = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected && Focused;
|
bool highlighted = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected && Focused;
|
||||||
Graphics graphics = e.Graphics;
|
Graphics graphics = e.Graphics;
|
||||||
backBrush ??= new SolidBrush(BackColor);
|
backBrush ??= new(BackColor);
|
||||||
Font font = node.NodeFont ?? Font;
|
Font font = node.NodeFont ?? Font;
|
||||||
Brush brush = highlighted ? SystemBrushes.Highlight : backBrush;
|
Brush brush = highlighted ? SystemBrushes.Highlight : backBrush;
|
||||||
string text; // = e.Node.Text;
|
string text; // = e.Node.Text;
|
||||||
|
@ -87,9 +87,9 @@ 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 = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
selectionBounds = new(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(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);
|
||||||
if (platform is not Platform.Paradox)
|
if (platform is not Platform.Paradox)
|
||||||
{
|
{
|
||||||
|
@ -100,11 +100,11 @@ internal class CustomTreeView : TreeView
|
||||||
: ColorTranslator.FromHtml("#69AAAA");
|
: ColorTranslator.FromHtml("#69AAAA");
|
||||||
text = platformId;
|
text = platformId;
|
||||||
size = TextRenderer.MeasureText(graphics, text, font);
|
size = TextRenderer.MeasureText(graphics, text, font);
|
||||||
int left = -4;
|
const 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.Size + new Size(bounds.Size.Width + left, 0));
|
selectionBounds = new(selectionBounds.Location, 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(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);
|
||||||
}
|
}
|
||||||
/*if (highlighted)
|
/*if (highlighted)
|
||||||
|
@ -116,7 +116,7 @@ internal class CustomTreeView : TreeView
|
||||||
{
|
{
|
||||||
if (bounds == node.Bounds)
|
if (bounds == node.Bounds)
|
||||||
{
|
{
|
||||||
size = new Size(4, 0);
|
size = new(4, 0);
|
||||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||||
graphics.FillRectangle(brush, bounds);
|
graphics.FillRectangle(brush, bounds);
|
||||||
}
|
}
|
||||||
|
@ -127,47 +127,45 @@ 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.Size + bounds.Size with { Height = 0 });
|
selectionBounds = new(selectionBounds.Location, 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(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1);
|
||||||
CheckBoxRenderer.DrawCheckBox(graphics, point, checkBoxState);
|
CheckBoxRenderer.DrawCheckBox(graphics, point, checkBoxState);
|
||||||
text = koaloaderToggleString;
|
text = KoaloaderToggleString;
|
||||||
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.Size + bounds.Size with { Height = 0 });
|
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||||
checkBoxBounds = new Rectangle(checkBoxBounds.Location, checkBoxBounds.Size + bounds.Size with { Height = 0 });
|
checkBoxBounds = new(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(bounds.Location.X - 1 + left, bounds.Location.Y + 1);
|
||||||
TextRenderer.DrawText(graphics, text, font, point, Enabled ? ColorTranslator.FromHtml("#006900") : ColorTranslator.FromHtml("#69AA69"),
|
TextRenderer.DrawText(graphics, text, font, point, Enabled ? ColorTranslator.FromHtml("#006900") : ColorTranslator.FromHtml("#69AA69"),
|
||||||
TextFormatFlags.Default);
|
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)
|
||||||
{
|
{
|
||||||
comboBoxFont ??= new Font(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, font.GdiVerticalFont);
|
comboBoxFont ??= new(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, 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;
|
const int padding = 2;
|
||||||
bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding);
|
bounds = new(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding);
|
||||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
selectionBounds = new(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(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.Size + new Size(bounds.Size.Width + left, 0));
|
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
||||||
comboBoxBounds = new Rectangle(comboBoxBounds.Location, comboBoxBounds.Size + new Size(bounds.Size.Width + left, 0));
|
comboBoxBounds = new(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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
_ = comboBoxBounds.Remove(selection);
|
_ = comboBoxBounds.Remove(selection);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.selectionBounds[node] = RectangleToClient(selectionBounds);
|
this.selectionBounds[node] = RectangleToClient(selectionBounds);
|
||||||
|
@ -179,11 +177,9 @@ internal class CustomTreeView : TreeView
|
||||||
Refresh();
|
Refresh();
|
||||||
Point clickPoint = PointToClient(e.Location);
|
Point clickPoint = PointToClient(e.Location);
|
||||||
SelectForm selectForm = (form ??= FindForm()) as SelectForm;
|
SelectForm selectForm = (form ??= FindForm()) as SelectForm;
|
||||||
foreach (KeyValuePair<TreeNode, Rectangle> pair in selectionBounds.ToList())
|
foreach (KeyValuePair<TreeNode, Rectangle> pair in selectionBounds)
|
||||||
if (pair.Key.TreeView is null)
|
if (pair.Key.TreeView is null)
|
||||||
{
|
|
||||||
_ = selectionBounds.Remove(pair.Key);
|
_ = selectionBounds.Remove(pair.Key);
|
||||||
}
|
|
||||||
else if (pair.Key.IsVisible && pair.Value.Contains(clickPoint))
|
else if (pair.Key.IsVisible && pair.Value.Contains(clickPoint))
|
||||||
{
|
{
|
||||||
SelectedNode = pair.Key;
|
SelectedNode = pair.Key;
|
||||||
|
@ -191,57 +187,51 @@ internal class CustomTreeView : TreeView
|
||||||
selectForm.OnNodeRightClick(pair.Key, e.Location);
|
selectForm.OnNodeRightClick(pair.Key, e.Location);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e.Button is MouseButtons.Left)
|
if (e.Button is not MouseButtons.Left)
|
||||||
{
|
return;
|
||||||
if (comboBoxBounds.Any() && selectForm is not null)
|
if (comboBoxBounds.Any() && selectForm is not null)
|
||||||
foreach (KeyValuePair<ProgramSelection, Rectangle> pair in comboBoxBounds.ToList())
|
foreach (KeyValuePair<ProgramSelection, Rectangle> pair in comboBoxBounds)
|
||||||
if (!ProgramSelection.All.Contains(pair.Key))
|
|
||||||
{
|
|
||||||
_ = comboBoxBounds.Remove(pair.Key);
|
|
||||||
}
|
|
||||||
else if (pair.Value.Contains(clickPoint))
|
|
||||||
{
|
|
||||||
List<string> proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")).Select(p =>
|
|
||||||
{
|
|
||||||
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
|
|
||||||
return proxyName;
|
|
||||||
}).Distinct().ToList();
|
|
||||||
comboBoxDropDown ??= new ToolStripDropDown();
|
|
||||||
comboBoxDropDown.ShowItemToolTips = false;
|
|
||||||
comboBoxDropDown.Items.Clear();
|
|
||||||
foreach (string proxy in proxies)
|
|
||||||
{
|
|
||||||
bool canUse = true;
|
|
||||||
foreach ((string directory, BinaryType binaryType) in pair.Key.ExecutableDirectories)
|
|
||||||
{
|
|
||||||
string path = directory + @"\" + proxy + ".dll";
|
|
||||||
if (File.Exists(path) && !path.IsResourceFile(ResourceIdentifier.Koaloader))
|
|
||||||
{
|
|
||||||
canUse = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (canUse)
|
|
||||||
_ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (s, e) =>
|
|
||||||
{
|
|
||||||
pair.Key.KoaloaderProxy = proxy == ProgramSelection.DefaultKoaloaderProxy ? null : proxy;
|
|
||||||
selectForm.OnKoaloaderChanged();
|
|
||||||
}) { Font = comboBoxFont });
|
|
||||||
}
|
|
||||||
comboBoxDropDown.Show(this, PointToScreen(new Point(pair.Value.Left, pair.Value.Bottom - 1)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<ProgramSelection, Rectangle> pair in checkBoxBounds.ToList())
|
|
||||||
if (!ProgramSelection.All.Contains(pair.Key))
|
if (!ProgramSelection.All.Contains(pair.Key))
|
||||||
{
|
_ = comboBoxBounds.Remove(pair.Key);
|
||||||
_ = checkBoxBounds.Remove(pair.Key);
|
|
||||||
}
|
|
||||||
else if (pair.Value.Contains(clickPoint))
|
else if (pair.Value.Contains(clickPoint))
|
||||||
{
|
{
|
||||||
pair.Key.Koaloader = !pair.Key.Koaloader;
|
List<string> proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")).Select(p =>
|
||||||
selectForm.OnKoaloaderChanged();
|
{
|
||||||
|
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
|
||||||
|
return proxyName;
|
||||||
|
}).Distinct().ToList();
|
||||||
|
comboBoxDropDown ??= new();
|
||||||
|
comboBoxDropDown.ShowItemToolTips = false;
|
||||||
|
comboBoxDropDown.Items.Clear();
|
||||||
|
foreach (string proxy in proxies)
|
||||||
|
{
|
||||||
|
bool canUse = true;
|
||||||
|
foreach ((string directory, BinaryType binaryType) in pair.Key.ExecutableDirectories)
|
||||||
|
{
|
||||||
|
string path = directory + @"\" + proxy + ".dll";
|
||||||
|
if (!File.Exists(path) || path.IsResourceFile(ResourceIdentifier.Koaloader))
|
||||||
|
continue;
|
||||||
|
canUse = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (canUse)
|
||||||
|
_ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (s, e) =>
|
||||||
|
{
|
||||||
|
pair.Key.KoaloaderProxy = proxy == ProgramSelection.DefaultKoaloaderProxy ? null : proxy;
|
||||||
|
selectForm.OnKoaloaderChanged();
|
||||||
|
}) { Font = comboBoxFont });
|
||||||
|
}
|
||||||
|
comboBoxDropDown.Show(this, PointToScreen(new(pair.Value.Left, pair.Value.Bottom - 1)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
foreach (KeyValuePair<ProgramSelection, Rectangle> pair in checkBoxBounds)
|
||||||
|
if (!ProgramSelection.All.Contains(pair.Key))
|
||||||
|
_ = checkBoxBounds.Remove(pair.Key);
|
||||||
|
else if (pair.Value.Contains(clickPoint))
|
||||||
|
{
|
||||||
|
pair.Key.Koaloader = !pair.Key.Koaloader;
|
||||||
|
selectForm?.OnKoaloaderChanged();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@ internal static class PlatformIdComparer
|
||||||
internal static NodeTextComparer NodeText => nodeTextComparer ??= new();
|
internal static NodeTextComparer NodeText => nodeTextComparer ??= new();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class StringComparer : IComparer<string>
|
internal sealed 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 _)
|
||||||
|
@ -36,7 +36,7 @@ internal class StringComparer : IComparer<string>
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NodeComparer : IComparer<TreeNode>
|
internal sealed 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
|
||||||
|
@ -50,7 +50,7 @@ internal class NodeComparer : IComparer<TreeNode>
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NodeNameComparer : IComparer
|
internal sealed 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
|
||||||
|
@ -62,7 +62,7 @@ internal class NodeNameComparer : IComparer
|
||||||
: PlatformIdComparer.String.Compare(A.Name, B.Name);
|
: PlatformIdComparer.String.Compare(A.Name, B.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NodeTextComparer : IComparer
|
internal sealed 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
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>net7.0-windows</TargetFramework>
|
<TargetFramework>net7.0-windows</TargetFramework>
|
||||||
<UseWindowsForms>True</UseWindowsForms>
|
<UseWindowsForms>True</UseWindowsForms>
|
||||||
<ApplicationIcon>Resources\ini.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\ini.ico</ApplicationIcon>
|
||||||
<Version>4.3.0.1</Version>
|
<Version>4.4.0.0</Version>
|
||||||
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>
|
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>
|
||||||
<Company>CreamInstaller</Company>
|
<Company>CreamInstaller</Company>
|
||||||
<Product>Automatic DLC Unlocker Installer & Configuration Generator</Product>
|
<Product>Automatic DLC Unlocker Installer & Configuration Generator</Product>
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DefineConstants>$(DefineConstants)</DefineConstants>
|
<DefineConstants>$(DefineConstants)</DefineConstants>
|
||||||
|
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||||
<AssemblyName>$(Company)</AssemblyName>
|
<AssemblyName>$(Company)</AssemblyName>
|
||||||
|
|
|
@ -6,13 +6,13 @@ using CreamInstaller.Utility;
|
||||||
|
|
||||||
namespace CreamInstaller.Forms;
|
namespace CreamInstaller.Forms;
|
||||||
|
|
||||||
internal partial class DebugForm : CustomForm
|
internal sealed partial class DebugForm : CustomForm
|
||||||
{
|
{
|
||||||
internal static DebugForm current;
|
private static DebugForm current;
|
||||||
|
|
||||||
private Form attachedForm;
|
private Form attachedForm;
|
||||||
|
|
||||||
internal DebugForm()
|
private DebugForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
debugTextBox.BackColor = LogTextBox.Background;
|
debugTextBox.BackColor = LogTextBox.Background;
|
||||||
|
@ -26,7 +26,6 @@ internal partial class DebugForm : CustomForm
|
||||||
current = null;
|
current = null;
|
||||||
return current ??= new();
|
return current ??= new();
|
||||||
}
|
}
|
||||||
set => current = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void WndProc(ref Message message) // make form immovable by user
|
protected override void WndProc(ref Message message) // make form immovable by user
|
||||||
|
@ -57,16 +56,15 @@ internal partial class DebugForm : CustomForm
|
||||||
UpdateAttachment();
|
UpdateAttachment();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnChange(object sender, EventArgs args) => UpdateAttachment();
|
private void OnChange(object sender, EventArgs args) => UpdateAttachment();
|
||||||
|
|
||||||
internal void UpdateAttachment()
|
private void UpdateAttachment()
|
||||||
{
|
{
|
||||||
if (attachedForm is not null && attachedForm.Visible)
|
if (attachedForm is null || !attachedForm.Visible)
|
||||||
{
|
return;
|
||||||
//Size = new(Size.Width, attachedForm.Size.Height);
|
//Size = new(Size.Width, attachedForm.Size.Height);
|
||||||
Location = new(attachedForm.Right, attachedForm.Top);
|
Location = new(attachedForm.Right, attachedForm.Top);
|
||||||
BringToFrontWithoutActivation();
|
BringToFrontWithoutActivation();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Log(string text) => Log(text, LogTextBox.Error);
|
internal void Log(string text) => Log(text, LogTextBox.Error);
|
||||||
|
@ -81,4 +79,4 @@ internal partial class DebugForm : CustomForm
|
||||||
debugTextBox.AppendText(text, color, true);
|
debugTextBox.AppendText(text, color, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ using CreamInstaller.Components;
|
||||||
|
|
||||||
namespace CreamInstaller.Forms;
|
namespace CreamInstaller.Forms;
|
||||||
|
|
||||||
internal partial class DialogForm : CustomForm
|
internal sealed partial class DialogForm : CustomForm
|
||||||
{
|
{
|
||||||
internal DialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
internal DialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ internal partial class DialogForm : CustomForm
|
||||||
string customFormText = null, Icon customFormIcon = null)
|
string customFormText = null, Icon customFormIcon = null)
|
||||||
{
|
{
|
||||||
descriptionIcon ??= Icon;
|
descriptionIcon ??= Icon;
|
||||||
icon.Image = descriptionIcon.ToBitmap();
|
icon.Image = descriptionIcon?.ToBitmap();
|
||||||
List<LinkLabel.Link> links = new();
|
List<LinkLabel.Link> links = new();
|
||||||
for (int i = 0; i < descriptionText.Length; i++)
|
for (int i = 0; i < descriptionText.Length; i++)
|
||||||
if (descriptionText[i] == '[')
|
if (descriptionText[i] == '[')
|
||||||
|
@ -25,15 +25,14 @@ internal partial class DialogForm : CustomForm
|
||||||
int textRight = descriptionText.IndexOf("]", textLeft == -1 ? i : textLeft, StringComparison.Ordinal);
|
int textRight = descriptionText.IndexOf("]", textLeft == -1 ? i : textLeft, StringComparison.Ordinal);
|
||||||
int linkLeft = descriptionText.IndexOf("(", textRight == -1 ? i : textRight, StringComparison.Ordinal);
|
int linkLeft = descriptionText.IndexOf("(", textRight == -1 ? i : textRight, StringComparison.Ordinal);
|
||||||
int linkRight = descriptionText.IndexOf(")", linkLeft == -1 ? i : linkLeft, StringComparison.Ordinal);
|
int linkRight = descriptionText.IndexOf(")", linkLeft == -1 ? i : linkLeft, StringComparison.Ordinal);
|
||||||
if (textLeft != -1 && textRight == linkLeft - 1 && linkRight != -1)
|
if (textLeft == -1 || textRight != linkLeft - 1 || linkRight == -1)
|
||||||
{
|
continue;
|
||||||
string text = descriptionText[(textLeft + 1)..textRight];
|
string text = descriptionText[(textLeft + 1)..textRight];
|
||||||
string link = descriptionText[(linkLeft + 1)..linkRight];
|
string link = descriptionText[(linkLeft + 1)..linkRight];
|
||||||
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(i, text.Length, link));
|
links.Add(new(i, text.Length, link));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
descriptionLabel.Text = descriptionText;
|
descriptionLabel.Text = descriptionText;
|
||||||
acceptButton.Text = acceptButtonText;
|
acceptButton.Text = acceptButtonText;
|
||||||
|
@ -53,12 +52,11 @@ internal partial class DialogForm : CustomForm
|
||||||
}
|
}
|
||||||
if (customFormIcon is not null)
|
if (customFormIcon is not null)
|
||||||
Icon = customFormIcon;
|
Icon = customFormIcon;
|
||||||
if (links.Any())
|
if (!links.Any())
|
||||||
{
|
return ShowDialog();
|
||||||
foreach (LinkLabel.Link link in links)
|
foreach (LinkLabel.Link link in links)
|
||||||
_ = descriptionLabel.Links.Add(link);
|
_ = descriptionLabel.Links.Add(link);
|
||||||
descriptionLabel.LinkClicked += (s, e) => Process.Start(new ProcessStartInfo((string)e.Link.LinkData) { UseShellExecute = true });
|
descriptionLabel.LinkClicked += (s, e) => Process.Start(new ProcessStartInfo((string)e.Link.LinkData) { UseShellExecute = true });
|
||||||
}
|
|
||||||
return ShowDialog();
|
return ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,4 +64,4 @@ internal partial class DialogForm : CustomForm
|
||||||
=> 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 ? Program.Name : Program.ApplicationNameShort
|
? TextRenderer.MeasureText(Program.ApplicationNameShort, Font).Width > Size.Width - 100 ? Program.Name : Program.ApplicationNameShort
|
||||||
: Program.ApplicationName;
|
: Program.ApplicationName;
|
||||||
}
|
}
|
2
CreamInstaller/Forms/InstallForm.Designer.cs
generated
2
CreamInstaller/Forms/InstallForm.Designer.cs
generated
|
@ -3,7 +3,7 @@ using System.Windows.Forms;
|
||||||
|
|
||||||
namespace CreamInstaller.Forms
|
namespace CreamInstaller.Forms
|
||||||
{
|
{
|
||||||
partial class InstallForm
|
sealed partial class InstallForm
|
||||||
{
|
{
|
||||||
private IContainer components = null;
|
private IContainer components = null;
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
|
|
|
@ -13,15 +13,15 @@ using static CreamInstaller.Resources.Resources;
|
||||||
|
|
||||||
namespace CreamInstaller.Forms;
|
namespace CreamInstaller.Forms;
|
||||||
|
|
||||||
internal partial class InstallForm : CustomForm
|
internal sealed partial class InstallForm : CustomForm
|
||||||
{
|
{
|
||||||
private readonly List<ProgramSelection> DisabledSelections = new();
|
private readonly List<ProgramSelection> disabledSelections = new();
|
||||||
|
|
||||||
private readonly int ProgramCount = ProgramSelection.AllEnabled.Count;
|
private readonly int programCount = ProgramSelection.AllEnabled.Count;
|
||||||
internal readonly bool Uninstalling;
|
private readonly bool uninstalling;
|
||||||
private int CompleteOperationsCount;
|
private int completeOperationsCount;
|
||||||
|
|
||||||
private int OperationsCount;
|
private int operationsCount;
|
||||||
internal bool Reselecting;
|
internal bool Reselecting;
|
||||||
|
|
||||||
internal InstallForm(bool uninstall = false)
|
internal InstallForm(bool uninstall = false)
|
||||||
|
@ -29,15 +29,15 @@ internal partial class InstallForm : CustomForm
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Text = Program.ApplicationName;
|
Text = Program.ApplicationName;
|
||||||
logTextBox.BackColor = LogTextBox.Background;
|
logTextBox.BackColor = LogTextBox.Background;
|
||||||
Uninstalling = uninstall;
|
uninstalling = uninstall;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateProgress(int progress)
|
private void UpdateProgress(int progress)
|
||||||
{
|
{
|
||||||
if (!userProgressBar.Disposing && !userProgressBar.IsDisposed)
|
if (!userProgressBar.Disposing && !userProgressBar.IsDisposed)
|
||||||
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)
|
if (value < userProgressBar.Value)
|
||||||
return;
|
return;
|
||||||
userProgressBar.Value = value;
|
userProgressBar.Value = value;
|
||||||
|
@ -67,12 +67,12 @@ internal partial class InstallForm : CustomForm
|
||||||
_ = await Repair(this, selection);
|
_ = await Repair(this, selection);
|
||||||
}
|
}
|
||||||
UpdateUser(
|
UpdateUser(
|
||||||
$"{(Uninstalling ? "Uninstalling" : "Installing")}" + $" {(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(s => s.directory == Path.GetDirectoryName(d.path)))
|
?.Where(d => selection.ExecutableDirectories.All(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.All(s => s.directory != selection.RootDirectory))
|
||||||
invalidDirectories = invalidDirectories?.Append(selection.RootDirectory);
|
invalidDirectories = invalidDirectories?.Append(selection.RootDirectory);
|
||||||
invalidDirectories = invalidDirectories?.Distinct();
|
invalidDirectories = invalidDirectories?.Distinct();
|
||||||
if (invalidDirectories is not null)
|
if (invalidDirectories is not null)
|
||||||
|
@ -80,30 +80,31 @@ internal partial class InstallForm : CustomForm
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
throw new CustomMessageException("The operation was 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 old_config, 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 && Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) || File.Exists(config))
|
|| directory != selection.RootDirectory && Koaloader.AutoLoadDLLs.Any(pair => File.Exists(directory + @"\" + pair.dll))
|
||||||
|
|| File.Exists(old_config) || File.Exists(config))
|
||||||
{
|
{
|
||||||
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
|
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||||
}
|
}
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
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)
|
if (Program.Canceled)
|
||||||
throw new CustomMessageException("The operation was 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 old_config, 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)) || File.Exists(config))
|
|| Koaloader.AutoLoadDLLs.Any(pair => File.Exists(directory + @"\" + pair.dll)) || File.Exists(old_config) || File.Exists(config))
|
||||||
{
|
{
|
||||||
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||||
}
|
}
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
bool uninstallProxy = Uninstalling || selection.Koaloader;
|
bool uninstallProxy = uninstalling || selection.Koaloader;
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -111,10 +112,10 @@ internal partial class InstallForm : CustomForm
|
||||||
throw new CustomMessageException("The operation was 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, out string api64_o, out string config,
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
|
||||||
out string cache);
|
out string config, 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(old_config) || File.Exists(config) || File.Exists(cache)
|
||||||
: File.Exists(api32) || File.Exists(api64))
|
: File.Exists(api32) || File.Exists(api64))
|
||||||
{
|
{
|
||||||
UpdateUser(
|
UpdateUser(
|
||||||
|
@ -170,7 +171,7 @@ internal partial class InstallForm : CustomForm
|
||||||
UpdateProgress(++cur / count * 100);
|
UpdateProgress(++cur / count * 100);
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
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)
|
if (Program.Canceled)
|
||||||
|
@ -185,8 +186,8 @@ internal partial class InstallForm : CustomForm
|
||||||
private async Task Operate()
|
private async Task Operate()
|
||||||
{
|
{
|
||||||
List<ProgramSelection> programSelections = ProgramSelection.AllEnabled;
|
List<ProgramSelection> programSelections = ProgramSelection.AllEnabled;
|
||||||
OperationsCount = programSelections.Count;
|
operationsCount = programSelections.Count;
|
||||||
CompleteOperationsCount = 0;
|
completeOperationsCount = 0;
|
||||||
foreach (ProgramSelection selection in programSelections)
|
foreach (ProgramSelection selection in programSelections)
|
||||||
{
|
{
|
||||||
if (Program.Canceled || !Program.IsProgramRunningDialog(this, selection))
|
if (Program.Canceled || !Program.IsProgramRunningDialog(this, selection))
|
||||||
|
@ -196,24 +197,24 @@ internal partial class InstallForm : CustomForm
|
||||||
await OperateFor(selection);
|
await OperateFor(selection);
|
||||||
UpdateUser($"Operation succeeded for {selection.Name}.", LogTextBox.Success);
|
UpdateUser($"Operation succeeded for {selection.Name}.", LogTextBox.Success);
|
||||||
selection.Enabled = false;
|
selection.Enabled = false;
|
||||||
DisabledSelections.Add(selection);
|
disabledSelections.Add(selection);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
UpdateUser($"Operation failed for {selection.Name}: " + exception, LogTextBox.Error);
|
UpdateUser($"Operation failed for {selection.Name}: " + exception, LogTextBox.Error);
|
||||||
}
|
}
|
||||||
++CompleteOperationsCount;
|
++completeOperationsCount;
|
||||||
}
|
}
|
||||||
Program.Cleanup();
|
Program.Cleanup();
|
||||||
List<ProgramSelection> FailedSelections = ProgramSelection.AllEnabled;
|
List<ProgramSelection> failedSelections = ProgramSelection.AllEnabled;
|
||||||
if (FailedSelections.Any())
|
if (failedSelections.Any())
|
||||||
if (FailedSelections.Count == 1)
|
if (failedSelections.Count == 1)
|
||||||
throw new CustomMessageException($"Operation failed for {FailedSelections.First().Name}.");
|
throw new CustomMessageException($"Operation failed for {failedSelections.First().Name}.");
|
||||||
else
|
else
|
||||||
throw new CustomMessageException($"Operation failed for {FailedSelections.Count} programs.");
|
throw new CustomMessageException($"Operation failed for {failedSelections.Count} programs.");
|
||||||
foreach (ProgramSelection selection in DisabledSelections)
|
foreach (ProgramSelection selection in disabledSelections)
|
||||||
selection.Enabled = true;
|
selection.Enabled = true;
|
||||||
DisabledSelections.Clear();
|
disabledSelections.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Start()
|
private async void Start()
|
||||||
|
@ -227,12 +228,12 @@ internal partial class InstallForm : CustomForm
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Operate();
|
await Operate();
|
||||||
UpdateUser($"DLC unlocker(s) successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + ProgramCount + " program(s).",
|
UpdateUser($"DLC unlocker(s) successfully {(uninstalling ? "uninstalled" : "installed and generated")} for " + programCount + " program(s).",
|
||||||
LogTextBox.Success);
|
LogTextBox.Success);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
UpdateUser($"DLC unlocker {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception, LogTextBox.Error);
|
UpdateUser($"DLC unlocker {(uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception, LogTextBox.Error);
|
||||||
retryButton.Enabled = true;
|
retryButton.Enabled = true;
|
||||||
}
|
}
|
||||||
userProgressBar.Value = userProgressBar.Maximum;
|
userProgressBar.Value = userProgressBar.Maximum;
|
||||||
|
@ -276,9 +277,9 @@ internal partial class InstallForm : CustomForm
|
||||||
{
|
{
|
||||||
Program.Cleanup();
|
Program.Cleanup();
|
||||||
Reselecting = true;
|
Reselecting = true;
|
||||||
foreach (ProgramSelection selection in DisabledSelections)
|
foreach (ProgramSelection selection in disabledSelections)
|
||||||
selection.Enabled = true;
|
selection.Enabled = true;
|
||||||
DisabledSelections.Clear();
|
disabledSelections.Clear();
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ using Onova.Services;
|
||||||
|
|
||||||
namespace CreamInstaller.Forms;
|
namespace CreamInstaller.Forms;
|
||||||
|
|
||||||
internal partial class MainForm : CustomForm
|
internal sealed partial class MainForm : CustomForm
|
||||||
{
|
{
|
||||||
private CancellationTokenSource cancellationTokenSource;
|
private CancellationTokenSource cancellationTokenSource;
|
||||||
private Version latestVersion;
|
private Version latestVersion;
|
||||||
|
@ -68,11 +68,10 @@ internal partial class MainForm : CustomForm
|
||||||
updateManager = new(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath), resolver, extractor);
|
updateManager = new(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath), resolver, extractor);
|
||||||
if (latestVersion is null)
|
if (latestVersion is null)
|
||||||
{
|
{
|
||||||
CheckForUpdatesResult checkForUpdatesResult = null;
|
|
||||||
cancellationTokenSource = new();
|
cancellationTokenSource = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token);
|
CheckForUpdatesResult checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token);
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (checkForUpdatesResult.CanUpdate)
|
if (checkForUpdatesResult.CanUpdate)
|
||||||
{
|
{
|
||||||
|
@ -133,7 +132,7 @@ internal partial class MainForm : CustomForm
|
||||||
foreach (HtmlNode node in nodes)
|
foreach (HtmlNode node in nodes)
|
||||||
changelogTreeView.Invoke(delegate
|
changelogTreeView.Invoke(delegate
|
||||||
{
|
{
|
||||||
TreeNode change = new() { Text = HttpUtility.HtmlDecode(node.InnerText) };
|
TreeNode change = new() { Text = HttpUtility.HtmlDecode(node.InnerText) ?? string.Empty };
|
||||||
root.Nodes.Add(change);
|
root.Nodes.Add(change);
|
||||||
root.Expand();
|
root.Expand();
|
||||||
if (changelogTreeView.Nodes.Count > 0)
|
if (changelogTreeView.Nodes.Count > 0)
|
||||||
|
@ -149,8 +148,8 @@ internal partial class MainForm : CustomForm
|
||||||
retry:
|
retry:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string FileName = Path.GetFileName(Program.CurrentProcessFilePath);
|
string fileName = Path.GetFileName(Program.CurrentProcessFilePath);
|
||||||
if (FileName != Program.ApplicationExecutable)
|
if (fileName != Program.ApplicationExecutable)
|
||||||
{
|
{
|
||||||
using DialogForm form = new(this);
|
using DialogForm form = new(this);
|
||||||
if (form.Show(SystemIcons.Warning,
|
if (form.Show(SystemIcons.Warning,
|
||||||
|
@ -232,4 +231,4 @@ internal partial class MainForm : CustomForm
|
||||||
cancellationTokenSource?.Dispose();
|
cancellationTokenSource?.Dispose();
|
||||||
updateManager?.Dispose();
|
updateManager?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ using CreamInstaller.Utility;
|
||||||
|
|
||||||
namespace CreamInstaller.Forms;
|
namespace CreamInstaller.Forms;
|
||||||
|
|
||||||
internal partial class SelectDialogForm : CustomForm
|
internal sealed 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();
|
||||||
|
@ -69,9 +69,7 @@ internal partial class SelectDialogForm : CustomForm
|
||||||
|
|
||||||
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
bool shouldCheck = false;
|
bool shouldCheck = selectionTreeView.Nodes.Cast<TreeNode>().Any(n => !n.Checked);
|
||||||
if (selectionTreeView.Nodes.Cast<TreeNode>().Any(n => !n.Checked))
|
|
||||||
shouldCheck = true;
|
|
||||||
foreach (TreeNode node in selectionTreeView.Nodes)
|
foreach (TreeNode node in selectionTreeView.Nodes)
|
||||||
{
|
{
|
||||||
node.Checked = shouldCheck;
|
node.Checked = shouldCheck;
|
||||||
|
@ -84,8 +82,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().ToList();
|
||||||
if (choices is null)
|
if (!choices.Any())
|
||||||
return;
|
return;
|
||||||
foreach (TreeNode node in selectionTreeView.Nodes)
|
foreach (TreeNode node in selectionTreeView.Nodes)
|
||||||
{
|
{
|
||||||
|
@ -96,10 +94,7 @@ internal partial class SelectDialogForm : CustomForm
|
||||||
|
|
||||||
private void OnSave(object sender, EventArgs e)
|
private void OnSave(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
List<(Platform platform, string id)> choices = new();
|
ProgramData.WriteProgramChoices(selectionTreeView.Nodes.Cast<TreeNode>().Where(n => n.Checked).Select(node => ((Platform)node.Tag, node.Name)));
|
||||||
foreach (TreeNode node in selectionTreeView.Nodes.Cast<TreeNode>().Where(n => n.Checked))
|
|
||||||
choices.Add(((Platform)node.Tag, node.Name));
|
|
||||||
ProgramData.WriteProgramChoices(choices);
|
|
||||||
loadButton.Enabled = ProgramData.ReadProgramChoices() is not null;
|
loadButton.Enabled = ProgramData.ReadProgramChoices() is not null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,4 @@
|
||||||
#pragma warning disable IDE0058
|
using System;
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
@ -22,15 +20,15 @@ using static CreamInstaller.Resources.Resources;
|
||||||
|
|
||||||
namespace CreamInstaller.Forms;
|
namespace CreamInstaller.Forms;
|
||||||
|
|
||||||
internal partial class SelectForm : CustomForm
|
internal sealed partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
private readonly string helpButtonListPrefix = "\n • ";
|
private const string HelpButtonListPrefix = "\n • ";
|
||||||
|
|
||||||
private readonly SynchronizedCollection<string> RemainingDLCs = new();
|
private readonly SynchronizedCollection<string> remainingDLCs = new();
|
||||||
|
|
||||||
private readonly SynchronizedCollection<string> RemainingGames = new();
|
private readonly SynchronizedCollection<string> remainingGames = new();
|
||||||
|
|
||||||
private List<(Platform platform, string id, string name)> ProgramsToScan;
|
private List<(Platform platform, string id, string name)> programsToScan;
|
||||||
|
|
||||||
internal SelectForm()
|
internal SelectForm()
|
||||||
{
|
{
|
||||||
|
@ -40,12 +38,12 @@ internal partial class SelectForm : CustomForm
|
||||||
|
|
||||||
public override ContextMenuStrip ContextMenuStrip => base.ContextMenuStrip ??= new();
|
public override ContextMenuStrip ContextMenuStrip => base.ContextMenuStrip ??= new();
|
||||||
|
|
||||||
internal List<TreeNode> TreeNodes => GatherTreeNodes(selectionTreeView.Nodes);
|
private List<TreeNode> TreeNodes => GatherTreeNodes(selectionTreeView.Nodes);
|
||||||
|
|
||||||
private static void UpdateRemaining(Label label, SynchronizedCollection<string> list, string descriptor)
|
private static void UpdateRemaining(Label label, SynchronizedCollection<string> list, string descriptor)
|
||||||
=> label.Text = list.Any() ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") : "";
|
=> label.Text = list.Any() ? $"Remaining {descriptor} ({list.Count}): " + string.Join(", ", list).Replace("&", "&&") : "";
|
||||||
|
|
||||||
private void UpdateRemainingGames() => UpdateRemaining(progressLabelGames, RemainingGames, "games");
|
private void UpdateRemainingGames() => UpdateRemaining(progressLabelGames, remainingGames, "games");
|
||||||
|
|
||||||
private void AddToRemainingGames(string gameName)
|
private void AddToRemainingGames(string gameName)
|
||||||
{
|
{
|
||||||
|
@ -55,8 +53,8 @@ internal partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
if (!RemainingGames.Contains(gameName))
|
if (!remainingGames.Contains(gameName))
|
||||||
RemainingGames.Add(gameName);
|
remainingGames.Add(gameName);
|
||||||
UpdateRemainingGames();
|
UpdateRemainingGames();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -69,12 +67,12 @@ internal partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
RemainingGames.Remove(gameName);
|
remainingGames.Remove(gameName);
|
||||||
UpdateRemainingGames();
|
UpdateRemainingGames();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateRemainingDLCs() => UpdateRemaining(progressLabelDLCs, RemainingDLCs, "DLCs");
|
private void UpdateRemainingDLCs() => UpdateRemaining(progressLabelDLCs, remainingDLCs, "DLCs");
|
||||||
|
|
||||||
private void AddToRemainingDLCs(string dlcId)
|
private void AddToRemainingDLCs(string dlcId)
|
||||||
{
|
{
|
||||||
|
@ -84,8 +82,8 @@ internal partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
if (!RemainingDLCs.Contains(dlcId))
|
if (!remainingDLCs.Contains(dlcId))
|
||||||
RemainingDLCs.Add(dlcId);
|
remainingDLCs.Add(dlcId);
|
||||||
UpdateRemainingDLCs();
|
UpdateRemainingDLCs();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -98,35 +96,35 @@ internal partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
RemainingDLCs.Remove(dlcId);
|
remainingDLCs.Remove(dlcId);
|
||||||
UpdateRemainingDLCs();
|
UpdateRemainingDLCs();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetApplicablePrograms(IProgress<int> progress)
|
private async Task GetApplicablePrograms(IProgress<int> progress)
|
||||||
{
|
{
|
||||||
if (ProgramsToScan is null || !ProgramsToScan.Any())
|
if (programsToScan is null || !programsToScan.Any())
|
||||||
return;
|
return;
|
||||||
int TotalGameCount = 0;
|
int totalGameCount = 0;
|
||||||
int CompleteGameCount = 0;
|
int completeGameCount = 0;
|
||||||
void AddToRemainingGames(string gameName)
|
void AddToRemainingGames(string gameName)
|
||||||
{
|
{
|
||||||
this.AddToRemainingGames(gameName);
|
this.AddToRemainingGames(gameName);
|
||||||
progress.Report(-Interlocked.Increment(ref TotalGameCount));
|
progress.Report(-Interlocked.Increment(ref totalGameCount));
|
||||||
progress.Report(CompleteGameCount);
|
progress.Report(completeGameCount);
|
||||||
}
|
}
|
||||||
void RemoveFromRemainingGames(string gameName)
|
void RemoveFromRemainingGames(string gameName)
|
||||||
{
|
{
|
||||||
this.RemoveFromRemainingGames(gameName);
|
this.RemoveFromRemainingGames(gameName);
|
||||||
progress.Report(Interlocked.Increment(ref CompleteGameCount));
|
progress.Report(Interlocked.Increment(ref completeGameCount));
|
||||||
}
|
}
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
List<TreeNode> treeNodes = TreeNodes;
|
List<TreeNode> treeNodes = TreeNodes;
|
||||||
RemainingGames.Clear(); // for display purposes only, otherwise ignorable
|
remainingGames.Clear(); // for display purposes only, otherwise ignorable
|
||||||
RemainingDLCs.Clear(); // for display purposes only, otherwise ignorable
|
remainingDLCs.Clear(); // for display purposes only, otherwise ignorable
|
||||||
List<Task> appTasks = new();
|
List<Task> appTasks = new();
|
||||||
if (ProgramsToScan.Any(c => c.platform is Platform.Paradox))
|
if (programsToScan.Any(c => c.platform is Platform.Paradox))
|
||||||
{
|
{
|
||||||
List<string> dllDirectories = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox);
|
List<string> dllDirectories = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox);
|
||||||
if (dllDirectories is not null)
|
if (dllDirectories is not null)
|
||||||
|
@ -153,7 +151,7 @@ internal partial class SelectForm : CustomForm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int steamGamesToCheck;
|
int steamGamesToCheck;
|
||||||
if (ProgramsToScan.Any(c => c.platform is Platform.Steam))
|
if (programsToScan.Any(c => c.platform is Platform.Steam))
|
||||||
{
|
{
|
||||||
List<(string appId, string name, string branch, int buildId, string gameDirectory)> steamGames = await SteamLibrary.GetGames();
|
List<(string appId, string name, string branch, int buildId, string gameDirectory)> steamGames = await SteamLibrary.GetGames();
|
||||||
steamGamesToCheck = steamGames.Count;
|
steamGamesToCheck = steamGames.Count;
|
||||||
|
@ -161,7 +159,7 @@ internal partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Steam && c.id == appId))
|
if (Program.IsGameBlocked(name, gameDirectory) || !programsToScan.Any(c => c.platform is Platform.Steam && c.id == appId))
|
||||||
{
|
{
|
||||||
Interlocked.Decrement(ref steamGamesToCheck);
|
Interlocked.Decrement(ref steamGamesToCheck);
|
||||||
continue;
|
continue;
|
||||||
|
@ -287,7 +285,7 @@ internal partial class SelectForm : CustomForm
|
||||||
_ = selectionTreeView.Nodes.Add(programNode);
|
_ = selectionTreeView.Nodes.Add(programNode);
|
||||||
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in dlc)
|
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in dlc)
|
||||||
{
|
{
|
||||||
if (Program.Canceled || programNode is null)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
string appId = pair.Key;
|
string appId = pair.Key;
|
||||||
(DlcType type, string name, string icon) dlcApp = pair.Value;
|
(DlcType type, string name, string icon) dlcApp = pair.Value;
|
||||||
|
@ -310,7 +308,7 @@ internal partial class SelectForm : CustomForm
|
||||||
appTasks.Add(task);
|
appTasks.Add(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ProgramsToScan.Any(c => c.platform is Platform.Epic))
|
if (programsToScan.Any(c => c.platform is Platform.Epic))
|
||||||
{
|
{
|
||||||
List<Manifest> epicGames = await EpicLibrary.GetGames();
|
List<Manifest> epicGames = await EpicLibrary.GetGames();
|
||||||
foreach (Manifest manifest in epicGames)
|
foreach (Manifest manifest in epicGames)
|
||||||
|
@ -320,7 +318,7 @@ internal partial class SelectForm : CustomForm
|
||||||
string directory = manifest.InstallLocation;
|
string directory = manifest.InstallLocation;
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
if (Program.IsGameBlocked(name, directory) || !ProgramsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace))
|
if (Program.IsGameBlocked(name, directory) || !programsToScan.Any(c => c.platform is Platform.Epic && c.id == @namespace))
|
||||||
continue;
|
continue;
|
||||||
AddToRemainingGames(name);
|
AddToRemainingGames(name);
|
||||||
Task task = Task.Run(async () =>
|
Task task = Task.Run(async () =>
|
||||||
|
@ -437,14 +435,14 @@ internal partial class SelectForm : CustomForm
|
||||||
appTasks.Add(task);
|
appTasks.Add(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ProgramsToScan.Any(c => c.platform is Platform.Ubisoft))
|
if (programsToScan.Any(c => c.platform is Platform.Ubisoft))
|
||||||
{
|
{
|
||||||
List<(string gameId, string name, string gameDirectory)> ubisoftGames = await UbisoftLibrary.GetGames();
|
List<(string gameId, string name, string gameDirectory)> ubisoftGames = await UbisoftLibrary.GetGames();
|
||||||
foreach ((string gameId, string name, string gameDirectory) in ubisoftGames)
|
foreach ((string gameId, string name, string gameDirectory) in ubisoftGames)
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return;
|
return;
|
||||||
if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Ubisoft && c.id == gameId))
|
if (Program.IsGameBlocked(name, gameDirectory) || !programsToScan.Any(c => c.platform is Platform.Ubisoft && c.id == gameId))
|
||||||
continue;
|
continue;
|
||||||
AddToRemainingGames(name);
|
AddToRemainingGames(name);
|
||||||
Task task = Task.Run(async () =>
|
Task task = Task.Run(async () =>
|
||||||
|
@ -521,34 +519,34 @@ internal partial class SelectForm : CustomForm
|
||||||
ShowProgressBar();
|
ShowProgressBar();
|
||||||
await ProgramData.Setup();
|
await ProgramData.Setup();
|
||||||
bool scan = forceScan;
|
bool scan = forceScan;
|
||||||
if (!scan && (ProgramsToScan is null || !ProgramsToScan.Any() || forceProvideChoices))
|
if (!scan && (programsToScan is null || !programsToScan.Any() || forceProvideChoices))
|
||||||
{
|
{
|
||||||
List<(Platform platform, string id, string name, bool alreadySelected)> gameChoices = new();
|
List<(Platform platform, string id, string name, bool alreadySelected)> gameChoices = new();
|
||||||
if (Directory.Exists(ParadoxLauncher.InstallPath))
|
if (Directory.Exists(ParadoxLauncher.InstallPath))
|
||||||
gameChoices.Add((Platform.Paradox, "PL", "Paradox Launcher",
|
gameChoices.Add((Platform.Paradox, "PL", "Paradox Launcher",
|
||||||
ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL")));
|
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL")));
|
||||||
if (Directory.Exists(SteamLibrary.InstallPath))
|
if (Directory.Exists(SteamLibrary.InstallPath))
|
||||||
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in (await SteamLibrary.GetGames()).Where(g
|
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in (await SteamLibrary.GetGames()).Where(g
|
||||||
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
|
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
|
||||||
gameChoices.Add((Platform.Steam, appId, name,
|
gameChoices.Add((Platform.Steam, appId, name,
|
||||||
ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Steam && p.id == appId)));
|
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Steam && p.id == appId)));
|
||||||
if (Directory.Exists(EpicLibrary.EpicManifestsPath))
|
if (Directory.Exists(EpicLibrary.EpicManifestsPath))
|
||||||
foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation)))
|
foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation)))
|
||||||
gameChoices.Add((Platform.Epic, manifest.CatalogNamespace, manifest.DisplayName,
|
gameChoices.Add((Platform.Epic, manifest.CatalogNamespace, manifest.DisplayName,
|
||||||
ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Epic && p.id == manifest.CatalogNamespace)));
|
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Epic && p.id == manifest.CatalogNamespace)));
|
||||||
foreach ((string gameId, string name, string gameDirectory) in (await UbisoftLibrary.GetGames()).Where(g
|
foreach ((string gameId, string name, string gameDirectory) in (await UbisoftLibrary.GetGames()).Where(g
|
||||||
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
|
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
|
||||||
gameChoices.Add((Platform.Ubisoft, gameId, name,
|
gameChoices.Add((Platform.Ubisoft, gameId, name,
|
||||||
ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Ubisoft && p.id == gameId)));
|
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Ubisoft && p.id == gameId)));
|
||||||
if (gameChoices.Any())
|
if (gameChoices.Any())
|
||||||
{
|
{
|
||||||
using SelectDialogForm form = new(this);
|
using SelectDialogForm form = new(this);
|
||||||
List<(Platform platform, string id, string name)> choices = form.QueryUser("Choose which programs and/or games to scan for DLC:", gameChoices);
|
List<(Platform platform, string id, string name)> choices = form.QueryUser("Choose which programs and/or games to scan for DLC:", gameChoices);
|
||||||
scan = choices is not null && choices.Any();
|
scan = choices is not null && choices.Any();
|
||||||
string retry = "\n\nPress the \"Rescan Programs / Games\" button to re-choose.";
|
const string retry = "\n\nPress the \"Rescan Programs / Games\" button to re-choose.";
|
||||||
if (scan)
|
if (scan)
|
||||||
{
|
{
|
||||||
ProgramsToScan = choices;
|
programsToScan = choices;
|
||||||
noneFoundLabel.Text = "None of the chosen programs nor games were applicable!" + retry;
|
noneFoundLabel.Text = "None of the chosen programs nor games were applicable!" + retry;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -576,14 +574,14 @@ internal partial class SelectForm : CustomForm
|
||||||
progressLabel.Text = setup ? $"Setting up SteamCMD . . . {p}%" : $"Gathering and caching your applicable games and their DLCs . . . {p}%";
|
progressLabel.Text = setup ? $"Setting up SteamCMD . . . {p}%" : $"Gathering and caching your applicable games and their DLCs . . . {p}%";
|
||||||
progressBar.Value = p;
|
progressBar.Value = p;
|
||||||
};
|
};
|
||||||
if (Directory.Exists(SteamLibrary.InstallPath) && ProgramsToScan is not null && ProgramsToScan.Any(c => c.platform is Platform.Steam))
|
if (Directory.Exists(SteamLibrary.InstallPath) && programsToScan is not null && programsToScan.Any(c => c.platform is Platform.Steam))
|
||||||
{
|
{
|
||||||
progressLabel.Text = "Setting up SteamCMD . . . ";
|
progressLabel.Text = "Setting up SteamCMD . . . ";
|
||||||
await SteamCMD.Setup(iProgress);
|
await SteamCMD.Setup(iProgress);
|
||||||
}
|
}
|
||||||
setup = false;
|
setup = false;
|
||||||
progressLabel.Text = "Gathering and caching your applicable games and their DLCs . . . ";
|
progressLabel.Text = "Gathering and caching your applicable games and their DLCs . . . ";
|
||||||
ProgramSelection.ValidateAll(ProgramsToScan);
|
ProgramSelection.ValidateAll(programsToScan);
|
||||||
/*TreeNodes.ForEach(node =>
|
/*TreeNodes.ForEach(node =>
|
||||||
{
|
{
|
||||||
if (node.Tag is not Platform platform
|
if (node.Tag is not Platform platform
|
||||||
|
@ -638,11 +636,16 @@ internal partial class SelectForm : CustomForm
|
||||||
|
|
||||||
private static void SyncNodeAncestors(TreeNode node)
|
private static void SyncNodeAncestors(TreeNode node)
|
||||||
{
|
{
|
||||||
TreeNode parentNode = node.Parent;
|
while (true)
|
||||||
if (parentNode is not null)
|
|
||||||
{
|
{
|
||||||
parentNode.Checked = parentNode.Nodes.Cast<TreeNode>().Any(childNode => childNode.Checked);
|
TreeNode parentNode = node.Parent;
|
||||||
SyncNodeAncestors(parentNode);
|
if (parentNode is not null)
|
||||||
|
{
|
||||||
|
parentNode.Checked = parentNode.Nodes.Cast<TreeNode>().Any(childNode => childNode.Checked);
|
||||||
|
node = parentNode;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,7 +724,7 @@ internal partial class SelectForm : CustomForm
|
||||||
=> Invoke(() =>
|
=> Invoke(() =>
|
||||||
{
|
{
|
||||||
ContextMenuStrip contextMenuStrip = ContextMenuStrip;
|
ContextMenuStrip contextMenuStrip = ContextMenuStrip;
|
||||||
while (ContextMenuStrip.Tag is bool used && used)
|
while (ContextMenuStrip.Tag is true)
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
ContextMenuStrip.Tag = true;
|
ContextMenuStrip.Tag = true;
|
||||||
ToolStripItemCollection items = contextMenuStrip.Items;
|
ToolStripItemCollection items = contextMenuStrip.Items;
|
||||||
|
@ -737,18 +740,18 @@ internal partial class SelectForm : CustomForm
|
||||||
dlcParentSelection = ProgramSelection.FromPlatformId(platform, dlc.Value.gameAppId);
|
dlcParentSelection = ProgramSelection.FromPlatformId(platform, dlc.Value.gameAppId);
|
||||||
if (selection is null && dlcParentSelection is null)
|
if (selection is null && dlcParentSelection is null)
|
||||||
return;
|
return;
|
||||||
ContextMenuItem header = null;
|
ContextMenuItem header;
|
||||||
if (id == "PL")
|
if (id == "PL")
|
||||||
header = new(node.Text, "Paradox Launcher");
|
header = new(node.Text, "Paradox Launcher");
|
||||||
else if (selection is not null)
|
else if (selection is not null)
|
||||||
header = new(node.Text, (id, selection.IconUrl));
|
header = new(node.Text, (id, selection.IconUrl));
|
||||||
else if (dlc is not null && dlcParentSelection is not null)
|
else
|
||||||
header = new(node.Text, (id, dlc.Value.app.icon), (id, dlcParentSelection.IconUrl));
|
header = new(node.Text, (id, dlc.Value.app.icon), (id, dlcParentSelection.IconUrl));
|
||||||
items.Add(header ?? new ContextMenuItem(node.Text));
|
items.Add(header);
|
||||||
string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf";
|
string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf";
|
||||||
string appInfoJSON = $@"{SteamCMD.AppInfoPath}\{id}.json";
|
string appInfoJSON = $@"{SteamCMD.AppInfoPath}\{id}.json";
|
||||||
string cooldown = $@"{ProgramData.CooldownPath}\{id}.txt";
|
string cooldown = $@"{ProgramData.CooldownPath}\{id}.txt";
|
||||||
if ((File.Exists(appInfoVDF) || File.Exists(appInfoJSON)) && (selection is not null || dlc is not null))
|
if (File.Exists(appInfoVDF) || File.Exists(appInfoJSON))
|
||||||
{
|
{
|
||||||
List<ContextMenuItem> queries = new();
|
List<ContextMenuItem> queries = new();
|
||||||
if (File.Exists(appInfoJSON))
|
if (File.Exists(appInfoJSON))
|
||||||
|
@ -773,17 +776,26 @@ internal partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
File.Delete(appInfoVDF);
|
File.Delete(appInfoVDF);
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.Delete(appInfoJSON);
|
File.Delete(appInfoJSON);
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.Delete(cooldown);
|
File.Delete(cooldown);
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
OnLoad(true);
|
OnLoad(true);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -793,7 +805,8 @@ internal partial class SelectForm : CustomForm
|
||||||
if (id == "PL")
|
if (id == "PL")
|
||||||
{
|
{
|
||||||
items.Add(new ToolStripSeparator());
|
items.Add(new ToolStripSeparator());
|
||||||
items.Add(new ContextMenuItem("Repair", "Command Prompt", async (sender, e) => await ParadoxLauncher.Repair(this, selection)));
|
async void EventHandler(object sender, EventArgs e) => await ParadoxLauncher.Repair(this, selection);
|
||||||
|
items.Add(new ContextMenuItem("Repair", "Command Prompt", EventHandler));
|
||||||
}
|
}
|
||||||
items.Add(new ToolStripSeparator());
|
items.Add(new ToolStripSeparator());
|
||||||
items.Add(new ContextMenuItem("Open Root Directory", "File Explorer",
|
items.Add(new ContextMenuItem("Open Root Directory", "File Explorer",
|
||||||
|
@ -807,10 +820,10 @@ internal partial class SelectForm : CustomForm
|
||||||
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
||||||
foreach (string directory in directories)
|
foreach (string directory in directories)
|
||||||
{
|
{
|
||||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
|
||||||
out string cache);
|
out string config, out string cache);
|
||||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)
|
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(old_config)
|
||||||
|| File.Exists(cache))
|
|| File.Exists(config) || File.Exists(cache))
|
||||||
items.Add(new ContextMenuItem($"Open Steamworks Directory #{++steam}", "File Explorer",
|
items.Add(new ContextMenuItem($"Open Steamworks Directory #{++steam}", "File Explorer",
|
||||||
(sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)));
|
(sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)));
|
||||||
}
|
}
|
||||||
|
@ -838,42 +851,37 @@ internal partial class SelectForm : CustomForm
|
||||||
}
|
}
|
||||||
if (id != "PL")
|
if (id != "PL")
|
||||||
{
|
{
|
||||||
if (selection is not null && selection.Platform is Platform.Steam
|
if (selection?.Platform is Platform.Steam || dlcParentSelection?.Platform is Platform.Steam)
|
||||||
|| dlcParentSelection is not null && dlcParentSelection.Platform is Platform.Steam)
|
|
||||||
{
|
{
|
||||||
items.Add(new ToolStripSeparator());
|
items.Add(new ToolStripSeparator());
|
||||||
items.Add(new ContextMenuItem("Open SteamDB", "SteamDB",
|
items.Add(new ContextMenuItem("Open SteamDB", "SteamDB",
|
||||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamdb.info/app/" + id)));
|
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamdb.info/app/" + id)));
|
||||||
}
|
}
|
||||||
if (selection is not null)
|
if (selection is not null)
|
||||||
{
|
switch (selection.Platform)
|
||||||
if (selection.Platform is Platform.Steam)
|
|
||||||
{
|
{
|
||||||
items.Add(new ContextMenuItem("Open Steam Store", "Steam Store",
|
case Platform.Steam:
|
||||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)));
|
items.Add(new ContextMenuItem("Open Steam Store", "Steam Store",
|
||||||
items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), "Steam Community",
|
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)));
|
||||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id)));
|
items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), "Steam Community",
|
||||||
|
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id)));
|
||||||
|
break;
|
||||||
|
case Platform.Epic:
|
||||||
|
items.Add(new ToolStripSeparator());
|
||||||
|
items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB",
|
||||||
|
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://scream-db.web.app/offers/" + id)));
|
||||||
|
items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games",
|
||||||
|
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)));
|
||||||
|
break;
|
||||||
|
case Platform.Ubisoft:
|
||||||
|
items.Add(new ToolStripSeparator());
|
||||||
|
items.Add(new ContextMenuItem("Open Ubisoft Store", "Ubisoft Store",
|
||||||
|
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://store.ubi.com/us/"
|
||||||
|
+ selection.Name.Replace(" ", "-").ToLowerInvariant())));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (selection.Platform is Platform.Epic)
|
|
||||||
{
|
|
||||||
items.Add(new ToolStripSeparator());
|
|
||||||
items.Add(new ContextMenuItem("Open ScreamDB", "ScreamDB",
|
|
||||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://scream-db.web.app/offers/" + id)));
|
|
||||||
items.Add(new ContextMenuItem("Open Epic Games Store", "Epic Games",
|
|
||||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)));
|
|
||||||
}
|
|
||||||
if (selection.Platform is Platform.Ubisoft)
|
|
||||||
{
|
|
||||||
items.Add(new ToolStripSeparator());
|
|
||||||
#pragma warning disable CA1308 // Normalize strings to uppercase
|
|
||||||
items.Add(new ContextMenuItem("Open Ubisoft Store", "Ubisoft Store",
|
|
||||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://store.ubi.com/us/"
|
|
||||||
+ selection.Name.Replace(" ", "-").ToLowerInvariant())));
|
|
||||||
#pragma warning restore CA1308 // Normalize strings to uppercase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (selection is not null && selection.WebsiteUrl is not null)
|
if (selection?.WebsiteUrl != null)
|
||||||
items.Add(new ContextMenuItem("Open Official Website", ("Web_" + id, IconGrabber.GetDomainFaviconUrl(selection.WebsiteUrl)),
|
items.Add(new ContextMenuItem("Open Official Website", ("Web_" + id, IconGrabber.GetDomainFaviconUrl(selection.WebsiteUrl)),
|
||||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.WebsiteUrl)));
|
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.WebsiteUrl)));
|
||||||
contextMenuStrip.Show(selectionTreeView, location);
|
contextMenuStrip.Show(selectionTreeView, location);
|
||||||
|
@ -900,38 +908,34 @@ internal partial class SelectForm : CustomForm
|
||||||
|
|
||||||
private void OnAccept(bool uninstall = false)
|
private void OnAccept(bool uninstall = false)
|
||||||
{
|
{
|
||||||
if (ProgramSelection.All.Any())
|
if (!ProgramSelection.All.Any())
|
||||||
|
return;
|
||||||
|
if (ProgramSelection.AllEnabled.Any(selection => !Program.IsProgramRunningDialog(this, selection)))
|
||||||
|
return;
|
||||||
|
if (!uninstall && ParadoxLauncher.DlcDialog(this))
|
||||||
|
return;
|
||||||
|
Hide();
|
||||||
|
InstallForm form = new(uninstall);
|
||||||
|
form.InheritLocation(this);
|
||||||
|
form.FormClosing += (s, e) =>
|
||||||
{
|
{
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllEnabled)
|
if (form.Reselecting)
|
||||||
if (!Program.IsProgramRunningDialog(this, selection))
|
|
||||||
return;
|
|
||||||
if (!uninstall && ParadoxLauncher.DlcDialog(this))
|
|
||||||
return;
|
|
||||||
Hide();
|
|
||||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
|
||||||
InstallForm form = new(uninstall);
|
|
||||||
#pragma warning restore CA2000 // Dispose objects before losing scope
|
|
||||||
form.InheritLocation(this);
|
|
||||||
form.FormClosing += (s, e) =>
|
|
||||||
{
|
{
|
||||||
if (form.Reselecting)
|
InheritLocation(form);
|
||||||
{
|
Show();
|
||||||
InheritLocation(form);
|
|
||||||
Show();
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugForm.Current.Attach(this);
|
DebugForm.Current.Attach(this);
|
||||||
#endif
|
#endif
|
||||||
OnLoad();
|
OnLoad();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Close();
|
Close();
|
||||||
};
|
};
|
||||||
form.Show();
|
form.Show();
|
||||||
Hide();
|
Hide();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugForm.Current.Attach(form);
|
DebugForm.Current.Attach(form);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInstall(object sender, EventArgs e) => OnAccept();
|
private void OnInstall(object sender, EventArgs e) => OnAccept();
|
||||||
|
@ -948,33 +952,20 @@ internal partial class SelectForm : CustomForm
|
||||||
|
|
||||||
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
bool shouldCheck = false;
|
bool shouldCheck = TreeNodes.Any(node => node.Parent is null && !node.Checked);
|
||||||
foreach (TreeNode node in TreeNodes)
|
foreach (TreeNode node in TreeNodes.Where(node => node.Parent is null && node.Checked != shouldCheck))
|
||||||
if (node.Parent is null && !node.Checked)
|
{
|
||||||
{
|
node.Checked = shouldCheck;
|
||||||
shouldCheck = true;
|
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
foreach (TreeNode node in TreeNodes)
|
|
||||||
if (node.Parent is null && node.Checked != shouldCheck)
|
|
||||||
{
|
|
||||||
node.Checked = shouldCheck;
|
|
||||||
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
|
||||||
}
|
|
||||||
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
|
allCheckBox.CheckedChanged -= OnAllCheckBoxChanged;
|
||||||
allCheckBox.Checked = shouldCheck;
|
allCheckBox.Checked = shouldCheck;
|
||||||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnKoaloaderAllCheckBoxChanged(object sender, EventArgs e)
|
private void OnKoaloaderAllCheckBoxChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
bool shouldCheck = false;
|
bool shouldCheck = ProgramSelection.AllSafe.Any(selection => !selection.Koaloader);
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
|
||||||
if (!selection.Koaloader)
|
|
||||||
{
|
|
||||||
shouldCheck = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||||
selection.Koaloader = shouldCheck;
|
selection.Koaloader = shouldCheck;
|
||||||
selectionTreeView.Invalidate();
|
selectionTreeView.Invalidate();
|
||||||
|
@ -984,21 +975,15 @@ internal partial class SelectForm : CustomForm
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool AreSelectionsDefault()
|
private bool AreSelectionsDefault()
|
||||||
{
|
=> TreeNodes.All(node => node.Parent is null || node.Tag is not Platform || (node.Text == "Unknown" ? !node.Checked : node.Checked));
|
||||||
foreach (TreeNode node in TreeNodes)
|
|
||||||
if (node.Parent is not null && node.Tag is Platform && (node.Text == "Unknown" ? node.Checked : !node.Checked))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CanSaveDlc() => installButton.Enabled && (ProgramData.ReadDlcChoices() is not null || !AreSelectionsDefault());
|
private bool CanSaveDlc() => installButton.Enabled && (ProgramData.ReadDlcChoices().Any() || !AreSelectionsDefault());
|
||||||
|
|
||||||
private void OnSaveDlc(object sender, EventArgs e)
|
private void OnSaveDlc(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices()
|
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices().ToList();
|
||||||
?? new List<(Platform platform, string gameId, string dlcId)>();
|
|
||||||
foreach (TreeNode node in TreeNodes)
|
foreach (TreeNode node in TreeNodes)
|
||||||
if (node.Parent is TreeNode parent && node.Tag is Platform platform)
|
if (node.Parent is { } parent && node.Tag is Platform platform)
|
||||||
{
|
{
|
||||||
if (node.Text == "Unknown" ? node.Checked : !node.Checked)
|
if (node.Text == "Unknown" ? node.Checked : !node.Checked)
|
||||||
choices.Add((platform, node.Parent.Name, node.Name));
|
choices.Add((platform, node.Parent.Name, node.Name));
|
||||||
|
@ -1011,15 +996,13 @@ internal partial class SelectForm : CustomForm
|
||||||
saveButton.Enabled = CanSaveDlc();
|
saveButton.Enabled = CanSaveDlc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CanLoadDlc() => ProgramData.ReadDlcChoices() is not null;
|
private static bool CanLoadDlc() => ProgramData.ReadDlcChoices().Any();
|
||||||
|
|
||||||
private void OnLoadDlc(object sender, EventArgs e)
|
private void OnLoadDlc(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices();
|
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices().ToList();
|
||||||
if (choices is null)
|
|
||||||
return;
|
|
||||||
foreach (TreeNode node in TreeNodes)
|
foreach (TreeNode node in TreeNodes)
|
||||||
if (node.Parent is TreeNode parent && node.Tag is Platform platform)
|
if (node.Parent is { } parent && node.Tag is Platform platform)
|
||||||
{
|
{
|
||||||
node.Checked = choices.Any(c => c.platform == platform && c.gameId == parent.Name && c.dlcId == node.Name)
|
node.Checked = choices.Any(c => c.platform == platform && c.gameId == parent.Name && c.dlcId == node.Name)
|
||||||
? node.Text == "Unknown"
|
? node.Text == "Unknown"
|
||||||
|
@ -1032,29 +1015,21 @@ internal partial class SelectForm : CustomForm
|
||||||
|
|
||||||
private void OnResetDlc(object sender, EventArgs e)
|
private void OnResetDlc(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
foreach (TreeNode node in TreeNodes)
|
foreach (TreeNode node in TreeNodes.Where(node => node.Parent is not null && node.Tag is Platform))
|
||||||
if (node.Parent is not null && node.Tag is Platform)
|
{
|
||||||
{
|
node.Checked = node.Text != "Unknown";
|
||||||
node.Checked = node.Text != "Unknown";
|
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
||||||
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
}
|
||||||
}
|
|
||||||
resetButton.Enabled = CanResetDlc();
|
resetButton.Enabled = CanResetDlc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AreKoaloaderSelectionsDefault()
|
private static bool AreKoaloaderSelectionsDefault() => ProgramSelection.AllSafe.All(selection => selection.Koaloader && selection.KoaloaderProxy is null);
|
||||||
{
|
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
|
||||||
if (!selection.Koaloader || selection.KoaloaderProxy is not null)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool CanSaveKoaloader() => ProgramData.ReadKoaloaderChoices() is not null || !AreKoaloaderSelectionsDefault();
|
private static bool CanSaveKoaloader() => ProgramData.ReadKoaloaderChoices().Any() || !AreKoaloaderSelectionsDefault();
|
||||||
|
|
||||||
private void OnSaveKoaloader(object sender, EventArgs e)
|
private void OnSaveKoaloader(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices()
|
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices().ToList();
|
||||||
?? new List<(Platform platform, string id, string proxy, bool enabled)>();
|
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||||
{
|
{
|
||||||
_ = choices.RemoveAll(c => c.platform == selection.Platform && c.id == selection.Id);
|
_ = choices.RemoveAll(c => c.platform == selection.Platform && c.id == selection.Id);
|
||||||
|
@ -1067,13 +1042,11 @@ internal partial class SelectForm : CustomForm
|
||||||
loadKoaloaderButton.Enabled = CanLoadKoaloader();
|
loadKoaloaderButton.Enabled = CanLoadKoaloader();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CanLoadKoaloader() => ProgramData.ReadKoaloaderChoices() is not null;
|
private static bool CanLoadKoaloader() => ProgramData.ReadKoaloaderChoices().Any();
|
||||||
|
|
||||||
private void OnLoadKoaloader(object sender, EventArgs e)
|
private void OnLoadKoaloader(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices();
|
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices().ToList();
|
||||||
if (choices is null)
|
|
||||||
return;
|
|
||||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||||
if (choices.Any(c => c.platform == selection.Platform && c.id == selection.Id))
|
if (choices.Any(c => c.platform == selection.Platform && c.id == selection.Id))
|
||||||
{
|
{
|
||||||
|
@ -1135,25 +1108,23 @@ internal partial class SelectForm : CustomForm
|
||||||
{
|
{
|
||||||
StringBuilder blockedGames = new();
|
StringBuilder blockedGames = new();
|
||||||
foreach (string name in Program.ProtectedGames)
|
foreach (string name in Program.ProtectedGames)
|
||||||
_ = blockedGames.Append(helpButtonListPrefix + name);
|
_ = blockedGames.Append(HelpButtonListPrefix + name);
|
||||||
StringBuilder blockedDirectories = new();
|
StringBuilder blockedDirectories = new();
|
||||||
foreach (string path in Program.ProtectedGameDirectories)
|
foreach (string path in Program.ProtectedGameDirectories)
|
||||||
_ = blockedDirectories.Append(helpButtonListPrefix + path);
|
_ = blockedDirectories.Append(HelpButtonListPrefix + path);
|
||||||
StringBuilder blockedDirectoryExceptions = new();
|
StringBuilder blockedDirectoryExceptions = new();
|
||||||
foreach (string name in Program.ProtectedGameDirectoryExceptions)
|
foreach (string name in Program.ProtectedGameDirectoryExceptions)
|
||||||
_ = blockedDirectoryExceptions.Append(helpButtonListPrefix + name);
|
_ = blockedDirectoryExceptions.Append(HelpButtonListPrefix + name);
|
||||||
using DialogForm form = new(this);
|
using DialogForm form = new(this);
|
||||||
_ = form.Show(SystemIcons.Information,
|
_ = form.Show(SystemIcons.Information,
|
||||||
"Blocks the program from caching and displaying games protected by anti-cheats."
|
"Blocks the program from caching and displaying games protected by anti-cheats."
|
||||||
+ "\nYou disable this option and install DLC unlockers to protected games at your own risk!" + "\n\nBlocked games: "
|
+ "\nYou disable this option and install DLC unlockers to protected games at your own risk!" + "\n\nBlocked games: "
|
||||||
+ (string.IsNullOrWhiteSpace(blockedGames.ToString()) ? "(none)" : blockedGames) + "\n\nBlocked game sub-directories: "
|
+ (string.IsNullOrWhiteSpace(blockedGames.ToString()) ? "(none)" : blockedGames) + "\n\nBlocked game sub-directories: "
|
||||||
+ (string.IsNullOrWhiteSpace(blockedDirectories.ToString()) ? "(none)" : blockedDirectories) + "\n\nBlocked game sub-directory exceptions: "
|
+ (string.IsNullOrWhiteSpace(blockedDirectories.ToString()) ? "(none)" : blockedDirectories) + "\n\nBlocked game sub-directory exceptions: "
|
||||||
+ (string.IsNullOrWhiteSpace(blockedDirectoryExceptions.ToString()) ? "(none)" : blockedDirectoryExceptions), "OK",
|
+ (string.IsNullOrWhiteSpace(blockedDirectoryExceptions.ToString()) ? "(none)" : blockedDirectoryExceptions),
|
||||||
customFormText: "Block Protected Games");
|
customFormText: "Block Protected Games");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSortCheckBoxChanged(object sender, EventArgs e)
|
private void OnSortCheckBoxChanged(object sender, EventArgs e)
|
||||||
=> selectionTreeView.TreeViewNodeSorter = sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
=> selectionTreeView.TreeViewNodeSorter = sortCheckBox.Checked ? PlatformIdComparer.NodeText : PlatformIdComparer.NodeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning restore IDE0058
|
|
|
@ -49,8 +49,10 @@ internal static class EpicLibrary
|
||||||
=> g.CatalogItemId == manifest.CatalogItemId && g.InstallLocation == manifest.InstallLocation))
|
=> g.CatalogItemId == manifest.CatalogItemId && g.InstallLocation == manifest.InstallLocation))
|
||||||
games.Add(manifest);
|
games.Add(manifest);
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
;
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return games;
|
return games;
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,14 +13,14 @@ namespace CreamInstaller.Platforms.Epic;
|
||||||
|
|
||||||
internal static class EpicStore
|
internal static class EpicStore
|
||||||
{
|
{
|
||||||
//private const int COOLDOWN_CATALOG_ITEM = 600;
|
//private const int CooldownCatalogItem = 600;
|
||||||
|
|
||||||
/* need a method to query catalog items
|
/* need a method to query catalog items
|
||||||
internal static async Task QueryCatalogItems(Manifest manifest)
|
internal static async Task QueryCatalogItems(Manifest manifest)
|
||||||
{
|
{
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
private const int COOLDOWN_ENTITLEMENT = 600;
|
private const int CooldownEntitlement = 600;
|
||||||
|
|
||||||
internal static async Task<List<(string id, string name, string product, string icon, string developer)>> QueryEntitlements(string categoryNamespace)
|
internal static async Task<List<(string id, string name, string product, string icon, string developer)>> QueryEntitlements(string categoryNamespace)
|
||||||
{
|
{
|
||||||
|
@ -28,16 +28,19 @@ internal static class EpicStore
|
||||||
string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json";
|
string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json";
|
||||||
bool cachedExists = File.Exists(cacheFile);
|
bool cachedExists = File.Exists(cacheFile);
|
||||||
Response response = null;
|
Response response = null;
|
||||||
if (!cachedExists || ProgramData.CheckCooldown(categoryNamespace, COOLDOWN_ENTITLEMENT))
|
if (!cachedExists || ProgramData.CheckCooldown(categoryNamespace, CooldownEntitlement))
|
||||||
{
|
{
|
||||||
response = await QueryGraphQL(categoryNamespace);
|
response = await QueryGraphQL(categoryNamespace);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await File.WriteAllTextAsync(cacheFile, JsonConvert.SerializeObject(response, Formatting.Indented));
|
await File.WriteAllTextAsync(cacheFile, JsonConvert.SerializeObject(response, Formatting.Indented));
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (cachedExists)
|
else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response = JsonConvert.DeserializeObject<Response>(await File.ReadAllTextAsync(cacheFile));
|
response = JsonConvert.DeserializeObject<Response>(await File.ReadAllTextAsync(cacheFile));
|
||||||
|
@ -57,11 +60,10 @@ internal static class EpicStore
|
||||||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||||
{
|
{
|
||||||
KeyImage keyImage = element.KeyImages[i];
|
KeyImage keyImage = element.KeyImages[i];
|
||||||
if (keyImage.Type == "DieselStoreFront")
|
if (keyImage.Type != "DieselStoreFront")
|
||||||
{
|
continue;
|
||||||
icon = keyImage.Url.ToString();
|
icon = keyImage.Url.ToString();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
foreach (Item item in element.Items)
|
foreach (Item item in element.Items)
|
||||||
dlcIds.Populate(item.Id, title, product, icon, null, element.Items.Length == 1);
|
dlcIds.Populate(item.Id, title, product, icon, null, element.Items.Length == 1);
|
||||||
|
@ -75,11 +77,10 @@ internal static class EpicStore
|
||||||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||||
{
|
{
|
||||||
KeyImage keyImage = element.KeyImages[i];
|
KeyImage keyImage = element.KeyImages[i];
|
||||||
if (keyImage.Type == "Thumbnail")
|
if (keyImage.Type != "Thumbnail")
|
||||||
{
|
continue;
|
||||||
icon = keyImage.Url.ToString();
|
icon = keyImage.Url.ToString();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
foreach (Item item in element.Items)
|
foreach (Item item in element.Items)
|
||||||
dlcIds.Populate(item.Id, title, product, icon, item.Developer, element.Items.Length == 1);
|
dlcIds.Populate(item.Id, title, product, icon, item.Developer, element.Items.Length == 1);
|
||||||
|
@ -96,14 +97,13 @@ internal static class EpicStore
|
||||||
for (int i = 0; i < dlcIds.Count; i++)
|
for (int i = 0; i < dlcIds.Count; i++)
|
||||||
{
|
{
|
||||||
(string id, string name, string product, string icon, string developer) app = dlcIds[i];
|
(string id, string name, string product, string icon, string developer) app = dlcIds[i];
|
||||||
if (app.id == id)
|
if (app.id != id)
|
||||||
{
|
continue;
|
||||||
found = true;
|
found = true;
|
||||||
dlcIds[i] = canOverwrite
|
dlcIds[i] = canOverwrite
|
||||||
? (app.id, title ?? app.name, product ?? app.product, icon ?? app.icon, developer ?? app.developer)
|
? (app.id, title ?? app.name, product ?? app.product, icon ?? app.icon, developer ?? app.developer)
|
||||||
: (app.id, app.name ?? title, app.product ?? product, app.icon ?? icon, app.developer ?? developer);
|
: (app.id, app.name ?? title, app.product ?? product, app.icon ?? icon, app.developer ?? developer);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
dlcIds.Add((id, title, product, icon, developer));
|
dlcIds.Add((id, title, product, icon, developer));
|
||||||
|
@ -131,4 +131,4 @@ internal static class EpicStore
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace CreamInstaller.Platforms.Epic.GraphQL;
|
namespace CreamInstaller.Platforms.Epic.GraphQL;
|
||||||
|
|
||||||
internal class Request
|
internal sealed class Request
|
||||||
{
|
{
|
||||||
internal Request(string @namespace) => Vars = new(@namespace);
|
internal Request(string @namespace) => Vars = new(@namespace);
|
||||||
|
|
||||||
|
@ -61,13 +61,13 @@ internal class Request
|
||||||
[JsonProperty(PropertyName = "variables")]
|
[JsonProperty(PropertyName = "variables")]
|
||||||
private Variables Vars { get; set; }
|
private Variables Vars { get; set; }
|
||||||
|
|
||||||
private class Headers
|
private sealed class Headers
|
||||||
{
|
{
|
||||||
[JsonProperty(PropertyName = "Content-Type")]
|
[JsonProperty(PropertyName = "Content-Type")]
|
||||||
private string ContentType => "application/graphql";
|
private string ContentType => "application/graphql";
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Variables
|
private sealed class Variables
|
||||||
{
|
{
|
||||||
internal Variables(string @namespace) => Namespace = @namespace;
|
internal Variables(string @namespace) => Namespace = @namespace;
|
||||||
|
|
||||||
|
|
|
@ -15,4 +15,4 @@ public class Manifest
|
||||||
public string MainGameCatalogNamespace { get; set; }
|
public string MainGameCatalogNamespace { get; set; }
|
||||||
|
|
||||||
public string MainGameCatalogItemId { get; set; }
|
public string MainGameCatalogItemId { get; set; }
|
||||||
}
|
}
|
|
@ -98,10 +98,12 @@ 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.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||||
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
||||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out _);
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
|
||||||
smokeInstalled = smokeInstalled || File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled
|
out string config, out _);
|
||||||
|
smokeInstalled = smokeInstalled || File.Exists(api32_o) || File.Exists(api64_o)
|
||||||
|
|| (File.Exists(config) || File.Exists(config)) && !koaloaderInstalled
|
||||||
|| File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|
|| File.Exists(api32) && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|
||||||
|| File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
|
|| File.Exists(api64) && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
|
||||||
await SmokeAPI.Uninstall(directory, deleteConfig: false);
|
await SmokeAPI.Uninstall(directory, deleteConfig: false);
|
||||||
|
@ -125,7 +127,7 @@ internal static class ParadoxLauncher
|
||||||
bool neededRepair = false;
|
bool neededRepair = false;
|
||||||
foreach (string directory in selection.DllDirectories)
|
foreach (string directory in selection.DllDirectories)
|
||||||
{
|
{
|
||||||
directory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _);
|
directory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _, out _);
|
||||||
if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32))
|
if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32))
|
||||||
{
|
{
|
||||||
steamOriginalSdk32.Write(api32);
|
steamOriginalSdk32.Write(api32);
|
||||||
|
@ -161,13 +163,13 @@ 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", customFormText: "Paradox Launcher");
|
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", 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", customFormText: "Paradox Launcher");
|
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher");
|
||||||
return RepairResult.Unnecessary;
|
return RepairResult.Unnecessary;
|
||||||
}
|
}
|
||||||
_ = form is InstallForm
|
_ = form is InstallForm
|
||||||
|
@ -175,8 +177,8 @@ internal static class ParadoxLauncher
|
||||||
+ "You will likely have to reinstall Paradox Launcher to fix this issue.")
|
+ "You will likely have to reinstall Paradox Launcher to fix this issue.")
|
||||||
: dialogForm.Show(SystemIcons.Error,
|
: dialogForm.Show(SystemIcons.Error,
|
||||||
"Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found."
|
"Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found."
|
||||||
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", "OK",
|
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.",
|
||||||
customFormText: "Paradox Launcher");
|
customFormText: "Paradox Launcher");
|
||||||
return RepairResult.Failure;
|
return RepairResult.Failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,24 +17,24 @@ namespace CreamInstaller.Platforms.Steam;
|
||||||
|
|
||||||
internal static class SteamCMD
|
internal static class SteamCMD
|
||||||
{
|
{
|
||||||
internal const int ProcessLimit = 20;
|
private const int ProcessLimit = 20;
|
||||||
|
|
||||||
internal static readonly string FilePath = DirectoryPath + @"\steamcmd.exe";
|
private static readonly string FilePath = DirectoryPath + @"\steamcmd.exe";
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<string, int> AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print
|
private static readonly ConcurrentDictionary<string, int> AttemptCount = new(); // the more app_updates, the longer SteamCMD should wait for app_info_print
|
||||||
|
|
||||||
private static readonly int[] locks = new int[ProcessLimit];
|
private static readonly int[] Locks = new int[ProcessLimit];
|
||||||
|
|
||||||
internal static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip";
|
private static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip";
|
||||||
internal static readonly string DllPath = DirectoryPath + @"\steamclient.dll";
|
private static readonly string DllPath = DirectoryPath + @"\steamclient.dll";
|
||||||
|
|
||||||
internal static readonly string AppCachePath = DirectoryPath + @"\appcache";
|
private static readonly string AppCachePath = DirectoryPath + @"\appcache";
|
||||||
internal static readonly string ConfigPath = DirectoryPath + @"\config";
|
private static readonly string ConfigPath = DirectoryPath + @"\config";
|
||||||
internal static readonly string DumpsPath = DirectoryPath + @"\dumps";
|
private static readonly string DumpsPath = DirectoryPath + @"\dumps";
|
||||||
internal static readonly string LogsPath = DirectoryPath + @"\logs";
|
private static readonly string LogsPath = DirectoryPath + @"\logs";
|
||||||
internal static readonly string SteamAppsPath = DirectoryPath + @"\steamapps";
|
private static readonly string SteamAppsPath = DirectoryPath + @"\steamapps";
|
||||||
|
|
||||||
internal static string DirectoryPath => ProgramData.DirectoryPath;
|
private static string DirectoryPath => ProgramData.DirectoryPath;
|
||||||
internal static string AppInfoPath => ProgramData.AppInfoPath;
|
internal static string AppInfoPath => ProgramData.AppInfoPath;
|
||||||
|
|
||||||
private static string GetArguments(string appId)
|
private static string GetArguments(string appId)
|
||||||
|
@ -43,19 +43,19 @@ internal static class SteamCMD
|
||||||
+ string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit"
|
+ string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit"
|
||||||
: $"+login anonymous +app_info_print {appId} +quit";
|
: $"+login anonymous +app_info_print {appId} +quit";
|
||||||
|
|
||||||
internal static async Task<string> Run(string appId)
|
private static async Task<string> Run(string appId)
|
||||||
=> await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
{
|
||||||
wait_for_lock:
|
wait_for_lock:
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return "";
|
return "";
|
||||||
for (int i = 0; i < locks.Length; i++)
|
for (int i = 0; i < Locks.Length; i++)
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return "";
|
return "";
|
||||||
if (Interlocked.CompareExchange(ref locks[i], 1, 0) == 0)
|
if (Interlocked.CompareExchange(ref Locks[i], 1, 0) == 0)
|
||||||
{
|
{
|
||||||
if (appId is not null)
|
if (appId != null)
|
||||||
{
|
{
|
||||||
AttemptCount.TryGetValue(appId, out int count);
|
AttemptCount.TryGetValue(appId, out int count);
|
||||||
AttemptCount[appId] = ++count;
|
AttemptCount[appId] = ++count;
|
||||||
|
@ -69,11 +69,13 @@ internal static class SteamCMD
|
||||||
StandardInputEncoding = Encoding.UTF8, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8
|
StandardInputEncoding = Encoding.UTF8, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8
|
||||||
};
|
};
|
||||||
Process process = Process.Start(processStartInfo);
|
Process process = Process.Start(processStartInfo);
|
||||||
|
if (appId == null)
|
||||||
|
return "";
|
||||||
StringBuilder output = new();
|
StringBuilder output = new();
|
||||||
StringBuilder appInfo = new();
|
StringBuilder appInfo = new();
|
||||||
bool appInfoStarted = false;
|
bool appInfoStarted = false;
|
||||||
DateTime lastOutput = DateTime.UtcNow;
|
DateTime lastOutput = DateTime.UtcNow;
|
||||||
while (true)
|
while (process != null)
|
||||||
{
|
{
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
{
|
{
|
||||||
|
@ -92,24 +94,23 @@ internal static class SteamCMD
|
||||||
}
|
}
|
||||||
DateTime now = DateTime.UtcNow;
|
DateTime now = DateTime.UtcNow;
|
||||||
TimeSpan timeDiff = now - lastOutput;
|
TimeSpan timeDiff = now - lastOutput;
|
||||||
if (timeDiff.TotalSeconds > 0.1)
|
if (!(timeDiff.TotalSeconds > 0.1))
|
||||||
|
continue;
|
||||||
|
process.Kill(true);
|
||||||
|
process.Close();
|
||||||
|
if (output.ToString().Contains($"No app info for AppID {appId} found, requesting..."))
|
||||||
{
|
{
|
||||||
process.Kill(true);
|
AttemptCount[appId]++;
|
||||||
process.Close();
|
processStartInfo.Arguments = GetArguments(appId);
|
||||||
if (output.ToString().Contains($"No app info for AppID {appId} found, requesting..."))
|
process = Process.Start(processStartInfo);
|
||||||
{
|
appInfoStarted = false;
|
||||||
AttemptCount[appId]++;
|
_ = output.Clear();
|
||||||
processStartInfo.Arguments = GetArguments(appId);
|
_ = appInfo.Clear();
|
||||||
process = Process.Start(processStartInfo);
|
|
||||||
appInfoStarted = false;
|
|
||||||
_ = output.Clear();
|
|
||||||
_ = appInfo.Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
_ = Interlocked.Decrement(ref locks[i]);
|
_ = Interlocked.Decrement(ref Locks[i]);
|
||||||
return appInfo.ToString();
|
return appInfo.ToString();
|
||||||
}
|
}
|
||||||
Thread.Sleep(200);
|
Thread.Sleep(200);
|
||||||
|
@ -174,7 +175,10 @@ internal static class SteamCMD
|
||||||
if (Directory.Exists(SteamAppsPath))
|
if (Directory.Exists(SteamAppsPath))
|
||||||
Directory.Delete(SteamAppsPath, true); // this is just a useless folder created from +app_update 4
|
Directory.Delete(SteamAppsPath, true); // this is just a useless folder created from +app_update 4
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
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)
|
||||||
|
@ -223,12 +227,12 @@ internal static class SteamCMD
|
||||||
File.Delete(appUpdateFile);
|
File.Delete(appUpdateFile);
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
if (appInfo is null || appInfo.Value?.Children()?.ToList()?.Count == 0)
|
if (appInfo.Value.Children().ToList().Count == 0)
|
||||||
return appInfo;
|
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)?.GetChild("buildid")?.ToString();
|
string buildid = appInfo.Value.GetChild("depots")?.GetChild("branches")?.GetChild(branch)?.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))
|
||||||
|
@ -279,7 +283,10 @@ internal static class SteamCMD
|
||||||
process.WaitForExit();
|
process.WaitForExit();
|
||||||
process.Close();
|
process.Close();
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
})).ToList();
|
})).ToList();
|
||||||
foreach (Task task in tasks)
|
foreach (Task task in tasks)
|
||||||
await task;
|
await task;
|
||||||
|
@ -291,4 +298,4 @@ internal static class SteamCMD
|
||||||
if (Directory.Exists(DirectoryPath))
|
if (Directory.Exists(DirectoryPath))
|
||||||
Directory.Delete(DirectoryPath, true);
|
Directory.Delete(DirectoryPath, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -110,4 +110,4 @@ internal static class SteamLibrary
|
||||||
}
|
}
|
||||||
return gameDirectories;
|
return gameDirectories;
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -124,4 +124,4 @@ internal static class SteamStore
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,10 @@ internal static class ValveDataFile
|
||||||
result = VdfConvert.Deserialize(value);
|
result = VdfConvert.Deserialize(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +26,10 @@ internal static class ValveDataFile
|
||||||
{
|
{
|
||||||
return token[index];
|
return token[index];
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -41,4 +41,4 @@ internal static class UbisoftLibrary
|
||||||
}
|
}
|
||||||
return games;
|
return games;
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@ namespace CreamInstaller;
|
||||||
internal static class Program
|
internal static class Program
|
||||||
{
|
{
|
||||||
internal static readonly string Name = Application.CompanyName;
|
internal static readonly string Name = Application.CompanyName;
|
||||||
internal static readonly string Description = Application.ProductName;
|
private static readonly string Description = Application.ProductName;
|
||||||
internal static readonly string Version = Application.ProductVersion;
|
internal static readonly string Version = Application.ProductVersion;
|
||||||
|
|
||||||
internal const string RepositoryOwner = "pointfeev";
|
internal const string RepositoryOwner = "pointfeev";
|
||||||
|
@ -32,8 +32,8 @@ internal static class Program
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
internal static readonly Assembly EntryAssembly = Assembly.GetEntryAssembly();
|
internal static readonly Assembly EntryAssembly = Assembly.GetEntryAssembly();
|
||||||
internal static readonly Process CurrentProcess = Process.GetCurrentProcess();
|
private static readonly Process CurrentProcess = Process.GetCurrentProcess();
|
||||||
internal static readonly string CurrentProcessFilePath = CurrentProcess.MainModule.FileName;
|
internal static readonly string CurrentProcessFilePath = CurrentProcess.MainModule?.FileName;
|
||||||
|
|
||||||
internal static bool BlockProtectedGames = true;
|
internal static bool BlockProtectedGames = true;
|
||||||
internal static readonly string[] ProtectedGames = { "PAYDAY 2" };
|
internal static readonly string[] ProtectedGames = { "PAYDAY 2" };
|
||||||
|
@ -46,25 +46,27 @@ internal static class Program
|
||||||
return false;
|
return false;
|
||||||
if (ProtectedGames.Contains(name))
|
if (ProtectedGames.Contains(name))
|
||||||
return true;
|
return true;
|
||||||
if (directory is not null && !ProtectedGameDirectoryExceptions.Contains(name))
|
if (directory is null || ProtectedGameDirectoryExceptions.Contains(name))
|
||||||
foreach (string path in ProtectedGameDirectories)
|
return false;
|
||||||
if (Directory.Exists(directory + path))
|
return ProtectedGameDirectories.Any(path => Directory.Exists(directory + path));
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool IsProgramRunningDialog(Form form, ProgramSelection selection)
|
internal static bool IsProgramRunningDialog(Form form, ProgramSelection selection)
|
||||||
{
|
{
|
||||||
if (selection.AreDllsLocked)
|
while (true)
|
||||||
{
|
{
|
||||||
using DialogForm dialogForm = new(form);
|
if (selection.AreDllsLocked)
|
||||||
if (dialogForm.Show(SystemIcons.Error, $"ERROR: {selection.Name} is currently running!" + "\n\nPlease close the program/game to continue . . . ",
|
{
|
||||||
"Retry", "Cancel") == DialogResult.OK)
|
using DialogForm dialogForm = new(form);
|
||||||
return IsProgramRunningDialog(form, selection);
|
if (dialogForm.Show(SystemIcons.Error,
|
||||||
|
$"ERROR: {selection.Name} is currently running!" + "\n\nPlease close the program/game to continue . . . ", "Retry", "Cancel")
|
||||||
|
== DialogResult.OK)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
|
@ -114,4 +116,4 @@ internal static class Program
|
||||||
Cleanup();
|
Cleanup();
|
||||||
HttpClientManager.Dispose();
|
HttpClientManager.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ public enum DlcType
|
||||||
EpicEntitlement
|
EpicEntitlement
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ProgramSelection
|
internal sealed class ProgramSelection
|
||||||
{
|
{
|
||||||
internal const string DefaultKoaloaderProxy = "version";
|
internal const string DefaultKoaloaderProxy = "version";
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ internal class ProgramSelection
|
||||||
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, out string cache);
|
directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out string old_config, out config, out string cache);
|
||||||
if (api32.IsFilePathLocked() || api32_o.IsFilePathLocked() || api64.IsFilePathLocked() || api64_o.IsFilePathLocked()
|
if (api32.IsFilePathLocked() || api32_o.IsFilePathLocked() || api64.IsFilePathLocked() || api64_o.IsFilePathLocked()
|
||||||
|| config.IsFilePathLocked() || cache.IsFilePathLocked())
|
|| old_config.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)
|
||||||
|
@ -114,16 +114,15 @@ internal class ProgramSelection
|
||||||
{
|
{
|
||||||
string appId = pair.Key;
|
string appId = pair.Key;
|
||||||
(DlcType type, string name, string icon) dlcApp = pair.Value;
|
(DlcType type, string name, string icon) dlcApp = pair.Value;
|
||||||
if (appId == dlcId)
|
if (appId != dlcId)
|
||||||
{
|
continue;
|
||||||
Toggle(appId, dlcApp, enabled);
|
Toggle(appId, dlcApp, enabled);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Enabled = SelectedDlc.Any() || ExtraSelectedDlc.Any();
|
Enabled = SelectedDlc.Any() || ExtraSelectedDlc.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Validate()
|
private void Validate()
|
||||||
{
|
{
|
||||||
if (Program.IsGameBlocked(Name, RootDirectory))
|
if (Program.IsGameBlocked(Name, RootDirectory))
|
||||||
{
|
{
|
||||||
|
@ -140,7 +139,7 @@ internal class ProgramSelection
|
||||||
_ = All.Remove(this);
|
_ = All.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Validate(List<(Platform platform, string id, string name)> programsToScan)
|
private void Validate(List<(Platform platform, string id, string name)> programsToScan)
|
||||||
{
|
{
|
||||||
if (programsToScan is null || !programsToScan.Any(p => p.platform == Platform && p.id == Id))
|
if (programsToScan is null || !programsToScan.Any(p => p.platform == Platform && p.id == Id))
|
||||||
{
|
{
|
||||||
|
@ -164,4 +163,4 @@ internal class ProgramSelection
|
||||||
return (selection.Id, pair.Value);
|
return (selection.Id, pair.Value);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@ namespace CreamInstaller.Resources;
|
||||||
|
|
||||||
internal static class Koaloader
|
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"), ("Lyptus", "Lyptus.dll"),
|
("Koaloader", "Unlocker.dll"), ("Koaloader", "Unlocker32.dll"), ("Koaloader", "Unlocker64.dll"), ("Lyptus", "Lyptus.dll"),
|
||||||
("Lyptus", "Lyptus32.dll"), ("Lyptus", "Lyptus64.dll"), ("SmokeAPI", "SmokeAPI.dll"), ("SmokeAPI", "SmokeAPI32.dll"),
|
("Lyptus", "Lyptus32.dll"), ("Lyptus", "Lyptus64.dll"), ("SmokeAPI", "SmokeAPI.dll"), ("SmokeAPI", "SmokeAPI32.dll"),
|
||||||
|
@ -21,28 +21,26 @@ internal static class Koaloader
|
||||||
("Uplay R2 Unlocker", "UplayR2Unlocker.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll")
|
("Uplay R2 Unlocker", "UplayR2Unlocker.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll")
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static void GetKoaloaderComponents(this string directory, out List<string> proxies, out string config)
|
internal static void GetKoaloaderComponents(this string directory, out List<string> proxies, out string old_config, out string config)
|
||||||
{
|
{
|
||||||
proxies = new();
|
proxies = 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)..];
|
||||||
}))
|
}).Select(proxy => directory + @"\" + proxy).ToList();
|
||||||
proxies.Add(directory + @"\" + proxy);
|
old_config = directory + @"\Koaloader.json";
|
||||||
config = directory + @"\Koaloader.json";
|
config = directory + @"\Koaloader.config.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteProxy(this string path, string proxyName, BinaryType binaryType)
|
private static void WriteProxy(this string path, string proxyName, BinaryType binaryType)
|
||||||
{
|
{
|
||||||
foreach (string resourceIdentifier in EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")))
|
foreach (string resourceIdentifier in EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")))
|
||||||
{
|
{
|
||||||
resourceIdentifier.GetProxyInfoFromIdentifier(out string _proxyName, out BinaryType _binaryType);
|
resourceIdentifier.GetProxyInfoFromIdentifier(out string _proxyName, out BinaryType _binaryType);
|
||||||
if (_proxyName == proxyName && _binaryType == binaryType)
|
if (_proxyName != proxyName || _binaryType != binaryType)
|
||||||
{
|
continue;
|
||||||
resourceIdentifier.Write(path);
|
resourceIdentifier.Write(path);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,16 +50,17 @@ internal static class Koaloader
|
||||||
baseIdentifier = baseIdentifier[..baseIdentifier.IndexOf('.')];
|
baseIdentifier = baseIdentifier[..baseIdentifier.IndexOf('.')];
|
||||||
proxyName = baseIdentifier[..baseIdentifier.LastIndexOf('_')];
|
proxyName = baseIdentifier[..baseIdentifier.LastIndexOf('_')];
|
||||||
string bitness = baseIdentifier[(baseIdentifier.LastIndexOf('_') + 1)..];
|
string bitness = baseIdentifier[(baseIdentifier.LastIndexOf('_') + 1)..];
|
||||||
binaryType = bitness == "32"
|
binaryType = bitness switch { "32" => BinaryType.BIT32, "64" => BinaryType.BIT64, _ => BinaryType.Unknown };
|
||||||
? BinaryType.BIT32
|
|
||||||
: bitness == "64"
|
|
||||||
? BinaryType.BIT64
|
|
||||||
: BinaryType.Unknown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null)
|
private static void CheckConfig(string directory, ProgramSelection selection, InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
directory.GetKoaloaderComponents(out _, out string config);
|
directory.GetKoaloaderComponents(out _, out string old_config, out string config);
|
||||||
|
if (File.Exists(old_config))
|
||||||
|
{
|
||||||
|
File.Delete(old_config);
|
||||||
|
installForm?.UpdateUser($"Deleted old configuration: {Path.GetFileName(old_config)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
SortedList<string, string> targets = new(PlatformIdComparer.String);
|
SortedList<string, string> targets = new(PlatformIdComparer.String);
|
||||||
SortedList<string, string> modules = new(PlatformIdComparer.String);
|
SortedList<string, string> modules = new(PlatformIdComparer.String);
|
||||||
if (targets.Any() || modules.Any())
|
if (targets.Any() || modules.Any())
|
||||||
|
@ -81,8 +80,7 @@ internal static class Koaloader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, string> targets, SortedList<string, string> modules,
|
private static void WriteConfig(StreamWriter writer, SortedList<string, string> targets, SortedList<string, string> modules, InstallForm installForm = null)
|
||||||
InstallForm installForm = null)
|
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
writer.WriteLine(" \"logging\": false,");
|
writer.WriteLine(" \"logging\": false,");
|
||||||
|
@ -125,18 +123,23 @@ internal static class Koaloader
|
||||||
internal static async Task Uninstall(string directory, string rootDirectory = null, InstallForm installForm = null, bool deleteConfig = true)
|
internal static async Task Uninstall(string directory, string rootDirectory = null, InstallForm installForm = null, bool deleteConfig = true)
|
||||||
=> await Task.Run(async () =>
|
=> await Task.Run(async () =>
|
||||||
{
|
{
|
||||||
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
|
directory.GetKoaloaderComponents(out List<string> proxies, out string old_config, out string config);
|
||||||
foreach (string proxyPath in proxies.Where(proxyPath => File.Exists(proxyPath) && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader)))
|
foreach (string proxyPath in proxies.Where(proxyPath => File.Exists(proxyPath) && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader)))
|
||||||
{
|
{
|
||||||
File.Delete(proxyPath);
|
File.Delete(proxyPath);
|
||||||
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
foreach ((string unlocker, string path) in AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
foreach ((string unlocker, string path) in AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||||
.Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile()))
|
.Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile()))
|
||||||
{
|
{
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
|
if (deleteConfig && File.Exists(old_config))
|
||||||
|
{
|
||||||
|
File.Delete(old_config);
|
||||||
|
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(old_config)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
if (deleteConfig && File.Exists(config))
|
if (deleteConfig && File.Exists(config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(config);
|
||||||
|
@ -154,7 +157,7 @@ internal static class Koaloader
|
||||||
InstallForm installForm = null, bool generateConfig = true)
|
InstallForm installForm = null, bool generateConfig = true)
|
||||||
=> await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
{
|
{
|
||||||
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
|
directory.GetKoaloaderComponents(out List<string> proxies, out _, out _);
|
||||||
string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy;
|
string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy;
|
||||||
string path = directory + @"\" + proxy + ".dll";
|
string path = directory + @"\" + proxy + ".dll";
|
||||||
foreach (string _path in proxies.Where(p => p != path && File.Exists(p) && p.IsResourceFile(ResourceIdentifier.Koaloader)))
|
foreach (string _path in proxies.Where(p => p != path && File.Exists(p) && p.IsResourceFile(ResourceIdentifier.Koaloader)))
|
||||||
|
@ -171,10 +174,15 @@ internal static class Koaloader
|
||||||
foreach (string executable in Directory.EnumerateFiles(directory, "*.exe"))
|
foreach (string executable in Directory.EnumerateFiles(directory, "*.exe"))
|
||||||
if (executable.TryGetFileBinaryType(out BinaryType binaryType))
|
if (executable.TryGetFileBinaryType(out BinaryType binaryType))
|
||||||
{
|
{
|
||||||
if (binaryType == BinaryType.BIT32)
|
switch (binaryType)
|
||||||
bit32 = true;
|
{
|
||||||
else if (binaryType == BinaryType.BIT64)
|
case BinaryType.BIT32:
|
||||||
bit64 = true;
|
bit32 = true;
|
||||||
|
break;
|
||||||
|
case BinaryType.BIT64:
|
||||||
|
bit64 = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (bit32 && bit64)
|
if (bit32 && bit64)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -216,118 +224,127 @@ internal static class Koaloader
|
||||||
}
|
}
|
||||||
SmokeAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
SmokeAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||||
}
|
}
|
||||||
if (selection.Platform is Platform.Epic or Platform.Paradox)
|
switch (selection.Platform)
|
||||||
{
|
{
|
||||||
if (bit32)
|
case Platform.Epic or Platform.Paradox:
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (bit64)
|
case 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)}", LogTextBox.Action, false);
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
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)}", LogTextBox.Action, false);
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
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)}", LogTextBox.Action, false);
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
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(
|
break;
|
||||||
$"Wrote Uplay R2 Unlocker{(rootDirectory is not null && directory != rootDirectory ? " to root directory" : "")}: {Path.GetFileName(path)}",
|
|
||||||
LogTextBox.Action, false);
|
|
||||||
}
|
}
|
||||||
if (bit64)
|
|
||||||
{
|
|
||||||
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)
|
if (generateConfig)
|
||||||
CheckConfig(directory, selection, installForm);
|
CheckConfig(directory, selection, installForm);
|
||||||
});
|
});
|
||||||
}
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -13,9 +13,9 @@ namespace CreamInstaller.Resources;
|
||||||
|
|
||||||
internal static class Resources
|
internal static class Resources
|
||||||
{
|
{
|
||||||
internal static List<string> embeddedResources;
|
private static List<string> embeddedResources;
|
||||||
|
|
||||||
internal static readonly Dictionary<ResourceIdentifier, IReadOnlyList<string>> ResourceMD5s = new()
|
private static readonly Dictionary<ResourceIdentifier, IReadOnlyList<string>> ResourceMD5s = new()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
ResourceIdentifier.Koaloader, new List<string>
|
ResourceIdentifier.Koaloader, new List<string>
|
||||||
|
@ -263,7 +263,51 @@ internal static class Resources
|
||||||
"76CAB00C7DD33FC19F7CDD1849FF9CA2", // Koaloader v2.4.0
|
"76CAB00C7DD33FC19F7CDD1849FF9CA2", // Koaloader v2.4.0
|
||||||
"DA4D6A7C0872757A74DDAE05A2C1D160", // Koaloader v2.4.0
|
"DA4D6A7C0872757A74DDAE05A2C1D160", // Koaloader v2.4.0
|
||||||
"1F46DE8747C0A157841AFFE6185CE4C9", // Koaloader v2.4.0
|
"1F46DE8747C0A157841AFFE6185CE4C9", // Koaloader v2.4.0
|
||||||
"BE16B588D018D8EFF1F3B6A600F26BED" // Koaloader v2.4.0
|
"BE16B588D018D8EFF1F3B6A600F26BED", // Koaloader v2.4.0
|
||||||
|
"4633C8CD34B05138C5FE4B8950D18A4F", // Koaloader v3.0.1
|
||||||
|
"B8FDA04A5C46AAE8701A332275FA1D79", // Koaloader v3.0.1
|
||||||
|
"1C82C832029D12FA8AF25931C0B30A51", // Koaloader v3.0.1
|
||||||
|
"2AD8B1B70AB1763F612DFFE6BA95C786", // Koaloader v3.0.1
|
||||||
|
"7D05AE4D30C175BA1579C141DDC8A6EA", // Koaloader v3.0.1
|
||||||
|
"BF2BD33D755E7D5BE7262F528F7D2892", // Koaloader v3.0.1
|
||||||
|
"DB00C89FF7ED4E3EF7A3222BDF339A8F", // Koaloader v3.0.1
|
||||||
|
"27EFBABFACA05C95F548AA1BCA2C35D8", // Koaloader v3.0.1
|
||||||
|
"CF676B825204D41B5A1461990146C0AA", // Koaloader v3.0.1
|
||||||
|
"9D4BFD2814B62AB466B11B6740A8C003", // Koaloader v3.0.1
|
||||||
|
"54F4593C319223AFEB1A3ECAC3EB5FD2", // Koaloader v3.0.1
|
||||||
|
"158425881AE6A4DC398579E7589EFCF8", // Koaloader v3.0.1
|
||||||
|
"78E94DF180F264044C07EA7D279058A3", // Koaloader v3.0.1
|
||||||
|
"94FB4AF523BB8D553D926590FA8C4F0A", // Koaloader v3.0.1
|
||||||
|
"63AAAA347EB9D4699CA745A539647356", // Koaloader v3.0.1
|
||||||
|
"1B660B7CC1EB4318B7FC5C2B9D1DF6AD", // Koaloader v3.0.1
|
||||||
|
"805AFEEE7DF85B3019ACD0C4329AAADD", // Koaloader v3.0.1
|
||||||
|
"421567BD7E44A6A3CD8CBE529AED6BB9", // Koaloader v3.0.1
|
||||||
|
"A4769BB227D64337E097FE176CB3DA78", // Koaloader v3.0.1
|
||||||
|
"F03C50515A9FA6B35CF4608577B77D5E", // Koaloader v3.0.1
|
||||||
|
"E606329ED2593839BA479E948640E515", // Koaloader v3.0.1
|
||||||
|
"2A0ABCDC9CF3AC598893D823A188A2AE", // Koaloader v3.0.1
|
||||||
|
"FC8F96E934B7275077B92C1EA59186AC", // Koaloader v3.0.1
|
||||||
|
"06F41AB13C803D0680BBDA231A696795", // Koaloader v3.0.1
|
||||||
|
"D1106C578EE1AA7870CEFD1A06DD57C4", // Koaloader v3.0.1
|
||||||
|
"64C7F3CE83EC5558B3DA2A749122D711", // Koaloader v3.0.1
|
||||||
|
"90556EF98B420EFE3DA97A4BB1141095", // Koaloader v3.0.1
|
||||||
|
"5CEA22F2E663C53ACC6EA80B40789619", // Koaloader v3.0.1
|
||||||
|
"414528403EC318912B424E1984BA4D48", // Koaloader v3.0.1
|
||||||
|
"28CA4DA6C30E69A255234BD3C78E2AD1", // Koaloader v3.0.1
|
||||||
|
"CBE2786E9A493ACDEB4E3276D355EBEC", // Koaloader v3.0.1
|
||||||
|
"2E1E0FAD1EC473DC750636D4C565BD62", // Koaloader v3.0.1
|
||||||
|
"D35E4F7BCE7F909F75B5C6CADF962F54", // Koaloader v3.0.1
|
||||||
|
"184323CD159F9C1883F5276977B543BF", // Koaloader v3.0.1
|
||||||
|
"328258F4E16803BD5FE4100B716A3968", // Koaloader v3.0.1
|
||||||
|
"9F250DEEC8AE1CE49CC91176B5BA3EAC", // Koaloader v3.0.1
|
||||||
|
"F39C05830A7E405990619191A2881C87", // Koaloader v3.0.1
|
||||||
|
"2EED18EC00C83E3756F8A6154BB44817", // Koaloader v3.0.1
|
||||||
|
"F63362E4B1CAABAEC0255BEC78E9EE66", // Koaloader v3.0.1
|
||||||
|
"F77C655EB7A7892DBF0A3591E07E7A00", // Koaloader v3.0.1
|
||||||
|
"4AF5004DDBBD93C21440430255EAF9F3", // Koaloader v3.0.1
|
||||||
|
"E68CFB48E827A0BA486CB900B0A6B24F", // Koaloader v3.0.1
|
||||||
|
"F395ADCA7D27C28121D1AE2C19DDBD6B", // Koaloader v3.0.1
|
||||||
|
"CBB805C763AF199AF2DB35B265A4FF15" // Koaloader v3.0.1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -287,7 +331,8 @@ internal static class Resources
|
||||||
"B2434578957CBE38BDCE0A671C1262FC", // SmokeAPI v1.0.0
|
"B2434578957CBE38BDCE0A671C1262FC", // SmokeAPI v1.0.0
|
||||||
"973AB1632B747D4BF3B2666F32E34327", // SmokeAPI v1.0.1
|
"973AB1632B747D4BF3B2666F32E34327", // SmokeAPI v1.0.1
|
||||||
"C7E41F569FC6A347D67D2BFB2BD10F25", // SmokeAPI v1.0.2
|
"C7E41F569FC6A347D67D2BFB2BD10F25", // SmokeAPI v1.0.2
|
||||||
"F9E7D5B248B86D1C2F2F2905A9F37755" // SmokeAPI v1.0.3
|
"F9E7D5B248B86D1C2F2F2905A9F37755", // SmokeAPI v1.0.3
|
||||||
|
"FD9032CCF73E3A4D7E187F35388BD569" // SmokeAPI v2.0.0-rc01
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -297,7 +342,8 @@ internal static class Resources
|
||||||
"08713035CAD6F52548FF324D0487B88D", // SmokeAPI v1.0.0
|
"08713035CAD6F52548FF324D0487B88D", // SmokeAPI v1.0.0
|
||||||
"D077737B9979D32458AC938A2978FA3C", // SmokeAPI v1.0.1
|
"D077737B9979D32458AC938A2978FA3C", // SmokeAPI v1.0.1
|
||||||
"49122A2E2E51CBB0AE5E1D59B280E4CD", // SmokeAPI v1.0.2
|
"49122A2E2E51CBB0AE5E1D59B280E4CD", // SmokeAPI v1.0.2
|
||||||
"13F3E9476116F7670E21365A400357AC" // SmokeAPI v1.0.3
|
"13F3E9476116F7670E21365A400357AC", // SmokeAPI v1.0.3
|
||||||
|
"151D09637E54A6DF281EAC5A9C484616" // SmokeAPI v2.0.0-rc01
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -332,13 +378,12 @@ internal static class Resources
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (embeddedResources is null)
|
if (embeddedResources is not null)
|
||||||
{
|
return embeddedResources;
|
||||||
string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
||||||
embeddedResources = new();
|
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..]);
|
||||||
}
|
|
||||||
return embeddedResources;
|
return embeddedResources;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +392,7 @@ internal static class Resources
|
||||||
{
|
{
|
||||||
using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier);
|
using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier);
|
||||||
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
|
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
|
||||||
resource.CopyTo(file);
|
resource?.CopyTo(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Write(this byte[] resource, string filePath)
|
internal static void Write(this byte[] resource, string filePath)
|
||||||
|
@ -419,7 +464,7 @@ internal static class Resources
|
||||||
return !executables.Any() ? null : executables;
|
return !executables.Any() ? null : executables;
|
||||||
});
|
});
|
||||||
|
|
||||||
internal static bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
|
private 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") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|
||||||
|
@ -441,37 +486,33 @@ internal static class Resources
|
||||||
if (Program.Canceled)
|
if (Program.Canceled)
|
||||||
return null;
|
return null;
|
||||||
string subDirectory = directory.BeautifyPath();
|
string subDirectory = directory.BeautifyPath();
|
||||||
if (!dllDirectories.Contains(subDirectory))
|
if (dllDirectories.Contains(subDirectory))
|
||||||
|
continue;
|
||||||
|
bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||||
|
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
||||||
|
if (platform is Platform.Steam or Platform.Paradox)
|
||||||
{
|
{
|
||||||
bool koaloaderInstalled = Koaloader.AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string old_config,
|
||||||
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
out string config, out string cache);
|
||||||
if (platform is Platform.Steam or Platform.Paradox)
|
if (File.Exists(api) || File.Exists(api_o) || File.Exists(api64) || File.Exists(api64_o)
|
||||||
{
|
|| (File.Exists(old_config) || File.Exists(config)) && !koaloaderInstalled || File.Exists(cache) && !koaloaderInstalled)
|
||||||
subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string config,
|
dllDirectories.Add(subDirectory);
|
||||||
out string cache);
|
}
|
||||||
if (File.Exists(api) || File.Exists(api_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled
|
if (platform is Platform.Epic or Platform.Paradox)
|
||||||
|| File.Exists(cache) && !koaloaderInstalled)
|
{
|
||||||
dllDirectories.Add(subDirectory);
|
subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
}
|
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled)
|
||||||
if (platform is Platform.Epic or Platform.Paradox)
|
dllDirectories.Add(subDirectory);
|
||||||
{
|
}
|
||||||
subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
if (platform is Platform.Ubisoft)
|
||||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o)
|
{
|
||||||
|| File.Exists(config) && !koaloaderInstalled)
|
subDirectory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||||
dllDirectories.Add(subDirectory);
|
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled)
|
||||||
}
|
dllDirectories.Add(subDirectory);
|
||||||
if (platform is Platform.Ubisoft)
|
subDirectory.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)
|
||||||
subDirectory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
|| File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled)
|
||||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o)
|
dllDirectories.Add(subDirectory);
|
||||||
|| 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;
|
||||||
|
@ -487,7 +528,7 @@ internal static class Resources
|
||||||
config = directory + @"\cream_api.ini";
|
config = directory + @"\cream_api.ini";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string ComputeMD5(this string filePath)
|
private static string ComputeMD5(this string filePath)
|
||||||
{
|
{
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
return null;
|
return null;
|
||||||
|
@ -500,10 +541,9 @@ 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 { } hash && ResourceMD5s[identifier].Contains(hash);
|
||||||
|
|
||||||
internal static bool IsResourceFile(this string filePath)
|
internal static bool IsResourceFile(this string filePath) => filePath.ComputeMD5() is { } hash && ResourceMD5s.Values.Any(hashes => hashes.Contains(hash));
|
||||||
=> filePath.ComputeMD5() is string hash && ResourceMD5s.Values.Any(hashes => hashes.Contains(hash));
|
|
||||||
|
|
||||||
internal enum BinaryType
|
internal enum BinaryType
|
||||||
{
|
{
|
||||||
|
@ -518,4 +558,4 @@ internal static class Resources
|
||||||
EpicOnlineServices32, EpicOnlineServices64, Uplay32,
|
EpicOnlineServices32, EpicOnlineServices64, Uplay32,
|
||||||
Uplay64, Upc32, Upc64
|
Uplay64, Upc32, Upc64
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -50,7 +50,7 @@ internal static class ScreamAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideCatalogItems,
|
private static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideCatalogItems,
|
||||||
SortedList<string, (DlcType type, string name, string icon)> entitlements, InstallForm installForm = null)
|
SortedList<string, (DlcType type, string name, string icon)> entitlements, InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
|
@ -156,4 +156,4 @@ internal static class ScreamAPI
|
||||||
if (generateConfig)
|
if (generateConfig)
|
||||||
CheckConfig(directory, selection, installForm);
|
CheckConfig(directory, selection, installForm);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -12,19 +12,20 @@ namespace CreamInstaller.Resources;
|
||||||
internal static class SmokeAPI
|
internal static class SmokeAPI
|
||||||
{
|
{
|
||||||
internal static void GetSmokeApiComponents(this string directory, out string api32, out string api32_o, out string api64, out string api64_o,
|
internal static void GetSmokeApiComponents(this string directory, out string api32, out string api32_o, out string api64, out string api64_o,
|
||||||
out string config, out string cache)
|
out string old_config, 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";
|
||||||
api64 = directory + @"\steam_api64.dll";
|
api64 = directory + @"\steam_api64.dll";
|
||||||
api64_o = directory + @"\steam_api64_o.dll";
|
api64_o = directory + @"\steam_api64_o.dll";
|
||||||
config = directory + @"\SmokeAPI.json";
|
old_config = directory + @"\SmokeAPI.json";
|
||||||
|
config = directory + @"\SmokeAPI.config.json";
|
||||||
cache = directory + @"\SmokeAPI.cache.json";
|
cache = directory + @"\SmokeAPI.cache.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
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 old_config, out _, out _);
|
||||||
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
IEnumerable<KeyValuePair<string, (DlcType type, string name, string icon)>> overrideDlc = selection.AllDlc.Except(selection.SelectedDlc);
|
||||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
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);
|
||||||
|
@ -34,28 +35,28 @@ internal static class SmokeAPI
|
||||||
{
|
{
|
||||||
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 selection.ExtraSelectedDlc)
|
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||||
if (selection.ExtraDlc.Where(e => e.id == id).Single().dlc.Count > 64)
|
if (selection.ExtraDlc.Single(e => e.id == id).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));
|
||||||
}
|
}
|
||||||
if (overrideDlc.Any() || injectDlc.Any())
|
if (overrideDlc.Any() || injectDlc.Any())
|
||||||
{
|
{
|
||||||
/*if (installForm is not null)
|
/*if (installForm is not null)
|
||||||
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(old_config).Close();
|
||||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
StreamWriter writer = new(old_config, true, Encoding.UTF8);
|
||||||
WriteConfig(writer, new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
WriteConfig(writer, new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||||
new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
new(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(old_config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(old_config);
|
||||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(old_config)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideDlc,
|
private static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> overrideDlc,
|
||||||
SortedList<string, (DlcType type, string name, string icon)> injectDlc, InstallForm installForm = null)
|
SortedList<string, (DlcType type, string name, string icon)> injectDlc, InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
|
@ -107,7 +108,8 @@ internal static class SmokeAPI
|
||||||
File.Delete(oldConfig);
|
File.Delete(oldConfig);
|
||||||
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string cache);
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
|
||||||
|
out string config, out string cache);
|
||||||
if (File.Exists(api32_o))
|
if (File.Exists(api32_o))
|
||||||
{
|
{
|
||||||
if (File.Exists(api32))
|
if (File.Exists(api32))
|
||||||
|
@ -128,6 +130,11 @@ internal static class SmokeAPI
|
||||||
File.Move(api64_o, api64);
|
File.Move(api64_o, api64);
|
||||||
installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Restored Steamworks: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
|
if (deleteConfig && File.Exists(old_config))
|
||||||
|
{
|
||||||
|
File.Delete(old_config);
|
||||||
|
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(old_config)}", LogTextBox.Action, false);
|
||||||
|
}
|
||||||
if (deleteConfig && File.Exists(config))
|
if (deleteConfig && File.Exists(config))
|
||||||
{
|
{
|
||||||
File.Delete(config);
|
File.Delete(config);
|
||||||
|
@ -149,7 +156,7 @@ internal static class SmokeAPI
|
||||||
File.Delete(oldConfig);
|
File.Delete(oldConfig);
|
||||||
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, false);
|
installForm?.UpdateUser($"Deleted old CreamAPI configuration: {Path.GetFileName(oldConfig)}", LogTextBox.Action, false);
|
||||||
}
|
}
|
||||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out _);
|
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _, out _);
|
||||||
if (File.Exists(api32) && !File.Exists(api32_o))
|
if (File.Exists(api32) && !File.Exists(api32_o))
|
||||||
{
|
{
|
||||||
File.Move(api32, api32_o);
|
File.Move(api32, api32_o);
|
||||||
|
@ -173,4 +180,4 @@ internal static class SmokeAPI
|
||||||
if (generateConfig)
|
if (generateConfig)
|
||||||
CheckConfig(directory, selection, installForm);
|
CheckConfig(directory, selection, installForm);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -44,7 +44,7 @@ internal static class UplayR1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
private static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||||
InstallForm installForm = null)
|
InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
|
@ -127,4 +127,4 @@ internal static class UplayR1
|
||||||
if (generateConfig)
|
if (generateConfig)
|
||||||
CheckConfig(directory, selection, installForm);
|
CheckConfig(directory, selection, installForm);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -46,7 +46,7 @@ internal static class UplayR2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
private static void WriteConfig(StreamWriter writer, SortedList<string, (DlcType type, string name, string icon)> blacklistDlc,
|
||||||
InstallForm installForm = null)
|
InstallForm installForm = null)
|
||||||
{
|
{
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
|
@ -137,4 +137,4 @@ internal static class UplayR2
|
||||||
if (generateConfig)
|
if (generateConfig)
|
||||||
CheckConfig(directory, selection, installForm);
|
CheckConfig(directory, selection, installForm);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -43,4 +43,4 @@ internal static class Diagnostics
|
||||||
internal static void OpenUrlInInternetBrowser(string url) => Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
|
internal static void OpenUrlInInternetBrowser(string url) => Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
|
||||||
|
|
||||||
internal static string BeautifyPath(this string path) => path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path));
|
internal static string BeautifyPath(this string path) => path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path));
|
||||||
}
|
}
|
|
@ -65,4 +65,4 @@ public class CustomMessageException : Exception
|
||||||
public override string Message { get; }
|
public override string Message { get; }
|
||||||
|
|
||||||
public override string ToString() => Message;
|
public override string ToString() => Message;
|
||||||
}
|
}
|
|
@ -56,4 +56,4 @@ internal static class HttpClientManager
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Dispose() => HttpClient?.Dispose();
|
internal static void Dispose() => HttpClient?.Dispose();
|
||||||
}
|
}
|
|
@ -25,4 +25,4 @@ internal static class IconGrabber
|
||||||
internal static Image GetCommandPromptImage() => GetFileIconImage(Environment.SystemDirectory + @"\cmd.exe");
|
internal static Image GetCommandPromptImage() => GetFileIconImage(Environment.SystemDirectory + @"\cmd.exe");
|
||||||
|
|
||||||
internal static Image GetFileExplorerImage() => GetFileIconImage(Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\explorer.exe");
|
internal static Image GetFileExplorerImage() => GetFileIconImage(Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\explorer.exe");
|
||||||
}
|
}
|
|
@ -26,4 +26,4 @@ internal static class LogTextBox
|
||||||
textBox.SelectionColor = textBox.ForeColor;
|
textBox.SelectionColor = textBox.ForeColor;
|
||||||
textBox.Invalidate();
|
textBox.Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,21 +11,21 @@ namespace CreamInstaller.Utility;
|
||||||
|
|
||||||
internal static class ProgramData
|
internal static class ProgramData
|
||||||
{
|
{
|
||||||
internal static readonly string DirectoryPathOld = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller";
|
private static readonly string DirectoryPathOld = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller";
|
||||||
|
|
||||||
internal static readonly string DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\CreamInstaller";
|
internal static readonly string DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\CreamInstaller";
|
||||||
|
|
||||||
internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo";
|
internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo";
|
||||||
internal static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt";
|
private static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt";
|
||||||
|
|
||||||
internal static readonly Version MinimumAppInfoVersion = Version.Parse("3.2.0.0");
|
private static readonly Version MinimumAppInfoVersion = Version.Parse("3.2.0.0");
|
||||||
|
|
||||||
internal static readonly string CooldownPath = DirectoryPath + @"\cooldown";
|
internal static readonly string CooldownPath = DirectoryPath + @"\cooldown";
|
||||||
|
|
||||||
internal static readonly string OldProgramChoicesPath = DirectoryPath + @"\choices.txt";
|
private static readonly string OldProgramChoicesPath = DirectoryPath + @"\choices.txt";
|
||||||
internal static readonly string ProgramChoicesPath = DirectoryPath + @"\choices.json";
|
private static readonly string ProgramChoicesPath = DirectoryPath + @"\choices.json";
|
||||||
internal static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
private static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
||||||
internal static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.json";
|
private static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.json";
|
||||||
|
|
||||||
internal static async Task Setup()
|
internal static async Task Setup()
|
||||||
=> await Task.Run(() =>
|
=> await Task.Run(() =>
|
||||||
|
@ -64,16 +64,19 @@ internal static class ProgramData
|
||||||
|
|
||||||
private static DateTime? GetCooldown(string identifier)
|
private static DateTime? GetCooldown(string identifier)
|
||||||
{
|
{
|
||||||
if (Directory.Exists(CooldownPath))
|
if (!Directory.Exists(CooldownPath))
|
||||||
|
return null;
|
||||||
|
string cooldownFile = CooldownPath + @$"\{identifier}.txt";
|
||||||
|
if (!File.Exists(cooldownFile))
|
||||||
|
return null;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
string cooldownFile = CooldownPath + @$"\{identifier}.txt";
|
if (DateTime.TryParse(File.ReadAllText(cooldownFile), out DateTime cooldown))
|
||||||
if (File.Exists(cooldownFile))
|
return cooldown;
|
||||||
try
|
}
|
||||||
{
|
catch
|
||||||
if (DateTime.TryParse(File.ReadAllText(cooldownFile), out DateTime cooldown))
|
{
|
||||||
return cooldown;
|
// ignored
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -87,13 +90,16 @@ internal static class ProgramData
|
||||||
{
|
{
|
||||||
File.WriteAllText(cooldownFile, time.ToString(CultureInfo.InvariantCulture));
|
File.WriteAllText(cooldownFile, time.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<(Platform platform, string id)> ReadProgramChoices()
|
internal static IEnumerable<(Platform platform, string id)> ReadProgramChoices()
|
||||||
{
|
{
|
||||||
if (!File.Exists(ProgramChoicesPath))
|
if (!File.Exists(ProgramChoicesPath))
|
||||||
return null;
|
return Enumerable.Empty<(Platform platform, string id)>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath), typeof(List<(Platform platform, string id)>)) as
|
return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath), typeof(List<(Platform platform, string id)>)) as
|
||||||
|
@ -101,11 +107,11 @@ internal static class ProgramData
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return new();
|
return Enumerable.Empty<(Platform platform, string id)>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteProgramChoices(List<(Platform platform, string id)> choices)
|
internal static void WriteProgramChoices(IEnumerable<(Platform platform, string id)> choices)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -114,21 +120,24 @@ internal static class ProgramData
|
||||||
else
|
else
|
||||||
File.WriteAllText(ProgramChoicesPath, JsonConvert.SerializeObject(choices));
|
File.WriteAllText(ProgramChoicesPath, JsonConvert.SerializeObject(choices));
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<(Platform platform, string gameId, string dlcId)> ReadDlcChoices()
|
internal static IEnumerable<(Platform platform, string gameId, string dlcId)> ReadDlcChoices()
|
||||||
{
|
{
|
||||||
if (!File.Exists(DlcChoicesPath))
|
if (!File.Exists(DlcChoicesPath))
|
||||||
return null;
|
return Enumerable.Empty<(Platform platform, string gameId, string dlcId)>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath), typeof(List<(Platform platform, string gameId, string dlcId)>)) as
|
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath), typeof(IEnumerable<(Platform platform, string gameId, string dlcId)>)) as
|
||||||
List<(Platform platform, string gameId, string dlcId)>;
|
IEnumerable<(Platform platform, string gameId, string dlcId)>;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return new();
|
return Enumerable.Empty<(Platform platform, string gameId, string dlcId)>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,25 +150,29 @@ internal static class ProgramData
|
||||||
else
|
else
|
||||||
File.WriteAllText(DlcChoicesPath, JsonConvert.SerializeObject(choices));
|
File.WriteAllText(DlcChoicesPath, JsonConvert.SerializeObject(choices));
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<(Platform platform, string id, string proxy, bool enabled)> ReadKoaloaderChoices()
|
internal static IEnumerable<(Platform platform, string id, string proxy, bool enabled)> ReadKoaloaderChoices()
|
||||||
{
|
{
|
||||||
if (!File.Exists(KoaloaderProxyChoicesPath))
|
if (!File.Exists(KoaloaderProxyChoicesPath))
|
||||||
return null;
|
return null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject(File.ReadAllText(KoaloaderProxyChoicesPath),
|
return JsonConvert.DeserializeObject(File.ReadAllText(KoaloaderProxyChoicesPath),
|
||||||
typeof(List<(Platform platform, string id, string proxy, bool enabled)>)) as List<(Platform platform, string id, string proxy, bool enabled)>;
|
typeof(IEnumerable<(Platform platform, string id, string proxy, bool enabled)>)) as
|
||||||
|
IEnumerable<(Platform platform, string id, string proxy, bool enabled)>;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return new();
|
return Enumerable.Empty<(Platform platform, string id, string proxy, bool enabled)>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void WriteKoaloaderProxyChoices(List<(Platform platform, string id, string proxy, bool enabled)> choices)
|
internal static void WriteKoaloaderProxyChoices(IEnumerable<(Platform platform, string id, string proxy, bool enabled)> choices)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -168,6 +181,9 @@ internal static class ProgramData
|
||||||
else
|
else
|
||||||
File.WriteAllText(KoaloaderProxyChoicesPath, JsonConvert.SerializeObject(choices));
|
File.WriteAllText(KoaloaderProxyChoicesPath, JsonConvert.SerializeObject(choices));
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue