NwPluginAPI icon indicating copy to clipboard operation
NwPluginAPI copied to clipboard

Plugin assembly loading fix

Open Axwabo opened this issue 2 years ago • 3 comments

Cross-plugin dependency fix

This PR fixes an issue where plugins would not load if they referenced another plugin that was not yet loaded.

The problem:

Assume the following scenario:

The following plugins are to be loaded:

  • PluginA
  • PluginB
  • PluginC

Both PluginA and PluginC depend on PluginB. PluginB has no dependencies.

  1. PluginA's assembly is loaded.
  2. The loader attempts to initialize PluginA, but fails because the dependency PluginB is not yet found.
  3. PluginB's assembly is loaded and initialized.
  4. PluginC is loaded and starts without any issues.

Changes:

  • Added the PluginAPI.Loader.PluginAssemblyInformation struct
  • Upon loading of a plugin assembly, it is not checked for entry points. If there are no missing references, the plugin information is added to a list.
  • A message is printed to the console: Initializing (count) plugins...
  • The list of plugins is iterated over and initialized.
  • Missing dependencies are now logged even when no exception was thrown.
  • Added a warning when a plugin has a dependency in a different version than the actually loaded dependency.

This way, a plugin can reference another that comes after it alphabetically and will still be initialized correctly.

Axwabo avatar Aug 28 '23 16:08 Axwabo

Please we need this PR, plugins loading is stuck at "Loading x plugins..."

Lufou avatar Dec 04 '23 14:12 Lufou

Encountered some issues with your PR, first I think it's better to load all dependencies before actual plugins, i.e:

Log.Info("<---<    Loading global dependencies     <---<");
LoadDependencies(Paths.GlobalPlugins.Dependencies);

Log.Info("<---<     Loading server dependencies    <---<");
LoadDependencies(Paths.LocalPlugins.Dependencies);

Log.Info("<---<    Loading global plugins     <---<");
// Load plugins from the Global directory inside "configs".
LoadPlugins(Paths.GlobalPlugins);

Log.Info("<---<     Loading server plugins    <---<");
// Load plugins from the [Server port] directory inside "configs".
LoadPlugins(Paths.LocalPlugins);

Log.Info("<---<        Load all plugins       <---<");

And I also think it's good to put try catch inside LoadPlugins function to be able to see if there's an error:

try
{
...........all the code of LoadPlugins..........
}
catch (Exception e)
{
   Log.Error(e.ToString());
}

Lufou avatar Dec 04 '23 17:12 Lufou

I'm not really not sure why but putting line 145

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;
}

in the try will break the loader (System.Net.Http.dll from the Managed folder will be counted as a missing dependency even if the file is there). I would recommend keeping it only in the catch statement like NW did.

Lufou avatar Dec 04 '23 19:12 Lufou