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:
@@ -42,7 +42,7 @@ public class GameDirectoryAssemblyLoadContext : AssemblyLoadContext, ICoreLoadCo
|
|||||||
|
|
||||||
if (key.StartsWith("System.") || ReferenceAssemblies.Contains(key))
|
if (key.StartsWith("System.") || ReferenceAssemblies.Contains(key))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_assemblyNames.TryAdd(key, file);
|
_assemblyNames.TryAdd(key, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -79,11 +79,11 @@ public class GameDirectoryAssemblyLoadContext : AssemblyLoadContext, ICoreLoadCo
|
|||||||
var path = Path.Join(dir, unmanagedDllName);
|
var path = Path.Join(dir, unmanagedDllName);
|
||||||
if (!Path.HasExtension(path))
|
if (!Path.HasExtension(path))
|
||||||
path += ".dll";
|
path += ".dll";
|
||||||
|
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
return LoadUnmanagedDllFromPath(path);
|
return LoadUnmanagedDllFromPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new DllNotFoundException($"Unable to load {unmanagedDllName}, module not found in valid locations");
|
throw new DllNotFoundException($"Unable to load {unmanagedDllName}, module not found in valid locations");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ if (args.Length == 0)
|
|||||||
{
|
{
|
||||||
var path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CringeLauncher",
|
var path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CringeLauncher",
|
||||||
"current", "CringeBootstrap.exe");
|
"current", "CringeBootstrap.exe");
|
||||||
|
|
||||||
Console.Write("Set your Launch Options under ");
|
Console.Write("Set your Launch Options under ");
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.Write("Space Engineers -> Properties -> Launch Options");
|
Console.Write("Space Engineers -> Properties -> Launch Options");
|
||||||
@@ -38,7 +38,7 @@ AssemblyLoadContext.Default.Resolving += (loadContext, name) =>
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var dir = Path.GetDirectoryName(args[0])!;
|
var dir = Path.GetDirectoryName(args[0])!;
|
||||||
var context = new GameDirectoryAssemblyLoadContext(dir);
|
var context = new GameDirectoryAssemblyLoadContext(dir);
|
||||||
|
|
||||||
|
@@ -66,7 +66,7 @@ internal sealed class ImGuiHandler : IGuiHandler, IDisposable
|
|||||||
ImGui_ImplWin32_Init(windowHandle);
|
ImGui_ImplWin32_Init(windowHandle);
|
||||||
ImGui_ImplDX11_Init(device.NativePointer, deviceContext.NativePointer);
|
ImGui_ImplDX11_Init(device.NativePointer, deviceContext.NativePointer);
|
||||||
_init = true;
|
_init = true;
|
||||||
|
|
||||||
_imageService.Initialize();
|
_imageService.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ internal sealed class ImGuiHandler : IGuiHandler, IDisposable
|
|||||||
|
|
||||||
UpdatePlatformWindows();
|
UpdatePlatformWindows();
|
||||||
RenderPlatformWindowsDefault();
|
RenderPlatformWindowsDefault();
|
||||||
|
|
||||||
_imageService.Update();
|
_imageService.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
@@ -58,7 +59,7 @@ public class Launcher : ICorePlugin
|
|||||||
{
|
{
|
||||||
if (Type.GetType("GameAnalyticsSDK.Net.Logging.GALogger, GameAnalytics.Mono") is { } gaLoggerType)
|
if (Type.GetType("GameAnalyticsSDK.Net.Logging.GALogger, GameAnalytics.Mono") is { } gaLoggerType)
|
||||||
RuntimeHelpers.RunClassConstructor(gaLoggerType.TypeHandle);
|
RuntimeHelpers.RunClassConstructor(gaLoggerType.TypeHandle);
|
||||||
|
|
||||||
LogManager.Setup()
|
LogManager.Setup()
|
||||||
.LoadConfigurationFromFile()
|
.LoadConfigurationFromFile()
|
||||||
.SetupExtensions(s =>
|
.SetupExtensions(s =>
|
||||||
@@ -75,19 +76,21 @@ public class Launcher : ICorePlugin
|
|||||||
|
|
||||||
var logger = LogManager.GetLogger("CringeBootstrap");
|
var logger = LogManager.GetLogger("CringeBootstrap");
|
||||||
logger.Info("Bootstrapping");
|
logger.Info("Bootstrapping");
|
||||||
|
|
||||||
//environment variable for viktor's plugins
|
//environment variable for viktor's plugins
|
||||||
Environment.SetEnvironmentVariable("SE_PLUGIN_DISABLE_METHOD_VERIFICATION", "True");
|
Environment.SetEnvironmentVariable("SE_PLUGIN_DISABLE_METHOD_VERIFICATION", "True");
|
||||||
|
|
||||||
#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
|
||||||
if (AssemblyLoadContext.GetLoadContext(typeof(Launcher).Assembly) is ICoreLoadContext coreLoadContext)
|
if (AssemblyLoadContext.GetLoadContext(typeof(Launcher).Assembly) is ICoreLoadContext coreLoadContext)
|
||||||
NativeLibrary.SetDllImportResolver(typeof(Steamworks.Constants).Assembly, (name, _, _) => coreLoadContext.ResolveUnmanagedDll(name));
|
NativeLibrary.SetDllImportResolver(typeof(Steamworks.Constants).Assembly, (name, _, _) => coreLoadContext.ResolveUnmanagedDll(name));
|
||||||
NativeLibrary.SetDllImportResolver(typeof(EosService).Assembly, (name, _, _) => NativeLibrary.Load(Path.Join(AppContext.BaseDirectory, name)));
|
NativeLibrary.SetDllImportResolver(typeof(EosService).Assembly, (name, _, _) => NativeLibrary.Load(Path.Join(AppContext.BaseDirectory, name)));
|
||||||
|
|
||||||
_harmony.PatchAll(typeof(Launcher).Assembly);
|
_harmony.PatchAll(typeof(Launcher).Assembly);
|
||||||
|
|
||||||
MyFileSystem.ExePath = Path.GetDirectoryName(args.ElementAtOrDefault(0) ?? Assembly.GetExecutingAssembly().Location)!;
|
MyFileSystem.ExePath = Path.GetDirectoryName(args.ElementAtOrDefault(0) ?? Assembly.GetExecutingAssembly().Location)!;
|
||||||
@@ -105,12 +108,12 @@ public class Launcher : ICorePlugin
|
|||||||
MyShaderCompiler.Init(MyShaderCompiler.TargetPlatform.PC, false);
|
MyShaderCompiler.Init(MyShaderCompiler.TargetPlatform.PC, false);
|
||||||
MyVRageWindows.Init(MyPerGameSettings.BasicGameInfo.ApplicationName, MySandboxGame.Log,
|
MyVRageWindows.Init(MyPerGameSettings.BasicGameInfo.ApplicationName, MySandboxGame.Log,
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
MyPerGameSettings.BasicGameInfo.ApplicationName),
|
MyPerGameSettings.BasicGameInfo.ApplicationName),
|
||||||
false, false);
|
false, false);
|
||||||
|
|
||||||
MyPlatformGameSettings.SAVE_TO_CLOUD_OPTION_AVAILABLE = true;
|
MyPlatformGameSettings.SAVE_TO_CLOUD_OPTION_AVAILABLE = true;
|
||||||
MyXAudio2.DEVICE_DETAILS_SUPPORTED = false;
|
MyXAudio2.DEVICE_DETAILS_SUPPORTED = false;
|
||||||
|
|
||||||
if (MyVRage.Platform.System.SimulationQuality == SimulationQuality.Normal)
|
if (MyVRage.Platform.System.SimulationQuality == SimulationQuality.Normal)
|
||||||
{
|
{
|
||||||
MyPlatformGameSettings.SIMPLIFIED_SIMULATION_OVERRIDE = false;
|
MyPlatformGameSettings.SIMPLIFIED_SIMULATION_OVERRIDE = false;
|
||||||
@@ -133,17 +136,17 @@ public class Launcher : ICorePlugin
|
|||||||
_renderComponent = new();
|
_renderComponent = new();
|
||||||
_renderComponent.Start(new(), () => InitEarlyWindow(splash), MyVideoSettingsManager.Initialize(), MyPerGameSettings.MaxFrameRate);
|
_renderComponent.Start(new(), () => InitEarlyWindow(splash), MyVideoSettingsManager.Initialize(), MyPerGameSettings.MaxFrameRate);
|
||||||
_renderComponent.RenderThread.BeforeDraw += MyFpsManager.Update;
|
_renderComponent.RenderThread.BeforeDraw += MyFpsManager.Update;
|
||||||
|
|
||||||
// this technically should wait for render thread init, but who cares
|
// this technically should wait for render thread init, but who cares
|
||||||
splash.ExecuteLoadingStages();
|
splash.ExecuteLoadingStages();
|
||||||
|
|
||||||
InitUgc();
|
InitUgc();
|
||||||
MyFileSystem.InitUserSpecific(MyGameService.UserId.ToString());
|
MyFileSystem.InitUserSpecific(MyGameService.UserId.ToString());
|
||||||
|
|
||||||
_lifetime.RegisterLifetime();
|
_lifetime.RegisterLifetime();
|
||||||
|
|
||||||
WaitForDevice();
|
WaitForDevice();
|
||||||
|
|
||||||
_game = new(args)
|
_game = new(args)
|
||||||
{
|
{
|
||||||
GameRenderComponent = _renderComponent,
|
GameRenderComponent = _renderComponent,
|
||||||
@@ -164,14 +167,14 @@ public class Launcher : ICorePlugin
|
|||||||
|
|
||||||
var retryPolicy = HttpPolicyExtensions.HandleTransientHttpError()
|
var retryPolicy = HttpPolicyExtensions.HandleTransientHttpError()
|
||||||
.WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(1));
|
.WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
services.AddHttpClient<PluginsLifetime>()
|
services.AddHttpClient<PluginsLifetime>()
|
||||||
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
|
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
|
||||||
{
|
{
|
||||||
AutomaticDecompression = DecompressionMethods.All
|
AutomaticDecompression = DecompressionMethods.All
|
||||||
})
|
})
|
||||||
.AddPolicyHandler(retryPolicy);
|
.AddPolicyHandler(retryPolicy);
|
||||||
|
|
||||||
services.AddHttpClient<ImGuiImageService>()
|
services.AddHttpClient<ImGuiImageService>()
|
||||||
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
|
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
|
||||||
{
|
{
|
||||||
@@ -208,25 +211,55 @@ public class Launcher : ICorePlugin
|
|||||||
private IVRageWindow InitEarlyWindow(Splash splash)
|
private IVRageWindow InitEarlyWindow(Splash splash)
|
||||||
{
|
{
|
||||||
ImGuiHandler.Instance = new(_configDir);
|
ImGuiHandler.Instance = new(_configDir);
|
||||||
|
|
||||||
RenderHandler.Current.RegisterComponent(splash);
|
RenderHandler.Current.RegisterComponent(splash);
|
||||||
|
|
||||||
MyVRage.Platform.Windows.CreateWindow("Cringe Launcher", MyPerGameSettings.GameIcon, null);
|
MyVRage.Platform.Windows.CreateWindow("Cringe Launcher", MyPerGameSettings.GameIcon, null);
|
||||||
|
|
||||||
MyVRage.Platform.Windows.Window.OnExit += MySandboxGame.ExitThreadSafe;
|
MyVRage.Platform.Windows.Window.OnExit += MySandboxGame.ExitThreadSafe;
|
||||||
|
|
||||||
MyRenderProxy.RenderThread = _renderComponent!.RenderThread;
|
MyRenderProxy.RenderThread = _renderComponent!.RenderThread;
|
||||||
|
|
||||||
MyVRage.Platform.Windows.Window.ShowAndFocus();
|
MyVRage.Platform.Windows.Window.ShowAndFocus();
|
||||||
|
|
||||||
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
|
||||||
var newVersion = await mgr.CheckForUpdatesAsync();
|
var newVersion = await mgr.CheckForUpdatesAsync();
|
||||||
if (newVersion == null)
|
if (newVersion == null)
|
||||||
@@ -234,7 +267,7 @@ public class Launcher : ICorePlugin
|
|||||||
logger.Info("Up to date");
|
logger.Info("Up to date");
|
||||||
return; // no update available
|
return; // no update available
|
||||||
}
|
}
|
||||||
|
|
||||||
// print update info
|
// print update info
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.WriteLine($"New version available: {mgr.CurrentVersion} -> {newVersion.TargetFullRelease.Version}");
|
Console.WriteLine($"New version available: {mgr.CurrentVersion} -> {newVersion.TargetFullRelease.Version}");
|
||||||
@@ -250,7 +283,7 @@ public class Launcher : ICorePlugin
|
|||||||
|
|
||||||
// download new version
|
// download new version
|
||||||
await mgr.DownloadUpdatesAsync(newVersion);
|
await mgr.DownloadUpdatesAsync(newVersion);
|
||||||
|
|
||||||
logger.Info("Done! Restarting...");
|
logger.Info("Done! Restarting...");
|
||||||
|
|
||||||
// install new version and restart app
|
// install new version and restart app
|
||||||
@@ -278,11 +311,11 @@ public class Launcher : ICorePlugin
|
|||||||
var textsPath = Path.Combine(MyFileSystem.RootPath, @"Content\Data\Localization\CoreTexts");
|
var textsPath = Path.Combine(MyFileSystem.RootPath, @"Content\Data\Localization\CoreTexts");
|
||||||
var hashSet = new HashSet<MyLanguagesEnum>();
|
var hashSet = new HashSet<MyLanguagesEnum>();
|
||||||
MyTexts.LoadSupportedLanguages(textsPath, hashSet);
|
MyTexts.LoadSupportedLanguages(textsPath, hashSet);
|
||||||
|
|
||||||
if (!MyTexts.Languages.TryGetValue(MyLanguage.Instance.GetOsLanguageCurrentOfficial(), out var description) &&
|
if (!MyTexts.Languages.TryGetValue(MyLanguage.Instance.GetOsLanguageCurrentOfficial(), out var description) &&
|
||||||
!MyTexts.Languages.TryGetValue(MyLanguagesEnum.English, out description))
|
!MyTexts.Languages.TryGetValue(MyLanguagesEnum.English, out description))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MyTexts.LoadTexts(textsPath, description.CultureName, description.SubcultureName);
|
MyTexts.LoadTexts(textsPath, description.CultureName, description.SubcultureName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,20 +323,20 @@ public class Launcher : ICorePlugin
|
|||||||
{
|
{
|
||||||
var steamGameService = MySteamGameService.Create(false, AppId);
|
var steamGameService = MySteamGameService.Create(false, AppId);
|
||||||
MyServiceManager.Instance.AddService(steamGameService);
|
MyServiceManager.Instance.AddService(steamGameService);
|
||||||
|
|
||||||
var aggregator = new MyServerDiscoveryAggregator();
|
var aggregator = new MyServerDiscoveryAggregator();
|
||||||
MySteamGameService.InitNetworking(false, steamGameService, MyPerGameSettings.GameName, aggregator);
|
MySteamGameService.InitNetworking(false, steamGameService, MyPerGameSettings.GameName, aggregator);
|
||||||
EosService.InitNetworking(false, false, MyPerGameSettings.GameName, steamGameService, "xyza7891964JhtVD93nm3nZp8t1MbnhC",
|
EosService.InitNetworking(false, false, MyPerGameSettings.GameName, steamGameService, "xyza7891964JhtVD93nm3nZp8t1MbnhC",
|
||||||
"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);
|
||||||
|
|
||||||
MyServiceManager.Instance.AddService(MySteamGameService.CreateMicrophone());
|
MyServiceManager.Instance.AddService(MySteamGameService.CreateMicrophone());
|
||||||
|
|
||||||
MyGameService.WorkshopService.AddAggregate(MySteamUgcService.Create(AppId, steamGameService));
|
MyGameService.WorkshopService.AddAggregate(MySteamUgcService.Create(AppId, steamGameService));
|
||||||
|
|
||||||
var modUgc = MyModIoService.Create(MyServiceManager.Instance.GetService<IMyGameService>(), "spaceengineers",
|
var modUgc = MyModIoService.Create(MyServiceManager.Instance.GetService<IMyGameService>(), "spaceengineers",
|
||||||
@@ -313,7 +346,7 @@ public class Launcher : ICorePlugin
|
|||||||
MyPlatformGameSettings.MODIO_PORTAL);
|
MyPlatformGameSettings.MODIO_PORTAL);
|
||||||
modUgc.IsConsentGiven = MySandboxGame.Config.ModIoConsent;
|
modUgc.IsConsentGiven = MySandboxGame.Config.ModIoConsent;
|
||||||
MyGameService.WorkshopService.AddAggregate(modUgc);
|
MyGameService.WorkshopService.AddAggregate(modUgc);
|
||||||
|
|
||||||
MySpaceEngineersAchievements.Initialize();
|
MySpaceEngineersAchievements.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,13 +354,13 @@ public class Launcher : ICorePlugin
|
|||||||
{
|
{
|
||||||
var renderQualityHint = MyVRage.Platform.Render.GetRenderQualityHint();
|
var renderQualityHint = MyVRage.Platform.Render.GetRenderQualityHint();
|
||||||
var preset = MyGuiScreenOptionsGraphics.GetPreset(renderQualityHint);
|
var preset = MyGuiScreenOptionsGraphics.GetPreset(renderQualityHint);
|
||||||
|
|
||||||
MyRenderProxy.Settings.User = MyVideoSettingsManager
|
MyRenderProxy.Settings.User = MyVideoSettingsManager
|
||||||
.GetGraphicsSettingsFromConfig(ref preset, renderQualityHint > MyRenderPresetEnum.CUSTOM)
|
.GetGraphicsSettingsFromConfig(ref preset, renderQualityHint > MyRenderPresetEnum.CUSTOM)
|
||||||
.PerformanceSettings.RenderSettings;
|
.PerformanceSettings.RenderSettings;
|
||||||
MyRenderProxy.Settings.EnableAnsel = MyPlatformGameSettings.ENABLE_ANSEL;
|
MyRenderProxy.Settings.EnableAnsel = MyPlatformGameSettings.ENABLE_ANSEL;
|
||||||
MyRenderProxy.Settings.EnableAnselWithSprites = MyPlatformGameSettings.ENABLE_ANSEL_WITH_SPRITES;
|
MyRenderProxy.Settings.EnableAnselWithSprites = MyPlatformGameSettings.ENABLE_ANSEL_WITH_SPRITES;
|
||||||
|
|
||||||
var graphicsRenderer = MySandboxGame.Config.GraphicsRenderer;
|
var graphicsRenderer = MySandboxGame.Config.GraphicsRenderer;
|
||||||
MySandboxGame.Config.GraphicsRenderer = graphicsRenderer;
|
MySandboxGame.Config.GraphicsRenderer = graphicsRenderer;
|
||||||
|
|
||||||
|
@@ -16,15 +16,15 @@ public static class EosInitPatch
|
|||||||
var ins = instructions.ToList();
|
var ins = instructions.ToList();
|
||||||
|
|
||||||
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,23 +42,26 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.WriteLine($"Blocking GetTypes for {__instance.FullName}");
|
Debug.WriteLine($"Blocking GetTypes for {__instance.FullName}");
|
||||||
|
|
||||||
__result = [];
|
__result = [];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -74,10 +77,9 @@ public static class IntrospectionPatches
|
|||||||
__result = [];
|
__result = [];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,13 +103,13 @@ public static class IntrospectionPatches
|
|||||||
.Concat(PluginsLifetime.Contexts.SelectMany(x => x.Assemblies)) ?? [];
|
.Concat(PluginsLifetime.Contexts.SelectMany(x => x.Assemblies)) ?? [];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix, HarmonyPatch(typeof(MySession), "PrepareBaseSession", typeof(MyObjectBuilder_Checkpoint), typeof(MyObjectBuilder_Sector))]
|
[HarmonyPrefix, HarmonyPatch(typeof(MySession), "PrepareBaseSession", typeof(MyObjectBuilder_Checkpoint), typeof(MyObjectBuilder_Sector))]
|
||||||
private static void PrepareSessionPrefix()
|
private static void PrepareSessionPrefix()
|
||||||
{
|
{
|
||||||
// i hate keen for that in MyUseObjectFactory..cctor
|
// i hate keen for that in MyUseObjectFactory..cctor
|
||||||
// MyUseObjectFactory.RegisterAssemblyTypes(Assembly.LoadFrom(Path.Combine(MyFileSystem.ExePath, "Sandbox.Game.dll")));
|
// MyUseObjectFactory.RegisterAssemblyTypes(Assembly.LoadFrom(Path.Combine(MyFileSystem.ExePath, "Sandbox.Game.dll")));
|
||||||
|
|
||||||
MyUseObjectFactory.RegisterAssemblyTypes(MyPlugins.SandboxGameAssembly);
|
MyUseObjectFactory.RegisterAssemblyTypes(MyPlugins.SandboxGameAssembly);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,10 +119,10 @@ public static class IntrospectionPatches
|
|||||||
foreach (var type in assemblies.SelectMany(b => IntrospectionContext.Global.CollectDerivedTypes<IPlugin>(b.GetMainModule())))
|
foreach (var type in assemblies.SelectMany(b => IntrospectionContext.Global.CollectDerivedTypes<IPlugin>(b.GetMainModule())))
|
||||||
{
|
{
|
||||||
var instance = Activator.CreateInstance(type);
|
var instance = Activator.CreateInstance(type);
|
||||||
|
|
||||||
if (instance is IPlugin plugin)
|
if (instance is IPlugin plugin)
|
||||||
___m_plugins.Add(plugin);
|
___m_plugins.Add(plugin);
|
||||||
|
|
||||||
if (instance is IHandleInputPlugin handleInputPlugin)
|
if (instance is IHandleInputPlugin handleInputPlugin)
|
||||||
___m_handleInputPlugins.Add(handleInputPlugin);
|
___m_handleInputPlugins.Add(handleInputPlugin);
|
||||||
}
|
}
|
||||||
@@ -138,22 +140,22 @@ public static class IntrospectionPatches
|
|||||||
|
|
||||||
if (assembly?.GetType($"Microsoft.Xml.Serialization.GeneratedAssembly.{typeName}Serializer") is not { } type)
|
if (assembly?.GetType($"Microsoft.Xml.Serialization.GeneratedAssembly.{typeName}Serializer") is not { } type)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
__result = Activator.CreateInstance(type) as XmlSerializer;
|
__result = Activator.CreateInstance(type) as XmlSerializer;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix, HarmonyPatch(typeof(MyXmlSerializerManager), nameof(MyXmlSerializerManager.RegisterFromAssembly))]
|
[HarmonyPrefix, HarmonyPatch(typeof(MyXmlSerializerManager), nameof(MyXmlSerializerManager.RegisterFromAssembly))]
|
||||||
private static bool XmlManagerRegisterPrefix(Assembly assembly) => AssemblyLoadContext.GetLoadContext(assembly) is ICoreLoadContext;
|
private static bool XmlManagerRegisterPrefix(Assembly assembly) => AssemblyLoadContext.GetLoadContext(assembly) is ICoreLoadContext;
|
||||||
|
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
private static class GameAssembliesPatch
|
private static class GameAssembliesPatch
|
||||||
{
|
{
|
||||||
private static IEnumerable<MethodInfo> TargetMethods()
|
private static IEnumerable<MethodInfo> TargetMethods()
|
||||||
{
|
{
|
||||||
return AccessTools.GetDeclaredMethods(typeof(MyPlugins))
|
return AccessTools.GetDeclaredMethods(typeof(MyPlugins))
|
||||||
.Where(b => b.Name.StartsWith("Register") &&
|
.Where(b => b.Name.StartsWith("Register") &&
|
||||||
b.GetParameters() is [var param] && param.ParameterType == typeof(string));
|
b.GetParameters() is [var param] && param.ParameterType == typeof(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@ public static class PluginNamePatch
|
|||||||
// to be just $"Plugin Init: {plugin}"
|
// to be just $"Plugin Init: {plugin}"
|
||||||
// so you could override .ToString
|
// so you could override .ToString
|
||||||
// doesn't change default behavior since base .ToString is .GetType().ToString()
|
// doesn't change default behavior since base .ToString is .GetType().ToString()
|
||||||
|
|
||||||
return new CodeMatcher(instructions)
|
return new CodeMatcher(instructions)
|
||||||
.SearchForward(b => b.Is(OpCodes.Ldstr, "Plugin Init: "))
|
.SearchForward(b => b.Is(OpCodes.Ldstr, "Plugin Init: "))
|
||||||
.Advance(2)
|
.Advance(2)
|
||||||
|
@@ -10,7 +10,7 @@ namespace CringeLauncher.Patches;
|
|||||||
public static class ScriptCompilationSettingsPatch
|
public static class ScriptCompilationSettingsPatch
|
||||||
{
|
{
|
||||||
private static readonly CSharpParseOptions Options = new(LanguageVersion.Latest, DocumentationMode.None);
|
private static readonly CSharpParseOptions Options = new(LanguageVersion.Latest, DocumentationMode.None);
|
||||||
|
|
||||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
{
|
{
|
||||||
var field = AccessTools.Field(typeof(MyScriptCompiler), nameof(MyScriptCompiler.m_conditionalParseOptions));
|
var field = AccessTools.Field(typeof(MyScriptCompiler), nameof(MyScriptCompiler.m_conditionalParseOptions));
|
||||||
|
@@ -14,7 +14,7 @@ public static class ScriptCompilerInitializationPatch
|
|||||||
return AccessTools.Method(Type.GetType("VRage.Scripting.MyVRageScriptingInternal, VRage.Scripting", true),
|
return AccessTools.Method(Type.GetType("VRage.Scripting.MyVRageScriptingInternal, VRage.Scripting", true),
|
||||||
"Initialize");
|
"Initialize");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool Prefix(Thread updateThread, Type[] referencedTypes, string[] symbols)
|
private static bool Prefix(Thread updateThread, Type[] referencedTypes, string[] symbols)
|
||||||
{
|
{
|
||||||
MyModWatchdog.Init(updateThread);
|
MyModWatchdog.Init(updateThread);
|
||||||
|
@@ -18,10 +18,10 @@ public static class SwapChainPatch
|
|||||||
WindowHandle = windowHandle;
|
WindowHandle = windowHandle;
|
||||||
MyPlatformRender.DisposeSwapChain();
|
MyPlatformRender.DisposeSwapChain();
|
||||||
MyPlatformRender.Log.WriteLine("CreateDeviceInternal create swapchain");
|
MyPlatformRender.Log.WriteLine("CreateDeviceInternal create swapchain");
|
||||||
|
|
||||||
if (MyPlatformRender.m_swapchain != null)
|
if (MyPlatformRender.m_swapchain != null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var chainDescription = new SwapChainDescription
|
var chainDescription = new SwapChainDescription
|
||||||
{
|
{
|
||||||
BufferCount = 2,
|
BufferCount = 2,
|
||||||
@@ -39,7 +39,7 @@ public static class SwapChainPatch
|
|||||||
Usage = Usage.ShaderInput | Usage.RenderTargetOutput,
|
Usage = Usage.ShaderInput | Usage.RenderTargetOutput,
|
||||||
SwapEffect = SwapEffect.Discard
|
SwapEffect = SwapEffect.Discard
|
||||||
};
|
};
|
||||||
|
|
||||||
var factory = MyPlatformRender.GetFactory();
|
var factory = MyPlatformRender.GetFactory();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -62,7 +62,7 @@ public static class SwapChainPatch
|
|||||||
{
|
{
|
||||||
ImGuiHandler.Instance?.Init(WindowHandle, MyRender11.DeviceInstance, MyRender11.RC.DeviceContext);
|
ImGuiHandler.Instance?.Init(WindowHandle, MyRender11.DeviceInstance, MyRender11.RC.DeviceContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix, HarmonyPatch(typeof(MyBackbuffer), MethodType.Constructor, typeof(SharpDX.Direct3D11.Resource))]
|
[HarmonyPrefix, HarmonyPatch(typeof(MyBackbuffer), MethodType.Constructor, typeof(SharpDX.Direct3D11.Resource))]
|
||||||
private static bool SwapChainBBPrefix(MyBackbuffer __instance, SharpDX.Direct3D11.Resource swapChainBB)
|
private static bool SwapChainBBPrefix(MyBackbuffer __instance, SharpDX.Direct3D11.Resource swapChainBB)
|
||||||
{
|
{
|
||||||
@@ -73,13 +73,13 @@ public static class SwapChainPatch
|
|||||||
Dimension = RenderTargetViewDimension.Texture2D,
|
Dimension = RenderTargetViewDimension.Texture2D,
|
||||||
});
|
});
|
||||||
__instance.m_srv = new ShaderResourceView(MyRender11.DeviceInstance, swapChainBB);
|
__instance.m_srv = new ShaderResourceView(MyRender11.DeviceInstance, swapChainBB);
|
||||||
|
|
||||||
ImGuiHandler.Rtv = new RenderTargetView(MyRender11.DeviceInstance, swapChainBB, new()
|
ImGuiHandler.Rtv = new RenderTargetView(MyRender11.DeviceInstance, swapChainBB, new()
|
||||||
{
|
{
|
||||||
Format = Format.R8G8B8A8_UNorm,
|
Format = Format.R8G8B8A8_UNorm,
|
||||||
Dimension = RenderTargetViewDimension.Texture2D,
|
Dimension = RenderTargetViewDimension.Texture2D,
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ public static class SwapChainPatch
|
|||||||
private static void SwapChainBBReleasePrefix(MyBackbuffer __instance)
|
private static void SwapChainBBReleasePrefix(MyBackbuffer __instance)
|
||||||
{
|
{
|
||||||
if (ImGuiHandler.Rtv is null) return;
|
if (ImGuiHandler.Rtv is null) return;
|
||||||
|
|
||||||
ImGuiHandler.Rtv.Dispose();
|
ImGuiHandler.Rtv.Dispose();
|
||||||
ImGuiHandler.Rtv = null;
|
ImGuiHandler.Rtv = null;
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -14,7 +14,7 @@ public static class WhitelistPatch
|
|||||||
private static void Prefix(MyScriptCompiler scriptCompiler)
|
private static void Prefix(MyScriptCompiler scriptCompiler)
|
||||||
{
|
{
|
||||||
var baseDir = new FileInfo(typeof(Type).Assembly.Location).DirectoryName!;
|
var baseDir = new FileInfo(typeof(Type).Assembly.Location).DirectoryName!;
|
||||||
|
|
||||||
scriptCompiler.AddReferencedAssemblies(
|
scriptCompiler.AddReferencedAssemblies(
|
||||||
typeof(Type).Assembly.Location,
|
typeof(Type).Assembly.Location,
|
||||||
typeof(LinkedList<>).Assembly.Location,
|
typeof(LinkedList<>).Assembly.Location,
|
||||||
|
@@ -9,7 +9,7 @@ public static class WhitelistTypeResolutionPatch
|
|||||||
{
|
{
|
||||||
[HarmonyReversePatch]
|
[HarmonyReversePatch]
|
||||||
private static INamedTypeSymbol ResolveTypeSymbol(MyScriptWhitelist.Batch batch, Type type) => throw null!;
|
private static INamedTypeSymbol ResolveTypeSymbol(MyScriptWhitelist.Batch batch, Type type) => throw null!;
|
||||||
|
|
||||||
// cant be assed to write a transpiler so heres a prefix
|
// cant be assed to write a transpiler so heres a prefix
|
||||||
private static bool Prefix(MyScriptWhitelist.Batch __instance, Type type, ref INamedTypeSymbol __result)
|
private static bool Prefix(MyScriptWhitelist.Batch __instance, Type type, ref INamedTypeSymbol __result)
|
||||||
{
|
{
|
||||||
@@ -26,18 +26,18 @@ public static class WhitelistTypeResolutionPatch
|
|||||||
// if type is not generic or constructed generic, run regular lookup
|
// if type is not generic or constructed generic, run regular lookup
|
||||||
if (!type.IsGenericType || !type.IsConstructedGenericType)
|
if (!type.IsGenericType || !type.IsConstructedGenericType)
|
||||||
return ResolveTypeSymbol(batch, type);
|
return ResolveTypeSymbol(batch, type);
|
||||||
|
|
||||||
var unconstructedSymbol = ResolveTypeSymbol(batch, type.GetGenericTypeDefinition());
|
var unconstructedSymbol = ResolveTypeSymbol(batch, type.GetGenericTypeDefinition());
|
||||||
|
|
||||||
var typeArguments = type.GetGenericArguments();
|
var typeArguments = type.GetGenericArguments();
|
||||||
|
|
||||||
var typeSymbolArguments = new ITypeSymbol[typeArguments.Length];
|
var typeSymbolArguments = new ITypeSymbol[typeArguments.Length];
|
||||||
for (var i = 0; i < typeArguments.Length; i++)
|
for (var i = 0; i < typeArguments.Length; i++)
|
||||||
{
|
{
|
||||||
// recursively resolve (possibly) generic arguments
|
// recursively resolve (possibly) generic arguments
|
||||||
typeSymbolArguments[i] = ResolveGenericTypeSymbol(batch, typeArguments[i]);
|
typeSymbolArguments[i] = ResolveGenericTypeSymbol(batch, typeArguments[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return unconstructedSymbol.Construct(typeSymbolArguments);
|
return unconstructedSymbol.Construct(typeSymbolArguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -11,26 +11,26 @@ public static class XmlRootWriterPatch
|
|||||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
{
|
{
|
||||||
var ins = instructions.ToList();
|
var ins = instructions.ToList();
|
||||||
|
|
||||||
var index = ins.FindIndex(b =>
|
var index = ins.FindIndex(b =>
|
||||||
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,11 +9,11 @@ namespace CringeLauncher.Utils;
|
|||||||
public static class ExceptionFormatter
|
public static class ExceptionFormatter
|
||||||
{
|
{
|
||||||
private static readonly AccessTools.FieldRef<Exception, string> StackTraceField = AccessTools.FieldRefAccess<Exception, string>("_remoteStackTraceString");
|
private static readonly AccessTools.FieldRef<Exception, string> StackTraceField = AccessTools.FieldRefAccess<Exception, string>("_remoteStackTraceString");
|
||||||
|
|
||||||
public static void FormatStackTrace(this Exception exception)
|
public static void FormatStackTrace(this Exception exception)
|
||||||
{
|
{
|
||||||
var stackTrace = new StackTrace(exception, true);
|
var stackTrace = new StackTrace(exception, true);
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
@@ -22,12 +22,12 @@ public static class ExceptionFormatter
|
|||||||
var method = frame.GetMethod();
|
var method = frame.GetMethod();
|
||||||
if (method is null)
|
if (method is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sb.Append("at ");
|
sb.Append("at ");
|
||||||
if (method.DeclaringType is { } declaringType &&
|
if (method.DeclaringType is { } declaringType &&
|
||||||
AssemblyLoadContext.GetLoadContext(declaringType.Assembly) is { } assemblyLoadContext)
|
AssemblyLoadContext.GetLoadContext(declaringType.Assembly) is { } assemblyLoadContext)
|
||||||
sb.Append(assemblyLoadContext).Append("//");
|
sb.Append(assemblyLoadContext).Append("//");
|
||||||
|
|
||||||
if (method.IsStatic)
|
if (method.IsStatic)
|
||||||
sb.Append("static ");
|
sb.Append("static ");
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ public static class ExceptionFormatter
|
|||||||
sb.Append(methodInfo.ReturnType, false);
|
sb.Append(methodInfo.ReturnType, false);
|
||||||
else
|
else
|
||||||
sb.Append("new");
|
sb.Append("new");
|
||||||
|
|
||||||
sb.Append(' ');
|
sb.Append(' ');
|
||||||
|
|
||||||
if (method.DeclaringType is null)
|
if (method.DeclaringType is null)
|
||||||
@@ -48,7 +48,7 @@ public static class ExceptionFormatter
|
|||||||
sb.Append('.');
|
sb.Append('.');
|
||||||
sb.Append(method.Name);
|
sb.Append(method.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method.ContainsGenericParameters)
|
if (method.ContainsGenericParameters)
|
||||||
sb.Append(method.GetGenericArguments(), false);
|
sb.Append(method.GetGenericArguments(), false);
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ public static class ExceptionFormatter
|
|||||||
if (j < parameters.Length - 1)
|
if (j < parameters.Length - 1)
|
||||||
sb.Append(", ");
|
sb.Append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.Append(')');
|
sb.Append(')');
|
||||||
|
|
||||||
if (frame.GetFileName() is { } fileName)
|
if (frame.GetFileName() is { } fileName)
|
||||||
@@ -75,7 +75,7 @@ public static class ExceptionFormatter
|
|||||||
}
|
}
|
||||||
|
|
||||||
ref var stackTraceString = ref StackTraceField(exception);
|
ref var stackTraceString = ref StackTraceField(exception);
|
||||||
|
|
||||||
stackTraceString = sb.ToString();
|
stackTraceString = sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,9 +84,9 @@ public static class ExceptionFormatter
|
|||||||
if (fullName && !string.IsNullOrEmpty(type.Namespace))
|
if (fullName && !string.IsNullOrEmpty(type.Namespace))
|
||||||
sb.Append(type.Namespace).Append('.');
|
sb.Append(type.Namespace).Append('.');
|
||||||
sb.Append(type.Name);
|
sb.Append(type.Name);
|
||||||
if (type.ContainsGenericParameters)
|
if (type.ContainsGenericParameters)
|
||||||
sb.Append(type.GetGenericArguments(), fullName);
|
sb.Append(type.GetGenericArguments(), fullName);
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ public static class MethodTools
|
|||||||
public static MethodInfo AsyncMethodBody(MethodInfo method)
|
public static MethodInfo AsyncMethodBody(MethodInfo method)
|
||||||
{
|
{
|
||||||
var (_, operand) = PatchProcessor.ReadMethodBody(method).First();
|
var (_, operand) = PatchProcessor.ReadMethodBody(method).First();
|
||||||
|
|
||||||
if (operand is not LocalVariableInfo localVar)
|
if (operand is not LocalVariableInfo localVar)
|
||||||
throw new InvalidOperationException($"Method {method.FullDescription()} does not contain a valid async state machine");
|
throw new InvalidOperationException($"Method {method.FullDescription()} does not contain a valid async state machine");
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
}
|
@@ -51,7 +51,7 @@ internal class PluginAssemblyLoadContext : DerivedAssemblyLoadContext
|
|||||||
{
|
{
|
||||||
if (_dependencyResolver.ResolveAssemblyToPath(assemblyName) is { } path)
|
if (_dependencyResolver.ResolveAssemblyToPath(assemblyName) is { } path)
|
||||||
return LoadFromAssemblyPath(path);
|
return LoadFromAssemblyPath(path);
|
||||||
|
|
||||||
return base.Load(assemblyName);
|
return base.Load(assemblyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ internal class PluginAssemblyLoadContext : DerivedAssemblyLoadContext
|
|||||||
{
|
{
|
||||||
if (_dependencyResolver.ResolveUnmanagedDllToPath(unmanagedDllName) is { } path)
|
if (_dependencyResolver.ResolveUnmanagedDllToPath(unmanagedDllName) is { } path)
|
||||||
return LoadUnmanagedDllFromPath(path);
|
return LoadUnmanagedDllFromPath(path);
|
||||||
|
|
||||||
return base.LoadUnmanagedDll(unmanagedDllName);
|
return base.LoadUnmanagedDll(unmanagedDllName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,14 +29,14 @@ internal sealed class PluginInstance(PluginMetadata metadata, string entrypointP
|
|||||||
{
|
{
|
||||||
if (AssemblyLoadContext.GetLoadContext(typeof(PluginInstance).Assembly) is not ICoreLoadContext parentContext)
|
if (AssemblyLoadContext.GetLoadContext(typeof(PluginInstance).Assembly) is not ICoreLoadContext parentContext)
|
||||||
throw new NotSupportedException("Plugin instantiation is not supported in this context");
|
throw new NotSupportedException("Plugin instantiation is not supported in this context");
|
||||||
|
|
||||||
_context = new PluginAssemblyLoadContext(parentContext, entrypointPath);
|
_context = new PluginAssemblyLoadContext(parentContext, entrypointPath);
|
||||||
contextBuilder.Add(_context);
|
contextBuilder.Add(_context);
|
||||||
|
|
||||||
var entrypoint = _context.LoadEntrypoint();
|
var entrypoint = _context.LoadEntrypoint();
|
||||||
|
|
||||||
var plugins = IntrospectionContext.Global.CollectDerivedTypes<IPlugin>(entrypoint.GetMainModule()).ToArray();
|
var plugins = IntrospectionContext.Global.CollectDerivedTypes<IPlugin>(entrypoint.GetMainModule()).ToArray();
|
||||||
|
|
||||||
if (plugins.Length == 0)
|
if (plugins.Length == 0)
|
||||||
throw new InvalidOperationException("Entrypoint does not contain any plugins");
|
throw new InvalidOperationException("Entrypoint does not contain any plugins");
|
||||||
if (plugins.Length > 1)
|
if (plugins.Length > 1)
|
||||||
@@ -66,7 +66,7 @@ internal sealed class PluginInstance(PluginMetadata metadata, string entrypointP
|
|||||||
{
|
{
|
||||||
if (_instance is null)
|
if (_instance is null)
|
||||||
throw new InvalidOperationException("Must call Instantiate first");
|
throw new InvalidOperationException("Must call Instantiate first");
|
||||||
|
|
||||||
MyPlugins.m_plugins.Add(WrappedInstance);
|
MyPlugins.m_plugins.Add(WrappedInstance);
|
||||||
if (_instance is IHandleInputPlugin)
|
if (_instance is IHandleInputPlugin)
|
||||||
MyPlugins.m_handleInputPlugins.Add(WrappedInstance);
|
MyPlugins.m_handleInputPlugins.Add(WrappedInstance);
|
||||||
|
@@ -19,7 +19,7 @@ public record PluginMetadata(string Name, NuGetVersion Version, string Source)
|
|||||||
(versionAttribute ?? fileVersionAttribute)?.ConstructorArguments[0].Value as UTF8String ?? "0.0.0.0",
|
(versionAttribute ?? fileVersionAttribute)?.ConstructorArguments[0].Value as UTF8String ?? "0.0.0.0",
|
||||||
out var version))
|
out var version))
|
||||||
version = new(0, 0, 0, 0);
|
version = new(0, 0, 0, 0);
|
||||||
|
|
||||||
return new(name, version, "Local");
|
return new(name, version, "Local");
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -14,7 +14,7 @@ internal sealed class PluginWrapper(PluginMetadata metadata, IPlugin plugin) : I
|
|||||||
public Type InstanceType => plugin.GetType();
|
public Type InstanceType => plugin.GetType();
|
||||||
|
|
||||||
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
private readonly IHandleInputPlugin? _handleInputPlugin = plugin as IHandleInputPlugin;
|
private readonly IHandleInputPlugin? _handleInputPlugin = plugin as IHandleInputPlugin;
|
||||||
|
|
||||||
private const float ErrorShowTime = 10f;
|
private const float ErrorShowTime = 10f;
|
||||||
|
@@ -20,14 +20,15 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
public static ImmutableArray<DerivedAssemblyLoadContext> Contexts { get; private set; } = [];
|
public static ImmutableArray<DerivedAssemblyLoadContext> Contexts { get; private set; } = [];
|
||||||
|
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public string Name => "Loading Plugins";
|
public string Name => "Loading Plugins";
|
||||||
|
|
||||||
private ImmutableArray<PluginInstance> _plugins = [];
|
private ImmutableArray<PluginInstance> _plugins = [];
|
||||||
private readonly DirectoryInfo _dir = Directory.CreateDirectory(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher"));
|
private readonly DirectoryInfo _dir = Directory.CreateDirectory(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher"));
|
||||||
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()
|
||||||
@@ -87,7 +92,7 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
PackagesConfig packagesConfig, ImmutableDictionary<string, ResolvedPackage> builtInPackages)
|
PackagesConfig packagesConfig, ImmutableDictionary<string, ResolvedPackage> builtInPackages)
|
||||||
{
|
{
|
||||||
var plugins = _plugins.ToBuilder();
|
var plugins = _plugins.ToBuilder();
|
||||||
|
|
||||||
var resolvedPackages = builtInPackages.ToDictionary();
|
var resolvedPackages = builtInPackages.ToDictionary();
|
||||||
foreach (var package in packages)
|
foreach (var package in packages)
|
||||||
{
|
{
|
||||||
@@ -100,14 +105,14 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
resolvedPackages.TryGetValue(dependency.Id, out var package);
|
resolvedPackages.TryGetValue(dependency.Id, out var package);
|
||||||
return package?.Entry;
|
return package?.Entry;
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var package in packages)
|
foreach (var package in packages)
|
||||||
{
|
{
|
||||||
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,29 +138,29 @@ 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
_plugins = plugins.ToImmutable();
|
_plugins = plugins.ToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DiscoverLocalPlugins(DirectoryInfo dir)
|
private void DiscoverLocalPlugins(DirectoryInfo dir)
|
||||||
{
|
{
|
||||||
var plugins = ImmutableArray<PluginInstance>.Empty.ToBuilder();
|
var plugins = ImmutableArray<PluginInstance>.Empty.ToBuilder();
|
||||||
|
|
||||||
foreach (var directory in dir.EnumerateDirectories())
|
foreach (var directory in dir.EnumerateDirectories())
|
||||||
{
|
{
|
||||||
var files = directory.GetFiles("*.deps.json");
|
var files = directory.GetFiles("*.deps.json");
|
||||||
|
|
||||||
if (files.Length != 1) continue;
|
if (files.Length != 1) continue;
|
||||||
|
|
||||||
var path = files[0].FullName[..^".deps.json".Length] + ".dll";
|
var path = files[0].FullName[..^".deps.json".Length] + ".dll";
|
||||||
|
|
||||||
LoadComponent(plugins, path);
|
LoadComponent(plugins, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
_plugins = plugins.ToImmutable();
|
_plugins = plugins.ToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +171,7 @@ internal class PluginsLifetime(ConfigHandler configHandler, HttpClient client) :
|
|||||||
plugins.Add(metadata is null ? new PluginInstance(path) : new(metadata, path));
|
plugins.Add(metadata is null ? new PluginInstance(path) : new(metadata, path));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error(e, "Failed to load plugin {PluginPath}", path);
|
Log.Error(e, "Failed to load plugin {PluginPath}", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,10 +33,10 @@ public static class BuiltInPackages
|
|||||||
(_, _, _, libraries) = await DependencyManifestSerializer.DeserializeAsync(stream);
|
(_, _, _, libraries) = await DependencyManifestSerializer.DeserializeAsync(stream);
|
||||||
|
|
||||||
var framework = runtimeFramework.Framework;
|
var framework = runtimeFramework.Framework;
|
||||||
|
|
||||||
var nlog = FromAssembly<LogFactory>(framework, version: libraries.Keys.Single(b => b.Id == NLog).Version);
|
var nlog = FromAssembly<LogFactory>(framework, version: libraries.Keys.Single(b => b.Id == NLog).Version);
|
||||||
Version seVersion = new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion!.Value);
|
Version seVersion = new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion!.Value);
|
||||||
|
|
||||||
var se = FromAssembly<SpaceEngineersGame>(framework, [
|
var se = FromAssembly<SpaceEngineersGame>(framework, [
|
||||||
nlog.AsDependency(libraries)
|
nlog.AsDependency(libraries)
|
||||||
], SeReferenceAssemblies, new(seVersion));
|
], SeReferenceAssemblies, new(seVersion));
|
||||||
@@ -50,7 +50,7 @@ public static class BuiltInPackages
|
|||||||
var def = ModuleDefMD.Load(r.ImageBytes, IntrospectionContext.Global.Context);
|
var def = ModuleDefMD.Load(r.ImageBytes, IntrospectionContext.Global.Context);
|
||||||
var attribute = def.CustomAttributes.Find(typeof(AssemblyFileVersionAttribute).FullName);
|
var attribute = def.CustomAttributes.Find(typeof(AssemblyFileVersionAttribute).FullName);
|
||||||
var version = attribute is null ? new(99, 0, 0) : NuGetVersion.Parse((string)attribute.ConstructorArguments[0].Value);
|
var version = attribute is null ? new(99, 0, 0) : NuGetVersion.Parse((string)attribute.ConstructorArguments[0].Value);
|
||||||
|
|
||||||
return new BuiltInSdkPackage(
|
return new BuiltInSdkPackage(
|
||||||
new(0, Path.GetFileNameWithoutExtension(r.FileName), version), framework,
|
new(0, Path.GetFileNameWithoutExtension(r.FileName), version), framework,
|
||||||
new(Path.GetFileNameWithoutExtension(r.FileName), version, [new(framework, [])], null, []));
|
new(Path.GetFileNameWithoutExtension(r.FileName), version, [new(framework, [])], null, []));
|
||||||
@@ -95,16 +95,16 @@ public static class BuiltInPackages
|
|||||||
var builder = ImmutableDictionary.CreateBuilder<string, ResolvedPackage>();
|
var builder = ImmutableDictionary.CreateBuilder<string, ResolvedPackage>();
|
||||||
foreach (var package in packages)
|
foreach (var package in packages)
|
||||||
builder.TryAdd(package.Package.Id, package);
|
builder.TryAdd(package.Package.Id, package);
|
||||||
|
|
||||||
return builder.ToImmutable();
|
return builder.ToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dependency AsDependency(this ResolvedPackage package, ImmutableDictionary<ManifestPackageKey, DependencyLibrary> libraries)
|
private static Dependency AsDependency(this ResolvedPackage package, ImmutableDictionary<ManifestPackageKey, DependencyLibrary> libraries)
|
||||||
{
|
{
|
||||||
//ignore the SE reference because the game can update without a launcher update
|
//ignore the SE reference because the game can update without a launcher update
|
||||||
if (package.Entry.Id != SeReferenceAssemblies && !libraries.ContainsKey(new(package.Package.Id, package.Package.Version)))
|
if (package.Entry.Id != SeReferenceAssemblies && !libraries.ContainsKey(new(package.Package.Id, package.Package.Version)))
|
||||||
throw new KeyNotFoundException($"Package {package.Package} not found in root dependencies manifest");
|
throw new KeyNotFoundException($"Package {package.Package} not found in root dependencies manifest");
|
||||||
|
|
||||||
return new Dependency(package.Package.Id, new(package.Package.Version));
|
return new Dependency(package.Package.Id, new(package.Package.Version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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,26 +39,43 @@ 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}");
|
||||||
|
|
||||||
var catalogEntry = items[version].CatalogEntry;
|
var catalogEntry = items[version].CatalogEntry;
|
||||||
|
|
||||||
var package = new Package(order, reference.Id, version);
|
var package = new Package(order, reference.Id, version);
|
||||||
|
|
||||||
if (packages.TryAdd(package, catalogEntry))
|
if (packages.TryAdd(package, catalogEntry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!packages.TryGetValue(package, out var existingEntry))
|
if (!packages.TryGetValue(package, out var existingEntry))
|
||||||
throw new InvalidOperationException($"Duplicate package error {package.Id}");
|
throw new InvalidOperationException($"Duplicate package error {package.Id}");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (package.Version < existingEntry.Version)
|
if (package.Version < existingEntry.Version)
|
||||||
throw new NotSupportedException($"Package reference {package.Id} has lower version {package.Version} than already resolved {existingEntry.Version}");
|
throw new NotSupportedException($"Package reference {package.Id} has lower version {package.Version} than already resolved {existingEntry.Version}");
|
||||||
|
|
||||||
if (package.Version == existingEntry.Version)
|
if (package.Version == existingEntry.Version)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -69,13 +86,13 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
foreach (var (package, catalogEntry) in packages)
|
foreach (var (package, catalogEntry) in packages)
|
||||||
{
|
{
|
||||||
var client = await packageSources.GetClientAsync(package.Id);
|
var client = await packageSources.GetClientAsync(package.Id);
|
||||||
|
|
||||||
if (client == null || !catalogEntry.DependencyGroups.HasValue)
|
if (client == null || !catalogEntry.DependencyGroups.HasValue)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var nearestGroup = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups.Value, runtimeFramework,
|
var nearestGroup = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups.Value, runtimeFramework,
|
||||||
g => g.TargetFramework);
|
g => g.TargetFramework);
|
||||||
|
|
||||||
if (nearestGroup is null)
|
if (nearestGroup is null)
|
||||||
throw new NotSupportedException($"Unable to find compatible dependency group for package {package.Id}");
|
throw new NotSupportedException($"Unable to find compatible dependency group for package {package.Id}");
|
||||||
|
|
||||||
@@ -91,14 +108,14 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
var dependencies = package.Entry.DependencyGroups
|
var dependencies = package.Entry.DependencyGroups
|
||||||
?.Single(b => b.TargetFramework == package.ResolvedFramework)?.Dependencies ??
|
?.Single(b => b.TargetFramework == package.ResolvedFramework)?.Dependencies ??
|
||||||
[];
|
[];
|
||||||
|
|
||||||
foreach (var (id, versionRange) in dependencies)
|
foreach (var (id, versionRange) in dependencies)
|
||||||
{
|
{
|
||||||
var client = await packageSources.GetClientAsync(id);
|
var client = await packageSources.GetClientAsync(id);
|
||||||
|
|
||||||
if (client == null)
|
if (client == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
RegistrationRoot? registrationRoot;
|
RegistrationRoot? registrationRoot;
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -109,15 +126,29 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Failed to resolve dependency {id} for {package.Package}", ex);
|
throw new InvalidOperationException($"Failed to resolve dependency {id} for {package.Package}", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = registrationRoot.Items.SelectMany(page => page.Items!)
|
var items = registrationRoot.Items.SelectMany(page => page.Items!)
|
||||||
.ToImmutableDictionary(b => b.CatalogEntry.Version);
|
.ToImmutableDictionary(b => b.CatalogEntry.Version);
|
||||||
|
|
||||||
var version = items.Values.Select(b => b.CatalogEntry.Version).OrderDescending().FirstOrDefault(versionRange.Satisfies);
|
var version = items.Values.Select(b => b.CatalogEntry.Version).OrderDescending().FirstOrDefault(versionRange.Satisfies);
|
||||||
|
|
||||||
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);
|
||||||
@@ -165,10 +196,10 @@ public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<Pac
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!packages.TryAdd(dependencyPackage, catalogEntry) || !dependencyVersions.TryAdd(dependencyPackage, versionRange))
|
if (!packages.TryAdd(dependencyPackage, catalogEntry) || !dependencyVersions.TryAdd(dependencyPackage, versionRange))
|
||||||
throw new InvalidOperationException($"Duplicate package {dependencyPackage.Id}");
|
throw new InvalidOperationException($"Duplicate package {dependencyPackage.Id}");
|
||||||
|
|
||||||
var nearestGroup = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups ?? [], runtimeFramework,
|
var nearestGroup = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups ?? [], runtimeFramework,
|
||||||
g => g.TargetFramework) ?? throw new NotSupportedException($"Unable to find compatible dependency group for {dependencyPackage} as dependency of {package.Package}");
|
g => g.TargetFramework) ?? throw new NotSupportedException($"Unable to find compatible dependency group for {dependencyPackage} as dependency of {package.Package}");
|
||||||
|
|
||||||
@@ -182,11 +213,30 @@ 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();
|
||||||
|
|
||||||
var i = 0f;
|
var i = 0f;
|
||||||
foreach (var package in resolvedPackages)
|
foreach (var package in resolvedPackages)
|
||||||
{
|
{
|
||||||
@@ -206,26 +256,26 @@ 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);
|
||||||
archive.ExtractToDirectory(dir.FullName);
|
archive.ExtractToDirectory(dir.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
packages.Add(new CachedPackage(package.Package, package.ResolvedFramework, dir, package.Entry));
|
packages.Add(new CachedPackage(package.Package, package.ResolvedFramework, dir, package.Entry));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CachedPackage cachedPackage:
|
case CachedPackage cachedPackage:
|
||||||
packages.Add(cachedPackage);
|
packages.Add(cachedPackage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progress?.Report(i++ / resolvedPackages.Count);
|
progress?.Report(i++ / resolvedPackages.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return packages.ToImmutable();
|
return packages.ToImmutable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,7 +48,7 @@ internal sealed class ImGuiImageService(HttpClient client) : IImGuiImageService
|
|||||||
});
|
});
|
||||||
|
|
||||||
var srv = new ShaderResourceView(MyRender11.DeviceInstance, tex);
|
var srv = new ShaderResourceView(MyRender11.DeviceInstance, tex);
|
||||||
|
|
||||||
_placeholderImage = new Image(null!, srv, new(1, 1));
|
_placeholderImage = new Image(null!, srv, new(1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,12 +88,12 @@ internal sealed class ImGuiImageService(HttpClient client) : IImGuiImageService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||||
if (_webCacheEtag.TryGetValue(new(url), out var existingEtag))
|
if (_webCacheEtag.TryGetValue(new(url), out var existingEtag))
|
||||||
request.Headers.IfNoneMatch.Add(existingEtag);
|
request.Headers.IfNoneMatch.Add(existingEtag);
|
||||||
using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
if (response.Headers.ETag is { } etag)
|
if (response.Headers.ETag is { } etag)
|
||||||
_webCacheEtag[new(url)] = etag;
|
_webCacheEtag[new(url)] = etag;
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ internal sealed class ImGuiImageService(HttpClient client) : IImGuiImageService
|
|||||||
if (cacheControl.MaxAge.HasValue)
|
if (cacheControl.MaxAge.HasValue)
|
||||||
{
|
{
|
||||||
var responseAge = DateTimeOffset.UtcNow - cacheControl.MaxAge.Value;
|
var responseAge = DateTimeOffset.UtcNow - cacheControl.MaxAge.Value;
|
||||||
return File.GetLastWriteTimeUtc(path) > responseAge;
|
return File.GetLastWriteTimeUtc(path) > responseAge;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -160,14 +160,14 @@ internal sealed class ImGuiImageService(HttpClient client) : IImGuiImageService
|
|||||||
CpuAccessFlags = CpuAccessFlags.None,
|
CpuAccessFlags = CpuAccessFlags.None,
|
||||||
OptionFlags = ResourceOptionFlags.None,
|
OptionFlags = ResourceOptionFlags.None,
|
||||||
}, img.ToDataBox());
|
}, img.ToDataBox());
|
||||||
|
|
||||||
var srv = new ShaderResourceView(MyRender11.DeviceInstance, tex);
|
var srv = new ShaderResourceView(MyRender11.DeviceInstance, tex);
|
||||||
|
|
||||||
image = new Image(identifier, srv, new(desc.Width, desc.Height));
|
image = new Image(identifier, srv, new(desc.Width, desc.Height));
|
||||||
_images.Add(identifier, image, true);
|
_images.Add(identifier, image, true);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ImageReference(ImGuiImage placeholderImage) : ImGuiImage
|
private class ImageReference(ImGuiImage placeholderImage) : ImGuiImage
|
||||||
{
|
{
|
||||||
public ImGuiImage? Image;
|
public ImGuiImage? Image;
|
||||||
@@ -175,14 +175,14 @@ internal sealed class ImGuiImageService(HttpClient client) : IImGuiImageService
|
|||||||
|
|
||||||
public override nint TextureId => Image ?? ErrorImage ?? placeholderImage;
|
public override nint TextureId => Image ?? ErrorImage ?? placeholderImage;
|
||||||
public override Vector2 Size => Image ?? ErrorImage ?? placeholderImage;
|
public override Vector2 Size => Image ?? ErrorImage ?? placeholderImage;
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
Image?.Dispose();
|
Image?.Dispose();
|
||||||
ErrorImage?.Dispose();
|
ErrorImage?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Image(ImageIdentifier identifier, ShaderResourceView srv, Vector2 size) : ImGuiImage
|
private class Image(ImageIdentifier identifier, ShaderResourceView srv, Vector2 size) : ImGuiImage
|
||||||
{
|
{
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
@@ -210,7 +210,7 @@ internal sealed class ImGuiImageService(HttpClient client) : IImGuiImageService
|
|||||||
|
|
||||||
private void OnUse()
|
private void OnUse()
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_lastUse = Stopwatch.GetTimestamp();
|
_lastUse = Stopwatch.GetTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,20 +223,20 @@ internal sealed class ImGuiImageService(HttpClient client) : IImGuiImageService
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"Image {{ {identifier} {size} }}";
|
return $"Image {{ {identifier} {size} }}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract record ImageIdentifier;
|
private abstract record ImageIdentifier;
|
||||||
private record WebImageIdentifier(Uri Url) : ImageIdentifier;
|
private record WebImageIdentifier(Uri Url) : ImageIdentifier;
|
||||||
private record FileImageIdentifier(string Path) : ImageIdentifier;
|
private record FileImageIdentifier(string Path) : ImageIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class ImGuiImage : IDisposable
|
public abstract class ImGuiImage : IDisposable
|
||||||
{
|
{
|
||||||
public abstract nint TextureId { get; }
|
public abstract nint TextureId { get; }
|
||||||
public abstract Vector2 Size { get; }
|
public abstract Vector2 Size { get; }
|
||||||
|
|
||||||
public static implicit operator nint(ImGuiImage image) => image.TextureId;
|
public static implicit operator nint(ImGuiImage image) => image.TextureId;
|
||||||
public static implicit operator Vector2(ImGuiImage image) => image.Size;
|
public static implicit operator Vector2(ImGuiImage image) => image.Size;
|
||||||
public abstract void Dispose();
|
public abstract void Dispose();
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
namespace CringePlugins.Splash;
|
namespace CringePlugins.Splash;
|
||||||
|
|
||||||
public interface ISplashProgress : IProgress<ProgressInfo>, IProgress<float>
|
public interface ISplashProgress : IProgress<ProgressInfo>, IProgress<float>
|
||||||
{
|
{
|
||||||
void DefineStage(ILoadingStage stage);
|
void DefineStage(ILoadingStage stage);
|
||||||
void DefineStepsCount(int count);
|
void DefineStepsCount(int count);
|
||||||
|
@@ -10,16 +10,16 @@ namespace CringePlugins.Splash;
|
|||||||
public class Splash : ISplashProgress, IRenderComponent
|
public class Splash : ISplashProgress, IRenderComponent
|
||||||
{
|
{
|
||||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
private readonly List<ILoadingStage> _loadingStages = [];
|
private readonly List<ILoadingStage> _loadingStages = [];
|
||||||
|
|
||||||
private ProgressInfo? _lastInfo;
|
private ProgressInfo? _lastInfo;
|
||||||
private bool _done;
|
private bool _done;
|
||||||
|
|
||||||
public void Report(ProgressInfo value)
|
public void Report(ProgressInfo value)
|
||||||
{
|
{
|
||||||
_lastInfo = value;
|
_lastInfo = value;
|
||||||
|
|
||||||
if (value is PercentProgressInfo percentProgressInfo)
|
if (value is PercentProgressInfo percentProgressInfo)
|
||||||
Logger.Info("{Text} {Percent:P0}", percentProgressInfo.Text, percentProgressInfo.Percent);
|
Logger.Info("{Text} {Percent:P0}", percentProgressInfo.Text, percentProgressInfo.Percent);
|
||||||
else
|
else
|
||||||
@@ -58,7 +58,7 @@ public class Splash : ISplashProgress, IRenderComponent
|
|||||||
public void OnFrame()
|
public void OnFrame()
|
||||||
{
|
{
|
||||||
if (_done) return;
|
if (_done) return;
|
||||||
|
|
||||||
SetNextWindowPos(GetMainViewport().GetCenter(), ImGuiCond.Always, new(.5f, .5f));
|
SetNextWindowPos(GetMainViewport().GetCenter(), ImGuiCond.Always, new(.5f, .5f));
|
||||||
SetNextWindowSize(new(400, GetFrameHeightWithSpacing()), ImGuiCond.Always);
|
SetNextWindowSize(new(400, GetFrameHeightWithSpacing()), ImGuiCond.Always);
|
||||||
Begin("Splash", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoInputs);
|
Begin("Splash", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoInputs);
|
||||||
@@ -68,13 +68,13 @@ public class Splash : ISplashProgress, IRenderComponent
|
|||||||
{
|
{
|
||||||
const string text = "Loading...";
|
const string text = "Loading...";
|
||||||
var size = CalcTextSize(text);
|
var size = CalcTextSize(text);
|
||||||
|
|
||||||
SetCursorPosX((GetWindowWidth() - size.X) * .5f);
|
SetCursorPosX((GetWindowWidth() - size.X) * .5f);
|
||||||
Text(text);
|
Text(text);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ProgressBar((_lastInfo as PercentProgressInfo)?.Percent ?? 0, sizeArg, _lastInfo.Text);
|
ProgressBar((_lastInfo as PercentProgressInfo)?.Percent ?? 0, sizeArg, _lastInfo.Text);
|
||||||
|
|
||||||
End();
|
End();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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;)
|
||||||
{
|
{
|
||||||
@@ -76,7 +75,7 @@ public sealed class NotificationsComponent : IRenderComponent
|
|||||||
|
|
||||||
|
|
||||||
Notifications.RemoveAll(x => x.IsGarbage);
|
Notifications.RemoveAll(x => x.IsGarbage);
|
||||||
|
|
||||||
_time += MyCommon.GetLastFrameDelta();
|
_time += MyCommon.GetLastFrameDelta();
|
||||||
}
|
}
|
||||||
public static void SpawnNotification(float showTime, Action renderCallback)
|
public static void SpawnNotification(float showTime, Action renderCallback)
|
||||||
|
@@ -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"))
|
||||||
{
|
{
|
||||||
@@ -172,7 +179,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
{
|
{
|
||||||
var source = _packagesConfig.Value.Sources[index];
|
var source = _packagesConfig.Value.Sources[index];
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
|
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
|
|
||||||
if (Selectable(source.Name, index == _selectedSource?.index, ImGuiSelectableFlags.SpanAllColumns))
|
if (Selectable(source.Name, index == _selectedSource?.index, ImGuiSelectableFlags.SpanAllColumns))
|
||||||
@@ -187,12 +194,12 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
|
|
||||||
EndTable();
|
EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
EndChild();
|
EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
SameLine();
|
SameLine();
|
||||||
|
|
||||||
BeginGroup();
|
BeginGroup();
|
||||||
|
|
||||||
BeginChild("Source View", new(0, -GetFrameHeightWithSpacing())); // Leave room for 1 line below us
|
BeginChild("Source View", new(0, -GetFrameHeightWithSpacing())); // Leave room for 1 line below us
|
||||||
@@ -200,7 +207,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
if (_selectedSource is not null)
|
if (_selectedSource is not null)
|
||||||
{
|
{
|
||||||
var (selectedSource, index) = _selectedSource.Value;
|
var (selectedSource, index) = _selectedSource.Value;
|
||||||
|
|
||||||
var name = selectedSource.Name;
|
var name = selectedSource.Name;
|
||||||
if (InputText("Name", ref name, 256))
|
if (InputText("Name", ref name, 256))
|
||||||
selectedSource = selectedSource with
|
selectedSource = selectedSource with
|
||||||
@@ -214,7 +221,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
{
|
{
|
||||||
Url = url
|
Url = url
|
||||||
};
|
};
|
||||||
|
|
||||||
var pattern = selectedSource.Pattern;
|
var pattern = selectedSource.Pattern;
|
||||||
if (InputText("Pattern", ref pattern, 1024))
|
if (InputText("Pattern", ref pattern, 1024))
|
||||||
selectedSource = selectedSource with
|
selectedSource = selectedSource with
|
||||||
@@ -237,7 +244,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
|
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
SameLine();
|
SameLine();
|
||||||
|
|
||||||
if (Button("Delete"))
|
if (Button("Delete"))
|
||||||
@@ -254,7 +261,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EndChild();
|
EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,14 +278,22 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
|
|
||||||
_selectedSource = (source, array.Length - 1);
|
_selectedSource = (source, array.Length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndGroup();
|
EndGroup();
|
||||||
|
|
||||||
EndTabItem();
|
EndTabItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
@@ -545,9 +563,9 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
|
|
||||||
EndCombo();
|
EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacing();
|
Spacing();
|
||||||
|
|
||||||
switch (_searchTask)
|
switch (_searchTask)
|
||||||
{
|
{
|
||||||
case { IsCompleted: false }:
|
case { IsCompleted: false }:
|
||||||
@@ -733,9 +751,9 @@ 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
|
||||||
{
|
{
|
||||||
var result = await source.SearchPackagesAsync(_searchQuery, take: 1000, packageType: "CringePlugin");
|
var result = await source.SearchPackagesAsync(_searchQuery, take: 1000, packageType: "CringePlugin");
|
||||||
@@ -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)
|
||||||
|
@@ -13,17 +13,17 @@ public class IntrospectionContext
|
|||||||
public IntrospectionContext()
|
public IntrospectionContext()
|
||||||
{
|
{
|
||||||
var assemblyResolver = new AssemblyResolver();
|
var assemblyResolver = new AssemblyResolver();
|
||||||
|
|
||||||
assemblyResolver.PreSearchPaths.Add(AppContext.BaseDirectory);
|
assemblyResolver.PreSearchPaths.Add(AppContext.BaseDirectory);
|
||||||
assemblyResolver.PreSearchPaths.Add(MyFileSystem.ExePath);
|
assemblyResolver.PreSearchPaths.Add(MyFileSystem.ExePath);
|
||||||
|
|
||||||
Context = new(assemblyResolver);
|
Context = new(assemblyResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Type> CollectAttributedTypes<TAttribute>(Module module, bool allowAbstract = false) where TAttribute : Attribute
|
public IEnumerable<Type> CollectAttributedTypes<TAttribute>(Module module, bool allowAbstract = false) where TAttribute : Attribute
|
||||||
{
|
{
|
||||||
var moduleDef = ModuleDefMD.Load(module, Context);
|
var moduleDef = ModuleDefMD.Load(module, Context);
|
||||||
|
|
||||||
var token = moduleDef.ImportAsTypeSig(typeof(TAttribute));
|
var token = moduleDef.ImportAsTypeSig(typeof(TAttribute));
|
||||||
|
|
||||||
return moduleDef.GetTypes()
|
return moduleDef.GetTypes()
|
||||||
@@ -53,7 +53,7 @@ public class IntrospectionContext
|
|||||||
if (defOrRef.FullName == token.FullName)
|
if (defOrRef.FullName == token.FullName)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ public class FrameworkJsonConverter(FrameworkNameFormat format) : JsonConverter<
|
|||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType != JsonTokenType.String)
|
||||||
throw new JsonException("Invalid framework string");
|
throw new JsonException("Invalid framework string");
|
||||||
|
|
||||||
var s = reader.GetString()!;
|
var s = reader.GetString()!;
|
||||||
return format switch
|
return format switch
|
||||||
{
|
{
|
||||||
|
@@ -10,7 +10,7 @@ public class ManifestPackageKeyJsonConverter : JsonConverter<ManifestPackageKey>
|
|||||||
{
|
{
|
||||||
if (reader.TokenType is not (JsonTokenType.String or JsonTokenType.PropertyName))
|
if (reader.TokenType is not (JsonTokenType.String or JsonTokenType.PropertyName))
|
||||||
throw new JsonException("Invalid package key string");
|
throw new JsonException("Invalid package key string");
|
||||||
|
|
||||||
return ManifestPackageKey.Parse(reader.GetString()!);
|
return ManifestPackageKey.Parse(reader.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,12 +19,12 @@ public class PackageAuthorsJsonConverter : JsonConverter<PackageAuthors>
|
|||||||
case JsonTokenType.StartArray:
|
case JsonTokenType.StartArray:
|
||||||
{
|
{
|
||||||
var builder = ImmutableArray.CreateBuilder<string>();
|
var builder = ImmutableArray.CreateBuilder<string>();
|
||||||
|
|
||||||
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
|
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
|
||||||
{
|
{
|
||||||
builder.Add(reader.GetString()!);
|
builder.Add(reader.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PackageAuthors(string.Join(", ", builder), builder.ToImmutable());
|
return new PackageAuthors(string.Join(", ", builder), builder.ToImmutable());
|
||||||
}
|
}
|
||||||
case JsonTokenType.Null:
|
case JsonTokenType.Null:
|
||||||
@@ -41,14 +41,14 @@ public class PackageAuthorsJsonConverter : JsonConverter<PackageAuthors>
|
|||||||
writer.WriteStringValue(value.Author);
|
writer.WriteStringValue(value.Author);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteStartArray();
|
writer.WriteStartArray();
|
||||||
|
|
||||||
foreach (var author in value.Authors)
|
foreach (var author in value.Authors)
|
||||||
{
|
{
|
||||||
writer.WriteStringValue(author);
|
writer.WriteStringValue(author);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteEndArray();
|
writer.WriteEndArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -10,7 +10,7 @@ public class ResourceTypeJsonConverter : JsonConverter<ResourceType>
|
|||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType != JsonTokenType.String)
|
||||||
throw new JsonException("Invalid resource type");
|
throw new JsonException("Invalid resource type");
|
||||||
|
|
||||||
return ResourceType.Parse(reader.GetString()!);
|
return ResourceType.Parse(reader.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ public class RuntimeFrameworkJsonConverter : JsonConverter<NuGetRuntimeFramework
|
|||||||
{
|
{
|
||||||
if (reader.TokenType is not (JsonTokenType.String or JsonTokenType.PropertyName))
|
if (reader.TokenType is not (JsonTokenType.String or JsonTokenType.PropertyName))
|
||||||
throw new JsonException("Invalid runtime framework string");
|
throw new JsonException("Invalid runtime framework string");
|
||||||
|
|
||||||
return NuGetRuntimeFramework.Parse(reader.GetString()!);
|
return NuGetRuntimeFramework.Parse(reader.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,12 +15,12 @@ public class StringOrStringArrayConverter : JsonConverter<ImmutableArray<string>
|
|||||||
case JsonTokenType.StartArray:
|
case JsonTokenType.StartArray:
|
||||||
{
|
{
|
||||||
var builder = ImmutableArray.CreateBuilder<string>();
|
var builder = ImmutableArray.CreateBuilder<string>();
|
||||||
|
|
||||||
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
|
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
|
||||||
{
|
{
|
||||||
builder.Add(reader.GetString()!);
|
builder.Add(reader.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.ToImmutable();
|
return builder.ToImmutable();
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -35,14 +35,14 @@ public class StringOrStringArrayConverter : JsonConverter<ImmutableArray<string>
|
|||||||
writer.WriteStringValue(value[0]);
|
writer.WriteStringValue(value[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteStartArray();
|
writer.WriteStartArray();
|
||||||
|
|
||||||
foreach (var author in value)
|
foreach (var author in value)
|
||||||
{
|
{
|
||||||
writer.WriteStringValue(author);
|
writer.WriteStringValue(author);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteEndArray();
|
writer.WriteEndArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -10,7 +10,7 @@ public class VersionJsonConverter : JsonConverter<NuGetVersion>
|
|||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType != JsonTokenType.String)
|
||||||
throw new JsonException("Invalid version string");
|
throw new JsonException("Invalid version string");
|
||||||
|
|
||||||
return NuGetVersion.Parse(reader.GetString()!);
|
return NuGetVersion.Parse(reader.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ public class VersionRangeJsonConverter : JsonConverter<VersionRange>
|
|||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType != JsonTokenType.String)
|
||||||
throw new JsonException("Invalid version range");
|
throw new JsonException("Invalid version range");
|
||||||
|
|
||||||
return VersionRange.Parse(reader.GetString()!);
|
return VersionRange.Parse(reader.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,10 +52,10 @@ public record ManifestPackageKey(string Id, NuGetVersion Version)
|
|||||||
var index = str.IndexOf('/');
|
var index = str.IndexOf('/');
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
throw new FormatException("Invalid package key: " + str);
|
throw new FormatException("Invalid package key: " + str);
|
||||||
|
|
||||||
return new ManifestPackageKey(str[..index], NuGetVersion.Parse(str[(index + 1)..]));
|
return new ManifestPackageKey(str[..index], NuGetVersion.Parse(str[(index + 1)..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => $"{Id}/{Version}";
|
public override string ToString() => $"{Id}/{Version}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +71,9 @@ public static class DependencyManifestSerializer
|
|||||||
new VersionJsonConverter()
|
new VersionJsonConverter()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Task SerializeAsync(Stream stream, DependenciesManifest manifest) => JsonSerializer.SerializeAsync(stream, manifest, SerializerOptions);
|
public static Task SerializeAsync(Stream stream, DependenciesManifest manifest) => JsonSerializer.SerializeAsync(stream, manifest, SerializerOptions);
|
||||||
|
|
||||||
public static ValueTask<DependenciesManifest> DeserializeAsync(Stream stream) => JsonSerializer.DeserializeAsync<DependenciesManifest>(stream, SerializerOptions)!;
|
public static ValueTask<DependenciesManifest> DeserializeAsync(Stream stream) => JsonSerializer.DeserializeAsync<DependenciesManifest>(stream, SerializerOptions)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,12 +86,12 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
|
|||||||
var targets = ImmutableDictionary<ManifestPackageKey, DependencyTarget>.Empty.ToBuilder();
|
var targets = ImmutableDictionary<ManifestPackageKey, DependencyTarget>.Empty.ToBuilder();
|
||||||
|
|
||||||
await MapCatalogEntryAsync(catalogEntry, targetFramework, targets);
|
await MapCatalogEntryAsync(catalogEntry, targetFramework, targets);
|
||||||
|
|
||||||
var manifest = new DependenciesManifest(runtimeTarget, ImmutableDictionary<NuGetRuntimeFramework, string>.Empty,
|
var manifest = new DependenciesManifest(runtimeTarget, ImmutableDictionary<NuGetRuntimeFramework, string>.Empty,
|
||||||
ImmutableDictionary<NuGetRuntimeFramework, ImmutableDictionary<ManifestPackageKey, DependencyTarget>>.Empty
|
ImmutableDictionary<NuGetRuntimeFramework, ImmutableDictionary<ManifestPackageKey, DependencyTarget>>.Empty
|
||||||
.Add(targetFramework, targets.ToImmutable()),
|
.Add(targetFramework, targets.ToImmutable()),
|
||||||
ImmutableDictionary<ManifestPackageKey, DependencyLibrary>.Empty);
|
ImmutableDictionary<ManifestPackageKey, DependencyLibrary>.Empty);
|
||||||
|
|
||||||
await DependencyManifestSerializer.SerializeAsync(stream, manifest);
|
await DependencyManifestSerializer.SerializeAsync(stream, manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,14 +100,14 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
|
|||||||
{
|
{
|
||||||
if (targets.ContainsKey(new(catalogEntry.Id, catalogEntry.Version)) || !catalogEntry.DependencyGroups.HasValue)
|
if (targets.ContainsKey(new(catalogEntry.Id, catalogEntry.Version)) || !catalogEntry.DependencyGroups.HasValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO take into account the target framework runtime identifier
|
// TODO take into account the target framework runtime identifier
|
||||||
var nearest = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups.Value, targetFramework.Framework,
|
var nearest = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups.Value, targetFramework.Framework,
|
||||||
group => group.TargetFramework);
|
group => group.TargetFramework);
|
||||||
|
|
||||||
if (nearest is null)
|
if (nearest is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
targets.Add(new(catalogEntry.Id, catalogEntry.Version),
|
targets.Add(new(catalogEntry.Id, catalogEntry.Version),
|
||||||
await MapEntryAsync(catalogEntry, nearest));
|
await MapEntryAsync(catalogEntry, nearest));
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
|
|||||||
{
|
{
|
||||||
if (entry is null)
|
if (entry is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
await MapCatalogEntryAsync(entry, targetFramework, targets);
|
await MapCatalogEntryAsync(entry, targetFramework, targets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
@@ -5,5 +5,5 @@ namespace NuGet.Models;
|
|||||||
|
|
||||||
public record CatalogEntry(string Id, NuGetVersion Version, ImmutableArray<DependencyGroup>? DependencyGroups, ImmutableArray<string>? PackageTypes,
|
public record CatalogEntry(string Id, NuGetVersion Version, ImmutableArray<DependencyGroup>? DependencyGroups, ImmutableArray<string>? PackageTypes,
|
||||||
ImmutableArray<CatalogPackageEntry>? PackageEntries);
|
ImmutableArray<CatalogPackageEntry>? PackageEntries);
|
||||||
|
|
||||||
public record CatalogPackageEntry(string Name, string FullName, long CompressedLength, long Length);
|
public record CatalogPackageEntry(string Name, string FullName, long CompressedLength, long Length);
|
@@ -13,10 +13,10 @@ public record NuGetRuntimeFramework(NuGetFramework Framework, string? RuntimeIde
|
|||||||
public static NuGetRuntimeFramework Parse(string str)
|
public static NuGetRuntimeFramework Parse(string str)
|
||||||
{
|
{
|
||||||
var index = str.IndexOf('/');
|
var index = str.IndexOf('/');
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return new NuGetRuntimeFramework(NuGetFramework.Parse(str), null);
|
return new NuGetRuntimeFramework(NuGetFramework.Parse(str), null);
|
||||||
|
|
||||||
return new NuGetRuntimeFramework(NuGetFramework.Parse(str[..index]), str[(index + 1)..]);
|
return new NuGetRuntimeFramework(NuGetFramework.Parse(str[..index]), str[(index + 1)..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
namespace NuGet.Models;
|
namespace NuGet.Models;
|
||||||
|
|
||||||
public record Registration([property: JsonPropertyName("catalogEntry")] string CatalogEntryUrl,
|
public record Registration([property: JsonPropertyName("catalogEntry")] string CatalogEntryUrl,
|
||||||
[property: JsonPropertyName("sleet:catalogEntry")] CatalogEntry? SleetEntry);
|
[property: JsonPropertyName("sleet:catalogEntry")] CatalogEntry? SleetEntry);
|
@@ -10,10 +10,10 @@ public record ResourceType(string Id, NuGetVersion? Version)
|
|||||||
public static ResourceType Parse(string typeString)
|
public static ResourceType Parse(string typeString)
|
||||||
{
|
{
|
||||||
var slash = typeString.IndexOf('/');
|
var slash = typeString.IndexOf('/');
|
||||||
|
|
||||||
if (slash < 0)
|
if (slash < 0)
|
||||||
return new ResourceType(typeString, null);
|
return new ResourceType(typeString, null);
|
||||||
|
|
||||||
var id = typeString[..slash];
|
var id = typeString[..slash];
|
||||||
var versionStr = typeString[(slash + 1)..];
|
var versionStr = typeString[(slash + 1)..];
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
@@ -69,7 +69,7 @@ public class NuGetClient
|
|||||||
bool? includePrerelease = null, NuGetVersion? minVersion = null, string? packageType = null)
|
bool? includePrerelease = null, NuGetVersion? minVersion = null, string? packageType = null)
|
||||||
{
|
{
|
||||||
var queryParameters = HttpUtility.ParseQueryString(string.Empty);
|
var queryParameters = HttpUtility.ParseQueryString(string.Empty);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(query))
|
if (!string.IsNullOrEmpty(query))
|
||||||
queryParameters.Add("q", query);
|
queryParameters.Add("q", query);
|
||||||
|
|
||||||
@@ -78,13 +78,13 @@ public class NuGetClient
|
|||||||
|
|
||||||
if (take.HasValue)
|
if (take.HasValue)
|
||||||
queryParameters.Add("take", take.Value.ToString());
|
queryParameters.Add("take", take.Value.ToString());
|
||||||
|
|
||||||
if (includePrerelease.HasValue)
|
if (includePrerelease.HasValue)
|
||||||
queryParameters.Add("prerelease", includePrerelease.Value.ToString());
|
queryParameters.Add("prerelease", includePrerelease.Value.ToString());
|
||||||
|
|
||||||
if (minVersion is not null)
|
if (minVersion is not null)
|
||||||
queryParameters.Add("semVerLevel", minVersion.ToString());
|
queryParameters.Add("semVerLevel", minVersion.ToString());
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(packageType))
|
if (!string.IsNullOrEmpty(packageType))
|
||||||
queryParameters.Add("packageType", packageType);
|
queryParameters.Add("packageType", packageType);
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ public abstract class DerivedAssemblyLoadContext(ICoreLoadContext parentContext,
|
|||||||
: AssemblyLoadContext(name, true)
|
: AssemblyLoadContext(name, true)
|
||||||
{
|
{
|
||||||
protected readonly ICoreLoadContext ParentContext = parentContext;
|
protected readonly ICoreLoadContext ParentContext = parentContext;
|
||||||
|
|
||||||
protected override Assembly? Load(AssemblyName assemblyName) => ParentContext.ResolveFromAssemblyName(assemblyName);
|
protected override Assembly? Load(AssemblyName assemblyName) => ParentContext.ResolveFromAssemblyName(assemblyName);
|
||||||
protected override nint LoadUnmanagedDll(string unmanagedDllName) => ParentContext.ResolveUnmanagedDll(unmanagedDllName);
|
protected override nint LoadUnmanagedDll(string unmanagedDllName) => ParentContext.ResolveUnmanagedDll(unmanagedDllName);
|
||||||
}
|
}
|
@@ -7,7 +7,7 @@ namespace TestPlugin;
|
|||||||
public class Plugin : IPlugin
|
public class Plugin : IPlugin
|
||||||
{
|
{
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ public class Plugin : IPlugin
|
|||||||
public void Init(object gameInstance)
|
public void Init(object gameInstance)
|
||||||
{
|
{
|
||||||
Log.Info("Test Plugin init");
|
Log.Info("Test Plugin init");
|
||||||
|
|
||||||
RenderHandler.Current.RegisterComponent(new TestRenderComponent());
|
RenderHandler.Current.RegisterComponent(new TestRenderComponent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ public class TestRenderComponent : IRenderComponent
|
|||||||
if (ImGui.Begin("Test Window"))
|
if (ImGui.Begin("Test Window"))
|
||||||
{
|
{
|
||||||
ImGui.Button("Test");
|
ImGui.Button("Test");
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user