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;
|
||||
|
||||
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)
|
||||
{
|
||||
Text = text;
|
||||
OnClickEvent = onClick;
|
||||
onClickEvent = 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) :
|
||||
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,
|
||||
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)
|
||||
=> 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;
|
||||
else
|
||||
{
|
||||
|
@ -84,7 +90,7 @@ internal class ContextMenuItem : ToolStripMenuItem
|
|||
}
|
||||
if (image is not null)
|
||||
{
|
||||
images[imageIdentifier] = image;
|
||||
Images[imageIdentifier] = image;
|
||||
item.Image = image;
|
||||
}
|
||||
}
|
||||
|
@ -95,26 +101,24 @@ internal class ContextMenuItem : ToolStripMenuItem
|
|||
{
|
||||
(string id, string iconUrl) = imageIdentifierInfo;
|
||||
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;
|
||||
else
|
||||
{
|
||||
image = await HttpClientManager.GetImageFromUrl(iconUrl);
|
||||
if (image is not null)
|
||||
{
|
||||
images[imageIdentifier] = image;
|
||||
Images[imageIdentifier] = image;
|
||||
item.Image = image;
|
||||
}
|
||||
else if (onFail is not null)
|
||||
onFail();
|
||||
else
|
||||
onFail?.Invoke();
|
||||
}
|
||||
});
|
||||
|
||||
protected override void OnClick(EventArgs e)
|
||||
{
|
||||
base.OnClick(e);
|
||||
if (OnClickEvent is null)
|
||||
return;
|
||||
OnClickEvent.Invoke(this, e);
|
||||
onClickEvent?.Invoke(this, e);
|
||||
}
|
||||
}
|
|
@ -11,9 +11,9 @@ using static CreamInstaller.Resources.Resources;
|
|||
|
||||
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> comboBoxBounds = new();
|
||||
|
||||
|
@ -34,7 +34,7 @@ internal class CustomTreeView : TreeView
|
|||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (m.Msg == 0x203)
|
||||
m.Result = IntPtr.Zero;
|
||||
m.Result = nint.Zero;
|
||||
else
|
||||
base.WndProc(ref m);
|
||||
form = FindForm();
|
||||
|
@ -54,11 +54,11 @@ internal class CustomTreeView : TreeView
|
|||
{
|
||||
e.DrawDefault = true;
|
||||
TreeNode node = e.Node;
|
||||
if (!node.IsVisible)
|
||||
if (node is not { IsVisible: true })
|
||||
return;
|
||||
bool highlighted = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected && Focused;
|
||||
Graphics graphics = e.Graphics;
|
||||
backBrush ??= new SolidBrush(BackColor);
|
||||
backBrush ??= new(BackColor);
|
||||
Font font = node.NodeFont ?? Font;
|
||||
Brush brush = highlighted ? SystemBrushes.Highlight : backBrush;
|
||||
string text; // = e.Node.Text;
|
||||
|
@ -87,9 +87,9 @@ internal class CustomTreeView : TreeView
|
|||
text = platform.ToString();
|
||||
size = TextRenderer.MeasureText(graphics, text, font);
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
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);
|
||||
if (platform is not Platform.Paradox)
|
||||
{
|
||||
|
@ -100,11 +100,11 @@ internal class CustomTreeView : TreeView
|
|||
: ColorTranslator.FromHtml("#69AAAA");
|
||||
text = platformId;
|
||||
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 };
|
||||
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);
|
||||
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);
|
||||
}
|
||||
/*if (highlighted)
|
||||
|
@ -116,7 +116,7 @@ internal class CustomTreeView : TreeView
|
|||
{
|
||||
if (bounds == node.Bounds)
|
||||
{
|
||||
size = new Size(4, 0);
|
||||
size = new(4, 0);
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||
graphics.FillRectangle(brush, bounds);
|
||||
}
|
||||
|
@ -127,49 +127,47 @@ internal class CustomTreeView : TreeView
|
|||
: CheckBoxState.UncheckedDisabled;
|
||||
size = CheckBoxRenderer.GetGlyphSize(graphics, checkBoxState);
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
Rectangle checkBoxBounds = bounds;
|
||||
graphics.FillRectangle(backBrush, bounds);
|
||||
point = new Point(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1);
|
||||
point = new(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1);
|
||||
CheckBoxRenderer.DrawCheckBox(graphics, point, checkBoxState);
|
||||
text = koaloaderToggleString;
|
||||
text = KoaloaderToggleString;
|
||||
size = TextRenderer.MeasureText(graphics, text, font);
|
||||
int left = 1;
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width + left };
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
checkBoxBounds = new Rectangle(checkBoxBounds.Location, checkBoxBounds.Size + bounds.Size with { Height = 0 });
|
||||
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
checkBoxBounds = new(checkBoxBounds.Location, checkBoxBounds.Size + bounds.Size with { Height = 0 });
|
||||
graphics.FillRectangle(backBrush, bounds);
|
||||
point = new Point(bounds.Location.X - 1 + left, bounds.Location.Y + 1);
|
||||
point = new(bounds.Location.X - 1 + left, bounds.Location.Y + 1);
|
||||
TextRenderer.DrawText(graphics, text, font, point, Enabled ? ColorTranslator.FromHtml("#006900") : ColorTranslator.FromHtml("#69AA69"),
|
||||
TextFormatFlags.Default);
|
||||
this.checkBoxBounds[selection] = RectangleToClient(checkBoxBounds);
|
||||
string proxy = selection.KoaloaderProxy ?? ProgramSelection.DefaultKoaloaderProxy;
|
||||
if (selection.Koaloader && proxy is not null)
|
||||
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;
|
||||
text = proxy + ".dll";
|
||||
size = TextRenderer.MeasureText(graphics, text, comboBoxFont) + new Size(6, 0);
|
||||
int padding = 2;
|
||||
bounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding);
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
const int padding = 2;
|
||||
bounds = new(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding);
|
||||
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
Rectangle comboBoxBounds = bounds;
|
||||
graphics.FillRectangle(backBrush, bounds);
|
||||
ComboBoxRenderer.DrawTextBox(graphics, bounds, text, comboBoxFont, comboBoxState);
|
||||
size = new Size(14, 0);
|
||||
size = new(14, 0);
|
||||
left = -1;
|
||||
bounds = bounds with { X = bounds.X + bounds.Width + left, Width = size.Width };
|
||||
selectionBounds = new Rectangle(selectionBounds.Location, selectionBounds.Size + new Size(bounds.Size.Width + left, 0));
|
||||
comboBoxBounds = new Rectangle(comboBoxBounds.Location, comboBoxBounds.Size + new Size(bounds.Size.Width + left, 0));
|
||||
selectionBounds = new(selectionBounds.Location, selectionBounds.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);
|
||||
this.comboBoxBounds[selection] = RectangleToClient(comboBoxBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = comboBoxBounds.Remove(selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.selectionBounds[node] = RectangleToClient(selectionBounds);
|
||||
}
|
||||
|
||||
|
@ -179,11 +177,9 @@ internal class CustomTreeView : TreeView
|
|||
Refresh();
|
||||
Point clickPoint = PointToClient(e.Location);
|
||||
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)
|
||||
{
|
||||
_ = selectionBounds.Remove(pair.Key);
|
||||
}
|
||||
else if (pair.Key.IsVisible && pair.Value.Contains(clickPoint))
|
||||
{
|
||||
SelectedNode = pair.Key;
|
||||
|
@ -191,14 +187,12 @@ internal class CustomTreeView : TreeView
|
|||
selectForm.OnNodeRightClick(pair.Key, e.Location);
|
||||
break;
|
||||
}
|
||||
if (e.Button is MouseButtons.Left)
|
||||
{
|
||||
if (e.Button is not MouseButtons.Left)
|
||||
return;
|
||||
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 =>
|
||||
|
@ -206,7 +200,7 @@ internal class CustomTreeView : TreeView
|
|||
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
|
||||
return proxyName;
|
||||
}).Distinct().ToList();
|
||||
comboBoxDropDown ??= new ToolStripDropDown();
|
||||
comboBoxDropDown ??= new();
|
||||
comboBoxDropDown.ShowItemToolTips = false;
|
||||
comboBoxDropDown.Items.Clear();
|
||||
foreach (string proxy in proxies)
|
||||
|
@ -215,12 +209,11 @@ internal class CustomTreeView : TreeView
|
|||
foreach ((string directory, BinaryType binaryType) in pair.Key.ExecutableDirectories)
|
||||
{
|
||||
string path = directory + @"\" + proxy + ".dll";
|
||||
if (File.Exists(path) && !path.IsResourceFile(ResourceIdentifier.Koaloader))
|
||||
{
|
||||
if (!File.Exists(path) || path.IsResourceFile(ResourceIdentifier.Koaloader))
|
||||
continue;
|
||||
canUse = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (canUse)
|
||||
_ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (s, e) =>
|
||||
{
|
||||
|
@ -228,20 +221,17 @@ internal class CustomTreeView : TreeView
|
|||
selectForm.OnKoaloaderChanged();
|
||||
}) { Font = comboBoxFont });
|
||||
}
|
||||
comboBoxDropDown.Show(this, PointToScreen(new Point(pair.Value.Left, pair.Value.Bottom - 1)));
|
||||
comboBoxDropDown.Show(this, PointToScreen(new(pair.Value.Left, pair.Value.Bottom - 1)));
|
||||
break;
|
||||
}
|
||||
foreach (KeyValuePair<ProgramSelection, Rectangle> pair in checkBoxBounds.ToList())
|
||||
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();
|
||||
selectForm?.OnKoaloaderChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ internal static class PlatformIdComparer
|
|||
internal static NodeTextComparer NodeText => nodeTextComparer ??= new();
|
||||
}
|
||||
|
||||
internal class StringComparer : IComparer<string>
|
||||
internal sealed class StringComparer : IComparer<string>
|
||||
{
|
||||
public int Compare(string a, string b)
|
||||
=> !int.TryParse(a, out _) && !int.TryParse(b, out _)
|
||||
|
@ -36,7 +36,7 @@ internal class StringComparer : IComparer<string>
|
|||
: 0;
|
||||
}
|
||||
|
||||
internal class NodeComparer : IComparer<TreeNode>
|
||||
internal sealed class NodeComparer : IComparer<TreeNode>
|
||||
{
|
||||
public int Compare(TreeNode a, TreeNode b)
|
||||
=> a.Tag is not Platform A
|
||||
|
@ -50,7 +50,7 @@ internal class NodeComparer : IComparer<TreeNode>
|
|||
: 0;
|
||||
}
|
||||
|
||||
internal class NodeNameComparer : IComparer
|
||||
internal sealed class NodeNameComparer : IComparer
|
||||
{
|
||||
public int Compare(object a, object b)
|
||||
=> a is not TreeNode A
|
||||
|
@ -62,7 +62,7 @@ internal class NodeNameComparer : IComparer
|
|||
: PlatformIdComparer.String.Compare(A.Name, B.Name);
|
||||
}
|
||||
|
||||
internal class NodeTextComparer : IComparer
|
||||
internal sealed class NodeTextComparer : IComparer
|
||||
{
|
||||
public int Compare(object a, object b)
|
||||
=> a is not TreeNode A
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<UseWindowsForms>True</UseWindowsForms>
|
||||
<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>
|
||||
<Company>CreamInstaller</Company>
|
||||
<Product>Automatic DLC Unlocker Installer & Configuration Generator</Product>
|
||||
|
@ -19,6 +19,7 @@
|
|||
<DebugType>embedded</DebugType>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>$(DefineConstants)</DefineConstants>
|
||||
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<AssemblyName>$(Company)</AssemblyName>
|
||||
|
|
|
@ -6,13 +6,13 @@ using CreamInstaller.Utility;
|
|||
|
||||
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;
|
||||
|
||||
internal DebugForm()
|
||||
private DebugForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
debugTextBox.BackColor = LogTextBox.Background;
|
||||
|
@ -26,7 +26,6 @@ internal partial class DebugForm : CustomForm
|
|||
current = null;
|
||||
return current ??= new();
|
||||
}
|
||||
set => current = value;
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message message) // make form immovable by user
|
||||
|
@ -57,17 +56,16 @@ internal partial class DebugForm : CustomForm
|
|||
UpdateAttachment();
|
||||
}
|
||||
|
||||
internal void OnChange(object sender, EventArgs args) => UpdateAttachment();
|
||||
private void OnChange(object sender, EventArgs args) => UpdateAttachment();
|
||||
|
||||
internal void UpdateAttachment()
|
||||
{
|
||||
if (attachedForm is not null && attachedForm.Visible)
|
||||
private void UpdateAttachment()
|
||||
{
|
||||
if (attachedForm is null || !attachedForm.Visible)
|
||||
return;
|
||||
//Size = new(Size.Width, attachedForm.Size.Height);
|
||||
Location = new(attachedForm.Right, attachedForm.Top);
|
||||
BringToFrontWithoutActivation();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Log(string text) => Log(text, LogTextBox.Error);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ using CreamInstaller.Components;
|
|||
|
||||
namespace CreamInstaller.Forms;
|
||||
|
||||
internal partial class DialogForm : CustomForm
|
||||
internal sealed partial class DialogForm : CustomForm
|
||||
{
|
||||
internal DialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
||||
|
||||
|
@ -16,7 +16,7 @@ internal partial class DialogForm : CustomForm
|
|||
string customFormText = null, Icon customFormIcon = null)
|
||||
{
|
||||
descriptionIcon ??= Icon;
|
||||
icon.Image = descriptionIcon.ToBitmap();
|
||||
icon.Image = descriptionIcon?.ToBitmap();
|
||||
List<LinkLabel.Link> links = new();
|
||||
for (int i = 0; i < descriptionText.Length; i++)
|
||||
if (descriptionText[i] == '[')
|
||||
|
@ -25,8 +25,8 @@ internal partial class DialogForm : CustomForm
|
|||
int textRight = descriptionText.IndexOf("]", textLeft == -1 ? i : textLeft, StringComparison.Ordinal);
|
||||
int linkLeft = descriptionText.IndexOf("(", textRight == -1 ? i : textRight, StringComparison.Ordinal);
|
||||
int linkRight = descriptionText.IndexOf(")", linkLeft == -1 ? i : linkLeft, StringComparison.Ordinal);
|
||||
if (textLeft != -1 && textRight == linkLeft - 1 && linkRight != -1)
|
||||
{
|
||||
if (textLeft == -1 || textRight != linkLeft - 1 || linkRight == -1)
|
||||
continue;
|
||||
string text = descriptionText[(textLeft + 1)..textRight];
|
||||
string link = descriptionText[(linkLeft + 1)..linkRight];
|
||||
if (string.IsNullOrWhiteSpace(link))
|
||||
|
@ -34,7 +34,6 @@ internal partial class DialogForm : CustomForm
|
|||
descriptionText = descriptionText.Remove(i, linkRight + 1 - i).Insert(i, text);
|
||||
links.Add(new(i, text.Length, link));
|
||||
}
|
||||
}
|
||||
descriptionLabel.Text = descriptionText;
|
||||
acceptButton.Text = acceptButtonText;
|
||||
if (cancelButtonText is null)
|
||||
|
@ -53,12 +52,11 @@ internal partial class DialogForm : CustomForm
|
|||
}
|
||||
if (customFormIcon is not null)
|
||||
Icon = customFormIcon;
|
||||
if (links.Any())
|
||||
{
|
||||
if (!links.Any())
|
||||
return ShowDialog();
|
||||
foreach (LinkLabel.Link link in links)
|
||||
_ = descriptionLabel.Links.Add(link);
|
||||
descriptionLabel.LinkClicked += (s, e) => Process.Start(new ProcessStartInfo((string)e.Link.LinkData) { UseShellExecute = true });
|
||||
}
|
||||
return ShowDialog();
|
||||
}
|
||||
|
||||
|
|
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
|
||||
{
|
||||
partial class InstallForm
|
||||
sealed partial class InstallForm
|
||||
{
|
||||
private IContainer components = null;
|
||||
protected override void Dispose(bool disposing)
|
||||
|
|
|
@ -13,15 +13,15 @@ using static CreamInstaller.Resources.Resources;
|
|||
|
||||
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;
|
||||
internal readonly bool Uninstalling;
|
||||
private int CompleteOperationsCount;
|
||||
private readonly int programCount = ProgramSelection.AllEnabled.Count;
|
||||
private readonly bool uninstalling;
|
||||
private int completeOperationsCount;
|
||||
|
||||
private int OperationsCount;
|
||||
private int operationsCount;
|
||||
internal bool Reselecting;
|
||||
|
||||
internal InstallForm(bool uninstall = false)
|
||||
|
@ -29,15 +29,15 @@ internal partial class InstallForm : CustomForm
|
|||
InitializeComponent();
|
||||
Text = Program.ApplicationName;
|
||||
logTextBox.BackColor = LogTextBox.Background;
|
||||
Uninstalling = uninstall;
|
||||
uninstalling = uninstall;
|
||||
}
|
||||
|
||||
internal void UpdateProgress(int progress)
|
||||
private void UpdateProgress(int progress)
|
||||
{
|
||||
if (!userProgressBar.Disposing && !userProgressBar.IsDisposed)
|
||||
userProgressBar.Invoke(() =>
|
||||
{
|
||||
int value = (int)((float)CompleteOperationsCount / OperationsCount * 100) + progress / OperationsCount;
|
||||
int value = (int)((float)completeOperationsCount / operationsCount * 100) + progress / operationsCount;
|
||||
if (value < userProgressBar.Value)
|
||||
return;
|
||||
userProgressBar.Value = value;
|
||||
|
@ -67,12 +67,12 @@ internal partial class InstallForm : CustomForm
|
|||
_ = await Repair(this, selection);
|
||||
}
|
||||
UpdateUser(
|
||||
$"{(Uninstalling ? "Uninstalling" : "Installing")}" + $" {(Uninstalling ? "from" : "for")} " + selection.Name
|
||||
$"{(uninstalling ? "Uninstalling" : "Installing")}" + $" {(uninstalling ? "from" : "for")} " + selection.Name
|
||||
+ $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation);
|
||||
IEnumerable<string> invalidDirectories = (await selection.RootDirectory.GetExecutables())
|
||||
?.Where(d => !selection.ExecutableDirectories.Any(s => s.directory == Path.GetDirectoryName(d.path)))
|
||||
?.Where(d => selection.ExecutableDirectories.All(s => s.directory != 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?.Distinct();
|
||||
if (invalidDirectories is not null)
|
||||
|
@ -80,30 +80,31 @@ internal partial class InstallForm : CustomForm
|
|||
{
|
||||
if (Program.Canceled)
|
||||
throw new CustomMessageException("The operation was canceled.");
|
||||
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
|
||||
directory.GetKoaloaderComponents(out List<string> proxies, out string old_config, out string config);
|
||||
if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|
||||
|| directory != selection.RootDirectory && Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) || File.Exists(config))
|
||||
|| directory != selection.RootDirectory && Koaloader.AutoLoadDLLs.Any(pair => File.Exists(directory + @"\" + pair.dll))
|
||||
|| File.Exists(old_config) || File.Exists(config))
|
||||
{
|
||||
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
|
||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||
}
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
if (Uninstalling || !selection.Koaloader)
|
||||
if (uninstalling || !selection.Koaloader)
|
||||
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
|
||||
{
|
||||
if (Program.Canceled)
|
||||
throw new CustomMessageException("The operation was canceled.");
|
||||
directory.GetKoaloaderComponents(out List<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))
|
||||
|| 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);
|
||||
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
|
||||
}
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
bool uninstallProxy = Uninstalling || selection.Koaloader;
|
||||
bool uninstallProxy = uninstalling || selection.Koaloader;
|
||||
int count = selection.DllDirectories.Count, cur = 0;
|
||||
foreach (string directory in selection.DllDirectories)
|
||||
{
|
||||
|
@ -111,10 +112,10 @@ internal partial class InstallForm : CustomForm
|
|||
throw new CustomMessageException("The operation was canceled.");
|
||||
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
||||
{
|
||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
|
||||
out string cache);
|
||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
|
||||
out string config, out string cache);
|
||||
if (uninstallProxy
|
||||
? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)
|
||||
? File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(old_config) || File.Exists(config) || File.Exists(cache)
|
||||
: File.Exists(api32) || File.Exists(api64))
|
||||
{
|
||||
UpdateUser(
|
||||
|
@ -170,7 +171,7 @@ internal partial class InstallForm : CustomForm
|
|||
UpdateProgress(++cur / count * 100);
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
if (selection.Koaloader && !Uninstalling)
|
||||
if (selection.Koaloader && !uninstalling)
|
||||
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
|
||||
{
|
||||
if (Program.Canceled)
|
||||
|
@ -185,8 +186,8 @@ internal partial class InstallForm : CustomForm
|
|||
private async Task Operate()
|
||||
{
|
||||
List<ProgramSelection> programSelections = ProgramSelection.AllEnabled;
|
||||
OperationsCount = programSelections.Count;
|
||||
CompleteOperationsCount = 0;
|
||||
operationsCount = programSelections.Count;
|
||||
completeOperationsCount = 0;
|
||||
foreach (ProgramSelection selection in programSelections)
|
||||
{
|
||||
if (Program.Canceled || !Program.IsProgramRunningDialog(this, selection))
|
||||
|
@ -196,24 +197,24 @@ internal partial class InstallForm : CustomForm
|
|||
await OperateFor(selection);
|
||||
UpdateUser($"Operation succeeded for {selection.Name}.", LogTextBox.Success);
|
||||
selection.Enabled = false;
|
||||
DisabledSelections.Add(selection);
|
||||
disabledSelections.Add(selection);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
UpdateUser($"Operation failed for {selection.Name}: " + exception, LogTextBox.Error);
|
||||
}
|
||||
++CompleteOperationsCount;
|
||||
++completeOperationsCount;
|
||||
}
|
||||
Program.Cleanup();
|
||||
List<ProgramSelection> FailedSelections = ProgramSelection.AllEnabled;
|
||||
if (FailedSelections.Any())
|
||||
if (FailedSelections.Count == 1)
|
||||
throw new CustomMessageException($"Operation failed for {FailedSelections.First().Name}.");
|
||||
List<ProgramSelection> failedSelections = ProgramSelection.AllEnabled;
|
||||
if (failedSelections.Any())
|
||||
if (failedSelections.Count == 1)
|
||||
throw new CustomMessageException($"Operation failed for {failedSelections.First().Name}.");
|
||||
else
|
||||
throw new CustomMessageException($"Operation failed for {FailedSelections.Count} programs.");
|
||||
foreach (ProgramSelection selection in DisabledSelections)
|
||||
throw new CustomMessageException($"Operation failed for {failedSelections.Count} programs.");
|
||||
foreach (ProgramSelection selection in disabledSelections)
|
||||
selection.Enabled = true;
|
||||
DisabledSelections.Clear();
|
||||
disabledSelections.Clear();
|
||||
}
|
||||
|
||||
private async void Start()
|
||||
|
@ -227,12 +228,12 @@ internal partial class InstallForm : CustomForm
|
|||
try
|
||||
{
|
||||
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);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
UpdateUser($"DLC unlocker {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception, LogTextBox.Error);
|
||||
UpdateUser($"DLC unlocker {(uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception, LogTextBox.Error);
|
||||
retryButton.Enabled = true;
|
||||
}
|
||||
userProgressBar.Value = userProgressBar.Maximum;
|
||||
|
@ -276,9 +277,9 @@ internal partial class InstallForm : CustomForm
|
|||
{
|
||||
Program.Cleanup();
|
||||
Reselecting = true;
|
||||
foreach (ProgramSelection selection in DisabledSelections)
|
||||
foreach (ProgramSelection selection in disabledSelections)
|
||||
selection.Enabled = true;
|
||||
DisabledSelections.Clear();
|
||||
disabledSelections.Clear();
|
||||
Close();
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ using Onova.Services;
|
|||
|
||||
namespace CreamInstaller.Forms;
|
||||
|
||||
internal partial class MainForm : CustomForm
|
||||
internal sealed partial class MainForm : CustomForm
|
||||
{
|
||||
private CancellationTokenSource cancellationTokenSource;
|
||||
private Version latestVersion;
|
||||
|
@ -68,11 +68,10 @@ internal partial class MainForm : CustomForm
|
|||
updateManager = new(AssemblyMetadata.FromAssembly(Program.EntryAssembly, Program.CurrentProcessFilePath), resolver, extractor);
|
||||
if (latestVersion is null)
|
||||
{
|
||||
CheckForUpdatesResult checkForUpdatesResult = null;
|
||||
cancellationTokenSource = new();
|
||||
try
|
||||
{
|
||||
checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token);
|
||||
CheckForUpdatesResult checkForUpdatesResult = await updateManager.CheckForUpdatesAsync(cancellationTokenSource.Token);
|
||||
#if !DEBUG
|
||||
if (checkForUpdatesResult.CanUpdate)
|
||||
{
|
||||
|
@ -133,7 +132,7 @@ internal partial class MainForm : CustomForm
|
|||
foreach (HtmlNode node in nodes)
|
||||
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.Expand();
|
||||
if (changelogTreeView.Nodes.Count > 0)
|
||||
|
@ -149,8 +148,8 @@ internal partial class MainForm : CustomForm
|
|||
retry:
|
||||
try
|
||||
{
|
||||
string FileName = Path.GetFileName(Program.CurrentProcessFilePath);
|
||||
if (FileName != Program.ApplicationExecutable)
|
||||
string fileName = Path.GetFileName(Program.CurrentProcessFilePath);
|
||||
if (fileName != Program.ApplicationExecutable)
|
||||
{
|
||||
using DialogForm form = new(this);
|
||||
if (form.Show(SystemIcons.Warning,
|
||||
|
|
|
@ -7,7 +7,7 @@ using CreamInstaller.Utility;
|
|||
|
||||
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();
|
||||
internal SelectDialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
||||
|
@ -69,9 +69,7 @@ internal partial class SelectDialogForm : CustomForm
|
|||
|
||||
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
||||
{
|
||||
bool shouldCheck = false;
|
||||
if (selectionTreeView.Nodes.Cast<TreeNode>().Any(n => !n.Checked))
|
||||
shouldCheck = true;
|
||||
bool shouldCheck = selectionTreeView.Nodes.Cast<TreeNode>().Any(n => !n.Checked);
|
||||
foreach (TreeNode node in selectionTreeView.Nodes)
|
||||
{
|
||||
node.Checked = shouldCheck;
|
||||
|
@ -84,8 +82,8 @@ internal partial class SelectDialogForm : CustomForm
|
|||
|
||||
private void OnLoad(object sender, EventArgs e)
|
||||
{
|
||||
List<(Platform platform, string id)> choices = ProgramData.ReadProgramChoices();
|
||||
if (choices is null)
|
||||
List<(Platform platform, string id)> choices = ProgramData.ReadProgramChoices().ToList();
|
||||
if (!choices.Any())
|
||||
return;
|
||||
foreach (TreeNode node in selectionTreeView.Nodes)
|
||||
{
|
||||
|
@ -96,10 +94,7 @@ internal partial class SelectDialogForm : CustomForm
|
|||
|
||||
private void OnSave(object sender, EventArgs e)
|
||||
{
|
||||
List<(Platform platform, string id)> choices = new();
|
||||
foreach (TreeNode node in selectionTreeView.Nodes.Cast<TreeNode>().Where(n => n.Checked))
|
||||
choices.Add(((Platform)node.Tag, node.Name));
|
||||
ProgramData.WriteProgramChoices(choices);
|
||||
ProgramData.WriteProgramChoices(selectionTreeView.Nodes.Cast<TreeNode>().Where(n => n.Checked).Select(node => ((Platform)node.Tag, node.Name)));
|
||||
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.Generic;
|
||||
using System.Drawing;
|
||||
|
@ -22,15 +20,15 @@ using static CreamInstaller.Resources.Resources;
|
|||
|
||||
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()
|
||||
{
|
||||
|
@ -40,12 +38,12 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
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)
|
||||
=> 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)
|
||||
{
|
||||
|
@ -55,8 +53,8 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
if (!RemainingGames.Contains(gameName))
|
||||
RemainingGames.Add(gameName);
|
||||
if (!remainingGames.Contains(gameName))
|
||||
remainingGames.Add(gameName);
|
||||
UpdateRemainingGames();
|
||||
});
|
||||
}
|
||||
|
@ -69,12 +67,12 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
RemainingGames.Remove(gameName);
|
||||
remainingGames.Remove(gameName);
|
||||
UpdateRemainingGames();
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateRemainingDLCs() => UpdateRemaining(progressLabelDLCs, RemainingDLCs, "DLCs");
|
||||
private void UpdateRemainingDLCs() => UpdateRemaining(progressLabelDLCs, remainingDLCs, "DLCs");
|
||||
|
||||
private void AddToRemainingDLCs(string dlcId)
|
||||
{
|
||||
|
@ -84,8 +82,8 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
if (!RemainingDLCs.Contains(dlcId))
|
||||
RemainingDLCs.Add(dlcId);
|
||||
if (!remainingDLCs.Contains(dlcId))
|
||||
remainingDLCs.Add(dlcId);
|
||||
UpdateRemainingDLCs();
|
||||
});
|
||||
}
|
||||
|
@ -98,35 +96,35 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
RemainingDLCs.Remove(dlcId);
|
||||
remainingDLCs.Remove(dlcId);
|
||||
UpdateRemainingDLCs();
|
||||
});
|
||||
}
|
||||
|
||||
private async Task GetApplicablePrograms(IProgress<int> progress)
|
||||
{
|
||||
if (ProgramsToScan is null || !ProgramsToScan.Any())
|
||||
if (programsToScan is null || !programsToScan.Any())
|
||||
return;
|
||||
int TotalGameCount = 0;
|
||||
int CompleteGameCount = 0;
|
||||
int totalGameCount = 0;
|
||||
int completeGameCount = 0;
|
||||
void AddToRemainingGames(string gameName)
|
||||
{
|
||||
this.AddToRemainingGames(gameName);
|
||||
progress.Report(-Interlocked.Increment(ref TotalGameCount));
|
||||
progress.Report(CompleteGameCount);
|
||||
progress.Report(-Interlocked.Increment(ref totalGameCount));
|
||||
progress.Report(completeGameCount);
|
||||
}
|
||||
void RemoveFromRemainingGames(string gameName)
|
||||
{
|
||||
this.RemoveFromRemainingGames(gameName);
|
||||
progress.Report(Interlocked.Increment(ref CompleteGameCount));
|
||||
progress.Report(Interlocked.Increment(ref completeGameCount));
|
||||
}
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
List<TreeNode> treeNodes = TreeNodes;
|
||||
RemainingGames.Clear(); // for display purposes only, otherwise ignorable
|
||||
RemainingDLCs.Clear(); // for display purposes only, otherwise ignorable
|
||||
remainingGames.Clear(); // for display purposes only, otherwise ignorable
|
||||
remainingDLCs.Clear(); // for display purposes only, otherwise ignorable
|
||||
List<Task> appTasks = new();
|
||||
if (ProgramsToScan.Any(c => c.platform is Platform.Paradox))
|
||||
if (programsToScan.Any(c => c.platform is Platform.Paradox))
|
||||
{
|
||||
List<string> dllDirectories = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox);
|
||||
if (dllDirectories is not null)
|
||||
|
@ -153,7 +151,7 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
}
|
||||
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();
|
||||
steamGamesToCheck = steamGames.Count;
|
||||
|
@ -161,7 +159,7 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Steam && c.id == appId))
|
||||
if (Program.IsGameBlocked(name, gameDirectory) || !programsToScan.Any(c => c.platform is Platform.Steam && c.id == appId))
|
||||
{
|
||||
Interlocked.Decrement(ref steamGamesToCheck);
|
||||
continue;
|
||||
|
@ -287,7 +285,7 @@ internal partial class SelectForm : CustomForm
|
|||
_ = selectionTreeView.Nodes.Add(programNode);
|
||||
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in dlc)
|
||||
{
|
||||
if (Program.Canceled || programNode is null)
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
string appId = pair.Key;
|
||||
(DlcType type, string name, string icon) dlcApp = pair.Value;
|
||||
|
@ -310,7 +308,7 @@ internal partial class SelectForm : CustomForm
|
|||
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();
|
||||
foreach (Manifest manifest in epicGames)
|
||||
|
@ -320,7 +318,7 @@ internal partial class SelectForm : CustomForm
|
|||
string directory = manifest.InstallLocation;
|
||||
if (Program.Canceled)
|
||||
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;
|
||||
AddToRemainingGames(name);
|
||||
Task task = Task.Run(async () =>
|
||||
|
@ -437,14 +435,14 @@ internal partial class SelectForm : CustomForm
|
|||
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();
|
||||
foreach ((string gameId, string name, string gameDirectory) in ubisoftGames)
|
||||
{
|
||||
if (Program.Canceled)
|
||||
return;
|
||||
if (Program.IsGameBlocked(name, gameDirectory) || !ProgramsToScan.Any(c => c.platform is Platform.Ubisoft && c.id == gameId))
|
||||
if (Program.IsGameBlocked(name, gameDirectory) || !programsToScan.Any(c => c.platform is Platform.Ubisoft && c.id == gameId))
|
||||
continue;
|
||||
AddToRemainingGames(name);
|
||||
Task task = Task.Run(async () =>
|
||||
|
@ -521,34 +519,34 @@ internal partial class SelectForm : CustomForm
|
|||
ShowProgressBar();
|
||||
await ProgramData.Setup();
|
||||
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();
|
||||
if (Directory.Exists(ParadoxLauncher.InstallPath))
|
||||
gameChoices.Add((Platform.Paradox, "PL", "Paradox Launcher",
|
||||
ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL")));
|
||||
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL")));
|
||||
if (Directory.Exists(SteamLibrary.InstallPath))
|
||||
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in (await SteamLibrary.GetGames()).Where(g
|
||||
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
|
||||
gameChoices.Add((Platform.Steam, appId, name,
|
||||
ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Steam && p.id == appId)));
|
||||
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Steam && p.id == appId)));
|
||||
if (Directory.Exists(EpicLibrary.EpicManifestsPath))
|
||||
foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation)))
|
||||
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
|
||||
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
|
||||
gameChoices.Add((Platform.Ubisoft, gameId, name,
|
||||
ProgramsToScan is not null && ProgramsToScan.Any(p => p.platform is Platform.Ubisoft && p.id == gameId)));
|
||||
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Ubisoft && p.id == gameId)));
|
||||
if (gameChoices.Any())
|
||||
{
|
||||
using SelectDialogForm form = new(this);
|
||||
List<(Platform platform, string id, string name)> choices = form.QueryUser("Choose which programs and/or games to scan for DLC:", gameChoices);
|
||||
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)
|
||||
{
|
||||
ProgramsToScan = choices;
|
||||
programsToScan = choices;
|
||||
noneFoundLabel.Text = "None of the chosen programs nor games were applicable!" + retry;
|
||||
}
|
||||
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}%";
|
||||
progressBar.Value = p;
|
||||
};
|
||||
if (Directory.Exists(SteamLibrary.InstallPath) && ProgramsToScan is not null && ProgramsToScan.Any(c => c.platform is Platform.Steam))
|
||||
if (Directory.Exists(SteamLibrary.InstallPath) && programsToScan is not null && programsToScan.Any(c => c.platform is Platform.Steam))
|
||||
{
|
||||
progressLabel.Text = "Setting up SteamCMD . . . ";
|
||||
await SteamCMD.Setup(iProgress);
|
||||
}
|
||||
setup = false;
|
||||
progressLabel.Text = "Gathering and caching your applicable games and their DLCs . . . ";
|
||||
ProgramSelection.ValidateAll(ProgramsToScan);
|
||||
ProgramSelection.ValidateAll(programsToScan);
|
||||
/*TreeNodes.ForEach(node =>
|
||||
{
|
||||
if (node.Tag is not Platform platform
|
||||
|
@ -637,12 +635,17 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
|
||||
private static void SyncNodeAncestors(TreeNode node)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
TreeNode parentNode = node.Parent;
|
||||
if (parentNode is not null)
|
||||
{
|
||||
parentNode.Checked = parentNode.Nodes.Cast<TreeNode>().Any(childNode => childNode.Checked);
|
||||
SyncNodeAncestors(parentNode);
|
||||
node = parentNode;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,7 +724,7 @@ internal partial class SelectForm : CustomForm
|
|||
=> Invoke(() =>
|
||||
{
|
||||
ContextMenuStrip contextMenuStrip = ContextMenuStrip;
|
||||
while (ContextMenuStrip.Tag is bool used && used)
|
||||
while (ContextMenuStrip.Tag is true)
|
||||
Thread.Sleep(100);
|
||||
ContextMenuStrip.Tag = true;
|
||||
ToolStripItemCollection items = contextMenuStrip.Items;
|
||||
|
@ -737,18 +740,18 @@ internal partial class SelectForm : CustomForm
|
|||
dlcParentSelection = ProgramSelection.FromPlatformId(platform, dlc.Value.gameAppId);
|
||||
if (selection is null && dlcParentSelection is null)
|
||||
return;
|
||||
ContextMenuItem header = null;
|
||||
ContextMenuItem header;
|
||||
if (id == "PL")
|
||||
header = new(node.Text, "Paradox Launcher");
|
||||
else if (selection is not null)
|
||||
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));
|
||||
items.Add(header ?? new ContextMenuItem(node.Text));
|
||||
items.Add(header);
|
||||
string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf";
|
||||
string appInfoJSON = $@"{SteamCMD.AppInfoPath}\{id}.json";
|
||||
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();
|
||||
if (File.Exists(appInfoJSON))
|
||||
|
@ -773,17 +776,26 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
File.Delete(appInfoVDF);
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
try
|
||||
{
|
||||
File.Delete(appInfoJSON);
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
try
|
||||
{
|
||||
File.Delete(cooldown);
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
OnLoad(true);
|
||||
}));
|
||||
}
|
||||
|
@ -793,7 +805,8 @@ internal partial class SelectForm : CustomForm
|
|||
if (id == "PL")
|
||||
{
|
||||
items.Add(new ToolStripSeparator());
|
||||
items.Add(new ContextMenuItem("Repair", "Command Prompt", async (sender, e) => await ParadoxLauncher.Repair(this, selection)));
|
||||
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 ContextMenuItem("Open Root Directory", "File Explorer",
|
||||
|
@ -807,10 +820,10 @@ internal partial class SelectForm : CustomForm
|
|||
if (selection.Platform is Platform.Steam or Platform.Paradox)
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
|
||||
out string cache);
|
||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)
|
||||
|| File.Exists(cache))
|
||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
|
||||
out string config, out string cache);
|
||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(old_config)
|
||||
|| File.Exists(config) || File.Exists(cache))
|
||||
items.Add(new ContextMenuItem($"Open Steamworks Directory #{++steam}", "File Explorer",
|
||||
(sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)));
|
||||
}
|
||||
|
@ -838,42 +851,37 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
if (id != "PL")
|
||||
{
|
||||
if (selection is not null && selection.Platform is Platform.Steam
|
||||
|| dlcParentSelection is not null && dlcParentSelection.Platform is Platform.Steam)
|
||||
if (selection?.Platform is Platform.Steam || dlcParentSelection?.Platform is Platform.Steam)
|
||||
{
|
||||
items.Add(new ToolStripSeparator());
|
||||
items.Add(new ContextMenuItem("Open SteamDB", "SteamDB",
|
||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamdb.info/app/" + id)));
|
||||
}
|
||||
if (selection is not null)
|
||||
switch (selection.Platform)
|
||||
{
|
||||
if (selection.Platform is Platform.Steam)
|
||||
{
|
||||
case Platform.Steam:
|
||||
items.Add(new ContextMenuItem("Open Steam Store", "Steam Store",
|
||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.ProductUrl)));
|
||||
items.Add(new ContextMenuItem("Open Steam Community", ("Sub_" + id, selection.SubIconUrl), "Steam Community",
|
||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser("https://steamcommunity.com/app/" + id)));
|
||||
}
|
||||
if (selection.Platform is Platform.Epic)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
if (selection.Platform is Platform.Ubisoft)
|
||||
{
|
||||
break;
|
||||
case 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
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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)),
|
||||
(sender, e) => Diagnostics.OpenUrlInInternetBrowser(selection.WebsiteUrl)));
|
||||
contextMenuStrip.Show(selectionTreeView, location);
|
||||
|
@ -900,17 +908,14 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private void OnAccept(bool uninstall = false)
|
||||
{
|
||||
if (ProgramSelection.All.Any())
|
||||
{
|
||||
foreach (ProgramSelection selection in ProgramSelection.AllEnabled)
|
||||
if (!Program.IsProgramRunningDialog(this, selection))
|
||||
if (!ProgramSelection.All.Any())
|
||||
return;
|
||||
if (ProgramSelection.AllEnabled.Any(selection => !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) =>
|
||||
{
|
||||
|
@ -932,7 +937,6 @@ internal partial class SelectForm : CustomForm
|
|||
DebugForm.Current.Attach(form);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInstall(object sender, EventArgs e) => OnAccept();
|
||||
|
||||
|
@ -948,15 +952,8 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private void OnAllCheckBoxChanged(object sender, EventArgs e)
|
||||
{
|
||||
bool shouldCheck = false;
|
||||
foreach (TreeNode node in TreeNodes)
|
||||
if (node.Parent is null && !node.Checked)
|
||||
{
|
||||
shouldCheck = true;
|
||||
break;
|
||||
}
|
||||
foreach (TreeNode node in TreeNodes)
|
||||
if (node.Parent is null && node.Checked != shouldCheck)
|
||||
bool shouldCheck = TreeNodes.Any(node => node.Parent is null && !node.Checked);
|
||||
foreach (TreeNode node in TreeNodes.Where(node => node.Parent is null && node.Checked != shouldCheck))
|
||||
{
|
||||
node.Checked = shouldCheck;
|
||||
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
||||
|
@ -966,15 +963,9 @@ internal partial class SelectForm : CustomForm
|
|||
allCheckBox.CheckedChanged += OnAllCheckBoxChanged;
|
||||
}
|
||||
|
||||
internal void OnKoaloaderAllCheckBoxChanged(object sender, EventArgs e)
|
||||
private void OnKoaloaderAllCheckBoxChanged(object sender, EventArgs e)
|
||||
{
|
||||
bool shouldCheck = false;
|
||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||
if (!selection.Koaloader)
|
||||
{
|
||||
shouldCheck = true;
|
||||
break;
|
||||
}
|
||||
bool shouldCheck = ProgramSelection.AllSafe.Any(selection => !selection.Koaloader);
|
||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||
selection.Koaloader = shouldCheck;
|
||||
selectionTreeView.Invalidate();
|
||||
|
@ -984,21 +975,15 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
|
||||
private bool AreSelectionsDefault()
|
||||
{
|
||||
foreach (TreeNode node in TreeNodes)
|
||||
if (node.Parent is not null && node.Tag is Platform && (node.Text == "Unknown" ? node.Checked : !node.Checked))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
=> TreeNodes.All(node => node.Parent is null || node.Tag is not Platform || (node.Text == "Unknown" ? !node.Checked : node.Checked));
|
||||
|
||||
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)
|
||||
{
|
||||
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices()
|
||||
?? new List<(Platform platform, string gameId, string dlcId)>();
|
||||
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices().ToList();
|
||||
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)
|
||||
choices.Add((platform, node.Parent.Name, node.Name));
|
||||
|
@ -1011,15 +996,13 @@ internal partial class SelectForm : CustomForm
|
|||
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)
|
||||
{
|
||||
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices();
|
||||
if (choices is null)
|
||||
return;
|
||||
List<(Platform platform, string gameId, string dlcId)> choices = ProgramData.ReadDlcChoices().ToList();
|
||||
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.Text == "Unknown"
|
||||
|
@ -1032,8 +1015,7 @@ internal partial class SelectForm : CustomForm
|
|||
|
||||
private void OnResetDlc(object sender, EventArgs e)
|
||||
{
|
||||
foreach (TreeNode node in TreeNodes)
|
||||
if (node.Parent is not null && node.Tag is Platform)
|
||||
foreach (TreeNode node in TreeNodes.Where(node => node.Parent is not null && node.Tag is Platform))
|
||||
{
|
||||
node.Checked = node.Text != "Unknown";
|
||||
OnTreeViewNodeCheckedChanged(null, new(node, TreeViewAction.ByMouse));
|
||||
|
@ -1041,20 +1023,13 @@ internal partial class SelectForm : CustomForm
|
|||
resetButton.Enabled = CanResetDlc();
|
||||
}
|
||||
|
||||
private static bool AreKoaloaderSelectionsDefault()
|
||||
{
|
||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||
if (!selection.Koaloader || selection.KoaloaderProxy is not null)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
private static bool AreKoaloaderSelectionsDefault() => ProgramSelection.AllSafe.All(selection => selection.Koaloader && selection.KoaloaderProxy is null);
|
||||
|
||||
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)
|
||||
{
|
||||
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices()
|
||||
?? new List<(Platform platform, string id, string proxy, bool enabled)>();
|
||||
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices().ToList();
|
||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||
{
|
||||
_ = choices.RemoveAll(c => c.platform == selection.Platform && c.id == selection.Id);
|
||||
|
@ -1067,13 +1042,11 @@ internal partial class SelectForm : CustomForm
|
|||
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)
|
||||
{
|
||||
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices();
|
||||
if (choices is null)
|
||||
return;
|
||||
List<(Platform platform, string id, string proxy, bool enabled)> choices = ProgramData.ReadKoaloaderChoices().ToList();
|
||||
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
|
||||
if (choices.Any(c => c.platform == selection.Platform && c.id == selection.Id))
|
||||
{
|
||||
|
@ -1135,25 +1108,23 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
StringBuilder blockedGames = new();
|
||||
foreach (string name in Program.ProtectedGames)
|
||||
_ = blockedGames.Append(helpButtonListPrefix + name);
|
||||
_ = blockedGames.Append(HelpButtonListPrefix + name);
|
||||
StringBuilder blockedDirectories = new();
|
||||
foreach (string path in Program.ProtectedGameDirectories)
|
||||
_ = blockedDirectories.Append(helpButtonListPrefix + path);
|
||||
_ = blockedDirectories.Append(HelpButtonListPrefix + path);
|
||||
StringBuilder blockedDirectoryExceptions = new();
|
||||
foreach (string name in Program.ProtectedGameDirectoryExceptions)
|
||||
_ = blockedDirectoryExceptions.Append(helpButtonListPrefix + name);
|
||||
_ = blockedDirectoryExceptions.Append(HelpButtonListPrefix + name);
|
||||
using DialogForm form = new(this);
|
||||
_ = form.Show(SystemIcons.Information,
|
||||
"Blocks the program from caching and displaying games protected by anti-cheats."
|
||||
+ "\nYou disable this option and install DLC unlockers to protected games at your own risk!" + "\n\nBlocked games: "
|
||||
+ (string.IsNullOrWhiteSpace(blockedGames.ToString()) ? "(none)" : blockedGames) + "\n\nBlocked game sub-directories: "
|
||||
+ (string.IsNullOrWhiteSpace(blockedDirectories.ToString()) ? "(none)" : blockedDirectories) + "\n\nBlocked game sub-directory exceptions: "
|
||||
+ (string.IsNullOrWhiteSpace(blockedDirectoryExceptions.ToString()) ? "(none)" : blockedDirectoryExceptions), "OK",
|
||||
+ (string.IsNullOrWhiteSpace(blockedDirectoryExceptions.ToString()) ? "(none)" : blockedDirectoryExceptions),
|
||||
customFormText: "Block Protected Games");
|
||||
}
|
||||
|
||||
private void OnSortCheckBoxChanged(object sender, EventArgs e)
|
||||
=> 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))
|
||||
games.Add(manifest);
|
||||
}
|
||||
catch { }
|
||||
;
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
return games;
|
||||
});
|
||||
|
|
|
@ -13,14 +13,14 @@ namespace CreamInstaller.Platforms.Epic;
|
|||
|
||||
internal static class EpicStore
|
||||
{
|
||||
//private const int COOLDOWN_CATALOG_ITEM = 600;
|
||||
//private const int CooldownCatalogItem = 600;
|
||||
|
||||
/* need a method to query catalog items
|
||||
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)
|
||||
{
|
||||
|
@ -28,16 +28,19 @@ internal static class EpicStore
|
|||
string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json";
|
||||
bool cachedExists = File.Exists(cacheFile);
|
||||
Response response = null;
|
||||
if (!cachedExists || ProgramData.CheckCooldown(categoryNamespace, COOLDOWN_ENTITLEMENT))
|
||||
if (!cachedExists || ProgramData.CheckCooldown(categoryNamespace, CooldownEntitlement))
|
||||
{
|
||||
response = await QueryGraphQL(categoryNamespace);
|
||||
try
|
||||
{
|
||||
await File.WriteAllTextAsync(cacheFile, JsonConvert.SerializeObject(response, Formatting.Indented));
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
else if (cachedExists)
|
||||
}
|
||||
else
|
||||
try
|
||||
{
|
||||
response = JsonConvert.DeserializeObject<Response>(await File.ReadAllTextAsync(cacheFile));
|
||||
|
@ -57,12 +60,11 @@ internal static class EpicStore
|
|||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||
{
|
||||
KeyImage keyImage = element.KeyImages[i];
|
||||
if (keyImage.Type == "DieselStoreFront")
|
||||
{
|
||||
if (keyImage.Type != "DieselStoreFront")
|
||||
continue;
|
||||
icon = keyImage.Url.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (Item item in element.Items)
|
||||
dlcIds.Populate(item.Id, title, product, icon, null, element.Items.Length == 1);
|
||||
}
|
||||
|
@ -75,12 +77,11 @@ internal static class EpicStore
|
|||
for (int i = 0; i < element.KeyImages?.Length; i++)
|
||||
{
|
||||
KeyImage keyImage = element.KeyImages[i];
|
||||
if (keyImage.Type == "Thumbnail")
|
||||
{
|
||||
if (keyImage.Type != "Thumbnail")
|
||||
continue;
|
||||
icon = keyImage.Url.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (Item item in element.Items)
|
||||
dlcIds.Populate(item.Id, title, product, icon, item.Developer, element.Items.Length == 1);
|
||||
}
|
||||
|
@ -96,15 +97,14 @@ internal static class EpicStore
|
|||
for (int i = 0; i < dlcIds.Count; 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;
|
||||
dlcIds[i] = canOverwrite
|
||||
? (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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
dlcIds.Add((id, title, product, icon, developer));
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace CreamInstaller.Platforms.Epic.GraphQL;
|
||||
|
||||
internal class Request
|
||||
internal sealed class Request
|
||||
{
|
||||
internal Request(string @namespace) => Vars = new(@namespace);
|
||||
|
||||
|
@ -61,13 +61,13 @@ internal class Request
|
|||
[JsonProperty(PropertyName = "variables")]
|
||||
private Variables Vars { get; set; }
|
||||
|
||||
private class Headers
|
||||
private sealed class Headers
|
||||
{
|
||||
[JsonProperty(PropertyName = "Content-Type")]
|
||||
private string ContentType => "application/graphql";
|
||||
}
|
||||
|
||||
private class Variables
|
||||
private sealed class Variables
|
||||
{
|
||||
internal Variables(string @namespace) => Namespace = @namespace;
|
||||
|
||||
|
|
|
@ -98,10 +98,12 @@ internal static class ParadoxLauncher
|
|||
byte[] epicOriginalSdk64 = null;
|
||||
foreach (string directory in selection.DllDirectories)
|
||||
{
|
||||
bool koaloaderInstalled = Koaloader.AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
.Any(pair => File.Exists(pair.path) && pair.path.IsResourceFile());
|
||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out _);
|
||||
smokeInstalled = smokeInstalled || File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled
|
||||
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
|
||||
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(api64) && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
|
||||
await SmokeAPI.Uninstall(directory, deleteConfig: false);
|
||||
|
@ -125,7 +127,7 @@ internal static class ParadoxLauncher
|
|||
bool neededRepair = false;
|
||||
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))
|
||||
{
|
||||
steamOriginalSdk32.Write(api32);
|
||||
|
@ -161,13 +163,13 @@ internal static class ParadoxLauncher
|
|||
if (installForm is not null)
|
||||
installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success);
|
||||
else
|
||||
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", "OK", customFormText: "Paradox Launcher");
|
||||
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", customFormText: "Paradox Launcher");
|
||||
return RepairResult.Success;
|
||||
}
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success);
|
||||
else
|
||||
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", "OK", customFormText: "Paradox Launcher");
|
||||
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher");
|
||||
return RepairResult.Unnecessary;
|
||||
}
|
||||
_ = form is InstallForm
|
||||
|
@ -175,7 +177,7 @@ internal static class ParadoxLauncher
|
|||
+ "You will likely have to reinstall Paradox Launcher to fix this issue.")
|
||||
: dialogForm.Show(SystemIcons.Error,
|
||||
"Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found."
|
||||
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", "OK",
|
||||
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.",
|
||||
customFormText: "Paradox Launcher");
|
||||
return RepairResult.Failure;
|
||||
}
|
||||
|
|
|
@ -17,24 +17,24 @@ namespace CreamInstaller.Platforms.Steam;
|
|||
|
||||
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 int[] locks = new int[ProcessLimit];
|
||||
private static readonly int[] Locks = new int[ProcessLimit];
|
||||
|
||||
internal static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip";
|
||||
internal static readonly string DllPath = DirectoryPath + @"\steamclient.dll";
|
||||
private static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip";
|
||||
private static readonly string DllPath = DirectoryPath + @"\steamclient.dll";
|
||||
|
||||
internal static readonly string AppCachePath = DirectoryPath + @"\appcache";
|
||||
internal static readonly string ConfigPath = DirectoryPath + @"\config";
|
||||
internal static readonly string DumpsPath = DirectoryPath + @"\dumps";
|
||||
internal static readonly string LogsPath = DirectoryPath + @"\logs";
|
||||
internal static readonly string SteamAppsPath = DirectoryPath + @"\steamapps";
|
||||
private static readonly string AppCachePath = DirectoryPath + @"\appcache";
|
||||
private static readonly string ConfigPath = DirectoryPath + @"\config";
|
||||
private static readonly string DumpsPath = DirectoryPath + @"\dumps";
|
||||
private static readonly string LogsPath = DirectoryPath + @"\logs";
|
||||
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;
|
||||
|
||||
private static string GetArguments(string appId)
|
||||
|
@ -43,19 +43,19 @@ internal static class SteamCMD
|
|||
+ string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+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(() =>
|
||||
{
|
||||
wait_for_lock:
|
||||
if (Program.Canceled)
|
||||
return "";
|
||||
for (int i = 0; i < locks.Length; i++)
|
||||
for (int i = 0; i < Locks.Length; i++)
|
||||
{
|
||||
if (Program.Canceled)
|
||||
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[appId] = ++count;
|
||||
|
@ -69,11 +69,13 @@ internal static class SteamCMD
|
|||
StandardInputEncoding = Encoding.UTF8, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8
|
||||
};
|
||||
Process process = Process.Start(processStartInfo);
|
||||
if (appId == null)
|
||||
return "";
|
||||
StringBuilder output = new();
|
||||
StringBuilder appInfo = new();
|
||||
bool appInfoStarted = false;
|
||||
DateTime lastOutput = DateTime.UtcNow;
|
||||
while (true)
|
||||
while (process != null)
|
||||
{
|
||||
if (Program.Canceled)
|
||||
{
|
||||
|
@ -92,8 +94,8 @@ internal static class SteamCMD
|
|||
}
|
||||
DateTime now = DateTime.UtcNow;
|
||||
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..."))
|
||||
|
@ -108,8 +110,7 @@ internal static class SteamCMD
|
|||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ = Interlocked.Decrement(ref locks[i]);
|
||||
_ = Interlocked.Decrement(ref Locks[i]);
|
||||
return appInfo.ToString();
|
||||
}
|
||||
Thread.Sleep(200);
|
||||
|
@ -174,7 +175,10 @@ internal static class SteamCMD
|
|||
if (Directory.Exists(SteamAppsPath))
|
||||
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)
|
||||
|
@ -223,12 +227,12 @@ internal static class SteamCMD
|
|||
File.Delete(appUpdateFile);
|
||||
goto restart;
|
||||
}
|
||||
if (appInfo is null || appInfo.Value?.Children()?.ToList()?.Count == 0)
|
||||
if (appInfo.Value.Children().ToList().Count == 0)
|
||||
return appInfo;
|
||||
VToken type = appInfo.Value?.GetChild("common")?.GetChild("type");
|
||||
VToken type = appInfo.Value.GetChild("common")?.GetChild("type");
|
||||
if (type is not null && type.ToString() != "Game")
|
||||
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)
|
||||
return appInfo;
|
||||
if (type is not null && (!int.TryParse(buildid, out int gamebuildId) || gamebuildId >= buildId))
|
||||
|
@ -279,7 +283,10 @@ internal static class SteamCMD
|
|||
process.WaitForExit();
|
||||
process.Close();
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
})).ToList();
|
||||
foreach (Task task in tasks)
|
||||
await task;
|
||||
|
|
|
@ -13,7 +13,10 @@ internal static class ValveDataFile
|
|||
result = VdfConvert.Deserialize(value);
|
||||
return true;
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -23,7 +26,10 @@ internal static class ValveDataFile
|
|||
{
|
||||
return token[index];
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace CreamInstaller;
|
|||
internal static class Program
|
||||
{
|
||||
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 const string RepositoryOwner = "pointfeev";
|
||||
|
@ -32,8 +32,8 @@ internal static class Program
|
|||
#endif
|
||||
|
||||
internal static readonly Assembly EntryAssembly = Assembly.GetEntryAssembly();
|
||||
internal static readonly Process CurrentProcess = Process.GetCurrentProcess();
|
||||
internal static readonly string CurrentProcessFilePath = CurrentProcess.MainModule.FileName;
|
||||
private static readonly Process CurrentProcess = Process.GetCurrentProcess();
|
||||
internal static readonly string CurrentProcessFilePath = CurrentProcess.MainModule?.FileName;
|
||||
|
||||
internal static bool BlockProtectedGames = true;
|
||||
internal static readonly string[] ProtectedGames = { "PAYDAY 2" };
|
||||
|
@ -46,26 +46,28 @@ internal static class Program
|
|||
return false;
|
||||
if (ProtectedGames.Contains(name))
|
||||
return true;
|
||||
if (directory is not null && !ProtectedGameDirectoryExceptions.Contains(name))
|
||||
foreach (string path in ProtectedGameDirectories)
|
||||
if (Directory.Exists(directory + path))
|
||||
return true;
|
||||
if (directory is null || ProtectedGameDirectoryExceptions.Contains(name))
|
||||
return false;
|
||||
return ProtectedGameDirectories.Any(path => Directory.Exists(directory + path));
|
||||
}
|
||||
|
||||
internal static bool IsProgramRunningDialog(Form form, ProgramSelection selection)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (selection.AreDllsLocked)
|
||||
{
|
||||
using DialogForm dialogForm = new(form);
|
||||
if (dialogForm.Show(SystemIcons.Error, $"ERROR: {selection.Name} is currently running!" + "\n\nPlease close the program/game to continue . . . ",
|
||||
"Retry", "Cancel") == DialogResult.OK)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
[STAThread]
|
||||
private static void Main()
|
||||
|
|
|
@ -19,7 +19,7 @@ public enum DlcType
|
|||
EpicEntitlement
|
||||
}
|
||||
|
||||
internal class ProgramSelection
|
||||
internal sealed class ProgramSelection
|
||||
{
|
||||
internal const string DefaultKoaloaderProxy = "version";
|
||||
|
||||
|
@ -68,9 +68,9 @@ internal class ProgramSelection
|
|||
if (api32.IsFilePathLocked() || api32_o.IsFilePathLocked() || api64.IsFilePathLocked() || api64_o.IsFilePathLocked()
|
||||
|| config.IsFilePathLocked())
|
||||
return true;
|
||||
directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out config, out string cache);
|
||||
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()
|
||||
|| config.IsFilePathLocked() || cache.IsFilePathLocked())
|
||||
|| old_config.IsFilePathLocked() || config.IsFilePathLocked() || cache.IsFilePathLocked())
|
||||
return true;
|
||||
}
|
||||
if (Platform is Platform.Epic or Platform.Paradox)
|
||||
|
@ -114,16 +114,15 @@ internal class ProgramSelection
|
|||
{
|
||||
string appId = pair.Key;
|
||||
(DlcType type, string name, string icon) dlcApp = pair.Value;
|
||||
if (appId == dlcId)
|
||||
{
|
||||
if (appId != dlcId)
|
||||
continue;
|
||||
Toggle(appId, dlcApp, enabled);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Enabled = SelectedDlc.Any() || ExtraSelectedDlc.Any();
|
||||
}
|
||||
|
||||
internal void Validate()
|
||||
private void Validate()
|
||||
{
|
||||
if (Program.IsGameBlocked(Name, RootDirectory))
|
||||
{
|
||||
|
@ -140,7 +139,7 @@ internal class ProgramSelection
|
|||
_ = 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))
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace CreamInstaller.Resources;
|
|||
|
||||
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"),
|
||||
("Lyptus", "Lyptus32.dll"), ("Lyptus", "Lyptus64.dll"), ("SmokeAPI", "SmokeAPI.dll"), ("SmokeAPI", "SmokeAPI32.dll"),
|
||||
|
@ -21,30 +21,28 @@ internal static class Koaloader
|
|||
("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();
|
||||
foreach (string proxy in EmbeddedResources.Select(proxy =>
|
||||
proxies = EmbeddedResources.Select(proxy =>
|
||||
{
|
||||
proxy = proxy[(proxy.IndexOf('.') + 1)..];
|
||||
return proxy[(proxy.IndexOf('.') + 1)..];
|
||||
}))
|
||||
proxies.Add(directory + @"\" + proxy);
|
||||
config = directory + @"\Koaloader.json";
|
||||
}).Select(proxy => directory + @"\" + proxy).ToList();
|
||||
old_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")))
|
||||
{
|
||||
resourceIdentifier.GetProxyInfoFromIdentifier(out string _proxyName, out BinaryType _binaryType);
|
||||
if (_proxyName == proxyName && _binaryType == binaryType)
|
||||
{
|
||||
if (_proxyName != proxyName || _binaryType != binaryType)
|
||||
continue;
|
||||
resourceIdentifier.Write(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void GetProxyInfoFromIdentifier(this string resourceIdentifier, out string proxyName, out BinaryType binaryType)
|
||||
{
|
||||
|
@ -52,16 +50,17 @@ internal static class Koaloader
|
|||
baseIdentifier = baseIdentifier[..baseIdentifier.IndexOf('.')];
|
||||
proxyName = baseIdentifier[..baseIdentifier.LastIndexOf('_')];
|
||||
string bitness = baseIdentifier[(baseIdentifier.LastIndexOf('_') + 1)..];
|
||||
binaryType = bitness == "32"
|
||||
? BinaryType.BIT32
|
||||
: bitness == "64"
|
||||
? BinaryType.BIT64
|
||||
: BinaryType.Unknown;
|
||||
binaryType = bitness switch { "32" => BinaryType.BIT32, "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> modules = new(PlatformIdComparer.String);
|
||||
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,
|
||||
InstallForm installForm = null)
|
||||
private static void WriteConfig(StreamWriter writer, SortedList<string, string> targets, SortedList<string, string> modules, InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
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)
|
||||
=> 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)))
|
||||
{
|
||||
File.Delete(proxyPath);
|
||||
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false);
|
||||
}
|
||||
foreach ((string unlocker, string path) in AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
foreach ((string unlocker, string path) in AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
.Where(pair => File.Exists(pair.path) && pair.path.IsResourceFile()))
|
||||
{
|
||||
File.Delete(path);
|
||||
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))
|
||||
{
|
||||
File.Delete(config);
|
||||
|
@ -154,7 +157,7 @@ internal static class Koaloader
|
|||
InstallForm installForm = null, bool generateConfig = true)
|
||||
=> 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 path = directory + @"\" + proxy + ".dll";
|
||||
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"))
|
||||
if (executable.TryGetFileBinaryType(out BinaryType binaryType))
|
||||
{
|
||||
if (binaryType == BinaryType.BIT32)
|
||||
switch (binaryType)
|
||||
{
|
||||
case BinaryType.BIT32:
|
||||
bit32 = true;
|
||||
else if (binaryType == BinaryType.BIT64)
|
||||
break;
|
||||
case BinaryType.BIT64:
|
||||
bit64 = true;
|
||||
break;
|
||||
}
|
||||
if (bit32 && bit64)
|
||||
break;
|
||||
}
|
||||
|
@ -216,7 +224,9 @@ internal static class Koaloader
|
|||
}
|
||||
SmokeAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||
}
|
||||
if (selection.Platform is Platform.Epic or Platform.Paradox)
|
||||
switch (selection.Platform)
|
||||
{
|
||||
case Platform.Epic or Platform.Paradox:
|
||||
{
|
||||
if (bit32)
|
||||
{
|
||||
|
@ -253,8 +263,9 @@ internal static class Koaloader
|
|||
LogTextBox.Action, false);
|
||||
}
|
||||
ScreamAPI.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||
break;
|
||||
}
|
||||
if (selection.Platform is Platform.Ubisoft)
|
||||
case Platform.Ubisoft:
|
||||
{
|
||||
if (bit32)
|
||||
{
|
||||
|
@ -264,7 +275,8 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action,
|
||||
false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR1Unlocker32.dll";
|
||||
}
|
||||
|
@ -281,7 +293,8 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action,
|
||||
false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR1Unlocker64.dll";
|
||||
}
|
||||
|
@ -299,7 +312,8 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action,
|
||||
false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR2Unlocker32.dll";
|
||||
}
|
||||
|
@ -316,7 +330,8 @@ internal static class Koaloader
|
|||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action, false);
|
||||
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker from non-root directory: {Path.GetFileName(path)}", LogTextBox.Action,
|
||||
false);
|
||||
}
|
||||
path = rootDirectory + @"\UplayR2Unlocker64.dll";
|
||||
}
|
||||
|
@ -326,6 +341,8 @@ internal static class Koaloader
|
|||
LogTextBox.Action, false);
|
||||
}
|
||||
UplayR2.CheckConfig(rootDirectory ?? directory, selection, installForm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (generateConfig)
|
||||
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 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>
|
||||
|
@ -263,7 +263,51 @@ internal static class Resources
|
|||
"76CAB00C7DD33FC19F7CDD1849FF9CA2", // Koaloader v2.4.0
|
||||
"DA4D6A7C0872757A74DDAE05A2C1D160", // Koaloader v2.4.0
|
||||
"1F46DE8747C0A157841AFFE6185CE4C9", // Koaloader v2.4.0
|
||||
"BE16B588D018D8EFF1F3B6A600F26BED" // Koaloader v2.4.0
|
||||
"BE16B588D018D8EFF1F3B6A600F26BED", // Koaloader v2.4.0
|
||||
"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
|
||||
"973AB1632B747D4BF3B2666F32E34327", // SmokeAPI v1.0.1
|
||||
"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
|
||||
"D077737B9979D32458AC938A2978FA3C", // SmokeAPI v1.0.1
|
||||
"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
|
||||
{
|
||||
if (embeddedResources is null)
|
||||
{
|
||||
if (embeddedResources is not null)
|
||||
return embeddedResources;
|
||||
string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
||||
embeddedResources = new();
|
||||
foreach (string resourceName in names.Where(n => n.StartsWith("CreamInstaller.Resources.")))
|
||||
embeddedResources.Add(resourceName[25..]);
|
||||
}
|
||||
return embeddedResources;
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +392,7 @@ internal static class Resources
|
|||
{
|
||||
using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier);
|
||||
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
|
||||
resource.CopyTo(file);
|
||||
resource?.CopyTo(file);
|
||||
}
|
||||
|
||||
internal static void Write(this byte[] resource, string filePath)
|
||||
|
@ -419,7 +464,7 @@ internal static class Resources
|
|||
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();
|
||||
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|
||||
|
@ -441,39 +486,35 @@ internal static class Resources
|
|||
if (Program.Canceled)
|
||||
return null;
|
||||
string subDirectory = directory.BeautifyPath();
|
||||
if (!dllDirectories.Contains(subDirectory))
|
||||
{
|
||||
bool koaloaderInstalled = Koaloader.AutoLoadDlls.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
|
||||
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)
|
||||
{
|
||||
subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string config,
|
||||
out string cache);
|
||||
if (File.Exists(api) || File.Exists(api_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled
|
||||
|| File.Exists(cache) && !koaloaderInstalled)
|
||||
subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string old_config,
|
||||
out string config, out string cache);
|
||||
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)
|
||||
dllDirectories.Add(subDirectory);
|
||||
}
|
||||
if (platform is Platform.Epic or Platform.Paradox)
|
||||
{
|
||||
subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o)
|
||||
|| File.Exists(config) && !koaloaderInstalled)
|
||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled)
|
||||
dllDirectories.Add(subDirectory);
|
||||
}
|
||||
if (platform is Platform.Ubisoft)
|
||||
{
|
||||
subDirectory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
|
||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o)
|
||||
|| File.Exists(config) && !koaloaderInstalled)
|
||||
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) && !koaloaderInstalled)
|
||||
dllDirectories.Add(subDirectory);
|
||||
subDirectory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o,
|
||||
out config);
|
||||
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;
|
||||
});
|
||||
|
||||
|
@ -487,7 +528,7 @@ internal static class Resources
|
|||
config = directory + @"\cream_api.ini";
|
||||
}
|
||||
|
||||
internal static string ComputeMD5(this string filePath)
|
||||
private static string ComputeMD5(this string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
return null;
|
||||
|
@ -500,10 +541,9 @@ internal static class Resources
|
|||
}
|
||||
|
||||
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)
|
||||
=> filePath.ComputeMD5() is string hash && ResourceMD5s.Values.Any(hashes => hashes.Contains(hash));
|
||||
internal static bool IsResourceFile(this string filePath) => filePath.ComputeMD5() is { } hash && ResourceMD5s.Values.Any(hashes => hashes.Contains(hash));
|
||||
|
||||
internal enum BinaryType
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
|
|
|
@ -12,19 +12,20 @@ namespace CreamInstaller.Resources;
|
|||
internal static class SmokeAPI
|
||||
{
|
||||
internal static void GetSmokeApiComponents(this string directory, out string api32, out string api32_o, out string api64, out string api64_o,
|
||||
out string config, out string cache)
|
||||
out string old_config, out string config, out string cache)
|
||||
{
|
||||
api32 = directory + @"\steam_api.dll";
|
||||
api32_o = directory + @"\steam_api_o.dll";
|
||||
api64 = directory + @"\steam_api64.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";
|
||||
}
|
||||
|
||||
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);
|
||||
foreach ((string id, string name, SortedList<string, (DlcType type, string name, string icon)> extraDlc) in selection.ExtraSelectedDlc)
|
||||
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));
|
||||
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));
|
||||
}
|
||||
if (overrideDlc.Any() || injectDlc.Any())
|
||||
{
|
||||
/*if (installForm is not null)
|
||||
installForm.UpdateUser("Generating SmokeAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/
|
||||
File.Create(config).Close();
|
||||
StreamWriter writer = new(config, true, Encoding.UTF8);
|
||||
File.Create(old_config).Close();
|
||||
StreamWriter writer = new(old_config, true, Encoding.UTF8);
|
||||
WriteConfig(writer, new(overrideDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String),
|
||||
new(injectDlc.ToDictionary(pair => pair.Key, pair => pair.Value), PlatformIdComparer.String), installForm);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
}
|
||||
else if (File.Exists(config))
|
||||
else if (File.Exists(old_config))
|
||||
{
|
||||
File.Delete(config);
|
||||
installForm?.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
|
||||
File.Delete(old_config);
|
||||
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)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
|
@ -107,7 +108,8 @@ internal static class SmokeAPI
|
|||
File.Delete(oldConfig);
|
||||
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))
|
||||
|
@ -128,6 +130,11 @@ internal static class SmokeAPI
|
|||
File.Move(api64_o, api64);
|
||||
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))
|
||||
{
|
||||
File.Delete(config);
|
||||
|
@ -149,7 +156,7 @@ internal static class SmokeAPI
|
|||
File.Delete(oldConfig);
|
||||
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))
|
||||
{
|
||||
File.Move(api32, api32_o);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
writer.WriteLine("{");
|
||||
|
|
|
@ -11,21 +11,21 @@ namespace CreamInstaller.Utility;
|
|||
|
||||
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 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 OldProgramChoicesPath = DirectoryPath + @"\choices.txt";
|
||||
internal static readonly string ProgramChoicesPath = DirectoryPath + @"\choices.json";
|
||||
internal static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
||||
internal static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.json";
|
||||
private static readonly string OldProgramChoicesPath = DirectoryPath + @"\choices.txt";
|
||||
private static readonly string ProgramChoicesPath = DirectoryPath + @"\choices.json";
|
||||
private static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
||||
private static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.json";
|
||||
|
||||
internal static async Task Setup()
|
||||
=> await Task.Run(() =>
|
||||
|
@ -64,16 +64,19 @@ internal static class ProgramData
|
|||
|
||||
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))
|
||||
if (!File.Exists(cooldownFile))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
if (DateTime.TryParse(File.ReadAllText(cooldownFile), out DateTime cooldown))
|
||||
return cooldown;
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -87,13 +90,16 @@ internal static class ProgramData
|
|||
{
|
||||
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))
|
||||
return null;
|
||||
return Enumerable.Empty<(Platform platform, string id)>();
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(ProgramChoicesPath), typeof(List<(Platform platform, string id)>)) as
|
||||
|
@ -101,11 +107,11 @@ internal static class ProgramData
|
|||
}
|
||||
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
|
||||
{
|
||||
|
@ -114,21 +120,24 @@ internal static class ProgramData
|
|||
else
|
||||
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))
|
||||
return null;
|
||||
return Enumerable.Empty<(Platform platform, string gameId, string dlcId)>();
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath), typeof(List<(Platform platform, string gameId, string dlcId)>)) as
|
||||
List<(Platform platform, string gameId, string dlcId)>;
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(DlcChoicesPath), typeof(IEnumerable<(Platform platform, string gameId, string dlcId)>)) as
|
||||
IEnumerable<(Platform platform, string gameId, string dlcId)>;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new();
|
||||
return Enumerable.Empty<(Platform platform, string gameId, string dlcId)>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,25 +150,29 @@ internal static class ProgramData
|
|||
else
|
||||
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))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject(File.ReadAllText(KoaloaderProxyChoicesPath),
|
||||
typeof(List<(Platform platform, string id, string proxy, bool enabled)>)) as List<(Platform platform, string id, string proxy, bool enabled)>;
|
||||
typeof(IEnumerable<(Platform platform, string id, string proxy, bool enabled)>)) as
|
||||
IEnumerable<(Platform platform, string id, string proxy, bool enabled)>;
|
||||
}
|
||||
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
|
||||
{
|
||||
|
@ -168,6 +181,9 @@ internal static class ProgramData
|
|||
else
|
||||
File.WriteAllText(KoaloaderProxyChoicesPath, JsonConvert.SerializeObject(choices));
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue