diff --git a/CringeBootstrap/packages.lock.json b/CringeBootstrap/packages.lock.json
index 7e9baad..1ef9944 100644
--- a/CringeBootstrap/packages.lock.json
+++ b/CringeBootstrap/packages.lock.json
@@ -29,6 +29,22 @@
"NuGet.Versioning": "6.10.1"
}
},
+ "Basic.Reference.Assemblies.Net80": {
+ "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==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Common": "4.11.0"
+ }
+ },
"dnlib": {
"type": "Transitive",
"resolved": "4.4.0",
@@ -359,8 +375,8 @@
},
"SpaceEngineersDedicated.ReferenceAssemblies": {
"type": "Transitive",
- "resolved": "1.205.24",
- "contentHash": "cgzWJWflVITp+fY5OPgffcoJ08KL5YHMQrMwaDAkUxfRwPgTzU8qOADsrMqq25vXsEbznU1DzNWwTPviYYi7UA==",
+ "resolved": "1.205.25",
+ "contentHash": "+70s6nJnBxEFYZY1qwKfM7FgYBYY6YDSPvbltEXrn7CVAeiWIxbtdcUZ4nDBGVTYqUWEI/r3zbLP1zlcNE27Dg==",
"dependencies": {
"SharpDX": "4.2.0-keen-cringe",
"protobuf-net": "1.0.0"
@@ -1294,7 +1310,6 @@
"dependencies": {
"CringeBootstrap.Abstractions": "[1.0.0, )",
"CringePlugins": "[1.0.0, )",
- "ImGui.NET.DirectX": "[1.91.0.1, )",
"Lib.Harmony.Thin": "[2.3.3, )",
"Microsoft.CodeAnalysis.CSharp": "[4.11.0, )",
"NLog": "[5.3.4, )",
@@ -1311,6 +1326,9 @@
"cringeplugins": {
"type": "Project",
"dependencies": {
+ "Basic.Reference.Assemblies.Net80": "[1.7.9, )",
+ "Basic.Reference.Assemblies.Net80Windows": "[1.7.9, )",
+ "ImGui.NET.DirectX": "[1.91.0.1, )",
"NLog": "[5.3.4, )",
"NuGet": "[1.0.0, )",
"SharedCringe": "[1.0.0, )",
diff --git a/CringeLauncher/CringeLauncher.csproj b/CringeLauncher/CringeLauncher.csproj
index 684e233..2d0da19 100644
--- a/CringeLauncher/CringeLauncher.csproj
+++ b/CringeLauncher/CringeLauncher.csproj
@@ -18,12 +18,11 @@
-
+
-
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/CringeLauncher/packages.lock.json b/CringeLauncher/packages.lock.json
index 0e14f31..d5059be 100644
--- a/CringeLauncher/packages.lock.json
+++ b/CringeLauncher/packages.lock.json
@@ -8,17 +8,6 @@
"resolved": "4.4.0",
"contentHash": "cKHI720q+zfEEvzklWVGt6B0TH3AibAyJbpUJl4U6KvTP13tycfnqJpkGHRZ/oQ45BTIoIxIwltHIJVDN+iCqQ=="
},
- "ImGui.NET.DirectX": {
- "type": "Direct",
- "requested": "[1.91.0.1, )",
- "resolved": "1.91.0.1",
- "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
- "dependencies": {
- "System.Buffers": "4.5.1",
- "System.Numerics.Vectors": "4.5.0",
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
"Krafs.Publicizer": {
"type": "Direct",
"requested": "[2.2.1, )",
@@ -67,8 +56,8 @@
"SpaceEngineersDedicated.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.*, )",
- "resolved": "1.205.24",
- "contentHash": "cgzWJWflVITp+fY5OPgffcoJ08KL5YHMQrMwaDAkUxfRwPgTzU8qOADsrMqq25vXsEbznU1DzNWwTPviYYi7UA==",
+ "resolved": "1.205.25",
+ "contentHash": "+70s6nJnBxEFYZY1qwKfM7FgYBYY6YDSPvbltEXrn7CVAeiWIxbtdcUZ4nDBGVTYqUWEI/r3zbLP1zlcNE27Dg==",
"dependencies": {
"SharpDX": "4.2.0-keen-cringe",
"protobuf-net": "1.0.0"
@@ -132,6 +121,32 @@
"NuGet.Versioning": "6.10.1"
}
},
+ "Basic.Reference.Assemblies.Net80": {
+ "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==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Common": "4.11.0"
+ }
+ },
+ "ImGui.NET.DirectX": {
+ "type": "Transitive",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "5.0.0",
@@ -363,6 +378,9 @@
"cringeplugins": {
"type": "Project",
"dependencies": {
+ "Basic.Reference.Assemblies.Net80": "[1.7.9, )",
+ "Basic.Reference.Assemblies.Net80Windows": "[1.7.9, )",
+ "ImGui.NET.DirectX": "[1.91.0.1, )",
"NLog": "[5.3.4, )",
"NuGet": "[1.0.0, )",
"SharedCringe": "[1.0.0, )",
@@ -387,17 +405,6 @@
}
},
"net8.0-windows10.0.19041/win-x64": {
- "ImGui.NET.DirectX": {
- "type": "Direct",
- "requested": "[1.91.0.1, )",
- "resolved": "1.91.0.1",
- "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
- "dependencies": {
- "System.Buffers": "4.5.1",
- "System.Numerics.Vectors": "4.5.0",
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- },
"Steamworks.NET": {
"type": "Direct",
"requested": "[20.1.0, )",
@@ -422,6 +429,16 @@
"System.CodeDom": "8.0.0"
}
},
+ "ImGui.NET.DirectX": {
+ "type": "Transitive",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
"System.Diagnostics.EventLog": {
"type": "Transitive",
"resolved": "8.0.0",
diff --git a/CringePlugins/Config/PackagesConfig.cs b/CringePlugins/Config/PackagesConfig.cs
index 9d7c8db..3084539 100644
--- a/CringePlugins/Config/PackagesConfig.cs
+++ b/CringePlugins/Config/PackagesConfig.cs
@@ -8,6 +8,8 @@ namespace CringePlugins.Config;
public record PackagesConfig(ImmutableArray Sources, ImmutableArray Packages)
{
public static PackagesConfig Default { get; } = new([
+ new("SpaceEngineersDedicated.ReferenceAssemblies", "https://nuget.storage.yandexcloud.net/index.json"),
+ new("ImGui.NET.DirectX", "https://nuget.storage.yandexcloud.net/index.json"),
new(string.Empty, "https://api.nuget.org/v3/index.json")
], []);
}
\ No newline at end of file
diff --git a/CringePlugins/CringePlugins.csproj b/CringePlugins/CringePlugins.csproj
index 8146a47..39fbba1 100644
--- a/CringePlugins/CringePlugins.csproj
+++ b/CringePlugins/CringePlugins.csproj
@@ -21,7 +21,10 @@
+
+
+
diff --git a/CringePlugins/Loader/PluginsLifetime.cs b/CringePlugins/Loader/PluginsLifetime.cs
index 21078f3..88fed83 100644
--- a/CringePlugins/Loader/PluginsLifetime.cs
+++ b/CringePlugins/Loader/PluginsLifetime.cs
@@ -8,6 +8,7 @@ using NLog;
using NuGet;
using NuGet.Deps;
using NuGet.Frameworks;
+using NuGet.Versioning;
namespace CringePlugins.Loader;
@@ -19,7 +20,7 @@ public class PluginsLifetime : 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-windows");
+ private readonly NuGetFramework _runtimeFramework = NuGetFramework.ParseFolder("net8.0-windows10.0.19041.0");
public async ValueTask Load(ISplashProgress progress)
{
@@ -83,18 +84,25 @@ public class PluginsLifetime : ILoadingStage
private async Task LoadPlugins(IReadOnlySet packages, PackageSourceMapping sourceMapping)
{
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 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);
foreach (var package in packages)
{
var dir = Path.Join(package.Directory.FullName, "lib", package.ResolvedFramework.GetShortFolderName());
await using (var stream = File.Create(Path.Join(dir, $"{package.Package.Id}.deps.json")))
- await DependencyManifestUtility.WriteDependencyManifestAsync(stream, package.Entry, _runtimeFramework,
- sourceMapping,
- dependency =>
- packages.First(b => b.Package.Id.Equals(dependency.Id, StringComparison.OrdinalIgnoreCase))
- .Package
- .Version);
+ await manifestBuilder.WriteDependencyManifestAsync(stream, package.Entry, _runtimeFramework);
LoadComponent(plugins, Path.Join(dir, $"{package.Package.Id}.dll"));
}
diff --git a/CringePlugins/Resolver/BuiltInPackages.cs b/CringePlugins/Resolver/BuiltInPackages.cs
new file mode 100644
index 0000000..fb6dd3e
--- /dev/null
+++ b/CringePlugins/Resolver/BuiltInPackages.cs
@@ -0,0 +1,78 @@
+using System.Collections.Immutable;
+using System.Reflection;
+using Basic.Reference.Assemblies;
+using CringePlugins.Loader;
+using CringePlugins.Utils;
+using dnlib.DotNet;
+using ImGuiNET;
+using Microsoft.CodeAnalysis;
+using NLog;
+using NuGet.Frameworks;
+using NuGet.Models;
+using NuGet.Versioning;
+using Sandbox.Game;
+using SpaceEngineers.Game;
+using VRage.Utils;
+
+namespace CringePlugins.Resolver;
+
+public static class BuiltInPackages
+{
+ private const string SeReferenceAssemblies = "SpaceEngineersDedicated.ReferenceAssemblies";
+ private const string ImGui = "ImGui.NET.DirectX";
+
+ public static ImmutableArray GetPackages(NuGetFramework runtimeFramework)
+ {
+ var nlog = FromAssembly(runtimeFramework, version: new(5, 3, 4));
+ Version seVersion = new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion!.Value);
+
+ var se = FromAssembly(runtimeFramework, [
+ nlog.AsDependency()
+ ], SeReferenceAssemblies, new(seVersion));
+ var imGui = FromAssembly(runtimeFramework, id: ImGui);
+
+ BuiltInSdkPackage MapSdkPackage(
+ (string FileName, byte[] ImageBytes, PortableExecutableReference Reference, Guid Mvid) r)
+ {
+ var def = ModuleDefMD.Load(r.ImageBytes, IntrospectionContext.Global.Context);
+ var attribute = def.CustomAttributes.Find(typeof(AssemblyFileVersionAttribute).FullName);
+ 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(Path.GetFileNameWithoutExtension(r.FileName), version, [new(runtimeFramework, [])], null, []));
+ }
+
+ return
+ [
+ ..Net80.ReferenceInfos.AllValues.Select(MapSdkPackage),
+ ..Net80Windows.ReferenceInfos.AllValues.Select(MapSdkPackage),
+ nlog,
+ se,
+ imGui,
+ FromAssembly(runtimeFramework, [se.AsDependency(), imGui.AsDependency()]),
+ ];
+ }
+
+ private static Dependency AsDependency(this ResolvedPackage package) => new(package.Package.Id, new(package.Package.Version));
+
+ private static BuiltInPackage FromAssembly(NuGetFramework runtimeFramework, ImmutableArray? dependencies = null, string? id = null, NuGetVersion? version = null)
+ {
+ var assembly = typeof(T).Assembly.GetName();
+ id ??= assembly.Name!;
+ version ??= new NuGetVersion(assembly.Version ?? new(0, 0, 0));
+ dependencies ??= [];
+
+ return new(
+ new(0, id, version, [..dependencies.Value.Select(b => b.Id)]),
+ runtimeFramework,
+ new(id, version, [
+ new(runtimeFramework, dependencies.Value)
+ ], null, [])
+ );
+ }
+}
+
+public record BuiltInPackage(Package Package, NuGetFramework ResolvedFramework, CatalogEntry Entry) : ResolvedPackage(Package, ResolvedFramework, Entry);
+
+public record BuiltInSdkPackage(Package Package, NuGetFramework ResolvedFramework, CatalogEntry Entry) : BuiltInPackage(Package, ResolvedFramework, Entry);
\ No newline at end of file
diff --git a/CringePlugins/Resolver/PackageResolver.cs b/CringePlugins/Resolver/PackageResolver.cs
index fbb2043..ec0e6ac 100644
--- a/CringePlugins/Resolver/PackageResolver.cs
+++ b/CringePlugins/Resolver/PackageResolver.cs
@@ -12,7 +12,7 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray> ResolveAsync()
{
var order = 0;
- var packages = new SortedSet();
+ var packages = new SortedDictionary();
foreach (var reference in references)
{
@@ -20,25 +20,25 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray b.CatalogEntry.PackageTypes is [{ Name: "CringePlugin" }]).Select(b => b.CatalogEntry.Version));
- if (version is not null)
- break;
- }
+ var items = registrationRoot.Items.SelectMany(page =>
+ page.Items.Where(b => b.CatalogEntry.PackageTypes is ["CringePlugin"]))
+ .ToImmutableDictionary(b => b.CatalogEntry.Version);
+
+ var version = reference.Range.FindBestMatch(items.Values.Select(b => b.CatalogEntry.Version));
if (version is null)
throw new Exception($"Unable to find version for package {reference.Id}");
var package = new Package(order, reference.Id, version, []); // todo resolve dependencies
- if (packages.Add(package))
+ if (packages.TryAdd(package, items[version].CatalogEntry))
continue;
- if (!packages.TryGetValue(package, out var existingPackage))
+ if (!packages.TryGetValue(package, out _))
throw new Exception($"Duplicate package {package.Id}");
+ var existingPackage = packages.Keys.First(b => b.Version == package.Version && b.Id == package.Id);
+
if (package.Version < existingPackage.Version)
throw new Exception($"Package reference {package.Id} has lower version {package.Version} than already resolved {existingPackage.Version}");
@@ -49,17 +49,13 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray.Empty.ToBuilder();
- foreach (var package in packages)
+ foreach (var (package, catalogEntry) in packages)
{
var client = await packageSources.GetClientAsync(package.Id);
-
- var (catalogEntryUrl, catalogEntry) = await client.GetPackageRegistrationAsync(package.Id, package.Version);
-
- catalogEntry ??= await client.GetPackageCatalogEntryAsync(catalogEntryUrl);
var nearestGroup = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups, runtimeFramework,
g => g.TargetFramework);
diff --git a/CringePlugins/Utils/IntrospectionContext.cs b/CringePlugins/Utils/IntrospectionContext.cs
index d58158b..44de507 100644
--- a/CringePlugins/Utils/IntrospectionContext.cs
+++ b/CringePlugins/Utils/IntrospectionContext.cs
@@ -6,12 +6,12 @@ namespace CringePlugins.Utils;
public class IntrospectionContext
{
public static IntrospectionContext Global { get; } = new();
-
- private readonly ModuleContext _context = ModuleDef.CreateModuleContext();
+
+ internal readonly ModuleContext Context = ModuleDef.CreateModuleContext();
public IEnumerable CollectAttributedTypes(Module module, bool allowAbstract = false) where TAttribute : Attribute
{
- var moduleDef = ModuleDefMD.Load(module, _context);
+ var moduleDef = ModuleDefMD.Load(module, Context);
return moduleDef.GetTypes()
.Where(b => b.CustomAttributes.IsDefined(typeof(TAttribute).FullName) && (allowAbstract || !b.IsAbstract))
@@ -20,7 +20,7 @@ public class IntrospectionContext
public IEnumerable CollectDerivedTypes(Module module, bool allowAbstract = false)
{
- var moduleDef = ModuleDefMD.Load(module, _context);
+ var moduleDef = ModuleDefMD.Load(module, Context);
var token = moduleDef.ImportAsTypeSig(typeof(T));
diff --git a/CringePlugins/packages.lock.json b/CringePlugins/packages.lock.json
index 7905d0f..0b38dbb 100644
--- a/CringePlugins/packages.lock.json
+++ b/CringePlugins/packages.lock.json
@@ -2,12 +2,41 @@
"version": 1,
"dependencies": {
"net8.0-windows7.0": {
+ "Basic.Reference.Assemblies.Net80": {
+ "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==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Common": "4.11.0"
+ }
+ },
"dnlib": {
"type": "Direct",
"requested": "[4.4.0, )",
"resolved": "4.4.0",
"contentHash": "cKHI720q+zfEEvzklWVGt6B0TH3AibAyJbpUJl4U6KvTP13tycfnqJpkGHRZ/oQ45BTIoIxIwltHIJVDN+iCqQ=="
},
+ "ImGui.NET.DirectX": {
+ "type": "Direct",
+ "requested": "[1.91.0.1, )",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
"Krafs.Publicizer": {
"type": "Direct",
"requested": "[2.2.1, )",
@@ -23,13 +52,28 @@
"SpaceEngineersDedicated.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.*, )",
- "resolved": "1.205.24",
- "contentHash": "cgzWJWflVITp+fY5OPgffcoJ08KL5YHMQrMwaDAkUxfRwPgTzU8qOADsrMqq25vXsEbznU1DzNWwTPviYYi7UA==",
+ "resolved": "1.205.25",
+ "contentHash": "+70s6nJnBxEFYZY1qwKfM7FgYBYY6YDSPvbltEXrn7CVAeiWIxbtdcUZ4nDBGVTYqUWEI/r3zbLP1zlcNE27Dg==",
"dependencies": {
"SharpDX": "4.2.0-keen-cringe",
"protobuf-net": "1.0.0"
}
},
+ "Microsoft.CodeAnalysis.Analyzers": {
+ "type": "Transitive",
+ "resolved": "3.3.4",
+ "contentHash": "AxkxcPR+rheX0SmvpLVIGLhOUXAKG56a64kV9VQZ4y9gR9ZmPXnqZvHJnmwLSwzrEP6junUF11vuc+aqo5r68g=="
+ },
+ "Microsoft.CodeAnalysis.Common": {
+ "type": "Transitive",
+ "resolved": "4.11.0",
+ "contentHash": "djf8ujmqYImFgB04UGtcsEhHrzVqzHowS+EEl/Yunc5LdrYrZhGBWUTXoCF0NzYXJxtfuD+UVQarWpvrNc94Qg==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.3.4",
+ "System.Collections.Immutable": "8.0.0",
+ "System.Reflection.Metadata": "8.0.0"
+ }
+ },
"NuGet.Frameworks": {
"type": "Transitive",
"resolved": "6.11.1",
@@ -50,6 +94,34 @@
"resolved": "4.2.0-keen-cringe",
"contentHash": "LaJN3h1Gi1FWVdef2I5WtOH9gwzKCBniH0CragarbkN2QheYY6Lqm+91PcOfp1w/4wdVb+k8Kjv3sO393Tphtw=="
},
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ },
+ "System.Collections.Immutable": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg=="
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
+ },
+ "System.Reflection.Metadata": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "ptvgrFh7PvWI8bcVqG5rsA/weWM09EnthFHR5SCnS6IN+P4mj6rE1lBDC4U8HL9/57htKAqy4KQ3bBj84cfYyQ==",
+ "dependencies": {
+ "System.Collections.Immutable": "8.0.0"
+ }
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
"cringebootstrap.abstractions": {
"type": "Project"
},
@@ -69,6 +141,18 @@
}
}
},
- "net8.0-windows7.0/win-x64": {}
+ "net8.0-windows7.0/win-x64": {
+ "ImGui.NET.DirectX": {
+ "type": "Direct",
+ "requested": "[1.91.0.1, )",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/NuGet/Converters/FrameworkJsonConverter.cs b/NuGet/Converters/FrameworkJsonConverter.cs
index 0327247..24cb9bb 100644
--- a/NuGet/Converters/FrameworkJsonConverter.cs
+++ b/NuGet/Converters/FrameworkJsonConverter.cs
@@ -6,7 +6,7 @@ namespace NuGet.Converters;
public class FrameworkJsonConverter(FrameworkNameFormat format) : JsonConverter
{
- public override NuGetFramework? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ public override NuGetFramework Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.String)
throw new JsonException("Invalid framework string");
@@ -23,12 +23,26 @@ public class FrameworkJsonConverter(FrameworkNameFormat format) : JsonConverter<
public override void Write(Utf8JsonWriter writer, NuGetFramework value, JsonSerializerOptions options)
{
- writer.WriteStringValue(format switch
+ writer.WriteStringValue(FormatValue(value));
+ }
+
+ private string FormatValue(NuGetFramework value)
+ {
+ return format switch
{
FrameworkNameFormat.ShortFolderName => value.GetShortFolderName(),
FrameworkNameFormat.FrameworkName => value.DotNetFrameworkName,
_ => throw new ArgumentOutOfRangeException()
- });
+ };
+ }
+
+ public override NuGetFramework ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert,
+ JsonSerializerOptions options) => Read(ref reader, typeToConvert, options);
+
+ public override void WriteAsPropertyName(Utf8JsonWriter writer, NuGetFramework value,
+ JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(FormatValue(value));
}
}
diff --git a/NuGet/Converters/ManifestPackageKeyJsonConverter.cs b/NuGet/Converters/ManifestPackageKeyJsonConverter.cs
index fb99a0d..46058fc 100644
--- a/NuGet/Converters/ManifestPackageKeyJsonConverter.cs
+++ b/NuGet/Converters/ManifestPackageKeyJsonConverter.cs
@@ -23,5 +23,8 @@ public class ManifestPackageKeyJsonConverter : JsonConverter
JsonSerializerOptions options) => Read(ref reader, typeToConvert, options);
public override void WriteAsPropertyName(Utf8JsonWriter writer, ManifestPackageKey value,
- JsonSerializerOptions options) => Write(writer, value, options);
+ JsonSerializerOptions options)
+ {
+ writer.WritePropertyName(value.ToString());
+ }
}
\ No newline at end of file
diff --git a/NuGet/Deps/DependenciesManifest.cs b/NuGet/Deps/DependenciesManifest.cs
index c74d0c9..b726c4b 100644
--- a/NuGet/Deps/DependenciesManifest.cs
+++ b/NuGet/Deps/DependenciesManifest.cs
@@ -1,4 +1,5 @@
using System.Collections.Immutable;
+using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -55,7 +56,7 @@ public record ManifestPackageKey(string Id, NuGetVersion Version)
public override string ToString() => $"{Id}/{Version}";
}
-public static class DependencyManifestUtility
+public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSourceMapping packageSources, Func versionResolver)
{
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
{
@@ -68,14 +69,13 @@ public static class DependencyManifestUtility
}
};
- public static async ValueTask WriteDependencyManifestAsync(Stream stream, CatalogEntry catalogEntry, NuGetFramework targetFramework,
- PackageSourceMapping packageSources, Func versionResolver)
+ public async ValueTask WriteDependencyManifestAsync(Stream stream, CatalogEntry catalogEntry, NuGetFramework targetFramework)
{
var runtimeTarget = new RuntimeTarget(targetFramework);
var targets = ImmutableDictionary.Empty.ToBuilder();
- await MapCatalogEntry(catalogEntry, targetFramework, packageSources, versionResolver, targets);
+ await MapCatalogEntryAsync(catalogEntry, targetFramework, targets);
var manifest = new DependenciesManifest(runtimeTarget, ImmutableDictionary.Empty,
ImmutableDictionary>.Empty
@@ -85,8 +85,8 @@ public static class DependencyManifestUtility
await JsonSerializer.SerializeAsync(stream, manifest, SerializerOptions);
}
- private static async Task MapCatalogEntry(CatalogEntry catalogEntry, NuGetFramework targetFramework,
- PackageSourceMapping packageSources, Func versionResolver, ImmutableDictionary.Builder targets)
+ private async Task MapCatalogEntryAsync(CatalogEntry catalogEntry, NuGetFramework targetFramework,
+ ImmutableDictionary.Builder targets)
{
if (targets.ContainsKey(new(catalogEntry.Id, catalogEntry.Version)))
return;
@@ -98,26 +98,58 @@ public static class DependencyManifestUtility
return;
targets.Add(new(catalogEntry.Id, catalogEntry.Version),
- MapEntry(catalogEntry, nearest, targetFramework, versionResolver));
+ await MapEntryAsync(catalogEntry, nearest));
- foreach (var dependency in nearest.Dependencies)
+ foreach (var dependency in nearest.Dependencies ?? [])
{
var client = await packageSources.GetClientAsync(dependency.Id);
- var (url, entry) = await client.GetPackageRegistrationAsync(dependency.Id, versionResolver(dependency));
+ var (url, entry) = await client.GetPackageRegistrationAsync(dependency.Id, versionResolver(dependency)!);
entry ??= await client.GetPackageCatalogEntryAsync(url);
- await MapCatalogEntry(entry, targetFramework, packageSources, versionResolver, targets);
+ await MapCatalogEntryAsync(entry, targetFramework, targets);
}
}
- private static DependencyTarget MapEntry(CatalogEntry entry, DependencyGroup group, NuGetFramework targetFramework, Func versionResolver)
+ private async Task MapEntryAsync(CatalogEntry entry, DependencyGroup group)
{
- return new(group.Dependencies.ToImmutableDictionary(b => b.Id, versionResolver),
- entry.PackageEntries.Where(b => b.FullName.StartsWith($"lib/{targetFramework.GetShortFolderName()}/"))
+ var packageEntries = entry.PackageEntries ?? await GetPackageContent(entry);
+
+ return new(group.Dependencies?.ToImmutableDictionary(b => b.Id, versionResolver) ?? ImmutableDictionary.Empty,
+ packageEntries.Where(b => b.FullName.StartsWith($"lib/{group.TargetFramework.GetShortFolderName()}/"))
.ToImmutableDictionary(b => b.FullName, _ => new RuntimeDependency()),
- entry.PackageEntries.Where(b =>
+ packageEntries.Where(b =>
b.FullName.StartsWith($"runtimes/{RuntimeInformation.RuntimeIdentifier}/native/"))
.ToImmutableDictionary(b => b.FullName, _ => new Dependency()));
}
+
+ private async Task> GetPackageContent(CatalogEntry entry)
+ {
+ while (true)
+ {
+ var dir = new DirectoryInfo(Path.Join(cacheDirectory.FullName, entry.Id, entry.Version.ToString()));
+
+ if (dir.Exists)
+ {
+ return
+ [
+ ..dir.EnumerateFiles("*", SearchOption.AllDirectories)
+ .Select(b => new CatalogPackageEntry(b.Name, b.FullName, b.Length, b.Length))
+ ];
+ }
+
+ var client = await packageSources.GetClientAsync(entry.Id);
+
+ dir.Create();
+
+ {
+ await using var stream = await client.GetPackageContentStreamAsync(entry.Id, entry.Version);
+ using var memStream = new MemoryStream();
+ await stream.CopyToAsync(memStream);
+ memStream.Position = 0;
+ using var archive = new ZipArchive(memStream, ZipArchiveMode.Read);
+ archive.ExtractToDirectory(dir.FullName);
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/NuGet/Models/CatalogEntry.cs b/NuGet/Models/CatalogEntry.cs
index b943755..b36d143 100644
--- a/NuGet/Models/CatalogEntry.cs
+++ b/NuGet/Models/CatalogEntry.cs
@@ -1,9 +1,9 @@
-using NuGet.Versioning;
+using System.Collections.Immutable;
+using NuGet.Versioning;
namespace NuGet.Models;
-public record CatalogEntry(string Id, NuGetVersion Version, DependencyGroup[] DependencyGroups, PackageType[]? PackageTypes,
- CatalogPackageEntry[] PackageEntries,
- bool Serviceable = true);
+public record CatalogEntry(string Id, NuGetVersion Version, ImmutableArray DependencyGroups, ImmutableArray? PackageTypes,
+ ImmutableArray? PackageEntries);
public record CatalogPackageEntry(string Name, string FullName, long CompressedLength, long Length);
\ No newline at end of file
diff --git a/NuGet/Models/DependencyGroup.cs b/NuGet/Models/DependencyGroup.cs
index 4c7a3b5..f77c3b5 100644
--- a/NuGet/Models/DependencyGroup.cs
+++ b/NuGet/Models/DependencyGroup.cs
@@ -1,5 +1,6 @@
-using NuGet.Frameworks;
+using System.Collections.Immutable;
+using NuGet.Frameworks;
namespace NuGet.Models;
-public record DependencyGroup(NuGetFramework TargetFramework, Dependency[] Dependencies);
\ No newline at end of file
+public record DependencyGroup(NuGetFramework TargetFramework, ImmutableArray? Dependencies = null);
\ No newline at end of file
diff --git a/NuGet/Models/PackageType.cs b/NuGet/Models/PackageType.cs
deleted file mode 100644
index b1d767f..0000000
--- a/NuGet/Models/PackageType.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace NuGet.Models;
-
-public record PackageType(string Name);
\ No newline at end of file
diff --git a/NuGet/NuGetClient.cs b/NuGet/NuGetClient.cs
index c7c30dd..7d4fc80 100644
--- a/NuGet/NuGetClient.cs
+++ b/NuGet/NuGetClient.cs
@@ -1,4 +1,5 @@
-using System.Net.Http.Json;
+using System.Net;
+using System.Net.Http.Json;
using System.Text.Json;
using NuGet.Converters;
using NuGet.Models;
@@ -32,8 +33,9 @@ public class NuGetClient
public Task GetPackageContentStreamAsync(string id, NuGetVersion version)
{
+ id = id.ToLower();
return _client.GetStreamAsync(new Uri(_packageBaseAddress,
- new Uri($"{id.ToLower()}/{version}.nupkg", UriKind.Relative)));
+ new Uri($"{id}/{version}/{id}.{version}.nupkg", UriKind.Relative)));
}
public Task GetPackageRegistrationAsync(string id, NuGetVersion version)
@@ -61,12 +63,20 @@ public class NuGetClient
public static async Task CreateFromIndexUrlAsync(string indexUrl)
{
- var client = new HttpClient();
+ var client = new HttpClient(new HttpClientHandler
+ {
+ AutomaticDecompression = DecompressionMethods.All
+ });
var index = await client.GetFromJsonAsync(indexUrl, SerializerOptions);
var (packageBaseAddress, _, _) = index!.Resources.First(b => b.Type.Id == "PackageBaseAddress");
var (registration, _, _) = index!.Resources.First(b => b.Type.Id == "RegistrationsBaseUrl");
+
+ if (!packageBaseAddress.EndsWith('/'))
+ packageBaseAddress += '/';
+ if (!registration.EndsWith('/'))
+ registration += '/';
return new NuGetClient(client, new Uri(packageBaseAddress), new Uri(registration));
}
diff --git a/NuGet/PackageSourceMapping.cs b/NuGet/PackageSourceMapping.cs
index 5cda169..4d22b8f 100644
--- a/NuGet/PackageSourceMapping.cs
+++ b/NuGet/PackageSourceMapping.cs
@@ -4,13 +4,14 @@ namespace NuGet;
public class PackageSourceMapping(ImmutableArray sources)
{
- private readonly ImmutableDictionary> _clients = sources.Select(b =>
- new KeyValuePair>(b.Pattern,
+ private readonly ImmutableArray<(string pattern, Task client)> _clients = [
+ ..sources.Select(b =>
+ (b.Pattern,
NuGetClient.CreateFromIndexUrlAsync(b.Url)))
- .ToImmutableDictionary();
+ ];
public Task GetClientAsync(string packageId) =>
- _clients.FirstOrDefault(b => packageId.StartsWith(b.Key)).Value;
+ _clients.FirstOrDefault(b => packageId.StartsWith(b.pattern)).client;
}
public record PackageSource(string Pattern, string Url);
\ No newline at end of file
diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj
index cc2ecfc..21f64a6 100644
--- a/TestPlugin/TestPlugin.csproj
+++ b/TestPlugin/TestPlugin.csproj
@@ -7,6 +7,7 @@
enable
true
true
+ CringePlugin
diff --git a/TestPlugin/packages.lock.json b/TestPlugin/packages.lock.json
new file mode 100644
index 0000000..070b0a2
--- /dev/null
+++ b/TestPlugin/packages.lock.json
@@ -0,0 +1,115 @@
+{
+ "version": 1,
+ "dependencies": {
+ "net8.0-windows7.0": {
+ "ImGui.NET.DirectX": {
+ "type": "Direct",
+ "requested": "[1.91.0.1, )",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "NLog": {
+ "type": "Direct",
+ "requested": "[5.3.4, )",
+ "resolved": "5.3.4",
+ "contentHash": "gLy7+O1hEYJXIlcTr1/VWjGXrZTQFZzYNO18IWasD64pNwz0BreV+nHLxWKXWZzERRzoKnsk2XYtwLkTVk7J1A=="
+ },
+ "SpaceEngineersDedicated.ReferenceAssemblies": {
+ "type": "Direct",
+ "requested": "[1.*, )",
+ "resolved": "1.205.24",
+ "contentHash": "cgzWJWflVITp+fY5OPgffcoJ08KL5YHMQrMwaDAkUxfRwPgTzU8qOADsrMqq25vXsEbznU1DzNWwTPviYYi7UA==",
+ "dependencies": {
+ "SharpDX": "4.2.0-keen-cringe",
+ "protobuf-net": "1.0.0"
+ }
+ },
+ "dnlib": {
+ "type": "Transitive",
+ "resolved": "4.4.0",
+ "contentHash": "cKHI720q+zfEEvzklWVGt6B0TH3AibAyJbpUJl4U6KvTP13tycfnqJpkGHRZ/oQ45BTIoIxIwltHIJVDN+iCqQ=="
+ },
+ "NuGet.Frameworks": {
+ "type": "Transitive",
+ "resolved": "6.11.1",
+ "contentHash": "plTZ3ariSWQVsFn2mk83SsdmSg1VpgIMTSZpP/eSE/NNQF02p+M9ItxAYeUZBMX+cQ2nFkSwxQRJ0/fkaV9Hbg=="
+ },
+ "NuGet.Versioning": {
+ "type": "Transitive",
+ "resolved": "6.11.1",
+ "contentHash": "YNn3BB71F+guJW42TbAhGcMh3gpyqFMZcPVD9pm5vcvGivTALtRely/VCPWQQ6JQ5PfwIrjPaJMO7VnqyeK3rg=="
+ },
+ "protobuf-net": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "kTGOK0E87473sOImOjgZOnz3kTC2aMLffoRWQLYNuBLJnwNNmjanF9IkevZ9Q7yYLeABQfcF3BpeepuMntMVNw=="
+ },
+ "SharpDX": {
+ "type": "Transitive",
+ "resolved": "4.2.0-keen-cringe",
+ "contentHash": "LaJN3h1Gi1FWVdef2I5WtOH9gwzKCBniH0CragarbkN2QheYY6Lqm+91PcOfp1w/4wdVb+k8Kjv3sO393Tphtw=="
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "cringebootstrap.abstractions": {
+ "type": "Project"
+ },
+ "cringeplugins": {
+ "type": "Project",
+ "dependencies": {
+ "NLog": "[5.3.4, )",
+ "NuGet": "[1.0.0, )",
+ "SharedCringe": "[1.0.0, )",
+ "SpaceEngineersDedicated.ReferenceAssemblies": "[1.*, )",
+ "dnlib": "[4.4.0, )"
+ }
+ },
+ "nuget": {
+ "type": "Project",
+ "dependencies": {
+ "NuGet.Frameworks": "[6.11.1, )",
+ "NuGet.Versioning": "[6.11.1, )"
+ }
+ },
+ "sharedcringe": {
+ "type": "Project",
+ "dependencies": {
+ "CringeBootstrap.Abstractions": "[1.0.0, )",
+ "NLog": "[5.3.4, )",
+ "SpaceEngineersDedicated.ReferenceAssemblies": "[1.*, )"
+ }
+ }
+ },
+ "net8.0-windows7.0/win-x64": {
+ "ImGui.NET.DirectX": {
+ "type": "Direct",
+ "requested": "[1.91.0.1, )",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file