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

Update ui when migrating pluginhub config
Added mod loader as a default plugin
Temp fix for pbs
This commit is contained in:
2025-05-13 04:04:22 -04:00
parent 3295afc447
commit 78880d2a78
4 changed files with 138 additions and 24 deletions

View File

@@ -12,7 +12,7 @@ using VRage.Scripting;
namespace CringeLauncher.Patches;
[HarmonyPatch]
public static class ModAssemblyLoadContextPatches
public static class ModAssemblyLoadContextPatches //todo: use ModScriptCompilerPatch
{
private static ModAssemblyLoadContext? _currentSessionContext;
private static readonly MyConcurrentHashSet<string> AssemblyNames = [];
@@ -30,7 +30,7 @@ public static class ModAssemblyLoadContextPatches
.InsertAndAdvance(new(OpCodes.Ldarg_0), CodeInstruction.LoadField(original.DeclaringType, "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");
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"))
.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");
return _currentSessionContext.LoadFromStream(new MemoryStream(assembly));
}))

View File

@@ -9,24 +9,39 @@ namespace CringePlugins.Compatability;
[XmlType("PluginConfig")]
public class PluginLoaderConfig
{
[XmlArrayItem("Id")]
public string[] Plugins { get; set; } = [];
/// <summary>
/// Raw plugin and mod ids
/// </summary>
[XmlArrayItem("Id")] public string[] Plugins { get; set; } = [];
[XmlArrayItem("Profile")]
public PluginLoaderProfile[] Profiles { get; set; } = [];
/// <summary>
/// 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 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('/', '.')}",
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>>();
foreach (var profile in Profiles)
@@ -34,24 +49,85 @@ public class PluginLoaderConfig
var builder = ImmutableArray.CreateBuilder<PackageReference>();
foreach (var plugin in profile.Plugins)
{
if (!IsValidId(plugin))
if (!IsValidPluginId(plugin))
continue;
builder.Add(new PackageReference($"Plugin.{plugin.Replace('/', '.')}",
new(defaultVersion)));
}
foreach (var package in defaultConfig.Packages)
{
if (!builder.Any(x => x.Id == package.Id))
builder.Add(package);
}
profiles[profile.Name] = builder.ToImmutable();
}
return old with
{
Packages = pluginsBuilder.ToImmutableArray(),
Profiles = profiles
Packages = pluginsBuilder.ToImmutable(),
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;
foreach (var c in pluginId)

View File

@@ -10,5 +10,9 @@ public record PackagesConfig(ImmutableArray<PackageSource> Sources, ImmutableArr
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("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?
}

View File

@@ -33,6 +33,7 @@ internal class PluginListComponent : IRenderComponent
private bool _open = true;
private PackagesConfig _packagesConfig;
private readonly PackageSourceMapping _sourceMapping;
private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web);
private ImmutableHashSet<PackageSource>? _selectedSources;
private readonly string _configPath;
private readonly string _gameFolder;
@@ -255,17 +256,50 @@ internal class PluginListComponent : IRenderComponent
if (BeginTabItem("Settings"))
{
var oldConfigPath = Path.Join(_gameFolder, "Plugins", "config.xml");
if (File.Exists(oldConfigPath) && Button("Migrate PluginLoader Config"))
if (File.Exists(oldConfigPath))
{
var configSerializer = new XmlSerializer(typeof(PluginLoaderConfig));
using var fs = File.OpenRead(oldConfigPath);
if (configSerializer.Deserialize(fs) is PluginLoaderConfig oldConfig)
if (Button("Migrate PluginLoader Plugins"))
{
_packagesConfig = oldConfig.Migrate(_packagesConfig);
var configSerializer = new XmlSerializer(typeof(PluginLoaderConfig));
using var fs = File.OpenRead(oldConfigPath);
if (configSerializer.Deserialize(fs) is PluginLoaderConfig oldConfig)
{
_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();