Mod config migration from plugin hub
All checks were successful
Build / Compute Version (push) Successful in 6s
Build / Build Nuget package (NuGet) (push) Successful in 50s
Build / Build Nuget package (SharedCringe) (push) Successful in 58s
Build / Build Nuget package (CringePlugins) (push) Successful in 1m11s
Build / Build Launcher (push) Successful in 1m42s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 3m5s
All checks were successful
Build / Compute Version (push) Successful in 6s
Build / Build Nuget package (NuGet) (push) Successful in 50s
Build / Build Nuget package (SharedCringe) (push) Successful in 58s
Build / Build Nuget package (CringePlugins) (push) Successful in 1m11s
Build / Build Launcher (push) Successful in 1m42s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 3m5s
Update ui when migrating pluginhub config Added mod loader as a default plugin Temp fix for pbs
This commit is contained in:
@@ -12,7 +12,7 @@ using VRage.Scripting;
|
|||||||
namespace CringeLauncher.Patches;
|
namespace CringeLauncher.Patches;
|
||||||
|
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
public static class ModAssemblyLoadContextPatches
|
public static class ModAssemblyLoadContextPatches //todo: use ModScriptCompilerPatch
|
||||||
{
|
{
|
||||||
private static ModAssemblyLoadContext? _currentSessionContext;
|
private static ModAssemblyLoadContext? _currentSessionContext;
|
||||||
private static readonly MyConcurrentHashSet<string> AssemblyNames = [];
|
private static readonly MyConcurrentHashSet<string> AssemblyNames = [];
|
||||||
@@ -30,7 +30,7 @@ public static class ModAssemblyLoadContextPatches
|
|||||||
.InsertAndAdvance(new(OpCodes.Ldarg_0), CodeInstruction.LoadField(original.DeclaringType, "target"))
|
.InsertAndAdvance(new(OpCodes.Ldarg_0), CodeInstruction.LoadField(original.DeclaringType, "target"))
|
||||||
.SetInstruction(CodeInstruction.CallClosure((byte[] assembly, byte[] symbols, MyApiTarget target) =>
|
.SetInstruction(CodeInstruction.CallClosure((byte[] assembly, byte[] symbols, MyApiTarget target) =>
|
||||||
{
|
{
|
||||||
if (target is not MyApiTarget.Mod) return Assembly.Load(assembly, symbols);
|
//if (target is not MyApiTarget.Mod) return Assembly.Load(assembly, symbols);
|
||||||
ArgumentNullException.ThrowIfNull(_currentSessionContext, "No session context");
|
ArgumentNullException.ThrowIfNull(_currentSessionContext, "No session context");
|
||||||
return _currentSessionContext.LoadFromStream(new MemoryStream(assembly), new MemoryStream(symbols));
|
return _currentSessionContext.LoadFromStream(new MemoryStream(assembly), new MemoryStream(symbols));
|
||||||
}))
|
}))
|
||||||
@@ -39,7 +39,7 @@ public static class ModAssemblyLoadContextPatches
|
|||||||
.InsertAndAdvance(new(OpCodes.Ldarg_0), CodeInstruction.LoadField(original.DeclaringType, "target"))
|
.InsertAndAdvance(new(OpCodes.Ldarg_0), CodeInstruction.LoadField(original.DeclaringType, "target"))
|
||||||
.SetInstruction(CodeInstruction.CallClosure((byte[] assembly, MyApiTarget target) =>
|
.SetInstruction(CodeInstruction.CallClosure((byte[] assembly, MyApiTarget target) =>
|
||||||
{
|
{
|
||||||
if (target is not MyApiTarget.Mod) return Assembly.Load(assembly);
|
//if (target is not MyApiTarget.Mod) return Assembly.Load(assembly);
|
||||||
ArgumentNullException.ThrowIfNull(_currentSessionContext, "No session context");
|
ArgumentNullException.ThrowIfNull(_currentSessionContext, "No session context");
|
||||||
return _currentSessionContext.LoadFromStream(new MemoryStream(assembly));
|
return _currentSessionContext.LoadFromStream(new MemoryStream(assembly));
|
||||||
}))
|
}))
|
||||||
|
@@ -9,24 +9,39 @@ namespace CringePlugins.Compatability;
|
|||||||
[XmlType("PluginConfig")]
|
[XmlType("PluginConfig")]
|
||||||
public class PluginLoaderConfig
|
public class PluginLoaderConfig
|
||||||
{
|
{
|
||||||
[XmlArrayItem("Id")]
|
/// <summary>
|
||||||
public string[] Plugins { get; set; } = [];
|
/// Raw plugin and mod ids
|
||||||
|
/// </summary>
|
||||||
|
[XmlArrayItem("Id")] public string[] Plugins { get; set; } = [];
|
||||||
|
|
||||||
[XmlArrayItem("Profile")]
|
/// <summary>
|
||||||
public PluginLoaderProfile[] Profiles { get; set; } = [];
|
/// Raw profiles
|
||||||
|
/// </summary>
|
||||||
|
[XmlArrayItem("Profile")] public PluginLoaderProfile[] Profiles { get; set; } = [];
|
||||||
|
|
||||||
public PackagesConfig Migrate(PackagesConfig old)
|
public PackagesConfig MigratePlugins(PackagesConfig old)
|
||||||
{
|
{
|
||||||
|
//ensure defaults are installed
|
||||||
|
var defaultConfig = PackagesConfig.Default;
|
||||||
|
var sources = old.Sources.ToBuilder();
|
||||||
|
foreach (var source in defaultConfig.Sources)
|
||||||
|
{
|
||||||
|
if (!sources.Contains(source))
|
||||||
|
sources.Add(source);
|
||||||
|
}
|
||||||
|
|
||||||
var pluginsBuilder = ImmutableArray.CreateBuilder<PackageReference>();
|
var pluginsBuilder = ImmutableArray.CreateBuilder<PackageReference>();
|
||||||
var defaultVersion = new NuGetVersion(1, 0, 0);
|
var defaultVersion = new NuGetVersion(1, 0, 0);
|
||||||
foreach (var plugin in Plugins)
|
foreach (var plugin in GetPlugins())
|
||||||
{
|
{
|
||||||
if (!IsValidId(plugin))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pluginsBuilder.Add(new PackageReference($"Plugin.{plugin.Replace('/', '.')}",
|
pluginsBuilder.Add(new PackageReference($"Plugin.{plugin.Replace('/', '.')}",
|
||||||
new(defaultVersion)));
|
new(defaultVersion)));
|
||||||
}
|
}
|
||||||
|
foreach (var package in defaultConfig.Packages)
|
||||||
|
{
|
||||||
|
if (!pluginsBuilder.Any(x => x.Id == package.Id))
|
||||||
|
pluginsBuilder.Add(package);
|
||||||
|
}
|
||||||
|
|
||||||
var profiles = new Dictionary<string, ImmutableArray<PackageReference>>();
|
var profiles = new Dictionary<string, ImmutableArray<PackageReference>>();
|
||||||
foreach (var profile in Profiles)
|
foreach (var profile in Profiles)
|
||||||
@@ -34,24 +49,85 @@ public class PluginLoaderConfig
|
|||||||
var builder = ImmutableArray.CreateBuilder<PackageReference>();
|
var builder = ImmutableArray.CreateBuilder<PackageReference>();
|
||||||
foreach (var plugin in profile.Plugins)
|
foreach (var plugin in profile.Plugins)
|
||||||
{
|
{
|
||||||
if (!IsValidId(plugin))
|
if (!IsValidPluginId(plugin))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
builder.Add(new PackageReference($"Plugin.{plugin.Replace('/', '.')}",
|
builder.Add(new PackageReference($"Plugin.{plugin.Replace('/', '.')}",
|
||||||
new(defaultVersion)));
|
new(defaultVersion)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var package in defaultConfig.Packages)
|
||||||
|
{
|
||||||
|
if (!builder.Any(x => x.Id == package.Id))
|
||||||
|
builder.Add(package);
|
||||||
|
}
|
||||||
|
|
||||||
profiles[profile.Name] = builder.ToImmutable();
|
profiles[profile.Name] = builder.ToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
return old with
|
return old with
|
||||||
{
|
{
|
||||||
Packages = pluginsBuilder.ToImmutableArray(),
|
Packages = pluginsBuilder.ToImmutable(),
|
||||||
Profiles = profiles
|
Profiles = profiles,
|
||||||
|
Sources = sources.ToImmutable()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsValidId(string pluginId)
|
public HashSet<string> GetPlugins() => GetPlugins(Plugins);
|
||||||
|
public HashSet<ulong> GetMods() => GetMods(Plugins);
|
||||||
|
public Dictionary<string, HashSet<string>> GetPluginProfiles()
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<string, HashSet<string>>(Profiles.Length);
|
||||||
|
|
||||||
|
foreach (var profile in Profiles)
|
||||||
|
{
|
||||||
|
dict[profile.Name] = GetPlugins(profile.Plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
public Dictionary<string, HashSet<ulong>> GetModProfiles()
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<string, HashSet<ulong>>(Profiles.Length);
|
||||||
|
|
||||||
|
foreach (var profile in Profiles)
|
||||||
|
{
|
||||||
|
dict[profile.Name] = GetMods(profile.Plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static HashSet<string> GetPlugins(string[] mixed)
|
||||||
|
{
|
||||||
|
var plugins = new HashSet<string>();
|
||||||
|
foreach (var plugin in mixed)
|
||||||
|
{
|
||||||
|
if (!IsValidPluginId(plugin))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
plugins.Add(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashSet<ulong> GetMods(string[] mixed)
|
||||||
|
{
|
||||||
|
var mods = new HashSet<ulong>();
|
||||||
|
foreach (var plugin in mixed)
|
||||||
|
{
|
||||||
|
if (!ulong.TryParse(plugin, out var modId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mods.Add(modId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidPluginId(string pluginId)
|
||||||
{
|
{
|
||||||
var count = 0;
|
var count = 0;
|
||||||
foreach (var c in pluginId)
|
foreach (var c in pluginId)
|
||||||
|
@@ -10,5 +10,9 @@ public record PackagesConfig(ImmutableArray<PackageSource> Sources, ImmutableArr
|
|||||||
public static PackagesConfig Default { get; } = new([
|
public static PackagesConfig Default { get; } = new([
|
||||||
new("zznty", @"^SpaceEngineersDedicated\.ReferenceAssemblies$|^ImGui\.NET\.DirectX$|^NuGet$|^Cringe.+$|^SharedCringe$|^Plugin.+$", "https://ng.zznty.ru/v3/index.json"),
|
new("zznty", @"^SpaceEngineersDedicated\.ReferenceAssemblies$|^ImGui\.NET\.DirectX$|^NuGet$|^Cringe.+$|^SharedCringe$|^Plugin.+$", "https://ng.zznty.ru/v3/index.json"),
|
||||||
new("nuget.org", string.Empty, "https://api.nuget.org/v3/index.json")
|
new("nuget.org", string.Empty, "https://api.nuget.org/v3/index.json")
|
||||||
], [], []); //todo: default profile with recommended plugins?
|
],
|
||||||
|
[
|
||||||
|
new PackageReference("Plugin.ClientModLoader", new(new(0,0,0)))
|
||||||
|
],
|
||||||
|
[]); //todo: default profile with recommended plugins?
|
||||||
}
|
}
|
@@ -33,6 +33,7 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
private bool _open = true;
|
private bool _open = true;
|
||||||
private PackagesConfig _packagesConfig;
|
private PackagesConfig _packagesConfig;
|
||||||
private readonly PackageSourceMapping _sourceMapping;
|
private readonly PackageSourceMapping _sourceMapping;
|
||||||
|
private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web);
|
||||||
private ImmutableHashSet<PackageSource>? _selectedSources;
|
private ImmutableHashSet<PackageSource>? _selectedSources;
|
||||||
private readonly string _configPath;
|
private readonly string _configPath;
|
||||||
private readonly string _gameFolder;
|
private readonly string _gameFolder;
|
||||||
@@ -255,17 +256,50 @@ internal class PluginListComponent : IRenderComponent
|
|||||||
if (BeginTabItem("Settings"))
|
if (BeginTabItem("Settings"))
|
||||||
{
|
{
|
||||||
var oldConfigPath = Path.Join(_gameFolder, "Plugins", "config.xml");
|
var oldConfigPath = Path.Join(_gameFolder, "Plugins", "config.xml");
|
||||||
if (File.Exists(oldConfigPath) && Button("Migrate PluginLoader Config"))
|
if (File.Exists(oldConfigPath))
|
||||||
|
{
|
||||||
|
if (Button("Migrate PluginLoader Plugins"))
|
||||||
{
|
{
|
||||||
var configSerializer = new XmlSerializer(typeof(PluginLoaderConfig));
|
var configSerializer = new XmlSerializer(typeof(PluginLoaderConfig));
|
||||||
using var fs = File.OpenRead(oldConfigPath);
|
using var fs = File.OpenRead(oldConfigPath);
|
||||||
|
|
||||||
if (configSerializer.Deserialize(fs) is PluginLoaderConfig oldConfig)
|
if (configSerializer.Deserialize(fs) is PluginLoaderConfig oldConfig)
|
||||||
{
|
{
|
||||||
_packagesConfig = oldConfig.Migrate(_packagesConfig);
|
_packagesConfig = oldConfig.MigratePlugins(_packagesConfig);
|
||||||
|
|
||||||
|
|
||||||
Save(false);
|
Save(false);
|
||||||
|
|
||||||
|
_packages = _packagesConfig.Packages.ToImmutableDictionary(b => b.Id, b => b.Range, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasModLodaer = _packages.ContainsKey("Plugin.ClientModLoader");
|
||||||
|
|
||||||
|
if (!hasModLodaer)
|
||||||
|
BeginDisabled();
|
||||||
|
|
||||||
|
if (Button("Migrate Pluginloader Mods"))
|
||||||
|
{
|
||||||
|
var configSerializer = new XmlSerializer(typeof(PluginLoaderConfig));
|
||||||
|
using var fs = File.OpenRead(oldConfigPath);
|
||||||
|
|
||||||
|
if (configSerializer.Deserialize(fs) is PluginLoaderConfig plConfig)
|
||||||
|
{
|
||||||
|
var dir = new DirectoryInfo(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
|
"CringeLauncher"));
|
||||||
|
var file = Path.Join(dir.FullName, "mods.json");
|
||||||
|
|
||||||
|
using var modsFile = File.Create(file);
|
||||||
|
JsonSerializer.Serialize(modsFile, plConfig.GetMods(), _serializerOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasModLodaer)
|
||||||
|
{
|
||||||
|
if (IsItemHovered())
|
||||||
|
SetTooltip("Requires Plugin.ClientModLoader");
|
||||||
|
|
||||||
|
EndDisabled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EndTabItem();
|
EndTabItem();
|
||||||
|
Reference in New Issue
Block a user