Skip to content

Commit

Permalink
fix(server): fix plugin loading dependencies of plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielMcAssey committed Jan 24, 2025
1 parent 5914594 commit 5d1dd10
Showing 1 changed file with 44 additions and 25 deletions.
69 changes: 44 additions & 25 deletions GLOKON.Baiters.Core/Plugins/PluginLoader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Serilog;
using System.Reflection;
using System.Runtime.Loader;

namespace GLOKON.Baiters.Core.Plugins
{
Expand All @@ -22,37 +23,26 @@ public static void LoadPlugins(GameManager gm)
{
try
{
Assembly pluginAssembly = Assembly.Load(AssemblyName.GetAssemblyName(pluginPath));

foreach (var pluginDependency in pluginAssembly.GetReferencedAssemblies())
{
try
{
AppDomain.CurrentDomain.Load(pluginDependency);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to load plugin dependency ({0})", pluginDependency.FullName);
}
}

pluginAssm.Add(pluginAssembly);
pluginAssm.Add(Assembly.LoadFrom(pluginPath));
}
catch (Exception ex)
{
Log.Error(ex, "Failed to load plugin file ({0})", pluginPath);
}
}

AssemblyLoadContext.Default.Resolving += Default_Resolving;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

foreach (var assembly in pluginAssm)
{
Type[] pluginTypes = assembly.GetTypes()
.Where((type) => type.IsClass && type.IsSubclassOf(typeof(BaitersPlugin)))
.ToArray();

foreach (Type pluginType in pluginTypes)
try
{
try
Type[] pluginTypes = assembly.GetTypes()
.Where((type) => type.IsClass && type.IsSubclassOf(typeof(BaitersPlugin)))
.ToArray();

foreach (Type pluginType in pluginTypes)
{
if (Activator.CreateInstance(pluginType, gm) is BaitersPlugin plugin)
{
Expand All @@ -65,10 +55,10 @@ public static void LoadPlugins(GameManager gm)
Log.Error("Failed to instantiate plugin ({0})", pluginType.FullName);
}
}
catch (Exception ex)
{
Log.Error(ex, "Failed to load plugin ({0})", pluginType.FullName);
}
}
catch (Exception ex)
{
Log.Error(ex, "Failed to load plugin ({0})", assembly.FullName);
}
}
}
Expand All @@ -87,8 +77,37 @@ public static void UnloadPlugins()
}
}

AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
AssemblyLoadContext.Default.Resolving -= Default_Resolving;
Plugins.Clear();
GC.Collect();
}

private static Assembly? Default_Resolving(AssemblyLoadContext context, AssemblyName assembly)
{
Log.Verbose("Attempting to resolve {0}", assembly);

string assemblyPath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"./plugins/{assembly.Name}.dll"));
return context.LoadFromAssemblyPath(assemblyPath);
}

private static Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
{
Assembly? assembly = null;

// Ignore version for internal dependencies
if (args.Name.Contains("GLOKON.Baiters.Core") || args.Name.Contains("GLOKON.Baiters.GodotInterop"))
{
var assemblyName = new AssemblyName(args.Name);

// Prevents infinte loop, as args will contain the assembly FullName once resolved
if (assemblyName.Name != args.Name)
{
assembly = ((AppDomain)sender).Load(assemblyName.Name);

Check warning on line 106 in GLOKON.Baiters.Core/Plugins/PluginLoader.cs

View workflow job for this annotation

GitHub Actions / Build Server (ubuntu-latest, linux-x64) / build-server

Converting null literal or possible null value to non-nullable type.

Check warning on line 106 in GLOKON.Baiters.Core/Plugins/PluginLoader.cs

View workflow job for this annotation

GitHub Actions / Build Server (ubuntu-latest, linux-x64) / build-server

Dereference of a possibly null reference.

Check warning on line 106 in GLOKON.Baiters.Core/Plugins/PluginLoader.cs

View workflow job for this annotation

GitHub Actions / Build Server (ubuntu-latest, linux-x64) / build-server

Possible null reference argument for parameter 'assemblyString' in 'Assembly AppDomain.Load(string assemblyString)'.

Check warning on line 106 in GLOKON.Baiters.Core/Plugins/PluginLoader.cs

View workflow job for this annotation

GitHub Actions / Build Server (windows-latest, win-x64) / build-server

Converting null literal or possible null value to non-nullable type.

Check warning on line 106 in GLOKON.Baiters.Core/Plugins/PluginLoader.cs

View workflow job for this annotation

GitHub Actions / Build Server (windows-latest, win-x64) / build-server

Dereference of a possibly null reference.

Check warning on line 106 in GLOKON.Baiters.Core/Plugins/PluginLoader.cs

View workflow job for this annotation

GitHub Actions / Build Server (windows-latest, win-x64) / build-server

Possible null reference argument for parameter 'assemblyString' in 'Assembly AppDomain.Load(string assemblyString)'.
}
}

return assembly;
}
}
}

0 comments on commit 5d1dd10

Please sign in to comment.