Skip to content
This repository was archived by the owner on Jun 21, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 51 additions & 18 deletions NwPluginAPI/Loader/AssemblyLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,40 +114,69 @@ private static void LoadPlugins(PluginDirectory directory)

var loadedAssemblies = AppDomain.CurrentDomain
.GetAssemblies()
.Select(x =>
$"{x.GetName().Name}&r v&6{x.GetName().Version.ToString(3)}");
.ToDictionary(x => x.GetName().Name, x => x.GetName().Version);

var loadedPluginAssemblies = new List<PluginAssemblyInformation>();
var pluginsToInitialize = new List<PluginAssemblyInformation>();

foreach (string pluginPath in files)
{
if (!TryGetAssembly(pluginPath, out Assembly assembly))
continue;
loadedPluginAssemblies.Add(new PluginAssemblyInformation(pluginPath, assembly));
loadedAssemblies[assembly.GetName().Name] = assembly.GetName().Version;
}

Type[] types = null;

var missingDependencies = assembly
foreach (var pluginInfo in loadedPluginAssemblies)
{
var missingDependencies = pluginInfo.Assembly
.GetReferencedAssemblies()
.Where(x => !loadedAssemblies.ContainsKey(x.Name))
.ToDictionary(x => x.Name, x => x.Version);
var versionMismatch = pluginInfo.Assembly
.GetReferencedAssemblies()
.Select(x =>
$"{x.Name}&r v&6{x.Version.ToString(3)}")
.Where(x => !loadedAssemblies.Contains(x)).ToArray();
.Where(x => loadedAssemblies.ContainsKey(x.Name) && loadedAssemblies[x.Name] != x.Version)
.ToDictionary(x => x.Name, x => (Expected: x.Version, Actual: loadedAssemblies[x.Name]));

try
{
if (missingDependencies.Length != 0)
ResolveAssemblyEmbeddedResources(assembly);
types = assembly.GetTypes();
if (missingDependencies.Count != 0)
ResolveAssemblyEmbeddedResources(pluginInfo.Assembly, missingDependencies);
if (missingDependencies.Count != 0)
{
Log.Error($"Failed loading plugin &2{Path.GetFileNameWithoutExtension(pluginInfo.Path)}&r, missing dependencies\n&2{string.Join("\n", missingDependencies.Select(x => "&r - &2" + x.Key + " v" + x.Value.ToString(3) + "&r"))}", "Loader");
continue;
}

pluginInfo.Types = pluginInfo.Assembly.GetTypes();
pluginsToInitialize.Add(pluginInfo);
}
catch (Exception e)
{
if (missingDependencies.Length != 0)
if (missingDependencies.Count != 0)
{
Log.Error($"Failed loading plugin &2{Path.GetFileNameWithoutExtension(pluginPath)}&r, missing dependencies\n&2{string.Join("\n", missingDependencies.Select(x => $"&r - &2{x}&r"))}\n\n{e}", "Loader");
continue;
Log.Error($"Failed loading plugin &2{Path.GetFileNameWithoutExtension(pluginInfo.Path)}&r, missing dependencies\n&2{string.Join("\n", missingDependencies.Select(x => "&r - &2" + x.Key + " v" + x.Value.ToString(3) + "&r"))}\n\n{e}", "Loader");
}
else
{
Log.Error("Failed loading plugin &2" + Path.GetFileNameWithoutExtension(pluginInfo.Path) + "&r, " + e, "Loader");
}

Log.Error($"Failed loading plugin &2{Path.GetFileNameWithoutExtension(pluginPath)}&r, {e.ToString()}");
continue;
}

if (versionMismatch.Count != 0)
{
Log.Warning($"Dependency version mismatch in plugin &2{Path.GetFileNameWithoutExtension(pluginInfo.Path)}&r\n&2{string.Join("\n", versionMismatch.Select(x => "&r - &2" + x.Key + " v" + x.Value.Actual.ToString(3) + " (expected version by plugin: " + x.Value.Expected.ToString(3) + ")" + "&r"))}", "Loader");
}
}

Log.Info($"Initializing &2{pluginsToInitialize.Count}&r plugins...");
foreach (var pluginInfo in pluginsToInitialize)
{
var pluginPath = pluginInfo.Path;
var assembly = pluginInfo.Assembly;
var types = pluginInfo.Types;
foreach (var entryType in types)
{
try
Expand Down Expand Up @@ -217,6 +246,7 @@ private static void LoadDependencies(string path)
Log.Error($"Failed loading dependency &2{Path.GetFileNameWithoutExtension(dependencyPath)}&r.\n{ex}");
continue;
}

successes++;
}

Expand Down Expand Up @@ -249,7 +279,8 @@ private static bool TryGetAssembly(string path, out Assembly assembly)
/// Attempts to load Embedded assemblies (compressed) from the target
/// </summary>
/// <param name="target">Assembly to check for embedded assemblies</param>
private static void ResolveAssemblyEmbeddedResources(Assembly target)
/// <param name="missingDependencies"></param>
private static void ResolveAssemblyEmbeddedResources(Assembly target, Dictionary<string, Version> missingDependencies)
{
Log.Debug($"Attempting to load embedded resources for {target.FullName}", Log.DebugMode);

Expand All @@ -271,7 +302,8 @@ private static void ResolveAssemblyEmbeddedResources(Assembly target)
}

dataStream.CopyTo(stream);
Assembly.Load(stream.ToArray());
var assemblyName = Assembly.Load(stream.ToArray()).GetName();
missingDependencies.Remove(assemblyName.Name);
Log.Debug($"Loaded {name}", Log.DebugMode);
}
}
Expand All @@ -289,7 +321,8 @@ private static void ResolveAssemblyEmbeddedResources(Assembly target)
{
Log.Debug($"Loading {name}", Log.DebugMode);
stream.CopyTo(memStream);
Assembly.Load(memStream.ToArray());
var assemblyName = Assembly.Load(memStream.ToArray()).GetName();
missingDependencies.Remove(assemblyName.Name);
Log.Debug($"Loaded {name}", Log.DebugMode);
}
}
Expand Down
24 changes: 24 additions & 0 deletions NwPluginAPI/Loader/PluginAssemblyInformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace PluginAPI.Loader
{

using System;
using System.Reflection;

internal sealed class PluginAssemblyInformation
{

public PluginAssemblyInformation(string path, Assembly assembly)
{
Path = path;
Assembly = assembly;
}

public Type[] Types = Array.Empty<Type>();

public readonly string Path;

public readonly Assembly Assembly;

}

}