From 88c5c5bb74318df4729da5feb25f062c72d549bf Mon Sep 17 00:00:00 2001 From: UnknownX7 Date: Tue, 14 Sep 2021 23:08:11 -0500 Subject: [PATCH 01/16] Fix MaxKeyCodeIndex --- Dalamud/Game/ClientState/Keys/KeyState.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Dalamud/Game/ClientState/Keys/KeyState.cs b/Dalamud/Game/ClientState/Keys/KeyState.cs index 49e6556c9..0476eee89 100644 --- a/Dalamud/Game/ClientState/Keys/KeyState.cs +++ b/Dalamud/Game/ClientState/Keys/KeyState.cs @@ -27,7 +27,7 @@ namespace Dalamud.Game.ClientState.Keys // The array is accessed in a way that this limit doesn't appear to exist // but there is other state data past this point, and keys beyond here aren't // generally valid for most things anyway - private const int MaxKeyCodeIndex = 0xA0; + private const int MaxKeyCode = 0xF0; private readonly IntPtr bufferBase; private readonly IntPtr indexBase; private VirtualKey[] validVirtualKeyCache = null; @@ -104,7 +104,7 @@ namespace Dalamud.Game.ClientState.Keys /// Virtual key code. /// If the code is valid. public bool IsVirtualKeyValid(int vkCode) - => vkCode > 0 && vkCode < MaxKeyCodeIndex && this.ConvertVirtualKey(vkCode) != 0; + => this.ConvertVirtualKey(vkCode) != 0; /// public bool IsVirtualKeyValid(VirtualKey vkCode) @@ -136,7 +136,7 @@ namespace Dalamud.Game.ClientState.Keys /// Converted value. private unsafe byte ConvertVirtualKey(int vkCode) { - if (vkCode <= 0 || vkCode >= 240) + if (vkCode <= 0 || vkCode >= MaxKeyCode) return 0; return *(byte*)(this.indexBase + vkCode); @@ -149,9 +149,6 @@ namespace Dalamud.Game.ClientState.Keys /// A reference to the indexed array. private unsafe ref int GetRefValue(int vkCode) { - if (vkCode < 0 || vkCode > MaxKeyCodeIndex) - throw new ArgumentException($"Keycode state is only valid up to {MaxKeyCodeIndex}"); - vkCode = this.ConvertVirtualKey(vkCode); if (vkCode == 0) From 443124d73f4778f5bba98bef2824e0d3257df2ed Mon Sep 17 00:00:00 2001 From: Raymond Date: Thu, 16 Sep 2021 09:00:19 -0400 Subject: [PATCH 02/16] loadIcon improvements, load dev plugin images --- .../Internal/Windows/PluginInstallerWindow.cs | 368 +++++++++++------- .../Internal/Types/LocalPluginManifest.cs | 9 +- 2 files changed, 234 insertions(+), 143 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs index 7318badbe..85d8356e5 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs @@ -25,7 +25,6 @@ using Dalamud.Plugin.Internal.Types; using Dalamud.Utility; using ImGuiNET; using ImGuiScene; -using Microsoft.VisualBasic; namespace Dalamud.Interface.Internal.Windows { @@ -56,7 +55,7 @@ namespace Dalamud.Interface.Internal.Windows private string[] testerImagePaths = new string[5]; private string testerIconPath = string.Empty; - private TextureWrap?[]? testerImages; + private TextureWrap?[] testerImages; private TextureWrap? testerIcon; private bool testerError = false; @@ -76,9 +75,8 @@ namespace Dalamud.Interface.Internal.Windows private List pluginListUpdatable = new(); private bool hasDevPlugins = false; - private bool downloadingIcons = false; - private Dictionary pluginImagesMap = new(); - private Dictionary pluginIconMap = new(); + private Dictionary pluginIconMap = new(); + private Dictionary pluginImagesMap = new(); private string searchText = string.Empty; @@ -197,8 +195,6 @@ namespace Dalamud.Interface.Internal.Windows { this.pluginIconMap.Clear(); this.pluginImagesMap.Clear(); - - this.DownloadPluginIcons(); } private static Vector2 GetButtonSize(string text) => ImGui.CalcTextSize(text) + (ImGui.GetStyle().FramePadding * 2); @@ -211,10 +207,18 @@ namespace Dalamud.Interface.Internal.Windows return MainRepoImageUrl.Format(isTesting ? "testing" : "plugins", manifest.InternalName, "icon.png"); } - private static List? GetPluginImageUrls(PluginManifest manifest, bool isThirdParty, bool isTesting) + private static List GetPluginImageUrls(PluginManifest manifest, bool isThirdParty, bool isTesting) { if (isThirdParty) + { + if (manifest.ImageUrls.Count > 5) + { + Log.Warning($"Plugin {manifest.InternalName} has too many images"); + return manifest.ImageUrls.Take(5).ToList(); + } + return manifest.ImageUrls; + } var output = new List(); for (var i = 1; i <= 5; i++) @@ -225,6 +229,46 @@ namespace Dalamud.Interface.Internal.Windows return output; } + private static FileInfo? GetPluginIconFileInfo(LocalPlugin? plugin) + { + var pluginDir = plugin.DllFile.Directory; + var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "icon.png")); + if (devUrl.Exists) + return devUrl; + + devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", "icon.png")); + if (devUrl.Exists) + return devUrl; + + return null; + } + + private static List GetPluginImageFileInfos(LocalPlugin? plugin) + { + var pluginDir = plugin.DllFile.Directory; + var output = new List(); + for (var i = 1; i <= 5; i++) + { + var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, $"image{i}.png")); + if (devUrl.Exists) + { + output.Add(devUrl); + continue; + } + + devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", $"image{i}.png")); + if (devUrl.Exists) + { + output.Add(devUrl); + continue; + } + + output.Add(null); + } + + return output; + } + private void DrawHeader() { var style = ImGui.GetStyle(); @@ -557,7 +601,6 @@ namespace Dalamud.Interface.Internal.Windows } } - // TODO: Technically, we really should just load images from a devplugin folder private void DrawImageTester() { var sectionSize = ImGuiHelpers.GlobalScale * 66; @@ -802,7 +845,7 @@ namespace Dalamud.Interface.Internal.Windows return ready; } - private bool DrawPluginCollapsingHeader(string label, PluginManifest manifest, bool trouble, bool updateAvailable, bool isNew, Action drawContextMenuAction, int index) + private bool DrawPluginCollapsingHeader(string label, LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty, bool trouble, bool updateAvailable, bool isNew, Action drawContextMenuAction, int index) { ImGui.Separator(); @@ -839,12 +882,20 @@ namespace Dalamud.Interface.Internal.Windows ImGui.SetCursorPos(startCursor); - var hasIcon = this.pluginIconMap.TryGetValue(manifest.InternalName, out var icon); - var iconTex = this.defaultIcon; - if (hasIcon && icon.IsDownloaded && icon.Texture != null) + var hasIcon = this.pluginIconMap.TryGetValue(manifest.InternalName, out var cachedIconTex); + if (!hasIcon) { - iconTex = icon.Texture; + this.pluginIconMap.Add(manifest.InternalName, null); + Task.Run(async () => await this.DownloadPluginIconAsync(plugin, manifest, isThirdParty)); + } + else if (cachedIconTex != null) + { + iconTex = cachedIconTex; + } + else + { + // nothing } var iconSize = ImGuiHelpers.ScaledVector2(64, 64); @@ -875,8 +926,8 @@ namespace Dalamud.Interface.Internal.Windows // Download count var downloadCountText = manifest.DownloadCount > 0 - ? Locs.PluginBody_AuthorWithDownloadCount(manifest.Author, manifest.DownloadCount) - : Locs.PluginBody_AuthorWithDownloadCountUnavailable(manifest.Author); + ? Locs.PluginBody_AuthorWithDownloadCount(manifest.Author, manifest.DownloadCount) + : Locs.PluginBody_AuthorWithDownloadCountUnavailable(manifest.Author); ImGui.SameLine(); ImGui.TextColored(ImGuiColors.DalamudGrey3, downloadCountText); @@ -929,7 +980,8 @@ namespace Dalamud.Interface.Internal.Windows ImGui.PushID($"available{index}{manifest.InternalName}"); - if (this.DrawPluginCollapsingHeader(label, manifest, false, false, !wasSeen, () => this.DrawAvailablePluginContextMenu(manifest), index)) + var isThirdParty = manifest.SourceRepo.IsThirdParty; + if (this.DrawPluginCollapsingHeader(label, null, manifest, isThirdParty, false, false, !wasSeen, () => this.DrawAvailablePluginContextMenu(manifest), index)) { if (!wasSeen) configuration.SeenPluginInternalName.Add(manifest.InternalName); @@ -998,7 +1050,7 @@ namespace Dalamud.Interface.Internal.Windows ImGuiHelpers.ScaledDummy(5); - if (this.DrawPluginImages(manifest, index, manifest.SourceRepo.IsThirdParty)) + if (this.DrawPluginImages(null, manifest, isThirdParty, index)) ImGuiHelpers.ScaledDummy(5); ImGui.Unindent(); @@ -1134,7 +1186,7 @@ namespace Dalamud.Interface.Internal.Windows ImGui.PushID($"installed{index}{plugin.Manifest.InternalName}"); - if (this.DrawPluginCollapsingHeader(label, plugin.Manifest, trouble, availablePluginUpdate != default, false, () => this.DrawInstalledPluginContextMenu(plugin), index)) + if (this.DrawPluginCollapsingHeader(label, plugin, plugin.Manifest, plugin.Manifest.IsThirdParty, trouble, availablePluginUpdate != default, false, () => this.DrawInstalledPluginContextMenu(plugin), index)) { if (!this.WasPluginSeen(plugin.Manifest.InternalName)) configuration.SeenPluginInternalName.Add(plugin.Manifest.InternalName); @@ -1156,7 +1208,7 @@ namespace Dalamud.Interface.Internal.Windows ImGui.SameLine(); ImGui.TextColored(ImGuiColors.DalamudGrey3, downloadText); - var isThirdParty = !string.IsNullOrEmpty(manifest.InstalledFromUrl); + var isThirdParty = manifest.IsThirdParty; // Installed from if (plugin.IsDev) @@ -1219,9 +1271,8 @@ namespace Dalamud.Interface.Internal.Windows ImGuiHelpers.ScaledDummy(5); - this.DrawPluginImages(manifest, index, isThirdParty); - - ImGuiHelpers.ScaledDummy(5); + if (this.DrawPluginImages(plugin, manifest, isThirdParty, index)) + ImGuiHelpers.ScaledDummy(5); ImGui.Unindent(); } @@ -1512,18 +1563,18 @@ namespace Dalamud.Interface.Internal.Windows } } - private bool DrawPluginImages(PluginManifest manifest, int index, bool isThirdParty) + private bool DrawPluginImages(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty, int index) { - if (!this.pluginImagesMap.TryGetValue(manifest.InternalName, out var images)) + var hasImages = this.pluginImagesMap.TryGetValue(manifest.InternalName, out var imageTextures); + if (!hasImages) { - Task.Run(() => this.DownloadPluginImagesAsync(manifest, isThirdParty)); + this.pluginImagesMap.Add(manifest.InternalName, Array.Empty()); + Task.Run(async () => await this.DownloadPluginImagesAsync(plugin, manifest, isThirdParty)); + return false; } - if (!images.IsDownloaded) - return false; - - if (images.Textures == null) + if (imageTextures.Length == 0) return false; const float thumbFactor = 2.7f; @@ -1536,42 +1587,39 @@ namespace Dalamud.Interface.Internal.Windows if (ImGui.BeginChild($"plugin{index}ImageScrolling", new Vector2(width - (70 * ImGuiHelpers.GlobalScale), (PluginImageHeight / thumbFactor) + scrollBarSize), false, ImGuiWindowFlags.HorizontalScrollbar | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoBackground)) { - if (images.Textures != null && images.Textures is { Length: > 0 }) + for (var i = 0; i < imageTextures.Length; i++) { - for (var i = 0; i < images.Textures.Length; i++) + var image = imageTextures[i]; + if (image == null) + continue; + + ImGui.PushStyleVar(ImGuiStyleVar.PopupBorderSize, 0); + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); + ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); + + var popupId = $"plugin{index}image{i}"; + if (ImGui.BeginPopup(popupId)) { - var popupId = $"plugin{index}image{i}"; - var image = images.Textures[i]; - if (image == null) - continue; + if (ImGui.ImageButton(image.ImGuiHandle, new Vector2(image.Width, image.Height))) + ImGui.CloseCurrentPopup(); - ImGui.PushStyleVar(ImGuiStyleVar.PopupBorderSize, 0); - ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); - ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); + ImGui.EndPopup(); + } - if (ImGui.BeginPopup(popupId)) - { - if (ImGui.ImageButton(image.ImGuiHandle, new Vector2(image.Width, image.Height))) - ImGui.CloseCurrentPopup(); + ImGui.PopStyleVar(3); - ImGui.EndPopup(); - } + ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); - ImGui.PopStyleVar(3); + if (ImGui.ImageButton(image.ImGuiHandle, ImGuiHelpers.ScaledVector2(image.Width / thumbFactor, image.Height / thumbFactor))) + ImGui.OpenPopup(popupId); - ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); + ImGui.PopStyleVar(); - if (ImGui.ImageButton(image.ImGuiHandle, ImGuiHelpers.ScaledVector2(image.Width / thumbFactor, image.Height / thumbFactor))) - ImGui.OpenPopup(popupId); - - ImGui.PopStyleVar(); - - if (i < images.Textures.Length - 1) - { - ImGui.SameLine(); - ImGuiHelpers.ScaledDummy(5); - ImGui.SameLine(); - } + if (i < imageTextures.Length - 1) + { + ImGui.SameLine(); + ImGuiHelpers.ScaledDummy(5); + ImGui.SameLine(); } } } @@ -1614,8 +1662,6 @@ namespace Dalamud.Interface.Internal.Windows .ToList(); this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList(); this.ResortPlugins(); - - this.DownloadPluginIcons(); } private void OnInstalledPluginsChanged() @@ -1626,8 +1672,6 @@ namespace Dalamud.Interface.Internal.Windows this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList(); this.hasDevPlugins = this.pluginListInstalled.Any(plugin => plugin.IsDev); this.ResortPlugins(); - - this.DownloadPluginIcons(); } private void ResortPlugins() @@ -1707,133 +1751,173 @@ namespace Dalamud.Interface.Internal.Windows this.errorModalOnNextFrame = true; } - private void DownloadPluginIcons() + private async Task DownloadPluginIconAsync(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty) { - if (this.downloadingIcons) + var interfaceManager = Service.Get(); + var pluginManager = Service.Get(); + + static bool ValidateIcon(TextureWrap icon, string loc) { - Log.Error("Already downloading icons, skipping..."); + if (icon == null) + return false; + + if (icon.Height > PluginIconHeight || icon.Width > PluginIconWidth) + { + Log.Error($"Icon at {loc} was not of the correct resolution."); + return false; + } + + if (icon.Height != icon.Width) + { + Log.Error($"Icon at {loc} was not square."); + return false; + } + + return true; + } + + if (plugin != null && plugin.IsDev) + { + var file = GetPluginIconFileInfo(plugin); + if (file != null) + { + Log.Verbose($"Fetching icon for {manifest.InternalName} from {file.FullName}"); + + var icon = interfaceManager.LoadImage(file.FullName); + + if (!ValidateIcon(icon, file.FullName)) + return; + + this.pluginIconMap[manifest.InternalName] = icon; + Log.Verbose($"Plugin icon for {manifest.InternalName} loaded from disk"); + } + return; } - this.downloadingIcons = true; - - var pluginManager = Service.Get(); - - Log.Verbose("Start downloading plugin icons..."); - - Task.Run(async () => - { - var plugins = pluginManager.AvailablePlugins.Select(x => x); - - foreach (var pluginManifest in plugins) - { - var useTesting = pluginManager.UseTesting(pluginManifest); - - if (!this.pluginIconMap.ContainsKey(pluginManifest.InternalName)) - await this.DownloadPluginIconAsync(pluginManifest, useTesting); - } - }).ContinueWith(t => - { - Log.Verbose($"Icon download finished, faulted: {t.IsFaulted}"); - this.downloadingIcons = false; - }); - } - - private async Task DownloadPluginIconAsync(RemotePluginManifest manifest, bool isTesting) - { - var interfaceManager = Service.Get(); - - Log.Verbose($"Downloading icon for {manifest.InternalName}"); - this.pluginIconMap.Add(manifest.InternalName, (false, null)); - - var url = GetPluginIconUrl(manifest, manifest.SourceRepo.IsThirdParty, isTesting); - - Log.Verbose($"Icon from {url}"); - + var useTesting = pluginManager.UseTesting(manifest); + var url = GetPluginIconUrl(manifest, isThirdParty, useTesting); if (url != null) { + Log.Verbose($"Downloading icon for {manifest.InternalName} from {url}"); + var data = await this.httpClient.GetAsync(url); if (data.StatusCode == HttpStatusCode.NotFound) return; data.EnsureSuccessStatusCode(); + var icon = interfaceManager.LoadImage(await data.Content.ReadAsByteArrayAsync()); - if (icon != null) - { - if (icon.Height > PluginIconHeight || icon.Width > PluginIconWidth) - { - Log.Error($"Icon at {manifest.IconUrl} was not of the correct resolution."); - return; - } + if (!ValidateIcon(icon, url)) + return; - if (icon.Height != icon.Width) - { - Log.Error($"Icon at {manifest.IconUrl} was not square."); - return; - } + this.pluginIconMap[manifest.InternalName] = icon; + Log.Verbose($"Plugin icon for {manifest.InternalName} downloaded"); - this.pluginIconMap[manifest.InternalName] = (true, icon); - } + return; } + + Log.Verbose($"Icon for {manifest.InternalName} is not available"); } - private async Task DownloadPluginImagesAsync(PluginManifest manifest, bool isThirdParty) + private async Task DownloadPluginImagesAsync(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty) { var interfaceManager = Service.Get(); var pluginManager = Service.Get(); - Log.Verbose($"Downloading images for {manifest.InternalName}"); - - this.pluginImagesMap.Add(manifest.InternalName, (false, null)); - - var urls = GetPluginImageUrls(manifest, isThirdParty, pluginManager.UseTesting(manifest)); - var didAny = false; - - if (urls != null) + static bool ValidateImage(TextureWrap image, string loc) { - if (urls.Count > 5) + if (image == null) + return false; + + if (image.Height != PluginImageHeight || image.Width != PluginImageWidth) { - Log.Error($"Plugin {manifest.InternalName} has too many images."); - return; + Log.Error($"Image at {loc} was not of the correct resolution."); + return false; } + return true; + } + + if (plugin != null && plugin.IsDev) + { + var files = GetPluginImageFileInfos(plugin); + if (files != null) + { + var didAny = false; + var pluginImages = new TextureWrap[files.Count]; + for (var i = 0; i < files.Count; i++) + { + var file = files[i]; + + if (file == null) + continue; + + Log.Verbose($"Loading image{i + 1} for {manifest.InternalName} from {file.FullName}"); + + var image = interfaceManager.LoadImage(await File.ReadAllBytesAsync(file.FullName)); + + if (!ValidateImage(image, file.FullName)) + continue; + + Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} loaded from disk"); + pluginImages[i] = image; + didAny = true; + } + + if (didAny) + { + Log.Verbose($"Plugin images for {manifest.InternalName} loaded from disk"); + this.pluginImagesMap[manifest.InternalName] = pluginImages; + + return; + } + } + + // Dev plugins are loaded from disk only + return; + } + + var useTesting = pluginManager.UseTesting(manifest); + var urls = GetPluginImageUrls(manifest, isThirdParty, useTesting); + if (urls != null) + { + var didAny = false; var pluginImages = new TextureWrap[urls.Count]; for (var i = 0; i < urls.Count; i++) { - var data = await this.httpClient.GetAsync(urls[i]); + var url = urls[i]; - Serilog.Log.Information($"Download from {urls[i]}"); + Log.Verbose($"Downloading image{i + 1} for {manifest.InternalName} from {url}"); + + var data = await this.httpClient.GetAsync(url); if (data.StatusCode == HttpStatusCode.NotFound) continue; data.EnsureSuccessStatusCode(); + var image = interfaceManager.LoadImage(await data.Content.ReadAsByteArrayAsync()); - if (image == null) - { - return; - } - - if (image.Height != PluginImageHeight || image.Width != PluginImageWidth) - { - Log.Error($"Image at {urls[i]} was not of the correct resolution."); - return; - } - - didAny = true; + if (!ValidateImage(image, url)) + continue; + Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} downloaded"); pluginImages[i] = image; + didAny = true; } if (didAny) { - this.pluginImagesMap[manifest.InternalName] = (true, pluginImages); + Log.Verbose($"Plugin images for {manifest.InternalName} downloaded"); + this.pluginImagesMap[manifest.InternalName] = pluginImages; + + return; } } - Log.Verbose($"Plugin images for {manifest.InternalName} downloaded"); + Log.Verbose($"Images for {manifest.InternalName} are not available"); } [SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "Disregard here")] diff --git a/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs b/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs index d0a3b7448..21f0bd8d7 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs @@ -24,10 +24,17 @@ namespace Dalamud.Plugin.Internal.Types /// /// Gets or sets the 3rd party repo URL that this plugin was installed from. Used to display where the plugin was - /// sourced from on the installed plugin view. This should not be included in the plugin master. + /// sourced from on the installed plugin view. This should not be included in the plugin master. This value is null + /// when installed from the main repo. /// public string InstalledFromUrl { get; set; } + /// + /// 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. + /// + public bool IsThirdParty => !string.IsNullOrEmpty(this.InstalledFromUrl); + /// /// Save a plugin manifest to file. /// From 617facb8e80bcf97444db6b0b10841416b532c48 Mon Sep 17 00:00:00 2001 From: Raymond Date: Thu, 16 Sep 2021 18:51:16 -0400 Subject: [PATCH 03/16] only check the images folder --- Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs index 85d8356e5..874993bd9 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs @@ -232,11 +232,8 @@ namespace Dalamud.Interface.Internal.Windows private static FileInfo? GetPluginIconFileInfo(LocalPlugin? plugin) { var pluginDir = plugin.DllFile.Directory; - var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "icon.png")); - if (devUrl.Exists) - return devUrl; - devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", "icon.png")); + var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", "icon.png")); if (devUrl.Exists) return devUrl; From acd5c7f93af6d450c8ad97cd8a882019885e2e1b Mon Sep 17 00:00:00 2001 From: Cara Date: Sun, 19 Sep 2021 15:24:25 +0930 Subject: [PATCH 04/16] feat: add an option to disable RMT Filtering --- .../Internal/DalamudConfiguration.cs | 5 +++++ Dalamud/Game/ChatHandlers.cs | 15 +++++++++------ .../Interface/Internal/Windows/SettingsWindow.cs | 6 ++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 4f3e4e59c..4b36b8288 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -195,6 +195,11 @@ namespace Dalamud.Configuration.Internal /// public bool PluginSafeMode { get; set; } + /// + /// Gets or sets a value indicating whether or not Dalamud RMT filtering should be disabled. + /// + public bool DisableRmtFiltering { get; set; } + /// /// Load a configuration from the provided path. /// diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index a1d936fc5..06349b3d0 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -151,13 +151,16 @@ namespace Dalamud.Game var textVal = message.TextValue; - var matched = this.rmtRegex.IsMatch(textVal); - if (matched) + if (!configuration.DisableRmtFiltering) { - // This seems to be a RMT ad - let's not show it - Log.Debug("Handled RMT ad: " + message.TextValue); - isHandled = true; - return; + var matched = this.rmtRegex.IsMatch(textVal); + if (matched) + { + // This seems to be a RMT ad - let's not show it + Log.Debug("Handled RMT ad: " + message.TextValue); + isHandled = true; + return; + } } if (configuration.BadWords != null && diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index ba67fd203..b40971eb3 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -59,6 +59,7 @@ namespace Dalamud.Interface.Internal.Windows private bool printPluginsWelcomeMsg; private bool autoUpdatePlugins; private bool doButtonsSystemMenu; + private bool disableRmtFiltering; #region Experimental @@ -99,6 +100,7 @@ namespace Dalamud.Interface.Internal.Windows this.printPluginsWelcomeMsg = configuration.PrintPluginsWelcomeMsg; this.autoUpdatePlugins = configuration.AutoUpdatePlugins; this.doButtonsSystemMenu = configuration.DoButtonsSystemMenu; + this.disableRmtFiltering = configuration.DisableRmtFiltering; this.languages = Localization.ApplicableLangCodes.Prepend("en").ToArray(); try @@ -238,6 +240,9 @@ namespace Dalamud.Interface.Internal.Windows ImGui.Checkbox(Loc.Localize("DalamudSettingsSystemMenu", "Dalamud buttons in system menu"), ref this.doButtonsSystemMenu); ImGui.TextColored(this.hintTextColor, Loc.Localize("DalamudSettingsSystemMenuMsgHint", "Add buttons for Dalamud plugins and settings to the system menu.")); + + ImGui.Checkbox(Loc.Localize("DalamudSettingsDisableRmtFiltering", "Disable RMT Filtering"), ref this.disableRmtFiltering); + ImGui.TextColored(this.hintTextColor, Loc.Localize("DalamudSettingsDisableRmtFilteringMsgHint", "Disable dalamud's built-in RMT ad filtering.")); } private void DrawLookAndFeelTab() @@ -689,6 +694,7 @@ namespace Dalamud.Interface.Internal.Windows configuration.PrintPluginsWelcomeMsg = this.printPluginsWelcomeMsg; configuration.AutoUpdatePlugins = this.autoUpdatePlugins; configuration.DoButtonsSystemMenu = this.doButtonsSystemMenu; + configuration.DisableRmtFiltering = this.disableRmtFiltering; configuration.Save(); From 132c34b3992adad7402be1a363b5cb68be8b4cfc Mon Sep 17 00:00:00 2001 From: Raymond Date: Mon, 20 Sep 2021 09:51:25 -0400 Subject: [PATCH 05/16] only check the images folder --- .../Interface/Internal/Windows/PluginInstallerWindow.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs index 874993bd9..27625a60d 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs @@ -246,14 +246,7 @@ namespace Dalamud.Interface.Internal.Windows var output = new List(); for (var i = 1; i <= 5; i++) { - var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, $"image{i}.png")); - if (devUrl.Exists) - { - output.Add(devUrl); - continue; - } - - devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", $"image{i}.png")); + var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", $"image{i}.png")); if (devUrl.Exists) { output.Add(devUrl); From cd1d135a87fe52e5b802d5088f3cd17909e53ac3 Mon Sep 17 00:00:00 2001 From: Raymond Date: Tue, 21 Sep 2021 09:29:54 -0400 Subject: [PATCH 06/16] Remove DalamudDebugStub --- DalamudDebugStub/DalamudDebugStub.vcxproj | 173 ------------------ .../DalamudDebugStub.vcxproj.filters | 33 ---- DalamudDebugStub/dllmain.cpp | 118 ------------ DalamudDebugStub/framework.h | 5 - DalamudDebugStub/pch.cpp | 5 - DalamudDebugStub/pch.h | 13 -- 6 files changed, 347 deletions(-) delete mode 100644 DalamudDebugStub/DalamudDebugStub.vcxproj delete mode 100644 DalamudDebugStub/DalamudDebugStub.vcxproj.filters delete mode 100644 DalamudDebugStub/dllmain.cpp delete mode 100644 DalamudDebugStub/framework.h delete mode 100644 DalamudDebugStub/pch.cpp delete mode 100644 DalamudDebugStub/pch.h diff --git a/DalamudDebugStub/DalamudDebugStub.vcxproj b/DalamudDebugStub/DalamudDebugStub.vcxproj deleted file mode 100644 index 4755bf877..000000000 --- a/DalamudDebugStub/DalamudDebugStub.vcxproj +++ /dev/null @@ -1,173 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - {9FDA9A5C-50C6-4333-8DCE-DFEB89363F2A} - Win32Proj - DalamudDebugStub - 10.0 - - - - DynamicLibrary - true - v142 - Unicode - - - DynamicLibrary - false - v142 - true - Unicode - - - DynamicLibrary - true - v142 - Unicode - - - DynamicLibrary - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - true - $(SolutionDir)bin\ - - - false - - - false - $(SolutionDir)bin\ - - - - Use - Level3 - true - WIN32;_DEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - pch.h - - - Windows - true - false - - - - - Use - Level3 - true - _DEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - pch.h - - - Windows - true - false - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies) - - - - - Use - Level3 - true - true - true - WIN32;NDEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - pch.h - - - Windows - true - true - true - false - - - - - Use - Level3 - true - true - true - NDEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - pch.h - - - Windows - true - true - true - false - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies) - - - - - - - - - - Create - Create - Create - Create - - - - - - \ No newline at end of file diff --git a/DalamudDebugStub/DalamudDebugStub.vcxproj.filters b/DalamudDebugStub/DalamudDebugStub.vcxproj.filters deleted file mode 100644 index d4f9881b8..000000000 --- a/DalamudDebugStub/DalamudDebugStub.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/DalamudDebugStub/dllmain.cpp b/DalamudDebugStub/dllmain.cpp deleted file mode 100644 index 37e475bd1..000000000 --- a/DalamudDebugStub/dllmain.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// dllmain.cpp : Defines the entry point for the DLL application. -#include "pch.h" - -#include -#include -#include -#include - -bool isExcept = false; - -LONG WINAPI -VectoredHandler( - struct _EXCEPTION_POINTERS* ExceptionInfo -) -{ - PEXCEPTION_RECORD Record = ExceptionInfo->ExceptionRecord; - - if (Record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) - return EXCEPTION_CONTINUE_SEARCH; - - //ListProcessThreads(GetCurrentProcessId()); - - if (!isExcept) - { - isExcept = true; - - TCHAR pszMessage[1024] = { 0 }; - _stprintf_s(pszMessage, _T("An internal error in Dalamud or a FFXIV plugin occured.\nThe game must close.\n\nDo you wish to save troubleshooting information?\n\nReasoning: 0x%x at 0x%x"), Record->ExceptionCode, Record->ExceptionAddress); - - auto res = MessageBox(NULL, pszMessage, L"Dalamud", MB_YESNO | MB_ICONERROR | MB_TOPMOST); - - if (res == IDYES) - { - TCHAR fileName[255] = { 0 }; - - char* pValue; - size_t len; - errno_t err = _dupenv_s(&pValue, &len, "APPDATA"); - - wchar_t* fullPath = new wchar_t[2048]; - - // Convert char* string to a wchar_t* string. - size_t convertedChars = 0; - mbstowcs_s(&convertedChars, fullPath, strlen(pValue) + 1, pValue, _TRUNCATE); - - SYSTEMTIME t; - GetSystemTime(&t); - _stprintf_s(fileName, _T("MD-%d-%d-%d-%d-%d-%d.dmp"), t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); - - _tcscat_s(fullPath, 2048, TEXT("\\XIVLauncher\\")); - _tcscat_s(fullPath, 2048, fileName); - - HANDLE hFile = CreateFileW(fullPath, GENERIC_READ | GENERIC_WRITE, - 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) - { - // Create the minidump - - MINIDUMP_EXCEPTION_INFORMATION mdei; - - mdei.ThreadId = GetCurrentThreadId(); - mdei.ExceptionPointers = ExceptionInfo; - mdei.ClientPointers = TRUE; - - BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), - hFile, (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithDataSegs | MiniDumpWithThreadInfo), (ExceptionInfo != 0) ? &mdei : 0, 0, 0); - - if (!rv) - _stprintf_s(pszMessage, _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError()); - else - _stprintf_s(pszMessage, _T("Minidump created.\n")); - - MessageBox(NULL, pszMessage, L"Dalamud", MB_OK | MB_ICONINFORMATION | MB_TOPMOST); - - // Close the file - - CloseHandle(hFile); - } - else - { - _tprintf(_T("CreateFile failed. Error: %u \n"), GetLastError()); - } - } - - exit(-1); - } - - PCONTEXT Context; - - Context = ExceptionInfo->ContextRecord; -#ifdef _AMD64_ - Context->Rip++; -#else - Context->Eip++; -#endif - return EXCEPTION_CONTINUE_EXECUTION; -} - -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved -) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - - AddVectoredExceptionHandler(99, VectoredHandler); - break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} - diff --git a/DalamudDebugStub/framework.h b/DalamudDebugStub/framework.h deleted file mode 100644 index 54b83e94f..000000000 --- a/DalamudDebugStub/framework.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files -#include diff --git a/DalamudDebugStub/pch.cpp b/DalamudDebugStub/pch.cpp deleted file mode 100644 index 64b7eef6d..000000000 --- a/DalamudDebugStub/pch.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// pch.cpp: source file corresponding to the pre-compiled header - -#include "pch.h" - -// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/DalamudDebugStub/pch.h b/DalamudDebugStub/pch.h deleted file mode 100644 index 885d5d62e..000000000 --- a/DalamudDebugStub/pch.h +++ /dev/null @@ -1,13 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#ifndef PCH_H -#define PCH_H - -// add headers that you want to pre-compile here -#include "framework.h" - -#endif //PCH_H From 0cfbc70286a30661e16f7bf879bfd9c623500d62 Mon Sep 17 00:00:00 2001 From: Raymond Date: Mon, 20 Sep 2021 19:42:50 -0400 Subject: [PATCH 07/16] formatting --- .../Internal/Windows/PluginInstallerWindow.cs | 4 ++-- Dalamud/Plugin/Internal/LocalDevPlugin.cs | 10 ++++------ Dalamud/Plugin/Internal/LocalPlugin.cs | 13 ++++++------- Dalamud/Plugin/Internal/PluginManager.cs | 4 ++-- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs index c7fc934a1..84ca51b42 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs @@ -873,8 +873,8 @@ namespace Dalamud.Interface.Internal.Windows // Download count var downloadCountText = manifest.DownloadCount > 0 - ? Locs.PluginBody_AuthorWithDownloadCount(manifest.Author, manifest.DownloadCount) - : Locs.PluginBody_AuthorWithDownloadCountUnavailable(manifest.Author); + ? Locs.PluginBody_AuthorWithDownloadCount(manifest.Author, manifest.DownloadCount) + : Locs.PluginBody_AuthorWithDownloadCountUnavailable(manifest.Author); ImGui.SameLine(); ImGui.TextColored(ImGuiColors.DalamudGrey3, downloadCountText); diff --git a/Dalamud/Plugin/Internal/LocalDevPlugin.cs b/Dalamud/Plugin/Internal/LocalDevPlugin.cs index d8e0d94e0..3615c01a9 100644 --- a/Dalamud/Plugin/Internal/LocalDevPlugin.cs +++ b/Dalamud/Plugin/Internal/LocalDevPlugin.cs @@ -145,19 +145,17 @@ namespace Dalamud.Plugin.Internal return; } + var notificationManager = Service.Get(); + try { this.Reload(); - Service.Get() - .AddNotification( - $"The DevPlugin '{this.Name} was reloaded successfully.", "Plugin reloaded!", NotificationType.Success); + notificationManager.AddNotification($"The DevPlugin '{this.Name} was reloaded successfully.", "Plugin reloaded!", NotificationType.Success); } catch (Exception ex) { Log.Error(ex, "DevPlugin reload failed."); - Service.Get() - .AddNotification( - $"The DevPlugin '{this.Name} could not be reloaded.", "Plugin reload failed!", NotificationType.Error); + notificationManager.AddNotification($"The DevPlugin '{this.Name} could not be reloaded.", "Plugin reload failed!", NotificationType.Error); } }, this.fileWatcherTokenSource.Token); diff --git a/Dalamud/Plugin/Internal/LocalPlugin.cs b/Dalamud/Plugin/Internal/LocalPlugin.cs index d51b14303..0d9985602 100644 --- a/Dalamud/Plugin/Internal/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/LocalPlugin.cs @@ -86,10 +86,8 @@ namespace Dalamud.Plugin.Internal var assemblyVersion = this.pluginAssembly.GetName().Version; - // Files that may or may not exist + // Although it is conditionally used here, we need to set the initial value regardless. this.manifestFile = LocalPluginManifest.GetManifestFile(this.DllFile); - this.disabledFile = LocalPluginManifest.GetDisabledFile(this.DllFile); - this.testingFile = LocalPluginManifest.GetTestingFile(this.DllFile); // If the parameter manifest was null if (manifest == null) @@ -108,22 +106,23 @@ namespace Dalamud.Plugin.Internal // Save the manifest to disk so there won't be any problems later. // We'll update the name property after it can be retrieved from the instance. - var manifestFile = LocalPluginManifest.GetManifestFile(this.DllFile); - this.Manifest.Save(manifestFile); + this.Manifest.Save(this.manifestFile); } else { this.Manifest = manifest; } - // This bit converts from ".disabled" functionality to using the manifest. + // This converts from the ".disabled" file feature to the manifest instead. + this.disabledFile = LocalPluginManifest.GetDisabledFile(this.DllFile); if (this.disabledFile.Exists) { this.Manifest.Disabled = true; this.disabledFile.Delete(); } - // This bit converts from ".testing" functionality to using the manifest. + // This converts from the ".testing" file feature to the manifest instead. + this.testingFile = LocalPluginManifest.GetTestingFile(this.DllFile); if (this.testingFile.Exists) { this.Manifest.Testing = true; diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 81d5b92a8..47e3ca478 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -553,13 +553,13 @@ namespace Dalamud.Plugin.Internal if (plugin.IsDev) { // Dev plugins always get added to the list so they can be fiddled with in the UI - Log.Information(ex, $"Dev plugin failed to load, adding anyways: {dllFile.Name}"); + Log.Information(ex, $"Dev plugin failed to load, adding anyways: {dllFile.Name}"); plugin.Disable(); // Disable here, otherwise you can't enable+load later } else if (plugin.Manifest.DalamudApiLevel < DalamudApiLevel) { // Out of date plugins get added so they can be updated. - Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}"); + Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}"); // plugin.Disable(); // Don't disable, or it gets deleted next boot. } else From c34d4dfd8714813e49c8f71cd71b864ab86be796 Mon Sep 17 00:00:00 2001 From: Raymond Date: Mon, 20 Sep 2021 17:09:34 -0400 Subject: [PATCH 08/16] treat banned plugins like out of date, dont load but allow update --- .../Exceptions/BannedPluginException.cs | 22 +++++++++++++++++++ Dalamud/Plugin/Internal/LocalPlugin.cs | 3 +++ Dalamud/Plugin/Internal/PluginManager.cs | 12 +++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 Dalamud/Plugin/Internal/Exceptions/BannedPluginException.cs diff --git a/Dalamud/Plugin/Internal/Exceptions/BannedPluginException.cs b/Dalamud/Plugin/Internal/Exceptions/BannedPluginException.cs new file mode 100644 index 000000000..e4418b6d3 --- /dev/null +++ b/Dalamud/Plugin/Internal/Exceptions/BannedPluginException.cs @@ -0,0 +1,22 @@ +namespace Dalamud.Plugin.Internal.Exceptions +{ + /// + /// This represents a banned plugin that attempted an operation. + /// + internal class BannedPluginException : PluginException + { + /// + /// Initializes a new instance of the class. + /// + /// The message describing the invalid operation. + public BannedPluginException(string message) + { + this.Message = message; + } + + /// + /// Gets the message describing the invalid operation. + /// + public override string Message { get; } + } +} diff --git a/Dalamud/Plugin/Internal/LocalPlugin.cs b/Dalamud/Plugin/Internal/LocalPlugin.cs index 0d9985602..e5f26c418 100644 --- a/Dalamud/Plugin/Internal/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/LocalPlugin.cs @@ -222,6 +222,9 @@ namespace Dalamud.Plugin.Internal throw new InvalidPluginOperationException($"Unable to load {this.Name}, unload previously faulted, restart Dalamud"); } + if (pluginManager.IsManifestBanned(this.Manifest)) + throw new BannedPluginException($"Unable to load {this.Name}, banned"); + if (this.Manifest.ApplicableVersion < startInfo.GameVersion) throw new InvalidPluginOperationException($"Unable to load {this.Name}, no applicable version"); diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 47e3ca478..5b87abbb1 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -548,6 +548,11 @@ namespace Dalamud.Plugin.Internal PluginLocations.Remove(plugin.AssemblyName.FullName); throw; } + catch (BannedPluginException) + { + // Out of date plugins get added so they can be updated. + Log.Information($"Plugin was banned, adding anyways: {dllFile.Name}"); + } catch (Exception ex) { if (plugin.IsDev) @@ -936,7 +941,12 @@ namespace Dalamud.Plugin.Internal return true; } - private bool IsManifestBanned(PluginManifest manifest) + /// + /// Determine if a plugin has been banned by inspecting the manifest. + /// + /// Manifest to inspect. + /// A value indicating whether the plugin/manifest has been banned. + public bool IsManifestBanned(PluginManifest manifest) { return this.bannedPlugins.Any(ban => ban.Name == manifest.InternalName && ban.AssemblyVersion == manifest.AssemblyVersion); } From cb1761f9982dcad254dfce5046c2e9c49518d6fd Mon Sep 17 00:00:00 2001 From: Raymond Date: Mon, 20 Sep 2021 16:32:01 -0400 Subject: [PATCH 09/16] add LocalPlugin.IsOutdated shortcut --- Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs | 6 +++--- Dalamud/Plugin/Internal/LocalPlugin.cs | 5 +++++ Dalamud/Plugin/Internal/PluginManager.cs | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs index 84ca51b42..e6c842eae 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs @@ -1124,7 +1124,7 @@ namespace Dalamud.Interface.Internal.Windows } // Outdated API level - if (plugin.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel) + if (plugin.IsOutdated) { label += Locs.PluginTitleMod_OutdatedError; trouble = true; @@ -1174,7 +1174,7 @@ namespace Dalamud.Interface.Internal.Windows ImGui.TextWrapped(manifest.Description); } - if (plugin.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel) + if (plugin.IsOutdated) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed); ImGui.TextWrapped(Locs.PluginBody_Outdated); @@ -1263,7 +1263,7 @@ namespace Dalamud.Interface.Internal.Windows var disabled = this.updateStatus == OperationStatus.InProgress || this.installStatus == OperationStatus.InProgress; // Disable everything if the plugin is outdated - disabled = disabled || (plugin.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel && !configuration.LoadAllApiLevels); + disabled = disabled || (plugin.IsOutdated && !configuration.LoadAllApiLevels); if (plugin.State == PluginState.InProgress) { diff --git a/Dalamud/Plugin/Internal/LocalPlugin.cs b/Dalamud/Plugin/Internal/LocalPlugin.cs index e5f26c418..0b2b1d91f 100644 --- a/Dalamud/Plugin/Internal/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/LocalPlugin.cs @@ -173,6 +173,11 @@ namespace Dalamud.Plugin.Internal /// public bool IsDisabled => this.Manifest.Disabled; + /// + /// Gets a value indicating whether this plugin's API level is out of date. + /// + public bool IsOutdated => this.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel; + /// /// Gets a value indicating whether the plugin is for testing use only. /// diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 5b87abbb1..d8bf6b802 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -561,7 +561,7 @@ namespace Dalamud.Plugin.Internal Log.Information(ex, $"Dev plugin failed to load, adding anyways: {dllFile.Name}"); plugin.Disable(); // Disable here, otherwise you can't enable+load later } - else if (plugin.Manifest.DalamudApiLevel < DalamudApiLevel) + else if (plugin.IsOutdated) { // Out of date plugins get added so they can be updated. Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}"); From f1e5a21494087e67b472ae090193ad70c418d906 Mon Sep 17 00:00:00 2001 From: Raymond Date: Mon, 20 Sep 2021 16:32:47 -0400 Subject: [PATCH 10/16] Extract DeletePlugin from dev, show if outdated or dev --- .../Internal/Windows/PluginInstallerWindow.cs | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs index e6c842eae..c5c56a137 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs @@ -1201,6 +1201,7 @@ namespace Dalamud.Interface.Internal.Windows // Controls this.DrawPluginControlButton(plugin); this.DrawDevPluginButtons(plugin); + this.DrawDeletePluginButton(plugin); this.DrawVisitRepoUrlButton(plugin.Manifest.RepoUrl); if (availablePluginUpdate != default) @@ -1411,7 +1412,6 @@ namespace Dalamud.Interface.Internal.Windows private void DrawDevPluginButtons(LocalPlugin localPlugin) { var configuration = Service.Get(); - var pluginManager = Service.Get(); if (localPlugin is LocalDevPlugin plugin) { @@ -1454,33 +1454,40 @@ namespace Dalamud.Interface.Internal.Windows { ImGui.SetTooltip(Locs.PluginButtonToolTip_AutomaticReloading); } + } + } - // Delete - if (plugin.State == PluginState.Unloaded) + private void DrawDeletePluginButton(LocalPlugin plugin) + { + var unloaded = plugin.State == PluginState.Unloaded; + var showButton = unloaded && (plugin.IsDev || plugin.IsOutdated); + + if (!showButton) + return; + + var pluginManager = Service.Get(); + + ImGui.SameLine(); + if (ImGuiComponents.IconButton(FontAwesomeIcon.TrashAlt)) + { + try { - ImGui.SameLine(); - if (ImGuiComponents.IconButton(FontAwesomeIcon.TrashAlt)) - { - try - { - plugin.DllFile.Delete(); - pluginManager.RemovePlugin(plugin); - } - catch (Exception ex) - { - Log.Error(ex, $"Plugin installer threw an error during removal of {plugin.Name}"); - - this.errorModalMessage = Locs.ErrorModal_DeleteFail(plugin.Name); - this.errorModalDrawing = true; - this.errorModalOnNextFrame = true; - } - } - - if (ImGui.IsItemHovered()) - { - ImGui.SetTooltip(Locs.PluginBody_DeleteDevPlugin); - } + plugin.DllFile.Delete(); + pluginManager.RemovePlugin(plugin); } + catch (Exception ex) + { + Log.Error(ex, $"Plugin installer threw an error during removal of {plugin.Name}"); + + this.errorModalMessage = Locs.ErrorModal_DeleteFail(plugin.Name); + this.errorModalDrawing = true; + this.errorModalOnNextFrame = true; + } + } + + if (ImGui.IsItemHovered()) + { + ImGui.SetTooltip(Locs.PluginButtonToolTip_DeletePlugin); } } From f98193a06dc740a31d6901deeeed7bd9628d3460 Mon Sep 17 00:00:00 2001 From: Raymond Date: Tue, 21 Sep 2021 10:15:51 -0400 Subject: [PATCH 11/16] Display banned plugins for updating --- .../Internal/Windows/PluginInstallerWindow.cs | 23 +++++++++++++++++-- Dalamud/Plugin/Internal/LocalPlugin.cs | 10 ++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs index c5c56a137..b244c33f3 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs @@ -868,6 +868,7 @@ namespace Dalamud.Interface.Internal.Windows ImGui.SameLine(); var cursor = ImGui.GetCursorPos(); + // Name ImGui.Text(label); @@ -1130,6 +1131,13 @@ namespace Dalamud.Interface.Internal.Windows trouble = true; } + // Banned + if (plugin.IsBanned) + { + label += Locs.PluginTitleMod_BannedError; + trouble = true; + } + ImGui.PushID($"installed{index}{plugin.Manifest.InternalName}"); if (this.DrawPluginCollapsingHeader(label, plugin.Manifest, trouble, availablePluginUpdate != default, false, () => this.DrawInstalledPluginContextMenu(plugin), index)) @@ -1181,6 +1189,13 @@ namespace Dalamud.Interface.Internal.Windows ImGui.PopStyleColor(); } + if (plugin.IsBanned) + { + ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed); + ImGui.TextWrapped(Locs.PluginBody_Banned); + ImGui.PopStyleColor(); + } + // Available commands (if loaded) if (plugin.IsLoaded) { @@ -1264,7 +1279,7 @@ namespace Dalamud.Interface.Internal.Windows var disabled = this.updateStatus == OperationStatus.InProgress || this.installStatus == OperationStatus.InProgress; // Disable everything if the plugin is outdated - disabled = disabled || (plugin.IsOutdated && !configuration.LoadAllApiLevels); + disabled = disabled || (plugin.IsOutdated && !configuration.LoadAllApiLevels) || plugin.IsBanned; if (plugin.State == PluginState.InProgress) { @@ -1460,7 +1475,7 @@ namespace Dalamud.Interface.Internal.Windows private void DrawDeletePluginButton(LocalPlugin plugin) { var unloaded = plugin.State == PluginState.Unloaded; - var showButton = unloaded && (plugin.IsDev || plugin.IsOutdated); + var showButton = unloaded && (plugin.IsDev || plugin.IsOutdated || plugin.IsBanned); if (!showButton) return; @@ -1926,6 +1941,8 @@ namespace Dalamud.Interface.Internal.Windows public static string PluginTitleMod_OutdatedError => Loc.Localize("InstallerOutdatedError", " (outdated)"); + public static string PluginTitleMod_BannedError => Loc.Localize("InstallerOutdatedError", " (banned)"); + public static string PluginTitleMod_New => Loc.Localize("InstallerNewPlugin ", " New!"); #endregion @@ -1960,6 +1977,8 @@ namespace Dalamud.Interface.Internal.Windows public static string PluginBody_Outdated => Loc.Localize("InstallerOutdatedPluginBody ", "This plugin is outdated and incompatible at the moment. Please wait for it to be updated by its author."); + public static string PluginBody_Banned => Loc.Localize("InstallerBannedPluginBody ", "This plugin version is banned and not available at the moment. Please wait for it to be updated by its author."); + #endregion #region Plugin buttons diff --git a/Dalamud/Plugin/Internal/LocalPlugin.cs b/Dalamud/Plugin/Internal/LocalPlugin.cs index 0b2b1d91f..c06c12c08 100644 --- a/Dalamud/Plugin/Internal/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/LocalPlugin.cs @@ -129,6 +129,9 @@ namespace Dalamud.Plugin.Internal this.testingFile.Delete(); } + var pluginManager = Service.Get(); + this.IsBanned = pluginManager.IsManifestBanned(this.Manifest); + this.SaveManifest(); } @@ -183,6 +186,11 @@ namespace Dalamud.Plugin.Internal /// public bool IsTesting => this.Manifest.IsTestingExclusive || this.Manifest.Testing; + /// + /// Gets a value indicating whether this plugin has been banned. + /// + public bool IsBanned { get; } + /// /// Gets a value indicating whether this plugin is dev plugin. /// @@ -262,7 +270,9 @@ namespace Dalamud.Plugin.Internal { var manifestFile = LocalPluginManifest.GetManifestFile(this.DllFile); if (manifestFile.Exists) + { this.Manifest = LocalPluginManifest.Load(manifestFile); + } } } From 18a3643fe612dd295a5d2e253c303fa5716bcbd8 Mon Sep 17 00:00:00 2001 From: Raymond Date: Wed, 22 Sep 2021 08:47:06 -0400 Subject: [PATCH 12/16] api3 plugins will have a null value, needs handling --- Dalamud/Plugin/Internal/LocalPlugin.cs | 2 +- Dalamud/Plugin/Internal/PluginManager.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dalamud/Plugin/Internal/LocalPlugin.cs b/Dalamud/Plugin/Internal/LocalPlugin.cs index c06c12c08..7310e5dca 100644 --- a/Dalamud/Plugin/Internal/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/LocalPlugin.cs @@ -159,7 +159,7 @@ namespace Dalamud.Plugin.Internal /// Gets the AssemblyName plugin, populated during . /// /// Plugin type. - public AssemblyName AssemblyName { get; private set; } = null; + public AssemblyName? AssemblyName { get; private set; } = null; /// /// Gets the plugin name, directly from the plugin or if it is not loaded from the manifest. diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index d8bf6b802..54966765a 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -545,7 +545,7 @@ namespace Dalamud.Plugin.Internal } catch (InvalidPluginException) { - PluginLocations.Remove(plugin.AssemblyName.FullName); + PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty); throw; } catch (BannedPluginException) @@ -569,7 +569,7 @@ namespace Dalamud.Plugin.Internal } else { - PluginLocations.Remove(plugin.AssemblyName.FullName); + PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty); throw; } } @@ -589,7 +589,7 @@ namespace Dalamud.Plugin.Internal throw new InvalidPluginOperationException($"Unable to remove {plugin.Name}, not unloaded"); this.InstalledPlugins = this.InstalledPlugins.Remove(plugin); - PluginLocations.Remove(plugin.AssemblyName.FullName); + PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty); this.NotifyInstalledPluginsChanged(); this.NotifyAvailablePluginsChanged(); From f5ef9a085a62485040926f0c03385d540040b609 Mon Sep 17 00:00:00 2001 From: Anna Clemens Date: Wed, 22 Sep 2021 16:25:06 -0400 Subject: [PATCH 13/16] feat: add fallible methods to SigScanner --- Dalamud/Game/SigScanner.cs | 105 +++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs index 28bb0137b..d6b5a77a3 100644 --- a/Dalamud/Game/SigScanner.cs +++ b/Dalamud/Game/SigScanner.cs @@ -134,6 +134,28 @@ namespace Dalamud.Game return baseAddress + index; } + /// + /// Try scanning memory for a signature. + /// + /// The base address to scan from. + /// The amount of bytes to scan. + /// The signature to search for. + /// The offset, if found. + /// true if the signature was found. + public static bool TryScan(IntPtr baseAddress, int size, string signature, out IntPtr result) + { + result = IntPtr.Zero; + try + { + result = Scan(baseAddress, size, signature); + return true; + } + catch (KeyNotFoundException) + { + return false; + } + } + /// /// Scan for a .data address using a .text function. /// This is intended to be used with IDA sigs. @@ -160,6 +182,29 @@ namespace Dalamud.Game return IntPtr.Add(instrAddr, Marshal.ReadInt32(instrAddr) + 4); } + /// + /// Try scanning for a .data address using a .text function. + /// This is intended to be used with IDA sigs. + /// Place your cursor on the line calling a static address, and create and IDA sig. + /// + /// The signature of the function using the data. + /// An IntPtr to the static memory location, if found. + /// The offset from function start of the instruction using the data. + /// true if the signature was found. + public bool TryGetStaticAddressFromSig(string signature, out IntPtr result, int offset = 0) + { + result = IntPtr.Zero; + try + { + result = this.GetStaticAddressFromSig(signature, offset); + return true; + } + catch (KeyNotFoundException) + { + return false; + } + } + /// /// Scan for a byte signature in the .data section. /// @@ -175,6 +220,26 @@ namespace Dalamud.Game return scanRet; } + /// + /// Try scanning for a byte signature in the .data section. + /// + /// The signature. + /// The real offset of the signature, if found. + /// true if the signature was found. + public bool TryScanData(string signature, out IntPtr result) + { + result = IntPtr.Zero; + try + { + result = this.ScanData(signature); + return true; + } + catch (KeyNotFoundException) + { + return false; + } + } + /// /// Scan for a byte signature in the whole module search area. /// @@ -190,6 +255,26 @@ namespace Dalamud.Game return scanRet; } + /// + /// Try scanning for a byte signature in the whole module search area. + /// + /// The signature. + /// The real offset of the signature, if found. + /// true if the signature was found. + public bool TryScanModule(string signature, out IntPtr result) + { + result = IntPtr.Zero; + try + { + result = this.ScanModule(signature); + return true; + } + catch (KeyNotFoundException) + { + return false; + } + } + /// /// Resolve a RVA address. /// @@ -224,6 +309,26 @@ namespace Dalamud.Game return scanRet; } + /// + /// Try scanning for a byte signature in the .text section. + /// + /// The signature. + /// The real offset of the signature, if found. + /// true if the signature was found. + public bool TryScanText(string signature, out IntPtr result) + { + result = IntPtr.Zero; + try + { + result = this.ScanText(signature); + return true; + } + catch (KeyNotFoundException) + { + return false; + } + } + /// /// Free the memory of the copied module search area on object disposal, if applicable. /// From 06d3ad80484beda857d7dab566c90d1826f2962d Mon Sep 17 00:00:00 2001 From: Raymond Date: Wed, 22 Sep 2021 17:13:06 -0400 Subject: [PATCH 14/16] formatting --- Dalamud/Game/SigScanner.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs index d6b5a77a3..e35b17cc4 100644 --- a/Dalamud/Game/SigScanner.cs +++ b/Dalamud/Game/SigScanner.cs @@ -144,7 +144,6 @@ namespace Dalamud.Game /// true if the signature was found. public static bool TryScan(IntPtr baseAddress, int size, string signature, out IntPtr result) { - result = IntPtr.Zero; try { result = Scan(baseAddress, size, signature); @@ -152,6 +151,7 @@ namespace Dalamud.Game } catch (KeyNotFoundException) { + result = IntPtr.Zero; return false; } } @@ -193,7 +193,6 @@ namespace Dalamud.Game /// true if the signature was found. public bool TryGetStaticAddressFromSig(string signature, out IntPtr result, int offset = 0) { - result = IntPtr.Zero; try { result = this.GetStaticAddressFromSig(signature, offset); @@ -201,6 +200,7 @@ namespace Dalamud.Game } catch (KeyNotFoundException) { + result = IntPtr.Zero; return false; } } @@ -228,7 +228,6 @@ namespace Dalamud.Game /// true if the signature was found. public bool TryScanData(string signature, out IntPtr result) { - result = IntPtr.Zero; try { result = this.ScanData(signature); @@ -236,6 +235,7 @@ namespace Dalamud.Game } catch (KeyNotFoundException) { + result = IntPtr.Zero; return false; } } @@ -263,7 +263,6 @@ namespace Dalamud.Game /// true if the signature was found. public bool TryScanModule(string signature, out IntPtr result) { - result = IntPtr.Zero; try { result = this.ScanModule(signature); @@ -271,6 +270,7 @@ namespace Dalamud.Game } catch (KeyNotFoundException) { + result = IntPtr.Zero; return false; } } @@ -317,7 +317,6 @@ namespace Dalamud.Game /// true if the signature was found. public bool TryScanText(string signature, out IntPtr result) { - result = IntPtr.Zero; try { result = this.ScanText(signature); @@ -325,6 +324,7 @@ namespace Dalamud.Game } catch (KeyNotFoundException) { + result = IntPtr.Zero; return false; } } From 5a271b03e7edef36779c21ae8f51d68cef81c64b Mon Sep 17 00:00:00 2001 From: Raymond Date: Fri, 24 Sep 2021 09:18:52 -0400 Subject: [PATCH 15/16] bump clientstructs --- lib/FFXIVClientStructs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index 01e885aac..ed5d30106 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit 01e885aacc68790d52329f5b3bdcba2838240e54 +Subproject commit ed5d30106f4b2deaa225d6a91db09a268c9cb77d From 3630ad1fe4281f0f190c1931ab0d6a9ab863d232 Mon Sep 17 00:00:00 2001 From: Raymond Date: Sun, 26 Sep 2021 09:05:17 -0400 Subject: [PATCH 16/16] Save repo manifest before continuing --- Dalamud/Plugin/Internal/PluginManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 54966765a..9e8292320 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -475,6 +475,9 @@ namespace Dalamud.Plugin.Internal var dllFile = LocalPluginManifest.GetPluginFile(outputDir, repoManifest); var manifestFile = LocalPluginManifest.GetManifestFile(dllFile); + // We need to save the repoManifest due to how the repo fills in some fields that authors are not expected to use. + File.WriteAllText(manifestFile.FullName, JsonConvert.SerializeObject(repoManifest, Formatting.Indented)); + // Reload as a local manifest, add some attributes, and save again. var manifest = LocalPluginManifest.Load(manifestFile);