diff --git a/.editorconfig b/.editorconfig index 72d2313af..109c9f406 100644 --- a/.editorconfig +++ b/.editorconfig @@ -118,7 +118,11 @@ resharper_arrange_type_member_modifiers_highlighting = hint resharper_arrange_type_modifiers_highlighting = hint resharper_built_in_type_reference_style_for_member_access_highlighting = hint resharper_built_in_type_reference_style_highlighting = none +resharper_foreach_can_be_converted_to_query_using_another_get_enumerator_highlighting = none +resharper_foreach_can_be_partly_converted_to_query_using_another_get_enumerator_highlighting = none resharper_invert_if_highlighting = none +resharper_loop_can_be_converted_to_query_highlighting = none +resharper_method_has_async_overload_highlighting = none resharper_redundant_base_qualifier_highlighting = none resharper_suggest_var_or_type_built_in_types_highlighting = hint resharper_suggest_var_or_type_elsewhere_highlighting = hint diff --git a/Dalamud.sln.DotSettings b/Dalamud.sln.DotSettings index 4653085d4..690f1a7ac 100644 --- a/Dalamud.sln.DotSettings +++ b/Dalamud.sln.DotSettings @@ -47,12 +47,15 @@ True True True + True True True True True True True + True + True True True True diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index e1dcad965..701e7624e 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -18,6 +18,7 @@ using Dalamud.Interface.Internal.Windows; using Dalamud.IoC; using Dalamud.IoC.Internal; using Dalamud.Plugin.Internal; +using Dalamud.Plugin.Internal.Types; using Dalamud.Utility; using Serilog; @@ -302,7 +303,7 @@ namespace Dalamud.Game { if (configuration.AutoUpdatePlugins) { - pluginManager.PrintUpdatedPlugins(updatedPlugins, Loc.Localize("DalamudPluginAutoUpdate", "Auto-update:")); + PluginManager.PrintUpdatedPlugins(updatedPlugins, Loc.Localize("DalamudPluginAutoUpdate", "Auto-update:")); notifications.AddNotification(Loc.Localize("NotificationUpdatedPlugins", "{0} of your plugins were updated.").Format(updatedPlugins.Count), Loc.Localize("NotificationAutoUpdate", "Auto-Update"), NotificationType.Info); } else diff --git a/Dalamud/Interface/Internal/Windows/PluginImageCache.cs b/Dalamud/Interface/Internal/Windows/PluginImageCache.cs index 10f972106..2e714a8c8 100644 --- a/Dalamud/Interface/Internal/Windows/PluginImageCache.cs +++ b/Dalamud/Interface/Internal/Windows/PluginImageCache.cs @@ -320,7 +320,7 @@ namespace Dalamud.Interface.Internal.Windows isThirdParty = true; } - var useTesting = pluginManager.UseTesting(manifest); + var useTesting = PluginManager.UseTesting(manifest); var url = this.GetPluginIconUrl(manifest, isThirdParty, useTesting); if (!url.IsNullOrEmpty()) @@ -441,7 +441,7 @@ namespace Dalamud.Interface.Internal.Windows isThirdParty = true; } - var useTesting = pluginManager.UseTesting(manifest); + var useTesting = PluginManager.UseTesting(manifest); var urls = this.GetPluginImageUrls(manifest, isThirdParty, useTesting); if (urls != null) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index 265dcb58d..893577754 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -348,7 +348,7 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller if (this.updatePluginCount > 0) { - pluginManager.PrintUpdatedPlugins(this.updatedPlugins, Locs.PluginUpdateHeader_Chatbox); + PluginManager.PrintUpdatedPlugins(this.updatedPlugins, Locs.PluginUpdateHeader_Chatbox); notifications.AddNotification(Locs.Notifications_UpdatesInstalled(this.updatePluginCount), Locs.Notifications_UpdatesInstalledTitle, NotificationType.Success); var installedGroupIdx = this.categoryManager.GroupList.TakeWhile( @@ -1251,7 +1251,7 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller var notifications = Service.Get(); var pluginManager = Service.Get(); - var useTesting = pluginManager.UseTesting(manifest); + var useTesting = PluginManager.UseTesting(manifest); var wasSeen = this.WasPluginSeen(manifest.InternalName); // Check for valid versions diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 9cc09e566..2893f6ab2 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -104,7 +104,7 @@ namespace Dalamud.Plugin.Internal /// /// Gets a value indicating whether plugins are not still loading from boot. /// - public bool PluginsReady { get; private set; } = false; + public bool PluginsReady { get; private set; } /// /// Gets a value indicating whether all added repos are not in progress. @@ -121,6 +121,82 @@ namespace Dalamud.Plugin.Internal /// public PluginConfigurations PluginConfigs { get; } + /// + /// Print to chat any plugin updates and whether they were successful. + /// + /// The list of updated plugin metadata. + /// The header text to send to chat prior to any update info. + public static void PrintUpdatedPlugins(List? updateMetadata, string header) + { + var chatGui = Service.Get(); + + if (updateMetadata is { Count: > 0 }) + { + chatGui.Print(header); + + foreach (var metadata in updateMetadata) + { + if (metadata.WasUpdated) + { + chatGui.Print(Locs.DalamudPluginUpdateSuccessful(metadata.Name, metadata.Version)); + } + else + { + chatGui.PrintChat(new XivChatEntry + { + Message = Locs.DalamudPluginUpdateFailed(metadata.Name, metadata.Version), + Type = XivChatType.Urgent, + }); + } + } + } + } + + /// + /// For a given manifest, determine if the testing version should be used over the normal version. + /// The higher of the two versions is calculated after checking other settings. + /// + /// Manifest to check. + /// A value indicating whether testing should be used. + public static bool UseTesting(PluginManifest manifest) + { + var configuration = Service.Get(); + + if (!configuration.DoPluginTest) + return false; + + if (manifest.IsTestingExclusive) + return true; + + var av = manifest.AssemblyVersion; + var tv = manifest.TestingAssemblyVersion; + var hasTv = tv != null; + + if (hasTv) + { + return tv > av; + } + + return false; + } + + /// + /// Gets a value indicating whether the given repo manifest should be visible to the user. + /// + /// Repo manifest. + /// If the manifest is visible. + public static bool IsManifestVisible(RemotePluginManifest manifest) + { + var configuration = Service.Get(); + + // Hidden by user + if (configuration.HiddenPluginInternalName.Contains(manifest.InternalName)) + return false; + + // Hidden by manifest + return !manifest.IsHide; + } + /// public void Dispose() { @@ -144,7 +220,7 @@ namespace Dalamud.Plugin.Internal /// Set the list of repositories to use and downloads their contents. /// Should be called when the Settings window has been updated or at instantiation. /// - /// Whether the available plugins changed should be evented after. + /// Whether the available plugins changed event should be sent after. /// A representing the asynchronous operation. public async Task SetPluginReposFromConfigAsync(bool notify) { @@ -198,7 +274,7 @@ namespace Dalamud.Plugin.Internal var manifest = LocalPluginManifest.Load(manifestFile); - pluginDefs.Add(new(dllFile, manifest, false)); + pluginDefs.Add(new PluginDef(dllFile, manifest, false)); } } @@ -225,7 +301,7 @@ namespace Dalamud.Plugin.Internal // Manifests are not required for devPlugins. the Plugin type will handle any null manifests. var manifestFile = LocalPluginManifest.GetManifestFile(dllFile); var manifest = manifestFile.Exists ? LocalPluginManifest.Load(manifestFile) : null; - devPluginDefs.Add(new(dllFile, manifest, true)); + devPluginDefs.Add(new PluginDef(dllFile, manifest, true)); } // Sort for load order - unloaded definitions have default priority of 0 @@ -235,9 +311,9 @@ namespace Dalamud.Plugin.Internal // Dev plugins should load first. pluginDefs.InsertRange(0, devPluginDefs); - void LoadPlugins(IEnumerable pluginDefs) + void LoadPlugins(IEnumerable pluginDefsList) { - foreach (var pluginDef in pluginDefs) + foreach (var pluginDef in pluginDefsList) { try { @@ -260,7 +336,7 @@ namespace Dalamud.Plugin.Internal var asyncPlugins = pluginDefs.Where(def => def.Manifest == null || def.Manifest.LoadPriority <= 0); Task.Run(() => LoadPlugins(asyncPlugins)) - .ContinueWith(task => + .ContinueWith(_ => { this.PluginsReady = true; this.NotifyInstalledPluginsChanged(); @@ -318,7 +394,7 @@ namespace Dalamud.Plugin.Internal this.AvailablePlugins = this.Repos .SelectMany(repo => repo.PluginMaster) .Where(this.IsManifestEligible) - .Where(this.IsManifestVisible) + .Where(IsManifestVisible) .ToImmutableList(); if (notify) @@ -412,7 +488,7 @@ namespace Dalamud.Plugin.Internal var response = await Util.HttpClient.GetAsync(downloadUrl); response.EnsureSuccessStatusCode(); - var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory.FullName, repoManifest.InternalName, version.ToString())); + var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory.FullName, repoManifest.InternalName, version?.ToString() ?? string.Empty)); try { @@ -568,7 +644,6 @@ namespace Dalamud.Plugin.Internal { // Out of date plugins get added so they can be updated. Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}"); - // plugin.Disable(); // Don't disable, or it gets deleted next boot. } else { @@ -625,14 +700,12 @@ namespace Dalamud.Plugin.Internal return version; }) - .Where(version => version != null) .ToArray(); if (versionDirs.Length == 0) { Log.Information($"No versions: cleaning up {pluginDir.FullName}"); pluginDir.Delete(true); - continue; } else { @@ -675,7 +748,6 @@ namespace Dalamud.Plugin.Internal { Log.Information($"Inapplicable version: cleaning up {versionDir.FullName}"); versionDir.Delete(true); - continue; } } catch (Exception ex) @@ -737,13 +809,12 @@ namespace Dalamud.Plugin.Internal { InternalName = plugin.Manifest.InternalName, Name = plugin.Manifest.Name, - Version = metadata.UseTesting - ? metadata.UpdateManifest.TestingAssemblyVersion - : metadata.UpdateManifest.AssemblyVersion, + Version = (metadata.UseTesting + ? metadata.UpdateManifest.TestingAssemblyVersion + : metadata.UpdateManifest.AssemblyVersion)!, + WasUpdated = true, }; - updateStatus.WasUpdated = true; - if (!dryRun) { // Unload if loaded @@ -836,88 +907,6 @@ namespace Dalamud.Plugin.Internal plugin.Load(PluginLoadReason.Installer); } - /// - /// Print to chat any plugin updates and whether they were successful. - /// - /// The list of updated plugin metadata. - /// The header text to send to chat prior to any update info. - public void PrintUpdatedPlugins(List updateMetadata, string header) - { - var chatGui = Service.Get(); - - if (updateMetadata != null && updateMetadata.Count > 0) - { - chatGui.Print(header); - - foreach (var metadata in updateMetadata) - { - if (metadata.WasUpdated) - { - chatGui.Print(Locs.DalamudPluginUpdateSuccessful(metadata.Name, metadata.Version)); - } - else - { - chatGui.PrintChat(new XivChatEntry - { - Message = Locs.DalamudPluginUpdateFailed(metadata.Name, metadata.Version), - Type = XivChatType.Urgent, - }); - } - } - } - } - - /// - /// For a given manifest, determine if the testing version should be used over the normal version. - /// The higher of the two versions is calculated after checking other settings. - /// - /// Manifest to check. - /// A value indicating whether testing should be used. - public bool UseTesting(PluginManifest manifest) - { - var configuration = Service.Get(); - - if (!configuration.DoPluginTest) - return false; - - if (manifest.IsTestingExclusive) - return true; - - var av = manifest.AssemblyVersion; - var tv = manifest.TestingAssemblyVersion; - var hasAv = av != null; - var hasTv = tv != null; - - if (hasAv && hasTv) - { - return tv > av; - } - else - { - return hasTv; - } - } - - /// - /// Gets a value indicating whether the given repo manifest should be visible to the user. - /// - /// Repo manifest. - /// If the manifest is visible. - public bool IsManifestVisible(RemotePluginManifest manifest) - { - var configuration = Service.Get(); - - // Hidden by user - if (configuration.HiddenPluginInternalName.Contains(manifest.InternalName)) - return false; - - // Hidden by manifest - if (manifest.IsHide) - return false; - - return true; - } - /// /// Gets a value indicating whether the given manifest is eligible for ANYTHING. These are hard /// checks that should not allow installation or loading. @@ -942,10 +931,7 @@ namespace Dalamud.Plugin.Internal return false; // Banned - if (this.IsManifestBanned(manifest)) - return false; - - return true; + return !this.IsManifestBanned(manifest); } /// @@ -984,7 +970,7 @@ namespace Dalamud.Plugin.Internal .Where(remoteManifest => plugin.Manifest.InternalName == remoteManifest.InternalName) .Select(remoteManifest => { - var useTesting = this.UseTesting(remoteManifest); + var useTesting = UseTesting(remoteManifest); var candidateVersion = useTesting ? remoteManifest.TestingAssemblyVersion : remoteManifest.AssemblyVersion; @@ -998,7 +984,7 @@ namespace Dalamud.Plugin.Internal if (updates.Count > 0) { var update = updates.Aggregate((t1, t2) => t1.candidateVersion > t2.candidateVersion ? t1 : t2); - updatablePlugins.Add(new(plugin, update.remoteManifest, update.useTesting)); + updatablePlugins.Add(new AvailablePluginUpdate(plugin, update.remoteManifest, update.useTesting)); } } @@ -1033,41 +1019,6 @@ namespace Dalamud.Plugin.Internal } } - private struct BannedPlugin - { - [JsonProperty] - public string Name { get; private set; } - - [JsonProperty] - public Version AssemblyVersion { get; private set; } - - [JsonProperty] - public string Reason { get; private set; } - } - - private struct PluginDef - { - public PluginDef(FileInfo dllFile, LocalPluginManifest? manifest, bool isDev) - { - this.DllFile = dllFile; - this.Manifest = manifest; - this.IsDev = isDev; - } - - public FileInfo DllFile { get; init; } - - public LocalPluginManifest? Manifest { get; init; } - - public bool IsDev { get; init; } - - public static int Sorter(PluginDef def1, PluginDef def2) - { - var prio1 = def1.Manifest?.LoadPriority ?? 0; - var prio2 = def2.Manifest?.LoadPriority ?? 0; - return prio2.CompareTo(prio1); - } - } - private static class Locs { public static string DalamudPluginUpdateSuccessful(string name, Version version) => Loc.Localize("DalamudPluginUpdateSuccessful", " 》 {0} updated to v{1}.").Format(name, version); @@ -1162,7 +1113,7 @@ namespace Dalamud.Plugin.Internal if (methodBase == null) continue; - yield return methodBase.Module.Assembly.FullName; + yield return methodBase.Module.Assembly.FullName!; } } @@ -1171,37 +1122,14 @@ namespace Dalamud.Plugin.Internal var targetType = typeof(PluginManager).Assembly.GetType(); var locationTarget = targetType.GetProperty(nameof(Assembly.Location))!.GetGetMethod(); - var locationPatch = typeof(PluginManager).GetMethod(nameof(PluginManager.AssemblyLocationPatch), BindingFlags.NonPublic | BindingFlags.Static); + var locationPatch = typeof(PluginManager).GetMethod(nameof(AssemblyLocationPatch), BindingFlags.NonPublic | BindingFlags.Static); this.assemblyLocationMonoHook = new MonoMod.RuntimeDetour.Hook(locationTarget, locationPatch); -#pragma warning disable SYSLIB0012 // Type or member is obsolete - var codebaseTarget = targetType.GetProperty(nameof(Assembly.CodeBase)).GetGetMethod(); - var codebasePatch = typeof(PluginManager).GetMethod(nameof(PluginManager.AssemblyCodeBasePatch), BindingFlags.NonPublic | BindingFlags.Static); + #pragma warning disable CS0618 + var codebaseTarget = targetType.GetProperty(nameof(Assembly.CodeBase))?.GetGetMethod(); + #pragma warning restore CS0618 + var codebasePatch = typeof(PluginManager).GetMethod(nameof(AssemblyCodeBasePatch), BindingFlags.NonPublic | BindingFlags.Static); this.assemblyCodeBaseMonoHook = new MonoMod.RuntimeDetour.Hook(codebaseTarget, codebasePatch); -#pragma warning restore SYSLIB0012 // Type or member is obsolete - } - - internal record PluginPatchData - { - /// - /// Initializes a new instance of the class. - /// - /// DLL file being loaded. - public PluginPatchData(FileInfo dllFile) - { - this.Location = dllFile.FullName; - this.CodeBase = new Uri(dllFile.FullName).AbsoluteUri; - } - - /// - /// Gets simulated Assembly.Location output. - /// - public string Location { get; } - - /// - /// Gets simulated Assembly.CodeBase output. - /// - public string CodeBase { get; } } } } diff --git a/Dalamud/Plugin/Internal/Types/BannedPlugin.cs b/Dalamud/Plugin/Internal/Types/BannedPlugin.cs new file mode 100644 index 000000000..1d5f956b3 --- /dev/null +++ b/Dalamud/Plugin/Internal/Types/BannedPlugin.cs @@ -0,0 +1,29 @@ +using System; + +using Newtonsoft.Json; + +namespace Dalamud.Plugin.Internal.Types; + +/// +/// Banned plugin version that is blocked from installation. +/// +internal struct BannedPlugin +{ + /// + /// Gets plugin name. + /// + [JsonProperty] + public string Name { get; private set; } + + /// + /// Gets plugin assembly version. + /// + [JsonProperty] + public Version AssemblyVersion { get; private set; } + + /// + /// Gets reason for the ban. + /// + [JsonProperty] + public string Reason { get; private set; } +} diff --git a/Dalamud/Plugin/Internal/Types/PluginDef.cs b/Dalamud/Plugin/Internal/Types/PluginDef.cs new file mode 100644 index 000000000..c5dbede0d --- /dev/null +++ b/Dalamud/Plugin/Internal/Types/PluginDef.cs @@ -0,0 +1,50 @@ +using System.IO; + +namespace Dalamud.Plugin.Internal.Types; + +/// +/// Plugin Definition. +/// +internal struct PluginDef +{ + /// + /// Initializes a new instance of the struct. + /// + /// plugin dll file. + /// plugin manifest. + /// plugin dev indicator. + public PluginDef(FileInfo dllFile, LocalPluginManifest? manifest, bool isDev) + { + this.DllFile = dllFile; + this.Manifest = manifest; + this.IsDev = isDev; + } + + /// + /// Gets plugin DLL File. + /// + public FileInfo DllFile { get; init; } + + /// + /// Gets plugin manifest. + /// + public LocalPluginManifest? Manifest { get; init; } + + /// + /// Gets a value indicating whether plugin is a dev plugin. + /// + public bool IsDev { get; init; } + + /// + /// Sort plugin definitions by priority. + /// + /// plugin definition 1 to compare. + /// plugin definition 2 to compare. + /// sort order. + public static int Sorter(PluginDef def1, PluginDef def2) + { + var priority1 = def1.Manifest?.LoadPriority ?? 0; + var priority2 = def2.Manifest?.LoadPriority ?? 0; + return priority2.CompareTo(priority1); + } +} diff --git a/Dalamud/Plugin/Internal/Types/PluginPatchData.cs b/Dalamud/Plugin/Internal/Types/PluginPatchData.cs new file mode 100644 index 000000000..d95c1e62c --- /dev/null +++ b/Dalamud/Plugin/Internal/Types/PluginPatchData.cs @@ -0,0 +1,27 @@ +using System; +using System.IO; + +namespace Dalamud.Plugin.Internal.Types; + +internal record PluginPatchData +{ + /// + /// Initializes a new instance of the class. + /// + /// DLL file being loaded. + public PluginPatchData(FileSystemInfo dllFile) + { + this.Location = dllFile.FullName; + this.CodeBase = new Uri(dllFile.FullName).AbsoluteUri; + } + + /// + /// Gets simulated Assembly.Location output. + /// + public string Location { get; } + + /// + /// Gets simulated Assembly.CodeBase output. + /// + public string CodeBase { get; } +}