diff --git a/Dalamud/Plugin/PluginDefinition.cs b/Dalamud/Plugin/PluginDefinition.cs
index 7adbcba78..3b866ff51 100644
--- a/Dalamud/Plugin/PluginDefinition.cs
+++ b/Dalamud/Plugin/PluginDefinition.cs
@@ -97,5 +97,10 @@ namespace Dalamud.Plugin
/// Download link used to get testing versions of the plugin.
///
public string DownloadLinkTesting { get; set; }
+
+ ///
+ /// Load priority for this plugin. Higher values means higher priority. 0 is default priority.
+ ///
+ public int LoadPriority { get; set; }
}
}
diff --git a/Dalamud/Plugin/PluginManager.cs b/Dalamud/Plugin/PluginManager.cs
index 93ddb880d..d7ee38a8e 100644
--- a/Dalamud/Plugin/PluginManager.cs
+++ b/Dalamud/Plugin/PluginManager.cs
@@ -95,7 +95,7 @@ namespace Dalamud.Plugin
this.Plugins.Remove(thisPlugin);
}
- public bool LoadPluginFromAssembly(FileInfo dllFile, bool raw, PluginLoadReason reason) {
+ public bool LoadPluginFromAssembly(FileInfo dllFile, bool raw, PluginLoadReason reason, bool preloaded = false, PluginDefinition preloadedDef = null) {
Log.Information("Loading plugin at {0}", dllFile.Directory.FullName);
// If this entire folder has been marked as a disabled plugin, don't even try to load anything
@@ -112,32 +112,50 @@ namespace Dalamud.Plugin
return false;
}
- // read the plugin def if present - again, fail before actually trying to load the dll if there is a problem
- var defJsonFile = new FileInfo(Path.Combine(dllFile.Directory.FullName, $"{Path.GetFileNameWithoutExtension(dllFile.Name)}.json"));
-
PluginDefinition pluginDef = null;
- // load the definition if it exists, even for raw/developer plugins
- if (defJsonFile.Exists)
- {
- Log.Information("Loading definition for plugin DLL {0}", dllFile.FullName);
- pluginDef =
- JsonConvert.DeserializeObject(
- File.ReadAllText(defJsonFile.FullName));
-
- if (pluginDef.ApplicableVersion != this.dalamud.StartInfo.GameVersion && pluginDef.ApplicableVersion != "any")
+ // Preloaded
+ if (preloaded) {
+ if (preloadedDef == null && !raw)
+ {
+ Log.Information("Plugin DLL {0} has no definition.", dllFile.FullName);
+ return false;
+ }
+ if (preloadedDef != null &&
+ preloadedDef.ApplicableVersion != this.dalamud.StartInfo.GameVersion &&
+ preloadedDef.ApplicableVersion != "any")
{
Log.Information("Plugin {0} has not applicable version.", dllFile.FullName);
return false;
}
+ pluginDef = preloadedDef;
+ } else {
+ // read the plugin def if present - again, fail before actually trying to load the dll if there is a problem
+ var defJsonFile = new FileInfo(Path.Combine(dllFile.Directory.FullName, $"{Path.GetFileNameWithoutExtension(dllFile.Name)}.json"));
+
+ // load the definition if it exists, even for raw/developer plugins
+ if (defJsonFile.Exists)
+ {
+ Log.Information("Loading definition for plugin DLL {0}", dllFile.FullName);
+
+ pluginDef =
+ JsonConvert.DeserializeObject(
+ File.ReadAllText(defJsonFile.FullName));
+
+ if (pluginDef.ApplicableVersion != this.dalamud.StartInfo.GameVersion && pluginDef.ApplicableVersion != "any")
+ {
+ Log.Information("Plugin {0} has not applicable version.", dllFile.FullName);
+ return false;
+ }
+ }
+ // but developer plugins don't require one to load
+ else if (!raw)
+ {
+ Log.Information("Plugin DLL {0} has no definition.", dllFile.FullName);
+ return false;
+ }
}
- // but developer plugins don't require one to load
- else if (!raw)
- {
- Log.Information("Plugin DLL {0} has no definition.", dllFile.FullName);
- return false;
- }
-
+
// TODO: given that it exists, the pluginDef's InternalName should probably be used
// as the actual assembly to load
// But plugins should also probably be loaded by directory and not by looking for every dll
@@ -203,14 +221,32 @@ namespace Dalamud.Plugin
if (folder.Exists)
{
Log.Information("Loading plugins at {0}", folder);
-
var pluginDlls = folder.GetFiles("*.dll", SearchOption.AllDirectories);
-
+
+ // Preload definitions to be able to determine load order
+ var pluginDefs = new List<(FileInfo dllFile, PluginDefinition definition)>();
foreach (var dllFile in pluginDlls) {
+ var defJson = new FileInfo(Path.Combine(dllFile.Directory.FullName, $"{Path.GetFileNameWithoutExtension(dllFile.Name)}.json"));
+ PluginDefinition def = null;
+ if (defJson.Exists)
+ def = JsonConvert.DeserializeObject(File.ReadAllText(defJson.FullName));
+ pluginDefs.Add((dllFile, def));
+ }
+
+ // Sort for load order - unloaded definitions have default priority of 0
+ pluginDefs.Sort(
+ (info1, info2) => {
+ var prio1 = info1.definition?.LoadPriority ?? 0;
+ var prio2 = info2.definition?.LoadPriority ?? 0;
+ return prio2.CompareTo(prio1);
+ });
+
+ // Pass preloaded definitions to LoadPluginFromAssembly, because we already loaded them anyways
+ foreach (var infos in pluginDefs) {
try {
- LoadPluginFromAssembly(dllFile, raw, PluginLoadReason.Boot);
+ LoadPluginFromAssembly(infos.dllFile, raw, PluginLoadReason.Boot, true, infos.definition);
} catch (Exception ex) {
- Log.Error(ex, $"Plugin load for {dllFile.FullName} failed.");
+ Log.Error(ex, $"Plugin load for {infos.dllFile.FullName} failed.");
}
}
}