Compare commits

...

1 Commits

Author SHA1 Message Date
roflmuffin
2535ac0575 feat: add assembly name lazy loading of shared libraries 2024-03-04 12:15:37 +10:00
4 changed files with 61 additions and 24 deletions

View File

@@ -130,11 +130,11 @@ namespace CounterStrikeSharp.API.Core
{
var sb = new StringBuilder();
sb.AppendFormat(" [#{0}:{1}]: \"{2}\" ({3})", plugin.PluginId,
plugin.State.ToString().ToUpper(), plugin.Plugin.ModuleName,
plugin.Plugin.ModuleVersion);
if (!string.IsNullOrEmpty(plugin.Plugin.ModuleAuthor))
plugin.State.ToString().ToUpper(), plugin.Plugin?.ModuleName ?? "Unknown",
plugin.Plugin?.ModuleVersion ?? "Unknown");
if (!string.IsNullOrEmpty(plugin.Plugin?.ModuleAuthor))
sb.AppendFormat(" by {0}", plugin.Plugin.ModuleAuthor);
if (!string.IsNullOrEmpty(plugin.Plugin.ModuleDescription))
if (!string.IsNullOrEmpty(plugin.Plugin?.ModuleDescription))
{
sb.Append("\n");
sb.Append(" ");

View File

@@ -1,8 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using CounterStrikeSharp.API.Core.Capabilities;
using CounterStrikeSharp.API.Core.Commands;
using CounterStrikeSharp.API.Core.Hosting;
using McMaster.NETCore.Plugins;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -15,8 +18,11 @@ public class PluginManager : IPluginManager
private readonly ICommandManager _commandManager;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<PluginManager> _logger;
private readonly Dictionary<string, Assembly> _sharedAssemblies = new();
private bool _loadedSharedLibs = false;
public PluginManager(IScriptHostConfiguration scriptHostConfiguration, ICommandManager commandManager, ILogger<PluginManager> logger, IServiceProvider serviceProvider, IServiceScopeFactory serviceScopeFactory)
public PluginManager(IScriptHostConfiguration scriptHostConfiguration, ICommandManager commandManager,
ILogger<PluginManager> logger, IServiceProvider serviceProvider, IServiceScopeFactory serviceScopeFactory)
{
_scriptHostConfiguration = scriptHostConfiguration;
_commandManager = commandManager;
@@ -24,6 +30,36 @@ public class PluginManager : IPluginManager
_serviceProvider = serviceProvider;
}
private void LoadLibrary(string path)
{
var loader = PluginLoader.CreateFromAssemblyFile(path, new[] { typeof(IPlugin), typeof(PluginCapability<>), typeof(PlayerCapability<>) },
config => { config.PreferSharedTypes = true; });
var assembly = loader.LoadDefaultAssembly();
_sharedAssemblies[assembly.GetName().FullName] = assembly;
}
private void LoadSharedLibraries()
{
var sharedDirectory = Directory.GetDirectories(_scriptHostConfiguration.SharedPath);
var sharedAssemblyPaths = sharedDirectory
.Select(dir => Path.Combine(dir, Path.GetFileName(dir) + ".dll"))
.Where(File.Exists)
.ToArray();
foreach (var sharedAssemblyPath in sharedAssemblyPaths)
{
try
{
LoadLibrary(sharedAssemblyPath);
}
catch (Exception e)
{
_logger.LogError(e, "Failed to load shared assembly from {Path}", sharedAssemblyPath);
}
}
}
public void Load()
{
var pluginDirectories = Directory.GetDirectories(_scriptHostConfiguration.PluginPath);
@@ -31,23 +67,23 @@ public class PluginManager : IPluginManager
.Select(dir => Path.Combine(dir, Path.GetFileName(dir) + ".dll"))
.Where(File.Exists)
.ToArray();
var sharedDirectory = Directory.GetDirectories(_scriptHostConfiguration.SharedPath);
var sharedAssemblyPaths = sharedDirectory
.Select(dir => Path.Combine(dir, Path.GetFileName(dir) + ".dll"))
.Where(File.Exists)
.ToArray();
foreach (var sharedAssemblyPath in sharedAssemblyPaths)
AssemblyLoadContext.Default.Resolving += (context, name) =>
{
try
if (!_loadedSharedLibs)
{
AssemblyLoadContext.Default.LoadFromAssemblyPath(sharedAssemblyPath);
} catch (Exception e)
{
_logger.LogError(e, "Failed to load shared assembly from {Path}", sharedAssemblyPath);
LoadSharedLibraries();
_loadedSharedLibs = true;
}
}
if (!_sharedAssemblies.TryGetValue(name.FullName, out var assembly))
{
_logger.LogError("Failed to use existing shared assembly: {Name}", name);
return null;
}
return assembly;
};
foreach (var path in pluginAssemblyPaths)
{
@@ -60,7 +96,7 @@ public class PluginManager : IPluginManager
_logger.LogError(e, "Failed to load plugin from {Path}", path);
}
}
foreach (var plugin in _loadedPluginContexts)
{
plugin.Plugin.OnAllPluginsLoaded(false);
@@ -74,7 +110,8 @@ public class PluginManager : IPluginManager
public void LoadPlugin(string path)
{
var plugin = new PluginContext(_serviceProvider, _commandManager, _scriptHostConfiguration, path, _loadedPluginContexts.Select(x => x.PluginId).DefaultIfEmpty(0).Max() + 1);
var plugin = new PluginContext(_serviceProvider, _commandManager, _scriptHostConfiguration, path,
_loadedPluginContexts.Select(x => x.PluginId).DefaultIfEmpty(0).Max() + 1);
_loadedPluginContexts.Add(plugin);
plugin.Load();
}

View File

@@ -18,6 +18,7 @@ using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Core.Capabilities;
using CounterStrikeSharp.API.Core.Commands;
using CounterStrikeSharp.API.Core.Hosting;
using CounterStrikeSharp.API.Core.Logging;
@@ -76,7 +77,7 @@ namespace CounterStrikeSharp.API.Core.Plugin
config.IsUnloadable = true;
config.PreferSharedTypes = true;
});
if (CoreConfig.PluginHotReloadEnabled)
{
_fileWatcher = new FileSystemWatcher
@@ -119,12 +120,12 @@ namespace CounterStrikeSharp.API.Core.Plugin
public void Load(bool hotReload = false)
{
if (State == PluginState.Loaded) return;
using (Loader.EnterContextualReflection())
{
var defaultAssembly = Loader.LoadDefaultAssembly();
Type pluginType = defaultAssembly.GetTypes()
Type pluginType = defaultAssembly.GetExportedTypes()
.FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t));
if (pluginType == null) throw new Exception("Unable to find plugin in assembly");

View File

@@ -132,7 +132,6 @@ namespace CounterStrikeSharp.API.Modules.Admin
foreach (var adminDef in adminsFromFile.Values)
{
adminDef.InitalizeFlags();
Console.WriteLine($"Domains: {adminDef.Flags.Count}");
if (SteamID.TryParse(adminDef.Identity, out var steamId))
{