diff --git a/CringeBootstrap/packages.lock.json b/CringeBootstrap/packages.lock.json
index 4af8f17..873aa45 100644
--- a/CringeBootstrap/packages.lock.json
+++ b/CringeBootstrap/packages.lock.json
@@ -18,18 +18,10 @@
"NuGet.Versioning": "6.12.1"
}
},
- "Basic.Reference.Assemblies.Net80": {
+ "Basic.Reference.Assemblies.Net90": {
"type": "Transitive",
"resolved": "1.7.9",
- "contentHash": "1wbS9ZJLFVrKD2jqv27gekIrpjpLffR9sitLQh5drWoG9KbyR/CgrAhw5I0c8Eq3zFMOToCmrpZi3VpRoInCgg==",
- "dependencies": {
- "Microsoft.CodeAnalysis.Common": "4.11.0"
- }
- },
- "Basic.Reference.Assemblies.Net80Windows": {
- "type": "Transitive",
- "resolved": "1.7.9",
- "contentHash": "98GFm8MC+pv37rTHaxBm5KFucqdJj0jK0XRHSGt2sXK9HNqtGImIFCFahxjUzskQjiUkPAzVhTou2OYZOuhhEg==",
+ "contentHash": "9CUkU6Z17tJL/cQc6FeZL0qfQf4CBaNpSBqFL6CTmrIC8827x7NEPyNq/inZA/r6Y5ziWo2Yd8caMxLPqDUpeA==",
"dependencies": {
"Microsoft.CodeAnalysis.Common": "4.11.0"
}
@@ -70,8 +62,8 @@
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
- "resolved": "4.11.0",
- "contentHash": "djf8ujmqYImFgB04UGtcsEhHrzVqzHowS+EEl/Yunc5LdrYrZhGBWUTXoCF0NzYXJxtfuD+UVQarWpvrNc94Qg==",
+ "resolved": "4.12.0",
+ "contentHash": "c1kNYihL2gdcuU1dqm8R8YeA4YkB43TpU3pa2r66Uooh6AAhRtENzj9A4Kj0a+H8JDDyuTjNZql9XlVUzV+UjA==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "3.3.4",
"System.Collections.Immutable": "8.0.0",
@@ -80,11 +72,11 @@
},
"Microsoft.CodeAnalysis.CSharp": {
"type": "Transitive",
- "resolved": "4.11.0",
- "contentHash": "6XYi2EusI8JT4y2l/F3VVVS+ISoIX9nqHsZRaG6W5aFeJ5BEuBosHfT/ABb73FN0RZ1Z3cj2j7cL28SToJPXOw==",
+ "resolved": "4.12.0",
+ "contentHash": "30vVQ1MizeC22iEdEvI2w0eTIYG43/L20yBzuQH01xKzJgHAoWehzI2F8u07o4mXh4DGMOjQF7aEm0zzvsG3Mg==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "3.3.4",
- "Microsoft.CodeAnalysis.Common": "[4.11.0]",
+ "Microsoft.CodeAnalysis.Common": "[4.12.0]",
"System.Collections.Immutable": "8.0.0",
"System.Reflection.Metadata": "8.0.0"
}
@@ -339,11 +331,10 @@
"cringelauncher": {
"type": "Project",
"dependencies": {
- "Basic.Reference.Assemblies.Net80": "[1.7.9, )",
- "Basic.Reference.Assemblies.Net80Windows": "[1.7.9, )",
+ "Basic.Reference.Assemblies.Net90": "[1.7.9, )",
"CringeBootstrap.Abstractions": "[1.0.0, )",
"CringePlugins": "[1.0.0, )",
- "Microsoft.CodeAnalysis.CSharp": "[4.11.0, )",
+ "Microsoft.CodeAnalysis.CSharp": "[4.12.0, )",
"NLog": "[5.3.4, )",
"SpaceEngineersDedicated.ReferenceAssemblies": "[1.*, )",
"Steamworks.NET": "[20.1.0, )",
diff --git a/CringeLauncher/CringeLauncher.csproj b/CringeLauncher/CringeLauncher.csproj
index 886fcaf..857630e 100644
--- a/CringeLauncher/CringeLauncher.csproj
+++ b/CringeLauncher/CringeLauncher.csproj
@@ -22,10 +22,9 @@
-
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -39,7 +38,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/CringeLauncher/packages.lock.json b/CringeLauncher/packages.lock.json
index e19b32b..1c2d8a7 100644
--- a/CringeLauncher/packages.lock.json
+++ b/CringeLauncher/packages.lock.json
@@ -2,20 +2,11 @@
"version": 1,
"dependencies": {
"net9.0-windows10.0.19041": {
- "Basic.Reference.Assemblies.Net80": {
+ "Basic.Reference.Assemblies.Net90": {
"type": "Direct",
"requested": "[1.7.9, )",
"resolved": "1.7.9",
- "contentHash": "1wbS9ZJLFVrKD2jqv27gekIrpjpLffR9sitLQh5drWoG9KbyR/CgrAhw5I0c8Eq3zFMOToCmrpZi3VpRoInCgg==",
- "dependencies": {
- "Microsoft.CodeAnalysis.Common": "4.11.0"
- }
- },
- "Basic.Reference.Assemblies.Net80Windows": {
- "type": "Direct",
- "requested": "[1.7.9, )",
- "resolved": "1.7.9",
- "contentHash": "98GFm8MC+pv37rTHaxBm5KFucqdJj0jK0XRHSGt2sXK9HNqtGImIFCFahxjUzskQjiUkPAzVhTou2OYZOuhhEg==",
+ "contentHash": "9CUkU6Z17tJL/cQc6FeZL0qfQf4CBaNpSBqFL6CTmrIC8827x7NEPyNq/inZA/r6Y5ziWo2Yd8caMxLPqDUpeA==",
"dependencies": {
"Microsoft.CodeAnalysis.Common": "4.11.0"
}
@@ -28,18 +19,18 @@
},
"Krafs.Publicizer": {
"type": "Direct",
- "requested": "[2.2.1, )",
- "resolved": "2.2.1",
- "contentHash": "QGI4nMGQbKsuFUUboixVHu4mv3lHB5RejIa7toIlzTmwLkuCYYEpUBJjmy3OpXYyj5dVSZAXVbr4oeMSloE67Q=="
+ "requested": "[2.3.0, )",
+ "resolved": "2.3.0",
+ "contentHash": "DjktTgctwxUMhMkWKrRECer3LR1lHzanCOlE4mpinAiY8SfWJq4DG/QitP5h1A+WBjyWHzQSOG+204i3VpO1FA=="
},
"Microsoft.CodeAnalysis.CSharp": {
"type": "Direct",
- "requested": "[4.11.0, )",
- "resolved": "4.11.0",
- "contentHash": "6XYi2EusI8JT4y2l/F3VVVS+ISoIX9nqHsZRaG6W5aFeJ5BEuBosHfT/ABb73FN0RZ1Z3cj2j7cL28SToJPXOw==",
+ "requested": "[4.12.0, )",
+ "resolved": "4.12.0",
+ "contentHash": "30vVQ1MizeC22iEdEvI2w0eTIYG43/L20yBzuQH01xKzJgHAoWehzI2F8u07o4mXh4DGMOjQF7aEm0zzvsG3Mg==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "3.3.4",
- "Microsoft.CodeAnalysis.Common": "[4.11.0]",
+ "Microsoft.CodeAnalysis.Common": "[4.12.0]",
"System.Collections.Immutable": "8.0.0",
"System.Reflection.Metadata": "8.0.0"
}
@@ -160,8 +151,8 @@
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
- "resolved": "4.11.0",
- "contentHash": "djf8ujmqYImFgB04UGtcsEhHrzVqzHowS+EEl/Yunc5LdrYrZhGBWUTXoCF0NzYXJxtfuD+UVQarWpvrNc94Qg==",
+ "resolved": "4.12.0",
+ "contentHash": "c1kNYihL2gdcuU1dqm8R8YeA4YkB43TpU3pa2r66Uooh6AAhRtENzj9A4Kj0a+H8JDDyuTjNZql9XlVUzV+UjA==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "3.3.4",
"System.Collections.Immutable": "8.0.0",
diff --git a/CringePlugins/CringePlugins.csproj b/CringePlugins/CringePlugins.csproj
index 22dd5ba..b880262 100644
--- a/CringePlugins/CringePlugins.csproj
+++ b/CringePlugins/CringePlugins.csproj
@@ -22,14 +22,13 @@
-
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/CringePlugins/Loader/PluginsLifetime.cs b/CringePlugins/Loader/PluginsLifetime.cs
index 75bd9b4..388a099 100644
--- a/CringePlugins/Loader/PluginsLifetime.cs
+++ b/CringePlugins/Loader/PluginsLifetime.cs
@@ -25,7 +25,7 @@ public class PluginsLifetime(string gameFolder) : ILoadingStage
private ImmutableArray _plugins = [];
private readonly DirectoryInfo _dir = Directory.CreateDirectory(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher"));
- private readonly NuGetFramework _runtimeFramework = NuGetFramework.ParseFolder("net8.0-windows10.0.19041.0");
+ private readonly NuGetFramework _runtimeFramework = NuGetFramework.ParseFolder("net9.0-windows10.0.19041.0");
public async ValueTask Load(ISplashProgress progress)
{
@@ -89,35 +89,40 @@ public class PluginsLifetime(string gameFolder) : ILoadingStage
Contexts = contextBuilder.ToImmutable();
}
- private async Task LoadPlugins(IReadOnlySet packages, PackageSourceMapping sourceMapping,
+ private async Task LoadPlugins(IReadOnlyCollection packages, PackageSourceMapping sourceMapping,
PackagesConfig packagesConfig)
{
var plugins = _plugins.ToBuilder();
- var packageVersions = BuiltInPackages.GetPackages(_runtimeFramework)
- .ToImmutableDictionary(b => b.Package.Id, b => b.Package.Version,
- StringComparer.OrdinalIgnoreCase);
-
- packageVersions = packageVersions.AddRange(packages.Select(b =>
- new KeyValuePair(b.Package.Id, b.Package.Version)));
+ var builtInPackages = BuiltInPackages.GetPackages(_runtimeFramework)
+ .ToImmutableDictionary(package => package.Package.Id);
+
+ var resolvedPackages = builtInPackages.ToDictionary();
+ foreach (var package in packages)
+ {
+ resolvedPackages.TryAdd(package.Package.Id, package);
+ }
var manifestBuilder = new DependencyManifestBuilder(_dir.CreateSubdirectory("cache"), sourceMapping,
- dependency => packageVersions.TryGetValue(dependency.Id, out var version) && version.Major != 99
- ? version
- : dependency.Range.MinVersion ?? dependency.Range.MaxVersion);
+ dependency =>
+ {
+ resolvedPackages.TryGetValue(dependency.Id, out var package);
+ return package?.Entry;
+ });
foreach (var package in packages)
{
+ if (builtInPackages.ContainsKey(package.Package.Id)) continue;
+
var dir = Path.Join(package.Directory.FullName, "lib", package.ResolvedFramework.GetShortFolderName());
var path = Path.Join(dir, $"{package.Package.Id}.deps.json");
if (!File.Exists(path))
{
- await using (var stream = File.Create(path))
- await manifestBuilder.WriteDependencyManifestAsync(stream, package.Entry, _runtimeFramework);
+ await using var stream = File.Create(path);
+ await manifestBuilder.WriteDependencyManifestAsync(stream, package.Entry, _runtimeFramework);
}
-
var client = await sourceMapping.GetClientAsync(package.Package.Id);
var sourceName = packagesConfig.Sources.First(b => b.Url == client.ToString()).Name;
LoadComponent(plugins, Path.Join(dir, $"{package.Package.Id}.dll"),
diff --git a/CringePlugins/Resolver/BuiltInPackages.cs b/CringePlugins/Resolver/BuiltInPackages.cs
index 050605d..b16e498 100644
--- a/CringePlugins/Resolver/BuiltInPackages.cs
+++ b/CringePlugins/Resolver/BuiltInPackages.cs
@@ -41,14 +41,14 @@ public static class BuiltInPackages
var version = attribute is null ? new(99, 0, 0) : NuGetVersion.Parse((string)attribute.ConstructorArguments[0].Value);
return new BuiltInSdkPackage(
- new(0, Path.GetFileNameWithoutExtension(r.FileName), version, []), runtimeFramework,
+ new(0, Path.GetFileNameWithoutExtension(r.FileName), version), runtimeFramework,
new(Path.GetFileNameWithoutExtension(r.FileName), version, [new(runtimeFramework, [])], null, []));
}
return
[
- ..Net80.ReferenceInfos.AllValues.Select(MapSdkPackage),
- ..Net80Windows.ReferenceInfos.AllValues.Select(MapSdkPackage),
+ ..Net90.ReferenceInfos.AllValues.Select(MapSdkPackage),
+ // ..Net80Windows.ReferenceInfos.AllValues.Select(MapSdkPackage),
nlog,
se,
imGui,
@@ -72,7 +72,7 @@ public static class BuiltInPackages
dependencies ??= [];
return new(
- new(0, id, version, [..dependencies.Value.Select(b => b.Id)]),
+ new(0, id, version),
runtimeFramework,
new(id, version, [
new(runtimeFramework, dependencies.Value)
diff --git a/CringePlugins/Resolver/PackageResolver.cs b/CringePlugins/Resolver/PackageResolver.cs
index 29cc0bb..7bcfb10 100644
--- a/CringePlugins/Resolver/PackageResolver.cs
+++ b/CringePlugins/Resolver/PackageResolver.cs
@@ -11,7 +11,7 @@ namespace CringePlugins.Resolver;
public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray references, PackageSourceMapping packageSources)
{
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
- public async Task> ResolveAsync()
+ public async Task> ResolveAsync()
{
var order = 0;
var packages = new SortedDictionary();
@@ -40,10 +40,12 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray.Empty.ToBuilder();
+ var set = ImmutableSortedSet.Empty.ToBuilder();
foreach (var (package, catalogEntry) in packages)
{
var client = await packageSources.GetClientAsync(package.Id);
@@ -80,6 +82,78 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray b.TargetFramework == package.ResolvedFramework)?.Dependencies ??
+ [];
+
+ foreach (var (id, versionRange) in dependencies)
+ {
+ var client = await packageSources.GetClientAsync(id);
+
+ RegistrationRoot? registrationRoot;
+
+ try
+ {
+ registrationRoot = await client.GetPackageRegistrationRootAsync(id);
+ }
+ catch (HttpRequestException ex)
+ {
+ throw new Exception($"Failed to resolve dependency {id} for {package.Package}", ex);
+ }
+
+ var items = registrationRoot.Items.SelectMany(page => page.Items!)
+ .ToImmutableDictionary(b => b.CatalogEntry.Version);
+
+ var version = items.Values.Select(b => b.CatalogEntry.Version).OrderDescending().FirstOrDefault(b => versionRange.Satisfies(b));
+
+ if (version is null)
+ throw new Exception($"Unable to find version for package {id} as dependency of {package.Package}");
+
+ var catalogEntry = items[version].CatalogEntry;
+
+ var dependencyPackage = new Package(i, id, version);
+
+ if (packages.TryGetValue(dependencyPackage, out var existingPackage))
+ {
+ if (dependencyPackage.Version < existingPackage.Version)
+ {
+ // dependency has lower version than already resolved
+ // need to check if existing fits the version range
+ // and reorder existing to ensure it's ordered before requesting package
+
+ if (!versionRange.Satisfies(existingPackage.Version))
+ throw new Exception(
+ $"Incompatible package version {dependencyPackage} (required by {package.Package}) from {existingPackage}");
+
+ if (dependencyPackage.CompareTo(existingPackage) < 0)
+ {
+ packages.Remove(dependencyPackage);
+ packages.Add(dependencyPackage, existingPackage);
+ }
+
+ continue;
+ }
+
+ throw new Exception($"Detected package downgrade from {existingPackage} to {dependencyPackage} as dependency of {package.Package}");
+ }
+
+ if (!packages.TryAdd(dependencyPackage, catalogEntry))
+ throw new Exception($"Duplicate package {dependencyPackage.Id}");
+
+ var nearestGroup = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups ?? [], runtimeFramework,
+ g => g.TargetFramework);
+
+ if (nearestGroup is null)
+ throw new Exception($"Unable to find compatible dependency group for {dependencyPackage} as dependency of {package.Package}");
+
+ set.Add(new RemoteDependencyPackage(dependencyPackage, nearestGroup.TargetFramework, client, package, catalogEntry));
+ }
+ }
return set.ToImmutable();
}
@@ -127,9 +201,40 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray Dependencies) : IComparable, IComparable
+public abstract record ResolvedPackage(Package Package, NuGetFramework ResolvedFramework, CatalogEntry Entry) : IComparable, IComparable
+{
+ public int CompareTo(ResolvedPackage? other)
+ {
+ if (ReferenceEquals(this, other)) return 0;
+ if (other is null) return 1;
+ return Package.CompareTo(other.Package);
+ }
+
+ public int CompareTo(object? obj)
+ {
+ if (obj is null) return 1;
+ if (ReferenceEquals(this, obj)) return 0;
+ return obj is ResolvedPackage other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(ResolvedPackage)}");
+ }
+
+ public override int GetHashCode() => Package.GetHashCode();
+
+ public virtual bool Equals(Package? other)
+ {
+ if (other is null) return false;
+ return Package.Equals(other);
+ }
+}
+
+public record Package(int Order, string Id, NuGetVersion Version) : IComparable, IComparable
{
public int CompareTo(Package? other)
{
diff --git a/CringePlugins/packages.lock.json b/CringePlugins/packages.lock.json
index 77c8da7..50adb13 100644
--- a/CringePlugins/packages.lock.json
+++ b/CringePlugins/packages.lock.json
@@ -2,20 +2,11 @@
"version": 1,
"dependencies": {
"net9.0-windows7.0": {
- "Basic.Reference.Assemblies.Net80": {
+ "Basic.Reference.Assemblies.Net90": {
"type": "Direct",
"requested": "[1.7.9, )",
"resolved": "1.7.9",
- "contentHash": "1wbS9ZJLFVrKD2jqv27gekIrpjpLffR9sitLQh5drWoG9KbyR/CgrAhw5I0c8Eq3zFMOToCmrpZi3VpRoInCgg==",
- "dependencies": {
- "Microsoft.CodeAnalysis.Common": "4.11.0"
- }
- },
- "Basic.Reference.Assemblies.Net80Windows": {
- "type": "Direct",
- "requested": "[1.7.9, )",
- "resolved": "1.7.9",
- "contentHash": "98GFm8MC+pv37rTHaxBm5KFucqdJj0jK0XRHSGt2sXK9HNqtGImIFCFahxjUzskQjiUkPAzVhTou2OYZOuhhEg==",
+ "contentHash": "9CUkU6Z17tJL/cQc6FeZL0qfQf4CBaNpSBqFL6CTmrIC8827x7NEPyNq/inZA/r6Y5ziWo2Yd8caMxLPqDUpeA==",
"dependencies": {
"Microsoft.CodeAnalysis.Common": "4.11.0"
}
@@ -39,9 +30,9 @@
},
"Krafs.Publicizer": {
"type": "Direct",
- "requested": "[2.2.1, )",
- "resolved": "2.2.1",
- "contentHash": "QGI4nMGQbKsuFUUboixVHu4mv3lHB5RejIa7toIlzTmwLkuCYYEpUBJjmy3OpXYyj5dVSZAXVbr4oeMSloE67Q=="
+ "requested": "[2.3.0, )",
+ "resolved": "2.3.0",
+ "contentHash": "DjktTgctwxUMhMkWKrRECer3LR1lHzanCOlE4mpinAiY8SfWJq4DG/QitP5h1A+WBjyWHzQSOG+204i3VpO1FA=="
},
"Lib.Harmony.Thin": {
"type": "Direct",
diff --git a/NuGet/Deps/DependenciesManifest.cs b/NuGet/Deps/DependenciesManifest.cs
index e45eb97..ec72de4 100644
--- a/NuGet/Deps/DependenciesManifest.cs
+++ b/NuGet/Deps/DependenciesManifest.cs
@@ -56,7 +56,7 @@ public record ManifestPackageKey(string Id, NuGetVersion Version)
public override string ToString() => $"{Id}/{Version}";
}
-public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSourceMapping packageSources, Func versionResolver)
+public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSourceMapping packageSources, Func catalogEntryResolver)
{
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
{
@@ -100,22 +100,11 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
targets.Add(new(catalogEntry.Id, catalogEntry.Version),
await MapEntryAsync(catalogEntry, nearest));
- foreach (var dependency in nearest.Dependencies ?? [])
+ foreach (var entry in (nearest.Dependencies ?? []).Select(catalogEntryResolver))
{
- var client = await packageSources.GetClientAsync(dependency.Id);
- var registrationRoot = await client.GetPackageRegistrationRootAsync(dependency.Id);
-
- var version = versionResolver(dependency)!;
- var entry = registrationRoot.Items.SelectMany(b => b.Items ?? []).FirstOrDefault(b => b.CatalogEntry.Version == version)?.CatalogEntry;
-
if (entry is null)
- {
- var (url, sleetEntry) = await client.GetPackageRegistrationAsync(dependency.Id, versionResolver(dependency)!);
-
- entry = sleetEntry;
- entry ??= await client.GetPackageCatalogEntryAsync(url);
- }
-
+ continue;
+
await MapCatalogEntryAsync(entry, targetFramework, targets);
}
}
@@ -123,8 +112,10 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
private async Task MapEntryAsync(CatalogEntry entry, DependencyGroup group)
{
var packageEntries = entry.PackageEntries ?? await GetPackageContent(entry);
-
- return new(group.Dependencies?.ToImmutableDictionary(b => b.Id, versionResolver) ?? ImmutableDictionary.Empty,
+
+ return new(
+ group.Dependencies?.ToImmutableDictionary(b => b.Id, b => catalogEntryResolver(b)!.Version) ??
+ ImmutableDictionary.Empty,
packageEntries.Where(b => b.FullName.StartsWith($"lib/{group.TargetFramework.GetShortFolderName()}/"))
.ToImmutableDictionary(b => b.FullName, _ => new RuntimeDependency()),
packageEntries.Where(b =>