diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index d183f7afd..72659fa05 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -329,6 +329,11 @@ namespace Dalamud { HelpMessage = "Draw dev menu DEBUG", ShowInHelp = false }); + + CommandManager.AddHandler("/xlplugins", new CommandInfo(OnOpenInstallerCommand) + { + HelpMessage = "Open the plugin installer" + }); } private void OnUnloadCommand(string command, string arguments) { @@ -550,6 +555,11 @@ namespace Dalamud { this.isImguiDrawDevMenu = true; } + private void OnOpenInstallerCommand(string command, string arguments) { + this.pluginWindow = new PluginInstallerWindow(this.PluginManager, this.StartInfo.PluginDirectory, this.StartInfo.GameVersion); + this.isImguiDrawPluginWindow = true; + } + private int RouletteSlugToKey(string slug) => slug.ToLower() switch { "leveling" => 1, "506070" => 2, diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index e1fd9aa11..3171c9eee 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -40,7 +40,7 @@ - + diff --git a/Dalamud/Plugin/PluginDefinition.cs b/Dalamud/Plugin/PluginDefinition.cs index 6e3c97d94..20768d6a6 100644 --- a/Dalamud/Plugin/PluginDefinition.cs +++ b/Dalamud/Plugin/PluginDefinition.cs @@ -13,6 +13,7 @@ namespace Dalamud.Plugin public string InternalName { get; set; } public string AssemblyVersion { get; set; } public string Description { get; set; } - public string ApplicableGameVersion { get; set; } + public string ApplicableVersion { get; set; } + public bool IsHide { get; set; } } } diff --git a/Dalamud/Plugin/PluginInstallerWindow.cs b/Dalamud/Plugin/PluginInstallerWindow.cs index 6dd8458e3..8ff71a132 100644 --- a/Dalamud/Plugin/PluginInstallerWindow.cs +++ b/Dalamud/Plugin/PluginInstallerWindow.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; @@ -60,6 +61,53 @@ namespace Dalamud.Plugin } } + public void UpdatePlugins() { + try { + var pluginsDirectory = new DirectoryInfo(this.pluginDirectory); + this.installStatus = PluginInstallStatus.Success; + foreach (var installed in pluginsDirectory.GetDirectories()) { + var versions = installed.GetDirectories(); + + if (versions.Length == 0) { + Log.Information("Has no versions: {0}", installed.FullName); + continue; + } + + var sortedVersions = versions.OrderBy(x => x.CreationTime); + var latest = sortedVersions.Last(); + + var localInfoFile = new FileInfo(Path.Combine(latest.FullName, $"{installed.Name}.json")); + + if (!localInfoFile.Exists) + { + Log.Information("Has no definition: {0}", localInfoFile.FullName); + continue; + } + + var info = JsonConvert.DeserializeObject(File.ReadAllText(localInfoFile.FullName)); + + var remoteInfo = this.pluginMaster.FirstOrDefault(x => x.Name == info.Name); + + if (remoteInfo == null) + { + Log.Information("Is not in pluginmaster: {0}", info.Name); + continue; + } + + if (remoteInfo.AssemblyVersion != info.AssemblyVersion) + { + this.manager.DisablePlugin(info); + InstallPlugin(remoteInfo); + } + } + } + catch (Exception e) + { + Log.Error(e, "Plugin update failed hard."); + this.installStatus = PluginInstallStatus.Fail; + } + } + private void InstallPlugin(PluginDefinition definition) { try { var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory, definition.InternalName, definition.AssemblyVersion)); @@ -70,8 +118,7 @@ namespace Dalamud.Plugin if (disabledFile.Exists) disabledFile.Delete(); - this.manager.LoadPluginFromAssembly(dllFile, false); - this.installStatus = PluginInstallStatus.Success; + this.installStatus = this.manager.LoadPluginFromAssembly(dllFile, false) ? PluginInstallStatus.Success : PluginInstallStatus.Fail; return; } @@ -88,8 +135,7 @@ namespace Dalamud.Plugin ZipFile.ExtractToDirectory(path, outputDir.FullName); - this.installStatus = PluginInstallStatus.Success; - this.manager.LoadPluginFromAssembly(dllFile, false); + this.installStatus = this.manager.LoadPluginFromAssembly(dllFile, false) ? PluginInstallStatus.Success : PluginInstallStatus.Fail; } catch (Exception e) { Log.Error(e, "Plugin download failed hard."); this.installStatus = PluginInstallStatus.Fail; @@ -120,8 +166,11 @@ namespace Dalamud.Plugin else { foreach (var pluginDefinition in this.pluginMaster) { - if (pluginDefinition.ApplicableGameVersion != this.gameVersion && - pluginDefinition.ApplicableGameVersion != "any") + if (pluginDefinition.ApplicableVersion != this.gameVersion && + pluginDefinition.ApplicableVersion != "any") + continue; + + if (pluginDefinition.IsHide) continue; if (ImGui.CollapsingHeader(pluginDefinition.Name)) { @@ -170,6 +219,9 @@ namespace Dalamud.Plugin if (ImGui.Button("Open Configuration")) v2Plugin.OpenConfigUi?.Invoke(null, null); } + + ImGui.SameLine(); + ImGui.TextColored(new Vector4(0.5f, 0.5f, 0.5f, 1.0f), $" v{pluginDefinition.AssemblyVersion}"); } ImGui.Unindent(); @@ -183,17 +235,22 @@ namespace Dalamud.Plugin ImGui.Separator(); - if (ImGui.Button("Remove All")) - { - - } - - ImGui.SameLine(); - - if (ImGui.Button("Open Plugin folder")) - { + if (this.installStatus == PluginInstallStatus.InProgress) { + ImGui.Button("In progress..."); + } else { + if (ImGui.Button("Update plugins")) + { + this.installStatus = PluginInstallStatus.InProgress; + Task.Run(() => UpdatePlugins()).ContinueWith(t => { + this.installStatus = + t.IsFaulted ? PluginInstallStatus.Fail : this.installStatus; + this.errorModalDrawing = this.installStatus == PluginInstallStatus.Fail; + this.errorModalOnNextFrame = this.installStatus == PluginInstallStatus.Fail; + }); + } } + ImGui.SameLine(); @@ -206,7 +263,7 @@ namespace Dalamud.Plugin if (ImGui.BeginPopupModal("Installer failed", ref this.errorModalDrawing, ImGuiWindowFlags.AlwaysAutoResize)) { - ImGui.Text("The plugin installer ran into an issue."); + ImGui.Text("The plugin installer ran into an issue or the plugin is incompatible."); ImGui.Text("Please restart the game and report this error on our discord."); ImGui.Spacing(); diff --git a/Dalamud/Plugin/PluginManager.cs b/Dalamud/Plugin/PluginManager.cs index 663d47732..f2a748f53 100644 --- a/Dalamud/Plugin/PluginManager.cs +++ b/Dalamud/Plugin/PluginManager.cs @@ -68,7 +68,7 @@ namespace Dalamud.Plugin this.Plugins.Remove(thisPlugin); } - public void LoadPluginFromAssembly(FileInfo dllFile, bool raw) { + public bool LoadPluginFromAssembly(FileInfo dllFile, bool raw) { Log.Information("Loading assembly at {0}", dllFile); var assemblyName = AssemblyName.GetAssemblyName(dllFile.FullName); var pluginAssembly = Assembly.Load(assemblyName); @@ -90,7 +90,7 @@ namespace Dalamud.Plugin if (disabledFile.Exists && !raw) { Log.Information("Plugin {0} is disabled.", dllFile.FullName); - return; + return false; } var defJsonFile = new FileInfo(Path.Combine(dllFile.Directory.FullName, $"{Path.GetFileNameWithoutExtension(dllFile.Name)}.json")); @@ -103,11 +103,16 @@ namespace Dalamud.Plugin 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; + } } else { Log.Information("Plugin DLL {0} has no definition.", dllFile.FullName); - return; + return false; } var plugin = (IDalamudPlugin)Activator.CreateInstance(type); @@ -116,9 +121,15 @@ namespace Dalamud.Plugin plugin.Initialize(dalamudInterface); Log.Information("Loaded plugin: {0}", plugin.Name); this.Plugins.Add((plugin, pluginDef, dalamudInterface)); + + return true; } } } + + Log.Information("Plugin DLL {0} has no plugin interface.", dllFile.FullName); + + return false; } private void LoadPluginsAt(DirectoryInfo folder, bool raw) {