diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index 05376a770..f21925b5a 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -2186,6 +2186,14 @@ internal class PluginInstallerWindow : Window, IDisposable ImGuiHelpers.SafeTextWrapped(manifest.Description); } + // Working Plugin ID + if (this.hasDevPlugins) + { + ImGuiHelpers.ScaledDummy(3); + ImGui.TextColored(ImGuiColors.DalamudGrey, $"WorkingPluginId: {manifest.WorkingPluginId}"); + ImGuiHelpers.ScaledDummy(3); + } + // Available commands (if loaded) if (plugin.IsLoaded) { diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index c98a6bbfc..58e122c3e 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -763,8 +763,9 @@ internal partial class PluginManager : IDisposable, IServiceType /// The plugin definition. /// If the testing version should be used. /// The reason this plugin was loaded. + /// WorkingPluginId this plugin should inherit. /// A representing the asynchronous operation. - public async Task InstallPluginAsync(RemotePluginManifest repoManifest, bool useTesting, PluginLoadReason reason) + public async Task InstallPluginAsync(RemotePluginManifest repoManifest, bool useTesting, PluginLoadReason reason, Guid? inheritedWorkingPluginId = null) { Log.Debug($"Installing plugin {repoManifest.Name} (testing={useTesting})"); @@ -851,6 +852,9 @@ internal partial class PluginManager : IDisposable, IServiceType // Reload as a local manifest, add some attributes, and save again. var manifest = LocalPluginManifest.Load(manifestFile); + if (manifest == null) + throw new Exception("Plugin had no valid manifest"); + if (manifest.InternalName != repoManifest.InternalName) { Directory.Delete(outputDir.FullName, true); @@ -858,6 +862,11 @@ internal partial class PluginManager : IDisposable, IServiceType $"Distributed internal name does not match repo internal name: {manifest.InternalName} - {repoManifest.InternalName}"); } + if (manifest.WorkingPluginId != Guid.Empty) + throw new Exception("Plugin shall not specify a WorkingPluginId"); + + manifest.WorkingPluginId = inheritedWorkingPluginId ?? Guid.NewGuid(); + if (useTesting) { manifest.Testing = true; @@ -1040,6 +1049,10 @@ internal partial class PluginManager : IDisposable, IServiceType { var plugin = metadata.InstalledPlugin; + var workingPluginId = metadata.InstalledPlugin.Manifest.WorkingPluginId; + if (workingPluginId == Guid.Empty) + throw new Exception("Existing plugin had no WorkingPluginId"); + var updateStatus = new PluginUpdateStatus { InternalName = plugin.Manifest.InternalName, @@ -1099,7 +1112,7 @@ internal partial class PluginManager : IDisposable, IServiceType try { - await this.InstallPluginAsync(metadata.UpdateManifest, metadata.UseTesting, PluginLoadReason.Update); + await this.InstallPluginAsync(metadata.UpdateManifest, metadata.UseTesting, PluginLoadReason.Update, workingPluginId); } catch (Exception ex) { diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index 5ad09ebc3..115ab0f8d 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -158,6 +158,14 @@ internal class LocalPlugin : IDisposable needsSaveDueToLegacyFiles = true; } + // Create an installation instance ID for this plugin, if it doesn't have one yet + if (this.manifest.WorkingPluginId == Guid.Empty) + { + this.manifest.WorkingPluginId = Guid.NewGuid(); + + needsSaveDueToLegacyFiles = true; + } + var pluginManager = Service.Get(); this.IsBanned = pluginManager.IsManifestBanned(this.manifest) && !this.IsDev; this.BanReason = pluginManager.GetBanReason(this.manifest); diff --git a/Dalamud/Plugin/Internal/Types/Manifest/ILocalPluginManifest.cs b/Dalamud/Plugin/Internal/Types/Manifest/ILocalPluginManifest.cs index 97365d1e5..5b147dde1 100644 --- a/Dalamud/Plugin/Internal/Types/Manifest/ILocalPluginManifest.cs +++ b/Dalamud/Plugin/Internal/Types/Manifest/ILocalPluginManifest.cs @@ -1,4 +1,6 @@ -namespace Dalamud.Plugin.Internal.Types.Manifest; +using System; + +namespace Dalamud.Plugin.Internal.Types.Manifest; /// /// Public interface for the local plugin manifest. @@ -16,4 +18,9 @@ public interface ILocalPluginManifest : IPluginManifest /// Gets a value indicating whether the plugin should be deleted during the next cleanup. /// public bool ScheduledForDeletion { get; } + + /// + /// Gets an ID uniquely identifying this specific installation of a plugin. + /// + public Guid WorkingPluginId { get; } } diff --git a/Dalamud/Plugin/Internal/Types/Manifest/LocalPluginManifest.cs b/Dalamud/Plugin/Internal/Types/Manifest/LocalPluginManifest.cs index 4b4bf5d6e..8afbe1aea 100644 --- a/Dalamud/Plugin/Internal/Types/Manifest/LocalPluginManifest.cs +++ b/Dalamud/Plugin/Internal/Types/Manifest/LocalPluginManifest.cs @@ -44,6 +44,9 @@ internal record LocalPluginManifest : PluginManifest, ILocalPluginManifest /// public string InstalledFromUrl { get; set; } = string.Empty; + /// + public Guid WorkingPluginId { get; set; } = Guid.Empty; + /// /// Gets a value indicating whether this manifest is associated with a plugin that was installed from a third party /// repo. Unless the manifest has been manually modified, this is determined by the InstalledFromUrl being null.