Add support for CreamAPI's new proxy mode

This commit is contained in:
pointfeev 2024-07-22 06:36:16 -04:00
parent 97f14a8dba
commit 5e288a3fc8
9 changed files with 192 additions and 82 deletions

View file

@ -133,7 +133,7 @@ internal sealed class CustomTreeView : TreeView
if (form is SelectForm)
{
Selection selection = Selection.FromId(platform, id);
if (selection is not null && selection.CanUseProxy)
if (selection is not null)
{
if (bounds == node.Bounds)
{
@ -238,16 +238,11 @@ internal sealed class CustomTreeView : TreeView
if (comboBoxBounds.Count > 0 && selectForm is not null)
foreach (KeyValuePair<Selection, Rectangle> pair in comboBoxBounds)
if (!Selection.All.ContainsKey(pair.Key) || !pair.Key.CanUseProxy)
if (!Selection.All.ContainsKey(pair.Key))
_ = comboBoxBounds.Remove(pair.Key);
else if (pair.Value.Contains(clickPoint))
{
HashSet<string> proxies = EmbeddedResources
.Where(r => r.StartsWith("Koaloader", StringComparison.Ordinal)).Select(p =>
{
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
return proxyName;
}).ToHashSet();
IEnumerable<string> proxies = pair.Key.GetAvailableProxies();
comboBoxDropDown ??= new();
comboBoxDropDown.ShowItemToolTips = false;
comboBoxDropDown.Items.Clear();
@ -257,7 +252,9 @@ internal sealed class CustomTreeView : TreeView
foreach ((string directory, BinaryType _) in pair.Key.ExecutableDirectories)
{
string path = directory + @"\" + proxy + ".dll";
if (!path.FileExists() || path.IsResourceFile(ResourceIdentifier.Koaloader))
if (!path.FileExists() || path.IsResourceFile(ResourceIdentifier.Koaloader) ||
path.IsResourceFile(ResourceIdentifier.Steamworks32) ||
path.IsResourceFile(ResourceIdentifier.Steamworks64))
continue;
canUse = false;
break;
@ -276,7 +273,7 @@ internal sealed class CustomTreeView : TreeView
}
foreach (KeyValuePair<Selection, Rectangle> pair in checkBoxBounds)
if (!Selection.All.ContainsKey(pair.Key) || !pair.Key.CanUseProxy)
if (!Selection.All.ContainsKey(pair.Key))
_ = checkBoxBounds.Remove(pair.Key);
else if (pair.Value.Contains(clickPoint))
{

View file

@ -65,11 +65,13 @@ internal sealed partial class InstallForm : CustomForm
}
bool useKoaloader = selection.UseProxy && (Program.UseSmokeAPI || selection.Platform is not Platform.Steam);
bool useCreamApiProxy = selection.UseProxy && !Program.UseSmokeAPI &&
(selection.Platform is Platform.Steam || selection.Platform is Platform.Paradox &&
selection.ExtraSelections.Any(s => s.Platform is Platform.Steam));
UpdateUser(
$"{(uninstalling ? "Uninstalling" : "Installing")}" + $" {(uninstalling ? "from" : "for")} " +
selection.Name
+ $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation);
selection.Name + $" with root directory \"{selection.RootDirectory}\" . . . ", LogTextBox.Operation);
IEnumerable<string> invalidDirectories = (await selection.RootDirectory.GetExecutables())
?.Where(d => selection.ExecutableDirectories.All(s => s.directory != Path.GetDirectoryName(d.path)))
.Select(d => Path.GetDirectoryName(d.path));
@ -81,6 +83,7 @@ internal sealed partial class InstallForm : CustomForm
{
if (Program.Canceled)
return;
directory.GetKoaloaderComponents(out string old_config, out string config);
if (directory.GetKoaloaderProxies().Any(proxy =>
proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
@ -93,13 +96,27 @@ internal sealed partial class InstallForm : CustomForm
$" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
}
directory.GetCreamApiComponents(out _, out _, out _, out _, out config);
if (directory.GetCreamApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))))
{
UpdateUser(
"Uninstalling CreamAPI in proxy mode from " + selection.Name +
$" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
await CreamAPI.ProxyUninstall(directory, this);
}
}
if (uninstalling || !useKoaloader)
foreach ((string directory, BinaryType _) in selection.ExecutableDirectories)
if (uninstalling || !useKoaloader || !useCreamApiProxy)
foreach ((string directory, _) in selection.ExecutableDirectories)
{
if (Program.Canceled)
return;
if (uninstalling || !useKoaloader)
{
directory.GetKoaloaderComponents(out string old_config, out string config);
if (directory.GetKoaloaderProxies().Any(proxy =>
proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
@ -113,12 +130,29 @@ internal sealed partial class InstallForm : CustomForm
}
}
bool uninstallingForKoaloader = uninstalling || useKoaloader;
if (uninstalling || !useCreamApiProxy)
{
directory.GetCreamApiComponents(out _, out _, out _, out _, out string config);
if (directory.GetCreamApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))) ||
config.FileExists())
{
UpdateUser(
"Uninstalling CreamAPI in proxy mode from " + selection.Name +
$" in directory \"{directory}\" . . . ", LogTextBox.Operation);
await CreamAPI.ProxyUninstall(directory, this);
}
}
}
bool uninstallingForProxy = uninstalling || useKoaloader || useCreamApiProxy;
int count = selection.DllDirectories.Count, cur = 0;
foreach (string directory in selection.DllDirectories)
{
if (Program.Canceled)
return;
if (selection.Platform is Platform.Steam or Platform.Paradox)
{
if (Program.UseSmokeAPI)
@ -126,17 +160,17 @@ internal sealed partial class InstallForm : CustomForm
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 old_log, out string log, out string cache);
if (uninstallingForKoaloader
if (uninstallingForProxy
? api32_o.FileExists() || api64_o.FileExists() || old_config.FileExists() ||
config.FileExists() || old_log.FileExists() || log.FileExists()
|| cache.FileExists()
: api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallingForKoaloader ? "Uninstalling" : "Installing")} SmokeAPI" +
$" {(uninstallingForKoaloader ? "from" : "for")} " + selection.Name
$"{(uninstallingForProxy ? "Uninstalling" : "Installing")} SmokeAPI" +
$" {(uninstallingForProxy ? "from" : "for")} " + selection.Name
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
if (uninstallingForKoaloader)
if (uninstallingForProxy)
await SmokeAPI.Uninstall(directory, this);
else
await SmokeAPI.Install(directory, selection, this);
@ -146,15 +180,15 @@ internal sealed partial class InstallForm : CustomForm
{
directory.GetCreamApiComponents(out string api32, out string api32_o, out string api64,
out string api64_o, out string config);
if (uninstalling
if (uninstallingForProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists()
: api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstalling ? "Uninstalling" : "Installing")} CreamAPI" +
$" {(uninstalling ? "from" : "for")} " + selection.Name
$"{(uninstallingForProxy ? "Uninstalling" : "Installing")} CreamAPI" +
$" {(uninstallingForProxy ? "from" : "for")} " + selection.Name
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
if (uninstalling)
if (uninstallingForProxy)
await CreamAPI.Uninstall(directory, this);
else
await CreamAPI.Install(directory, selection, this);
@ -166,15 +200,15 @@ internal sealed partial class InstallForm : CustomForm
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64,
out string api64_o, out string config, out string log);
if (uninstallingForKoaloader
if (uninstallingForProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallingForKoaloader ? "Uninstalling" : "Installing")} ScreamAPI" +
$" {(uninstallingForKoaloader ? "from" : "for")} " + selection.Name
$"{(uninstallingForProxy ? "Uninstalling" : "Installing")} ScreamAPI" +
$" {(uninstallingForProxy ? "from" : "for")} " + selection.Name
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
if (uninstallingForKoaloader)
if (uninstallingForProxy)
await ScreamAPI.Uninstall(directory, this);
else
await ScreamAPI.Install(directory, selection, this);
@ -185,15 +219,15 @@ internal sealed partial class InstallForm : CustomForm
{
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64,
out string api64_o, out string config, out string log);
if (uninstallingForKoaloader
if (uninstallingForProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallingForKoaloader ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" +
$" {(uninstallingForKoaloader ? "from" : "for")} " + selection.Name
$"{(uninstallingForProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" +
$" {(uninstallingForProxy ? "from" : "for")} " + selection.Name
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
if (uninstallingForKoaloader)
if (uninstallingForProxy)
await UplayR1.Uninstall(directory, this);
else
await UplayR1.Install(directory, selection, this);
@ -201,15 +235,15 @@ internal sealed partial class InstallForm : CustomForm
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o,
out api64, out api64_o, out config, out log);
if (uninstallingForKoaloader
if (uninstallingForProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: old_api32.FileExists() || old_api64.FileExists() || api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallingForKoaloader ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" +
$" {(uninstallingForKoaloader ? "from" : "for")} " + selection.Name
$"{(uninstallingForProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" +
$" {(uninstallingForProxy ? "from" : "for")} " + selection.Name
+ $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
if (uninstallingForKoaloader)
if (uninstallingForProxy)
await UplayR2.Uninstall(directory, this);
else
await UplayR2.Install(directory, selection, this);
@ -219,15 +253,27 @@ internal sealed partial class InstallForm : CustomForm
UpdateProgress(++cur / count * 100);
}
if (useKoaloader && !uninstalling)
if ((useCreamApiProxy || useKoaloader) && !uninstalling)
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
{
if (Program.Canceled)
return;
UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ",
if (useCreamApiProxy)
{
UpdateUser(
"Installing CreamAPI in proxy mode for " + selection.Name +
$" in directory \"{directory}\" . . . ",
LogTextBox.Operation);
await CreamAPI.ProxyInstall(directory, binaryType, selection, this);
}
else if (useKoaloader)
{
UpdateUser("Installing Koaloader for " + selection.Name + $" in directory \"{directory}\" . . . ",
LogTextBox.Operation);
await Koaloader.Install(directory, binaryType, selection, selection.RootDirectory, this);
}
}
UpdateProgress(100);
}

View file

@ -22,9 +22,6 @@ namespace CreamInstaller.Forms;
internal sealed partial class SelectForm : CustomForm
{
// TODO: fix the form display reset save load buttons for proxy
// consolidate all reset save load functionality into only 3 buttons instead of 6?
private const string HelpButtonListPrefix = "\n • ";
private static SelectForm current;
@ -1167,7 +1164,7 @@ internal sealed partial class SelectForm : CustomForm
saveButton.Enabled = CanSaveSelections();
resetButton.Enabled = CanResetSelections();
proxyAllCheckBox.CheckedChanged -= OnProxyAllCheckBoxChanged;
proxyAllCheckBox.Checked = Selection.All.Keys.All(selection => !selection.CanUseProxy || selection.UseProxy);
proxyAllCheckBox.Checked = Selection.All.Keys.All(selection => selection.UseProxy);
proxyAllCheckBox.CheckedChanged += OnProxyAllCheckBoxChanged;
}

View file

@ -83,9 +83,6 @@ internal static class ParadoxLauncher
byte[] epicOriginalSdk64 = null;
foreach (string directory in selection.DllDirectories.TakeWhile(_ => !Program.Canceled))
{
bool koaloaderInstalled = Koaloader.AutoLoadDLLs
.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
.Any(pair => pair.path.FileExists() && pair.path.IsResourceFile());
string api32;
string api32_o;
string api64;
@ -93,17 +90,16 @@ internal static class ParadoxLauncher
if (Program.UseSmokeAPI)
{
directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o,
out string old_config, out string config, out _, out _, out _);
out _, out _, out _, out _, out _);
creamInstalled = creamInstalled || api32_o.FileExists() || api64_o.FileExists()
|| (old_config.FileExists() || config.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
await SmokeAPI.Uninstall(directory, deleteOthers: false);
}
else
{
directory.GetCreamApiComponents(out api32, out api32_o, out api64, out api64_o, out string config);
creamInstalled = creamInstalled || api32_o.FileExists() || api64_o.FileExists() || config.FileExists()
directory.GetCreamApiComponents(out api32, out api32_o, out api64, out api64_o, out _);
creamInstalled = creamInstalled || api32_o.FileExists() || api64_o.FileExists()
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
await CreamAPI.Uninstall(directory, deleteOthers: false);
@ -115,10 +111,8 @@ internal static class ParadoxLauncher
if (steamOriginalSdk64 is null && api64.FileExists() &&
!api64.IsResourceFile(ResourceIdentifier.Steamworks64))
steamOriginalSdk64 = api64.ReadFileBytes(true);
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out string screamConfig,
out string log);
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out _, out _);
screamInstalled = screamInstalled || api32_o.FileExists() || api64_o.FileExists()
|| (screamConfig.FileExists() || log.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64);
await ScreamAPI.Uninstall(directory, deleteOthers: false);
@ -136,8 +130,15 @@ internal static class ParadoxLauncher
bool neededRepair = false;
foreach (string directory in selection.DllDirectories.TakeWhile(_ => !Program.Canceled))
{
directory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _, out _,
string api32;
string api64;
if (Program.UseSmokeAPI)
directory.GetSmokeApiComponents(out api32, out _, out api64, out _, out _, out _,
out _,
out _, out _);
else
directory.GetCreamApiComponents(out api32, out _, out api64, out _, out _);
if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32))
{
steamOriginalSdk32.WriteResource(api32);
@ -160,13 +161,9 @@ internal static class ParadoxLauncher
if (creamInstalled)
if (Program.UseSmokeAPI)
{
await SmokeAPI.Install(directory, selection, generateConfig: false);
}
else
{
await CreamAPI.Install(directory, selection, generateConfig: false);
}
directory.GetScreamApiComponents(out api32, out _, out api64, out _, out _, out _);
if (epicOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))

