Added options to disable launcher/plugin auto updates
All checks were successful
Build / Compute Version (push) Successful in 6s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 4m4s
Build / Build Nuget package (NuGet) (push) Successful in 4m7s
Build / Build Nuget package (SharedCringe) (push) Successful in 4m5s
Build / Build Nuget package (CringePlugins) (push) Successful in 4m25s
Build / Build Launcher (push) Successful in 5m12s
All checks were successful
Build / Compute Version (push) Successful in 6s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 4m4s
Build / Build Nuget package (NuGet) (push) Successful in 4m7s
Build / Build Nuget package (SharedCringe) (push) Successful in 4m5s
Build / Build Nuget package (CringePlugins) (push) Successful in 4m25s
Build / Build Launcher (push) Successful in 5m12s
Also ran cleanup
This commit is contained in:
@@ -51,9 +51,9 @@ public class GameDirectoryAssemblyLoadContext : AssemblyLoadContext, ICoreLoadCo
|
|||||||
AddOverride(new(name), Path.Join(AppContext.BaseDirectory, name + ".dll"));
|
AddOverride(new(name), Path.Join(AppContext.BaseDirectory, name + ".dll"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Assembly? Load(AssemblyName name)
|
protected override Assembly? Load(AssemblyName assemblyName)
|
||||||
{
|
{
|
||||||
var key = name.Name ?? name.FullName[..','];
|
var key = assemblyName.Name ?? assemblyName.FullName[..','];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@@ -1,9 +1,4 @@
|
|||||||
using System.Net;
|
using CringeBootstrap.Abstractions;
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Runtime.Loader;
|
|
||||||
using CringeBootstrap.Abstractions;
|
|
||||||
using CringeLauncher.Utils;
|
using CringeLauncher.Utils;
|
||||||
using CringePlugins.Config;
|
using CringePlugins.Config;
|
||||||
using CringePlugins.Loader;
|
using CringePlugins.Loader;
|
||||||
@@ -25,6 +20,12 @@ using Sandbox.Game;
|
|||||||
using SpaceEngineers.Game;
|
using SpaceEngineers.Game;
|
||||||
using SpaceEngineers.Game.Achievements;
|
using SpaceEngineers.Game.Achievements;
|
||||||
using SpaceEngineers.Game.GUI;
|
using SpaceEngineers.Game.GUI;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using System.Text.Json;
|
||||||
using Velopack;
|
using Velopack;
|
||||||
using VRage;
|
using VRage;
|
||||||
using VRage.Audio;
|
using VRage.Audio;
|
||||||
@@ -81,6 +82,8 @@ public class Launcher : ICorePlugin
|
|||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
CheckUpdates(args, logger).GetAwaiter().GetResult();
|
CheckUpdates(args, logger).GetAwaiter().GetResult();
|
||||||
|
#else
|
||||||
|
logger.Info("Updates disabled: {Flag}", CheckUpdatesDisabledAsync(logger).GetAwaiter().GetResult());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// hook up steam as we ship it inside base context as an override
|
// hook up steam as we ship it inside base context as an override
|
||||||
@@ -222,9 +225,39 @@ public class Launcher : ICorePlugin
|
|||||||
return MyVRage.Platform.Windows.Window;
|
return MyVRage.Platform.Windows.Window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> CheckUpdatesDisabledAsync(Logger logger)
|
||||||
|
{
|
||||||
|
var path = Path.Join(_configDir.FullName, "launcher.json");
|
||||||
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var stream = File.OpenRead(path);
|
||||||
|
|
||||||
|
var conf = await JsonSerializer.DeserializeAsync<LauncherConfig>(stream, ConfigHandler.SerializerOptions);
|
||||||
|
|
||||||
|
return conf?.DisableLauncherUpdates ?? false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.Error(ex, "Error reading launcher config");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task CheckUpdates(string[] args, Logger logger)
|
private async Task CheckUpdates(string[] args, Logger logger)
|
||||||
{
|
{
|
||||||
|
if (await CheckUpdatesDisabledAsync(logger))
|
||||||
|
{
|
||||||
|
logger.Warn("Updates Disabled (may break from keen update)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
logger.Info("Checking for updates...");
|
logger.Info("Checking for updates...");
|
||||||
|
|
||||||
var mgr = new UpdateManager("https://dl.zznty.ru/CringeLauncher/");
|
var mgr = new UpdateManager("https://dl.zznty.ru/CringeLauncher/");
|
||||||
|
|
||||||
// check for new version
|
// check for new version
|
||||||
@@ -297,7 +330,7 @@ public class Launcher : ICorePlugin
|
|||||||
"AKGM16qoFtct0IIIA8RCqEIYG4d4gXPPDNpzGuvlhLA", "24b1cd652a18461fa9b3d533ac8d6b5b",
|
"AKGM16qoFtct0IIIA8RCqEIYG4d4gXPPDNpzGuvlhLA", "24b1cd652a18461fa9b3d533ac8d6b5b",
|
||||||
"1958fe26c66d4151a327ec162e4d49c8", "07c169b3b641401496d352cad1c905d6",
|
"1958fe26c66d4151a327ec162e4d49c8", "07c169b3b641401496d352cad1c905d6",
|
||||||
"https://retail.epicgames.com/", EosService.CreatePlatform(),
|
"https://retail.epicgames.com/", EosService.CreatePlatform(),
|
||||||
MyPlatformGameSettings.VERBOSE_NETWORK_LOGGING, ArraySegment<string>.Empty, aggregator,
|
MyPlatformGameSettings.VERBOSE_NETWORK_LOGGING, [], aggregator,
|
||||||
MyMultiplayer.Channels);
|
MyMultiplayer.Channels);
|
||||||
|
|
||||||
MyServiceManager.Instance.AddService<IMyServerDiscovery>(aggregator);
|
MyServiceManager.Instance.AddService<IMyServerDiscovery>(aggregator);
|
||||||
|
@@ -17,13 +17,13 @@ public static class EosInitPatch
|
|||||||
|
|
||||||
var stIndex = ins.FindIndex(b => b.opcode == OpCodes.Stloc_1);
|
var stIndex = ins.FindIndex(b => b.opcode == OpCodes.Stloc_1);
|
||||||
|
|
||||||
ins.InsertRange(stIndex, new []
|
ins.InsertRange(stIndex,
|
||||||
{
|
[
|
||||||
new CodeInstruction(OpCodes.Dup),
|
new CodeInstruction(OpCodes.Dup),
|
||||||
new(OpCodes.Ldc_I4_2), // PlatformFlags.DisableOverlay
|
new(OpCodes.Ldc_I4_2), // PlatformFlags.DisableOverlay
|
||||||
new(OpCodes.Conv_I8),
|
new(OpCodes.Conv_I8),
|
||||||
CodeInstruction.Call("Epic.OnlineServices.Platform.Options:set_Flags"),
|
CodeInstruction.Call("Epic.OnlineServices.Platform.Options:set_Flags"),
|
||||||
});
|
]);
|
||||||
|
|
||||||
return ins;
|
return ins;
|
||||||
}
|
}
|
||||||
|
@@ -42,16 +42,19 @@ public static class IntrospectionPatches
|
|||||||
//mods need to look for specific derived types
|
//mods need to look for specific derived types
|
||||||
Debug.WriteLine($"Getting special types for {__instance.FullName}");
|
Debug.WriteLine($"Getting special types for {__instance.FullName}");
|
||||||
var module = __instance.GetMainModule();
|
var module = __instance.GetMainModule();
|
||||||
__result = IntrospectionContext.Global.CollectDerivedTypes<MyObjectBuilder_Base>(module)
|
__result =
|
||||||
.Concat(IntrospectionContext.Global.CollectDerivedTypes<MyStatLogic>(module))
|
[
|
||||||
.Concat(IntrospectionContext.Global.CollectAttributedTypes<MyObjectBuilderDefinitionAttribute>(module))
|
.. IntrospectionContext.Global.CollectDerivedTypes<MyObjectBuilder_Base>(module)
|
||||||
.Concat(IntrospectionContext.Global.CollectDerivedTypes<MyComponentBase>(module))
|
,
|
||||||
.Concat(IntrospectionContext.Global.CollectAttributedTypes<MyComponentBuilderAttribute>(module))
|
.. IntrospectionContext.Global.CollectDerivedTypes<MyStatLogic>(module),
|
||||||
.Concat(IntrospectionContext.Global.CollectDerivedTypes<IMyTextSurfaceScript>(module))
|
.. IntrospectionContext.Global.CollectAttributedTypes<MyObjectBuilderDefinitionAttribute>(module),
|
||||||
.Concat(IntrospectionContext.Global.CollectDerivedTypes<IMyUseObject>(module))
|
.. IntrospectionContext.Global.CollectDerivedTypes<MyComponentBase>(module),
|
||||||
.Concat(IntrospectionContext.Global.CollectDerivedTypes<IMyHudStat>(module))
|
.. IntrospectionContext.Global.CollectAttributedTypes<MyComponentBuilderAttribute>(module),
|
||||||
.Concat(IntrospectionContext.Global.CollectAttributedTypes<MySessionComponentDescriptor>(module))
|
.. IntrospectionContext.Global.CollectDerivedTypes<IMyTextSurfaceScript>(module),
|
||||||
.ToArray();
|
.. IntrospectionContext.Global.CollectDerivedTypes<IMyUseObject>(module),
|
||||||
|
.. IntrospectionContext.Global.CollectDerivedTypes<IMyHudStat>(module),
|
||||||
|
.. IntrospectionContext.Global.CollectAttributedTypes<MySessionComponentDescriptor>(module),
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -76,8 +79,7 @@ public static class IntrospectionPatches
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static classes are abstract
|
// static classes are abstract
|
||||||
__result = IntrospectionContext.Global.CollectAttributedTypes<HarmonyAttribute>(assembly.GetMainModule(), true)
|
__result = [.. IntrospectionContext.Global.CollectAttributedTypes<HarmonyAttribute>(assembly.GetMainModule(), true)];
|
||||||
.ToArray();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ public static class WhitelistAllowPatch
|
|||||||
private static void Prefix(ref MemberInfo[] members)
|
private static void Prefix(ref MemberInfo[] members)
|
||||||
{
|
{
|
||||||
if (members.Any(b => b is null))
|
if (members.Any(b => b is null))
|
||||||
members = members.Where(b => b is { }).ToArray();
|
members = [.. members.Where(b => b is { })];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Exception? Finalizer(Exception __exception)
|
private static Exception? Finalizer(Exception __exception)
|
||||||
|
@@ -16,20 +16,20 @@ public static class XmlRootWriterPatch
|
|||||||
b.opcode == OpCodes.Ldstr && b.operand is "xsi:type");
|
b.opcode == OpCodes.Ldstr && b.operand is "xsi:type");
|
||||||
ins[index].operand = "xsi";
|
ins[index].operand = "xsi";
|
||||||
|
|
||||||
ins.InsertRange(index + 1, new[]
|
ins.InsertRange(index + 1,
|
||||||
{
|
[
|
||||||
new CodeInstruction(OpCodes.Ldstr, "type"),
|
new CodeInstruction(OpCodes.Ldstr, "type"),
|
||||||
new CodeInstruction(OpCodes.Ldstr, "http://www.w3.org/2001/XMLSchema-instance")
|
new CodeInstruction(OpCodes.Ldstr, "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
});
|
]);
|
||||||
|
|
||||||
var instruction = ins[ins.FindIndex(b => b.opcode == OpCodes.Callvirt)];
|
var instruction = ins[ins.FindIndex(b => b.opcode == OpCodes.Callvirt)];
|
||||||
instruction.operand = AccessTools.Method(typeof(XmlWriter), "WriteAttributeString", new[]
|
instruction.operand = AccessTools.Method(typeof(XmlWriter), "WriteAttributeString",
|
||||||
{
|
[
|
||||||
typeof(string),
|
typeof(string),
|
||||||
typeof(string),
|
typeof(string),
|
||||||
typeof(string),
|
typeof(string),
|
||||||
typeof(string)
|
typeof(string)
|
||||||
});
|
]);
|
||||||
|
|
||||||
return ins;
|
return ins;
|
||||||
}
|
}
|
||||||
|
@@ -9,16 +9,18 @@ namespace CringePlugins.Config;
|
|||||||
|
|
||||||
public sealed class ConfigHandler
|
public sealed class ConfigHandler
|
||||||
{
|
{
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
public static readonly JsonSerializerOptions SerializerOptions = new(NuGetClient.SerializerOptions)
|
||||||
|
|
||||||
private readonly DirectoryInfo _configDirectory;
|
|
||||||
private readonly JsonSerializerOptions _serializerOptions = new(NuGetClient.SerializerOptions)
|
|
||||||
{
|
{
|
||||||
WriteIndented = true,
|
WriteIndented = true,
|
||||||
AllowTrailingCommas = true,
|
AllowTrailingCommas = true,
|
||||||
ReadCommentHandling = JsonCommentHandling.Skip
|
ReadCommentHandling = JsonCommentHandling.Skip
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
private readonly DirectoryInfo _configDirectory;
|
||||||
|
|
||||||
|
|
||||||
private readonly EvaluationOptions _evaluationOptions = new()
|
private readonly EvaluationOptions _evaluationOptions = new()
|
||||||
{
|
{
|
||||||
OutputFormat = OutputFormat.List,
|
OutputFormat = OutputFormat.List,
|
||||||
@@ -67,7 +69,7 @@ public sealed class ConfigHandler
|
|||||||
T instance;
|
T instance;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
instance = jsonNode.Deserialize<T>(_serializerOptions)!;
|
instance = jsonNode.Deserialize<T>(SerializerOptions)!;
|
||||||
}
|
}
|
||||||
catch (JsonException e)
|
catch (JsonException e)
|
||||||
{
|
{
|
||||||
@@ -84,7 +86,7 @@ public sealed class ConfigHandler
|
|||||||
{
|
{
|
||||||
var spec = IConfigurationSpecProvider.FromType(typeof(T));
|
var spec = IConfigurationSpecProvider.FromType(typeof(T));
|
||||||
|
|
||||||
var jsonNode = JsonSerializer.SerializeToNode(newValue, _serializerOptions)!;
|
var jsonNode = JsonSerializer.SerializeToNode(newValue, SerializerOptions)!;
|
||||||
|
|
||||||
if (spec != null && !TryValidate(name, spec, jsonNode))
|
if (spec != null && !TryValidate(name, spec, jsonNode))
|
||||||
throw new JsonException($"Supplied config value for {name} is invalid");
|
throw new JsonException($"Supplied config value for {name} is invalid");
|
||||||
@@ -96,7 +98,7 @@ public sealed class ConfigHandler
|
|||||||
{
|
{
|
||||||
Indented = true
|
Indented = true
|
||||||
});
|
});
|
||||||
jsonNode.WriteTo(writer, _serializerOptions);
|
jsonNode.WriteTo(writer, SerializerOptions);
|
||||||
|
|
||||||
ConfigReloaded?.Invoke(this, new ConfigValue<T>(name, newValue));
|
ConfigReloaded?.Invoke(this, new ConfigValue<T>(name, newValue));
|
||||||
}
|
}
|
||||||
|
5
CringePlugins/Config/LauncherConfig.cs
Normal file
5
CringePlugins/Config/LauncherConfig.cs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
namespace CringePlugins.Config;
|
||||||
|
public sealed record LauncherConfig(bool DisableLauncherUpdates, bool DisablePluginUpdates)
|
||||||
|
{
|
||||||
|
public static LauncherConfig Default => new(false, false);
|
||||||
|
}
|
@@ -28,6 +28,7 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
private readonly NuGetRuntimeFramework _runtimeFramework = new(NuGetFramework.ParseFolder("net9.0-windows10.0.19041.0"), RuntimeInformation.RuntimeIdentifier);
|
private readonly NuGetRuntimeFramework _runtimeFramework = new(NuGetFramework.ParseFolder("net9.0-windows10.0.19041.0"), RuntimeInformation.RuntimeIdentifier);
|
||||||
|
|
||||||
private ConfigReference<PackagesConfig>? _configReference;
|
private ConfigReference<PackagesConfig>? _configReference;
|
||||||
|
private ConfigReference<LauncherConfig>? _launcherConfig;
|
||||||
|
|
||||||
public async ValueTask Load(ISplashProgress progress)
|
public async ValueTask Load(ISplashProgress progress)
|
||||||
{
|
{
|
||||||
@@ -40,7 +41,9 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
progress.Report("Loading config");
|
progress.Report("Loading config");
|
||||||
|
|
||||||
_configReference = configHandler.RegisterConfig("packages", PackagesConfig.Default);
|
_configReference = configHandler.RegisterConfig("packages", PackagesConfig.Default);
|
||||||
|
_launcherConfig = configHandler.RegisterConfig("launcher", LauncherConfig.Default);
|
||||||
var packagesConfig = _configReference.Value;
|
var packagesConfig = _configReference.Value;
|
||||||
|
var launcherConfig = _launcherConfig.Value;
|
||||||
|
|
||||||
progress.Report("Resolving packages");
|
progress.Report("Resolving packages");
|
||||||
|
|
||||||
@@ -48,12 +51,14 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
// TODO take into account the target framework runtime identifier
|
// TODO take into account the target framework runtime identifier
|
||||||
var resolver = new PackageResolver(_runtimeFramework.Framework, packagesConfig.Packages, sourceMapping);
|
var resolver = new PackageResolver(_runtimeFramework.Framework, packagesConfig.Packages, sourceMapping);
|
||||||
|
|
||||||
var packages = await resolver.ResolveAsync();
|
var cacheDir = _dir.CreateSubdirectory("cache");
|
||||||
|
|
||||||
|
var packages = await resolver.ResolveAsync(cacheDir, launcherConfig.DisablePluginUpdates);
|
||||||
|
|
||||||
progress.Report("Downloading packages");
|
progress.Report("Downloading packages");
|
||||||
|
|
||||||
var builtInPackages = await BuiltInPackages.GetPackagesAsync(_runtimeFramework);
|
var builtInPackages = await BuiltInPackages.GetPackagesAsync(_runtimeFramework);
|
||||||
var cachedPackages = await resolver.DownloadPackagesAsync(_dir.CreateSubdirectory("cache"), packages, builtInPackages.Keys.ToHashSet(), progress);
|
var cachedPackages = await PackageResolver.DownloadPackagesAsync(cacheDir, packages, builtInPackages.Keys.ToHashSet(), progress);
|
||||||
|
|
||||||
progress.Report("Loading plugins");
|
progress.Report("Loading plugins");
|
||||||
|
|
||||||
@@ -62,7 +67,7 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
|
|
||||||
await LoadPlugins(cachedPackages, sourceMapping, packagesConfig, builtInPackages);
|
await LoadPlugins(cachedPackages, sourceMapping, packagesConfig, builtInPackages);
|
||||||
|
|
||||||
RenderHandler.Current.RegisterComponent(new PluginListComponent(_configReference, sourceMapping, MyFileSystem.ExePath, _plugins));
|
RenderHandler.Current.RegisterComponent(new PluginListComponent(_configReference, _launcherConfig, sourceMapping, MyFileSystem.ExePath, _plugins));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterLifetime()
|
public void RegisterLifetime()
|
||||||
@@ -105,9 +110,9 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
{
|
{
|
||||||
if (builtInPackages.ContainsKey(package.Package.Id)) continue;
|
if (builtInPackages.ContainsKey(package.Package.Id)) continue;
|
||||||
|
|
||||||
var client = await sourceMapping.GetClientAsync(package.Package.Id);
|
var packageClient = await sourceMapping.GetClientAsync(package.Package.Id);
|
||||||
|
|
||||||
if (client == null)
|
if (packageClient == null)
|
||||||
{
|
{
|
||||||
Log.Warn("Client not found for {Package}", package.Package.Id);
|
Log.Warn("Client not found for {Package}", package.Package.Id);
|
||||||
continue;
|
continue;
|
||||||
@@ -133,7 +138,7 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceName = packagesConfig.Sources.First(b => b.Url == client.ToString()).Name;
|
var sourceName = packagesConfig.Sources.First(b => b.Url == packageClient.ToString()).Name;
|
||||||
LoadComponent(plugins, Path.Join(dir, $"{package.Package.Id}.dll"),
|
LoadComponent(plugins, Path.Join(dir, $"{package.Package.Id}.dll"),
|
||||||
new(package.Package.Id, package.Package.Version, sourceName));
|
new(package.Package.Id, package.Package.Version, sourceName));
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,17 @@
|
|||||||
using System.Collections.Immutable;
|
using NLog;
|
||||||
using System.IO.Compression;
|
|
||||||
using NLog;
|
|
||||||
using NuGet;
|
using NuGet;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
using NuGet.Models;
|
using NuGet.Models;
|
||||||
using NuGet.Versioning;
|
using NuGet.Versioning;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
namespace CringePlugins.Resolver;
|
namespace CringePlugins.Resolver;
|
||||||
|
|
||||||
public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<PackageReference> references, PackageSourceMapping packageSources)
|
public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<PackageReference> references, PackageSourceMapping packageSources)
|
||||||
{
|
{
|
||||||
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
||||||
public async Task<ImmutableSortedSet<ResolvedPackage>> ResolveAsync()
|
public async Task<ImmutableSortedSet<ResolvedPackage>> ResolveAsync(DirectoryInfo baseDir, bool disableUpdates)
|
||||||
{
|
{
|
||||||
var order = 0;
|
var order = 0;
|
||||||
var packages = new Dictionary<Package, CatalogEntry>();
|
var packages = new Dictionary<Package, CatalogEntry>();
|
||||||
@@ -39,7 +39,24 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
page.Items!.Where(b => b.CatalogEntry.PackageTypes is ["CringePlugin"]))
|
page.Items!.Where(b => b.CatalogEntry.PackageTypes is ["CringePlugin"]))
|
||||||
.ToImmutableDictionary(b => b.CatalogEntry.Version);
|
.ToImmutableDictionary(b => b.CatalogEntry.Version);
|
||||||
|
|
||||||
var version = items.Values.Select(b => b.CatalogEntry.Version).OrderDescending().First(b => reference.Range.Satisfies(b));
|
var version = items.Values.Select(b => b.CatalogEntry.Version).OrderDescending().First(reference.Range.Satisfies);
|
||||||
|
|
||||||
|
if (disableUpdates)
|
||||||
|
{
|
||||||
|
if (GetLatestInstalledVersion(baseDir, reference.Id, reference.Range) is { } installedVersion && items.ContainsKey(installedVersion))
|
||||||
|
{
|
||||||
|
if (installedVersion < version)
|
||||||
|
{
|
||||||
|
Log.Warn("Using outdated version of package {Package} {InstalledVersion} instead of {AvailableVersion} due to updates being disabled",
|
||||||
|
reference.Id, installedVersion, version);
|
||||||
|
}
|
||||||
|
version = installedVersion;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Warn("No valid installed version found for package {Package}", reference.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (version is null)
|
if (version is null)
|
||||||
throw new NotSupportedException($"Unable to find version for package {reference.Id}");
|
throw new NotSupportedException($"Unable to find version for package {reference.Id}");
|
||||||
@@ -118,6 +135,20 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
if (version is null)
|
if (version is null)
|
||||||
throw new NotSupportedException($"Unable to find version for package {id} as dependency of {package.Package}");
|
throw new NotSupportedException($"Unable to find version for package {id} as dependency of {package.Package}");
|
||||||
|
|
||||||
|
if (disableUpdates)
|
||||||
|
{
|
||||||
|
if (GetLatestInstalledVersion(baseDir, id, versionRange) is { } installedVersion && items.ContainsKey(installedVersion))
|
||||||
|
{
|
||||||
|
if (installedVersion < version)
|
||||||
|
{
|
||||||
|
Log.Warn("Using outdated version of dependency package {Package} {InstalledVersion} instead of {AvailableVersion} due to updates being disabled",
|
||||||
|
id, installedVersion, version);
|
||||||
|
}
|
||||||
|
version = installedVersion;
|
||||||
|
}
|
||||||
|
//todo: warnings here? we'd need to check against builtin packages
|
||||||
|
}
|
||||||
|
|
||||||
var catalogEntry = items[version].CatalogEntry;
|
var catalogEntry = items[version].CatalogEntry;
|
||||||
|
|
||||||
var dependencyPackage = new Package(i, id, version);
|
var dependencyPackage = new Package(i, id, version);
|
||||||
@@ -182,7 +213,26 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
return set.ToImmutable();
|
return set.ToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ImmutableHashSet<CachedPackage>> DownloadPackagesAsync(DirectoryInfo baseDirectory,
|
private static NuGetVersion? GetLatestInstalledVersion(DirectoryInfo baseDirectory, string id, VersionRange range)
|
||||||
|
{
|
||||||
|
var dir = new DirectoryInfo(Path.Join(baseDirectory.FullName, id));
|
||||||
|
|
||||||
|
if (!dir.Exists)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
NuGetVersion? maxVersion = null;
|
||||||
|
foreach (var subdir in dir.GetDirectories())
|
||||||
|
{
|
||||||
|
if (NuGetVersion.TryParse(subdir.Name, out var version) && range.Satisfies(version) && (maxVersion == null || version > maxVersion))
|
||||||
|
{
|
||||||
|
maxVersion = version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<ImmutableHashSet<CachedPackage>> DownloadPackagesAsync(DirectoryInfo baseDirectory,
|
||||||
IReadOnlySet<ResolvedPackage> resolvedPackages, IReadOnlySet<string>? ignorePackages = null, IProgress<float>? progress = null)
|
IReadOnlySet<ResolvedPackage> resolvedPackages, IReadOnlySet<string>? ignorePackages = null, IProgress<float>? progress = null)
|
||||||
{
|
{
|
||||||
var packages = ImmutableHashSet<CachedPackage>.Empty.ToBuilder();
|
var packages = ImmutableHashSet<CachedPackage>.Empty.ToBuilder();
|
||||||
@@ -206,7 +256,7 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
var client = (package as RemoteDependencyPackage)?.Client ?? ((RemotePackage)package).Client;
|
var client = (package as RemoteDependencyPackage)?.Client ?? ((RemotePackage)package).Client;
|
||||||
|
|
||||||
await using var stream = await client.GetPackageContentStreamAsync(package.Package.Id, package.Package.Version);
|
await using var stream = await client.GetPackageContentStreamAsync(package.Package.Id, package.Package.Version);
|
||||||
using var memStream = new MemoryStream();
|
await using var memStream = new MemoryStream();
|
||||||
await stream.CopyToAsync(memStream);
|
await stream.CopyToAsync(memStream);
|
||||||
memStream.Position = 0;
|
memStream.Position = 0;
|
||||||
using var archive = new ZipArchive(memStream, ZipArchiveMode.Read);
|
using var archive = new ZipArchive(memStream, ZipArchiveMode.Read);
|
||||||
|
@@ -25,7 +25,6 @@ public sealed class NotificationsComponent : IRenderComponent
|
|||||||
var lastY = _notificationSize.Y;
|
var lastY = _notificationSize.Y;
|
||||||
var viewportPos = ImGui.GetMainViewport().Pos;
|
var viewportPos = ImGui.GetMainViewport().Pos;
|
||||||
|
|
||||||
|
|
||||||
//todo: consider adding a limit to the number of messages that can be displayed at once
|
//todo: consider adding a limit to the number of messages that can be displayed at once
|
||||||
for (var i = Notifications.Count; i-- > 0;)
|
for (var i = Notifications.Count; i-- > 0;)
|
||||||
{
|
{
|
||||||
|
@@ -38,10 +38,13 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
private int _selectedProfile = -1;
|
private int _selectedProfile = -1;
|
||||||
private ImmutableArray<Profile> _profiles;
|
private ImmutableArray<Profile> _profiles;
|
||||||
|
|
||||||
|
private bool _disableUpdates;
|
||||||
|
private bool _disablePluginUpdates;
|
||||||
|
|
||||||
private bool _changed;
|
private bool _restartRequired;
|
||||||
private bool _open = true;
|
private bool _open = true;
|
||||||
private readonly ConfigReference<PackagesConfig> _packagesConfig;
|
private readonly ConfigReference<PackagesConfig> _packagesConfig;
|
||||||
|
private readonly ConfigReference<LauncherConfig> _launcherConfig;
|
||||||
private readonly PackageSourceMapping _sourceMapping;
|
private readonly PackageSourceMapping _sourceMapping;
|
||||||
private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web);
|
private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web);
|
||||||
private ImmutableHashSet<PackageSource>? _selectedSources;
|
private ImmutableHashSet<PackageSource>? _selectedSources;
|
||||||
@@ -51,10 +54,11 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
private (PackageSource source, int index)? _selectedSource;
|
private (PackageSource source, int index)? _selectedSource;
|
||||||
private readonly IImGuiImageService _imageService = GameServicesExtension.GameServices.GetRequiredService<IImGuiImageService>();
|
private readonly IImGuiImageService _imageService = GameServicesExtension.GameServices.GetRequiredService<IImGuiImageService>();
|
||||||
|
|
||||||
public PluginListComponent(ConfigReference<PackagesConfig> packagesConfig, PackageSourceMapping sourceMapping, string gameFolder,
|
public PluginListComponent(ConfigReference<PackagesConfig> packagesConfig, ConfigReference<LauncherConfig> launcherConfig,
|
||||||
ImmutableArray<PluginInstance> plugins)
|
PackageSourceMapping sourceMapping, string gameFolder, ImmutableArray<PluginInstance> plugins)
|
||||||
{
|
{
|
||||||
_packagesConfig = packagesConfig;
|
_packagesConfig = packagesConfig;
|
||||||
|
_launcherConfig = launcherConfig;
|
||||||
_sourceMapping = sourceMapping;
|
_sourceMapping = sourceMapping;
|
||||||
_gameFolder = gameFolder;
|
_gameFolder = gameFolder;
|
||||||
_plugins = plugins;
|
_plugins = plugins;
|
||||||
@@ -62,6 +66,9 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
StringComparer.OrdinalIgnoreCase);
|
StringComparer.OrdinalIgnoreCase);
|
||||||
_profiles = packagesConfig.Value.Profiles;
|
_profiles = packagesConfig.Value.Profiles;
|
||||||
|
|
||||||
|
_disablePluginUpdates = _launcherConfig.Value.DisablePluginUpdates;
|
||||||
|
_disableUpdates = _launcherConfig.Value.DisableLauncherUpdates;
|
||||||
|
|
||||||
MyScreenManager.ScreenAdded += ScreenChanged;
|
MyScreenManager.ScreenAdded += ScreenChanged;
|
||||||
MyScreenManager.ScreenRemoved += ScreenChanged;
|
MyScreenManager.ScreenRemoved += ScreenChanged;
|
||||||
}
|
}
|
||||||
@@ -83,9 +90,9 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_changed)
|
if (_restartRequired)
|
||||||
{
|
{
|
||||||
TextDisabled("Changes would be applied on the next restart");
|
TextDisabled("Changes will be applied on the next restart");
|
||||||
SameLine();
|
SameLine();
|
||||||
if (Button("Restart Now"))
|
if (Button("Restart Now"))
|
||||||
{
|
{
|
||||||
@@ -279,6 +286,14 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
|
|
||||||
if (BeginTabItem("Settings"))
|
if (BeginTabItem("Settings"))
|
||||||
{
|
{
|
||||||
|
if (Checkbox("Disable Plugin Updates", ref _disablePluginUpdates))
|
||||||
|
{
|
||||||
|
_launcherConfig.Value = _launcherConfig.Value with { DisablePluginUpdates = _disablePluginUpdates };
|
||||||
|
}
|
||||||
|
if (Checkbox("Disable Launcher Updates", ref _disableUpdates))
|
||||||
|
{
|
||||||
|
_launcherConfig.Value = _launcherConfig.Value with { DisableLauncherUpdates = _disableUpdates };
|
||||||
|
}
|
||||||
var oldConfigPath = Path.Join(_gameFolder, "Plugins", "config.xml");
|
var oldConfigPath = Path.Join(_gameFolder, "Plugins", "config.xml");
|
||||||
if (File.Exists(oldConfigPath))
|
if (File.Exists(oldConfigPath))
|
||||||
{
|
{
|
||||||
@@ -299,6 +314,8 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
|
|
||||||
var hasModLodaer = _packages.ContainsKey("Plugin.ClientModLoader");
|
var hasModLodaer = _packages.ContainsKey("Plugin.ClientModLoader");
|
||||||
|
|
||||||
|
SameLine();
|
||||||
|
|
||||||
if (!hasModLodaer)
|
if (!hasModLodaer)
|
||||||
BeginDisabled();
|
BeginDisabled();
|
||||||
|
|
||||||
@@ -310,11 +327,12 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
if (configSerializer.Deserialize(fs) is PluginLoaderConfig plConfig)
|
if (configSerializer.Deserialize(fs) is PluginLoaderConfig plConfig)
|
||||||
{
|
{
|
||||||
var dir = new DirectoryInfo(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
var dir = new DirectoryInfo(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
"CringeLauncher"));
|
"config", "CringeLauncher"));
|
||||||
var file = Path.Join(dir.FullName, "mods.json");
|
var file = Path.Join(dir.FullName, "mods.json");
|
||||||
|
|
||||||
using var modsFile = File.Create(file);
|
using var modsFile = File.Create(file);
|
||||||
JsonSerializer.Serialize(modsFile, plConfig.GetMods(), _serializerOptions);
|
JsonSerializer.Serialize(modsFile, plConfig.GetMods(), _serializerOptions);
|
||||||
|
_restartRequired = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,7 +553,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
{
|
{
|
||||||
_selectedSources = selected
|
_selectedSources = selected
|
||||||
? (_selectedSources?.Count ?? 0) + 1 == _packagesConfig.Value.Sources.Length ? null : _selectedSources?.Add(source)
|
? (_selectedSources?.Count ?? 0) + 1 == _packagesConfig.Value.Sources.Length ? null : _selectedSources?.Add(source)
|
||||||
: (_selectedSources ?? _packagesConfig.Value.Sources.ToImmutableHashSet()).Remove(source);
|
: (_selectedSources ?? [.. _packagesConfig.Value.Sources]).Remove(source);
|
||||||
|
|
||||||
_searchTask = RefreshAsync();
|
_searchTask = RefreshAsync();
|
||||||
EndCombo();
|
EndCombo();
|
||||||
@@ -733,7 +751,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
|
|
||||||
await foreach (var source in _sourceMapping)
|
await foreach (var source in _sourceMapping)
|
||||||
{
|
{
|
||||||
if (source == null || _selectedSources is not null && _selectedSources.All(b => b.Url != source.ToString()))
|
if (source == null || _selectedSources?.All(b => b.Url != source.ToString()) == true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -758,7 +776,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
Packages = [.. _packages.Select(b => new PackageReference(b.Key, b.Value))]
|
Packages = [.. _packages.Select(b => new PackageReference(b.Key, b.Value))]
|
||||||
} : _packagesConfig;
|
} : _packagesConfig;
|
||||||
|
|
||||||
_changed = true;
|
_restartRequired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe int ComparePlugins(PluginInstance x, PluginInstance y, ImGuiTableSortSpecsPtr specs)
|
private static unsafe int ComparePlugins(PluginInstance x, PluginInstance y, ImGuiTableSortSpecsPtr specs)
|
||||||
|
@@ -156,7 +156,7 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
|
|||||||
|
|
||||||
{
|
{
|
||||||
await using var stream = await client.GetPackageContentStreamAsync(entry.Id, entry.Version);
|
await using var stream = await client.GetPackageContentStreamAsync(entry.Id, entry.Version);
|
||||||
using var memStream = new MemoryStream();
|
await using var memStream = new MemoryStream();
|
||||||
await stream.CopyToAsync(memStream);
|
await stream.CopyToAsync(memStream);
|
||||||
memStream.Position = 0;
|
memStream.Position = 0;
|
||||||
using var archive = new ZipArchive(memStream, ZipArchiveMode.Read);
|
using var archive = new ZipArchive(memStream, ZipArchiveMode.Read);
|
||||||
|
@@ -7,7 +7,7 @@ using NuGet.Versioning;
|
|||||||
|
|
||||||
namespace NuGet;
|
namespace NuGet;
|
||||||
|
|
||||||
public class NuGetClient
|
public sealed class NuGetClient
|
||||||
{
|
{
|
||||||
private readonly Uri _index;
|
private readonly Uri _index;
|
||||||
private readonly HttpClient _client;
|
private readonly HttpClient _client;
|
||||||
|
Reference in New Issue
Block a user