View file

@ -36,7 +36,7 @@ internal static class Program
internal static readonly int CurrentProcessId = CurrentProcess.Id;
// this may forever be false, but who knows, maybe acidicoala makes it once again better than CreamAPI some day
internal static bool UseSmokeAPI = false;
internal const bool UseSmokeAPI = false;
internal static bool BlockProtectedGames = true;
internal static readonly string[] ProtectedGames = ["PAYDAY 2"];

View file

@ -12,7 +12,10 @@ namespace CreamInstaller.Resources;
internal static class CreamAPI
{
// TODO: add proxy mode support
internal static readonly List<string> ProxyDLLs = ["winmm", "winhttp", "version"];
internal static IEnumerable<string> GetCreamApiProxies(this string directory)
=> from proxy in ProxyDLLs select directory + @"\" + proxy + ".dll";
internal static void GetCreamApiComponents(this string directory, out string api32, out string api32_o,
out string api64, out string api64_o, out string config)
@ -113,7 +116,7 @@ internal static class CreamAPI
}
internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteOthers = true)
=> await Task.Run(() =>
=> await Task.Run(async () =>
{
DeleteSmokeApiComponents(directory, installForm);
@ -149,11 +152,14 @@ internal static class CreamAPI
if (!deleteOthers)
return;
if (config.FileExists())
{
config.DeleteFile();
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
}
await SmokeAPI.Uninstall(directory, installForm, false);
});
internal static async Task Install(string directory, Selection selection, InstallForm installForm = null,
@ -194,6 +200,59 @@ internal static class CreamAPI
CheckConfig(directory, selection, installForm);
});
internal static async Task ProxyUninstall(string directory, InstallForm installForm = null,
bool deleteOthers = true)
=> await Task.Run(() =>
{
foreach (string proxy in directory.GetCreamApiProxies().Where(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))))
{
proxy.DeleteFile(true);
installForm?.UpdateUser($"Deleted CreamAPI: {Path.GetFileName(proxy)}", LogTextBox.Action, false);
}
if (!deleteOthers)
return;
directory.GetCreamApiComponents(out _, out _, out _, out _, out string config);
if (config.FileExists())
{
config.DeleteFile();
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
}
});
internal static async Task ProxyInstall(string directory, BinaryType binaryType, Selection selection,
InstallForm installForm = null, bool generateConfig = true)
=> await Task.Run(async () =>
{
await Koaloader.Uninstall(directory, selection.RootDirectory, installForm);
string proxy = selection.Proxy ?? Selection.DefaultProxy;
string path = directory + @"\" + proxy + ".dll";
foreach (string _path in directory.GetCreamApiProxies().Where(p =>
p != path && p.FileExists() && (p.IsResourceFile(ResourceIdentifier.Steamworks32) ||
p.IsResourceFile(ResourceIdentifier.Steamworks64))))
{
_path.DeleteFile(true);
installForm?.UpdateUser($"Deleted CreamAPI: {Path.GetFileName(_path)}", LogTextBox.Action, false);
}
if (path.FileExists() && !path.IsResourceFile(ResourceIdentifier.Steamworks32) &&
!path.IsResourceFile(ResourceIdentifier.Steamworks64))
throw new CustomMessageException("A non-CreamAPI DLL named " + proxy +
".dll already exists in this directory!");
(binaryType == BinaryType.BIT32 ? "CreamAPI.steam_api.dll" : "CreamAPI.steam_api64.dll")
.WriteManifestResource(path);
installForm?.UpdateUser(
$"Wrote {(binaryType == BinaryType.BIT32 ? "32-bit" : "64-bit")} CreamAPI: {Path.GetFileName(path)}",
LogTextBox.Action,
false);
if (generateConfig)
CheckConfig(directory, selection, installForm);
});
internal static readonly Dictionary<ResourceIdentifier, HashSet<string>> ResourceMD5s = new()
{
[ResourceIdentifier.Steamworks32] =

View file

@ -182,7 +182,7 @@ internal static class Koaloader
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
}
if (Program.UseSmokeAPI) await SmokeAPI.Uninstall(directory, installForm, deleteConfig);
await SmokeAPI.Uninstall(directory, installForm, deleteConfig);
await ScreamAPI.Uninstall(directory, installForm, deleteConfig);
await UplayR1.Uninstall(directory, installForm, deleteConfig);
await UplayR2.Uninstall(directory, installForm, deleteConfig);
@ -193,8 +193,10 @@ internal static class Koaloader
internal static async Task Install(string directory, BinaryType binaryType, Selection selection,
string rootDirectory = null,
InstallForm installForm = null, bool generateConfig = true)
=> await Task.Run(() =>
=> await Task.Run(async () =>
{
await CreamAPI.ProxyUninstall(directory, installForm);
string proxy = selection.Proxy ?? Selection.DefaultProxy;
string path = directory + @"\" + proxy + ".dll";
foreach (string _path in directory.GetKoaloaderProxies().Where(p =>

View file

@ -186,7 +186,7 @@ internal static class SmokeAPI
}
internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteOthers = true)
=> await Task.Run(() =>
=> await Task.Run(async () =>
{
DeleteCreamApiComponents(directory, installForm);
@ -222,6 +222,7 @@ internal static class SmokeAPI
if (!deleteOthers)
return;
if (old_config.FileExists())
{
old_config.DeleteFile();
@ -252,6 +253,8 @@ internal static class SmokeAPI
log.DeleteFile();
installForm?.UpdateUser($"Deleted log: {Path.GetFileName(log)}", LogTextBox.Action, false);
}
await CreamAPI.Uninstall(directory, installForm, false);
});
internal static async Task Install(string directory, Selection selection, InstallForm installForm = null,

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using CreamInstaller.Forms;
using CreamInstaller.Resources;
using CreamInstaller.Utility;
using static CreamInstaller.Resources.Resources;
@ -20,16 +21,13 @@ public enum Platform
internal sealed class Selection : IEquatable<Selection>
{
internal const string DefaultProxy = "version";
// TODO: add proxy mode support for CreamAPI and set this to true
internal bool CanUseProxy => Program.UseSmokeAPI || Platform is not Platform.Steam;
internal const string DefaultProxy = "winmm";
internal static readonly ConcurrentDictionary<Selection, byte> All = new();
internal readonly HashSet<string> DllDirectories;
internal readonly List<(string directory, BinaryType binaryType)> ExecutableDirectories;
internal readonly HashSet<Selection> ExtraSelections = new();
internal readonly HashSet<Selection> ExtraSelections = [];
internal readonly string Id;
internal readonly string Name;
internal readonly Platform Platform;
@ -43,6 +41,17 @@ internal sealed class Selection : IEquatable<Selection>
internal string SubIcon;
internal string Website;
internal IEnumerable<string> GetAvailableProxies()
{
if (!Program.UseSmokeAPI && Platform is Platform.Steam or Platform.Paradox)
return CreamAPI.ProxyDLLs;
return EmbeddedResources.Where(r => r.StartsWith("Koaloader", StringComparison.Ordinal)).Select(p =>
{
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
return proxyName;
}).ToHashSet();
}
private Selection(Platform platform, string id, string name, string rootDirectory, HashSet<string> dllDirectories,
List<(string directory, BinaryType binaryType)> executableDirectories)
{